Commit aa7c5241 authored by Andreas Gruenbacher's avatar Andreas Gruenbacher Committed by Al Viro

tmpfs: Use xattr handler infrastructure

Use the VFS xattr handler infrastructure and get rid of similar code in
the filesystem.  For implementing shmem_xattr_handler_set, we need a
version of simple_xattr_set which removes the attribute when value is
NULL.  Use this to implement kernfs_iop_removexattr as well.
Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: default avatarJames Morris <james.l.morris@oracle.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: linux-mm@kvack.org
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 9172abbc
...@@ -205,7 +205,7 @@ int kernfs_iop_removexattr(struct dentry *dentry, const char *name) ...@@ -205,7 +205,7 @@ int kernfs_iop_removexattr(struct dentry *dentry, const char *name)
if (!attrs) if (!attrs)
return -ENOMEM; return -ENOMEM;
return simple_xattr_remove(&attrs->xattrs, name); return simple_xattr_set(&attrs->xattrs, name, NULL, 0, XATTR_REPLACE);
} }
ssize_t kernfs_iop_getxattr(struct dentry *dentry, const char *name, void *buf, ssize_t kernfs_iop_getxattr(struct dentry *dentry, const char *name, void *buf,
......
...@@ -851,8 +851,22 @@ int simple_xattr_get(struct simple_xattrs *xattrs, const char *name, ...@@ -851,8 +851,22 @@ int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
return ret; return ret;
} }
static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name, /**
const void *value, size_t size, int flags) * simple_xattr_set - xattr SET operation for in-memory/pseudo filesystems
* @xattrs: target simple_xattr list
* @name: name of the extended attribute
* @value: value of the xattr. If %NULL, will remove the attribute.
* @size: size of the new xattr
* @flags: %XATTR_{CREATE|REPLACE}
*
* %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails
* with -EEXIST. If %XATTR_REPLACE is set, the xattr should exist;
* otherwise, fails with -ENODATA.
*
* Returns 0 on success, -errno on failure.
*/
int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
const void *value, size_t size, int flags)
{ {
struct simple_xattr *xattr; struct simple_xattr *xattr;
struct simple_xattr *new_xattr = NULL; struct simple_xattr *new_xattr = NULL;
...@@ -902,36 +916,6 @@ static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name, ...@@ -902,36 +916,6 @@ static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
} }
/**
* simple_xattr_set - xattr SET operation for in-memory/pseudo filesystems
* @xattrs: target simple_xattr list
* @name: name of the new extended attribute
* @value: value of the new xattr. If %NULL, will remove the attribute
* @size: size of the new xattr
* @flags: %XATTR_{CREATE|REPLACE}
*
* %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails
* with -EEXIST. If %XATTR_REPLACE is set, the xattr should exist;
* otherwise, fails with -ENODATA.
*
* Returns 0 on success, -errno on failure.
*/
int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
const void *value, size_t size, int flags)
{
if (size == 0)
value = ""; /* empty EA, do not remove */
return __simple_xattr_set(xattrs, name, value, size, flags);
}
/*
* xattr REMOVE operation for in-memory/pseudo filesystems
*/
int simple_xattr_remove(struct simple_xattrs *xattrs, const char *name)
{
return __simple_xattr_set(xattrs, name, NULL, 0, XATTR_REPLACE);
}
static bool xattr_is_trusted(const char *name) static bool xattr_is_trusted(const char *name)
{ {
return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN); return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
......
...@@ -104,9 +104,7 @@ int simple_xattr_get(struct simple_xattrs *xattrs, const char *name, ...@@ -104,9 +104,7 @@ int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
void *buffer, size_t size); void *buffer, size_t size);
int simple_xattr_set(struct simple_xattrs *xattrs, const char *name, int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
const void *value, size_t size, int flags); const void *value, size_t size, int flags);
int simple_xattr_remove(struct simple_xattrs *xattrs, const char *name); ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer, size_t size);
ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer,
size_t size);
void simple_xattr_list_add(struct simple_xattrs *xattrs, void simple_xattr_list_add(struct simple_xattrs *xattrs,
struct simple_xattr *new_xattr); struct simple_xattr *new_xattr);
......
...@@ -2561,94 +2561,47 @@ static int shmem_initxattrs(struct inode *inode, ...@@ -2561,94 +2561,47 @@ static int shmem_initxattrs(struct inode *inode,
return 0; return 0;
} }
static const struct xattr_handler *shmem_xattr_handlers[] = { static int shmem_xattr_handler_get(const struct xattr_handler *handler,
#ifdef CONFIG_TMPFS_POSIX_ACL struct dentry *dentry, const char *name,
&posix_acl_access_xattr_handler, void *buffer, size_t size)
&posix_acl_default_xattr_handler,
#endif
NULL
};
static int shmem_xattr_validate(const char *name)
{
struct { const char *prefix; size_t len; } arr[] = {
{ XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN },
{ XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN }
};
int i;
for (i = 0; i < ARRAY_SIZE(arr); i++) {
size_t preflen = arr[i].len;
if (strncmp(name, arr[i].prefix, preflen) == 0) {
if (!name[preflen])
return -EINVAL;
return 0;
}
}
return -EOPNOTSUPP;
}
static ssize_t shmem_getxattr(struct dentry *dentry, const char *name,
void *buffer, size_t size)
{ {
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry)); struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
int err;
/*
* 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);
err = shmem_xattr_validate(name);
if (err)
return err;
name = xattr_full_name(handler, name);
return simple_xattr_get(&info->xattrs, name, buffer, size); return simple_xattr_get(&info->xattrs, name, buffer, size);
} }
static int shmem_setxattr(struct dentry *dentry, const char *name, static int shmem_xattr_handler_set(const struct xattr_handler *handler,
const void *value, size_t size, int flags) struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{ {
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry)); struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
int err;
/*
* 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);
err = shmem_xattr_validate(name);
if (err)
return err;
name = xattr_full_name(handler, name);
return simple_xattr_set(&info->xattrs, name, value, size, flags); return simple_xattr_set(&info->xattrs, name, value, size, flags);
} }
static int shmem_removexattr(struct dentry *dentry, const char *name) static const struct xattr_handler shmem_security_xattr_handler = {
{ .prefix = XATTR_SECURITY_PREFIX,
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry)); .get = shmem_xattr_handler_get,
int err; .set = shmem_xattr_handler_set,
};
/*
* 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);
err = shmem_xattr_validate(name); static const struct xattr_handler shmem_trusted_xattr_handler = {
if (err) .prefix = XATTR_TRUSTED_PREFIX,
return err; .get = shmem_xattr_handler_get,
.set = shmem_xattr_handler_set,
};
return simple_xattr_remove(&info->xattrs, name); static const struct xattr_handler *shmem_xattr_handlers[] = {
} #ifdef CONFIG_TMPFS_POSIX_ACL
&posix_acl_access_xattr_handler,
&posix_acl_default_xattr_handler,
#endif
&shmem_security_xattr_handler,
&shmem_trusted_xattr_handler,
NULL
};
static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size) static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size)
{ {
...@@ -2661,10 +2614,10 @@ static const struct inode_operations shmem_short_symlink_operations = { ...@@ -2661,10 +2614,10 @@ static const struct inode_operations shmem_short_symlink_operations = {
.readlink = generic_readlink, .readlink = generic_readlink,
.follow_link = simple_follow_link, .follow_link = simple_follow_link,
#ifdef CONFIG_TMPFS_XATTR #ifdef CONFIG_TMPFS_XATTR
.setxattr = shmem_setxattr, .setxattr = generic_setxattr,
.getxattr = shmem_getxattr, .getxattr = generic_getxattr,
.listxattr = shmem_listxattr, .listxattr = shmem_listxattr,
.removexattr = shmem_removexattr, .removexattr = generic_removexattr,
#endif #endif
}; };
...@@ -2673,10 +2626,10 @@ static const struct inode_operations shmem_symlink_inode_operations = { ...@@ -2673,10 +2626,10 @@ static const struct inode_operations shmem_symlink_inode_operations = {
.follow_link = shmem_follow_link, .follow_link = shmem_follow_link,
.put_link = shmem_put_link, .put_link = shmem_put_link,
#ifdef CONFIG_TMPFS_XATTR #ifdef CONFIG_TMPFS_XATTR
.setxattr = shmem_setxattr, .setxattr = generic_setxattr,
.getxattr = shmem_getxattr, .getxattr = generic_getxattr,
.listxattr = shmem_listxattr, .listxattr = shmem_listxattr,
.removexattr = shmem_removexattr, .removexattr = generic_removexattr,
#endif #endif
}; };
...@@ -3148,10 +3101,10 @@ static const struct inode_operations shmem_inode_operations = { ...@@ -3148,10 +3101,10 @@ static const struct inode_operations shmem_inode_operations = {
.getattr = shmem_getattr, .getattr = shmem_getattr,
.setattr = shmem_setattr, .setattr = shmem_setattr,
#ifdef CONFIG_TMPFS_XATTR #ifdef CONFIG_TMPFS_XATTR
.setxattr = shmem_setxattr, .setxattr = generic_setxattr,
.getxattr = shmem_getxattr, .getxattr = generic_getxattr,
.listxattr = shmem_listxattr, .listxattr = shmem_listxattr,
.removexattr = shmem_removexattr, .removexattr = generic_removexattr,
.set_acl = simple_set_acl, .set_acl = simple_set_acl,
#endif #endif
}; };
...@@ -3170,10 +3123,10 @@ static const struct inode_operations shmem_dir_inode_operations = { ...@@ -3170,10 +3123,10 @@ static const struct inode_operations shmem_dir_inode_operations = {
.tmpfile = shmem_tmpfile, .tmpfile = shmem_tmpfile,
#endif #endif
#ifdef CONFIG_TMPFS_XATTR #ifdef CONFIG_TMPFS_XATTR
.setxattr = shmem_setxattr, .setxattr = generic_setxattr,
.getxattr = shmem_getxattr, .getxattr = generic_getxattr,
.listxattr = shmem_listxattr, .listxattr = shmem_listxattr,
.removexattr = shmem_removexattr, .removexattr = generic_removexattr,
#endif #endif
#ifdef CONFIG_TMPFS_POSIX_ACL #ifdef CONFIG_TMPFS_POSIX_ACL
.setattr = shmem_setattr, .setattr = shmem_setattr,
...@@ -3183,10 +3136,10 @@ static const struct inode_operations shmem_dir_inode_operations = { ...@@ -3183,10 +3136,10 @@ static const struct inode_operations shmem_dir_inode_operations = {
static const struct inode_operations shmem_special_inode_operations = { static const struct inode_operations shmem_special_inode_operations = {
#ifdef CONFIG_TMPFS_XATTR #ifdef CONFIG_TMPFS_XATTR
.setxattr = shmem_setxattr, .setxattr = generic_setxattr,
.getxattr = shmem_getxattr, .getxattr = generic_getxattr,
.listxattr = shmem_listxattr, .listxattr = shmem_listxattr,
.removexattr = shmem_removexattr, .removexattr = generic_removexattr,
#endif #endif
#ifdef CONFIG_TMPFS_POSIX_ACL #ifdef CONFIG_TMPFS_POSIX_ACL
.setattr = shmem_setattr, .setattr = shmem_setattr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment