#include <stdio.h>
#include <string.h>
-#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/sysmacros.h>
#include <dirent.h>
#include <libgen.h>
-#include <math.h>
-#include <assert.h>
+#ifdef CONFIG_VALGRIND_DEV
+#include <valgrind/drd.h>
+#else
+#define DRD_IGNORE_VAR(x) do { } while (0)
+#endif
#include "fio.h"
#include "smalloc.h"
#include "diskutil.h"
+#include "helper_thread.h"
static int last_majdev, last_mindev;
static struct disk_util *last_du;
-static struct fio_mutex *disk_util_mutex;
-
-FLIST_HEAD(disk_list);
+static struct fio_sem *disk_util_sem;
static struct disk_util *__init_per_file_disk_util(struct thread_data *td,
int majdev, int mindev, char *path);
slave->users--;
}
- fio_mutex_remove(du->lock);
+ fio_sem_remove(du->lock);
+ free(du->sysfs_root);
sfree(du);
}
static void update_io_tick_disk(struct disk_util *du)
{
struct disk_util_stat __dus, *dus, *ldus;
- struct timeval t;
+ struct timespec t;
if (!du->users)
return;
dprint(FD_DISKUTIL, "update io ticks\n");
- fio_mutex_down(disk_util_mutex);
+ fio_sem_down(disk_util_sem);
- if (!helper_exit) {
+ if (!helper_should_exit()) {
flist_for_each(entry, &disk_list) {
du = flist_entry(entry, struct disk_util, list);
update_io_tick_disk(du);
} else
ret = 1;
- fio_mutex_up(disk_util_mutex);
+ fio_sem_up(disk_util_sem);
return ret;
}
struct flist_head *entry;
struct disk_util *du;
- fio_mutex_down(disk_util_mutex);
+ fio_sem_down(disk_util_sem);
flist_for_each(entry, &disk_list) {
du = flist_entry(entry, struct disk_util, list);
if (major == du->major && minor == du->minor) {
- fio_mutex_up(disk_util_mutex);
+ fio_sem_up(disk_util_sem);
return du;
}
}
- fio_mutex_up(disk_util_mutex);
+ fio_sem_up(disk_util_sem);
return NULL;
}
/*
* 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)) {
!strcmp(dirent->d_name, ".."))
continue;
- sprintf(temppath, "%s%s%s", slavesdir, FIO_OS_PATH_SEPARATOR, dirent->d_name);
+ 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) {
+ 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.");
+ perror("Error getting slave device numbers");
closedir(dirhandle);
return;
}
if (slavedu)
continue;
- sprintf(temppath, "%s%s%s", slavesdir, FIO_OS_PATH_SEPARATOR, slavepath);
+ sprintf(temppath, "%s/%s", slavesdir, slavepath);
__init_per_file_disk_util(td, majdev, mindev, temppath);
slavedu = disk_util_exists(majdev, mindev);
dprint(FD_DISKUTIL, "add maj/min %d/%d: %s\n", majdev, mindev, path);
du = smalloc(sizeof(*du));
- if (!du) {
- log_err("fio: smalloc() pool exhausted\n");
+ if (!du)
return NULL;
- }
+ DRD_IGNORE_VAR(du->users);
memset(du, 0, sizeof(*du));
INIT_FLIST_HEAD(&du->list);
l = snprintf(du->path, sizeof(du->path), "%s/stat", path);
return NULL;
}
strncpy((char *) du->dus.name, basename(path), FIO_DU_NAME_SZ - 1);
- du->sysfs_root = path;
+ du->sysfs_root = strdup(path);
du->major = majdev;
du->minor = mindev;
INIT_FLIST_HEAD(&du->slavelist);
INIT_FLIST_HEAD(&du->slaves);
- du->lock = fio_mutex_init(FIO_MUTEX_UNLOCKED);
+ du->lock = fio_sem_init(FIO_SEM_UNLOCKED);
du->users = 0;
- fio_mutex_down(disk_util_mutex);
+ fio_sem_down(disk_util_sem);
flist_for_each(entry, &disk_list) {
__du = flist_entry(entry, struct disk_util, list);
if (!strcmp((char *) du->dus.name, (char *) __du->dus.name)) {
disk_util_free(du);
- fio_mutex_up(disk_util_mutex);
+ fio_sem_up(disk_util_sem);
return __du;
}
}
get_io_ticks(du, &du->last_dus);
flist_add_tail(&du->list, &disk_list);
- fio_mutex_up(disk_util_mutex);
+ fio_sem_up(disk_util_sem);
find_add_disk_slaves(td, path, du);
return du;
return 0;
while ((dir = readdir(D)) != NULL) {
- char full_path[256];
+ char full_path[257];
if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
continue;
- sprintf(full_path, "%s%s%s", path, FIO_OS_PATH_SEPARATOR, dir->d_name);
+ sprintf(full_path, "%s/%s", path, dir->d_name);
if (!strcmp(dir->d_name, "dev")) {
if (!check_dev_match(majdev, mindev, full_path)) {
log_err("unknown sysfs layout\n");
return NULL;
}
+ tmp[PATH_MAX - 1] = '\0';
strncpy(tmp, p, PATH_MAX - 1);
sprintf(path, "%s", tmp);
}
- if (td->o.ioscheduler && !td->sysfs_root)
- td->sysfs_root = strdup(path);
-
return disk_util_add(td, majdev, mindev, path);
}
mindev);
du = disk_util_exists(majdev, mindev);
- if (du) {
- if (td->o.ioscheduler && !td->sysfs_root)
- td->sysfs_root = strdup(du->sysfs_root);
-
+ if (du)
return du;
- }
/*
* for an fs without a device, we will repeatedly stat through
unsigned int i;
if (!td->o.do_disk_util ||
- (td->io_ops->flags & (FIO_DISKLESSIO | FIO_NODISKUTIL)))
+ td_ioengine_flagged(td, FIO_DISKLESSIO | FIO_NODISKUTIL))
return;
for_each_file(td, f, i)
void disk_util_prune_entries(void)
{
- fio_mutex_down(disk_util_mutex);
+ fio_sem_down(disk_util_sem);
while (!flist_empty(&disk_list)) {
struct disk_util *du;
}
last_majdev = last_mindev = -1;
- fio_mutex_up(disk_util_mutex);
- fio_mutex_remove(disk_util_mutex);
+ fio_sem_up(disk_util_sem);
+ fio_sem_remove(disk_util_sem);
}
void print_disk_util(struct disk_util_stat *dus, struct disk_util_agg *agg,
{
struct flist_head *entry;
struct disk_util *du;
+ bool do_json;
- if (!disk_util_mutex)
+ if (!disk_util_sem)
return;
- fio_mutex_down(disk_util_mutex);
+ fio_sem_down(disk_util_sem);
if (flist_empty(&disk_list)) {
- fio_mutex_up(disk_util_mutex);
+ fio_sem_up(disk_util_sem);
return;
}
- if (output_format & FIO_OUTPUT_JSON)
- assert(parent);
+ if ((output_format & FIO_OUTPUT_JSON) && parent)
+ do_json = true;
+ else
+ do_json = false;
- if (!terse && !(output_format & FIO_OUTPUT_JSON))
+ if (!terse && !do_json)
log_buf(out, "\nDisk stats (read/write):\n");
- if (output_format & FIO_OUTPUT_JSON)
+ if (do_json)
json_object_add_disk_utils(parent, &disk_list);
- if (output_format & ~(FIO_OUTPUT_JSON)) {
+ else if (output_format & ~(FIO_OUTPUT_JSON | FIO_OUTPUT_JSON_PLUS)) {
flist_for_each(entry, &disk_list) {
du = flist_entry(entry, struct disk_util, list);
}
}
- fio_mutex_up(disk_util_mutex);
+ fio_sem_up(disk_util_sem);
}
void setup_disk_util(void)
{
- disk_util_mutex = fio_mutex_init(FIO_MUTEX_UNLOCKED);
+ disk_util_sem = fio_sem_init(FIO_SEM_UNLOCKED);
}