[XFS] Use the generic xattr methods.
Use the generic set, get and removexattr methods and supply the s_xattr array with fine-grained handlers. All XFS/Linux highlevel attr handling is rewritten from scratch and placed into fs/xfs/linux-2.6/xfs_xattr.c so that it's separated from the generic low-level code. SGI-PV: 982343 SGI-Modid: xfs-linux-melb:xfs-kern:31234a Signed-off-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: Tim Shimmin <tes@sgi.com> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
This commit is contained in:
parent
d532506cd8
commit
0ec585163a
7 changed files with 18 additions and 395 deletions
|
@ -106,7 +106,8 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \
|
|||
xfs_iops.o \
|
||||
xfs_lrw.o \
|
||||
xfs_super.o \
|
||||
xfs_vnode.o)
|
||||
xfs_vnode.o \
|
||||
xfs_xattr.o)
|
||||
|
||||
# Objects in support/
|
||||
xfs-y += $(addprefix support/, \
|
||||
|
|
|
@ -275,7 +275,7 @@ xfs_vn_mknod(
|
|||
struct xfs_inode *ip = NULL;
|
||||
xfs_acl_t *default_acl = NULL;
|
||||
struct xfs_name name;
|
||||
attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS;
|
||||
int (*test_default_acl)(struct inode *) = _ACL_DEFAULT_EXISTS;
|
||||
int error;
|
||||
|
||||
/*
|
||||
|
@ -781,98 +781,6 @@ xfs_vn_truncate(
|
|||
WARN_ON(error);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_vn_setxattr(
|
||||
struct dentry *dentry,
|
||||
const char *name,
|
||||
const void *data,
|
||||
size_t size,
|
||||
int flags)
|
||||
{
|
||||
bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
|
||||
char *attr = (char *)name;
|
||||
attrnames_t *namesp;
|
||||
int xflags = 0;
|
||||
|
||||
namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
|
||||
if (!namesp)
|
||||
return -EOPNOTSUPP;
|
||||
attr += namesp->attr_namelen;
|
||||
|
||||
/* Convert Linux syscall to XFS internal ATTR flags */
|
||||
if (flags & XATTR_CREATE)
|
||||
xflags |= ATTR_CREATE;
|
||||
if (flags & XATTR_REPLACE)
|
||||
xflags |= ATTR_REPLACE;
|
||||
xflags |= namesp->attr_flag;
|
||||
return namesp->attr_set(vp, attr, (void *)data, size, xflags);
|
||||
}
|
||||
|
||||
STATIC ssize_t
|
||||
xfs_vn_getxattr(
|
||||
struct dentry *dentry,
|
||||
const char *name,
|
||||
void *data,
|
||||
size_t size)
|
||||
{
|
||||
bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
|
||||
char *attr = (char *)name;
|
||||
attrnames_t *namesp;
|
||||
int xflags = 0;
|
||||
|
||||
namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
|
||||
if (!namesp)
|
||||
return -EOPNOTSUPP;
|
||||
attr += namesp->attr_namelen;
|
||||
|
||||
/* Convert Linux syscall to XFS internal ATTR flags */
|
||||
if (!size) {
|
||||
xflags |= ATTR_KERNOVAL;
|
||||
data = NULL;
|
||||
}
|
||||
xflags |= namesp->attr_flag;
|
||||
return namesp->attr_get(vp, attr, (void *)data, size, xflags);
|
||||
}
|
||||
|
||||
STATIC ssize_t
|
||||
xfs_vn_listxattr(
|
||||
struct dentry *dentry,
|
||||
char *data,
|
||||
size_t size)
|
||||
{
|
||||
bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
|
||||
int error, xflags = ATTR_KERNAMELS;
|
||||
ssize_t result;
|
||||
|
||||
if (!size)
|
||||
xflags |= ATTR_KERNOVAL;
|
||||
xflags |= capable(CAP_SYS_ADMIN) ? ATTR_KERNFULLS : ATTR_KERNORMALS;
|
||||
|
||||
error = attr_generic_list(vp, data, size, xflags, &result);
|
||||
if (error < 0)
|
||||
return error;
|
||||
return result;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_vn_removexattr(
|
||||
struct dentry *dentry,
|
||||
const char *name)
|
||||
{
|
||||
bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
|
||||
char *attr = (char *)name;
|
||||
attrnames_t *namesp;
|
||||
int xflags = 0;
|
||||
|
||||
namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
|
||||
if (!namesp)
|
||||
return -EOPNOTSUPP;
|
||||
attr += namesp->attr_namelen;
|
||||
|
||||
xflags |= namesp->attr_flag;
|
||||
return namesp->attr_remove(vp, attr, xflags);
|
||||
}
|
||||
|
||||
STATIC long
|
||||
xfs_vn_fallocate(
|
||||
struct inode *inode,
|
||||
|
@ -920,10 +828,10 @@ const struct inode_operations xfs_inode_operations = {
|
|||
.truncate = xfs_vn_truncate,
|
||||
.getattr = xfs_vn_getattr,
|
||||
.setattr = xfs_vn_setattr,
|
||||
.setxattr = xfs_vn_setxattr,
|
||||
.getxattr = xfs_vn_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.removexattr = xfs_vn_removexattr,
|
||||
.fallocate = xfs_vn_fallocate,
|
||||
};
|
||||
|
||||
|
@ -940,10 +848,10 @@ const struct inode_operations xfs_dir_inode_operations = {
|
|||
.permission = xfs_vn_permission,
|
||||
.getattr = xfs_vn_getattr,
|
||||
.setattr = xfs_vn_setattr,
|
||||
.setxattr = xfs_vn_setxattr,
|
||||
.getxattr = xfs_vn_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.removexattr = xfs_vn_removexattr,
|
||||
};
|
||||
|
||||
const struct inode_operations xfs_dir_ci_inode_operations = {
|
||||
|
@ -959,10 +867,10 @@ const struct inode_operations xfs_dir_ci_inode_operations = {
|
|||
.permission = xfs_vn_permission,
|
||||
.getattr = xfs_vn_getattr,
|
||||
.setattr = xfs_vn_setattr,
|
||||
.setxattr = xfs_vn_setxattr,
|
||||
.getxattr = xfs_vn_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.removexattr = xfs_vn_removexattr,
|
||||
};
|
||||
|
||||
const struct inode_operations xfs_symlink_inode_operations = {
|
||||
|
@ -972,8 +880,8 @@ const struct inode_operations xfs_symlink_inode_operations = {
|
|||
.permission = xfs_vn_permission,
|
||||
.getattr = xfs_vn_getattr,
|
||||
.setattr = xfs_vn_setattr,
|
||||
.setxattr = xfs_vn_setxattr,
|
||||
.getxattr = xfs_vn_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.removexattr = xfs_vn_removexattr,
|
||||
};
|
||||
|
|
|
@ -27,6 +27,7 @@ extern const struct file_operations xfs_file_operations;
|
|||
extern const struct file_operations xfs_dir_file_operations;
|
||||
extern const struct file_operations xfs_invis_file_operations;
|
||||
|
||||
extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size);
|
||||
|
||||
struct xfs_inode;
|
||||
extern void xfs_ichgtime(struct xfs_inode *, int);
|
||||
|
|
|
@ -1766,6 +1766,7 @@ xfs_fs_fill_super(
|
|||
goto out_free_mp;
|
||||
|
||||
sb_min_blocksize(sb, BBSIZE);
|
||||
sb->s_xattr = xfs_xattr_handlers;
|
||||
sb->s_export_op = &xfs_export_operations;
|
||||
sb->s_qcop = &xfs_quotactl_operations;
|
||||
sb->s_op = &xfs_super_operations;
|
||||
|
|
|
@ -110,6 +110,7 @@ extern void xfs_flush_device(struct xfs_inode *);
|
|||
extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
|
||||
|
||||
extern const struct export_operations xfs_export_operations;
|
||||
extern struct xattr_handler *xfs_xattr_handlers[];
|
||||
|
||||
#define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info))
|
||||
|
||||
|
|
|
@ -57,11 +57,6 @@
|
|||
* Provide the external interfaces to manage attribute lists.
|
||||
*/
|
||||
|
||||
#define ATTR_SYSCOUNT 2
|
||||
static struct attrnames posix_acl_access;
|
||||
static struct attrnames posix_acl_default;
|
||||
static struct attrnames *attr_system_names[ATTR_SYSCOUNT];
|
||||
|
||||
/*========================================================================
|
||||
* Function prototypes for the kernel.
|
||||
*========================================================================*/
|
||||
|
@ -2378,270 +2373,3 @@ xfs_attr_trace_enter(int type, char *where,
|
|||
(void *)a13, (void *)a14, (void *)a15);
|
||||
}
|
||||
#endif /* XFS_ATTR_TRACE */
|
||||
|
||||
|
||||
/*========================================================================
|
||||
* System (pseudo) namespace attribute interface routines.
|
||||
*========================================================================*/
|
||||
|
||||
STATIC int
|
||||
posix_acl_access_set(
|
||||
bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
|
||||
{
|
||||
return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
posix_acl_access_remove(
|
||||
bhv_vnode_t *vp, char *name, int xflags)
|
||||
{
|
||||
return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
posix_acl_access_get(
|
||||
bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
|
||||
{
|
||||
return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
posix_acl_access_exists(
|
||||
bhv_vnode_t *vp)
|
||||
{
|
||||
return xfs_acl_vhasacl_access(vp);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
posix_acl_default_set(
|
||||
bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
|
||||
{
|
||||
return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
posix_acl_default_get(
|
||||
bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
|
||||
{
|
||||
return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
posix_acl_default_remove(
|
||||
bhv_vnode_t *vp, char *name, int xflags)
|
||||
{
|
||||
return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
posix_acl_default_exists(
|
||||
bhv_vnode_t *vp)
|
||||
{
|
||||
return xfs_acl_vhasacl_default(vp);
|
||||
}
|
||||
|
||||
static struct attrnames posix_acl_access = {
|
||||
.attr_name = "posix_acl_access",
|
||||
.attr_namelen = sizeof("posix_acl_access") - 1,
|
||||
.attr_get = posix_acl_access_get,
|
||||
.attr_set = posix_acl_access_set,
|
||||
.attr_remove = posix_acl_access_remove,
|
||||
.attr_exists = posix_acl_access_exists,
|
||||
};
|
||||
|
||||
static struct attrnames posix_acl_default = {
|
||||
.attr_name = "posix_acl_default",
|
||||
.attr_namelen = sizeof("posix_acl_default") - 1,
|
||||
.attr_get = posix_acl_default_get,
|
||||
.attr_set = posix_acl_default_set,
|
||||
.attr_remove = posix_acl_default_remove,
|
||||
.attr_exists = posix_acl_default_exists,
|
||||
};
|
||||
|
||||
static struct attrnames *attr_system_names[] =
|
||||
{ &posix_acl_access, &posix_acl_default };
|
||||
|
||||
|
||||
/*========================================================================
|
||||
* Namespace-prefix-style attribute name interface routines.
|
||||
*========================================================================*/
|
||||
|
||||
STATIC int
|
||||
attr_generic_set(
|
||||
bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
|
||||
{
|
||||
return -xfs_attr_set(xfs_vtoi(vp), name, data, size, xflags);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
attr_generic_get(
|
||||
bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
|
||||
{
|
||||
int error, asize = size;
|
||||
|
||||
error = xfs_attr_get(xfs_vtoi(vp), name, data, &asize, xflags);
|
||||
if (!error)
|
||||
return asize;
|
||||
return -error;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
attr_generic_remove(
|
||||
bhv_vnode_t *vp, char *name, int xflags)
|
||||
{
|
||||
return -xfs_attr_remove(xfs_vtoi(vp), name, xflags);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
attr_generic_listadd(
|
||||
attrnames_t *prefix,
|
||||
attrnames_t *namesp,
|
||||
void *data,
|
||||
size_t size,
|
||||
ssize_t *result)
|
||||
{
|
||||
char *p = data + *result;
|
||||
|
||||
*result += prefix->attr_namelen;
|
||||
*result += namesp->attr_namelen + 1;
|
||||
if (!size)
|
||||
return 0;
|
||||
if (*result > size)
|
||||
return -ERANGE;
|
||||
strcpy(p, prefix->attr_name);
|
||||
p += prefix->attr_namelen;
|
||||
strcpy(p, namesp->attr_name);
|
||||
p += namesp->attr_namelen + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
attr_system_list(
|
||||
bhv_vnode_t *vp,
|
||||
void *data,
|
||||
size_t size,
|
||||
ssize_t *result)
|
||||
{
|
||||
attrnames_t *namesp;
|
||||
int i, error = 0;
|
||||
|
||||
for (i = 0; i < ATTR_SYSCOUNT; i++) {
|
||||
namesp = attr_system_names[i];
|
||||
if (!namesp->attr_exists || !namesp->attr_exists(vp))
|
||||
continue;
|
||||
error = attr_generic_listadd(&attr_system, namesp,
|
||||
data, size, result);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
attr_generic_list(
|
||||
bhv_vnode_t *vp, void *data, size_t size, int xflags, ssize_t *result)
|
||||
{
|
||||
attrlist_cursor_kern_t cursor = { 0 };
|
||||
int error;
|
||||
|
||||
error = xfs_attr_list(xfs_vtoi(vp), data, size, xflags, &cursor);
|
||||
if (error > 0)
|
||||
return -error;
|
||||
*result = -error;
|
||||
return attr_system_list(vp, data, size, result);
|
||||
}
|
||||
|
||||
attrnames_t *
|
||||
attr_lookup_namespace(
|
||||
char *name,
|
||||
struct attrnames **names,
|
||||
int nnames)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nnames; i++)
|
||||
if (!strncmp(name, names[i]->attr_name, names[i]->attr_namelen))
|
||||
return names[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
attr_system_set(
|
||||
bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
|
||||
{
|
||||
attrnames_t *namesp;
|
||||
int error;
|
||||
|
||||
if (xflags & ATTR_CREATE)
|
||||
return -EINVAL;
|
||||
|
||||
namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
|
||||
if (!namesp)
|
||||
return -EOPNOTSUPP;
|
||||
error = namesp->attr_set(vp, name, data, size, xflags);
|
||||
if (!error)
|
||||
error = vn_revalidate(vp);
|
||||
return error;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
attr_system_get(
|
||||
bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
|
||||
{
|
||||
attrnames_t *namesp;
|
||||
|
||||
namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
|
||||
if (!namesp)
|
||||
return -EOPNOTSUPP;
|
||||
return namesp->attr_get(vp, name, data, size, xflags);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
attr_system_remove(
|
||||
bhv_vnode_t *vp, char *name, int xflags)
|
||||
{
|
||||
attrnames_t *namesp;
|
||||
|
||||
namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
|
||||
if (!namesp)
|
||||
return -EOPNOTSUPP;
|
||||
return namesp->attr_remove(vp, name, xflags);
|
||||
}
|
||||
|
||||
struct attrnames attr_system = {
|
||||
.attr_name = "system.",
|
||||
.attr_namelen = sizeof("system.") - 1,
|
||||
.attr_flag = ATTR_SYSTEM,
|
||||
.attr_get = attr_system_get,
|
||||
.attr_set = attr_system_set,
|
||||
.attr_remove = attr_system_remove,
|
||||
};
|
||||
|
||||
struct attrnames attr_trusted = {
|
||||
.attr_name = "trusted.",
|
||||
.attr_namelen = sizeof("trusted.") - 1,
|
||||
.attr_flag = ATTR_ROOT,
|
||||
.attr_get = attr_generic_get,
|
||||
.attr_set = attr_generic_set,
|
||||
.attr_remove = attr_generic_remove,
|
||||
};
|
||||
|
||||
struct attrnames attr_secure = {
|
||||
.attr_name = "security.",
|
||||
.attr_namelen = sizeof("security.") - 1,
|
||||
.attr_flag = ATTR_SECURE,
|
||||
.attr_get = attr_generic_get,
|
||||
.attr_set = attr_generic_set,
|
||||
.attr_remove = attr_generic_remove,
|
||||
};
|
||||
|
||||
struct attrnames attr_user = {
|
||||
.attr_name = "user.",
|
||||
.attr_namelen = sizeof("user.") - 1,
|
||||
.attr_get = attr_generic_get,
|
||||
.attr_set = attr_generic_set,
|
||||
.attr_remove = attr_generic_remove,
|
||||
};
|
||||
|
||||
struct attrnames *attr_namespaces[] =
|
||||
{ &attr_system, &attr_trusted, &attr_secure, &attr_user };
|
||||
|
|
|
@ -38,30 +38,14 @@
|
|||
struct cred;
|
||||
struct xfs_attr_list_context;
|
||||
|
||||
typedef int (*attrset_t)(bhv_vnode_t *, char *, void *, size_t, int);
|
||||
typedef int (*attrget_t)(bhv_vnode_t *, char *, void *, size_t, int);
|
||||
typedef int (*attrremove_t)(bhv_vnode_t *, char *, int);
|
||||
typedef int (*attrexists_t)(bhv_vnode_t *);
|
||||
|
||||
typedef struct attrnames {
|
||||
char * attr_name;
|
||||
unsigned int attr_namelen;
|
||||
unsigned int attr_flag;
|
||||
attrget_t attr_get;
|
||||
attrset_t attr_set;
|
||||
attrremove_t attr_remove;
|
||||
attrexists_t attr_exists;
|
||||
} attrnames_t;
|
||||
|
||||
#define ATTR_NAMECOUNT 4
|
||||
extern struct attrnames attr_user;
|
||||
extern struct attrnames attr_secure;
|
||||
extern struct attrnames attr_system;
|
||||
extern struct attrnames attr_trusted;
|
||||
extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
|
||||
|
||||
extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int);
|
||||
extern int attr_generic_list(bhv_vnode_t *, void *, size_t, int, ssize_t *);
|
||||
|
||||
#define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */
|
||||
#define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */
|
||||
|
@ -69,7 +53,6 @@ extern int attr_generic_list(bhv_vnode_t *, void *, size_t, int, ssize_t *);
|
|||
#define ATTR_SECURE 0x0008 /* use attrs in security namespace */
|
||||
#define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */
|
||||
#define ATTR_REPLACE 0x0020 /* pure set: fail if attr does not exist */
|
||||
#define ATTR_SYSTEM 0x0100 /* use attrs in system (pseudo) namespace */
|
||||
|
||||
#define ATTR_KERNACCESS 0x0400 /* [kernel] iaccess, inode held io-locked */
|
||||
#define ATTR_KERNOTIME 0x1000 /* [kernel] don't update inode timestamps */
|
||||
|
|
Loading…
Reference in a new issue