diff --git a/kmod/src/dir.c b/kmod/src/dir.c index 00734909..92b9eb29 100644 --- a/kmod/src/dir.c +++ b/kmod/src/dir.c @@ -1242,10 +1242,10 @@ const struct inode_operations scoutfs_symlink_iops = { .put_link = scoutfs_put_link, .getattr = scoutfs_getattr, .setattr = scoutfs_setattr, - .setxattr = scoutfs_setxattr, - .getxattr = scoutfs_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = scoutfs_listxattr, - .removexattr = scoutfs_removexattr, + .removexattr = generic_removexattr, }; /* @@ -1978,10 +1978,10 @@ const struct inode_operations_wrapper scoutfs_dir_iops = { .rename = scoutfs_rename, .getattr = scoutfs_getattr, .setattr = scoutfs_setattr, - .setxattr = scoutfs_setxattr, - .getxattr = scoutfs_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = scoutfs_listxattr, - .removexattr = scoutfs_removexattr, + .removexattr = generic_removexattr, .symlink = scoutfs_symlink, .permission = scoutfs_permission, }, diff --git a/kmod/src/inode.c b/kmod/src/inode.c index 62ef3093..9b8beede 100644 --- a/kmod/src/inode.c +++ b/kmod/src/inode.c @@ -136,20 +136,20 @@ void scoutfs_destroy_inode(struct inode *inode) static const struct inode_operations scoutfs_file_iops = { .getattr = scoutfs_getattr, .setattr = scoutfs_setattr, - .setxattr = scoutfs_setxattr, - .getxattr = scoutfs_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = scoutfs_listxattr, - .removexattr = scoutfs_removexattr, + .removexattr = generic_removexattr, .fiemap = scoutfs_data_fiemap, }; static const struct inode_operations scoutfs_special_iops = { .getattr = scoutfs_getattr, .setattr = scoutfs_setattr, - .setxattr = scoutfs_setxattr, - .getxattr = scoutfs_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = scoutfs_listxattr, - .removexattr = scoutfs_removexattr, + .removexattr = generic_removexattr, }; /* diff --git a/kmod/src/super.c b/kmod/src/super.c index d38fcb65..f786d23f 100644 --- a/kmod/src/super.c +++ b/kmod/src/super.c @@ -47,6 +47,7 @@ #include "omap.h" #include "volopt.h" #include "fence.h" +#include "xattr.h" #include "scoutfs_trace.h" static struct dentry *scoutfs_debugfs_root; @@ -483,6 +484,7 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_op = &scoutfs_super_ops; sb->s_export_op = &scoutfs_export_ops; + sb->s_xattr = scoutfs_xattr_handlers; sb->s_flags |= MS_I_VERSION; /* btree blocks use long lived bh->b_data refs */ diff --git a/kmod/src/xattr.c b/kmod/src/xattr.c index a87b69c2..f1d8834d 100644 --- a/kmod/src/xattr.c +++ b/kmod/src/xattr.c @@ -79,16 +79,6 @@ static void init_xattr_key(struct scoutfs_key *key, u64 ino, u32 name_hash, #define SCOUTFS_XATTR_PREFIX "scoutfs." #define SCOUTFS_XATTR_PREFIX_LEN (sizeof(SCOUTFS_XATTR_PREFIX) - 1) -static int unknown_prefix(const char *name) -{ - return strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) && - strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) && - strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) && - strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)&& - strncmp(name, SCOUTFS_XATTR_PREFIX, SCOUTFS_XATTR_PREFIX_LEN); -} - - #define HIDE_TAG "hide." #define SRCH_TAG "srch." #define TOTL_TAG "totl." @@ -455,8 +445,7 @@ out: * Copy the value for the given xattr name into the caller's buffer, if it * fits. Return the bytes copied or -ERANGE if it doesn't fit. */ -ssize_t scoutfs_getxattr(struct dentry *dentry, const char *name, void *buffer, - size_t size) +static int scoutfs_xattr_get(struct dentry *dentry, const char *name, void *buffer, size_t size) { struct inode *inode = dentry->d_inode; struct scoutfs_inode_info *si = SCOUTFS_I(inode); @@ -468,9 +457,6 @@ ssize_t scoutfs_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t name_len; int ret; - if (unknown_prefix(name)) - return -EOPNOTSUPP; - name_len = strlen(name); if (name_len > SCOUTFS_XATTR_MAX_NAME_LEN) return -ENODATA; @@ -661,9 +647,6 @@ static int scoutfs_xattr_set(struct dentry *dentry, const char *name, (flags & ~(XATTR_CREATE | XATTR_REPLACE))) return -EINVAL; - if (unknown_prefix(name)) - return -EOPNOTSUPP; - if (scoutfs_xattr_parse_tags(name, name_len, &tgs) != 0) return -EINVAL; @@ -831,19 +814,67 @@ out: return ret; } -int scoutfs_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) +/* + * Future kernels have this amazing hack to rewind the name to get the + * skipped prefix. We're back in the stone ages without the handler + * arg, so we Just Know that this is possible. This will become a + * compat hook to either call the kernel's xattr_full_name(handler), or + * our hack to use the flags as the prefix length. + */ +static const char *full_name_hack(void *handler, const char *name, int len) { - if (size == 0) - value = ""; /* set empty value */ + return name - len; +} +static int scoutfs_xattr_get_handler(struct dentry *dentry, const char *name, + void *value, size_t size, int handler_flags) +{ + name = full_name_hack(NULL, name, handler_flags); + return scoutfs_xattr_get(dentry, name, value, size); +} + +static int scoutfs_xattr_set_handler(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags, int handler_flags) +{ + name = full_name_hack(NULL, name, handler_flags); return scoutfs_xattr_set(dentry, name, value, size, flags); } -int scoutfs_removexattr(struct dentry *dentry, const char *name) -{ - return scoutfs_xattr_set(dentry, name, NULL, 0, XATTR_REPLACE); -} +static const struct xattr_handler scoutfs_xattr_user_handler = { + .prefix = XATTR_USER_PREFIX, + .flags = XATTR_USER_PREFIX_LEN, + .get = scoutfs_xattr_get_handler, + .set = scoutfs_xattr_set_handler, +}; + +static const struct xattr_handler scoutfs_xattr_scoutfs_handler = { + .prefix = SCOUTFS_XATTR_PREFIX, + .flags = SCOUTFS_XATTR_PREFIX_LEN, + .get = scoutfs_xattr_get_handler, + .set = scoutfs_xattr_set_handler, +}; + +static const struct xattr_handler scoutfs_xattr_trusted_handler = { + .prefix = XATTR_TRUSTED_PREFIX, + .flags = XATTR_TRUSTED_PREFIX_LEN, + .get = scoutfs_xattr_get_handler, + .set = scoutfs_xattr_set_handler, +}; + +static const struct xattr_handler scoutfs_xattr_security_handler = { + .prefix = XATTR_SECURITY_PREFIX, + .flags = XATTR_SECURITY_PREFIX_LEN, + .get = scoutfs_xattr_get_handler, + .set = scoutfs_xattr_set_handler, +}; + +const struct xattr_handler *scoutfs_xattr_handlers[] = { + &scoutfs_xattr_user_handler, + &scoutfs_xattr_scoutfs_handler, + &scoutfs_xattr_trusted_handler, + &scoutfs_xattr_security_handler, + NULL +}; ssize_t scoutfs_list_xattrs(struct inode *inode, char *buffer, size_t size, __u32 *hash_pos, __u64 *id_pos, diff --git a/kmod/src/xattr.h b/kmod/src/xattr.h index cbc6c599..36025663 100644 --- a/kmod/src/xattr.h +++ b/kmod/src/xattr.h @@ -1,16 +1,12 @@ #ifndef _SCOUTFS_XATTR_H_ #define _SCOUTFS_XATTR_H_ -ssize_t scoutfs_getxattr(struct dentry *dentry, const char *name, void *buffer, - size_t size); -int scoutfs_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags); -int scoutfs_removexattr(struct dentry *dentry, const char *name); +extern const struct xattr_handler *scoutfs_xattr_handlers[]; + ssize_t scoutfs_listxattr(struct dentry *dentry, char *buffer, size_t size); ssize_t scoutfs_list_xattrs(struct inode *inode, char *buffer, size_t size, __u32 *hash_pos, __u64 *id_pos, bool e_range, bool show_hidden); - int scoutfs_xattr_drop(struct super_block *sb, u64 ino, struct scoutfs_lock *lock);