From: Jens Axboe Date: Thu, 24 Nov 2005 15:06:29 +0000 (+0100) Subject: [PATCH] fio: add some basic disk utilization stats X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=debf703afaedadfef8b385e14c860e1e6a36ec51;p=disktools.git [PATCH] fio: add some basic disk utilization stats --- diff --git a/fio.c b/fio.c index 8cec4c5..a789bd8 100644 --- a/fio.c +++ b/fio.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -1474,6 +1476,157 @@ static int setup_file(struct thread_data *td) return setup_file_mmap(td); } +static int check_dev_match(dev_t dev, char *path) +{ + int major, minor; + char line[256], *p; + FILE *f; + + f = fopen(path, "r"); + if (!f) { + perror("open path"); + return 1; + } + + p = fgets(line, sizeof(line), f); + if (!p) { + fclose(f); + return 1; + } + + if (sscanf(p, "%u:%u", &major, &minor) != 2) { + fclose(f); + return 1; + } + + if (((major << 8) | minor) == dev) { + fclose(f); + return 0; + } + + fclose(f); + return 1; +} + +static char *find_block_dir(dev_t dev, char *path) +{ + struct dirent *dir; + char *found = NULL; + struct stat st; + DIR *D; + + D = opendir(path); + if (!D) + return NULL; + + while ((dir = readdir(D)) != NULL) { + char full_path[256]; + + if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..")) + continue; + if (!strcmp(dir->d_name, "device")) + continue; + + sprintf(full_path, "%s/%s", path, dir->d_name); + + if (!strcmp(dir->d_name, "dev")) { + if (!check_dev_match(dev, full_path)) { + found = path; + break; + } + } + + if (stat(full_path, &st) == -1) { + perror("stat"); + break; + } + + if (!S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode)) + continue; + + if ((found = find_block_dir(dev, full_path)) != NULL) + break; + } + + closedir(D); + return found; +} + +static int get_io_ticks(struct thread_data *td) +{ + int i1, i2, i3, i4, i5, i6, i7, i8, i9; + unsigned long long ull1, ull2; + char line[256]; + FILE *f; + char *p; + + f = fopen(td->disk_stat_path, "r"); + if (!f) + return 0; + + p = fgets(line, sizeof(line), f); + if (!p) { + fclose(f); + return 0; + } + + if (sscanf(p, "%8u %8u %8llu %8u %8u %8u %8llu %8u %8u %8u %8u", &i1, &i2, &ull1, &i3, &i4, &i5, &ull2, &i6, &i7, &i8, &i9) != 11) { + fclose(f); + return 0; + } + + fclose(f); + return i8; +} + +static void finish_disk_stats(struct thread_data *td) +{ + unsigned long ticks; + + ticks = get_io_ticks(td); + td->io_ticks = ticks - td->io_ticks; +} + +static int init_disk_stats(struct thread_data *td) +{ + struct stat st; + char foo[256], tmp[256]; + dev_t dev; + char *p, *dir; + + if (fstat(td->fd, &st) < 0) { + td->error = errno; + return 1; + } + + if (td->filetype == FIO_TYPE_FILE) + dev = st.st_dev; + else + dev = st.st_rdev; + + sprintf(foo, "/sys/block"); + dir = find_block_dir(dev, foo); + if (!dir) + return 0; + + /* + * if this is inside a partition dir, jump back to parent + */ + sprintf(tmp, "%s/queue", dir); + if (stat(tmp, &st)) { + p = dirname(dir); + sprintf(tmp, "%s/queue", p); + if (stat(tmp, &st)) { + fprintf(stderr, "unknown sysfs layout\n"); + return 0; + } + sprintf(td->disk_stat_path, "%s/stat", p); + } + + td->io_ticks = get_io_ticks(td); + return 0; +} + static void clear_io_state(struct thread_data *td) { if (!td->use_aio) @@ -1535,6 +1688,9 @@ static void *thread_main(void *data) if (!td->create_serialize && setup_file(td)) goto err; + if (init_disk_stats(td)) + goto err; + if (init_random_state(td)) goto err; @@ -1576,6 +1732,8 @@ static void *thread_main(void *data) ret = 0; + finish_disk_stats(td); + if (td->bw_log) finish_log(td, td->bw_log, "bw"); if (td->lat_log) @@ -1675,6 +1833,11 @@ static void show_thread_status(struct thread_data *td, } printf(" cpu : usr=%3.2f%%, sys=%3.2f%%, ctx=%lu\n", usr_cpu, sys_cpu, td->ctx); + + if (td->io_ticks) { + double disk_util = (double) 100 * td->io_ticks / (double) td->runtime; + printf(" disk : util=%3.2f%%\n", disk_util); + } } static void print_thread_status(struct thread_data *td, int nr_running, diff --git a/fio.h b/fio.h index 96df3bf..1ef9d33 100644 --- a/fio.h +++ b/fio.h @@ -167,6 +167,12 @@ struct thread_data { unsigned long ctx; struct list_head io_hist_list; + + /* + * disk util stats + */ + char disk_stat_path[256]; + unsigned long io_ticks; }; extern int parse_jobs_ini(char *);