Fix disk utilization and ioscheduler switch on raw devices
authorJens Axboe <jens.axboe@oracle.com>
Mon, 2 Apr 2007 12:46:07 +0000 (14:46 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Mon, 2 Apr 2007 12:46:07 +0000 (14:46 +0200)
Add a method for mapping a raw device to the real block device,
so our sysfs lookup stuff works as expected.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
fio.h
os-linux.h
os.h
stat.c

diff --git a/fio.h b/fio.h
index 07b40ff47780a17e6ed3b0248e2e3c708e91b547..a86a58281c62981bc3625d70739f776c20acc055 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -648,7 +648,7 @@ struct disk_util {
 
        char *name;
        char path[256];
 
        char *name;
        char path[256];
-       dev_t dev;
+       int major, minor;
 
        struct disk_util_stat dus;
        struct disk_util_stat last_dus;
 
        struct disk_util_stat dus;
        struct disk_util_stat last_dus;
index 1ed3d3b650b206921c0c22a5b1e3c656820d228e..561b273db94e3dcd590e7e6dbfa24e39c497ba00 100644 (file)
@@ -7,6 +7,8 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <linux/unistd.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <linux/unistd.h>
+#include <linux/raw.h>
+#include <linux/major.h>
 
 #define FIO_HAVE_LIBAIO
 #define FIO_HAVE_POSIXAIO
 
 #define FIO_HAVE_LIBAIO
 #define FIO_HAVE_POSIXAIO
@@ -19,6 +21,7 @@
 #define FIO_HAVE_IOSCHED_SWITCH
 #define FIO_HAVE_ODIRECT
 #define FIO_HAVE_HUGETLB
 #define FIO_HAVE_IOSCHED_SWITCH
 #define FIO_HAVE_ODIRECT
 #define FIO_HAVE_HUGETLB
+#define FIO_HAVE_RAWBIND
 
 #define OS_MAP_ANON            (MAP_ANONYMOUS)
 
 
 #define OS_MAP_ANON            (MAP_ANONYMOUS)
 
@@ -168,4 +171,33 @@ static inline double os_random_double(os_random_state_t *rs)
        return val;
 }
 
        return val;
 }
 
+static inline void fio_lookup_raw(dev_t dev, int *majdev, int *mindev)
+{
+       struct raw_config_request rq;
+       int fd;
+
+       if (major(dev) != RAW_MAJOR)
+               return;
+
+       /*
+        * we should be able to find /dev/rawctl or /dev/raw/rawctl
+        */
+       fd = open("/dev/rawctl", O_RDONLY);
+       if (fd < 0) {
+               fd = open("/dev/raw/rawctl", O_RDONLY);
+               if (fd < 0)
+                       return;
+       }
+
+       rq.raw_minor = minor(dev);
+       if (ioctl(fd, RAW_GETBIND, &rq) < 0) {
+               close(fd);
+               return;
+       }
+
+       close(fd);
+       *majdev = rq.block_major;
+       *mindev = rq.block_minor;
+}
+
 #endif
 #endif
diff --git a/os.h b/os.h
index 823843a3043c680f55b1452c5a9416768f1dc9fc..104f4a81a7f06a147a3c07732707aaa30258ee40 100644 (file)
--- a/os.h
+++ b/os.h
@@ -56,4 +56,8 @@
 #endif
 #endif
 
 #endif
 #endif
 
+#ifndef FIO_HAVE_RAWBIND
+#define fio_lookup_raw(dev, majdev, mindev)
+#endif
+
 #endif
 #endif
diff --git a/stat.c b/stat.c
index e974da77ff7ec557728daef9ea5c9e6243018af6..29a5f912d26d597ded5142842e34e1ad39405599 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -11,7 +11,7 @@
 
 static struct itimerval itimer;
 static struct list_head disk_list = LIST_HEAD_INIT(disk_list);
 
 static struct itimerval itimer;
 static struct list_head disk_list = LIST_HEAD_INIT(disk_list);
