Btrfs: add ioctl to get and reset the device stats
An ioctl interface is added to get the device statistic counters. A second ioctl is added to atomically get and reset these counters. Signed-off-by: Stefan Behrens <sbehrens@giantdisaster.de>
This commit is contained in:
parent
442a4f6308
commit
c11d2c236c
|
@ -3046,6 +3046,28 @@ static long btrfs_ioctl_scrub_progress(struct btrfs_root *root,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long btrfs_ioctl_get_dev_stats(struct btrfs_root *root,
|
||||||
|
void __user *arg, int reset_after_read)
|
||||||
|
{
|
||||||
|
struct btrfs_ioctl_get_dev_stats *sa;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (reset_after_read && !capable(CAP_SYS_ADMIN))
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
sa = memdup_user(arg, sizeof(*sa));
|
||||||
|
if (IS_ERR(sa))
|
||||||
|
return PTR_ERR(sa);
|
||||||
|
|
||||||
|
ret = btrfs_get_dev_stats(root, sa, reset_after_read);
|
||||||
|
|
||||||
|
if (copy_to_user(arg, sa, sizeof(*sa)))
|
||||||
|
ret = -EFAULT;
|
||||||
|
|
||||||
|
kfree(sa);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg)
|
static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -3434,6 +3456,10 @@ long btrfs_ioctl(struct file *file, unsigned int
|
||||||
return btrfs_ioctl_balance_ctl(root, arg);
|
return btrfs_ioctl_balance_ctl(root, arg);
|
||||||
case BTRFS_IOC_BALANCE_PROGRESS:
|
case BTRFS_IOC_BALANCE_PROGRESS:
|
||||||
return btrfs_ioctl_balance_progress(root, argp);
|
return btrfs_ioctl_balance_progress(root, argp);
|
||||||
|
case BTRFS_IOC_GET_DEV_STATS:
|
||||||
|
return btrfs_ioctl_get_dev_stats(root, argp, 0);
|
||||||
|
case BTRFS_IOC_GET_AND_RESET_DEV_STATS:
|
||||||
|
return btrfs_ioctl_get_dev_stats(root, argp, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
|
|
|
@ -285,6 +285,16 @@ enum btrfs_dev_stat_values {
|
||||||
BTRFS_DEV_STAT_VALUES_MAX
|
BTRFS_DEV_STAT_VALUES_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct btrfs_ioctl_get_dev_stats {
|
||||||
|
__u64 devid; /* in */
|
||||||
|
__u64 nr_items; /* in/out */
|
||||||
|
|
||||||
|
/* out values: */
|
||||||
|
__u64 values[BTRFS_DEV_STAT_VALUES_MAX];
|
||||||
|
|
||||||
|
__u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */
|
||||||
|
};
|
||||||
|
|
||||||
#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
|
#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
|
||||||
struct btrfs_ioctl_vol_args)
|
struct btrfs_ioctl_vol_args)
|
||||||
#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
|
#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
|
||||||
|
@ -349,5 +359,9 @@ enum btrfs_dev_stat_values {
|
||||||
struct btrfs_ioctl_ino_path_args)
|
struct btrfs_ioctl_ino_path_args)
|
||||||
#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
|
#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
|
||||||
struct btrfs_ioctl_ino_path_args)
|
struct btrfs_ioctl_ino_path_args)
|
||||||
|
#define BTRFS_IOC_GET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 52, \
|
||||||
|
struct btrfs_ioctl_get_dev_stats)
|
||||||
|
#define BTRFS_IOC_GET_AND_RESET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 53, \
|
||||||
|
struct btrfs_ioctl_get_dev_stats)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4673,3 +4673,37 @@ void btrfs_dev_stat_print_on_error(struct btrfs_device *dev)
|
||||||
btrfs_dev_stat_read(dev,
|
btrfs_dev_stat_read(dev,
|
||||||
BTRFS_DEV_STAT_GENERATION_ERRS));
|
BTRFS_DEV_STAT_GENERATION_ERRS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int btrfs_get_dev_stats(struct btrfs_root *root,
|
||||||
|
struct btrfs_ioctl_get_dev_stats *stats,
|
||||||
|
int reset_after_read)
|
||||||
|
{
|
||||||
|
struct btrfs_device *dev;
|
||||||
|
struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
mutex_lock(&fs_devices->device_list_mutex);
|
||||||
|
dev = btrfs_find_device(root, stats->devid, NULL, NULL);
|
||||||
|
mutex_unlock(&fs_devices->device_list_mutex);
|
||||||
|
|
||||||
|
if (!dev) {
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"btrfs: get dev_stats failed, device not found\n");
|
||||||
|
return -ENODEV;
|
||||||
|
} else if (reset_after_read) {
|
||||||
|
for (i = 0; i < BTRFS_DEV_STAT_VALUES_MAX; i++) {
|
||||||
|
if (stats->nr_items > i)
|
||||||
|
stats->values[i] =
|
||||||
|
btrfs_dev_stat_read_and_reset(dev, i);
|
||||||
|
else
|
||||||
|
btrfs_dev_stat_reset(dev, i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < BTRFS_DEV_STAT_VALUES_MAX; i++)
|
||||||
|
if (stats->nr_items > i)
|
||||||
|
stats->values[i] = btrfs_dev_stat_read(dev, i);
|
||||||
|
}
|
||||||
|
if (stats->nr_items > BTRFS_DEV_STAT_VALUES_MAX)
|
||||||
|
stats->nr_items = BTRFS_DEV_STAT_VALUES_MAX;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -290,6 +290,9 @@ struct btrfs_device *btrfs_find_device_for_logical(struct btrfs_root *root,
|
||||||
u64 logical, int mirror_num);
|
u64 logical, int mirror_num);
|
||||||
void btrfs_dev_stat_print_on_error(struct btrfs_device *device);
|
void btrfs_dev_stat_print_on_error(struct btrfs_device *device);
|
||||||
void btrfs_dev_stat_inc_and_print(struct btrfs_device *dev, int index);
|
void btrfs_dev_stat_inc_and_print(struct btrfs_device *dev, int index);
|
||||||
|
int btrfs_get_dev_stats(struct btrfs_root *root,
|
||||||
|
struct btrfs_ioctl_get_dev_stats *stats,
|
||||||
|
int reset_after_read);
|
||||||
|
|
||||||
static inline void btrfs_dev_stat_inc(struct btrfs_device *dev,
|
static inline void btrfs_dev_stat_inc(struct btrfs_device *dev,
|
||||||
int index)
|
int index)
|
||||||
|
|
Loading…
Reference in New Issue