19f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe#include <stdio.h>
29f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe#include <string.h>
39f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe#include <sys/time.h>
49f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe#include <sys/types.h>
59f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe#include <sys/stat.h>
69f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe#include <dirent.h>
79f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe#include <libgen.h>
89f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe#include <math.h>
99edf7b3ed581a61433ad620d457b4d0349115e52Jens Axboe#include <assert.h>
109f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
119f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe#include "fio.h"
12c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe#include "smalloc.h"
137c9b1bce094d58c374b086bbb780c08265623ea4Jens Axboe#include "diskutil.h"
149f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
159f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboestatic int last_majdev, last_mindev;
16c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboestatic struct disk_util *last_du;
179f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
189ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboestatic struct fio_mutex *disk_util_mutex;
199ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe
20d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens AxboeFLIST_HEAD(disk_list);
219f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
222db4ecca2d502c6d26386b5eb918a7957d98afb7Jens Axboestatic struct disk_util *__init_per_file_disk_util(struct thread_data *td,
232db4ecca2d502c6d26386b5eb918a7957d98afb7Jens Axboe		int majdev, int mindev, char *path);
242db4ecca2d502c6d26386b5eb918a7957d98afb7Jens Axboe
25c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboestatic void disk_util_free(struct disk_util *du)
26c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe{
27c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe	if (du == last_du)
28c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe		last_du = NULL;
29c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe
30b8d541d5705ef74307277d541ca9153ab8844096Jens Axboe	while (!flist_empty(&du->slaves)) {
31b8d541d5705ef74307277d541ca9153ab8844096Jens Axboe		struct disk_util *slave;
32b8d541d5705ef74307277d541ca9153ab8844096Jens Axboe
33b8d541d5705ef74307277d541ca9153ab8844096Jens Axboe		slave = flist_entry(du->slaves.next, struct disk_util, slavelist);
34b8d541d5705ef74307277d541ca9153ab8844096Jens Axboe		flist_del(&slave->slavelist);
35b8d541d5705ef74307277d541ca9153ab8844096Jens Axboe		slave->users--;
36b8d541d5705ef74307277d541ca9153ab8844096Jens Axboe	}
3793bcfd20e37cef8cec350fe06d3a086724c9f257Bruce Cran
38c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe	fio_mutex_remove(du->lock);
39c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe	sfree(du);
40c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe}
41c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe
429f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboestatic int get_io_ticks(struct disk_util *du, struct disk_util_stat *dus)
439f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe{
449f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	unsigned in_flight;
45d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	unsigned long long sectors[2];
469f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	char line[256];
479f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	FILE *f;
489f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	char *p;
495ec10eaad3b09875b91e19a20bbdfa06f2117562Jens Axboe	int ret;
509f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
51cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe	dprint(FD_DISKUTIL, "open stat file: %s\n", du->path);
52cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe
539f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	f = fopen(du->path, "r");
549f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	if (!f)
559f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		return 1;
569f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
579f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	p = fgets(line, sizeof(line), f);
589f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	if (!p) {
599f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		fclose(f);
609f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		return 1;
619f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	}
629f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
63cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe	dprint(FD_DISKUTIL, "%s: %s", du->path, p);
64cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe
65a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	ret = sscanf(p, "%u %u %llu %u %u %u %llu %u %u %u %u\n",
66a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					&dus->s.ios[0],
67a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					&dus->s.merges[0], &sectors[0],
68a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					&dus->s.ticks[0], &dus->s.ios[1],
69a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					&dus->s.merges[1], &sectors[1],
70a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					&dus->s.ticks[1], &in_flight,
71a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					&dus->s.io_ticks,
72a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					&dus->s.time_in_queue);
739f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	fclose(f);
74cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe	dprint(FD_DISKUTIL, "%s: stat read ok? %d\n", du->path, ret == 1);
75a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	dus->s.sectors[0] = sectors[0];
76a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	dus->s.sectors[1] = sectors[1];
77cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe	return ret != 11;
789f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe}
799f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
809f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboestatic void update_io_tick_disk(struct disk_util *du)
819f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe{
829f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	struct disk_util_stat __dus, *dus, *ldus;
839f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	struct timeval t;
849f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
85c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe	if (!du->users)
86c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe		return;
8790b97ac3bc4368b79300207c796bcfbb828d07b9Jens Axboe	if (get_io_ticks(du, &__dus))
8890b97ac3bc4368b79300207c796bcfbb828d07b9Jens Axboe		return;
899f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
909f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	dus = &du->dus;
919f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	ldus = &du->last_dus;
929f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
93a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	dus->s.sectors[0] += (__dus.s.sectors[0] - ldus->s.sectors[0]);
94a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	dus->s.sectors[1] += (__dus.s.sectors[1] - ldus->s.sectors[1]);
95a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	dus->s.ios[0] += (__dus.s.ios[0] - ldus->s.ios[0]);
96a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	dus->s.ios[1] += (__dus.s.ios[1] - ldus->s.ios[1]);
97a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	dus->s.merges[0] += (__dus.s.merges[0] - ldus->s.merges[0]);
98a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	dus->s.merges[1] += (__dus.s.merges[1] - ldus->s.merges[1]);
99a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	dus->s.ticks[0] += (__dus.s.ticks[0] - ldus->s.ticks[0]);
100a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	dus->s.ticks[1] += (__dus.s.ticks[1] - ldus->s.ticks[1]);
101a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	dus->s.io_ticks += (__dus.s.io_ticks - ldus->s.io_ticks);
102a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	dus->s.time_in_queue += (__dus.s.time_in_queue - ldus->s.time_in_queue);
1039f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
1049f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	fio_gettime(&t, NULL);
105a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	dus->s.msec += mtime_since(&du->time, &t);
1069f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	memcpy(&du->time, &t, sizeof(t));
107a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	memcpy(&ldus->s, &__dus.s, sizeof(__dus.s));
1089f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe}
1099f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
1109ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboeint update_io_ticks(void)
1119f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe{
11201743ee1718e7ec4b16ae3e53c8f64900c6052ccJens Axboe	struct flist_head *entry;
1139f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	struct disk_util *du;
1149ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	int ret = 0;
1159f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
116cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe	dprint(FD_DISKUTIL, "update io ticks\n");
117cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe
1189ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	fio_mutex_down(disk_util_mutex);
1199ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe
1209ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	if (!disk_util_exit) {
1219ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe		flist_for_each(entry, &disk_list) {
1229ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe			du = flist_entry(entry, struct disk_util, list);
1239ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe			update_io_tick_disk(du);
1249ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe		}
1259ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	} else
1269ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe		ret = 1;
1279ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe
1289ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	fio_mutex_up(disk_util_mutex);
1299ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	return ret;
1309f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe}
1319f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
132e11c410cbd60400c10d92d0115880c6e5728aa4eJens Axboestatic struct disk_util *disk_util_exists(int major, int minor)
1339f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe{
13401743ee1718e7ec4b16ae3e53c8f64900c6052ccJens Axboe	struct flist_head *entry;
1359f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	struct disk_util *du;
1369f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
1379ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	fio_mutex_down(disk_util_mutex);
1389ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe
13901743ee1718e7ec4b16ae3e53c8f64900c6052ccJens Axboe	flist_for_each(entry, &disk_list) {
14001743ee1718e7ec4b16ae3e53c8f64900c6052ccJens Axboe		du = flist_entry(entry, struct disk_util, list);
1419f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
1429ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe		if (major == du->major && minor == du->minor) {
1439ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe			fio_mutex_up(disk_util_mutex);
144e11c410cbd60400c10d92d0115880c6e5728aa4eJens Axboe			return du;
1459ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe		}
1469f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	}
1479f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
1489ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	fio_mutex_up(disk_util_mutex);
149e11c410cbd60400c10d92d0115880c6e5728aa4eJens Axboe	return NULL;
1509f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe}
1519f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
1526742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoostatic int get_device_numbers(char *file_name, int *maj, int *min)
1536742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo{
1546742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	struct stat st;
1556742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	int majdev, mindev;
1566742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	char tempname[PATH_MAX], *p;
1576742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
1586742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	if (!lstat(file_name, &st)) {
1596742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		if (S_ISBLK(st.st_mode)) {
1606742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			majdev = major(st.st_rdev);
1616742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			mindev = minor(st.st_rdev);
1626742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		} else if (S_ISCHR(st.st_mode)) {
1636742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			majdev = major(st.st_rdev);
1646742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			mindev = minor(st.st_rdev);
1656742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			if (fio_lookup_raw(st.st_rdev, &majdev, &mindev))
1666742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo				return -1;
1676742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		} else if (S_ISFIFO(st.st_mode))
1686742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			return -1;
1696742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		else {
1706742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			majdev = major(st.st_dev);
1716742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			mindev = minor(st.st_dev);
1726742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		}
1736742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	} else {
1746742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		/*
1756742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		 * must be a file, open "." in that path
1766742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		 */
1776742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		strncpy(tempname, file_name, PATH_MAX - 1);
1786742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		p = dirname(tempname);
1796742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		if (stat(p, &st)) {
1806742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			perror("disk util stat");
1816742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			return -1;
1826742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		}
1836742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
1846742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		majdev = major(st.st_dev);
1856742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		mindev = minor(st.st_dev);
1866742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	}
1876742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
1886742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	*min = mindev;
1896742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	*maj = majdev;
1906742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
1916742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	return 0;
1926742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo}
1936742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
1946742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoostatic int read_block_dev_entry(char *path, int *maj, int *min)
1956742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo{
1966742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	char line[256], *p;
1976742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	FILE *f;
1986742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
1996742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	f = fopen(path, "r");
2006742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	if (!f) {
2016742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		perror("open path");
2026742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		return 1;
2036742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	}
2046742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
2056742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	p = fgets(line, sizeof(line), f);
2066742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	fclose(f);
2076742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
2086742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	if (!p)
2096742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		return 1;
2106742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
2116742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	if (sscanf(p, "%u:%u", maj, min) != 2)
2126742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		return 1;
2136742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
2146742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	return 0;
2156742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo}
2166742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
2176742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoostatic void find_add_disk_slaves(struct thread_data *td, char *path,
2182db4ecca2d502c6d26386b5eb918a7957d98afb7Jens Axboe				 struct disk_util *masterdu)
2196742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo{
2206742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	DIR *dirhandle = NULL;
2216742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	struct dirent *dirent = NULL;
2226742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	char slavesdir[PATH_MAX], temppath[PATH_MAX], slavepath[PATH_MAX];
2236742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	struct disk_util *slavedu = NULL;
2246742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	int majdev, mindev;
2256742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	ssize_t linklen;
2266742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
2272db4ecca2d502c6d26386b5eb918a7957d98afb7Jens Axboe	sprintf(slavesdir, "%s/%s", path, "slaves");
2286742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	dirhandle = opendir(slavesdir);
2296742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	if (!dirhandle)
2306742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		return;
2316742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
2326742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	while ((dirent = readdir(dirhandle)) != NULL) {
2332db4ecca2d502c6d26386b5eb918a7957d98afb7Jens Axboe		if (!strcmp(dirent->d_name, ".") ||
2342db4ecca2d502c6d26386b5eb918a7957d98afb7Jens Axboe		    !strcmp(dirent->d_name, ".."))
2356742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			continue;
2366742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
237b9fd788f0e8adacc33316107594e9eb0463743d7Bruce Cran		sprintf(temppath, "%s%s%s", slavesdir, FIO_OS_PATH_SEPARATOR, dirent->d_name);
2386742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		/* Can we always assume that the slaves device entries
2396742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		 * are links to the real directories for the slave
2406742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		 * devices?
2416742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		 */
242976406b8a0d823f053400178b7b86f32a973762dJens Axboe		linklen = readlink(temppath, slavepath, PATH_MAX - 1);
2432db4ecca2d502c6d26386b5eb918a7957d98afb7Jens Axboe		if (linklen  < 0) {
2446742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			perror("readlink() for slave device.");
245f0cc675fd0a5902f3637a91024082d2d24a665a7Jens Axboe			closedir(dirhandle);
2466742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			return;
2476742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		}
2482db4ecca2d502c6d26386b5eb918a7957d98afb7Jens Axboe		slavepath[linklen] = '\0';
2496742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
2506742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		sprintf(temppath, "%s/%s/dev", slavesdir, slavepath);
2516742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		if (read_block_dev_entry(temppath, &majdev, &mindev)) {
2526742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			perror("Error getting slave device numbers.");
253f0cc675fd0a5902f3637a91024082d2d24a665a7Jens Axboe			closedir(dirhandle);
2546742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			return;
2556742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		}
2566742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
257b06de82e3b075874733dd233571499c1c1ca453cAlan D. Brunelle		/*
258b06de82e3b075874733dd233571499c1c1ca453cAlan D. Brunelle		 * See if this maj,min already exists
259b06de82e3b075874733dd233571499c1c1ca453cAlan D. Brunelle		 */
260b06de82e3b075874733dd233571499c1c1ca453cAlan D. Brunelle		slavedu = disk_util_exists(majdev, mindev);
261b06de82e3b075874733dd233571499c1c1ca453cAlan D. Brunelle		if (slavedu)
262b06de82e3b075874733dd233571499c1c1ca453cAlan D. Brunelle			continue;
263b06de82e3b075874733dd233571499c1c1ca453cAlan D. Brunelle
264b9fd788f0e8adacc33316107594e9eb0463743d7Bruce Cran		sprintf(temppath, "%s%s%s", slavesdir, FIO_OS_PATH_SEPARATOR, slavepath);
2656742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		__init_per_file_disk_util(td, majdev, mindev, temppath);
2666742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		slavedu = disk_util_exists(majdev, mindev);
2676742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
2686742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		/* Should probably use an assert here. slavedu should
2696742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		 * always be present at this point. */
270b8d541d5705ef74307277d541ca9153ab8844096Jens Axboe		if (slavedu) {
271b8d541d5705ef74307277d541ca9153ab8844096Jens Axboe			slavedu->users++;
2726742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			flist_add_tail(&slavedu->slavelist, &masterdu->slaves);
273b8d541d5705ef74307277d541ca9153ab8844096Jens Axboe		}
2746742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	}
2756742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
2766742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	closedir(dirhandle);
2776742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo}
2786742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
279b8fefc2b27591449b75e946da781342f616fae14Jens Axboestatic struct disk_util *disk_util_add(struct thread_data *td, int majdev,
280c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe				       int mindev, char *path)
2819f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe{
2829f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	struct disk_util *du, *__du;
28301743ee1718e7ec4b16ae3e53c8f64900c6052ccJens Axboe	struct flist_head *entry;
2844b919f7740f4875d73c0619a08d269d5c679e19fKen Raeburn	int l;
2859f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
286cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe	dprint(FD_DISKUTIL, "add maj/min %d/%d: %s\n", majdev, mindev, path);
287cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe
288c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe	du = smalloc(sizeof(*du));
289fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe	if (!du) {
290fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe		log_err("fio: smalloc() pool exhausted\n");
291fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe		return NULL;
292fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe	}
293fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe
2949f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	memset(du, 0, sizeof(*du));
29501743ee1718e7ec4b16ae3e53c8f64900c6052ccJens Axboe	INIT_FLIST_HEAD(&du->list);
2964b919f7740f4875d73c0619a08d269d5c679e19fKen Raeburn	l = snprintf(du->path, sizeof(du->path), "%s/stat", path);
2974b919f7740f4875d73c0619a08d269d5c679e19fKen Raeburn	if (l < 0 || l >= sizeof(du->path)) {
2984b919f7740f4875d73c0619a08d269d5c679e19fKen Raeburn		log_err("constructed path \"%.100s[...]/stat\" larger than buffer (%zu bytes)\n",
2994b919f7740f4875d73c0619a08d269d5c679e19fKen Raeburn			path, sizeof(du->path) - 1);
3004b919f7740f4875d73c0619a08d269d5c679e19fKen Raeburn		sfree(du);
3014b919f7740f4875d73c0619a08d269d5c679e19fKen Raeburn		return NULL;
3024b919f7740f4875d73c0619a08d269d5c679e19fKen Raeburn	}
303a2ba41edb1d278237a5990c4860291b35463f231Jens Axboe	strncpy((char *) du->dus.name, basename(path), FIO_DU_NAME_SZ - 1);
304e11c410cbd60400c10d92d0115880c6e5728aa4eJens Axboe	du->sysfs_root = path;
3059f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	du->major = majdev;
3069f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	du->minor = mindev;
3076742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	INIT_FLIST_HEAD(&du->slavelist);
3086742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	INIT_FLIST_HEAD(&du->slaves);
309521da527743088a9bd2ab882f8b64799d49d5848Jens Axboe	du->lock = fio_mutex_init(FIO_MUTEX_UNLOCKED);
310c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe	du->users = 0;
3119f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
3129ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	fio_mutex_down(disk_util_mutex);
3139ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe
31401743ee1718e7ec4b16ae3e53c8f64900c6052ccJens Axboe	flist_for_each(entry, &disk_list) {
31501743ee1718e7ec4b16ae3e53c8f64900c6052ccJens Axboe		__du = flist_entry(entry, struct disk_util, list);
3169f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
317d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		dprint(FD_DISKUTIL, "found %s in list\n", __du->dus.name);
318cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe
319d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		if (!strcmp((char *) du->dus.name, (char *) __du->dus.name)) {
320c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe			disk_util_free(du);
3219ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe			fio_mutex_up(disk_util_mutex);
322c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe			return __du;
3239f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		}
3249f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	}
3259f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
326d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	dprint(FD_DISKUTIL, "add %s to list\n", du->dus.name);
327cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe
3289f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	fio_gettime(&du->time, NULL);
3299f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	get_io_ticks(du, &du->last_dus);
3309f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
33101743ee1718e7ec4b16ae3e53c8f64900c6052ccJens Axboe	flist_add_tail(&du->list, &disk_list);
3329ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	fio_mutex_up(disk_util_mutex);
3339ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe
3346742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	find_add_disk_slaves(td, path, du);
335c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe	return du;
3369f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe}
3379f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
3389f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboestatic int check_dev_match(int majdev, int mindev, char *path)
3399f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe{
3409f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	int major, minor;
3419f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
3426742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	if (read_block_dev_entry(path, &major, &minor))
3439f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		return 1;
3449f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
345c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe	if (majdev == major && mindev == minor)
3469f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		return 0;
3479f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
3489f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	return 1;
3499f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe}
3509f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
351ac0be2acff3864979e5e260d332d25ca90e22417Jens Axboestatic int find_block_dir(int majdev, int mindev, char *path, int link_ok)
3529f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe{
3539f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	struct dirent *dir;
3549f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	struct stat st;
3559f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	int found = 0;
3569f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	DIR *D;
3579f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
3589f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	D = opendir(path);
3599f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	if (!D)
3609f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		return 0;
3619f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
3629f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	while ((dir = readdir(D)) != NULL) {
3639f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		char full_path[256];
3649f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
3659f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
3669f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe			continue;
3679f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
368b9fd788f0e8adacc33316107594e9eb0463743d7Bruce Cran		sprintf(full_path, "%s%s%s", path, FIO_OS_PATH_SEPARATOR, dir->d_name);
3699f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
3709f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		if (!strcmp(dir->d_name, "dev")) {
3719f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe			if (!check_dev_match(majdev, mindev, full_path)) {
3729f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe				found = 1;
3739f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe				break;
3749f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe			}
3759f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		}
3769f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
377ac0be2acff3864979e5e260d332d25ca90e22417Jens Axboe		if (link_ok) {
378ac0be2acff3864979e5e260d332d25ca90e22417Jens Axboe			if (stat(full_path, &st) == -1) {
379ac0be2acff3864979e5e260d332d25ca90e22417Jens Axboe				perror("stat");
380ac0be2acff3864979e5e260d332d25ca90e22417Jens Axboe				break;
381ac0be2acff3864979e5e260d332d25ca90e22417Jens Axboe			}
382ac0be2acff3864979e5e260d332d25ca90e22417Jens Axboe		} else {
383ac0be2acff3864979e5e260d332d25ca90e22417Jens Axboe			if (lstat(full_path, &st) == -1) {
384ac0be2acff3864979e5e260d332d25ca90e22417Jens Axboe				perror("stat");
385ac0be2acff3864979e5e260d332d25ca90e22417Jens Axboe				break;
386ac0be2acff3864979e5e260d332d25ca90e22417Jens Axboe			}
3879f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		}
3889f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
3899f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		if (!S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))
3909f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe			continue;
3919f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
392ac0be2acff3864979e5e260d332d25ca90e22417Jens Axboe		found = find_block_dir(majdev, mindev, full_path, 0);
3939f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		if (found) {
3949f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe			strcpy(path, full_path);
3959f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe			break;
3969f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		}
3979f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	}
3989f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
3999f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	closedir(D);
4009f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	return found;
4019f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe}
4029f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
403c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboestatic struct disk_util *__init_per_file_disk_util(struct thread_data *td,
404c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe						   int majdev, int mindev,
405c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe						   char *path)
4069f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe{
4079f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	struct stat st;
4086742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	char tmp[PATH_MAX];
4099f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	char *p;
4109f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
4116742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	/*
4126742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	 * If there's a ../queue/ directory there, we are inside a partition.
4136742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	 * Check if that is the case and jump back. For loop/md/dm etc we
4146742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	 * are already in the right spot.
4156742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	 */
4166742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	sprintf(tmp, "%s/../queue", path);
4176742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	if (!stat(tmp, &st)) {
4186742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		p = dirname(path);
4196742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		sprintf(tmp, "%s/queue", p);
4206742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		if (stat(tmp, &st)) {
4216742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			log_err("unknown sysfs layout\n");
422c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe			return NULL;
4239f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		}
4246742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		strncpy(tmp, p, PATH_MAX - 1);
4256742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		sprintf(path, "%s", tmp);
4269f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	}
4279f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
4286742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	if (td->o.ioscheduler && !td->sysfs_root)
4296742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo		td->sysfs_root = strdup(path);
4306742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
431c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe	return disk_util_add(td, majdev, mindev, path);
4326742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo}
4336742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
434c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboestatic struct disk_util *init_per_file_disk_util(struct thread_data *td,
435c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe						 char *filename)
4366742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo{
4376742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
4386742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	char foo[PATH_MAX];
4396742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	struct disk_util *du;
4406742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	int mindev, majdev;
4416742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
442c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe	if (get_device_numbers(filename, &majdev, &mindev))
443c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe		return NULL;
4446742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo
4456742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	dprint(FD_DISKUTIL, "%s belongs to maj/min %d/%d\n", filename, majdev,
4466742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo			mindev);
447cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe
448e11c410cbd60400c10d92d0115880c6e5728aa4eJens Axboe	du = disk_util_exists(majdev, mindev);
449e11c410cbd60400c10d92d0115880c6e5728aa4eJens Axboe	if (du) {
450e11c410cbd60400c10d92d0115880c6e5728aa4eJens Axboe		if (td->o.ioscheduler && !td->sysfs_root)
451e11c410cbd60400c10d92d0115880c6e5728aa4eJens Axboe			td->sysfs_root = strdup(du->sysfs_root);
452e11c410cbd60400c10d92d0115880c6e5728aa4eJens Axboe
453c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe		return du;
454e11c410cbd60400c10d92d0115880c6e5728aa4eJens Axboe	}
4559f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
4569f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	/*
4579f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	 * for an fs without a device, we will repeatedly stat through
4589f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	 * sysfs which can take oodles of time for thousands of files. so
4599f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	 * cache the last lookup and compare with that before going through
4609f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	 * everything again.
4619f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	 */
4629f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	if (mindev == last_mindev && majdev == last_majdev)
463c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe		return last_du;
4649f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
4659f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	last_mindev = mindev;
4669f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	last_majdev = majdev;
4675ec10eaad3b09875b91e19a20bbdfa06f2117562Jens Axboe
4689f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	sprintf(foo, "/sys/block");
469ac0be2acff3864979e5e260d332d25ca90e22417Jens Axboe	if (!find_block_dir(majdev, mindev, foo, 1))
470c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe		return NULL;
4719f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
472c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe	return __init_per_file_disk_util(td, majdev, mindev, foo);
4736742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo}
4749f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
475c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboestatic struct disk_util *__init_disk_util(struct thread_data *td,
476c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe					  struct fio_file *f)
4776742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo{
4786742301361b7eeded19656ac18a09fde33122b74Shehjar Tikoo	return init_per_file_disk_util(td, f->file_name);
4799f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe}
4809f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
4819f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboevoid init_disk_util(struct thread_data *td)
4829f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe{
4839f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	struct fio_file *f;
4849f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	unsigned int i;
4859f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
4869f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	if (!td->o.do_disk_util ||
4879f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	    (td->io_ops->flags & (FIO_DISKLESSIO | FIO_NODISKUTIL)))
4889f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe		return;
4899f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
4909f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	for_each_file(td, f, i)
491c97bd0fa0f68d924f4e6f3c480f380c4ca20b872Jens Axboe		f->du = __init_disk_util(td, f);
4929f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe}
4939f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
494f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboestatic void show_agg_stats(struct disk_util_agg *agg, int terse)
495d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe{
496d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	if (!agg->slavecount)
497d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		return;
498d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
499f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe	if (!terse) {
500f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe		log_info(", aggrios=%u/%u, aggrmerge=%u/%u, aggrticks=%u/%u,"
501f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				" aggrin_queue=%u, aggrutil=%3.2f%%",
502f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->ios[0] / agg->slavecount,
503f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->ios[1] / agg->slavecount,
504f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->merges[0] / agg->slavecount,
505f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->merges[1] / agg->slavecount,
506f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->ticks[0] / agg->slavecount,
507f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->ticks[1] / agg->slavecount,
508f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->time_in_queue / agg->slavecount,
509f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->max_util.u.f);
510f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe	} else {
51197b007ec1428ae434790d64cf528a9b101d1265dJens Axboe		log_info(";slaves;%u;%u;%u;%u;%u;%u;%u;%3.2f%%",
512f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->ios[0] / agg->slavecount,
513f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->ios[1] / agg->slavecount,
514f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->merges[0] / agg->slavecount,
515f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->merges[1] / agg->slavecount,
516f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->ticks[0] / agg->slavecount,
517f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->ticks[1] / agg->slavecount,
518f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->time_in_queue / agg->slavecount,
519f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe				agg->max_util.u.f);
520f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe	}
521d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe}
522d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
523043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoostatic void aggregate_slaves_stats(struct disk_util *masterdu)
524043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo{
525d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	struct disk_util_agg *agg = &masterdu->agg;
526043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo	struct disk_util_stat *dus;
527043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo	struct flist_head *entry;
528043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo	struct disk_util *slavedu;
529d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	double util;
530043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo
531043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo	flist_for_each(entry, &masterdu->slaves) {
532043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo		slavedu = flist_entry(entry, struct disk_util, slavelist);
533043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo		dus = &slavedu->dus;
534a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe		agg->ios[0] += dus->s.ios[0];
535a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe		agg->ios[1] += dus->s.ios[1];
536a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe		agg->merges[0] += dus->s.merges[0];
537a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe		agg->merges[1] += dus->s.merges[1];
538a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe		agg->sectors[0] += dus->s.sectors[0];
539a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe		agg->sectors[1] += dus->s.sectors[1];
540a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe		agg->ticks[0] += dus->s.ticks[0];
541a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe		agg->ticks[1] += dus->s.ticks[1];
542a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe		agg->time_in_queue += dus->s.time_in_queue;
543d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		agg->slavecount++;
544d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
545a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe		util = (double) (100 * dus->s.io_ticks / (double) slavedu->dus.s.msec);
546043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo		/* System utilization is the utilization of the
547043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo		 * component with the highest utilization.
548043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo		 */
549d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		if (util > agg->max_util.u.f)
550d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe			agg->max_util.u.f = util;
551043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo
552043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo	}
553043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo
554d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	if (agg->max_util.u.f > 100.0)
555d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		agg->max_util.u.f = 100.0;
556d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe}
557d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
55827357187b0899380bae5c6748f2b2d034502e162Jens Axboevoid disk_util_prune_entries(void)
559d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe{
5609ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	fio_mutex_down(disk_util_mutex);
5619ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe
562d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	while (!flist_empty(&disk_list)) {
56327357187b0899380bae5c6748f2b2d034502e162Jens Axboe		struct disk_util *du;
56427357187b0899380bae5c6748f2b2d034502e162Jens Axboe
565d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		du = flist_entry(disk_list.next, struct disk_util, list);
566d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		flist_del(&du->list);
567d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		disk_util_free(du);
568d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	}
569043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo
570d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	last_majdev = last_mindev = -1;
5719ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	fio_mutex_up(disk_util_mutex);
5729ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	fio_mutex_remove(disk_util_mutex);
573d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe}
574d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
575f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboevoid print_disk_util(struct disk_util_stat *dus, struct disk_util_agg *agg,
576f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe		     int terse)
577d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe{
5786914f59e5e3560325dc8892c9f77689df7b9aa8bJens Axboe	double util = 0;
579d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
580a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	if (dus->s.msec)
581a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe		util = (double) 100 * dus->s.io_ticks / (double) dus->s.msec;
582d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	if (util > 100.0)
583d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		util = 100.0;
584d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
585f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe	if (!terse) {
586f1d64553c9dc0e99c038cf3a5f0cb2a50026e7d3Jens Axboe		if (agg->slavecount)
587f1d64553c9dc0e99c038cf3a5f0cb2a50026e7d3Jens Axboe			log_info("  ");
588f1d64553c9dc0e99c038cf3a5f0cb2a50026e7d3Jens Axboe
589f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe		log_info("  %s: ios=%u/%u, merge=%u/%u, ticks=%u/%u, "
590f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe			 "in_queue=%u, util=%3.2f%%", dus->name,
591a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					dus->s.ios[0], dus->s.ios[1],
592a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					dus->s.merges[0], dus->s.merges[1],
593a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					dus->s.ticks[0], dus->s.ticks[1],
594a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					dus->s.time_in_queue, util);
595f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe	} else {
5963d7cd9b4c2570548bebfae4871c3ca068c5a29feJens Axboe		log_info(";%s;%u;%u;%u;%u;%u;%u;%u;%3.2f%%",
597a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					dus->name, dus->s.ios[0],
598a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					dus->s.ios[1], dus->s.merges[0],
599a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					dus->s.merges[1], dus->s.ticks[0],
600a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					dus->s.ticks[1],
601a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe					dus->s.time_in_queue, util);
602f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe	}
603d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
604d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	/*
605d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	 * If the device has slaves, aggregate the stats for
606d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	 * those slave devices also.
607d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	 */
608f1d64553c9dc0e99c038cf3a5f0cb2a50026e7d3Jens Axboe	show_agg_stats(agg, terse);
609d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
610f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe	if (!terse)
611f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe		log_info("\n");
612043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo}
613043b74b9ddba4cc7ecb876ca41b7daa7d1ec5da3Shehjar Tikoo
614952b05e00103bf45576e1860cde0626bd42ed52aCastor Fuvoid json_array_add_disk_util(struct disk_util_stat *dus,
615952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu		struct disk_util_agg *agg, struct json_array *array)
616cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li{
617cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	struct json_object *obj;
618952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu	double util = 0;
619cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li
620a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	if (dus->s.msec)
621a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe		util = (double) 100 * dus->s.io_ticks / (double) dus->s.msec;
622cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	if (util > 100.0)
623cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li		util = 100.0;
624cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li
625952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu	obj = json_create_object();
626952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu	json_array_add_value_object(array, obj);
627cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li
628cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	json_object_add_value_string(obj, "name", dus->name);
629a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	json_object_add_value_int(obj, "read_ios", dus->s.ios[0]);
630a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	json_object_add_value_int(obj, "write_ios", dus->s.ios[1]);
631a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	json_object_add_value_int(obj, "read_merges", dus->s.merges[0]);
632a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	json_object_add_value_int(obj, "write_merges", dus->s.merges[1]);
633a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	json_object_add_value_int(obj, "read_ticks", dus->s.ticks[0]);
634a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	json_object_add_value_int(obj, "write_ticks", dus->s.ticks[1]);
635a3b4cf7dcae447729f0f4a4ea122f605b909ed70Jens Axboe	json_object_add_value_int(obj, "in_queue", dus->s.time_in_queue);
636cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	json_object_add_value_float(obj, "util", util);
637cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li
638cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	/*
639cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	 * If the device has slaves, aggregate the stats for
640cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	 * those slave devices also.
641cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	 */
642cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	if (!agg->slavecount)
643cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li		return;
644cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	json_object_add_value_int(obj, "aggr_read_ios",
645cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li				agg->ios[0] / agg->slavecount);
646cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	json_object_add_value_int(obj, "aggr_write_ios",
647cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li				agg->ios[1] / agg->slavecount);
648cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	json_object_add_value_int(obj, "aggr_read_merges",
649cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li				agg->merges[0] / agg->slavecount);
650cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	json_object_add_value_int(obj, "aggr_write_merge",
651cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li				agg->merges[1] / agg->slavecount);
652cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	json_object_add_value_int(obj, "aggr_read_ticks",
653cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li				agg->ticks[0] / agg->slavecount);
654cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	json_object_add_value_int(obj, "aggr_write_ticks",
655cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li				agg->ticks[1] / agg->slavecount);
656cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	json_object_add_value_int(obj, "aggr_in_queue",
657cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li				agg->time_in_queue / agg->slavecount);
658cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li	json_object_add_value_float(obj, "aggr_util", agg->max_util.u.f);
659cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li}
660cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li
66110aa136bddbaa7c845ab4eacb4a9a4a88d6657a3Jens Axboestatic void json_object_add_disk_utils(struct json_object *obj,
66210aa136bddbaa7c845ab4eacb4a9a4a88d6657a3Jens Axboe				       struct flist_head *head)
663952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu{
664952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu	struct json_array *array = json_create_array();
665952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu	struct flist_head *entry;
666952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu	struct disk_util *du;
667952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu
668952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu	json_object_add_value_array(obj, "disk_util", array);
669952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu
670952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu	flist_for_each(entry, head) {
671952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu		du = flist_entry(entry, struct disk_util, list);
672952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu
673952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu		aggregate_slaves_stats(du);
674952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu		json_array_add_disk_util(&du->dus, &du->agg, array);
675952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu	}
676952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu}
677952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu
678cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Livoid show_disk_util(int terse, struct json_object *parent)
6799f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe{
680d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	struct flist_head *entry;
6819f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe	struct disk_util *du;
6829f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
6839ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	fio_mutex_down(disk_util_mutex);
6849ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe
6859ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	if (flist_empty(&disk_list)) {
6869ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe		fio_mutex_up(disk_util_mutex);
6870a839f308177e95c4c45c41ee1d4fa2b8f231f24Jens Axboe		return;
6889ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	}
6890a839f308177e95c4c45c41ee1d4fa2b8f231f24Jens Axboe
6909edf7b3ed581a61433ad620d457b4d0349115e52Jens Axboe	if (output_format == FIO_OUTPUT_JSON)
6919edf7b3ed581a61433ad620d457b4d0349115e52Jens Axboe		assert(parent);
6929edf7b3ed581a61433ad620d457b4d0349115e52Jens Axboe
6939edf7b3ed581a61433ad620d457b4d0349115e52Jens Axboe	if (!terse && output_format != FIO_OUTPUT_JSON)
694f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe		log_info("\nDisk stats (read/write):\n");
6959f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
6969edf7b3ed581a61433ad620d457b4d0349115e52Jens Axboe	if (output_format == FIO_OUTPUT_JSON)
697952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu		json_object_add_disk_utils(parent, &disk_list);
6989edf7b3ed581a61433ad620d457b4d0349115e52Jens Axboe	else
699952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu		flist_for_each(entry, &disk_list) {
700952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu			du = flist_entry(entry, struct disk_util, list);
7019f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe
702952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu			aggregate_slaves_stats(du);
703cc372b17f2827e89da79241f1bbaca1e7c650611Shaohua Li			print_disk_util(&du->dus, &du->agg, terse);
704952b05e00103bf45576e1860cde0626bd42ed52aCastor Fu		}
7059ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe
7069ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe	fio_mutex_up(disk_util_mutex);
7079ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe}
7089ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe
7099ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboevoid setup_disk_util(void)
7109ec7779f89d4dde9fe1e23d68abaefda54b35de7Jens Axboe{
711521da527743088a9bd2ab882f8b64799d49d5848Jens Axboe	disk_util_mutex = fio_mutex_init(FIO_MUTEX_UNLOCKED);
7129f8f2064bcb196c10c9d3a2b64b951d796af22b5Jens Axboe}
713