-static dev_t last_dev;
+static int last_majdev, last_mindev;
 
 /*
  * Cheesy number->string conversion, complete with carry rounding error.
 
 /*
  * Cheesy number->string conversion, complete with carry rounding error.
@@ -121,7 +121,7 @@ void update_io_ticks(void)
        }
 }
 
        }
 }
 
-static int disk_util_exists(dev_t dev)
+static int disk_util_exists(int major, int minor)
 {
        struct list_head *entry;
        struct disk_util *du;
 {
        struct list_head *entry;
        struct disk_util *du;
@@ -129,14 +129,14 @@ static int disk_util_exists(dev_t dev)
        list_for_each(entry, &disk_list) {
                du = list_entry(entry, struct disk_util, list);
 
        list_for_each(entry, &disk_list) {
                du = list_entry(entry, struct disk_util, list);
 
-               if (du->dev == dev)
+               if (major == du->major && minor == du->minor)
                        return 1;
        }
 
        return 0;
 }
 
                        return 1;
        }
 
        return 0;
 }
 
-static void disk_util_add(dev_t dev, char *path)
+static void disk_util_add(int majdev, int mindev, char *path)
 {
        struct disk_util *du, *__du;
        struct list_head *entry;
 {
        struct disk_util *du, *__du;
        struct list_head *entry;
@@ -146,7 +146,8 @@ static void disk_util_add(dev_t dev, char *path)
        INIT_LIST_HEAD(&du->list);
        sprintf(du->path, "%s/stat", path);
        du->name = strdup(basename(path));
        INIT_LIST_HEAD(&du->list);
        sprintf(du->path, "%s/stat", path);
        du->name = strdup(basename(path));
-       du->dev = dev;
+       du->major = majdev;
+       du->minor = mindev;
 
        list_for_each(entry, &disk_list) {
                __du = list_entry(entry, struct disk_util, list);
 
        list_for_each(entry, &disk_list) {
                __du = list_entry(entry, struct disk_util, list);
@@ -164,9 +165,9 @@ static void disk_util_add(dev_t dev, char *path)
        list_add_tail(&du->list, &disk_list);
 }
 
        list_add_tail(&du->list, &disk_list);
 }
 
-static int check_dev_match(dev_t dev, char *path)
+static int check_dev_match(int majdev, int mindev, char *path)
 {
 {
-       unsigned int major, minor;
+       int major, minor;
        char line[256], *p;
        FILE *f;
 
        char line[256], *p;
        FILE *f;
 
@@ -187,7 +188,7 @@ static int check_dev_match(dev_t dev, char *path)
                return 1;
        }
 
                return 1;
        }
 
-       if (((major << 8) | minor) == dev) {
+       if (majdev == major && mindev == minor) {
                fclose(f);
                return 0;
        }
                fclose(f);
                return 0;
        }
@@ -196,7 +197,7 @@ static int check_dev_match(dev_t dev, char *path)
        return 1;
 }
 
        return 1;
 }
 
-static int find_block_dir(dev_t dev, char *path)
+static int find_block_dir(int majdev, int mindev, char *path)
 {
        struct dirent *dir;
        struct stat st;
 {
        struct dirent *dir;
        struct stat st;
@@ -216,7 +217,7 @@ static int find_block_dir(dev_t dev, char *path)
                sprintf(full_path, "%s/%s", path, dir->d_name);
 
                if (!strcmp(dir->d_name, "dev")) {
                sprintf(full_path, "%s/%s", path, dir->d_name);
 
                if (!strcmp(dir->d_name, "dev")) {
-                       if (!check_dev_match(dev, full_path)) {
+                       if (!check_dev_match(majdev, mindev, full_path)) {
                                found = 1;
                                break;
                        }
                                found = 1;
                                break;
                        }
@@ -230,7 +231,7 @@ static int find_block_dir(dev_t dev, char *path)
                if (!S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))
                        continue;
 
                if (!S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))
                        continue;
 
-               found = find_block_dir(dev, full_path);
+               found = find_block_dir(majdev, mindev, full_path);
                if (found) {
                        strcpy(path, full_path);
                        break;
                if (found) {
                        strcpy(path, full_path);
                        break;
@@ -245,14 +246,21 @@ static void __init_disk_util(struct thread_data *td, struct fio_file *f)
 {
        struct stat st;
        char foo[PATH_MAX], tmp[PATH_MAX];
 {
        struct stat st;
        char foo[PATH_MAX], tmp[PATH_MAX];
-       dev_t dev;
+       int mindev, majdev;
        char *p;
 
        if (!stat(f->file_name, &st)) {
        char *p;
 
        if (!stat(f->file_name, &st)) {
-               if (S_ISBLK(st.st_mode))
-                       dev = st.st_rdev;
-               else
-                       dev = st.st_dev;
+               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);
+                       fio_lookup_raw(st.st_rdev, &majdev, &mindev);
+               } else {
+                       majdev = major(st.st_dev);
+                       mindev = minor(st.st_dev);
+               }
        } else {
                /*
                 * must be a file, open "." in that path
        } else {
                /*
                 * must be a file, open "." in that path
@@ -264,10 +272,11 @@ static void __init_disk_util(struct thread_data *td, struct fio_file *f)
                        return;
                }
 
                        return;
                }
 
-               dev = st.st_dev;
+               majdev = major(st.st_dev);
+               mindev = minor(st.st_dev);
        }
 
        }
 
-       if (disk_util_exists(dev))
+       if (disk_util_exists(majdev, mindev))
                return;
 
        /*
                return;
 
        /*
@@ -276,13 +285,14 @@ static void __init_disk_util(struct thread_data *td, struct fio_file *f)
         * cache the last lookup and compare with that before going through
         * everything again.
         */
         * cache the last lookup and compare with that before going through
         * everything again.
         */
-       if (dev == last_dev)
+       if (mindev == last_mindev && majdev == last_majdev)
                return;
 
                return;
 
-       last_dev = dev;
+       last_mindev = mindev;
+       last_majdev = majdev;
                
        sprintf(foo, "/sys/block");
                
        sprintf(foo, "/sys/block");
-       if (!find_block_dir(dev, foo))
+       if (!find_block_dir(majdev, mindev, foo))
                return;
 
        /*
                return;
 
        /*
@@ -305,7 +315,7 @@ static void __init_disk_util(struct thread_data *td, struct fio_file *f)
        if (td->o.ioscheduler && !td->sysfs_root)
                td->sysfs_root = strdup(foo);
 
        if (td->o.ioscheduler && !td->sysfs_root)
                td->sysfs_root = strdup(foo);
 
-       disk_util_add(dev, foo);
+       disk_util_add(majdev, mindev, foo);
 }
 
 void init_disk_util(struct thread_data *td)
 }
 
 void init_disk_util(struct thread_data *td)