* [PATCH] use generic_*xattr routines
@ 2008-04-30 11:22 Christoph Hellwig
2008-05-21 8:16 ` Christoph Hellwig
0 siblings, 1 reply; 11+ messages in thread
From: Christoph Hellwig @ 2008-04-30 11:22 UTC (permalink / raw)
To: xfs
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.
The code size reduction is not as big as I had hoped, but it's still a
worthwile cleanup.
I didn't managed to get rid of struct attrnames yet, as it's still used
to hack the Linux string prefixes into the output inside the lowest
level xattr code. I have some plans to clean that bit up aswell, but
that will have to wait for a while.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: linux-2.6-xfs/fs/xfs/Makefile
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/Makefile 2008-04-30 08:24:31.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/Makefile 2008-04-30 08:43:49.000000000 +0200
@@ -97,6 +97,7 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \
xfs_lrw.o \
xfs_super.o \
xfs_vnode.o \
+ xfs_xattr.o \
xfs_ksyms.o)
# Objects in support/
Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_iops.c 2008-04-30 08:35:43.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c 2008-04-30 08:43:49.000000000 +0200
@@ -282,7 +282,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;
/*
@@ -735,98 +735,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,
@@ -874,10 +782,10 @@ const struct inode_operations xfs_inode_
.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,
};
@@ -894,10 +802,10 @@ const struct inode_operations xfs_dir_in
.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 = {
@@ -907,8 +815,8 @@ const struct inode_operations xfs_symlin
.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,
};
Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_xattr.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_xattr.c 2008-04-30 12:55:33.000000000 +0200
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2008 Christoph Hellwig.
+ * Released under GPL v2.
+ */
+
+#include "xfs.h"
+#include "xfs_attr.h"
+#include "xfs_acl.h"
+#include "xfs_vnodeops.h"
+
+#include <linux/posix_acl_xattr.h>
+#include <linux/xattr.h>
+
+
+/*
+ * ACL handling. Should eventually be moved into xfs_acl.c
+ */
+
+static int
+xfs_decode_acl(const char *name)
+{
+ if (strcmp(name, "posix_acl_access") == 0)
+ return _ACL_TYPE_ACCESS;
+ else if (strcmp(name, "posix_acl_default") == 0)
+ return _ACL_TYPE_DEFAULT;
+ return -EINVAL;
+}
+
+static int
+xfs_xattr_system_get(struct inode *inode, const char *name,
+ void *buffer, size_t size)
+{
+ int acl;
+
+ acl = xfs_decode_acl(name);
+ if (acl < 0)
+ return acl;
+
+ return xfs_acl_vget(inode, buffer, size, acl);
+}
+
+static int
+xfs_xattr_system_set(struct inode *inode, const char *name,
+ const void *value, size_t size, int flags)
+{
+ int error, acl;
+
+ acl = xfs_decode_acl(name);
+ if (acl < 0)
+ return acl;
+ if (flags & XATTR_CREATE)
+ return -EINVAL;
+
+ if (!value)
+ return xfs_acl_vremove(inode, acl);
+
+ error = xfs_acl_vset(inode, (void *)value, size, acl);
+ if (!error)
+ vn_revalidate(inode);
+ return error;
+}
+
+static struct xattr_handler xfs_xattr_system_handler = {
+ .prefix = XATTR_SYSTEM_PREFIX,
+ .get = xfs_xattr_system_get,
+ .set = xfs_xattr_system_set,
+};
+
+
+/*
+ * Real xattr handling. The only difference between the namespaces is
+ * a flag passed to the low-level attr code.
+ */
+
+static int
+__xfs_xattr_get(struct inode *inode, const char *name,
+ void *value, size_t size, int xflags)
+{
+ struct xfs_inode *ip = XFS_I(inode);
+ int error, asize = size;
+
+ if (strcmp(name, "") == 0)
+ return -EINVAL;
+
+ /* Convert Linux syscall to XFS internal ATTR flags */
+ if (!size) {
+ xflags |= ATTR_KERNOVAL;
+ value = NULL;
+ }
+
+ error = -xfs_attr_get(ip, name, value, &asize, xflags);
+ if (error)
+ return error;
+ return asize;
+}
+
+static int
+__xfs_xattr_set(struct inode *inode, const char *name, const void *value,
+ size_t size, int flags, int xflags)
+{
+ struct xfs_inode *ip = XFS_I(inode);
+
+ if (strcmp(name, "") == 0)
+ return -EINVAL;
+
+ /* Convert Linux syscall to XFS internal ATTR flags */
+ if (flags & XATTR_CREATE)
+ xflags |= ATTR_CREATE;
+ if (flags & XATTR_REPLACE)
+ xflags |= ATTR_REPLACE;
+
+ if (!value)
+ return -xfs_attr_remove(ip, name, xflags);
+ return -xfs_attr_set(ip, name, (void *)value, size, xflags);
+}
+
+static int
+xfs_xattr_user_get(struct inode *inode, const char *name,
+ void *value, size_t size)
+{
+ return __xfs_xattr_get(inode, name, value, size, 0);
+}
+
+static int
+xfs_xattr_user_set(struct inode *inode, const char *name,
+ const void *value, size_t size, int flags)
+{
+ return __xfs_xattr_set(inode, name, value, size, flags, 0);
+}
+
+struct attrnames attr_user = {
+ .attr_name = "user.",
+ .attr_namelen = sizeof("user.") - 1,
+};
+
+static struct xattr_handler xfs_xattr_user_handler = {
+ .prefix = XATTR_USER_PREFIX,
+ .get = xfs_xattr_user_get,
+ .set = xfs_xattr_user_set,
+};
+
+
+static int
+xfs_xattr_trusted_get(struct inode *inode, const char *name,
+ void *value, size_t size)
+{
+ return __xfs_xattr_get(inode, name, value, size, ATTR_ROOT);
+}
+
+static int
+xfs_xattr_trusted_set(struct inode *inode, const char *name,
+ const void *value, size_t size, int flags)
+{
+ return __xfs_xattr_set(inode, name, value, size, flags, ATTR_ROOT);
+}
+
+struct attrnames attr_trusted = {
+ .attr_name = "trusted.",
+ .attr_namelen = sizeof("trusted.") - 1,
+};
+
+static struct xattr_handler xfs_xattr_trusted_handler = {
+ .prefix = XATTR_TRUSTED_PREFIX,
+ .get = xfs_xattr_trusted_get,
+ .set = xfs_xattr_trusted_set,
+};
+
+
+static int
+xfs_xattr_secure_get(struct inode *inode, const char *name,
+ void *value, size_t size)
+{
+ return __xfs_xattr_get(inode, name, value, size, ATTR_SECURE);
+}
+
+static int
+xfs_xattr_secure_set(struct inode *inode, const char *name,
+ const void *value, size_t size, int flags)
+{
+ return __xfs_xattr_set(inode, name, value, size, flags, ATTR_SECURE);
+}
+
+struct attrnames attr_secure = {
+ .attr_name = "security.",
+ .attr_namelen = sizeof("security.") - 1,
+};
+
+static struct xattr_handler xfs_xattr_security_handler = {
+ .prefix = XATTR_SECURITY_PREFIX,
+ .get = xfs_xattr_secure_get,
+ .set = xfs_xattr_secure_set,
+};
+
+
+struct xattr_handler *xfs_xattr_handlers[] = {
+ &xfs_xattr_user_handler,
+ &xfs_xattr_trusted_handler,
+ &xfs_xattr_security_handler,
+ &xfs_xattr_system_handler,
+ NULL
+};
+
+static int
+list_one_attr(const char *name, const size_t len, void *data,
+ size_t size, ssize_t *result)
+{
+ char *p = data + *result;
+
+ *result += len;
+ if (!size)
+ return 0;
+ if (*result > size)
+ return -ERANGE;
+
+ strcpy(p, name);
+ p += len;
+ return 0;
+}
+
+ssize_t
+xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size)
+{
+ struct inode *inode = dentry->d_inode;
+ struct xfs_inode *ip = XFS_I(inode);
+ attrlist_cursor_kern_t cursor = { 0 };
+ int error, xflags;
+ ssize_t result;
+
+ xflags = ATTR_KERNAMELS;
+ if (!size)
+ xflags |= ATTR_KERNOVAL;
+
+ if (capable(CAP_SYS_ADMIN))
+ xflags |= ATTR_KERNFULLS;
+ else
+ xflags |= ATTR_KERNORMALS;
+
+
+ /*
+ * First read the regular on-disk attributes.
+ */
+ result = -xfs_attr_list(ip, data, size, xflags, &cursor);
+ if (result < 0)
+ return result;
+
+ /*
+ * Then add the two synthetic ACL attributes.
+ */
+ if (xfs_acl_vhasacl_access(inode)) {
+ error = list_one_attr(POSIX_ACL_XATTR_ACCESS,
+ strlen(POSIX_ACL_XATTR_ACCESS) + 1,
+ data, size, &result);
+ if (error)
+ return error;
+ }
+
+ if (xfs_acl_vhasacl_default(inode)) {
+ error = list_one_attr(POSIX_ACL_XATTR_DEFAULT,
+ strlen(POSIX_ACL_XATTR_DEFAULT) + 1,
+ data, size, &result);
+ if (error)
+ return error;
+ }
+
+ return result;
+}
Index: linux-2.6-xfs/fs/xfs/xfs_attr.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_attr.c 2008-04-30 08:35:43.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_attr.c 2008-04-30 08:43:49.000000000 +0200
@@ -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.
*========================================================================*/
@@ -2435,270 +2430,3 @@ xfs_attr_trace_enter(int type, char *whe
(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 };
Index: linux-2.6-xfs/fs/xfs/xfs_attr.h
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_attr.h 2008-04-30 08:35:43.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_attr.h 2008-04-30 08:43:49.000000000 +0200
@@ -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
#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 */
Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.h
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_iops.h 2008-04-30 08:24:31.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.h 2008-04-30 08:43:49.000000000 +0200
@@ -26,6 +26,7 @@ extern const struct file_operations xfs_
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);
Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_super.c 2008-04-30 08:24:32.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.c 2008-04-30 08:43:49.000000000 +0200
@@ -1328,6 +1328,7 @@ xfs_fs_fill_super(
goto fail_vfsop;
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;
Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.h
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_super.h 2008-04-30 08:24:31.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.h 2008-04-30 08:43:49.000000000 +0200
@@ -84,6 +84,7 @@ extern void xfs_blkdev_put(struct block_
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))
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH] use generic_*xattr routines 2008-04-30 11:22 [PATCH] use generic_*xattr routines Christoph Hellwig @ 2008-05-21 8:16 ` Christoph Hellwig 2008-05-22 7:17 ` Timothy Shimmin 2008-05-23 5:22 ` Timothy Shimmin 0 siblings, 2 replies; 11+ messages in thread From: Christoph Hellwig @ 2008-05-21 8:16 UTC (permalink / raw) To: xfs On Wed, Apr 30, 2008 at 01:22:17PM +0200, Christoph Hellwig wrote: > 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. > > The code size reduction is not as big as I had hoped, but it's still a > worthwile cleanup. > > I didn't managed to get rid of struct attrnames yet, as it's still used > to hack the Linux string prefixes into the output inside the lowest > level xattr code. I have some plans to clean that bit up aswell, but > that will have to wait for a while. Updated on top of the case-insensitive filename changes: Signed-off-by: Christoph Hellwig <hch@lst.de> Index: linux-2.6-xfs/fs/xfs/Makefile =================================================================== --- linux-2.6-xfs.orig/fs/xfs/Makefile 2008-05-21 09:59:53.000000000 +0200 +++ linux-2.6-xfs/fs/xfs/Makefile 2008-05-21 10:06:38.000000000 +0200 @@ -97,6 +97,7 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \ xfs_lrw.o \ xfs_super.o \ xfs_vnode.o \ + xfs_xattr.o \ xfs_ksyms.o) # Objects in support/ Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c =================================================================== --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_iops.c 2008-05-21 09:59:53.000000000 +0200 +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c 2008-05-21 10:14:54.000000000 +0200 @@ -282,7 +282,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; /* @@ -771,98 +771,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, @@ -910,10 +818,10 @@ const struct inode_operations xfs_inode_ .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, }; @@ -930,10 +838,10 @@ const struct inode_operations xfs_dir_in .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 = { @@ -949,10 +857,10 @@ const struct inode_operations xfs_dir_ci .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 = { @@ -962,8 +870,8 @@ const struct inode_operations xfs_symlin .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, }; Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_xattr.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_xattr.c 2008-05-21 10:06:38.000000000 +0200 @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2008 Christoph Hellwig. + * Released under GPL v2. + */ + +#include "xfs.h" +#include "xfs_attr.h" +#include "xfs_acl.h" +#include "xfs_vnodeops.h" + +#include <linux/posix_acl_xattr.h> +#include <linux/xattr.h> + + +/* + * ACL handling. Should eventually be moved into xfs_acl.c + */ + +static int +xfs_decode_acl(const char *name) +{ + if (strcmp(name, "posix_acl_access") == 0) + return _ACL_TYPE_ACCESS; + else if (strcmp(name, "posix_acl_default") == 0) + return _ACL_TYPE_DEFAULT; + return -EINVAL; +} + +static int +xfs_xattr_system_get(struct inode *inode, const char *name, + void *buffer, size_t size) +{ + int acl; + + acl = xfs_decode_acl(name); + if (acl < 0) + return acl; + + return xfs_acl_vget(inode, buffer, size, acl); +} + +static int +xfs_xattr_system_set(struct inode *inode, const char *name, + const void *value, size_t size, int flags) +{ + int error, acl; + + acl = xfs_decode_acl(name); + if (acl < 0) + return acl; + if (flags & XATTR_CREATE) + return -EINVAL; + + if (!value) + return xfs_acl_vremove(inode, acl); + + error = xfs_acl_vset(inode, (void *)value, size, acl); + if (!error) + vn_revalidate(inode); + return error; +} + +static struct xattr_handler xfs_xattr_system_handler = { + .prefix = XATTR_SYSTEM_PREFIX, + .get = xfs_xattr_system_get, + .set = xfs_xattr_system_set, +}; + + +/* + * Real xattr handling. The only difference between the namespaces is + * a flag passed to the low-level attr code. + */ + +static int +__xfs_xattr_get(struct inode *inode, const char *name, + void *value, size_t size, int xflags) +{ + struct xfs_inode *ip = XFS_I(inode); + int error, asize = size; + + if (strcmp(name, "") == 0) + return -EINVAL; + + /* Convert Linux syscall to XFS internal ATTR flags */ + if (!size) { + xflags |= ATTR_KERNOVAL; + value = NULL; + } + + error = -xfs_attr_get(ip, name, value, &asize, xflags); + if (error) + return error; + return asize; +} + +static int +__xfs_xattr_set(struct inode *inode, const char *name, const void *value, + size_t size, int flags, int xflags) +{ + struct xfs_inode *ip = XFS_I(inode); + + if (strcmp(name, "") == 0) + return -EINVAL; + + /* Convert Linux syscall to XFS internal ATTR flags */ + if (flags & XATTR_CREATE) + xflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) + xflags |= ATTR_REPLACE; + + if (!value) + return -xfs_attr_remove(ip, name, xflags); + return -xfs_attr_set(ip, name, (void *)value, size, xflags); +} + +static int +xfs_xattr_user_get(struct inode *inode, const char *name, + void *value, size_t size) +{ + return __xfs_xattr_get(inode, name, value, size, 0); +} + +static int +xfs_xattr_user_set(struct inode *inode, const char *name, + const void *value, size_t size, int flags) +{ + return __xfs_xattr_set(inode, name, value, size, flags, 0); +} + +struct attrnames attr_user = { + .attr_name = "user.", + .attr_namelen = sizeof("user.") - 1, +}; + +static struct xattr_handler xfs_xattr_user_handler = { + .prefix = XATTR_USER_PREFIX, + .get = xfs_xattr_user_get, + .set = xfs_xattr_user_set, +}; + + +static int +xfs_xattr_trusted_get(struct inode *inode, const char *name, + void *value, size_t size) +{ + return __xfs_xattr_get(inode, name, value, size, ATTR_ROOT); +} + +static int +xfs_xattr_trusted_set(struct inode *inode, const char *name, + const void *value, size_t size, int flags) +{ + return __xfs_xattr_set(inode, name, value, size, flags, ATTR_ROOT); +} + +struct attrnames attr_trusted = { + .attr_name = "trusted.", + .attr_namelen = sizeof("trusted.") - 1, +}; + +static struct xattr_handler xfs_xattr_trusted_handler = { + .prefix = XATTR_TRUSTED_PREFIX, + .get = xfs_xattr_trusted_get, + .set = xfs_xattr_trusted_set, +}; + + +static int +xfs_xattr_secure_get(struct inode *inode, const char *name, + void *value, size_t size) +{ + return __xfs_xattr_get(inode, name, value, size, ATTR_SECURE); +} + +static int +xfs_xattr_secure_set(struct inode *inode, const char *name, + const void *value, size_t size, int flags) +{ + return __xfs_xattr_set(inode, name, value, size, flags, ATTR_SECURE); +} + +struct attrnames attr_secure = { + .attr_name = "security.", + .attr_namelen = sizeof("security.") - 1, +}; + +static struct xattr_handler xfs_xattr_security_handler = { + .prefix = XATTR_SECURITY_PREFIX, + .get = xfs_xattr_secure_get, + .set = xfs_xattr_secure_set, +}; + + +struct xattr_handler *xfs_xattr_handlers[] = { + &xfs_xattr_user_handler, + &xfs_xattr_trusted_handler, + &xfs_xattr_security_handler, + &xfs_xattr_system_handler, + NULL +}; + +static int +list_one_attr(const char *name, const size_t len, void *data, + size_t size, ssize_t *result) +{ + char *p = data + *result; + + *result += len; + if (!size) + return 0; + if (*result > size) + return -ERANGE; + + strcpy(p, name); + p += len; + return 0; +} + +ssize_t +xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size) +{ + struct inode *inode = dentry->d_inode; + struct xfs_inode *ip = XFS_I(inode); + attrlist_cursor_kern_t cursor = { 0 }; + int error, xflags; + ssize_t result; + + xflags = ATTR_KERNAMELS; + if (!size) + xflags |= ATTR_KERNOVAL; + + if (capable(CAP_SYS_ADMIN)) + xflags |= ATTR_KERNFULLS; + else + xflags |= ATTR_KERNORMALS; + + + /* + * First read the regular on-disk attributes. + */ + result = -xfs_attr_list(ip, data, size, xflags, &cursor); + if (result < 0) + return result; + + /* + * Then add the two synthetic ACL attributes. + */ + if (xfs_acl_vhasacl_access(inode)) { + error = list_one_attr(POSIX_ACL_XATTR_ACCESS, + strlen(POSIX_ACL_XATTR_ACCESS) + 1, + data, size, &result); + if (error) + return error; + } + + if (xfs_acl_vhasacl_default(inode)) { + error = list_one_attr(POSIX_ACL_XATTR_DEFAULT, + strlen(POSIX_ACL_XATTR_DEFAULT) + 1, + data, size, &result); + if (error) + return error; + } + + return result; +} Index: linux-2.6-xfs/fs/xfs/xfs_attr.c =================================================================== --- linux-2.6-xfs.orig/fs/xfs/xfs_attr.c 2008-05-21 09:59:53.000000000 +0200 +++ linux-2.6-xfs/fs/xfs/xfs_attr.c 2008-05-21 10:06:38.000000000 +0200 @@ -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 *whe (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 }; Index: linux-2.6-xfs/fs/xfs/xfs_attr.h =================================================================== --- linux-2.6-xfs.orig/fs/xfs/xfs_attr.h 2008-05-21 09:59:53.000000000 +0200 +++ linux-2.6-xfs/fs/xfs/xfs_attr.h 2008-05-21 10:06:38.000000000 +0200 @@ -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 #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 */ Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.h =================================================================== --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_iops.h 2008-05-21 09:59:53.000000000 +0200 +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.h 2008-05-21 10:14:20.000000000 +0200 @@ -27,6 +27,7 @@ extern const struct file_operations xfs_ 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); Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.c =================================================================== --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_super.c 2008-05-21 09:59:53.000000000 +0200 +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.c 2008-05-21 10:14:20.000000000 +0200 @@ -1767,6 +1767,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; Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.h =================================================================== --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_super.h 2008-05-21 09:59:53.000000000 +0200 +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.h 2008-05-21 10:14:20.000000000 +0200 @@ -81,6 +81,7 @@ extern void xfs_flush_device(struct xfs_ 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)) ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] use generic_*xattr routines 2008-05-21 8:16 ` Christoph Hellwig @ 2008-05-22 7:17 ` Timothy Shimmin 2008-05-23 5:22 ` Timothy Shimmin 1 sibling, 0 replies; 11+ messages in thread From: Timothy Shimmin @ 2008-05-22 7:17 UTC (permalink / raw) To: Christoph Hellwig; +Cc: xfs Looking at this now and will reply tomorrow. --Tim Christoph Hellwig wrote: > On Wed, Apr 30, 2008 at 01:22:17PM +0200, Christoph Hellwig wrote: >> 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. >> >> The code size reduction is not as big as I had hoped, but it's still a >> worthwile cleanup. >> >> I didn't managed to get rid of struct attrnames yet, as it's still used >> to hack the Linux string prefixes into the output inside the lowest >> level xattr code. I have some plans to clean that bit up aswell, but >> that will have to wait for a while. > > Updated on top of the case-insensitive filename changes: > > > Signed-off-by: Christoph Hellwig <hch@lst.de> > > Index: linux-2.6-xfs/fs/xfs/Makefile > =================================================================== > --- linux-2.6-xfs.orig/fs/xfs/Makefile 2008-05-21 09:59:53.000000000 +0200 > +++ linux-2.6-xfs/fs/xfs/Makefile 2008-05-21 10:06:38.000000000 +0200 > @@ -97,6 +97,7 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \ > xfs_lrw.o \ > xfs_super.o \ > xfs_vnode.o \ > + xfs_xattr.o \ > xfs_ksyms.o) > > # Objects in support/ > Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c > =================================================================== > --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_iops.c 2008-05-21 09:59:53.000000000 +0200 > +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c 2008-05-21 10:14:54.000000000 +0200 > @@ -282,7 +282,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; > > /* > @@ -771,98 +771,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, > @@ -910,10 +818,10 @@ const struct inode_operations xfs_inode_ > .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, > }; > > @@ -930,10 +838,10 @@ const struct inode_operations xfs_dir_in > .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 = { > @@ -949,10 +857,10 @@ const struct inode_operations xfs_dir_ci > .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 = { > @@ -962,8 +870,8 @@ const struct inode_operations xfs_symlin > .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, > }; > Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_xattr.c > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_xattr.c 2008-05-21 10:06:38.000000000 +0200 > @@ -0,0 +1,266 @@ > +/* > + * Copyright (C) 2008 Christoph Hellwig. > + * Released under GPL v2. > + */ > + > +#include "xfs.h" > +#include "xfs_attr.h" > +#include "xfs_acl.h" > +#include "xfs_vnodeops.h" > + > +#include <linux/posix_acl_xattr.h> > +#include <linux/xattr.h> > + > + > +/* > + * ACL handling. Should eventually be moved into xfs_acl.c > + */ > + > +static int > +xfs_decode_acl(const char *name) > +{ > + if (strcmp(name, "posix_acl_access") == 0) > + return _ACL_TYPE_ACCESS; > + else if (strcmp(name, "posix_acl_default") == 0) > + return _ACL_TYPE_DEFAULT; > + return -EINVAL; > +} > + > +static int > +xfs_xattr_system_get(struct inode *inode, const char *name, > + void *buffer, size_t size) > +{ > + int acl; > + > + acl = xfs_decode_acl(name); > + if (acl < 0) > + return acl; > + > + return xfs_acl_vget(inode, buffer, size, acl); > +} > + > +static int > +xfs_xattr_system_set(struct inode *inode, const char *name, > + const void *value, size_t size, int flags) > +{ > + int error, acl; > + > + acl = xfs_decode_acl(name); > + if (acl < 0) > + return acl; > + if (flags & XATTR_CREATE) > + return -EINVAL; > + > + if (!value) > + return xfs_acl_vremove(inode, acl); > + > + error = xfs_acl_vset(inode, (void *)value, size, acl); > + if (!error) > + vn_revalidate(inode); > + return error; > +} > + > +static struct xattr_handler xfs_xattr_system_handler = { > + .prefix = XATTR_SYSTEM_PREFIX, > + .get = xfs_xattr_system_get, > + .set = xfs_xattr_system_set, > +}; > + > + > +/* > + * Real xattr handling. The only difference between the namespaces is > + * a flag passed to the low-level attr code. > + */ > + > +static int > +__xfs_xattr_get(struct inode *inode, const char *name, > + void *value, size_t size, int xflags) > +{ > + struct xfs_inode *ip = XFS_I(inode); > + int error, asize = size; > + > + if (strcmp(name, "") == 0) > + return -EINVAL; > + > + /* Convert Linux syscall to XFS internal ATTR flags */ > + if (!size) { > + xflags |= ATTR_KERNOVAL; > + value = NULL; > + } > + > + error = -xfs_attr_get(ip, name, value, &asize, xflags); > + if (error) > + return error; > + return asize; > +} > + > +static int > +__xfs_xattr_set(struct inode *inode, const char *name, const void *value, > + size_t size, int flags, int xflags) > +{ > + struct xfs_inode *ip = XFS_I(inode); > + > + if (strcmp(name, "") == 0) > + return -EINVAL; > + > + /* Convert Linux syscall to XFS internal ATTR flags */ > + if (flags & XATTR_CREATE) > + xflags |= ATTR_CREATE; > + if (flags & XATTR_REPLACE) > + xflags |= ATTR_REPLACE; > + > + if (!value) > + return -xfs_attr_remove(ip, name, xflags); > + return -xfs_attr_set(ip, name, (void *)value, size, xflags); > +} > + > +static int > +xfs_xattr_user_get(struct inode *inode, const char *name, > + void *value, size_t size) > +{ > + return __xfs_xattr_get(inode, name, value, size, 0); > +} > + > +static int > +xfs_xattr_user_set(struct inode *inode, const char *name, > + const void *value, size_t size, int flags) > +{ > + return __xfs_xattr_set(inode, name, value, size, flags, 0); > +} > + > +struct attrnames attr_user = { > + .attr_name = "user.", > + .attr_namelen = sizeof("user.") - 1, > +}; > + > +static struct xattr_handler xfs_xattr_user_handler = { > + .prefix = XATTR_USER_PREFIX, > + .get = xfs_xattr_user_get, > + .set = xfs_xattr_user_set, > +}; > + > + > +static int > +xfs_xattr_trusted_get(struct inode *inode, const char *name, > + void *value, size_t size) > +{ > + return __xfs_xattr_get(inode, name, value, size, ATTR_ROOT); > +} > + > +static int > +xfs_xattr_trusted_set(struct inode *inode, const char *name, > + const void *value, size_t size, int flags) > +{ > + return __xfs_xattr_set(inode, name, value, size, flags, ATTR_ROOT); > +} > + > +struct attrnames attr_trusted = { > + .attr_name = "trusted.", > + .attr_namelen = sizeof("trusted.") - 1, > +}; > + > +static struct xattr_handler xfs_xattr_trusted_handler = { > + .prefix = XATTR_TRUSTED_PREFIX, > + .get = xfs_xattr_trusted_get, > + .set = xfs_xattr_trusted_set, > +}; > + > + > +static int > +xfs_xattr_secure_get(struct inode *inode, const char *name, > + void *value, size_t size) > +{ > + return __xfs_xattr_get(inode, name, value, size, ATTR_SECURE); > +} > + > +static int > +xfs_xattr_secure_set(struct inode *inode, const char *name, > + const void *value, size_t size, int flags) > +{ > + return __xfs_xattr_set(inode, name, value, size, flags, ATTR_SECURE); > +} > + > +struct attrnames attr_secure = { > + .attr_name = "security.", > + .attr_namelen = sizeof("security.") - 1, > +}; > + > +static struct xattr_handler xfs_xattr_security_handler = { > + .prefix = XATTR_SECURITY_PREFIX, > + .get = xfs_xattr_secure_get, > + .set = xfs_xattr_secure_set, > +}; > + > + > +struct xattr_handler *xfs_xattr_handlers[] = { > + &xfs_xattr_user_handler, > + &xfs_xattr_trusted_handler, > + &xfs_xattr_security_handler, > + &xfs_xattr_system_handler, > + NULL > +}; > + > +static int > +list_one_attr(const char *name, const size_t len, void *data, > + size_t size, ssize_t *result) > +{ > + char *p = data + *result; > + > + *result += len; > + if (!size) > + return 0; > + if (*result > size) > + return -ERANGE; > + > + strcpy(p, name); > + p += len; > + return 0; > +} > + > +ssize_t > +xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size) > +{ > + struct inode *inode = dentry->d_inode; > + struct xfs_inode *ip = XFS_I(inode); > + attrlist_cursor_kern_t cursor = { 0 }; > + int error, xflags; > + ssize_t result; > + > + xflags = ATTR_KERNAMELS; > + if (!size) > + xflags |= ATTR_KERNOVAL; > + > + if (capable(CAP_SYS_ADMIN)) > + xflags |= ATTR_KERNFULLS; > + else > + xflags |= ATTR_KERNORMALS; > + > + > + /* > + * First read the regular on-disk attributes. > + */ > + result = -xfs_attr_list(ip, data, size, xflags, &cursor); > + if (result < 0) > + return result; > + > + /* > + * Then add the two synthetic ACL attributes. > + */ > + if (xfs_acl_vhasacl_access(inode)) { > + error = list_one_attr(POSIX_ACL_XATTR_ACCESS, > + strlen(POSIX_ACL_XATTR_ACCESS) + 1, > + data, size, &result); > + if (error) > + return error; > + } > + > + if (xfs_acl_vhasacl_default(inode)) { > + error = list_one_attr(POSIX_ACL_XATTR_DEFAULT, > + strlen(POSIX_ACL_XATTR_DEFAULT) + 1, > + data, size, &result); > + if (error) > + return error; > + } > + > + return result; > +} > Index: linux-2.6-xfs/fs/xfs/xfs_attr.c > =================================================================== > --- linux-2.6-xfs.orig/fs/xfs/xfs_attr.c 2008-05-21 09:59:53.000000000 +0200 > +++ linux-2.6-xfs/fs/xfs/xfs_attr.c 2008-05-21 10:06:38.000000000 +0200 > @@ -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 *whe > (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 }; > Index: linux-2.6-xfs/fs/xfs/xfs_attr.h > =================================================================== > --- linux-2.6-xfs.orig/fs/xfs/xfs_attr.h 2008-05-21 09:59:53.000000000 +0200 > +++ linux-2.6-xfs/fs/xfs/xfs_attr.h 2008-05-21 10:06:38.000000000 +0200 > @@ -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 > #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 */ > Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.h > =================================================================== > --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_iops.h 2008-05-21 09:59:53.000000000 +0200 > +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.h 2008-05-21 10:14:20.000000000 +0200 > @@ -27,6 +27,7 @@ extern const struct file_operations xfs_ > 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); > Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.c > =================================================================== > --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_super.c 2008-05-21 09:59:53.000000000 +0200 > +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.c 2008-05-21 10:14:20.000000000 +0200 > @@ -1767,6 +1767,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; > Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.h > =================================================================== > --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_super.h 2008-05-21 09:59:53.000000000 +0200 > +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.h 2008-05-21 10:14:20.000000000 +0200 > @@ -81,6 +81,7 @@ extern void xfs_flush_device(struct xfs_ > 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)) > > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] use generic_*xattr routines 2008-05-21 8:16 ` Christoph Hellwig 2008-05-22 7:17 ` Timothy Shimmin @ 2008-05-23 5:22 ` Timothy Shimmin 2008-05-23 5:48 ` Christoph Hellwig 1 sibling, 1 reply; 11+ messages in thread From: Timothy Shimmin @ 2008-05-23 5:22 UTC (permalink / raw) To: Christoph Hellwig; +Cc: xfs Hi Christoph, Looks reasonable to me. In list_one_attr(), which looks based on attr_generic_listadd(), it does a final: > + p += len; which seems useless. An aside, I noticed in passing (which was in existing code), how we call vn_revalidate in xfs_xattr_system_set(). I presume this is because we call xfs_acl_setmode() in xfs_acl_vset() when we want to sync the mode bits to the ACL. If this is the case, then I think it would have been clearer to put vn_revalidate() in the vicinity of xfs_acl_setmode(). Or is there some other reason? I'll test it out. Thanks, Tim. Christoph Hellwig wrote: > On Wed, Apr 30, 2008 at 01:22:17PM +0200, Christoph Hellwig wrote: >> 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. >> >> The code size reduction is not as big as I had hoped, but it's still a >> worthwile cleanup. >> >> I didn't managed to get rid of struct attrnames yet, as it's still used >> to hack the Linux string prefixes into the output inside the lowest >> level xattr code. I have some plans to clean that bit up aswell, but >> that will have to wait for a while. > > Updated on top of the case-insensitive filename changes: > > Just my notes (for my reference)... > Signed-off-by: Christoph Hellwig <hch@lst.de> > > Index: linux-2.6-xfs/fs/xfs/Makefile > =================================================================== > --- linux-2.6-xfs.orig/fs/xfs/Makefile 2008-05-21 09:59:53.000000000 +0200 > +++ linux-2.6-xfs/fs/xfs/Makefile 2008-05-21 10:06:38.000000000 +0200 > @@ -97,6 +97,7 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \ > xfs_lrw.o \ > xfs_super.o \ > xfs_vnode.o \ > + xfs_xattr.o \ > xfs_ksyms.o) > Okay adding in a linux-2.6/xfs_xattr.c (slightly different name than xfs_attr.c) > # Objects in support/ > Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c > =================================================================== > --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_iops.c 2008-05-21 09:59:53.000000000 +0200 > +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c 2008-05-21 10:14:54.000000000 +0200 > @@ -282,7 +282,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; > > /* > @@ -771,98 +771,6 @@ xfs_vn_truncate( > WARN_ON(error); > } > So you are removing xfs_vn_setxattr, xfs_vn_getxattr, and xfs_vn_removexattr and calling generic_xattr and retaining the code in xattr_handler's. You leave xfs_vn_listxattr alone. Just like ext3 does its own. Ok. > -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, > @@ -910,10 +818,10 @@ const struct inode_operations xfs_inode_ > .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, > }; > > @@ -930,10 +838,10 @@ const struct inode_operations xfs_dir_in > .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 = { > @@ -949,10 +857,10 @@ const struct inode_operations xfs_dir_ci > .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 = { > @@ -962,8 +870,8 @@ const struct inode_operations xfs_symlin > .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, > }; > Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_xattr.c > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_xattr.c 2008-05-21 10:06:38.000000000 +0200 > @@ -0,0 +1,266 @@ > +/* > + * Copyright (C) 2008 Christoph Hellwig. > + * Released under GPL v2. > + */ > + > +#include "xfs.h" > +#include "xfs_attr.h" > +#include "xfs_acl.h" > +#include "xfs_vnodeops.h" > + > +#include <linux/posix_acl_xattr.h> > +#include <linux/xattr.h> > + > + > +/* > + * ACL handling. Should eventually be moved into xfs_acl.c > + */ > + > +static int > +xfs_decode_acl(const char *name) > +{ > + if (strcmp(name, "posix_acl_access") == 0) > + return _ACL_TYPE_ACCESS; > + else if (strcmp(name, "posix_acl_default") == 0) > + return _ACL_TYPE_DEFAULT; > + return -EINVAL; > +} > + Fine. > +static int > +xfs_xattr_system_get(struct inode *inode, const char *name, > + void *buffer, size_t size) > +{ > + int acl; > + > + acl = xfs_decode_acl(name); > + if (acl < 0) > + return acl; > + > + return xfs_acl_vget(inode, buffer, size, acl); > +} > + Fine. Seems a little funny as we are calling it a system EA but then directly calling the acl code. i.e. acknowledging, I guess, that we only have Posix ACLs as system EAs. Almost could call it xfs_xattr_acl_get(). It saves on one liner wrappers I guess. > +static int > +xfs_xattr_system_set(struct inode *inode, const char *name, > + const void *value, size_t size, int flags) > +{ > + int error, acl; > + > + acl = xfs_decode_acl(name); > + if (acl < 0) > + return acl; > + if (flags & XATTR_CREATE) > + return -EINVAL; > + > + if (!value) > + return xfs_acl_vremove(inode, acl); > + > + error = xfs_acl_vset(inode, (void *)value, size, acl); > + if (!error) > + vn_revalidate(inode); > + return error; > +} > + Why the vn_revalidate? b/c we did that in xfs_attr.c/attr_system_set(). It updates the linux inode fields based on the xfs inode fields. I wonder why. Because we can modify an ACL which can cause mode changes? in the call to xfs_acl_setmode(vp, xfs_acl, &basicperms) I wonder why we do it at this point though as it doesn't look so obvious. > +static struct xattr_handler xfs_xattr_system_handler = { > + .prefix = XATTR_SYSTEM_PREFIX, > + .get = xfs_xattr_system_get, > + .set = xfs_xattr_system_set, > +}; > + > + > +/* > + * Real xattr handling. The only difference between the namespaces is > + * a flag passed to the low-level attr code. > + */ > + > +static int > +__xfs_xattr_get(struct inode *inode, const char *name, > + void *value, size_t size, int xflags) > +{ > + struct xfs_inode *ip = XFS_I(inode); > + int error, asize = size; > + > + if (strcmp(name, "") == 0) > + return -EINVAL; > + > + /* Convert Linux syscall to XFS internal ATTR flags */ > + if (!size) { > + xflags |= ATTR_KERNOVAL; > + value = NULL; > + } > + > + error = -xfs_attr_get(ip, name, value, &asize, xflags); > + if (error) > + return error; > + return asize; > +} > + Ok. > +static int > +__xfs_xattr_set(struct inode *inode, const char *name, const void *value, > + size_t size, int flags, int xflags) > +{ > + struct xfs_inode *ip = XFS_I(inode); > + > + if (strcmp(name, "") == 0) > + return -EINVAL; > + > + /* Convert Linux syscall to XFS internal ATTR flags */ > + if (flags & XATTR_CREATE) > + xflags |= ATTR_CREATE; > + if (flags & XATTR_REPLACE) > + xflags |= ATTR_REPLACE; > + > + if (!value) > + return -xfs_attr_remove(ip, name, xflags); > + return -xfs_attr_set(ip, name, (void *)value, size, xflags); > +} > + Ok. > +static int > +xfs_xattr_user_get(struct inode *inode, const char *name, > + void *value, size_t size) > +{ > + return __xfs_xattr_get(inode, name, value, size, 0); > +} > + > +static int > +xfs_xattr_user_set(struct inode *inode, const char *name, > + const void *value, size_t size, int flags) > +{ > + return __xfs_xattr_set(inode, name, value, size, flags, 0); > +} > + > +struct attrnames attr_user = { > + .attr_name = "user.", > + .attr_namelen = sizeof("user.") - 1, > +}; > + > +static struct xattr_handler xfs_xattr_user_handler = { > + .prefix = XATTR_USER_PREFIX, > + .get = xfs_xattr_user_get, > + .set = xfs_xattr_user_set, > +}; > + Ok. > + > +static int > +xfs_xattr_trusted_get(struct inode *inode, const char *name, > + void *value, size_t size) > +{ > + return __xfs_xattr_get(inode, name, value, size, ATTR_ROOT); > +} > + > +static int > +xfs_xattr_trusted_set(struct inode *inode, const char *name, > + const void *value, size_t size, int flags) > +{ > + return __xfs_xattr_set(inode, name, value, size, flags, ATTR_ROOT); > +} > + > +struct attrnames attr_trusted = { > + .attr_name = "trusted.", > + .attr_namelen = sizeof("trusted.") - 1, > +}; > + > +static struct xattr_handler xfs_xattr_trusted_handler = { > + .prefix = XATTR_TRUSTED_PREFIX, > + .get = xfs_xattr_trusted_get, > + .set = xfs_xattr_trusted_set, > +}; > + Ok. > + > +static int > +xfs_xattr_secure_get(struct inode *inode, const char *name, > + void *value, size_t size) > +{ > + return __xfs_xattr_get(inode, name, value, size, ATTR_SECURE); > +} > + > +static int > +xfs_xattr_secure_set(struct inode *inode, const char *name, > + const void *value, size_t size, int flags) > +{ > + return __xfs_xattr_set(inode, name, value, size, flags, ATTR_SECURE); > +} > + > +struct attrnames attr_secure = { > + .attr_name = "security.", > + .attr_namelen = sizeof("security.") - 1, > +}; > + > +static struct xattr_handler xfs_xattr_security_handler = { > + .prefix = XATTR_SECURITY_PREFIX, > + .get = xfs_xattr_secure_get, > + .set = xfs_xattr_secure_set, > +}; > + Ok. > + > +struct xattr_handler *xfs_xattr_handlers[] = { > + &xfs_xattr_user_handler, > + &xfs_xattr_trusted_handler, > + &xfs_xattr_security_handler, > + &xfs_xattr_system_handler, > + NULL > +}; > + So List code is done separately. Hmmmm... Oh, okay, ATTR_KERNAMELS (for attr_vn_listxattr) uses concatenated string arrays whereas for not ATTR_KERNAMELS, such as is used in xfs_attrlist_by_handle is uses list data in the form: <u32: valuelen> <char: name-array> <pad-to-4-byte-boundary> > +static int > +list_one_attr(const char *name, const size_t len, void *data, > + size_t size, ssize_t *result) > +{ > + char *p = data + *result; > + > + *result += len; > + if (!size) > + return 0; > + if (*result > size) > + return -ERANGE; > + > + strcpy(p, name); > + p += len; Q: Why increment p? Ok, this code looks like it is coming from attr_generic_listadd(). > + return 0; > +} > + Previously, in attr_generic_list it did: -> xfs_attr_list -> attr_system_list So you've expanded out attr_system_list into xfs_vn_listxattr(). > +ssize_t > +xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size) > +{ > + struct inode *inode = dentry->d_inode; > + struct xfs_inode *ip = XFS_I(inode); > + attrlist_cursor_kern_t cursor = { 0 }; > + int error, xflags; > + ssize_t result; > + > + xflags = ATTR_KERNAMELS; > + if (!size) > + xflags |= ATTR_KERNOVAL; > + > + if (capable(CAP_SYS_ADMIN)) > + xflags |= ATTR_KERNFULLS; > + else > + xflags |= ATTR_KERNORMALS; > + > + > + /* > + * First read the regular on-disk attributes. > + */ > + result = -xfs_attr_list(ip, data, size, xflags, &cursor); > + if (result < 0) > + return result; > + > + /* > + * Then add the two synthetic ACL attributes. > + */ > + if (xfs_acl_vhasacl_access(inode)) { > + error = list_one_attr(POSIX_ACL_XATTR_ACCESS, > + strlen(POSIX_ACL_XATTR_ACCESS) + 1, > + data, size, &result); > + if (error) > + return error; > + } > + > + if (xfs_acl_vhasacl_default(inode)) { > + error = list_one_attr(POSIX_ACL_XATTR_DEFAULT, > + strlen(POSIX_ACL_XATTR_DEFAULT) + 1, > + data, size, &result); > + if (error) > + return error; > + } > + > + return result; > +} Looks reasonable. > Index: linux-2.6-xfs/fs/xfs/xfs_attr.c > =================================================================== > --- linux-2.6-xfs.orig/fs/xfs/xfs_attr.c 2008-05-21 09:59:53.000000000 +0200 > +++ linux-2.6-xfs/fs/xfs/xfs_attr.c 2008-05-21 10:06:38.000000000 +0200 > @@ -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 *whe > (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 }; > Index: linux-2.6-xfs/fs/xfs/xfs_attr.h > =================================================================== > --- linux-2.6-xfs.orig/fs/xfs/xfs_attr.h 2008-05-21 09:59:53.000000000 +0200 > +++ linux-2.6-xfs/fs/xfs/xfs_attr.h 2008-05-21 10:06:38.000000000 +0200 > @@ -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 > #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 */ > Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.h > =================================================================== > --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_iops.h 2008-05-21 09:59:53.000000000 +0200 > +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.h 2008-05-21 10:14:20.000000000 +0200 > @@ -27,6 +27,7 @@ extern const struct file_operations xfs_ > 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); > Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.c > =================================================================== > --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_super.c 2008-05-21 09:59:53.000000000 +0200 > +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.c 2008-05-21 10:14:20.000000000 +0200 > @@ -1767,6 +1767,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; > Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.h > =================================================================== > --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_super.h 2008-05-21 09:59:53.000000000 +0200 > +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_super.h 2008-05-21 10:14:20.000000000 +0200 > @@ -81,6 +81,7 @@ extern void xfs_flush_device(struct xfs_ > 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)) > > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] use generic_*xattr routines 2008-05-23 5:22 ` Timothy Shimmin @ 2008-05-23 5:48 ` Christoph Hellwig 2008-05-26 1:43 ` Timothy Shimmin 0 siblings, 1 reply; 11+ messages in thread From: Christoph Hellwig @ 2008-05-23 5:48 UTC (permalink / raw) To: Timothy Shimmin; +Cc: xfs On Fri, May 23, 2008 at 03:22:14PM +1000, Timothy Shimmin wrote: > Hi Christoph, > > Looks reasonable to me. > > In list_one_attr(), which looks based on attr_generic_listadd(), > it does a final: > > + p += len; > which seems useless. Yeah, feel free to remove it when you commit the patch. Alternatively I'll send an incremental patch once commited. > An aside, I noticed in passing (which was in existing code), > how we call vn_revalidate > in xfs_xattr_system_set(). I presume this is because we > call xfs_acl_setmode() in xfs_acl_vset() when we want to sync > the mode bits to the ACL. > If this is the case, then I think it would have been clearer > to put vn_revalidate() in the vicinity of xfs_acl_setmode(). > Or is there some other reason? No real reason, I was just keeping what was there before. But getting rid of vn_revalidate complete is on my todo list. The timestamp updates in there are already not nessecary anymore, and the i_mode/i_uid/i_gid and i_flags updates can be done much better in the caller that change the values in the dinode. > > + xfs_xattr.o \ > > xfs_ksyms.o) > > > Okay adding in a linux-2.6/xfs_xattr.c > (slightly different name than xfs_attr.c) Yeah. For one xfs_attr.c is already taken in fs/xfs and second the xattr name makes it pretty clear these are the Linux xattr routines and not the lowlevel XFS attr code > So you are removing xfs_vn_setxattr, xfs_vn_getxattr, and > xfs_vn_removexattr and calling generic_xattr and retaining the > code in xattr_handler's. > > You leave xfs_vn_listxattr alone. Just like ext3 does its own. Ok. Yes, the generic listxattr doesn't buy us anything as we just traverse the attr btree and list all of them in their natural order. No point in traversing it N times for N different attribute handlers. > > +static int > > +xfs_decode_acl(const char *name) > > +{ > > + if (strcmp(name, "posix_acl_access") == 0) > > + return _ACL_TYPE_ACCESS; > > + else if (strcmp(name, "posix_acl_default") == 0) > > + return _ACL_TYPE_DEFAULT; > > + return -EINVAL; > > +} > > + > Fine. > > > +static int > > +xfs_xattr_system_get(struct inode *inode, const char *name, > > + void *buffer, size_t size) > > +{ > > + int acl; > > + > > + acl = xfs_decode_acl(name); > > + if (acl < 0) > > + return acl; > > + > > + return xfs_acl_vget(inode, buffer, size, acl); > > +} > > + > Fine. > Seems a little funny as we are calling it a system EA but > then directly calling the acl code. > i.e. acknowledging, I guess, that we only have Posix ACLs > as system EAs. > Almost could call it xfs_xattr_acl_get(). > It saves on one liner wrappers I guess. Probably worth adding a comment that we only have acls for now. The reason I did this is to avoid doing multiple memcpys on the xattr name for decoding it. It will probably need some revisiting if/when we support other system xattrs. > Why the vn_revalidate? > b/c we did that in xfs_attr.c/attr_system_set(). > It updates the linux inode fields based on the xfs inode fields. > I wonder why. > Because we can modify an ACL which can cause mode changes? > in the call to xfs_acl_setmode(vp, xfs_acl, &basicperms) > I wonder why we do it at this point though as it doesn't > look so obvious. Yeah, se the comment above. vn_revalidate will go away pretty soon at which point this is sorted out. > > +struct xattr_handler *xfs_xattr_handlers[] = { > > + &xfs_xattr_user_handler, > > + &xfs_xattr_trusted_handler, > > + &xfs_xattr_security_handler, > > + &xfs_xattr_system_handler, > > + NULL > > +}; > > + > > So List code is done separately. Hmmmm... > > Oh, okay, ATTR_KERNAMELS (for attr_vn_listxattr) uses > concatenated string arrays > whereas for not ATTR_KERNAMELS, such as is used in > xfs_attrlist_by_handle is uses list data in the form: > <u32: valuelen> <char: name-array> <pad-to-4-byte-boundary> Yes, this is quite unfortunate. My plan is to refactor the low-level attr code so that is passes down a formatter ala filldir for directory reading. This should clean up the attr listing code a lot and also gets rid of the levtover struct attrnames bits. But that a different patch which still needs to be written. > Previously, in attr_generic_list it did: > -> xfs_attr_list > -> attr_system_list > > So you've expanded out attr_system_list into xfs_vn_listxattr(). Yes. And loop-unrolled it while we're at it because the loop over the system attrs didn't make much sense. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] use generic_*xattr routines 2008-05-23 5:48 ` Christoph Hellwig @ 2008-05-26 1:43 ` Timothy Shimmin 2008-05-26 5:37 ` Christoph Hellwig 0 siblings, 1 reply; 11+ messages in thread From: Timothy Shimmin @ 2008-05-26 1:43 UTC (permalink / raw) To: Christoph Hellwig; +Cc: xfs-oss Christoph Hellwig wrote: > On Fri, May 23, 2008 at 03:22:14PM +1000, Timothy Shimmin wrote: >> Hi Christoph, >> >> Looks reasonable to me. >> >> In list_one_attr(), which looks based on attr_generic_listadd(), >> it does a final: >>> + p += len; >> which seems useless. > > Yeah, feel free to remove it when you commit the patch. Alternatively > I'll send an incremental patch once commited. > Yep, I'll remove it before checkin. >> An aside, I noticed in passing (which was in existing code), >> how we call vn_revalidate >> in xfs_xattr_system_set(). I presume this is because we >> call xfs_acl_setmode() in xfs_acl_vset() when we want to sync >> the mode bits to the ACL. >> If this is the case, then I think it would have been clearer >> to put vn_revalidate() in the vicinity of xfs_acl_setmode(). >> Or is there some other reason? > > No real reason, I was just keeping what was there before. But getting > rid of vn_revalidate complete is on my todo list. The timestamp updates > in there are already not nessecary anymore, and the i_mode/i_uid/i_gid > and i_flags updates can be done much better in the caller that change > the values in the dinode. > Okay, good to know. >> So you are removing xfs_vn_setxattr, xfs_vn_getxattr, and >> xfs_vn_removexattr and calling generic_xattr and retaining the >> code in xattr_handler's. >> >> You leave xfs_vn_listxattr alone. Just like ext3 does its own. Ok. > > Yes, the generic listxattr doesn't buy us anything as we just traverse > the attr btree and list all of them in their natural order. No point > in traversing it N times for N different attribute handlers. > Good point (I didn't really look). >>> +static int >>> +xfs_xattr_system_get(struct inode *inode, const char *name, >>> + void *buffer, size_t size) >>> +{ >>> + int acl; >>> + >>> + acl = xfs_decode_acl(name); >>> + if (acl < 0) >>> + return acl; >>> + >>> + return xfs_acl_vget(inode, buffer, size, acl); >>> +} >>> + >> Fine. >> Seems a little funny as we are calling it a system EA but >> then directly calling the acl code. >> i.e. acknowledging, I guess, that we only have Posix ACLs >> as system EAs. >> Almost could call it xfs_xattr_acl_get(). >> It saves on one liner wrappers I guess. > > Probably worth adding a comment that we only have acls for now. > The reason I did this is to avoid doing multiple memcpys on the xattr > name for decoding it. It will probably need some revisiting if/when > we support other system xattrs. Okay, I'll add a comment. > > Yeah, se the comment above. vn_revalidate will go away pretty soon at > which point this is sorted out. > >>> +struct xattr_handler *xfs_xattr_handlers[] = { >>> + &xfs_xattr_user_handler, >>> + &xfs_xattr_trusted_handler, >>> + &xfs_xattr_security_handler, >>> + &xfs_xattr_system_handler, >>> + NULL >>> +}; >>> + >> So List code is done separately. Hmmmm... >> >> Oh, okay, ATTR_KERNAMELS (for attr_vn_listxattr) uses >> concatenated string arrays >> whereas for not ATTR_KERNAMELS, such as is used in >> xfs_attrlist_by_handle is uses list data in the form: >> <u32: valuelen> <char: name-array> <pad-to-4-byte-boundary> > > Yes, this is quite unfortunate. My plan is to refactor the low-level > attr code so that is passes down a formatter ala filldir for directory > reading. This should clean up the attr listing code a lot and also > gets rid of the levtover struct attrnames bits. But that a different > patch which still needs to be written. > I guess this is done to some extent by the put_listent() callback. Though, the context structure is probably a bit overused in different ways. The callback was also used for searching (for parent-ptr code) as well as for list formatting. I presume we are preserving the valuelen list format to keep the API for xfs_attrlist_by_handle used by xfsdump and probably for dmf. Thanks, --Tim ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] use generic_*xattr routines 2008-05-26 1:43 ` Timothy Shimmin @ 2008-05-26 5:37 ` Christoph Hellwig 2008-05-27 10:50 ` Timothy Shimmin 0 siblings, 1 reply; 11+ messages in thread From: Christoph Hellwig @ 2008-05-26 5:37 UTC (permalink / raw) To: Timothy Shimmin; +Cc: xfs-oss On Mon, May 26, 2008 at 11:43:42AM +1000, Timothy Shimmin wrote: > I guess this is done to some extent by the put_listent() callback. > Though, the context structure is probably a bit overused in different > ways. > The callback was also used for searching (for parent-ptr code) as well > as for list formatting. > I presume we are preserving the valuelen list format to keep the API > for xfs_attrlist_by_handle used by xfsdump and probably for dmf. Yes, the idea is to change the put_listen callback for work more like filldir. Thas is: - the callback is supplied by the xfs_attr_list caller, not set based on options - there will be an opaque object supplied to xfs_attr_list that is to be used by put_listent so that we don't have to pass down implementation-specific arguments directly. I'd also like to move the attrlist_cursor_kern_t into this callback opaque context because it doesn't make sense for the normal xattr API, but I'll have to see if that's actually feasible. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] use generic_*xattr routines 2008-05-26 5:37 ` Christoph Hellwig @ 2008-05-27 10:50 ` Timothy Shimmin 2008-05-29 12:39 ` Christoph Hellwig 0 siblings, 1 reply; 11+ messages in thread From: Timothy Shimmin @ 2008-05-27 10:50 UTC (permalink / raw) To: Christoph Hellwig; +Cc: xfs-oss Christoph Hellwig wrote: > On Mon, May 26, 2008 at 11:43:42AM +1000, Timothy Shimmin wrote: >> I guess this is done to some extent by the put_listent() callback. >> Though, the context structure is probably a bit overused in different >> ways. >> The callback was also used for searching (for parent-ptr code) as well >> as for list formatting. >> I presume we are preserving the valuelen list format to keep the API >> for xfs_attrlist_by_handle used by xfsdump and probably for dmf. > > Yes, the idea is to change the put_listen callback for work more like > filldir. Thas is: > > - the callback is supplied by the xfs_attr_list caller, not set based > on options Oh, okay. For example, instead of setting the flags to ATTR_KERNOVAL such as in xfs_vn_listxattr when size is 0, one could just set the callback to xfs_attr_kern_list_sizes and pass it in etc... > - there will be an opaque object supplied to xfs_attr_list that is to > be used by put_listent so that we don't have to pass down > implementation-specific arguments directly. > Ok. So instead of overloading fields in xfs_attr_list_context_t, you'll pass down a void* argument or some such for callback specific data. > I'd also like to move the attrlist_cursor_kern_t into this callback > opaque context because it doesn't make sense for the normal xattr API, > but I'll have to see if that's actually feasible. BTW, the cursor stuff is a bit flawed. Like the dir1 code (I believe), if from userspace you use the cursor and modifications happen to the EAs (add or removal) between calls, we can end up repeating elements in the list or miss some. We don't preserve the position and we can compact the data etc. --Tim xfs_attr_list( xfs_inode_t *dp, char *buffer, int bufsize, int flags, attrlist_cursor_kern_t *cursor) { xfs_attr_list_context_t context; ... if (flags & ATTR_KERNAMELS) { context.bufsize = bufsize; context.firstu = context.bufsize; if (flags & ATTR_KERNOVAL) context.put_listent = xfs_attr_kern_list_sizes; else context.put_listent = xfs_attr_kern_list; } else { context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */ context.firstu = context.bufsize; context.alist->al_count = 0; context.alist->al_more = 0; context.alist->al_offset[0] = context.bufsize; context.put_listent = xfs_attr_put_listent; } ssize_t xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size) { struct inode *inode = dentry->d_inode; struct xfs_inode *ip = XFS_I(inode); attrlist_cursor_kern_t cursor = { 0 }; int error, xflags; ssize_t result; xflags = ATTR_KERNAMELS; if (!size) xflags |= ATTR_KERNOVAL; if (capable(CAP_SYS_ADMIN)) xflags |= ATTR_KERNFULLS; else xflags |= ATTR_KERNORMALS; /* * First read the regular on-disk attributes. */ result = -xfs_attr_list(ip, data, size, xflags, &cursor); ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] use generic_*xattr routines 2008-05-27 10:50 ` Timothy Shimmin @ 2008-05-29 12:39 ` Christoph Hellwig 2008-05-30 6:37 ` Timothy Shimmin 0 siblings, 1 reply; 11+ messages in thread From: Christoph Hellwig @ 2008-05-29 12:39 UTC (permalink / raw) To: Timothy Shimmin; +Cc: Christoph Hellwig, xfs-oss On Tue, May 27, 2008 at 08:50:48PM +1000, Timothy Shimmin wrote: > > - the callback is supplied by the xfs_attr_list caller, not set based > > on options > > Oh, okay. For example, instead of setting the flags to ATTR_KERNOVAL > such as in xfs_vn_listxattr when size is 0, one could just set the callback > to xfs_attr_kern_list_sizes and pass it in etc... Yes. I have an initial patch that goes directly to xfs_attr_list_int from xfs_xattr.c and kills most of the ATTR_KERN flags. It's a quite nice cleanup already. Next step will be to convert dmapi to use it's own callback aswell. This will be an even bigger cleanup as put_listent gets the xattr value aswell and we can kill the additional xfs_attr_get calls, making this code simpler and more efficient. > > - there will be an opaque object supplied to xfs_attr_list that is to > > be used by put_listent so that we don't have to pass down > > implementation-specific arguments directly. > > > > Ok. > So instead of overloading fields in xfs_attr_list_context_t, > you'll pass down a void* argument or some such for callback specific data. I've started looking at this and after some investigattion I think we should just pass the xfs_inode directly to all the functions and then a void parameter, yes. We'll need to find a solution for the seen_enough paramter, but I think this could be handled similar to filldir. There's also some functions directly touching the attr cursor which seems solveable, too. > > I'd also like to move the attrlist_cursor_kern_t into this callback > > opaque context because it doesn't make sense for the normal xattr API, > > but I'll have to see if that's actually feasible. > > BTW, the cursor stuff is a bit flawed. Like the dir1 code (I believe), > if from userspace you use the cursor and modifications happen to the EAs > (add or removal) between calls, > we can end up repeating elements in the list or miss some. > We don't preserve the position and we can compact the data etc. Yes, I think this whole cursor is a rather bad idea. But given that it's used by xfsdump we can't easily get rid of it. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] use generic_*xattr routines 2008-05-29 12:39 ` Christoph Hellwig @ 2008-05-30 6:37 ` Timothy Shimmin 2008-05-30 7:53 ` Christoph Hellwig 0 siblings, 1 reply; 11+ messages in thread From: Timothy Shimmin @ 2008-05-30 6:37 UTC (permalink / raw) To: Christoph Hellwig; +Cc: xfs-oss Christoph Hellwig wrote: > On Tue, May 27, 2008 at 08:50:48PM +1000, Timothy Shimmin wrote: >>> - the callback is supplied by the xfs_attr_list caller, not set based >>> on options >> Oh, okay. For example, instead of setting the flags to ATTR_KERNOVAL >> such as in xfs_vn_listxattr when size is 0, one could just set the callback >> to xfs_attr_kern_list_sizes and pass it in etc... > > Yes. I have an initial patch that goes directly to xfs_attr_list_int > from xfs_xattr.c and kills most of the ATTR_KERN flags. It's a quite > nice cleanup already. Next step will be to convert dmapi to use it's > own callback aswell. This will be an even bigger cleanup as > put_listent gets the xattr value aswell and we can kill the additional > xfs_attr_get calls, making this code simpler and more efficient. > Sorry, what xfs_attr_get call are you referring to? >>> - there will be an opaque object supplied to xfs_attr_list that is to >>> be used by put_listent so that we don't have to pass down >>> implementation-specific arguments directly. >>> >> Ok. >> So instead of overloading fields in xfs_attr_list_context_t, >> you'll pass down a void* argument or some such for callback specific data. > > I've started looking at this and after some investigation I think > we should just pass the xfs_inode directly to all the functions and then > a void parameter, yes. We'll need to find a solution for the > seen_enough paramter, but I think this could be handled similar to > filldir. There's also some functions directly touching the attr cursor > which seems solveable, too. > I'll await the patch :) The seen_enough param was added for search type callbacks so the callback could terminate the list walk early. Oh okay, I also used it to stop when we fill the buffer. >>> I'd also like to move the attrlist_cursor_kern_t into this callback >>> opaque context because it doesn't make sense for the normal xattr API, >>> but I'll have to see if that's actually feasible. >> BTW, the cursor stuff is a bit flawed. Like the dir1 code (I believe), >> if from userspace you use the cursor and modifications happen to the EAs >> (add or removal) between calls, >> we can end up repeating elements in the list or miss some. >> We don't preserve the position and we can compact the data etc. > > Yes, I think this whole cursor is a rather bad idea. But given that > it's used by xfsdump we can't easily get rid of it. Not if we are to remain compatible with old xfsdump programs (assuming we changed the latest one). Yep. --Tim ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] use generic_*xattr routines 2008-05-30 6:37 ` Timothy Shimmin @ 2008-05-30 7:53 ` Christoph Hellwig 0 siblings, 0 replies; 11+ messages in thread From: Christoph Hellwig @ 2008-05-30 7:53 UTC (permalink / raw) To: Timothy Shimmin; +Cc: xfs-oss On Fri, May 30, 2008 at 04:37:42PM +1000, Timothy Shimmin wrote: > > Yes. I have an initial patch that goes directly to xfs_attr_list_int > > from xfs_xattr.c and kills most of the ATTR_KERN flags. It's a quite > > nice cleanup already. Next step will be to convert dmapi to use it's > > own callback aswell. This will be an even bigger cleanup as > > put_listent gets the xattr value aswell and we can kill the additional > > xfs_attr_get calls, making this code simpler and more efficient. > > > Sorry, what xfs_attr_get call are you referring to? xfs_dm_getall_dmattr currently does an xfs_attr_list and then performs and xfs_attr_get for each attribute it cares about. But rewriting this to use put_listent we not only get rid of the temporary buffer but also the need to calls xfs_attr_get because put_listent already gets the attribute value passed. It also fixes the race mentioned in the comment and with a properly written put_listent helper can copy the attributes directly to userspace without any kernel buffer at all. That would also fix the direct userspace pointer dereference currently lingering in that code :) > > I've started looking at this and after some investigation I think > > we should just pass the xfs_inode directly to all the functions and then > > a void parameter, yes. We'll need to find a solution for the > > seen_enough paramter, but I think this could be handled similar to > > filldir. There's also some functions directly touching the attr cursor > > which seems solveable, too. > > > I'll await the patch :) > The seen_enough param was added for search type callbacks so the callback > could terminate the list walk early. > Oh okay, I also used it to stop when we fill the buffer. Yes. May idea is to break out of the loop as soon as put_listent returns a non-zero value just like filldir. We can then decided to play with positivie / begative values to allow for a sucessfull early exit, or just like filldir have the actual errno inside the private context structure. I suspect the first variant will be cleaner. ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2008-05-30 7:52 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-04-30 11:22 [PATCH] use generic_*xattr routines Christoph Hellwig 2008-05-21 8:16 ` Christoph Hellwig 2008-05-22 7:17 ` Timothy Shimmin 2008-05-23 5:22 ` Timothy Shimmin 2008-05-23 5:48 ` Christoph Hellwig 2008-05-26 1:43 ` Timothy Shimmin 2008-05-26 5:37 ` Christoph Hellwig 2008-05-27 10:50 ` Timothy Shimmin 2008-05-29 12:39 ` Christoph Hellwig 2008-05-30 6:37 ` Timothy Shimmin 2008-05-30 7:53 ` Christoph Hellwig
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox