I'll list these in order of invasiveness; the first two are just bug fixes but the latter two changes semantics somewhat.

xattr-printk.patch:
--------------------
This patch removes some unnecessary printk()'s that were hanging around in the listxattr path (it was printing out key names every time it was called).

xattr-svr-error-handling.patch:
--------------------
This patch fixes a variety of server side problems in error handling for extended attribute failure cases. In many places the state machine was either not setting an error code properly, or not using the right return value. In some cases (such as trying to set a reserved value) it tended to cause the state machine to hang.

xattr-svr-name-spaces.patch:
--------------------
This patch adds logic to the server side to enforce that all extended attributes must be in a supported name space (currently just "system", "user", "trusted", and "security"), rather than letting the client choose arbitrary names. In addition, all previously reserved keys (such as "metafile_dist") are now presented in the "system.pvfs2." name space rather than as top level keys. There is no change to the wire protocol or on disk storage of these keys, the server just does a translation to get the right key name for those.

The reserved word filtering on the server is simplified a bit by this, because now it can just dis-allow writes to "system.pvfs2.*" rather than having to check for a specific list of reserved words.

xattr-kernel-name-spaces.patch:
--------------------
This patch tweaks the kernel side xattr code a little to make it easier to use specialized handlers for different name spaces (both in 2.6 and 2.4 kernels). The only one that is currently handled seperately is the "trusted" name space; the caller is checked for CAP_SYS_ADMIN capability before being allowed to access that name space. (Note that no similar check is performed at the system interface level yet, however, so the check only helps on file systems accessed through the VFS).

-Phil
diff -Naur pvfs2A/src/kernel/linux-2.6/Makefile.in pvfs2B/src/kernel/linux-2.6/Makefile.in
--- pvfs2A/src/kernel/linux-2.6/Makefile.in	2005-12-06 20:46:33.000000000 +0100
+++ pvfs2B/src/kernel/linux-2.6/Makefile.in	2006-02-28 15:45:51.000000000 +0100
@@ -46,7 +46,8 @@
     symlink.c \
     xattr.c \
     acl.c \
-    xattr_default.c \
+    xattr-trusted.c \
+    xattr-default.c \
     waitqueue.c \
     pvfs2-proc.c
 hsrc = \
diff -Naur pvfs2A/src/kernel/linux-2.6/acl.c pvfs2B/src/kernel/linux-2.6/acl.c
--- pvfs2A/src/kernel/linux-2.6/acl.c	2006-01-09 16:55:05.000000000 +0100
+++ pvfs2B/src/kernel/linux-2.6/acl.c	2006-02-28 15:45:51.000000000 +0100
@@ -196,7 +196,7 @@
         pvfs2_error("pvfs2_get_acl: Could not allocate value ptr\n");
         return ERR_PTR(-ENOMEM);
     }
-    ret = pvfs2_inode_getxattr(inode, key, value, PVFS_MAX_XATTR_VALUELEN);
+    ret = pvfs2_inode_getxattr(inode, "", key, value, PVFS_MAX_XATTR_VALUELEN);
     /* if the key exists, convert it to an in-memory rep */
     if (ret > 0)
     {
@@ -282,7 +282,7 @@
         }
     }
     /* Go ahead and set the extended attribute now */
-    error = pvfs2_inode_setxattr(inode, name, value, size, 0);
+    error = pvfs2_inode_setxattr(inode, "", name, value, size, 0);
     if (value) 
     {
         kfree(value);
diff -Naur pvfs2A/src/kernel/linux-2.6/pvfs2-kernel.h pvfs2B/src/kernel/linux-2.6/pvfs2-kernel.h
--- pvfs2A/src/kernel/linux-2.6/pvfs2-kernel.h	2006-01-04 15:51:01.000000000 +0100
+++ pvfs2B/src/kernel/linux-2.6/pvfs2-kernel.h	2006-02-28 16:01:59.000000000 +0100
@@ -249,11 +249,13 @@
 #ifdef HAVE_XATTR
 #define PVFS2_XATTR_INDEX_POSIX_ACL_ACCESS  1
 #define PVFS2_XATTR_INDEX_POSIX_ACL_DEFAULT 2
-#define PVFS2_XATTR_INDEX_DEFAULT           3
+#define PVFS2_XATTR_INDEX_TRUSTED           3
+#define PVFS2_XATTR_INDEX_DEFAULT           4
 
 #define PVFS2_XATTR_NAME_ACL_ACCESS  POSIX_ACL_XATTR_ACCESS
 #define PVFS2_XATTR_NAME_ACL_DEFAULT POSIX_ACL_XATTR_DEFAULT
-#define PVFS2_XATTR_NAME_DEFAULT     ""
+#define PVFS2_XATTR_NAME_TRUSTED_PREFIX "trusted."
+#define PVFS2_XATTR_NAME_DEFAULT_PREFIX ""
 
 #if !defined(PVFS2_LINUX_KERNEL_2_4) && defined(HAVE_GENERIC_GETXATTR)
 
@@ -262,6 +264,7 @@
 
 extern struct xattr_handler *pvfs2_xattr_handlers[];
 extern struct xattr_handler pvfs2_xattr_acl_default_handler, pvfs2_xattr_acl_access_handler;
+extern struct xattr_handler pvfs2_xattr_trusted_handler;
 extern struct xattr_handler pvfs2_xattr_default_handler;
 
 typedef struct {
@@ -288,6 +291,17 @@
     }
     return internal_flag;
 }
+
+int pvfs2_xattr_set_trusted(struct inode *inode, 
+    const char *name, const void *buffer, size_t size, int flags);
+int pvfs2_xattr_get_trusted(struct inode *inode,
+    const char *name, void *buffer, size_t size);
+int pvfs2_xattr_set_default(struct inode *inode, 
+    const char *name, const void *buffer, size_t size, int flags);
+int pvfs2_xattr_get_default(struct inode *inode,
+    const char *name, void *buffer, size_t size);
+
+
 #endif
 
 /************************************
@@ -546,10 +560,12 @@
     PVFS_credentials *credentials);
 
 ssize_t pvfs2_inode_getxattr(
-        struct inode *inode, const char *name, void *buffer, size_t size);
-int pvfs2_inode_setxattr(struct inode *inode, const char *name,
-        const void *value, size_t size, int flags);
-int pvfs2_inode_removexattr(struct inode *inode, const char *name);
+        struct inode *inode, const char* prefix,
+        const char *name, void *buffer, size_t size);
+int pvfs2_inode_setxattr(struct inode *inode, const char* prefix,
+        const char *name, const void *value, size_t size, int flags);
+int pvfs2_inode_removexattr(struct inode *inode, const char* prefix,
+        const char *name);
 int pvfs2_inode_listxattr(struct inode *inode, char *, size_t);
 
 int pvfs2_inode_getattr(
diff -Naur pvfs2A/src/kernel/linux-2.6/pvfs2-utils.c pvfs2B/src/kernel/linux-2.6/pvfs2-utils.c
--- pvfs2A/src/kernel/linux-2.6/pvfs2-utils.c	2006-02-22 14:28:57.000000000 +0100
+++ pvfs2B/src/kernel/linux-2.6/pvfs2-utils.c	2006-02-24 21:50:58.000000000 +0100
@@ -505,8 +505,8 @@
  * unless the key does not exist for the file and/or if
  * there were errors in fetching the attribute value.
  */
