From 5307c56954aef244c757a4d7317fa49e307df416 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Tue, 16 May 2017 14:11:56 -0700 Subject: [PATCH] scoutfs: add a stat_more ioctl We have inode fields that we want to return to userspace with very low overhead. Signed-off-by: Zach Brown --- kmod/src/ioctl.c | 20 ++++++++++++++++++++ kmod/src/ioctl.h | 21 +++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/kmod/src/ioctl.c b/kmod/src/ioctl.c index 44a24682..3e0807cc 100644 --- a/kmod/src/ioctl.c +++ b/kmod/src/ioctl.c @@ -413,6 +413,24 @@ out: return ret; } +static long scoutfs_ioc_stat_more(struct file *file, unsigned long arg) +{ + struct inode *inode = file_inode(file); + struct scoutfs_ioctl_stat_more stm; + + if (get_user(stm.valid_bytes, (__u64 __user *)arg)) + return -EFAULT; + + stm.valid_bytes = min_t(u64, stm.valid_bytes, + sizeof(struct scoutfs_ioctl_stat_more)); + stm.data_version = scoutfs_inode_get_data_version(inode); + + if (copy_to_user((void __user *)arg, &stm, stm.valid_bytes)) + return -EFAULT; + + return 0; +} + long scoutfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { @@ -426,6 +444,8 @@ long scoutfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return scoutfs_ioc_release(file, arg); case SCOUTFS_IOC_STAGE: return scoutfs_ioc_stage(file, arg); + case SCOUTFS_IOC_STAT_MORE: + return scoutfs_ioc_stat_more(file, arg); } return -ENOTTY; diff --git a/kmod/src/ioctl.h b/kmod/src/ioctl.h index 4d529550..a32a6724 100644 --- a/kmod/src/ioctl.h +++ b/kmod/src/ioctl.h @@ -130,4 +130,25 @@ struct scoutfs_ioctl_stage { #define SCOUTFS_IOC_STAGE _IOW(SCOUTFS_IOCTL_MAGIC, 6, \ struct scoutfs_ioctl_stage) +/* + * Give the user inode fields that are not otherwise visible. statx() + * isn't always available and xattrs are relatively expensive. + * + * @valid_bytes stores the number of bytes that are valid in the + * structure. The caller sets this to the size of the struct that they + * understand. The kernel then fills and copies back the min of the + * size they and the user caller understand. The user can tell if a + * field is set if all of its bytes are within the valid_bytes that the + * kernel set on return. + * + * New fields are only added to the end of the struct. + */ +struct scoutfs_ioctl_stat_more { + __u64 valid_bytes; + __u64 data_version; +} __packed; + +#define SCOUTFS_IOC_STAT_MORE _IOW(SCOUTFS_IOCTL_MAGIC, 7, \ + struct scoutfs_ioctl_stat_more) + #endif