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

9p: xattr simplifications

Now that the xattr handler is passed to the xattr handler operations, we
can use the same get and set operations for the user, trusted, and security
xattr namespaces.  In those namespaces, we can access the full attribute
name by "reattaching" the name prefix the vfs has skipped for us.  Add a
xattr_full_name helper to make this obvious in the code.

For the "system.posix_acl_access" and "system.posix_acl_default"
attributes, handler->prefix is the full attribute name; the suffix is the
empty string.
Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
Cc: Eric Van Hensbergen <ericvh@gmail.com>
Cc: Ron Minnich <rminnich@sandia.gov>
Cc: Latchesar Ionkov <lucho@ionkov.net>
Cc: v9fs-developer@lists.sourceforge.net
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent d9a82a04
...@@ -10,10 +10,7 @@ obj-$(CONFIG_9P_FS) := 9p.o ...@@ -10,10 +10,7 @@ obj-$(CONFIG_9P_FS) := 9p.o
vfs_dentry.o \ vfs_dentry.o \
v9fs.o \ v9fs.o \
fid.o \ fid.o \
xattr.o \ xattr.o
xattr_user.o \
xattr_trusted.o
9p-$(CONFIG_9P_FSCACHE) += cache.o 9p-$(CONFIG_9P_FSCACHE) += cache.o
9p-$(CONFIG_9P_FS_POSIX_ACL) += acl.o 9p-$(CONFIG_9P_FS_POSIX_ACL) += acl.o
9p-$(CONFIG_9P_FS_SECURITY) += xattr_security.o
...@@ -212,31 +212,12 @@ int v9fs_acl_mode(struct inode *dir, umode_t *modep, ...@@ -212,31 +212,12 @@ int v9fs_acl_mode(struct inode *dir, umode_t *modep,
return 0; return 0;
} }
static int v9fs_remote_get_acl(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
char *full_name;
switch (type) {
case ACL_TYPE_ACCESS:
full_name = POSIX_ACL_XATTR_ACCESS;
break;
case ACL_TYPE_DEFAULT:
full_name = POSIX_ACL_XATTR_DEFAULT;
break;
default:
BUG();
}
return v9fs_xattr_get(dentry, full_name, buffer, size);
}
static int v9fs_xattr_get_acl(const struct xattr_handler *handler, static int v9fs_xattr_get_acl(const struct xattr_handler *handler,
struct dentry *dentry, const char *name, struct dentry *dentry, const char *name,
void *buffer, size_t size) void *buffer, size_t size)
{ {
struct v9fs_session_info *v9ses; struct v9fs_session_info *v9ses;
struct posix_acl *acl; struct posix_acl *acl;
int type = handler->flags;
int error; int error;
if (strcmp(name, "") != 0) if (strcmp(name, "") != 0)
...@@ -247,9 +228,9 @@ static int v9fs_xattr_get_acl(const struct xattr_handler *handler, ...@@ -247,9 +228,9 @@ static int v9fs_xattr_get_acl(const struct xattr_handler *handler,
* We allow set/get/list of acl when access=client is not specified * We allow set/get/list of acl when access=client is not specified
*/ */
if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
return v9fs_remote_get_acl(dentry, name, buffer, size, type); return v9fs_xattr_get(dentry, handler->prefix, buffer, size);
acl = v9fs_get_cached_acl(d_inode(dentry), type); acl = v9fs_get_cached_acl(d_inode(dentry), handler->flags);
if (IS_ERR(acl)) if (IS_ERR(acl))
return PTR_ERR(acl); return PTR_ERR(acl);
if (acl == NULL) if (acl == NULL)
...@@ -260,26 +241,6 @@ static int v9fs_xattr_get_acl(const struct xattr_handler *handler, ...@@ -260,26 +241,6 @@ static int v9fs_xattr_get_acl(const struct xattr_handler *handler,
return error; return error;
} }
static int v9fs_remote_set_acl(struct dentry *dentry, const char *name,
const void *value, size_t size,
int flags, int type)
{
char *full_name;
switch (type) {
case ACL_TYPE_ACCESS:
full_name = POSIX_ACL_XATTR_ACCESS;
break;
case ACL_TYPE_DEFAULT:
full_name = POSIX_ACL_XATTR_DEFAULT;
break;
default:
BUG();
}
return v9fs_xattr_set(dentry, full_name, value, size, flags);
}
static int v9fs_xattr_set_acl(const struct xattr_handler *handler, static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
struct dentry *dentry, const char *name, struct dentry *dentry, const char *name,
const void *value, size_t size, int flags) const void *value, size_t size, int flags)
...@@ -298,8 +259,8 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler, ...@@ -298,8 +259,8 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
* xattr value. We leave it to the server to validate * xattr value. We leave it to the server to validate
*/ */
if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
return v9fs_remote_set_acl(dentry, name, return v9fs_xattr_set(dentry, handler->prefix, value, size,
value, size, flags, handler->flags); flags);
if (S_ISLNK(inode->i_mode)) if (S_ISLNK(inode->i_mode))
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -320,7 +281,6 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler, ...@@ -320,7 +281,6 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
switch (handler->flags) { switch (handler->flags) {
case ACL_TYPE_ACCESS: case ACL_TYPE_ACCESS:
name = POSIX_ACL_XATTR_ACCESS;
if (acl) { if (acl) {
umode_t mode = inode->i_mode; umode_t mode = inode->i_mode;
retval = posix_acl_equiv_mode(acl, &mode); retval = posix_acl_equiv_mode(acl, &mode);
...@@ -351,7 +311,6 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler, ...@@ -351,7 +311,6 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
} }
break; break;
case ACL_TYPE_DEFAULT: case ACL_TYPE_DEFAULT:
name = POSIX_ACL_XATTR_DEFAULT;
if (!S_ISDIR(inode->i_mode)) { if (!S_ISDIR(inode->i_mode)) {
retval = acl ? -EINVAL : 0; retval = acl ? -EINVAL : 0;
goto err_out; goto err_out;
...@@ -360,7 +319,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler, ...@@ -360,7 +319,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
default: default:
BUG(); BUG();
} }
retval = v9fs_xattr_set(dentry, name, value, size, flags); retval = v9fs_xattr_set(dentry, handler->prefix, value, size, flags);
if (!retval) if (!retval)
set_cached_acl(inode, handler->flags, acl); set_cached_acl(inode, handler->flags, acl);
err_out: err_out:
......
...@@ -137,6 +137,48 @@ ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) ...@@ -137,6 +137,48 @@ ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
return v9fs_xattr_get(dentry, NULL, buffer, buffer_size); return v9fs_xattr_get(dentry, NULL, buffer, buffer_size);
} }
static int v9fs_xattr_handler_get(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
const char *full_name = xattr_full_name(handler, name);
if (strcmp(name, "") == 0)
return -EINVAL;
return v9fs_xattr_get(dentry, full_name, buffer, size);
}
static int v9fs_xattr_handler_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
const char *full_name = xattr_full_name(handler, name);
if (strcmp(name, "") == 0)
return -EINVAL;
return v9fs_xattr_set(dentry, full_name, value, size, flags);
}
static struct xattr_handler v9fs_xattr_user_handler = {
.prefix = XATTR_USER_PREFIX,
.get = v9fs_xattr_handler_get,
.set = v9fs_xattr_handler_set,
};
static struct xattr_handler v9fs_xattr_trusted_handler = {
.prefix = XATTR_TRUSTED_PREFIX,
.get = v9fs_xattr_handler_get,
.set = v9fs_xattr_handler_set,
};
#ifdef CONFIG_9P_FS_SECURITY
static struct xattr_handler v9fs_xattr_security_handler = {
.prefix = XATTR_SECURITY_PREFIX,
.get = v9fs_xattr_handler_get,
.set = v9fs_xattr_handler_set,
};
#endif
const struct xattr_handler *v9fs_xattr_handlers[] = { const struct xattr_handler *v9fs_xattr_handlers[] = {
&v9fs_xattr_user_handler, &v9fs_xattr_user_handler,
&v9fs_xattr_trusted_handler, &v9fs_xattr_trusted_handler,
......
...@@ -19,9 +19,6 @@ ...@@ -19,9 +19,6 @@
#include <net/9p/client.h> #include <net/9p/client.h>
extern const struct xattr_handler *v9fs_xattr_handlers[]; extern const struct xattr_handler *v9fs_xattr_handlers[];
extern struct xattr_handler v9fs_xattr_user_handler;
extern struct xattr_handler v9fs_xattr_trusted_handler;
extern struct xattr_handler v9fs_xattr_security_handler;
extern const struct xattr_handler v9fs_xattr_acl_access_handler; extern const struct xattr_handler v9fs_xattr_acl_access_handler;
extern const struct xattr_handler v9fs_xattr_acl_default_handler; extern const struct xattr_handler v9fs_xattr_acl_default_handler;
......
/*
* Copyright IBM Corporation, 2010
* Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2.1 of the GNU Lesser General Public License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include "xattr.h"
static int v9fs_xattr_security_get(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
int retval;
char *full_name;
size_t name_len;
size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
if (name == NULL)
return -EINVAL;
if (strcmp(name, "") == 0)
return -EINVAL;
name_len = strlen(name);
full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
if (!full_name)
return -ENOMEM;
memcpy(full_name, XATTR_SECURITY_PREFIX, prefix_len);
memcpy(full_name+prefix_len, name, name_len);
full_name[prefix_len + name_len] = '\0';
retval = v9fs_xattr_get(dentry, full_name, buffer, size);
kfree(full_name);
return retval;
}
static int v9fs_xattr_security_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
int retval;
char *full_name;
size_t name_len;
size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
if (name == NULL)
return -EINVAL;
if (strcmp(name, "") == 0)
return -EINVAL;
name_len = strlen(name);
full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
if (!full_name)
return -ENOMEM;
memcpy(full_name, XATTR_SECURITY_PREFIX, prefix_len);
memcpy(full_name + prefix_len, name, name_len);
full_name[prefix_len + name_len] = '\0';
retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
kfree(full_name);
return retval;
}
struct xattr_handler v9fs_xattr_security_handler = {
.prefix = XATTR_SECURITY_PREFIX,
.get = v9fs_xattr_security_get,
.set = v9fs_xattr_security_set,
};
/*
* Copyright IBM Corporation, 2010
* Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2.1 of the GNU Lesser General Public License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include "xattr.h"
static int v9fs_xattr_trusted_get(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
int retval;
char *full_name;
size_t name_len;
size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
if (name == NULL)
return -EINVAL;
if (strcmp(name, "") == 0)
return -EINVAL;
name_len = strlen(name);
full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
if (!full_name)
return -ENOMEM;
memcpy(full_name, XATTR_TRUSTED_PREFIX, prefix_len);
memcpy(full_name+prefix_len, name, name_len);
full_name[prefix_len + name_len] = '\0';
retval = v9fs_xattr_get(dentry, full_name, buffer, size);
kfree(full_name);
return retval;
}
static int v9fs_xattr_trusted_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
int retval;
char *full_name;
size_t name_len;
size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
if (name == NULL)
return -EINVAL;
if (strcmp(name, "") == 0)
return -EINVAL;
name_len = strlen(name);
full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
if (!full_name)
return -ENOMEM;
memcpy(full_name, XATTR_TRUSTED_PREFIX, prefix_len);
memcpy(full_name + prefix_len, name, name_len);
full_name[prefix_len + name_len] = '\0';
retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
kfree(full_name);
return retval;
}
struct xattr_handler v9fs_xattr_trusted_handler = {
.prefix = XATTR_TRUSTED_PREFIX,
.get = v9fs_xattr_trusted_get,
.set = v9fs_xattr_trusted_set,
};
/*
* Copyright IBM Corporation, 2010
* Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2.1 of the GNU Lesser General Public License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include "xattr.h"
static int v9fs_xattr_user_get(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
int retval;
char *full_name;
size_t name_len;
size_t prefix_len = XATTR_USER_PREFIX_LEN;
if (name == NULL)
return -EINVAL;
if (strcmp(name, "") == 0)
return -EINVAL;
name_len = strlen(name);
full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
if (!full_name)
return -ENOMEM;
memcpy(full_name, XATTR_USER_PREFIX, prefix_len);
memcpy(full_name+prefix_len, name, name_len);
full_name[prefix_len + name_len] = '\0';
retval = v9fs_xattr_get(dentry, full_name, buffer, size);
kfree(full_name);
return retval;
}
static int v9fs_xattr_user_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
int retval;
char *full_name;
size_t name_len;
size_t prefix_len = XATTR_USER_PREFIX_LEN;
if (name == NULL)
return -EINVAL;
if (strcmp(name, "") == 0)
return -EINVAL;
name_len = strlen(name);
full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
if (!full_name)
return -ENOMEM;
memcpy(full_name, XATTR_USER_PREFIX, prefix_len);
memcpy(full_name + prefix_len, name, name_len);
full_name[prefix_len + name_len] = '\0';
retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
kfree(full_name);
return retval;
}
struct xattr_handler v9fs_xattr_user_handler = {
.prefix = XATTR_USER_PREFIX,
.get = v9fs_xattr_user_get,
.set = v9fs_xattr_user_set,
};
...@@ -790,6 +790,30 @@ EXPORT_SYMBOL(generic_listxattr); ...@@ -790,6 +790,30 @@ EXPORT_SYMBOL(generic_listxattr);
EXPORT_SYMBOL(generic_setxattr); EXPORT_SYMBOL(generic_setxattr);
EXPORT_SYMBOL(generic_removexattr); EXPORT_SYMBOL(generic_removexattr);
/**
* xattr_full_name - Compute full attribute name from suffix
*
* @handler: handler of the xattr_handler operation
* @name: name passed to the xattr_handler operation
*
* The get and set xattr handler operations are called with the remainder of
* the attribute name after skipping the handler's prefix: for example, "foo"
* is passed to the get operation of a handler with prefix "user." to get
* attribute "user.foo". The full name is still "there" in the name though.
*
* Note: the list xattr handler operation when called from the vfs is passed a
* NULL name; some file systems use this operation internally, with varying
* semantics.
*/
const char *xattr_full_name(const struct xattr_handler *handler,
const char *name)
{
size_t prefix_len = strlen(handler->prefix);
return name - prefix_len;
}
EXPORT_SYMBOL(xattr_full_name);
/* /*
* Allocate new xattr and copy in the value; but leave the name to callers. * Allocate new xattr and copy in the value; but leave the name to callers.
*/ */
......
...@@ -21,15 +21,19 @@ struct dentry; ...@@ -21,15 +21,19 @@ struct dentry;
struct xattr_handler { struct xattr_handler {
const char *prefix; const char *prefix;
int flags; /* fs private flags passed back to the handlers */ int flags; /* fs private flags */
size_t (*list)(struct dentry *dentry, char *list, size_t list_size, size_t (*list)(const struct xattr_handler *, struct dentry *dentry,
const char *name, size_t name_len, int handler_flags); char *list, size_t list_size, const char *name,
int (*get)(struct dentry *dentry, const char *name, void *buffer, size_t name_len);
size_t size, int handler_flags); int (*get)(const struct xattr_handler *, struct dentry *dentry,
int (*set)(struct dentry *dentry, const char *name, const void *buffer, const char *name, void *buffer, size_t size);
size_t size, int flags, int handler_flags); int (*set)(const struct xattr_handler *, struct dentry *dentry,
const char *name, const void *buffer, size_t size,
int flags);
}; };
const char *xattr_full_name(const struct xattr_handler *, const char *);
struct xattr { struct xattr {
const char *name; const char *name;
void *value; void *value;
......
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