-ssize_t pvfs2_inode_getxattr(struct inode *inode, const char *name, 
-        void *buffer, size_t size)
+ssize_t pvfs2_inode_getxattr(struct inode *inode, const char* prefix,
+    const char *name, void *buffer, size_t size)
 {
     ssize_t ret = -ENOMEM;
     pvfs2_kernel_op_t *new_op = NULL;
@@ -518,10 +518,10 @@
         pvfs2_error("pvfs2_inode_getxattr: bogus NULL pointers\n");
         return -EINVAL;
     }
-    if (size < 0 || strlen(name) >= PVFS_MAX_XATTR_NAMELEN)
+    if (size < 0 || (strlen(name)+strlen(prefix)) >= PVFS_MAX_XATTR_NAMELEN)
     {
         pvfs2_error("Invalid size (%d) or key length (%d)\n", 
-                (int) size, (int) strlen(name));
+                (int) size, (int)(strlen(name)+strlen(prefix)));
         return -EINVAL;
     }
     if (inode)
@@ -539,16 +539,17 @@
 
         new_op->upcall.type = PVFS2_VFS_OP_GETXATTR;
         new_op->upcall.req.getxattr.refn = pvfs2_inode->refn;
-        strncpy(new_op->upcall.req.getxattr.key, name, PVFS_MAX_XATTR_NAMELEN);
+        ret = snprintf((char*)new_op->upcall.req.getxattr.key,
+            PVFS_MAX_XATTR_NAMELEN, "%s%s", prefix, name);
         /* 
          * NOTE: Although keys are meant to be NULL terminated textual strings,
          * I am going to explicitly pass the length just in case we change this
          * later on...
          */
-        new_op->upcall.req.getxattr.key_sz = 
-            strlen(new_op->upcall.req.getxattr.key) + 1;
+        new_op->upcall.req.getxattr.key_sz = ret + 1;
         pvfs2_print("pvfs2_inode_getxattr: key %s, key_sz %d\n", 
-                name, (int) new_op->upcall.req.getxattr.key_sz);
+                (char*)new_op->upcall.req.getxattr.key, 
+                (int) new_op->upcall.req.getxattr.key_sz);
 
         ret = service_operation(
             new_op, "pvfs2_inode_getxattr", PVFS2_OP_RETRY_COUNT, 
@@ -598,7 +599,7 @@
                             new_length);
                     ret = new_length;
                     pvfs2_print("pvfs2_getxattr: key: %s, val_length: %d\n",
-                            name, (int) ret);
+                        (char*)new_op->upcall.req.getxattr.key, (int) ret);
                 }
             }
         }
@@ -620,8 +621,8 @@
  * Returns a -ve number on error and 0 on success.
  * Key is text, but value can be binary!
  */
-int pvfs2_inode_setxattr(struct inode *inode, const char *name,
-        const void *value, size_t size, int flags)
+int pvfs2_inode_setxattr(struct inode *inode, const char* prefix, 
+    const char *name, const void *value, size_t size, int flags)
 {
     int ret = -ENOMEM;
     pvfs2_kernel_op_t *new_op = NULL;
@@ -638,16 +639,16 @@
         pvfs2_error("pvfs2_inode_setxattr: bogus NULL pointers!\n");
         return -EINVAL;
     }
-    if (strlen(name) >= PVFS_MAX_XATTR_NAMELEN)
+    if ((strlen(name)+strlen(prefix)) >= PVFS_MAX_XATTR_NAMELEN)
     {
         pvfs2_error("pvfs2_inode_setxattr: bogus key size (%d)\n", 
-                (int) strlen(name));
+                (int)(strlen(name)+strlen(prefix)));
         return -EINVAL;
     }
     /* This is equivalent to a removexattr */
     if (size == 0 && value == NULL)
     {
-        return pvfs2_inode_removexattr(inode, name);
+        return pvfs2_inode_removexattr(inode, prefix, name);
     }
     if (inode)
     {
@@ -673,10 +674,10 @@
          * I am going to explicitly pass the length just in case we change this
          * later on...
          */
-        strncpy(new_op->upcall.req.setxattr.keyval.key, 
-                name, PVFS_MAX_XATTR_NAMELEN);
+        ret = snprintf((char*)new_op->upcall.req.setxattr.keyval.key,
+            PVFS_MAX_XATTR_NAMELEN, "%s%s", prefix, name);
         new_op->upcall.req.setxattr.keyval.key_sz = 
-            strlen(new_op->upcall.req.setxattr.keyval.key) + 1;
+            ret + 1;
         memcpy(new_op->upcall.req.setxattr.keyval.val, value, size);
         new_op->upcall.req.setxattr.keyval.val[size] = '\0';
         /* For some reason, val_sz should include the \0 at the end as well */
@@ -695,16 +696,17 @@
     return ret;
 }
 
-int pvfs2_inode_removexattr(struct inode *inode, const char *name)
+int pvfs2_inode_removexattr(struct inode *inode, const char* prefix, 
+    const char *name)
 {
     int ret = -ENOMEM;
     pvfs2_kernel_op_t *new_op = NULL;
     pvfs2_inode_t *pvfs2_inode = NULL;
 
-    if (strlen(name) >= PVFS_MAX_XATTR_NAMELEN)
+    if ((strlen(name)+strlen(prefix)) >= PVFS_MAX_XATTR_NAMELEN)
     {
         pvfs2_error("pvfs2_inode_removexattr: Invalid key length(%d)\n", 
-                (int) strlen(name));
+                (int)(strlen(name)+strlen(prefix)));
         return -EINVAL;
     }
     if (inode)
@@ -726,10 +728,9 @@
          * I am going to explicitly pass the length just in case we change this
          * later on...
          */
