+static int get_device_numbers(char *file_name, int *maj, int *min)
+{
+ struct stat st;
+ int majdev, mindev;
+ char tempname[PATH_MAX], *p;
+
+ if (!lstat(file_name, &st)) {
+ if (S_ISBLK(st.st_mode)) {
+ majdev = major(st.st_rdev);
+ mindev = minor(st.st_rdev);
+ } else if (S_ISCHR(st.st_mode)) {
+ majdev = major(st.st_rdev);
+ mindev = minor(st.st_rdev);
+ if (fio_lookup_raw(st.st_rdev, &majdev, &mindev))
+ return -1;
+ } else if (S_ISFIFO(st.st_mode))
+ return -1;
+ else {
+ majdev = major(st.st_dev);
+ mindev = minor(st.st_dev);
+ }
+ } else {
+ /*
+ * must be a file, open "." in that path
+ */
+ tempname[PATH_MAX - 1] = '\0';
+ strncpy(tempname, file_name, PATH_MAX - 1);
+ p = dirname(tempname);
+ if (stat(p, &st)) {
+ perror("disk util stat");
+ return -1;
+ }
+
+ majdev = major(st.st_dev);
+ mindev = minor(st.st_dev);
+ }
+
+ *min = mindev;
+ *maj = majdev;
+
+ return 0;
+}
+
+static int read_block_dev_entry(char *path, int *maj, int *min)
+{
+ char line[256], *p;
+ FILE *f;
+
+ f = fopen(path, "r");
+ if (!f) {
+ perror("open path");
+ return 1;
+ }
+
+ p = fgets(line, sizeof(line), f);
+ fclose(f);
+
+ if (!p)
+ return 1;
+
+ if (sscanf(p, "%u:%u", maj, min) != 2)
+ return 1;
+
+ return 0;
+}
+
+static void find_add_disk_slaves(struct thread_data *td, char *path,
+ struct disk_util *masterdu)
+{
+ DIR *dirhandle = NULL;
+ struct dirent *dirent = NULL;
+ char slavesdir[PATH_MAX], temppath[PATH_MAX], slavepath[PATH_MAX];
+ struct disk_util *slavedu = NULL;
+ int majdev, mindev;
+ ssize_t linklen;
+
+ sprintf(slavesdir, "%s/%s", path, "slaves");
+ dirhandle = opendir(slavesdir);
+ if (!dirhandle)
+ return;
+
+ while ((dirent = readdir(dirhandle)) != NULL) {
+ if (!strcmp(dirent->d_name, ".") ||
+ !strcmp(dirent->d_name, ".."))
+ continue;
+
+ sprintf(temppath, "%s/%s", slavesdir, dirent->d_name);
+ /* Can we always assume that the slaves device entries
+ * are links to the real directories for the slave
+ * devices?
+ */
+ linklen = readlink(temppath, slavepath, PATH_MAX - 1);
+ if (linklen < 0) {
+ perror("readlink() for slave device.");
+ closedir(dirhandle);
+ return;
+ }
+ slavepath[linklen] = '\0';
+
+ sprintf(temppath, "%s/%s/dev", slavesdir, slavepath);
+ if (access(temppath, F_OK) != 0)
+ sprintf(temppath, "%s/%s/device/dev", slavesdir, slavepath);
+ if (read_block_dev_entry(temppath, &majdev, &mindev)) {
+ perror("Error getting slave device numbers");
+ closedir(dirhandle);
+ return;
+ }
+
+ /*
+ * See if this maj,min already exists
+ */
+ slavedu = disk_util_exists(majdev, mindev);
+ if (slavedu)
+ continue;
+
+ sprintf(temppath, "%s/%s", slavesdir, slavepath);
+ __init_per_file_disk_util(td, majdev, mindev, temppath);
+ slavedu = disk_util_exists(majdev, mindev);
+
+ /* Should probably use an assert here. slavedu should
+ * always be present at this point. */
+ if (slavedu) {
+ slavedu->users++;
+ flist_add_tail(&slavedu->slavelist, &masterdu->slaves);
+ }
+ }
+
+ closedir(dirhandle);
+}
+
+static struct disk_util *disk_util_add(struct thread_data *td, int majdev,
+ int mindev, char *path)