Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9172abbc authored by Andreas Gruenbacher's avatar Andreas Gruenbacher Committed by Al Viro
Browse files

btrfs: Use xattr handler infrastructure



Use the VFS xattr handler infrastructure and get rid of similar code in
the filesystem.

Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 98e9cb57
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -9994,7 +9994,7 @@ static const struct inode_operations btrfs_dir_inode_operations = {
	.setattr	= btrfs_setattr,
	.mknod		= btrfs_mknod,
	.setxattr	= btrfs_setxattr,
	.getxattr	= btrfs_getxattr,
	.getxattr	= generic_getxattr,
	.listxattr	= btrfs_listxattr,
	.removexattr	= btrfs_removexattr,
	.permission	= btrfs_permission,
@@ -10071,7 +10071,7 @@ static const struct inode_operations btrfs_file_inode_operations = {
	.getattr	= btrfs_getattr,
	.setattr	= btrfs_setattr,
	.setxattr	= btrfs_setxattr,
	.getxattr	= btrfs_getxattr,
	.getxattr	= generic_getxattr,
	.listxattr      = btrfs_listxattr,
	.removexattr	= btrfs_removexattr,
	.permission	= btrfs_permission,
@@ -10085,7 +10085,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
	.setattr	= btrfs_setattr,
	.permission	= btrfs_permission,
	.setxattr	= btrfs_setxattr,
	.getxattr	= btrfs_getxattr,
	.getxattr	= generic_getxattr,
	.listxattr	= btrfs_listxattr,
	.removexattr	= btrfs_removexattr,
	.get_acl	= btrfs_get_acl,
@@ -10100,7 +10100,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
	.setattr	= btrfs_setattr,
	.permission	= btrfs_permission,
	.setxattr	= btrfs_setxattr,
	.getxattr	= btrfs_getxattr,
	.getxattr	= generic_getxattr,
	.listxattr	= btrfs_listxattr,
	.removexattr	= btrfs_removexattr,
	.update_time	= btrfs_update_time,
+59 −107
Original line number Diff line number Diff line
@@ -351,137 +351,89 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
	return ret;
}

/*
 * List of handlers for synthetic system.* attributes.  All real ondisk
 * attributes are handled directly.
 */
const struct xattr_handler *btrfs_xattr_handlers[] = {
#ifdef CONFIG_BTRFS_FS_POSIX_ACL
	&posix_acl_access_xattr_handler,
	&posix_acl_default_xattr_handler,
#endif
	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)
static int btrfs_xattr_handler_get(const struct xattr_handler *handler,
				   struct dentry *dentry, const char *name,
				   void *buffer, size_t size)
{
	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;
	struct inode *inode = d_inode(dentry);

	return 0;
	name = xattr_full_name(handler, name);
	return __btrfs_getxattr(inode, name, buffer, size);
}

ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
		       void *buffer, size_t 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)
{
	int ret;
	struct inode *inode = d_inode(dentry);

	/*
	 * 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);
	name = xattr_full_name(handler, name);
	return __btrfs_setxattr(NULL, inode, name, buffer, size, flags);
}

	ret = btrfs_is_valid_xattr(name);
	if (ret)
		return ret;
	return __btrfs_getxattr(d_inode(dentry), name, buffer, size);
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[] = {
	&btrfs_security_xattr_handler,
#ifdef CONFIG_BTRFS_FS_POSIX_ACL
	&posix_acl_access_xattr_handler,
	&posix_acl_default_xattr_handler,
#endif
	&btrfs_trusted_xattr_handler,
	&btrfs_user_xattr_handler,
	&btrfs_btrfs_xattr_handler,
	NULL,
};

int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
		   size_t size, int flags)
{
	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))
		return -EROFS;

	/*
	 * 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)
{
	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))
		return -EROFS;

	/*
	 * 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,
+0 −2
Original line number Diff line number Diff line
@@ -28,8 +28,6 @@ extern ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
extern int __btrfs_setxattr(struct btrfs_trans_handle *trans,
			    struct inode *inode, const char *name,
			    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,
		const void *value, size_t size, int flags);
extern int btrfs_removexattr(struct dentry *dentry, const char *name);