-        strncpy(new_op->upcall.req.removexattr.key, name, 
-                PVFS_MAX_XATTR_NAMELEN);
-        new_op->upcall.req.removexattr.key_sz = 
-            strlen(new_op->upcall.req.removexattr.key) + 1;
+        ret = snprintf((char*)new_op->upcall.req.removexattr.key,
+            PVFS_MAX_XATTR_NAMELEN, "%s%s", prefix, name);
+        new_op->upcall.req.removexattr.key_sz = ret + 1;
 
         ret = service_operation(
             new_op, "pvfs2_inode_removexattr", PVFS2_OP_RETRY_COUNT,
diff -Naur pvfs2A/src/kernel/linux-2.6/xattr-default.c pvfs2B/src/kernel/linux-2.6/xattr-default.c
--- pvfs2A/src/kernel/linux-2.6/xattr-default.c	1970-01-01 01:00:00.000000000 +0100
+++ pvfs2B/src/kernel/linux-2.6/xattr-default.c	2006-02-28 15:45:51.000000000 +0100
@@ -0,0 +1,66 @@
+/*
+ * (C) 2001 Clemson University and The University of Chicago
+ *
+ * See COPYING in top-level directory.
+ */
+
+/** \file
+ *  \ingroup pvfs2linux
+ *
+ *  Extended attributes for PVFS2 that handles all setxattr
+ *  stuff even for those keys that do not have a prefix!
+ *  This is the 2.6 kernels way of doing extended attributes
+ */
+
+#include "pvfs2-kernel.h"
+#include "pvfs2-bufmap.h"
+
+#ifdef HAVE_XATTR
+
+#include <linux/xattr.h>
+
+int pvfs2_xattr_set_default(struct inode *inode, 
+    const char *name, const void *buffer, size_t size, int flags)
+{
+    int internal_flag = 0;
+
+    if (strcmp(name, "") == 0)
+        return -EINVAL;
+    internal_flag = convert_to_internal_xattr_flags(flags);
+    return pvfs2_inode_setxattr(inode, PVFS2_XATTR_NAME_DEFAULT_PREFIX,
+        name, buffer, size, internal_flag);
+}
+
+int pvfs2_xattr_get_default(struct inode *inode,
+    const char *name, void *buffer, size_t size)
+{
+    if (strcmp(name, "") == 0)
+        return -EINVAL;
+    return pvfs2_inode_getxattr(inode, PVFS2_XATTR_NAME_DEFAULT_PREFIX,
+        name, buffer, size);
+}
+#endif
+
+#if !defined(PVFS2_LINUX_KERNEL_2_4) && defined(HAVE_GENERIC_GETXATTR)
+
+struct xattr_handler pvfs2_xattr_default_handler = {
+    /* 
+     * NOTE: this is set to be the empty string.
+     * so that all un-prefixed xattrs keys get caught
+     * here!
+     */
+    .prefix = PVFS2_XATTR_NAME_DEFAULT_PREFIX, 
+    .get    = pvfs2_xattr_get_default,
+    .set    = pvfs2_xattr_set_default,
+};
+
+#endif
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */
diff -Naur pvfs2A/src/kernel/linux-2.6/xattr-trusted.c pvfs2B/src/kernel/linux-2.6/xattr-trusted.c
--- pvfs2A/src/kernel/linux-2.6/xattr-trusted.c	1970-01-01 01:00:00.000000000 +0100
+++ pvfs2B/src/kernel/linux-2.6/xattr-trusted.c	2006-02-28 16:25:21.000000000 +0100
@@ -0,0 +1,64 @@
+/*
+ * (C) 2001 Clemson University and The University of Chicago
+ *
+ * See COPYING in top-level directory.
+ */
+
+/** \file
+ *  \ingroup pvfs2linux
+ *
+ *  Extended attributes for PVFS2 that handle the trusted prefix.
+ */
+
+#include "pvfs2-kernel.h"
+#include "pvfs2-bufmap.h"
+
+#ifdef HAVE_XATTR
+
+#include <linux/xattr.h>
+
+int pvfs2_xattr_set_trusted(struct inode *inode, 
+    const char *name, const void *buffer, size_t size, int flags)
+{
+    int internal_flag = 0;
+
+    if (strcmp(name, "") == 0)
+        return -EINVAL;
+    if(!capable(CAP_SYS_ADMIN))
+        return -EPERM;
+    internal_flag = convert_to_internal_xattr_flags(flags);
+    return pvfs2_inode_setxattr(inode, PVFS2_XATTR_NAME_TRUSTED_PREFIX,
+        name, buffer, size, internal_flag);
+}
+
+int pvfs2_xattr_get_trusted(struct inode *inode,
+    const char *name, void *buffer, size_t size)
+{
+    if (strcmp(name, "") == 0)
+        return -EINVAL;
+    if(!capable(CAP_SYS_ADMIN))
+        return -EPERM;
+    return pvfs2_inode_getxattr(inode, PVFS2_XATTR_NAME_TRUSTED_PREFIX,
+        name, buffer, size);
+}
+
+#endif
+
+#if !defined(PVFS2_LINUX_KERNEL_2_4) && defined(HAVE_GENERIC_GETXATTR)
+
+struct xattr_handler pvfs2_xattr_trusted_handler = {
+    .prefix = PVFS2_XATTR_NAME_TRUSTED_PREFIX, 
+    .get    = pvfs2_xattr_get_trusted,
+    .set    = pvfs2_xattr_set_trusted,
+};
+
+#endif
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */
diff -Naur pvfs2A/src/kernel/linux-2.6/xattr.c pvfs2B/src/kernel/linux-2.6/xattr.c
--- pvfs2A/src/kernel/linux-2.6/xattr.c	2006-01-09 17:12:32.000000000 +0100
+++ pvfs2B/src/kernel/linux-2.6/xattr.c	2006-02-28 15:45:51.000000000 +0100
@@ -33,20 +33,27 @@
      */
     &pvfs2_xattr_acl_access_handler,
     &pvfs2_xattr_acl_default_handler,
-    /* 
-     * NOTE: Please add prefix-based xattrs before this comment. 
-     * Don't forget to change the handler map above and the associated
-     * defines in pvfs2-kernel.h!
-     * The pvfs2_xattr_default_handler handles all xattrs with "" (the empty)
-     * prefix string! No one seemed to have any strong opinions on whether
-     * this will hurt us/help us in the long run.
-     */
+    &pvfs2_xattr_trusted_handler,
     &pvfs2_xattr_default_handler,
     NULL
 };
 
 #else 
 
+/* prefix comparison function; taken from RedHat patched 2.4 kernel with
+ * xattr support
+ */
+static inline const char * pvfs2_strcmp_prefix(
+    const char *a, 
+    const char *a_prefix)
+{               
+    while (*a_prefix && *a == *a_prefix) {
+        a++;    
+        a_prefix++;
+    }       
+    return *a_prefix ? NULL : a;
+}       
+
 /* These routines are used only for the 2.4 kernel xattr callbacks or for early 2.6 kernels */
 
 /* All pointers are in kernel-space */
@@ -59,17 +66,38 @@
 #endif
 {
     struct inode *inode = dentry->d_inode;
-    int internal_flag = 0;
+    const char* n;
+    int ret = -EOPNOTSUPP;
 
-    internal_flag = convert_to_internal_xattr_flags(flags);
-    return pvfs2_inode_setxattr(inode, name, value, size, internal_flag);
+    if((n = pvfs2_strcmp_prefix(name, PVFS2_XATTR_NAME_TRUSTED_PREFIX)))
+    {
+        ret = pvfs2_xattr_set_trusted(inode, n, value, size, flags);
+    }
+    else
+    {
+        ret = pvfs2_xattr_set_default(inode, name, value, size, flags);
+    }
+
+    return ret;
 }
 
 ssize_t pvfs2_getxattr(struct dentry *dentry, const char *name,
 		         void *buffer, size_t size)
 {
     struct inode *inode = dentry->d_inode;
-    return pvfs2_inode_getxattr(inode, name, buffer, size);
+    const char* n;
+    int ret = -EOPNOTSUPP;
+
+    if((n = pvfs2_strcmp_prefix(name, PVFS2_XATTR_NAME_TRUSTED_PREFIX)))
+    {
+        ret = pvfs2_xattr_get_trusted(inode, n, buffer, size);
+    }
+    else
+    {
+        ret = pvfs2_xattr_get_default(inode, name, buffer, size);
+    }
+
+    return ret;
 }
 
 #endif
