diff --git a/src/context.h b/src/context.h index c10f17d..fd03388 100644 --- a/src/context.h +++ b/src/context.h @@ -59,6 +59,13 @@ typedef enum nwipe_select_t_ { NWIPE_SELECT_DISABLED // Do not wipe this device and do not allow it to be selected. } nwipe_select_t; +/* I/O mode for data path: auto, direct, or cached. */ +typedef enum { + NWIPE_IO_MODE_AUTO = 0, /* Try O_DIRECT, fall back to cached I/O if not supported. */ + NWIPE_IO_MODE_DIRECT, /* Force O_DIRECT, fail if not supported. */ + NWIPE_IO_MODE_CACHED /* Force cached I/O, never attempt O_DIRECT. */ +} nwipe_io_mode_t; + #define NWIPE_KNOB_SPEEDRING_SIZE 30 #define NWIPE_KNOB_SPEEDRING_GRANULARITY 10 @@ -199,6 +206,7 @@ typedef struct nwipe_context_t_ char HPA_size_text[NWIPE_DEVICE_SIZE_TXT_LENGTH]; // Human readable size bytes, KB, MB, GB .. int HPA_display_toggle_state; // 0 or 1 Used to toggle between "[1TB] [ 33C]" and [HDA STATUS] time_t HPA_toggle_time; // records a time, then if for instance 3 seconds has elapsed the display changes + nwipe_io_mode_t io_mode; // specific I/O method for a given drive, direct or cached. int test_use1; int test_use2; diff --git a/src/nwipe.c b/src/nwipe.c index c88176d..ebce88c 100644 --- a/src/nwipe.c +++ b/src/nwipe.c @@ -738,10 +738,12 @@ int main( int argc, char** argv ) if( open_flags & O_DIRECT ) { io_desc = "direct I/O (O_DIRECT)"; + c2[i]->io_mode = NWIPE_IO_MODE_DIRECT; } else { io_desc = "cached I/O"; + c2[i]->io_mode = NWIPE_IO_MODE_CACHED; } nwipe_log( NWIPE_LOG_NOTICE, "Using %s on device '%s'.", io_desc, c2[i]->device_name ); diff --git a/src/options.h b/src/options.h index dbec04f..067353b 100644 --- a/src/options.h +++ b/src/options.h @@ -23,6 +23,8 @@ #ifndef OPTIONS_H_ #define OPTIONS_H_ +#include "method.h" + /* Program knobs. */ #define NWIPE_KNOB_IDENTITY_SIZE 512 #define NWIPE_KNOB_LABEL_SIZE 128 @@ -47,13 +49,6 @@ void nwipe_options_log( void ); /* Function to display help text */ void display_help(); -/* I/O mode for data path: auto, direct, or cached. */ -typedef enum { - NWIPE_IO_MODE_AUTO = 0, /* Try O_DIRECT, fall back to cached I/O if not supported. */ - NWIPE_IO_MODE_DIRECT, /* Force O_DIRECT, fail if not supported. */ - NWIPE_IO_MODE_CACHED /* Force cached I/O, never attempt O_DIRECT. */ -} nwipe_io_mode_t; - typedef struct { int autonuke; // Do not prompt the user for confirmation when set. @@ -77,7 +72,8 @@ typedef struct int PDF_preview_details; // 0=Disable preview Org/Cust/date/time before drive selection, 1=Enable Preview int PDFtag; // Enable display of hostID, such as UUID or serial no. on PDF report. nwipe_verify_t verify; // A flag to indicate whether writes should be verified. - nwipe_io_mode_t io_mode; // Runtime I/O mode selection (auto/direct/cached). + nwipe_io_mode_t io_mode; // Global runtime I/O mode selection (auto/direct/cached), note in auto mode each + // drive may use a different I/O mode if directIO isn't supported on a given drive. } nwipe_options_t; extern nwipe_options_t nwipe_options; diff --git a/src/pass.c b/src/pass.c index 2f0000b..d45ac96 100644 --- a/src/pass.c +++ b/src/pass.c @@ -386,18 +386,22 @@ int nwipe_random_pass( NWIPE_METHOD_SIGNATURE ) int syncRate = nwipe_options.sync; - /* For direct I/O we do not need periodic fdatasync(), I/O errors are detected - * at write() time. Keep sync for cached I/O only. */ - if( nwipe_options.io_mode == NWIPE_IO_MODE_DIRECT ) - { - syncRate = 0; - } - /* Select effective I/O block size (e.g. 4 MiB, never smaller than st_blksize). */ io_blocksize = nwipe_effective_io_blocksize( c ); - /* Compute the per-write sync rate based on io_blocksize and old semantics. */ - syncRate = nwipe_compute_sync_rate_for_device( c, io_blocksize ); + /* For direct I/O we do not need periodic fdatasync(), I/O errors are detected + * at write() time. Keep sync for cached I/O only. */ + + if( c->io_mode == NWIPE_IO_MODE_DIRECT ) + { + syncRate = 0; + nwipe_log( NWIPE_LOG_NOTICE, "Disabled fdatasync for %s, DirectI/O in use.", c->device_name ); + } + else /* for cached I/O only */ + { + /* Compute the per-write sync rate based on io_blocksize and old semantics. */ + syncRate = nwipe_compute_sync_rate_for_device( c, io_blocksize ); + } int i = 0; int idx; @@ -824,6 +828,22 @@ int nwipe_static_pass( NWIPE_METHOD_SIGNATURE, nwipe_pattern_t* pattern ) u64 z = c->device_size; int syncRate = nwipe_options.sync; + + io_blocksize = nwipe_effective_io_blocksize( c ); + + /* For direct I/O we do not need periodic fdatasync(), I/O errors are detected + * at write() time. Keep sync for cached I/O only. */ + if( c->io_mode == NWIPE_IO_MODE_DIRECT ) + { + syncRate = 0; + nwipe_log( NWIPE_LOG_NOTICE, "Disabled fdatasync for %s, DirectI/O in use.", c->device_name ); + } + else /* for cached I/O only */ + { + /* Compute per-write sync rate (same semantics as random pass). */ + syncRate = nwipe_compute_sync_rate_for_device( c, io_blocksize ); + } + int i = 0; if( pattern == NULL ) @@ -838,11 +858,6 @@ int nwipe_static_pass( NWIPE_METHOD_SIGNATURE, nwipe_pattern_t* pattern ) return -1; } - io_blocksize = nwipe_effective_io_blocksize( c ); - - /* Compute per-write sync rate (same semantics as random pass). */ - syncRate = nwipe_compute_sync_rate_for_device( c, io_blocksize ); - /* * For static patterns we want enough buffer space to always have a * contiguous window of "io_blocksize" bytes available starting at any