mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
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: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: James Morris <james.l.morris@oracle.com> Cc: Hugh Dickins <hughd@google.com> Cc: linux-mm@kvack.org Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
9172abbcd3
commit
aa7c5241c3
@ -205,7 +205,7 @@ int kernfs_iop_removexattr(struct dentry *dentry, const char *name)
|
||||
if (!attrs)
|
||||
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,
|
||||
|
48
fs/xattr.c
48
fs/xattr.c
@ -851,8 +851,22 @@ int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
|
||||
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 *new_xattr = NULL;
|
||||
@ -902,36 +916,6 @@ out:
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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,
|
||||
void *buffer, size_t size);
|
||||
int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
|
||||
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,
|
||||
struct simple_xattr *new_xattr);
|
||||
|
||||
|
145
mm/shmem.c
145
mm/shmem.c
@ -2561,95 +2561,48 @@ static int shmem_initxattrs(struct inode *inode,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shmem_xattr_handler_get(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
|
||||
|
||||
name = xattr_full_name(handler, name);
|
||||
return simple_xattr_get(&info->xattrs, name, buffer, size);
|
||||
}
|
||||
|
||||
static int shmem_xattr_handler_set(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
|
||||
|
||||
name = xattr_full_name(handler, name);
|
||||
return simple_xattr_set(&info->xattrs, name, value, size, flags);
|
||||
}
|
||||
|
||||
static const struct xattr_handler shmem_security_xattr_handler = {
|
||||
.prefix = XATTR_SECURITY_PREFIX,
|
||||
.get = shmem_xattr_handler_get,
|
||||
.set = shmem_xattr_handler_set,
|
||||
};
|
||||
|
||||
static const struct xattr_handler shmem_trusted_xattr_handler = {
|
||||
.prefix = XATTR_TRUSTED_PREFIX,
|
||||
.get = shmem_xattr_handler_get,
|
||||
.set = shmem_xattr_handler_set,
|
||||
};
|
||||
|
||||
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 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));
|
||||
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;
|
||||
|
||||
return simple_xattr_get(&info->xattrs, name, buffer, size);
|
||||
}
|
||||
|
||||
static int shmem_setxattr(struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
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;
|
||||
|
||||
return simple_xattr_set(&info->xattrs, name, value, size, flags);
|
||||
}
|
||||
|
||||
static int shmem_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
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_removexattr(dentry, name);
|
||||
|
||||
err = shmem_xattr_validate(name);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return simple_xattr_remove(&info->xattrs, name);
|
||||
}
|
||||
|
||||
static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
||||
{
|
||||
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
|
||||
@ -2661,10 +2614,10 @@ static const struct inode_operations shmem_short_symlink_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.follow_link = simple_follow_link,
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = shmem_setxattr,
|
||||
.getxattr = shmem_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = shmem_removexattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -2673,10 +2626,10 @@ static const struct inode_operations shmem_symlink_inode_operations = {
|
||||
.follow_link = shmem_follow_link,
|
||||
.put_link = shmem_put_link,
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = shmem_setxattr,
|
||||
.getxattr = shmem_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = shmem_removexattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -3148,10 +3101,10 @@ static const struct inode_operations shmem_inode_operations = {
|
||||
.getattr = shmem_getattr,
|
||||
.setattr = shmem_setattr,
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = shmem_setxattr,
|
||||
.getxattr = shmem_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = shmem_removexattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.set_acl = simple_set_acl,
|
||||
#endif
|
||||
};
|
||||
@ -3170,10 +3123,10 @@ static const struct inode_operations shmem_dir_inode_operations = {
|
||||
.tmpfile = shmem_tmpfile,
|
||||
#endif
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = shmem_setxattr,
|
||||
.getxattr = shmem_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = shmem_removexattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
#ifdef CONFIG_TMPFS_POSIX_ACL
|
||||
.setattr = shmem_setattr,
|
||||
@ -3183,10 +3136,10 @@ static const struct inode_operations shmem_dir_inode_operations = {
|
||||
|
||||
static const struct inode_operations shmem_special_inode_operations = {
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = shmem_setxattr,
|
||||
.getxattr = shmem_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = shmem_removexattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
#ifdef CONFIG_TMPFS_POSIX_ACL
|
||||
.setattr = shmem_setattr,
|
||||
|
Loading…
Reference in New Issue
Block a user