@@ -83,7 +111,7 @@
 int pvfs2_removexattr(struct dentry *dentry, const char *name)
 {
     struct inode *inode = dentry->d_inode;
-    return pvfs2_inode_removexattr(inode, name);
+    return pvfs2_inode_removexattr(inode, NULL, name);
 }
 
 #endif
diff -Naur pvfs2A/src/kernel/linux-2.6/xattr_default.c pvfs2B/src/kernel/linux-2.6/xattr_default.c
--- pvfs2A/src/kernel/linux-2.6/xattr_default.c	2005-10-06 17:11:40.000000000 +0200
+++ pvfs2B/src/kernel/linux-2.6/xattr_default.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,60 +0,0 @@
-/*
- * (C) 2001 Clemson University and The University of Chicago
- *
- * See COPYING in top-level directory.
- */
-
-/** \file
- *  \ingroup pvfs2linux
- *
- *  Extended attributes for PVFS2 that handles all setxattr
- *  stuff even for those keys that do not have a prefix!
- *  This is the 2.6 kernels way of doing extended attributes
- */
-
-#include "pvfs2-kernel.h"
-#include "pvfs2-bufmap.h"
-
-#if !defined(PVFS2_LINUX_KERNEL_2_4) && defined(HAVE_GENERIC_GETXATTR)
-
-#include <linux/xattr.h>
-
-static int pvfs2_xattr_get_default(struct inode *inode,
-        const char *name, void *buffer, size_t size)
-{
-    if (strcmp(name, "") == 0)
-        return -EINVAL;
-    return pvfs2_inode_getxattr(inode, name, buffer, size);
-}
-
-static int pvfs2_xattr_set_default(struct inode *inode, 
-        const char *name, const void *buffer, size_t size, int flags)
-{
-    int internal_flag = 0;
-
-    if (strcmp(name, "") == 0)
-        return -EINVAL;
-    internal_flag = convert_to_internal_xattr_flags(flags);
-    return pvfs2_inode_setxattr(inode, name, buffer, size, internal_flag);
-}
-
-struct xattr_handler pvfs2_xattr_default_handler = {
-    /* 
-     * NOTE: this is set to be the empty string.
-     * so that all un-prefixed xattrs keys get caught
-     * here!
-     */
-    .prefix = PVFS2_XATTR_NAME_DEFAULT, 
-    .get    = pvfs2_xattr_get_default,
-    .set    = pvfs2_xattr_set_default,
-};
-
-#endif
-/*
- * Local variables:
- *  c-indent-level: 4
- *  c-basic-offset: 4
- * End:
- *
- * vim: ts=8 sts=4 sw=4 expandtab
- */
---------------------
PatchSet 433 
Date: 2006/02/22 14:28:57
Author: pcarns
Branch: HEAD
Tag: (none) 
Log:
Removed unecessary printk's in the listxattr code path
[artf30851]

Members: 
	src/kernel/linux-2.6/pvfs2-utils.c:1.17->1.18 

Index: src/kernel/linux-2.6/pvfs2-utils.c
diff -u src/kernel/linux-2.6/pvfs2-utils.c:1.17 src/kernel/linux-2.6/pvfs2-utils.c:1.18
--- src/kernel/linux-2.6/pvfs2-utils.c:1.17	Wed Jan  4 08:51:01 2006
+++ src/kernel/linux-2.6/pvfs2-utils.c	Wed Feb 22 07:28:57 2006
@@ -842,14 +842,6 @@
             }
         }
     done:
-        if (ret == 0 && buffer != NULL)
-        {
-            for (i = 0; i < total; i++)
-            {
-                printk("%c", buffer[i]);
-            }
-            printk("\n");
-        }
         pvfs2_print("pvfs2_inode_listxattr: returning %d\n", ret ? (int) ret : (int) total);
         /* when request is serviced properly, free req op struct */
         op_release(new_op);
---------------------
PatchSet 436 
Date: 2006/02/22 15:02:27
Author: pcarns
Branch: HEAD
Tag: (none) 
Log:
Bug fix: corrected error handling paths in all server side xattr state
machines
[artf30852]

Members: 
	src/server/get-eattr.sm:1.1->1.2 
	src/server/list-eattr.sm:1.1->1.2 
	src/server/set-eattr.sm:1.1->1.2 

Index: src/server/get-eattr.sm
diff -u src/server/get-eattr.sm:1.1 src/server/get-eattr.sm:1.2
--- src/server/get-eattr.sm:1.1	Mon Aug  1 10:13:06 2005
+++ src/server/get-eattr.sm	Wed Feb 22 08:02:27 2006
@@ -123,10 +123,16 @@
     PINT_STATE_DEBUG("setup_resp");
     gossip_debug(GOSSIP_GETEATTR_DEBUG,"geteattr requesting %d keys\n",
             s_op->req->u.geteattr.nkey);
+
+    js_p->error_code = 0;
+
     s_op->resp.u.geteattr.val =
         malloc(s_op->req->u.geteattr.nkey*sizeof(PVFS_ds_keyval));
     if (!s_op->resp.u.geteattr.val)
-        return -PVFS_ENOMEM;
+    {
+        js_p->error_code = -PVFS_ENOMEM;
+        return(1);
+    }
     s_op->resp.u.geteattr.nkey = s_op->req->u.geteattr.nkey;
     for (i = 0, tsz = 0; i < s_op->req->u.geteattr.nkey; i++)
         tsz += s_op->req->u.geteattr.valsz[i];
@@ -135,7 +141,8 @@
     {
         s_op->resp.u.geteattr.nkey = 0;
         free (s_op->resp.u.geteattr.val);
-        return -PVFS_ENOMEM;
+        js_p->error_code = -PVFS_ENOMEM;
+        return(1);
     }
     gossip_debug(GOSSIP_GETEATTR_DEBUG,"geteattr buffer size %d bytes\n",
             tsz);
Index: src/server/list-eattr.sm
diff -u src/server/list-eattr.sm:1.1 src/server/list-eattr.sm:1.2
--- src/server/list-eattr.sm:1.1	Wed Nov  2 06:53:53 2005
+++ src/server/list-eattr.sm	Wed Feb 22 08:02:27 2006
@@ -122,10 +122,17 @@
     PINT_STATE_DEBUG("setup_resp");
     gossip_debug(GOSSIP_LISTEATTR_DEBUG, "listeattr requesting %d keys\n",
             s_op->req->u.listeattr.nkey);
+
+    js_p->error_code = 0;
+
     s_op->resp.u.listeattr.key =
         malloc(s_op->req->u.listeattr.nkey * sizeof(PVFS_ds_keyval));
     if (!s_op->resp.u.listeattr.key)
-        return -PVFS_ENOMEM;
+    {
+        js_p->error_code = -PVFS_ENOMEM;
+        return(1);
+    }
+
     s_op->resp.u.listeattr.nkey = s_op->req->u.listeattr.nkey;
     for (i = 0, tsz = 0; i < s_op->req->u.listeattr.nkey; i++)
         tsz += s_op->req->u.listeattr.keysz[i];
@@ -134,7 +141,8 @@
     {
         s_op->resp.u.listeattr.nkey = 0;
         free (s_op->resp.u.listeattr.key);
-        return -PVFS_ENOMEM;
+        js_p->error_code = -PVFS_ENOMEM;
+        return(1);
     }
     gossip_debug(GOSSIP_LISTEATTR_DEBUG,"listeattr buffer size %d bytes\n",
             tsz);
