Add job number specific dumping and fix atexit() error
authorJens Axboe <jens.axboe@oracle.com>
Fri, 23 May 2008 09:55:53 +0000 (11:55 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Fri, 23 May 2008 09:55:53 +0000 (11:55 +0200)
The threads/process jobs should use _exit() so they don't run
the main atexit() function.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
README
debug.h
filehash.c
filehash.h
fio.c
init.c

diff --git a/README b/README
index ea8f5ef8e22c47462abafae9faf53e03509bc24f..53cc7ebd54689f62bab783865806ae53ec64a62f 100644 (file)
--- 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 22577a8a8afccee744c55c8ec8c4879659208093..883628da0b22fb07c9838ce0aa63b90f9e355576 100644 (file)
--- 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)
 
index b459220b6766317a31e35cba31e546e69768ff6e..54cea990f927c158c3987bca29904e9e2bc47b98 100644 (file)
@@ -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;
index a89a91f81d8d2ce6941deada5c02291df63ca6d2..993943a0be2dd9141285e8439fd3d138bb2ceaf5 100644 (file)
@@ -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 90bad972727e403ff9474ef71e913b63790bd7fb..c17ea3c3ae8822ba68f8f705c4ce13812d5052a3 100644 (file)
--- 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 2a3fcee73ddb7eeb9839650ba3ee28286f6ca581..3469584f3c9f51162f5a9c2fb755213af7bfb736 100644 (file)
--- 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)