#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_IOSCHED_SWITCH
#define FIO_HAVE_ODIRECT
#define FIO_HAVE_HUGETLB
+#define FIO_HAVE_RAWBIND
#define OS_MAP_ANON (MAP_ANONYMOUS)
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
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.
}
}
-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;
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;
}
-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;
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_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;
return 1;
}
- if (((major << 8) | minor) == dev) {
+ if (majdev == major && mindev == minor) {
fclose(f);
return 0;
}
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;
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;
}
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;
{
struct stat st;
char foo[PATH_MAX], tmp[PATH_MAX];
- dev_t dev;
+ int mindev, majdev;
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
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;
/*
* 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;
- last_dev = dev;
+ last_mindev = mindev;
+ last_majdev = majdev;
sprintf(foo, "/sys/block");
- if (!find_block_dir(dev, foo))
+ if (!find_block_dir(majdev, mindev, foo))
return;
/*
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)