@@ -215,7 +223,10 @@
     {
         tmp_valid = (int *) calloc(1, s_op->resp.u.listeattr.nkey * sizeof(int));
         if (tmp_valid == NULL)
+        {
             js_p->error_code = -PVFS_ENOMEM;
+            return(1);
+        }
     }
     a_p = &s_op->attr;
     gossip_debug(GOSSIP_LISTEATTR_DEBUG,"listeattr obtained %d instead of %d keys\n",
Index: src/server/set-eattr.sm
diff -u src/server/set-eattr.sm:1.1 src/server/set-eattr.sm:1.2
--- src/server/set-eattr.sm:1.1	Mon Aug  1 10:13:11 2005
+++ src/server/set-eattr.sm	Wed Feb 22 08:02:27 2006
@@ -130,7 +132,7 @@
             {
                 /* can't set these keys with this request */
                 js_p->error_code = -PVFS_EINVAL;
-                return -PVFS_EINVAL;
+                return 1;
             }
         case PVFS_TYPE_SYMLINK :
             if (!strncmp(s_op->req->u.seteattr.key[i].buffer,
@@ -139,7 +141,7 @@
             {
                 /* can't set these keys with this request */
                 js_p->error_code = -PVFS_EINVAL;
-                return -PVFS_EINVAL;
+                return 1;
             }
         case PVFS_TYPE_DIRECTORY :
             if (!strncmp(s_op->req->u.seteattr.key[i].buffer,
@@ -148,7 +150,7 @@
             {
                 /* can't set these keys with this request */
                 js_p->error_code = -PVFS_EINVAL;
-                return -PVFS_EINVAL;
+                return 1;
             }
         default :
             /* no holds barred for other types */
@@ -162,7 +164,7 @@
         {
             /* can't set these keys with this request */
             js_p->error_code = -PVFS_EINVAL;
-            return -PVFS_EINVAL;
+            return 1;
         }
     }
 
---------------------
PatchSet 440 
Date: 2006/02/22 22:04:31
Author: pcarns
Branch: HEAD
Tag: (none) 
Log:
Adjusted list-eattr.sm to make all attributes that are not in a name space
appear in the "system." namespace for clients.  Removed keyword filtering
logic.
[artf30912]

Members: 
	src/server/list-eattr.sm:1.2->1.3 
	src/server/pvfs2-server.c:1.31->1.32 
	src/server/pvfs2-server.h:1.21->1.22 

Index: src/server/list-eattr.sm
diff -u src/server/list-eattr.sm:1.2 src/server/list-eattr.sm:1.3
--- src/server/list-eattr.sm:1.2	Wed Feb 22 08:02:27 2006
+++ src/server/list-eattr.sm	Wed Feb 22 15:04:31 2006
@@ -205,173 +205,98 @@
 }
 #endif
 
-/*
- * listeattr_check_resp()
- * Check the response - handle any errors
- * We also need to do filtering here to prevent TROVE_COMMON_KEYS from
- * being made visible to the users
- * Possibly others if we decide acl's should not be made visible...
+/* listeattr_check_resp()
+ *
+ * checks what attributes we found, handles errors, filters for appropriate
+ * extended attribute name spaces
+ *
+ * NOTE: all attributes should fall into one of the name spaces defined in 
+ * the PINT_eattr_namespaces array.  If we find a key that does not, then we
+ * will translate it so that it appears in the "system." name
+ * space on the client side.
  */
 static int listeattr_check_resp(PINT_server_op *s_op, job_status_s *js_p)
 {
-    int k, count_valid = 0, error = 0, tmp_size = 0, *tmp_valid = NULL, orig_size = 0;
-    char *tmp_buffer = NULL;
-    PVFS_object_attr *a_p = NULL;
+    int num_found = 0;
+    int i = 0;
+    char* tmp_buffer = NULL;
+    char translate_prefix[] = "system.";
+    int translate_prefix_len = strlen("system.");
+    int ret = 0;
 
-    PINT_STATE_DEBUG("check_resp");
-    if (s_op->resp.u.listeattr.nkey > 0)
-    {
-        tmp_valid = (int *) calloc(1, s_op->resp.u.listeattr.nkey * sizeof(int));
-        if (tmp_valid == NULL)
-        {
-            js_p->error_code = -PVFS_ENOMEM;
-            return(1);
-        }
-    }
-    a_p = &s_op->attr;
-    gossip_debug(GOSSIP_LISTEATTR_DEBUG,"listeattr obtained %d instead of %d keys\n",
-            js_p->count, s_op->resp.u.listeattr.nkey);
-    /* put the returned read buffer size in buffer_sz */
-    /* it is the only thing returned across the wire */
-    gossip_debug(GOSSIP_LISTEATTR_DEBUG,"status %d error_code %d nkeys %d spare_buffer %p\n",
-            s_op->resp.status, js_p->error_code, s_op->resp.u.listeattr.nkey, s_op->u.eattr.buffer);
-    for (k = 0; k < s_op->resp.u.listeattr.nkey; k++)
-    {
-        orig_size += s_op->req->u.listeattr.keysz[k];
-        if (js_p->error_code == 0)
-        {
-            gossip_debug(GOSSIP_LISTEATTR_DEBUG, "key[%d] = %p\n",
-                             k, s_op->resp.u.listeattr.key[k].buffer);
-            if (a_p->objtype == PVFS_TYPE_METAFILE)
-            {
-                /* dont even check these if they are not valid */
-                if (k >= js_p->count)
-                {
-                    continue;
-                }
-                /* We dont wish to return these keys.. */
-                if (!strncmp(s_op->resp.u.listeattr.key[k].buffer,
-                    Trove_Common_Keys[METAFILE_HANDLES_KEY].key,
-                    s_op->resp.u.listeattr.key[k].read_sz) ||
-                    !strncmp(s_op->resp.u.listeattr.key[k].buffer,
-                    Trove_Common_Keys[METAFILE_DIST_KEY].key,
-                    s_op->resp.u.listeattr.key[k].read_sz))
-                {
-                    continue;
-                }
-            }
-            else if (a_p->objtype == PVFS_TYPE_SYMLINK)
-            {
-                /* dont even check these if they are not valid */
-                if (k >= js_p->count)
-                {
-                    continue;
-                }
-                if (!strncmp(s_op->resp.u.listeattr.key[k].buffer,
-                    Trove_Common_Keys[SYMLINK_TARGET_KEY].key,
-                    s_op->resp.u.listeattr.key[k].read_sz))
-                {
-                    continue;
-                }
-            }
-            else if (a_p->objtype == PVFS_TYPE_DIRECTORY)
-            {
-                /* dont even check these if they are not valid */
-                if (k >= js_p->count)
-                {
-                    continue;
-                }
-                if (!strncmp(s_op->resp.u.listeattr.key[k].buffer,
-                    Trove_Common_Keys[DIR_ENT_KEY].key,
-                    s_op->resp.u.listeattr.key[k].read_sz))
-                {
-                    continue;
-                }
-            }
-            tmp_valid[k] = s_op->resp.u.listeattr.key[k].read_sz;
-            count_valid++;
-            tmp_size += s_op->resp.u.listeattr.key[k].read_sz;
-            s_op->resp.u.listeattr.key[k].buffer_sz =
-                s_op->resp.u.listeattr.key[k].read_sz;
-        }
-        /* in case of any errors, we initialize it to 0 */
-        else {
-            s_op->resp.u.listeattr.key[k].buffer_sz = 0;
-            s_op->resp.u.listeattr.key[k].read_sz = 0;
-            error = 1;
-        }
-    }
-    /* On any errors, return */
-    if (error) 
-    {
-        if (tmp_valid)
-            free(tmp_valid);
-        return 1;
-    }
     /* Nothing was requested? then fill token to hold the max available keys */
     if (s_op->resp.u.listeattr.nkey == 0)
     {
         s_op->resp.u.listeattr.token = js_p->count;
-        if (tmp_valid)
-            free(tmp_valid);
+        js_p->error_code = 0;
         return 1;
     }
-    s_op->resp.u.listeattr.token = js_p->position;
-    /* if nothing has to be filtered, then return */
-    if (count_valid == s_op->resp.u.listeattr.nkey)
+
+    /* how many entries did we find that we can process? */
+    num_found = js_p->count;
+    if(num_found > s_op->resp.u.listeattr.nkey)
     {
-        if (tmp_valid)
-            free(tmp_valid);
-        return 1;
+        num_found = s_op->resp.u.listeattr.nkey;
     }
-    /* Allocate something large enough to hold the filtered set of keys */
-    tmp_buffer = (char *) calloc(1, tmp_size);
-    if (tmp_buffer == NULL)
+
+    s_op->resp.u.listeattr.token = js_p->position;
+    s_op->resp.u.listeattr.nkey = num_found;
+
+    if(num_found == 0)
+    {
+        /* there aren't any extended attr's; go ahead and return */
+        js_p->error_code = 0;
+        return(1);
+    }
+  
+    tmp_buffer = (char*)malloc(PVFS_REQ_LIMIT_KEY_LEN);
+    if(!tmp_buffer)
     {
-        if (tmp_valid)
-            free(tmp_valid);
         js_p->error_code = -PVFS_ENOMEM;
-        for (k = 0; k < s_op->resp.u.listeattr.nkey; k++)
-        {
-            s_op->resp.u.listeattr.key[k].buffer_sz = 0;
-        }
-        return 1;
+        return(1);
     }
-    gossip_debug(GOSSIP_LISTEATTR_DEBUG, "tmp_buffer (%p,%d) spare_buffer (%p,%d)\n", 
-        tmp_buffer, tmp_size, s_op->u.eattr.buffer, orig_size);
-    tmp_size = 0;
-    count_valid = 0;
-    for (k = 0; k <  s_op->resp.u.listeattr.nkey; k++)
+
+    /* iterate through the keys that we found */
+    for(i=0; i<num_found; i++)
     {
-        if (tmp_valid[k] > 0)
+        /* check to see if it is prefixed into a supported name space */
+        if(!PINT_eattr_is_prefixed(s_op->resp.u.listeattr.key[i].buffer))
         {
-            gossip_debug(GOSSIP_LISTEATTR_DEBUG, "tmp_size = %d tmp_valid[%d] = %d buf = %s(%p)\n",
-                    tmp_size, k, tmp_valid[k], (char *)s_op->resp.u.listeattr.key[k].buffer,
-                    s_op->resp.u.listeattr.key[k].buffer);
-            memcpy(tmp_buffer + tmp_size, s_op->resp.u.listeattr.key[k].buffer, tmp_valid[k]);
-            s_op->resp.u.listeattr.key[count_valid].buffer = (char *) s_op->u.eattr.buffer + tmp_size; 
-            gossip_debug(GOSSIP_LISTEATTR_DEBUG, "buf [%d] = %p\n", 
-                    count_valid, s_op->resp.u.listeattr.key[count_valid].buffer);
-            tmp_size += tmp_valid[k];
-            s_op->resp.u.listeattr.key[count_valid].read_sz 
-                     = s_op->resp.u.listeattr.key[count_valid].buffer_sz = tmp_valid[k];
-            gossip_debug(GOSSIP_LISTEATTR_DEBUG, "k = %d read_sz: %d\n", k, tmp_valid[k]);
-            count_valid++;
+            /* we need to tack on a "system." prefix */
+
+            /* find out if the key size requested is large enough */
+            if((translate_prefix_len + s_op->resp.u.listeattr.key[i].read_sz) >
+                s_op->req->u.listeattr.keysz[i])
+            {
+                /* NOTE: trying to mimic the semantics of
+                 * trove_keyval_iterate_keys(): it will also report an
+                 * overall error if one of the key buffers is to small,
+                 * though the choice of error code may be different.
+                 */
+                free(tmp_buffer);
+                js_p->error_code = -PVFS_EMSGSIZE;
+                return(1);
+            }
+
+            /* add a prefix onto the key and adjust sizes accordingly */
+            /* NOTE: this will have to change if we ever permit non-string
+             * keys (which would break using them for xattrs anyway)
+             */
+            ret = sprintf(tmp_buffer,
+                "%s%s", translate_prefix,
+                (char*)s_op->resp.u.listeattr.key[i].buffer);
+            memcpy(s_op->resp.u.listeattr.key[i].buffer, tmp_buffer,
+                (ret+1));
+            s_op->resp.u.listeattr.key[i].read_sz += translate_prefix_len;
         }
-    }
-    /* Copy it to the scratch buffer */
-    memcpy(s_op->u.eattr.buffer, tmp_buffer, tmp_size);
-    for (k = 0; k < count_valid; k++)
-    {
-        gossip_debug(GOSSIP_LISTEATTR_DEBUG, "afterwards buf[%d] = %s (%p)\n", k,
-                (char *) s_op->resp.u.listeattr.key[k].buffer, s_op->resp.u.listeattr.key[k].buffer);
-    }
-    s_op->resp.u.listeattr.nkey = count_valid;
+
+        s_op->resp.u.listeattr.key[i].buffer_sz =
+            s_op->resp.u.listeattr.key[i].read_sz;
+    }    
+
     free(tmp_buffer);
-    free(tmp_valid);
-    gossip_debug(GOSSIP_LISTEATTR_DEBUG, "listeattr returning %d keys after filtering\n",
-                    count_valid);
-    return 1;
+    js_p->error_code = 0;
+    return(1);
 }
 
 /* listeattr_cleanup()
Index: src/server/pvfs2-server.c
diff -u src/server/pvfs2-server.c:1.31 src/server/pvfs2-server.c:1.32
--- src/server/pvfs2-server.c:1.31	Tue Feb 21 14:25:47 2006
+++ src/server/pvfs2-server.c	Wed Feb 22 15:04:31 2006
@@ -119,6 +119,16 @@
     {"symlink_target", 15}
 };
 
+/* extended attribute name spaces supported in PVFS2 */
+char *PINT_eattr_namespaces[] =
+{
+    "system.",
+    "user.",
+    "trusted.",
+    "security.",
+    NULL
+};
+
 /* These three are used continuously in our wait loop.  They could be
  * relatively large, so rather than allocate them on the stack, we'll
  * make them dynamically allocated globals.
Index: src/server/pvfs2-server.h
diff -u src/server/pvfs2-server.h:1.21 src/server/pvfs2-server.h:1.22
--- src/server/pvfs2-server.h:1.21	Fri Feb 10 17:07:17 2006
+++ src/server/pvfs2-server.h	Wed Feb 22 15:04:31 2006
@@ -19,6 +19,7 @@
 #include <sys/types.h>
 #include <pwd.h>
 #include <grp.h>
+#include <string.h>
 #include "pvfs2-debug.h"
 #include "pvfs2-storage.h"
 #include "job.h"
@@ -116,6 +117,29 @@
             PINT_server_req_table[op].string_name);
 }
 
+extern char*PINT_eattr_namespaces[];
+/* PINT_eattr_is_prefixed()
+ *
+ * This function will check to see if a given xattr key falls into the set of
+ * name spaces that PVFS2 supports
+ *
+ * returns 1 if the prefix is supported, 0 otherwise
+ */
+static inline int PINT_eattr_is_prefixed(char* key_name)
+{
+    int i = 0;
+    while(PINT_eattr_namespaces[i])
+    {
+        if(strncmp(PINT_eattr_namespaces[i], key_name,
+            strlen(PINT_eattr_namespaces[i])) == 0)
+        {
+            return(1);
+        }
+        i++;
+    }
+    return(0);
+}
+
 /* used to keep a random, but handy, list of keys around */
 typedef struct PINT_server_trove_keys
 {
---------------------
PatchSet 441 
Date: 2006/02/22 22:08:55
Author: pcarns
Branch: HEAD
Tag: (none) 
Log:
further list-eattr.sm refinement: put internal attributes in the
system.pvfs2. name space rather than the system. name space to make sure that
we avoid collisions.
[artf30912]

Members: 
	src/server/list-eattr.sm:1.3->1.4 

Index: src/server/list-eattr.sm
diff -u src/server/list-eattr.sm:1.3 src/server/list-eattr.sm:1.4
--- src/server/list-eattr.sm:1.3	Wed Feb 22 15:04:31 2006
+++ src/server/list-eattr.sm	Wed Feb 22 15:08:55 2006
@@ -212,7 +212,7 @@
  *
  * NOTE: all attributes should fall into one of the name spaces defined in 
  * the PINT_eattr_namespaces array.  If we find a key that does not, then we
- * will translate it so that it appears in the "system." name
+ * will translate it so that it appears in the "system.pvfs2." name
  * space on the client side.
  */
 static int listeattr_check_resp(PINT_server_op *s_op, job_status_s *js_p)
@@ -220,8 +220,8 @@
     int num_found = 0;
     int i = 0;
     char* tmp_buffer = NULL;
-    char translate_prefix[] = "system.";
-    int translate_prefix_len = strlen("system.");
+    char translate_prefix[] = "system.pvfs2.";
+    int translate_prefix_len = strlen("system.pvfs2.");
     int ret = 0;
 
     /* Nothing was requested? then fill token to hold the max available keys */
@@ -262,7 +262,7 @@
         /* check to see if it is prefixed into a supported name space */
         if(!PINT_eattr_is_prefixed(s_op->resp.u.listeattr.key[i].buffer))
         {
-            /* we need to tack on a "system." prefix */
+            /* we need to tack on a "system.pvfs2." prefix */
 
             /* find out if the key size requested is large enough */
             if((translate_prefix_len + s_op->resp.u.listeattr.key[i].read_sz) >
---------------------
PatchSet 442 
Date: 2006/02/22 22:40:39
Author: pcarns
Branch: HEAD
Tag: (none) 
Log:
Adjusted get-eattr.sm to check for proper name space usage and to translate
items in the system.pvfs2. name space
[artf30912]

Members: 
	src/apps/admin/pvfs2-viewdist.c:1.2->1.3 
	src/server/get-eattr.sm:1.2->1.3 

Index: src/apps/admin/pvfs2-viewdist.c
diff -u src/apps/admin/pvfs2-viewdist.c:1.2 src/apps/admin/pvfs2-viewdist.c:1.3
--- src/apps/admin/pvfs2-viewdist.c:1.2	Tue Jan 17 19:55:11 2006
+++ src/apps/admin/pvfs2-viewdist.c	Wed Feb 22 15:40:39 2006
@@ -80,8 +80,8 @@
 ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size);
 #endif
 
-#define DIST_KEY "metafile_dist"
-#define DFILE_KEY "datafile_handles"
+#define DIST_KEY "system.pvfs2.metafile_dist"
+#define DFILE_KEY "system.pvfs2.datafile_handles"
 
 static int generic_dist(file_object *obj, PVFS_credentials *creds,
         char **dist, int *size)
@@ -109,7 +109,7 @@
         if ((ret = PVFS_sys_geteattr(obj->u.pvfs2.ref, 
                 creds, &key, &val)) < 0)
         {
-            PVFS_perror("PVFS_sys_geteattr failed %d\n", ret);
+            PVFS_perror("PVFS_sys_geteattr", ret);
             return -1;
         }
         *size = val.read_sz;
@@ -151,7 +151,7 @@
         if ((ret = PVFS_sys_geteattr(obj->u.pvfs2.ref, 
                 creds, &key, &val)) < 0)
         {
-            PVFS_perror("PVFS_sys_geteattr failed %d\n", ret);
+            PVFS_perror("PVFS_sys_geteattr", ret);
             return -1;
         }
         ret = val.read_sz;
Index: src/server/get-eattr.sm
diff -u src/server/get-eattr.sm:1.2 src/server/get-eattr.sm:1.3
--- src/server/get-eattr.sm:1.2	Wed Feb 22 08:02:27 2006
+++ src/server/get-eattr.sm	Wed Feb 22 15:40:39 2006
@@ -25,32 +25,6 @@
 #include "pvfs2-util.h"
 #include "pint-util.h"
 
-static inline char *get_object_type(int objtype)
-{
-    static char *obj_types[] =
-    {
-        "NONE", "METAFILE", "DATAFILE",
-        "DIRECTORY", "SYMLINK", "DIRDATA", "UNKNOWN"
-    };
-
-    switch(objtype)
-    {
-        case PVFS_TYPE_NONE:
-            return obj_types[0];
-        case PVFS_TYPE_METAFILE:
-            return obj_types[1];
-        case PVFS_TYPE_DATAFILE:
-            return obj_types[2];
-        case PVFS_TYPE_DIRECTORY:
-            return obj_types[3];
-        case PVFS_TYPE_SYMLINK:
-            return obj_types[4];
-        case PVFS_TYPE_DIRDATA:
-            return obj_types[5];
-    }
-    return obj_types[6];
-}
-
 static int geteattr_setup_resp(
     PINT_server_op *s_op, job_status_s *js_p);
 static int geteattr_read_eattrib(
@@ -120,16 +94,62 @@
 static int geteattr_setup_resp(PINT_server_op *s_op, job_status_s *js_p)
 {
     int i, tsz;
+    char reserved_prefix[] = "system.pvfs2.";
+    int reserved_prefix_len = strlen("system.pvfs2.");
+    char* tmp_buffer = NULL;
+    int tmp_len = 0;
+    int ret;
+
     PINT_STATE_DEBUG("setup_resp");
     gossip_debug(GOSSIP_GETEATTR_DEBUG,"geteattr requesting %d keys\n",
             s_op->req->u.geteattr.nkey);
 
     js_p->error_code = 0;
+ 
+    tmp_buffer = (char*)malloc(PVFS_REQ_LIMIT_KEY_LEN);
+    if(!tmp_buffer)
+    {
+        js_p->error_code = -PVFS_ENOMEM;
+        return(1);
+    }
+
+    /* iterate through the keys and see if they fall into valid name spaces */
+    for(i=0; i<s_op->req->u.geteattr.nkey; i++)
+    {
+        if(!PINT_eattr_is_prefixed(s_op->req->u.geteattr.key[i].buffer))
+        {
+            /* not prefixed: treat this as if the key does not exist */
+            free(tmp_buffer);
+            js_p->error_code = -PVFS_ENOENT;
+            return(1);
+        }
+
+        /* look for keys in the special "system.pvfs2." prefix and strip the
+         * prefix off; they are stored as keyvals with no prefix within
+         * trove.
+         */
+        if(strncmp(s_op->req->u.geteattr.key[i].buffer, reserved_prefix,
+            reserved_prefix_len) == 0)
+        {
+            ret = sscanf(s_op->req->u.geteattr.key[i].buffer,
+                "system.pvfs2.%s", tmp_buffer);
+            if(ret != 1)
+            {
+                free(tmp_buffer);
+                js_p->error_code = -PVFS_ENOENT;
+                return(1);
+            }
+            tmp_len = strlen(tmp_buffer) + 1;
+            memcpy(s_op->req->u.geteattr.key[i].buffer, tmp_buffer, tmp_len);
+            s_op->req->u.geteattr.key[i].buffer_sz = tmp_len;
+        }
+    }
 
     s_op->resp.u.geteattr.val =
         malloc(s_op->req->u.geteattr.nkey*sizeof(PVFS_ds_keyval));
     if (!s_op->resp.u.geteattr.val)
     {
+        free(tmp_buffer);
         js_p->error_code = -PVFS_ENOMEM;
         return(1);
     }
@@ -141,6 +161,7 @@
     {
         s_op->resp.u.geteattr.nkey = 0;
         free (s_op->resp.u.geteattr.val);
+        free(tmp_buffer);
         js_p->error_code = -PVFS_ENOMEM;
         return(1);
     }
@@ -154,6 +175,7 @@
             (char *) s_op->u.eattr.buffer + tsz;
         tsz += s_op->req->u.geteattr.valsz[i];
     }
+    free(tmp_buffer);
     return 1;
 }
 
---------------------
PatchSet 445 
Date: 2006/02/23 16:55:41
Author: pcarns
Branch: HEAD
Tag: (none) 
Log:
Adjusted set-eattr to properly inforce that xattr keys must be in a known
name space, and that keys in the system.pvfs2 name space cannot be modified.
[artf30912]

Members: 
	src/server/set-eattr.sm:1.2->1.3 

Index: src/server/set-eattr.sm
diff -u src/server/set-eattr.sm:1.2 src/server/set-eattr.sm:1.3
--- src/server/set-eattr.sm:1.2	Wed Feb 22 08:02:27 2006
+++ src/server/set-eattr.sm	Thu Feb 23 09:55:41 2006
@@ -91,18 +91,16 @@
 %%
 
 /*
- * This routine really just does debugging - can print out info about
- * the target of the operation.  There are few things to verify here
- * be we'll try to verify what we can.  We can also disallow setting
- * extended attributes on certain object types if we want.  We might
- * want to prevent access to standard metadata keys.
- *
+ * This routine checks keys to confirm that the name spaces are valid.
+ * It also prints debugging information.
  */
 static int seteattr_verify_eattribs(
     PINT_server_op *s_op, job_status_s *js_p)
 {
     PVFS_object_attr *a_p = NULL;
     int i;
+    char reserved_prefix[] = "system.pvfs2.";
+    int reserved_prefix_len = strlen("system.pvfs2.");
 
     PINT_STATE_DEBUG("verify_eattribs");
 
@@ -117,57 +115,28 @@
                  get_object_type(a_p->objtype),
                  a_p->owner, a_p->group, a_p->perms, a_p->objtype);
 
-    /* if any key is bad, we reject the whole list */
+    /* iterate through the keys that are being written */
     for (i = 0; i < s_op->req->u.seteattr.nkey; i++)
     {
-        switch (a_p->objtype)
+        /* make sure that they all fall into a supported name space */
+        if(!PINT_eattr_is_prefixed(s_op->req->u.seteattr.key[i].buffer))
         {
-        case PVFS_TYPE_METAFILE :
-            if (!strncmp(s_op->req->u.seteattr.key[i].buffer,
-                        Trove_Common_Keys[METAFILE_HANDLES_KEY].key,
-                        s_op->req->u.seteattr.key[i].buffer_sz) ||
-                !strncmp(s_op->req->u.seteattr.key[i].buffer,
-                        Trove_Common_Keys[METAFILE_DIST_KEY].key,
-                        s_op->req->u.seteattr.key[i].buffer_sz))
-            {
-                /* can't set these keys with this request */
-                js_p->error_code = -PVFS_EINVAL;
-                return 1;
-            }
-        case PVFS_TYPE_SYMLINK :
-            if (!strncmp(s_op->req->u.seteattr.key[i].buffer,
-                        Trove_Common_Keys[SYMLINK_TARGET_KEY].key,
-                        s_op->req->u.seteattr.key[i].buffer_sz))
-            {
-                /* can't set these keys with this request */
-                js_p->error_code = -PVFS_EINVAL;
-                return 1;
-            }
-        case PVFS_TYPE_DIRECTORY :
-            if (!strncmp(s_op->req->u.seteattr.key[i].buffer,
-                        Trove_Common_Keys[DIR_ENT_KEY].key,
-                        s_op->req->u.seteattr.key[i].buffer_sz))
-            {
-                /* can't set these keys with this request */
-                js_p->error_code = -PVFS_EINVAL;
-                return 1;
-            }
-        default :
-            /* no holds barred for other types */
-            ;
+            /* emulating return code seen on ext3 */
+            js_p->error_code = -PVFS_EOPNOTSUPP;
+            return 1;
         }
 
-        /* no one is allowed to set standard attribs with this op */
-        if (!strncmp((void *)s_op->req->u.seteattr.key[i].buffer,
-                    (void *)&s_op->req->u.seteattr.handle,
-                    sizeof(s_op->req->u.seteattr.handle)))
+        /* don't allow anyone to set things in the system.pvfs2 name space */
+        if(strncmp(s_op->req->u.seteattr.key[i].buffer, reserved_prefix,
+            reserved_prefix_len) == 0)
         {
-            /* can't set these keys with this request */
+            /* what error code make sense here? */
             js_p->error_code = -PVFS_EINVAL;
             return 1;
         }
     }
 
+    js_p->error_code = 0;
     return 1;
 }
 
_______________________________________________
Pvfs2-developers mailing list
[email protected]
http://www.beowulf-underground.org/mailman/listinfo/pvfs2-developers

Reply via email to