From d3da945def84a793a3ee6af6ea3a9288754548cf Mon Sep 17 00:00:00 2001 From: Brian Pow Date: Sun, 19 Jul 2020 20:53:11 +0800 Subject: [PATCH 1/7] add --keep parameter to keep existing NUM.h2w files --- f3write.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/f3write.c b/f3write.c index 20e30dc..d32b2e1 100644 --- a/f3write.c +++ b/f3write.c @@ -39,6 +39,8 @@ static struct argp_option options[] = { "Maximum write rate", 0}, {"show-progress", 'p', "NUM", 0, "Show progress if NUM is not zero", 0}, + {"keep", 'k', 0, 0, + "Keep existing NUM.h2w file, otherwise all NUM.h2w files will be removed in each run", 0}, { 0 } }; @@ -47,6 +49,7 @@ struct args { long end_at; long max_write_rate; int show_progress; + int keep; const char *dev_path; }; @@ -84,6 +87,10 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) args->show_progress = !!arg_to_long(state, arg); break; + case 'k': + args->keep = 1; + break; + case ARGP_KEY_INIT: args->dev_path = NULL; break; @@ -170,7 +177,7 @@ static int write_chunk(int fd, size_t chunk_size, uint64_t *poffset) /* Return true when disk is full. */ static int create_and_fill_file(const char *path, long number, size_t size, - int *phas_suggested_max_write_rate, struct flow *fw) + int *phas_suggested_max_write_rate, struct flow *fw, int keep) { char *full_fn; const char *filename; @@ -184,6 +191,11 @@ static int create_and_fill_file(const char *path, long number, size_t size, /* Create the file. */ full_fn = full_fn_from_number(&filename, path, number); assert(full_fn); + if(access(full_fn, F_OK) != -1 && keep) + { + printf("Skipping file %s\n", filename); + return false; + } printf("Creating file %s ... ", filename); fflush(stdout); fd = open(full_fn, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR); @@ -273,7 +285,7 @@ static int flush_chunk(const struct flow *fw, int fd) } static int fill_fs(const char *path, long start_at, long end_at, - long max_write_rate, int progress) + long max_write_rate, int progress, int keep) { uint64_t free_space; struct flow fw; @@ -310,7 +322,7 @@ static int fill_fs(const char *path, long start_at, long end_at, assert(!gettimeofday(&t1, NULL)); for (i = start_at; i <= end_at; i++) if (create_and_fill_file(path, i, GIGABYTES, - &has_suggested_max_write_rate, &fw)) + &has_suggested_max_write_rate, &fw, keep)) break; assert(!gettimeofday(&t2, NULL)); @@ -360,6 +372,7 @@ int main(int argc, char **argv) .start_at = 0, .end_at = LONG_MAX - 1, .max_write_rate = 0, + .keep = 0, /* If stdout isn't a terminal, supress progress. */ .show_progress = isatty(STDOUT_FILENO), }; @@ -368,8 +381,9 @@ int main(int argc, char **argv) argp_parse(&argp, argc, argv, 0, NULL, &args); print_header(stdout, "write"); - unlink_old_files(args.dev_path, args.start_at, args.end_at); + if(!args.keep) + unlink_old_files(args.dev_path, args.start_at, args.end_at); return fill_fs(args.dev_path, args.start_at, args.end_at, - args.max_write_rate, args.show_progress); + args.max_write_rate, args.show_progress, args.keep); } From cb8f7c8b0f2035abc2f00a5847e4a3fd65ccdac6 Mon Sep 17 00:00:00 2001 From: Brian Pow Date: Mon, 20 Jul 2020 22:45:50 +0800 Subject: [PATCH 2/7] add --fix parameter to run f3fix automatically if counterfeit memory detected --- f3probe.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/f3probe.c b/f3probe.c index 21babb1..ef98c56 100644 --- a/f3probe.c +++ b/f3probe.c @@ -1,4 +1,5 @@ #define _POSIX_C_SOURCE 200809L +#define _GNU_SOURCE #include #include @@ -51,6 +52,8 @@ static struct argp_option options[] = { "Reset method to use during the probe", 0}, {"time-ops", 't', NULL, 0, "Time reads, writes, and resets", 0}, + {"fix", 'i', NULL, 0, + "Run f3fix if counterfeit flash memory detected", 0}, { 0 } }; @@ -76,6 +79,8 @@ struct args { int block_order; int cache_order; int strict_cache; + + bool fix; }; static error_t parse_opt(int key, char *arg, struct argp_state *state) @@ -167,7 +172,11 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) case 't': args->time_ops = true; break; - + + case 'i': + args->fix = true; + break; + case ARGP_KEY_INIT: args->filename = NULL; break; @@ -373,8 +382,8 @@ static int test_device(struct args *args) uint64_t read_count, read_time_us; uint64_t write_count, write_time_us; uint64_t reset_count, reset_time_us; + uint64_t last_good_sector; const char *final_dev_filename; - dev = args->debug ? create_file_device(args->filename, args->real_size_byte, args->fake_size_byte, args->wrap, args->block_order, @@ -474,7 +483,7 @@ static int test_device(struct args *args) case FKTY_LIMBO: case FKTY_WRAPAROUND: case FKTY_CHAIN: { - uint64_t last_good_sector = (real_size_byte >> 9) - 1; + last_good_sector = (real_size_byte >> 9) - 1; assert(block_order >= 9); printf("Bad news: The device `%s' is a counterfeit of type %s\n\n" "You can \"fix\" this device using the following command:\n" @@ -507,6 +516,13 @@ static int test_device(struct args *args) report_ops("Reset", reset_count, reset_time_us); } + if (fake_type == FKTY_CHAIN || fake_type == FKTY_LIMBO || fake_type == FKTY_CHAIN) + if (args->fix) { + char *cmd = NULL; + asprintf(&cmd, "f3fix --last-sec=%" PRIu64 " %s", last_good_sector, final_dev_filename); + system(cmd); + free(cmd); + } free((void *)final_dev_filename); return fake_type == FKTY_GOOD ? 0 : 100 + fake_type; } @@ -545,6 +561,7 @@ int main(int argc, char **argv) .block_order = 0, .cache_order = -1, .strict_cache = false, + .fix = false, }; /* Read parameters. */ From a4f122e2e71ed376feb9e99556192d53cc483c80 Mon Sep 17 00:00:00 2001 From: Brian Pow Date: Mon, 20 Jul 2020 23:09:01 +0800 Subject: [PATCH 3/7] add --delete parameter to delete corrupted NUM.h2w file --- f3read.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/f3read.c b/f3read.c index 7537b2e..cf50046 100644 --- a/f3read.c +++ b/f3read.c @@ -40,6 +40,8 @@ static struct argp_option options[] = { "Maximum read rate", 0}, {"show-progress", 'p', "NUM", 0, "Show progress if NUM is not zero", 0}, + {"delete", 'd', NULL, 0, + "delete corrupted NUM.h2w file", 0}, { 0 } }; @@ -48,6 +50,7 @@ struct args { long end_at; long max_read_rate; int show_progress; + bool delete; const char *dev_path; }; @@ -85,6 +88,10 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) args->show_progress = !!arg_to_long(state, arg); break; + case 'd': + args->delete = true; + break; + case ARGP_KEY_INIT: args->dev_path = NULL; break; @@ -340,7 +347,7 @@ static inline void pr_avg_speed(double speed) } static void iterate_files(const char *path, const long *files, - long start_at, long end_at, long max_read_rate, int progress) + long start_at, long end_at, long max_read_rate, int progress, bool delete) { uint64_t tot_ok, tot_corrupted, tot_changed, tot_overwritten, tot_size; int and_read_all = 1; @@ -379,6 +386,12 @@ static void iterate_files(const char *path, const long *files, tot_overwritten += stats.secs_overwritten; tot_size += stats.bytes_read; and_read_all = and_read_all && stats.read_all; + if (stats.secs_corrupted && delete) { + const char *filename; + char *full_fn = full_fn_from_number(&filename, path, *files); + if (unlink(full_fn)) + err(errno, "Can't remove file %s\n", full_fn); + } files++; } assert(!gettimeofday(&t2, NULL)); @@ -428,6 +441,7 @@ int main(int argc, char **argv) .max_read_rate = 0, /* If stdout isn't a terminal, supress progress. */ .show_progress = isatty(STDOUT_FILENO), + .delete = false, }; /* Read parameters. */ @@ -437,7 +451,7 @@ int main(int argc, char **argv) files = ls_my_files(args.dev_path, args.start_at, args.end_at); iterate_files(args.dev_path, files, args.start_at, args.end_at, - args.max_read_rate, args.show_progress); + args.max_read_rate, args.show_progress, args.delete); free((void *)files); return 0; } From 72cda3d5b7f02d6690b93d068c4c6db36aeed273 Mon Sep 17 00:00:00 2001 From: Brian Pow Date: Wed, 29 Jul 2020 22:11:44 +0800 Subject: [PATCH 4/7] f3write: code cleanup --- f3write.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/f3write.c b/f3write.c index d32b2e1..a350d5e 100644 --- a/f3write.c +++ b/f3write.c @@ -39,8 +39,8 @@ static struct argp_option options[] = { "Maximum write rate", 0}, {"show-progress", 'p', "NUM", 0, "Show progress if NUM is not zero", 0}, - {"keep", 'k', 0, 0, - "Keep existing NUM.h2w file, otherwise all NUM.h2w files will be removed in each run", 0}, + {"keep", 'k', 0, 0, + "Keep existing NUM.h2w files instead of removing them", 0}, { 0 } }; @@ -49,7 +49,7 @@ struct args { long end_at; long max_write_rate; int show_progress; - int keep; + bool keep; const char *dev_path; }; @@ -88,7 +88,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) break; case 'k': - args->keep = 1; + args->keep = true; break; case ARGP_KEY_INIT: @@ -177,7 +177,7 @@ static int write_chunk(int fd, size_t chunk_size, uint64_t *poffset) /* Return true when disk is full. */ static int create_and_fill_file(const char *path, long number, size_t size, - int *phas_suggested_max_write_rate, struct flow *fw, int keep) + int *phas_suggested_max_write_rate, struct flow *fw, bool keep) { char *full_fn; const char *filename; @@ -191,21 +191,24 @@ static int create_and_fill_file(const char *path, long number, size_t size, /* Create the file. */ full_fn = full_fn_from_number(&filename, path, number); assert(full_fn); - if(access(full_fn, F_OK) != -1 && keep) - { - printf("Skipping file %s\n", filename); - return false; - } + printf("Creating file %s ... ", filename); fflush(stdout); - fd = open(full_fn, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR); + fd = open(full_fn, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR); if (fd < 0) { if (errno == ENOSPC) { printf("No space left.\n"); free(full_fn); return true; } - err(errno, "Can't create file %s", full_fn); + if (errno == EEXIST) { + if (keep) { + printf("Skipped.\n"); + free(full_fn); + return false; + } + err(errno, "Unexpectedly found file %s, but option --keep is not in use", full_fn); + } } assert(fd >= 0); @@ -285,7 +288,7 @@ static int flush_chunk(const struct flow *fw, int fd) } static int fill_fs(const char *path, long start_at, long end_at, - long max_write_rate, int progress, int keep) + long max_write_rate, int progress, bool keep) { uint64_t free_space; struct flow fw; @@ -372,7 +375,7 @@ int main(int argc, char **argv) .start_at = 0, .end_at = LONG_MAX - 1, .max_write_rate = 0, - .keep = 0, + .keep = false, /* If stdout isn't a terminal, supress progress. */ .show_progress = isatty(STDOUT_FILENO), }; From 52423ec9ceaeea7b8f794b043602d4ea92adf99e Mon Sep 17 00:00:00 2001 From: Brian Pow Date: Wed, 29 Jul 2020 22:18:48 +0800 Subject: [PATCH 5/7] f3read: code cleanup --- f3read.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/f3read.c b/f3read.c index cf50046..b2759cc 100644 --- a/f3read.c +++ b/f3read.c @@ -40,8 +40,8 @@ static struct argp_option options[] = { "Maximum read rate", 0}, {"show-progress", 'p', "NUM", 0, "Show progress if NUM is not zero", 0}, - {"delete", 'd', NULL, 0, - "delete corrupted NUM.h2w file", 0}, + {"delete", 'd', NULL, 0, + "Delete corrupted NUM.h2w files", 0}, { 0 } }; @@ -386,11 +386,13 @@ static void iterate_files(const char *path, const long *files, tot_overwritten += stats.secs_overwritten; tot_size += stats.bytes_read; and_read_all = and_read_all && stats.read_all; - if (stats.secs_corrupted && delete) { + if (delete && (stats.secs_corrupted || tot_changed || tot_overwritten)) { const char *filename; char *full_fn = full_fn_from_number(&filename, path, *files); + assert(full_fn) if (unlink(full_fn)) err(errno, "Can't remove file %s\n", full_fn); + free(full_fn); } files++; } From 981484233278f8b5ffd8cc0c416ffe0f9664087d Mon Sep 17 00:00:00 2001 From: Brian Pow Date: Wed, 29 Jul 2020 22:19:20 +0800 Subject: [PATCH 6/7] f3probe: code cleanup --- f3probe.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/f3probe.c b/f3probe.c index ef98c56..a197e75 100644 --- a/f3probe.c +++ b/f3probe.c @@ -52,7 +52,7 @@ static struct argp_option options[] = { "Reset method to use during the probe", 0}, {"time-ops", 't', NULL, 0, "Time reads, writes, and resets", 0}, - {"fix", 'i', NULL, 0, + {"fix", 'i', NULL, 0, "Run f3fix if counterfeit flash memory detected", 0}, { 0 } }; @@ -79,7 +79,6 @@ struct args { int block_order; int cache_order; int strict_cache; - bool fix; }; @@ -384,6 +383,8 @@ static int test_device(struct args *args) uint64_t reset_count, reset_time_us; uint64_t last_good_sector; const char *final_dev_filename; + char *fix_cmd; + dev = args->debug ? create_file_device(args->filename, args->real_size_byte, args->fake_size_byte, args->wrap, args->block_order, @@ -485,6 +486,7 @@ static int test_device(struct args *args) case FKTY_CHAIN: { last_good_sector = (real_size_byte >> 9) - 1; assert(block_order >= 9); + assert(asprintf(&fix_cmd, "f3fix --last-sec=%" PRIu64 " %s", last_good_sector, final_dev_filename) > 0); printf("Bad news: The device `%s' is a counterfeit of type %s\n\n" "You can \"fix\" this device using the following command:\n" "f3fix --last-sec=%" PRIu64 " %s\n", @@ -516,13 +518,10 @@ static int test_device(struct args *args) report_ops("Reset", reset_count, reset_time_us); } - if (fake_type == FKTY_CHAIN || fake_type == FKTY_LIMBO || fake_type == FKTY_CHAIN) - if (args->fix) { - char *cmd = NULL; - asprintf(&cmd, "f3fix --last-sec=%" PRIu64 " %s", last_good_sector, final_dev_filename); - system(cmd); - free(cmd); - } + if (args->fix && fix_cmd) { + system(fix_cmd); + } + free(fix_cmd); free((void *)final_dev_filename); return fake_type == FKTY_GOOD ? 0 : 100 + fake_type; } From 7af01dd7964749bb184294dc9da297e90df4d4e1 Mon Sep 17 00:00:00 2001 From: Brian Pow Date: Wed, 29 Jul 2020 22:23:15 +0800 Subject: [PATCH 7/7] f3read: add missing semicolon --- f3read.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/f3read.c b/f3read.c index b2759cc..05f7059 100644 --- a/f3read.c +++ b/f3read.c @@ -389,7 +389,7 @@ static void iterate_files(const char *path, const long *files, if (delete && (stats.secs_corrupted || tot_changed || tot_overwritten)) { const char *filename; char *full_fn = full_fn_from_number(&filename, path, *files); - assert(full_fn) + assert(full_fn); if (unlink(full_fn)) err(errno, "Can't remove file %s\n", full_fn); free(full_fn);