btrfs: Use xattr handler infrastructure
Use the VFS xattr handler infrastructure and get rid of similar code in the filesystem. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
98e9cb5711
commit
9172abbcd3
|
@ -9994,7 +9994,7 @@ static const struct inode_operations btrfs_dir_inode_operations = {
|
||||||
.setattr = btrfs_setattr,
|
.setattr = btrfs_setattr,
|
||||||
.mknod = btrfs_mknod,
|
.mknod = btrfs_mknod,
|
||||||
.setxattr = btrfs_setxattr,
|
.setxattr = btrfs_setxattr,
|
||||||
.getxattr = btrfs_getxattr,
|
.getxattr = generic_getxattr,
|
||||||
.listxattr = btrfs_listxattr,
|
.listxattr = btrfs_listxattr,
|
||||||
.removexattr = btrfs_removexattr,
|
.removexattr = btrfs_removexattr,
|
||||||
.permission = btrfs_permission,
|
.permission = btrfs_permission,
|
||||||
|
@ -10071,7 +10071,7 @@ static const struct inode_operations btrfs_file_inode_operations = {
|
||||||
.getattr = btrfs_getattr,
|
.getattr = btrfs_getattr,
|
||||||
.setattr = btrfs_setattr,
|
.setattr = btrfs_setattr,
|
||||||
.setxattr = btrfs_setxattr,
|
.setxattr = btrfs_setxattr,
|
||||||
.getxattr = btrfs_getxattr,
|
.getxattr = generic_getxattr,
|
||||||
.listxattr = btrfs_listxattr,
|
.listxattr = btrfs_listxattr,
|
||||||
.removexattr = btrfs_removexattr,
|
.removexattr = btrfs_removexattr,
|
||||||
.permission = btrfs_permission,
|
.permission = btrfs_permission,
|
||||||
|
@ -10085,7 +10085,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
|
||||||
.setattr = btrfs_setattr,
|
.setattr = btrfs_setattr,
|
||||||
.permission = btrfs_permission,
|
.permission = btrfs_permission,
|
||||||
.setxattr = btrfs_setxattr,
|
.setxattr = btrfs_setxattr,
|
||||||
.getxattr = btrfs_getxattr,
|
.getxattr = generic_getxattr,
|
||||||
.listxattr = btrfs_listxattr,
|
.listxattr = btrfs_listxattr,
|
||||||
.removexattr = btrfs_removexattr,
|
.removexattr = btrfs_removexattr,
|
||||||
.get_acl = btrfs_get_acl,
|
.get_acl = btrfs_get_acl,
|
||||||
|
@ -10100,7 +10100,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
|
||||||
.setattr = btrfs_setattr,
|
.setattr = btrfs_setattr,
|
||||||
.permission = btrfs_permission,
|
.permission = btrfs_permission,
|
||||||
.setxattr = btrfs_setxattr,
|
.setxattr = btrfs_setxattr,
|
||||||
.getxattr = btrfs_getxattr,
|
.getxattr = generic_getxattr,
|
||||||
.listxattr = btrfs_listxattr,
|
.listxattr = btrfs_listxattr,
|
||||||
.removexattr = btrfs_removexattr,
|
.removexattr = btrfs_removexattr,
|
||||||
.update_time = btrfs_update_time,
|
.update_time = btrfs_update_time,
|
||||||
|
|
168
fs/btrfs/xattr.c
168
fs/btrfs/xattr.c
|
@ -351,137 +351,89 @@ err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static int btrfs_xattr_handler_get(const struct xattr_handler *handler,
|
||||||
* List of handlers for synthetic system.* attributes. All real ondisk
|
struct dentry *dentry, const char *name,
|
||||||
* attributes are handled directly.
|
void *buffer, size_t size)
|
||||||
*/
|
{
|
||||||
|
struct inode *inode = d_inode(dentry);
|
||||||
|
|
||||||
|
name = xattr_full_name(handler, name);
|
||||||
|
return __btrfs_getxattr(inode, name, buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int btrfs_xattr_handler_set(const struct xattr_handler *handler,
|
||||||
|
struct dentry *dentry, const char *name,
|
||||||
|
const void *buffer, size_t size,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
struct inode *inode = d_inode(dentry);
|
||||||
|
|
||||||
|
name = xattr_full_name(handler, name);
|
||||||
|
return __btrfs_setxattr(NULL, inode, name, buffer, size, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
|
||||||
|
struct dentry *dentry,
|
||||||
|
const char *name, const void *value,
|
||||||
|
size_t size, int flags)
|
||||||
|
{
|
||||||
|
name = xattr_full_name(handler, name);
|
||||||
|
return btrfs_set_prop(d_inode(dentry), name, value, size, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct xattr_handler btrfs_security_xattr_handler = {
|
||||||
|
.prefix = XATTR_SECURITY_PREFIX,
|
||||||
|
.get = btrfs_xattr_handler_get,
|
||||||
|
.set = btrfs_xattr_handler_set,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct xattr_handler btrfs_trusted_xattr_handler = {
|
||||||
|
.prefix = XATTR_TRUSTED_PREFIX,
|
||||||
|
.get = btrfs_xattr_handler_get,
|
||||||
|
.set = btrfs_xattr_handler_set,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct xattr_handler btrfs_user_xattr_handler = {
|
||||||
|
.prefix = XATTR_USER_PREFIX,
|
||||||
|
.get = btrfs_xattr_handler_get,
|
||||||
|
.set = btrfs_xattr_handler_set,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct xattr_handler btrfs_btrfs_xattr_handler = {
|
||||||
|
.prefix = XATTR_BTRFS_PREFIX,
|
||||||
|
.get = btrfs_xattr_handler_get,
|
||||||
|
.set = btrfs_xattr_handler_set_prop,
|
||||||
|
};
|
||||||
|
|
||||||
const struct xattr_handler *btrfs_xattr_handlers[] = {
|
const struct xattr_handler *btrfs_xattr_handlers[] = {
|
||||||
|
&btrfs_security_xattr_handler,
|
||||||
#ifdef CONFIG_BTRFS_FS_POSIX_ACL
|
#ifdef CONFIG_BTRFS_FS_POSIX_ACL
|
||||||
&posix_acl_access_xattr_handler,
|
&posix_acl_access_xattr_handler,
|
||||||
&posix_acl_default_xattr_handler,
|
&posix_acl_default_xattr_handler,
|
||||||
#endif
|
#endif
|
||||||
|
&btrfs_trusted_xattr_handler,
|
||||||
|
&btrfs_user_xattr_handler,
|
||||||
|
&btrfs_btrfs_xattr_handler,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the attribute is in a supported namespace.
|
|
||||||
*
|
|
||||||
* This is applied after the check for the synthetic attributes in the system
|
|
||||||
* namespace.
|
|
||||||
*/
|
|
||||||
static int btrfs_is_valid_xattr(const char *name)
|
|
||||||
{
|
|
||||||
int len = strlen(name);
|
|
||||||
int prefixlen = 0;
|
|
||||||
|
|
||||||
if (!strncmp(name, XATTR_SECURITY_PREFIX,
|
|
||||||
XATTR_SECURITY_PREFIX_LEN))
|
|
||||||
prefixlen = XATTR_SECURITY_PREFIX_LEN;
|
|
||||||
else if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
|
||||||
prefixlen = XATTR_SYSTEM_PREFIX_LEN;
|
|
||||||
else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
|
|
||||||
prefixlen = XATTR_TRUSTED_PREFIX_LEN;
|
|
||||||
else if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
|
|
||||||
prefixlen = XATTR_USER_PREFIX_LEN;
|
|
||||||
else if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
|
|
||||||
prefixlen = XATTR_BTRFS_PREFIX_LEN;
|
|
||||||
else
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The name cannot consist of just prefix
|
|
||||||
*/
|
|
||||||
if (len <= prefixlen)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
|
|
||||||
void *buffer, size_t size)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If this is a request for a synthetic attribute in the system.*
|
|
||||||
* namespace use the generic infrastructure to resolve a handler
|
|
||||||
* for it via sb->s_xattr.
|
|
||||||
*/
|
|
||||||
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
|
||||||
return generic_getxattr(dentry, name, buffer, size);
|
|
||||||
|
|
||||||
ret = btrfs_is_valid_xattr(name);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
return __btrfs_getxattr(d_inode(dentry), name, buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
|
int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
|
||||||
size_t size, int flags)
|
size_t size, int flags)
|
||||||
{
|
{
|
||||||
struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root;
|
struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root;
|
||||||
int ret;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The permission on security.* and system.* is not checked
|
|
||||||
* in permission().
|
|
||||||
*/
|
|
||||||
if (btrfs_root_readonly(root))
|
if (btrfs_root_readonly(root))
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
|
return generic_setxattr(dentry, name, value, size, flags);
|
||||||
/*
|
|
||||||
* If this is a request for a synthetic attribute in the system.*
|
|
||||||
* namespace use the generic infrastructure to resolve a handler
|
|
||||||
* for it via sb->s_xattr.
|
|
||||||
*/
|
|
||||||
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
|
||||||
return generic_setxattr(dentry, name, value, size, flags);
|
|
||||||
|
|
||||||
ret = btrfs_is_valid_xattr(name);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
|
|
||||||
return btrfs_set_prop(d_inode(dentry), name,
|
|
||||||
value, size, flags);
|
|
||||||
|
|
||||||
if (size == 0)
|
|
||||||
value = ""; /* empty EA, do not remove */
|
|
||||||
|
|
||||||
return __btrfs_setxattr(NULL, d_inode(dentry), name, value, size,
|
|
||||||
flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_removexattr(struct dentry *dentry, const char *name)
|
int btrfs_removexattr(struct dentry *dentry, const char *name)
|
||||||
{
|
{
|
||||||
struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root;
|
struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root;
|
||||||
int ret;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The permission on security.* and system.* is not checked
|
|
||||||
* in permission().
|
|
||||||
*/
|
|
||||||
if (btrfs_root_readonly(root))
|
if (btrfs_root_readonly(root))
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
|
return generic_removexattr(dentry, name);
|
||||||
/*
|
|
||||||
* If this is a request for a synthetic attribute in the system.*
|
|
||||||
* namespace use the generic infrastructure to resolve a handler
|
|
||||||
* for it via sb->s_xattr.
|
|
||||||
*/
|
|
||||||
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
|
||||||
return generic_removexattr(dentry, name);
|
|
||||||
|
|
||||||
ret = btrfs_is_valid_xattr(name);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
|
|
||||||
return btrfs_set_prop(d_inode(dentry), name,
|
|
||||||
NULL, 0, XATTR_REPLACE);
|
|
||||||
|
|
||||||
return __btrfs_setxattr(NULL, d_inode(dentry), name, NULL, 0,
|
|
||||||
XATTR_REPLACE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int btrfs_initxattrs(struct inode *inode,
|
static int btrfs_initxattrs(struct inode *inode,
|
||||||
|
|
|
@ -28,8 +28,6 @@ extern ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
|
||||||
extern int __btrfs_setxattr(struct btrfs_trans_handle *trans,
|
extern int __btrfs_setxattr(struct btrfs_trans_handle *trans,
|
||||||
struct inode *inode, const char *name,
|
struct inode *inode, const char *name,
|
||||||
const void *value, size_t size, int flags);
|
const void *value, size_t size, int flags);
|
||||||
extern ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
|
|
||||||
void *buffer, size_t size);
|
|
||||||
extern int btrfs_setxattr(struct dentry *dentry, const char *name,
|
extern int btrfs_setxattr(struct dentry *dentry, const char *name,
|
||||||
const void *value, size_t size, int flags);
|
const void *value, size_t size, int flags);
|
||||||
extern int btrfs_removexattr(struct dentry *dentry, const char *name);
|
extern int btrfs_removexattr(struct dentry *dentry, const char *name);
|
||||||
|
|
Loading…
Reference in New Issue