From 5e1d306e4f9a6337d07cc2d536d77c53e083226f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 23 May 2008 11:55:53 +0200 Subject: [PATCH] Add job number specific dumping and fix atexit() error The threads/process jobs should use _exit() so they don't run the main atexit() function. Signed-off-by: Jens Axboe --- README | 1 + debug.h | 8 ++++++++ filehash.c | 17 +++++++++++++++++ filehash.h | 1 + fio.c | 9 ++++++--- init.c | 40 +++++++++++++++++++++++++++++++++------- 6 files changed, 66 insertions(+), 10 deletions(-) diff --git a/README b/README index ea8f5ef8..53cc7ebd 100644 --- a/README +++ b/README @@ -116,6 +116,7 @@ options in fio. Currently the options are: random Dump info related to random offset generation parse Dump info related to option matching and parsing diskutil Dump info related to disk utilization updates + job:x Dump info only related to job number x ? or help Show available debug options. You can specify as many as you want, eg --debug=file,mem will enable diff --git a/debug.h b/debug.h index 22577a8a..883628da 100644 --- a/debug.h +++ b/debug.h @@ -14,6 +14,7 @@ enum { FD_RANDOM, FD_PARSE, FD_DISKUTIL, + FD_JOB, FD_DEBUG_MAX, }; @@ -21,17 +22,24 @@ enum { struct debug_level { const char *name; unsigned long shift; + unsigned int jobno; }; extern struct debug_level debug_levels[]; extern unsigned long fio_debug; +extern unsigned int fio_debug_jobno, *fio_debug_jobp; #define dprint(type, str, args...) \ do { \ + pid_t pid = getpid(); \ assert(type < FD_DEBUG_MAX); \ if ((((1 << type)) & fio_debug) == 0) \ break; \ + if (fio_debug_jobp && *fio_debug_jobp != -1U \ + && pid != *fio_debug_jobp) \ + break; \ log_info("%-8s ", debug_levels[(type)].name); \ + log_info("%-5u ", pid); \ log_info(str, ##args); \ } while (0) diff --git a/filehash.c b/filehash.c index b459220b..54cea990 100644 --- a/filehash.c +++ b/filehash.c @@ -79,6 +79,23 @@ struct fio_file *add_file_hash(struct fio_file *f) return alias; } +void file_hash_exit(void) +{ + unsigned int i, has_entries = 0; + + fio_mutex_down(hash_lock); + for (i = 0; i < HASH_BUCKETS; i++) + has_entries += !list_empty(&file_hash[i]); + fio_mutex_up(hash_lock); + + if (has_entries) + log_err("fio: file hash not empty on exit\n"); + + file_hash = NULL; + fio_mutex_remove(hash_lock); + hash_lock = NULL; +} + void file_hash_init(void *ptr) { unsigned int i; diff --git a/filehash.h b/filehash.h index a89a91f8..993943a0 100644 --- a/filehash.h +++ b/filehash.h @@ -4,6 +4,7 @@ extern unsigned int file_hash_size; extern void file_hash_init(void *); +extern void file_hash_exit(void); extern struct fio_file *lookup_file_hash(const char *); extern struct fio_file *add_file_hash(struct fio_file *); extern void remove_file_hash(struct fio_file *); diff --git a/fio.c b/fio.c index 90bad972..c17ea3c3 100644 --- a/fio.c +++ b/fio.c @@ -1233,12 +1233,15 @@ static void run_threads(void) if (pthread_detach(td->thread) < 0) perror("pthread_detach"); } else { + pid_t pid; dprint(FD_PROCESS, "will fork\n"); - if (!fork()) { + pid = fork(); + if (!pid) { int ret = fork_main(shm_id, i); - exit(ret); - } + _exit(ret); + } else if (i == fio_debug_jobno) + *fio_debug_jobp = pid; } fio_mutex_down(startup_mutex); } diff --git a/init.c b/init.c index 2a3fcee7..3469584f 100644 --- a/init.c +++ b/init.c @@ -47,6 +47,8 @@ static int write_lat_log; static int prev_group_jobs; unsigned long fio_debug = 0; +unsigned int fio_debug_jobno = -1; +unsigned int *fio_debug_jobp = NULL; /* * Command line options. These will contain the above, plus a few @@ -760,8 +762,12 @@ static void free_shm(void) struct shmid_ds sbuf; if (threads) { - shmdt((void *) threads); + void *tp = threads; + threads = NULL; + file_hash_exit(); + fio_debug_jobp = NULL; + shmdt(tp); shmctl(shm_id, IPC_RMID, &sbuf); } @@ -786,6 +792,7 @@ static int setup_thread_area(void) size_t size = max_jobs * sizeof(struct thread_data); size += file_hash_size; + size += sizeof(unsigned int); shm_id = shmget(0, size, IPC_CREAT | 0600); if (shm_id != -1) @@ -809,6 +816,8 @@ static int setup_thread_area(void) memset(threads, 0, max_jobs * sizeof(struct thread_data)); hash = (void *) threads + max_jobs * sizeof(struct thread_data); + fio_debug_jobp = (void *) hash + file_hash_size; + *fio_debug_jobp = -1; file_hash_init(hash); atexit(free_shm); return 0; @@ -849,6 +858,7 @@ struct debug_level debug_levels[] = { { .name = "random", .shift = FD_RANDOM }, { .name = "parse", .shift = FD_PARSE }, { .name = "diskutil", .shift = FD_DISKUTIL }, + { .name = "job", .shift = FD_JOB }, { }, }; @@ -869,22 +879,38 @@ static int set_debug(const char *string) } log_info("all\n"); return 1; - } else if (!strcmp(string, "all")) { - fio_debug = ~0UL; - return 0; } while ((opt = strsep(&p, ",")) != NULL) { int found = 0; + if (!strncmp(opt, "all", 3)) { + log_info("fio: set all debug options\n"); + fio_debug = ~0UL; + continue; + } + for (i = 0; debug_levels[i].name; i++) { dl = &debug_levels[i]; - if (!strncmp(opt, dl->name, strlen(opt))) { + found = !strncmp(opt, dl->name, strlen(dl->name)); + if (!found) + continue; + + if (dl->shift == FD_JOB) { + opt = strchr(opt, ':'); + if (!opt) { + log_err("fio: missing job number\n"); + break; + } + opt++; + fio_debug_jobno = atoi(opt); + log_info("fio: set debug jobno %d\n", + fio_debug_jobno); + } else { log_info("fio: set debug option %s\n", opt); - found = 1; fio_debug |= (1UL << dl->shift); - break; } + break; } if (!found) -- 2.25.1