Commit 0ec58516 authored by Lachlan McIlroy's avatar Lachlan McIlroy Committed by Niv Sardi

[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: default avatarChristoph Hellwig <hch@infradead.org>
Signed-off-by: default avatarTim Shimmin <tes@sgi.com>
Signed-off-by: default avatarLachlan McIlroy <lachlan@sgi.com>
parent d532506c
...@@ -106,7 +106,8 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \ ...@@ -106,7 +106,8 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \
xfs_iops.o \ xfs_iops.o \
xfs_lrw.o \ xfs_lrw.o \
xfs_super.o \ xfs_super.o \
xfs_vnode.o) xfs_vnode.o \
xfs_xattr.o)
# Objects in support/ # Objects in support/
xfs-y += $(addprefix support/, \ xfs-y += $(addprefix support/, \
......
...@@ -275,7 +275,7 @@ xfs_vn_mknod( ...@@ -275,7 +275,7 @@ xfs_vn_mknod(
struct xfs_inode *ip = NULL; struct xfs_inode *ip = NULL;
xfs_acl_t *default_acl = NULL; xfs_acl_t *default_acl = NULL;
struct xfs_name name; struct xfs_name name;
attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; int (*test_default_acl)(struct inode *) = _ACL_DEFAULT_EXISTS;
int error; int error;
/* /*
...@@ -781,98 +781,6 @@ xfs_vn_truncate( ...@@ -781,98 +781,6 @@ xfs_vn_truncate(
WARN_ON(error); 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 STATIC long
xfs_vn_fallocate( xfs_vn_fallocate(
struct inode *inode, struct inode *inode,
...@@ -920,10 +828,10 @@ const struct inode_operations xfs_inode_operations = { ...@@ -920,10 +828,10 @@ const struct inode_operations xfs_inode_operations = {
.truncate = xfs_vn_truncate, .truncate = xfs_vn_truncate,
.getattr = xfs_vn_getattr, .getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr, .setattr = xfs_vn_setattr,
.setxattr = xfs_vn_setxattr, .setxattr = generic_setxattr,
.getxattr = xfs_vn_getxattr, .getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr, .listxattr = xfs_vn_listxattr,
.removexattr = xfs_vn_removexattr,
.fallocate = xfs_vn_fallocate, .fallocate = xfs_vn_fallocate,
}; };
...@@ -940,10 +848,10 @@ const struct inode_operations xfs_dir_inode_operations = { ...@@ -940,10 +848,10 @@ const struct inode_operations xfs_dir_inode_operations = {
.permission = xfs_vn_permission, .permission = xfs_vn_permission,
.getattr = xfs_vn_getattr, .getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr, .setattr = xfs_vn_setattr,
.setxattr = xfs_vn_setxattr, .setxattr = generic_setxattr,
.getxattr = xfs_vn_getxattr, .getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr, .listxattr = xfs_vn_listxattr,
.removexattr = xfs_vn_removexattr,
}; };
const struct inode_operations xfs_dir_ci_inode_operations = { const struct inode_operations xfs_dir_ci_inode_operations = {
...@@ -959,10 +867,10 @@ 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, .permission = xfs_vn_permission,
.getattr = xfs_vn_getattr, .getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr, .setattr = xfs_vn_setattr,
.setxattr = xfs_vn_setxattr, .setxattr = generic_setxattr,
.getxattr = xfs_vn_getxattr, .getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr, .listxattr = xfs_vn_listxattr,
.removexattr = xfs_vn_removexattr,
}; };
const struct inode_operations xfs_symlink_inode_operations = { const struct inode_operations xfs_symlink_inode_operations = {
...@@ -972,8 +880,8 @@ const struct inode_operations xfs_symlink_inode_operations = { ...@@ -972,8 +880,8 @@ const struct inode_operations xfs_symlink_inode_operations = {
.permission = xfs_vn_permission, .permission = xfs_vn_permission,
.getattr = xfs_vn_getattr, .getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr, .setattr = xfs_vn_setattr,
.setxattr = xfs_vn_setxattr, .setxattr = generic_setxattr,
.getxattr = xfs_vn_getxattr, .getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr, .listxattr = xfs_vn_listxattr,
.removexattr = xfs_vn_removexattr,
}; };
...@@ -27,6 +27,7 @@ extern const struct file_operations xfs_file_operations; ...@@ -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_dir_file_operations;
extern const struct file_operations xfs_invis_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; struct xfs_inode;
extern void xfs_ichgtime(struct xfs_inode *, int); extern void xfs_ichgtime(struct xfs_inode *, int);
......
...@@ -1766,6 +1766,7 @@ xfs_fs_fill_super( ...@@ -1766,6 +1766,7 @@ xfs_fs_fill_super(
goto out_free_mp; goto out_free_mp;
sb_min_blocksize(sb, BBSIZE); sb_min_blocksize(sb, BBSIZE);
sb->s_xattr = xfs_xattr_handlers;
sb->s_export_op = &xfs_export_operations; sb->s_export_op = &xfs_export_operations;
sb->s_qcop = &xfs_quotactl_operations; sb->s_qcop = &xfs_quotactl_operations;
sb->s_op = &xfs_super_operations; sb->s_op = &xfs_super_operations;
......
...@@ -110,6 +110,7 @@ extern void xfs_flush_device(struct xfs_inode *); ...@@ -110,6 +110,7 @@ extern void xfs_flush_device(struct xfs_inode *);
extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
extern const struct export_operations xfs_export_operations; 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)) #define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info))
......
...@@ -57,11 +57,6 @@ ...@@ -57,11 +57,6 @@
* Provide the external interfaces to manage attribute lists. * 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. * Function prototypes for the kernel.
*========================================================================*/ *========================================================================*/
...@@ -2378,270 +2373,3 @@ xfs_attr_trace_enter(int type, char *where, ...@@ -2378,270 +2373,3 @@ xfs_attr_trace_enter(int type, char *where,
(void *)a13, (void *)a14, (void *)a15); (void *)a13, (void *)a14, (void *)a15);
} }
#endif /* XFS_ATTR_TRACE */ #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 @@ ...@@ -38,30 +38,14 @@
struct cred; struct cred;
struct xfs_attr_list_context; 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 { typedef struct attrnames {
char * attr_name; char * attr_name;
unsigned int attr_namelen; 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; } attrnames_t;
#define ATTR_NAMECOUNT 4
extern struct attrnames attr_user; extern struct attrnames attr_user;
extern struct attrnames attr_secure; extern struct attrnames attr_secure;
extern struct attrnames attr_system;
extern struct attrnames attr_trusted; 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_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */
#define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */ #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 *); ...@@ -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_SECURE 0x0008 /* use attrs in security namespace */
#define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */ #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_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_KERNACCESS 0x0400 /* [kernel] iaccess, inode held io-locked */
#define ATTR_KERNOTIME 0x1000 /* [kernel] don't update inode timestamps */ #define ATTR_KERNOTIME 0x1000 /* [kernel] don't update inode timestamps */
......
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