Whamcloud - gitweb
branch: b1_4
authorericm <ericm>
Thu, 13 Oct 2005 05:23:42 +0000 (05:23 +0000)
committerericm <ericm>
Thu, 13 Oct 2005 05:23:42 +0000 (05:23 +0000)
land b1_4_xattr: support manipulating user extended attributes.

31 files changed:
ldiskfs/kernel_patches/patches/ext3-ea-in-inode-2.6-rhel4.patch
lustre/include/linux/lustre_cfg.h
lustre/include/linux/lustre_compat25.h
lustre/include/linux/lustre_fsfilt.h
lustre/include/linux/lustre_idl.h
lustre/include/linux/lustre_lite.h
lustre/include/linux/lustre_mds.h
lustre/include/linux/obd_support.h
lustre/kernel_patches/patches/ext3-ea-in-inode-2.6-rhel4.patch
lustre/llite/Makefile.in
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/lproc_llite.c
lustre/llite/namei.c
lustre/llite/special.c
lustre/llite/symlink.c
lustre/llite/xattr.c [new file with mode: 0644]
lustre/lvfs/fsfilt_ext3.c
lustre/mdc/mdc_request.c
lustre/mds/Makefile.in
lustre/mds/handler.c
lustre/mds/mds_internal.h
lustre/mds/mds_xattr.c [new file with mode: 0644]
lustre/ptlrpc/lproc_ptlrpc.c
lustre/ptlrpc/pack_generic.c
lustre/tests/local.sh
lustre/tests/sanity.sh
lustre/utils/lconf
lustre/utils/llmount.c
lustre/utils/wiretest.c

index 9d5bee1..507b044 100644 (file)
@@ -1,7 +1,7 @@
 Index: linux-stage/fs/ext3/ialloc.c
 ===================================================================
---- linux-stage.orig/fs/ext3/ialloc.c  2005-02-25 16:47:04.411977280 +0200
-+++ linux-stage/fs/ext3/ialloc.c       2005-02-25 16:50:40.752088584 +0200
+--- linux-stage.orig/fs/ext3/ialloc.c  2005-10-04 16:53:24.000000000 -0600
++++ linux-stage/fs/ext3/ialloc.c       2005-10-04 17:07:25.000000000 -0600
 @@ -629,6 +629,11 @@
        spin_unlock(&sbi->s_next_gen_lock);
  
@@ -16,9 +16,9 @@ Index: linux-stage/fs/ext3/ialloc.c
        if(DQUOT_ALLOC_INODE(inode)) {
 Index: linux-stage/fs/ext3/inode.c
 ===================================================================
---- linux-stage.orig/fs/ext3/inode.c   2005-02-25 16:47:04.415976672 +0200
-+++ linux-stage/fs/ext3/inode.c        2005-02-25 16:50:40.756087976 +0200
-@@ -2274,7 +2274,7 @@ static unsigned long ext3_get_inode_bloc
+--- linux-stage.orig/fs/ext3/inode.c   2005-10-04 17:00:22.000000000 -0600
++++ linux-stage/fs/ext3/inode.c        2005-10-04 17:07:25.000000000 -0600
+@@ -2274,7 +2274,7 @@
   * trying to determine the inode's location on-disk and no read need be
   * performed.
   */
@@ -27,7 +27,7 @@ Index: linux-stage/fs/ext3/inode.c
                                struct ext3_iloc *iloc, int in_mem)
  {
        unsigned long block;
-@@ -2484,6 +2484,11 @@ void ext3_read_inode(struct inode * inod
+@@ -2484,6 +2484,11 @@
                ei->i_data[block] = raw_inode->i_block[block];
        INIT_LIST_HEAD(&ei->i_orphan);
  
@@ -39,7 +39,7 @@ Index: linux-stage/fs/ext3/inode.c
        if (S_ISREG(inode->i_mode)) {
                inode->i_op = &ext3_file_inode_operations;
                inode->i_fop = &ext3_file_operations;
-@@ -2619,6 +2624,9 @@ static int ext3_do_update_inode(handle_t
+@@ -2619,6 +2624,9 @@
        } else for (block = 0; block < EXT3_N_BLOCKS; block++)
                raw_inode->i_block[block] = ei->i_data[block];
  
@@ -49,7 +49,7 @@ Index: linux-stage/fs/ext3/inode.c
        BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
        rc = ext3_journal_dirty_metadata(handle, bh);
        if (!err)
-@@ -2849,7 +2857,8 @@ ext3_reserve_inode_write(handle_t *handl
+@@ -2849,7 +2857,8 @@
  {
        int err = 0;
        if (handle) {
@@ -61,19 +61,19 @@ Index: linux-stage/fs/ext3/inode.c
                        err = ext3_journal_get_write_access(handle, iloc->bh);
 Index: linux-stage/fs/ext3/xattr.c
 ===================================================================
---- linux-stage.orig/fs/ext3/xattr.c   2005-02-25 16:47:04.422975608 +0200
-+++ linux-stage/fs/ext3/xattr.c        2005-02-25 17:19:04.958009904 +0200
+--- linux-stage.orig/fs/ext3/xattr.c   2005-10-04 16:50:11.000000000 -0600
++++ linux-stage/fs/ext3/xattr.c        2005-10-04 17:19:43.000000000 -0600
 @@ -149,17 +149,12 @@
  }
  
  /*
 - * ext3_xattr_get()
-+ * ext3_xattr_block_get()
-  *
+- *
 - * Copy an extended attribute into the buffer
 - * provided, or compute the buffer size required.
 - * Buffer is NULL to compute the size of the buffer required.
-- *
++ * ext3_xattr_block_get()
+  *
 - * Returns a negative error number on failure, or the number of bytes
 - * used / required on success.
 + * routine looks for attribute in EA block and returns it's value and size
@@ -224,7 +224,7 @@ Index: linux-stage/fs/ext3/xattr.c
        error = 0;
        if (!EXT3_I(inode)->i_file_acl)
                goto cleanup;
-@@ -330,11 +419,139 @@
+@@ -330,11 +419,149 @@
  
  cleanup:
        brelse(bh);
@@ -245,6 +245,7 @@ Index: linux-stage/fs/ext3/xattr.c
 +      char *start, *end, *buf;
 +      struct ext3_iloc iloc;
 +      int storage_size;
++      size_t rest = buffer_size;
 +      int ret;
 +      int size = 0;
 +      
@@ -282,9 +283,8 @@ Index: linux-stage/fs/ext3/xattr.c
 +              }
 +              handler = ext3_xattr_handler(last->e_name_index);
 +              if (handler)
-+                      size = handler->list(inode, NULL, 0, last->e_name,
++                      size += handler->list(inode, NULL, 0, last->e_name,
 +                                            last->e_name_len);
-+                      
 +              last = next;
 +      }
 +
@@ -303,9 +303,19 @@ Index: linux-stage/fs/ext3/xattr.c
 +              struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
 +              struct xattr_handler *handler;
 +              handler = ext3_xattr_handler(last->e_name_index);
-+              if (handler)
-+                      buf += handler->list(inode, buf, (buffer+buffer_size)-buf, last->e_name,
-+                                            last->e_name_len);
++              if (handler) {
++                      size_t size = handler->list(inode, buffer, rest,
++                                                  last->e_name,
++                                                  last->e_name_len);
++                      if (buffer) {
++                              if (size > rest) {
++                                      ret = -ERANGE;
++                                      goto cleanup;
++                              }
++                              buffer += size;
++                      }
++                      rest -= size;
++              }
 +              last = next;
 +      }
 +      ret = size;
@@ -365,7 +375,7 @@ Index: linux-stage/fs/ext3/xattr.c
  /*
   * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
   * not set, set it.
-@@ -356,6 +573,279 @@
+@@ -356,6 +583,279 @@
  }
  
  /*
@@ -645,7 +655,7 @@ Index: linux-stage/fs/ext3/xattr.c
   * ext3_xattr_set_handle()
   *
   * Create, replace or remove an extended attribute for this inode. Buffer
-@@ -369,6 +859,104 @@
+@@ -369,6 +869,104 @@
   */
  int
  ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
@@ -750,7 +760,7 @@ Index: linux-stage/fs/ext3/xattr.c
                      const char *name, const void *value, size_t value_len,
                      int flags)
  {
-@@ -391,22 +979,7 @@
+@@ -391,22 +989,7 @@
         *             towards the end of the block).
         * end -- Points right after the block pointed to by header.
         */
@@ -773,7 +783,7 @@ Index: linux-stage/fs/ext3/xattr.c
        if (EXT3_I(inode)->i_file_acl) {
                /* The inode already has an extended attribute block. */
                bh = sb_bread(sb, EXT3_I(inode)->i_file_acl);
-@@ -638,7 +1211,6 @@
+@@ -638,7 +1221,6 @@
        brelse(bh);
        if (!(bh && header == HDR(bh)))
                kfree(header);
@@ -783,8 +793,8 @@ Index: linux-stage/fs/ext3/xattr.c
  }
 Index: linux-stage/fs/ext3/xattr.h
 ===================================================================
---- linux-stage.orig/fs/ext3/xattr.h   2005-02-25 16:47:04.423975456 +0200
-+++ linux-stage/fs/ext3/xattr.h        2005-02-25 16:50:40.763086912 +0200
+--- linux-stage.orig/fs/ext3/xattr.h   2005-10-04 16:50:11.000000000 -0600
++++ linux-stage/fs/ext3/xattr.h        2005-10-04 17:07:25.000000000 -0600
 @@ -67,7 +67,8 @@
  extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
  extern int ext3_xattr_list(struct inode *, char *, size_t);
@@ -797,8 +807,8 @@ Index: linux-stage/fs/ext3/xattr.h
  extern void ext3_xattr_put_super(struct super_block *);
 Index: linux-stage/include/linux/ext3_fs.h
 ===================================================================
---- linux-stage.orig/include/linux/ext3_fs.h   2005-02-25 16:47:04.425975152 +0200
-+++ linux-stage/include/linux/ext3_fs.h        2005-02-25 16:50:40.765086608 +0200
+--- linux-stage.orig/include/linux/ext3_fs.h   2005-10-04 16:53:29.000000000 -0600
++++ linux-stage/include/linux/ext3_fs.h        2005-10-04 17:07:25.000000000 -0600
 @@ -293,6 +293,8 @@
                        __u32   m_i_reserved2[2];
                } masix2;
@@ -818,8 +828,8 @@ Index: linux-stage/include/linux/ext3_fs.h
  extern int  ext3_write_inode (struct inode *, int);
 Index: linux-stage/include/linux/ext3_fs_i.h
 ===================================================================
---- linux-stage.orig/include/linux/ext3_fs_i.h 2005-02-25 16:47:04.426975000 +0200
-+++ linux-stage/include/linux/ext3_fs_i.h      2005-02-25 16:50:40.766086456 +0200
+--- linux-stage.orig/include/linux/ext3_fs_i.h 2005-10-04 16:50:11.000000000 -0600
++++ linux-stage/include/linux/ext3_fs_i.h      2005-10-04 17:07:25.000000000 -0600
 @@ -113,6 +113,9 @@
         */
        loff_t  i_disksize;
index b32f6f8..a5232af 100644 (file)
@@ -245,6 +245,7 @@ struct lustre_mount_data {
         char     lmd_profile[64];
 };
 
-#define LMD_FLG_FLOCK 0x0001
+#define LMD_FLG_FLOCK           0x0001
+#define LMD_FLG_USER_XATTR      0x0002
 
 #endif // _LUSTRE_CFG_H
index bb01446..8788fe6 100644 (file)
@@ -56,6 +56,9 @@ void groups_free(struct group_info *ginfo);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 
+#define lock_24kernel()         do {} while (0)
+#define unlock_24kernel()       do {} while (0)
+
 /*
  * OBD need working random driver, thus all our
  * initialization routines must be called after device
@@ -144,6 +147,9 @@ static inline int cleanup_group_info(void)
 
 #else /* 2.4.. */
 
+#define lock_24kernel()         lock_kernel()
+#define unlock_24kernel()       unlock_kernel()
+
 #ifdef HAVE_MM_INLINE
 #include <linux/mm_inline.h>
 #endif
index b82effc..a446c65 100644 (file)
@@ -38,6 +38,8 @@ struct fsfilt_objinfo {
         int fso_bufcnt;
 };
 
+#define XATTR_LUSTRE_MDS_LOV_EA         "lov"
+
 struct fsfilt_operations {
         struct list_head fs_list;
         struct module *fs_owner;
index b6fc6c5..87cc637 100644 (file)
@@ -374,8 +374,12 @@ struct lov_mds_md_v1 {            /* LOV EA mds/wire data (little-endian) */
 #define OBD_MD_FLUSRQUOTA  (0x20000000ULL) /* over quota flags sent from ost */
 #define OBD_MD_FLGRPQUOTA  (0x40000000ULL) /* over quota flags sent from ost */
 
-#define OBD_MD_MDS        (0x100000000ULL) /* where an inode lives on */
-#define OBD_MD_REINT      (0x200000000ULL) /* reintegrate oa */
+#define OBD_MD_MDS         (0x0000000100000000ULL) /* where an inode lives on */
+#define OBD_MD_REINT       (0x0000000200000000ULL) /* reintegrate oa */
+
+#define OBD_MD_FLXATTR     (0x0000001000000000ULL) /* xattr */
+#define OBD_MD_FLXATTRLS   (0x0000002000000000ULL) /* xattr list */
+#define OBD_MD_FLXATTRRM   (0x0000004000000000ULL) /* xattr remove */
 
 #define OBD_MD_FLGETATTR (OBD_MD_FLID    | OBD_MD_FLATIME | OBD_MD_FLMTIME | \
                           OBD_MD_FLCTIME | OBD_MD_FLSIZE  | OBD_MD_FLBLKSZ | \
@@ -491,6 +495,8 @@ typedef enum {
         MDS_SET_INFO     = 46,
         MDS_QUOTACHECK   = 47,
         MDS_QUOTACTL     = 48,
+        MDS_GETXATTR     = 49,
+        MDS_SETXATTR     = 50,
         MDS_LAST_OPC
 } mds_cmd_t;
 
index ee62508..e6bb40b 100644 (file)
@@ -59,6 +59,8 @@ enum {
 #endif
          LPROC_LL_STAFS,
          LPROC_LL_ALLOC_INODE,
+         LPROC_LL_SETXATTR,
+         LPROC_LL_GETXATTR,
 
          LPROC_LL_DIRECT_READ,
          LPROC_LL_DIRECT_WRITE,
index d3aae2c..5c43429 100644 (file)
@@ -186,6 +186,15 @@ int mdc_getattr_name(struct obd_export *exp, struct ll_fid *fid,
 int mdc_setattr(struct obd_export *exp, struct mdc_op_data *data,
                 struct iattr *iattr, void *ea, int ealen, void *ea2, int ea2len,
                 struct ptlrpc_request **request);
+int mdc_setxattr(struct obd_export *exp, struct ll_fid *fid,
+                 obd_valid valid, const char *xattr_name,
+                 const char *input, int input_size,
+                 int output_size, int flags,
+                 struct ptlrpc_request **request);
+int mdc_getxattr(struct obd_export *exp, struct ll_fid *fid,
+                 obd_valid valid, const char *xattr_name,
+                 const char *input, int input_size,
+                 int output_size, struct ptlrpc_request **request);
 int mdc_open(struct obd_export *exp, obd_id ino, int type, int flags,
              struct lov_mds_md *lmm, int lmm_size, struct lustre_handle *fh,
              struct ptlrpc_request **);
index 554461b..0bb7e55 100644 (file)
@@ -93,6 +93,11 @@ extern wait_queue_head_t obd_race_waitq;
 #define OBD_FAIL_MDS_QUOTACHECK_NET      0x12d
 #define OBD_FAIL_MDS_QUOTACTL_NET        0x12e
 #define OBD_FAIL_MDS_CLIENT_ADD          0x12f
+#define OBD_FAIL_MDS_GETXATTR_NET        0x130
+#define OBD_FAIL_MDS_GETXATTR_PACK       0x131
+#define OBD_FAIL_MDS_SETXATTR_NET        0x132
+#define OBD_FAIL_MDS_SETXATTR            0x133
+#define OBD_FAIL_MDS_SETXATTR_WRITE      0x134
 
 #define OBD_FAIL_OST                     0x200
 #define OBD_FAIL_OST_CONNECT_NET         0x201
index 9d5bee1..507b044 100644 (file)
@@ -1,7 +1,7 @@
 Index: linux-stage/fs/ext3/ialloc.c
 ===================================================================
---- linux-stage.orig/fs/ext3/ialloc.c  2005-02-25 16:47:04.411977280 +0200
-+++ linux-stage/fs/ext3/ialloc.c       2005-02-25 16:50:40.752088584 +0200
+--- linux-stage.orig/fs/ext3/ialloc.c  2005-10-04 16:53:24.000000000 -0600
++++ linux-stage/fs/ext3/ialloc.c       2005-10-04 17:07:25.000000000 -0600
 @@ -629,6 +629,11 @@
        spin_unlock(&sbi->s_next_gen_lock);
  
@@ -16,9 +16,9 @@ Index: linux-stage/fs/ext3/ialloc.c
        if(DQUOT_ALLOC_INODE(inode)) {
 Index: linux-stage/fs/ext3/inode.c
 ===================================================================
---- linux-stage.orig/fs/ext3/inode.c   2005-02-25 16:47:04.415976672 +0200
-+++ linux-stage/fs/ext3/inode.c        2005-02-25 16:50:40.756087976 +0200
-@@ -2274,7 +2274,7 @@ static unsigned long ext3_get_inode_bloc
+--- linux-stage.orig/fs/ext3/inode.c   2005-10-04 17:00:22.000000000 -0600
++++ linux-stage/fs/ext3/inode.c        2005-10-04 17:07:25.000000000 -0600
+@@ -2274,7 +2274,7 @@
   * trying to determine the inode's location on-disk and no read need be
   * performed.
   */
@@ -27,7 +27,7 @@ Index: linux-stage/fs/ext3/inode.c
                                struct ext3_iloc *iloc, int in_mem)
  {
        unsigned long block;
-@@ -2484,6 +2484,11 @@ void ext3_read_inode(struct inode * inod
+@@ -2484,6 +2484,11 @@
                ei->i_data[block] = raw_inode->i_block[block];
        INIT_LIST_HEAD(&ei->i_orphan);
  
@@ -39,7 +39,7 @@ Index: linux-stage/fs/ext3/inode.c
        if (S_ISREG(inode->i_mode)) {
                inode->i_op = &ext3_file_inode_operations;
                inode->i_fop = &ext3_file_operations;
-@@ -2619,6 +2624,9 @@ static int ext3_do_update_inode(handle_t
+@@ -2619,6 +2624,9 @@
        } else for (block = 0; block < EXT3_N_BLOCKS; block++)
                raw_inode->i_block[block] = ei->i_data[block];
  
@@ -49,7 +49,7 @@ Index: linux-stage/fs/ext3/inode.c
        BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
        rc = ext3_journal_dirty_metadata(handle, bh);
        if (!err)
-@@ -2849,7 +2857,8 @@ ext3_reserve_inode_write(handle_t *handl
+@@ -2849,7 +2857,8 @@
  {
        int err = 0;
        if (handle) {
@@ -61,19 +61,19 @@ Index: linux-stage/fs/ext3/inode.c
                        err = ext3_journal_get_write_access(handle, iloc->bh);
 Index: linux-stage/fs/ext3/xattr.c
 ===================================================================
---- linux-stage.orig/fs/ext3/xattr.c   2005-02-25 16:47:04.422975608 +0200
-+++ linux-stage/fs/ext3/xattr.c        2005-02-25 17:19:04.958009904 +0200
+--- linux-stage.orig/fs/ext3/xattr.c   2005-10-04 16:50:11.000000000 -0600
++++ linux-stage/fs/ext3/xattr.c        2005-10-04 17:19:43.000000000 -0600
 @@ -149,17 +149,12 @@
  }
  
  /*
 - * ext3_xattr_get()
-+ * ext3_xattr_block_get()
-  *
+- *
 - * Copy an extended attribute into the buffer
 - * provided, or compute the buffer size required.
 - * Buffer is NULL to compute the size of the buffer required.
-- *
++ * ext3_xattr_block_get()
+  *
 - * Returns a negative error number on failure, or the number of bytes
 - * used / required on success.
 + * routine looks for attribute in EA block and returns it's value and size
@@ -224,7 +224,7 @@ Index: linux-stage/fs/ext3/xattr.c
        error = 0;
        if (!EXT3_I(inode)->i_file_acl)
                goto cleanup;
-@@ -330,11 +419,139 @@
+@@ -330,11 +419,149 @@
  
  cleanup:
        brelse(bh);
@@ -245,6 +245,7 @@ Index: linux-stage/fs/ext3/xattr.c
 +      char *start, *end, *buf;
 +      struct ext3_iloc iloc;
 +      int storage_size;
++      size_t rest = buffer_size;
 +      int ret;
 +      int size = 0;
 +      
@@ -282,9 +283,8 @@ Index: linux-stage/fs/ext3/xattr.c
 +              }
 +              handler = ext3_xattr_handler(last->e_name_index);
 +              if (handler)
-+                      size = handler->list(inode, NULL, 0, last->e_name,
++                      size += handler->list(inode, NULL, 0, last->e_name,
 +                                            last->e_name_len);
-+                      
 +              last = next;
 +      }
 +
@@ -303,9 +303,19 @@ Index: linux-stage/fs/ext3/xattr.c
 +              struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
 +              struct xattr_handler *handler;
 +              handler = ext3_xattr_handler(last->e_name_index);
-+              if (handler)
-+                      buf += handler->list(inode, buf, (buffer+buffer_size)-buf, last->e_name,
-+                                            last->e_name_len);
++              if (handler) {
++                      size_t size = handler->list(inode, buffer, rest,
++                                                  last->e_name,
++                                                  last->e_name_len);
++                      if (buffer) {
++                              if (size > rest) {
++                                      ret = -ERANGE;
++                                      goto cleanup;
++                              }
++                              buffer += size;
++                      }
++                      rest -= size;
++              }
 +              last = next;
 +      }
 +      ret = size;
@@ -365,7 +375,7 @@ Index: linux-stage/fs/ext3/xattr.c
  /*
   * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
   * not set, set it.
-@@ -356,6 +573,279 @@
+@@ -356,6 +583,279 @@
  }
  
  /*
@@ -645,7 +655,7 @@ Index: linux-stage/fs/ext3/xattr.c
   * ext3_xattr_set_handle()
   *
   * Create, replace or remove an extended attribute for this inode. Buffer
-@@ -369,6 +859,104 @@
+@@ -369,6 +869,104 @@
   */
  int
  ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
@@ -750,7 +760,7 @@ Index: linux-stage/fs/ext3/xattr.c
                      const char *name, const void *value, size_t value_len,
                      int flags)
  {
-@@ -391,22 +979,7 @@
+@@ -391,22 +989,7 @@
         *             towards the end of the block).
         * end -- Points right after the block pointed to by header.
         */
@@ -773,7 +783,7 @@ Index: linux-stage/fs/ext3/xattr.c
        if (EXT3_I(inode)->i_file_acl) {
                /* The inode already has an extended attribute block. */
                bh = sb_bread(sb, EXT3_I(inode)->i_file_acl);
-@@ -638,7 +1211,6 @@
+@@ -638,7 +1221,6 @@
        brelse(bh);
        if (!(bh && header == HDR(bh)))
                kfree(header);
@@ -783,8 +793,8 @@ Index: linux-stage/fs/ext3/xattr.c
  }
 Index: linux-stage/fs/ext3/xattr.h
 ===================================================================
---- linux-stage.orig/fs/ext3/xattr.h   2005-02-25 16:47:04.423975456 +0200
-+++ linux-stage/fs/ext3/xattr.h        2005-02-25 16:50:40.763086912 +0200
+--- linux-stage.orig/fs/ext3/xattr.h   2005-10-04 16:50:11.000000000 -0600
++++ linux-stage/fs/ext3/xattr.h        2005-10-04 17:07:25.000000000 -0600
 @@ -67,7 +67,8 @@
  extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
  extern int ext3_xattr_list(struct inode *, char *, size_t);
@@ -797,8 +807,8 @@ Index: linux-stage/fs/ext3/xattr.h
  extern void ext3_xattr_put_super(struct super_block *);
 Index: linux-stage/include/linux/ext3_fs.h
 ===================================================================
---- linux-stage.orig/include/linux/ext3_fs.h   2005-02-25 16:47:04.425975152 +0200
-+++ linux-stage/include/linux/ext3_fs.h        2005-02-25 16:50:40.765086608 +0200
+--- linux-stage.orig/include/linux/ext3_fs.h   2005-10-04 16:53:29.000000000 -0600
++++ linux-stage/include/linux/ext3_fs.h        2005-10-04 17:07:25.000000000 -0600
 @@ -293,6 +293,8 @@
                        __u32   m_i_reserved2[2];
                } masix2;
@@ -818,8 +828,8 @@ Index: linux-stage/include/linux/ext3_fs.h
  extern int  ext3_write_inode (struct inode *, int);
 Index: linux-stage/include/linux/ext3_fs_i.h
 ===================================================================
---- linux-stage.orig/include/linux/ext3_fs_i.h 2005-02-25 16:47:04.426975000 +0200
-+++ linux-stage/include/linux/ext3_fs_i.h      2005-02-25 16:50:40.766086456 +0200
+--- linux-stage.orig/include/linux/ext3_fs_i.h 2005-10-04 16:50:11.000000000 -0600
++++ linux-stage/include/linux/ext3_fs_i.h      2005-10-04 17:07:25.000000000 -0600
 @@ -113,6 +113,9 @@
         */
        loff_t  i_disksize;
index 4daad42..7a908d7 100644 (file)
@@ -1,5 +1,5 @@
 MODULES := llite
-llite-objs := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o rw.o lproc_llite.o namei.o special.o symlink.o llite_mmap.o
+llite-objs := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o rw.o lproc_llite.o namei.o special.o symlink.o llite_mmap.o xattr.o
 
 ifeq ($(PATCHLEVEL),4)
 llite-objs += rw24.o super.o
index 170f7a7..0c06efc 100644 (file)
@@ -1636,5 +1636,9 @@ struct inode_operations ll_file_inode_operations = {
 #else
         .revalidate_it  = ll_inode_revalidate_it,
 #endif
+        .setxattr       = ll_setxattr,
+        .getxattr       = ll_getxattr,
+        .listxattr      = ll_listxattr,
+        .removexattr    = ll_removexattr,
 };
 
index dfefb72..346ef4c 100644 (file)
@@ -131,6 +131,7 @@ struct ll_ra_info {
 #define LL_SBI_NOLCK            0x1 /* DLM locking disabled (directio-only) */
 #define LL_SBI_CHECKSUM         0x2 /* checksum each page as it's written */
 #define LL_SBI_FLOCK            0x4
+#define LL_SBI_USER_XATTR       0x8 /* support user xattr */
 
 struct ll_sb_info {
         struct list_head          ll_list;
@@ -541,4 +542,12 @@ static inline __u64 ll_file_maxbytes(struct inode *inode)
         return ll_i2info(inode)->lli_maxbytes;
 }
 
+/* llite/xattr.c */
+int ll_setxattr(struct dentry *dentry, const char *name,
+                const void *value, size_t size, int flags);
+int ll_getxattr(struct dentry *dentry, const char *name,
+                void *buffer, size_t size);
+int ll_listxattr(struct dentry *dentry, char *buffer, size_t size);
+int ll_removexattr(struct dentry *dentry, const char *name);
+
 #endif /* LLITE_INTERNAL_H */
index 92759c3..f668c62 100644 (file)
@@ -452,6 +452,11 @@ void ll_options(char *options, char **ost, char **mdc, int *flags)
                         *flags &= ~tmp;
                         continue;
                 }
+                tmp = ll_set_opt("user_xattr", this_char, LL_SBI_USER_XATTR);
+                if (tmp) {
+                        *flags |= tmp;
+                        continue;
+                }
         }
         EXIT;
 }
@@ -727,6 +732,8 @@ int lustre_fill_super(struct super_block *sb, void *data, int silent)
                 memcpy(sbi->ll_lmd, lmd, sizeof(*lmd));
                 if (lmd->lmd_flags & LMD_FLG_FLOCK)
                         sbi->ll_flags |= LL_SBI_FLOCK;
+                if (lmd->lmd_flags & LMD_FLG_USER_XATTR)
+                        sbi->ll_flags |= LL_SBI_USER_XATTR;
 
                 /* generate a string unique to this super, let's try
                  the address of the super itself.*/
index 54cb257..c445c91 100644 (file)
@@ -350,6 +350,8 @@ struct llite_file_opcode {
         /* special inode operation */
         { LPROC_LL_STAFS,          LPROCFS_TYPE_REGS, "statfs" },
         { LPROC_LL_ALLOC_INODE,    LPROCFS_TYPE_REGS, "alloc_inode" },
+        { LPROC_LL_SETXATTR,       LPROCFS_TYPE_REGS, "setxattr" },
+        { LPROC_LL_GETXATTR,       LPROCFS_TYPE_REGS, "getxattr" },
         { LPROC_LL_DIRECT_READ,    LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES,
                                    "direct_read" },
         { LPROC_LL_DIRECT_WRITE,   LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES,
index 4ec2685..4511658 100644 (file)
@@ -891,4 +891,8 @@ struct inode_operations ll_dir_inode_operations = {
         .create             = ll_create_nd,
         .getattr_it         = ll_getattr,
 #endif
+        .setxattr           = ll_setxattr,
+        .getxattr           = ll_getxattr,
+        .listxattr          = ll_listxattr,
+        .removexattr        = ll_removexattr,
 };
index 1e9355a..328801d 100644 (file)
@@ -332,6 +332,10 @@ struct inode_operations ll_special_inode_operations = {
 #else
         .revalidate_it  = ll_inode_revalidate_it,
 #endif
+        .setxattr       = ll_setxattr,
+        .getxattr       = ll_getxattr,
+        .listxattr      = ll_listxattr,
+        .removexattr    = ll_removexattr,
 };
 
 struct file_operations ll_special_chr_inode_fops = {
index 57dc9b3..0b5d990 100644 (file)
@@ -157,8 +157,12 @@ struct inode_operations ll_fast_symlink_inode_operations = {
         .setattr_raw    = ll_setattr_raw,
         .follow_link    = ll_follow_link,
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-        .revalidate_it  = ll_inode_revalidate_it
+        .revalidate_it  = ll_inode_revalidate_it,
 #else 
-        .getattr_it     = ll_getattr
+        .getattr_it     = ll_getattr,
 #endif
+        .setxattr       = ll_setxattr,
+        .getxattr       = ll_getxattr,
+        .listxattr      = ll_listxattr,
+        .removexattr    = ll_removexattr,
 };
diff --git a/lustre/llite/xattr.c b/lustre/llite/xattr.c
new file mode 100644 (file)
index 0000000..b932648
--- /dev/null
@@ -0,0 +1,236 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  Copyright (c) 2004 - 2005 Cluster File Systems, Inc.
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/xattr_acl.h>
+
+#define DEBUG_SUBSYSTEM S_LLITE
+
+#include <linux/obd_support.h>
+#include <linux/lustre_lite.h>
+#include <linux/lustre_dlm.h>
+#include <linux/lustre_version.h>
+#include <linux/lustre_mds.h>
+
+#include "llite_internal.h"
+
+#define XATTR_USER_PREFIX       "user."
+#define XATTR_TRUSTED_PREFIX    "trusted."
+#define XATTR_SECURITY_PREFIX   "security."
+
+#define XATTR_USER_T            (1)
+#define XATTR_TRUSTED_T         (2)
+#define XATTR_SECURITY_T        (3)
+#define XATTR_POSIXACL_T        (4)
+#define XATTR_OTHER_T           (5)
+
+static
+int get_xattr_type(const char *name)
+{
+        if (!strcmp(name, XATTR_NAME_ACL_ACCESS) ||
+            !strcmp(name, XATTR_NAME_ACL_DEFAULT))
+                return XATTR_POSIXACL_T;
+
+        if (!strncmp(name, XATTR_USER_PREFIX,
+                     sizeof(XATTR_USER_PREFIX) - 1))
+                return XATTR_USER_T;
+
+        if (!strncmp(name, XATTR_TRUSTED_PREFIX,
+                     sizeof(XATTR_TRUSTED_PREFIX) - 1))
+                return XATTR_TRUSTED_T;
+
+        if (!strncmp(name, XATTR_SECURITY_PREFIX,
+                     sizeof(XATTR_SECURITY_PREFIX) - 1))
+                return XATTR_SECURITY_T;
+
+        return XATTR_OTHER_T;
+}
+
+static
+int ll_setxattr_common(struct inode *inode, const char *name,
+                       const void *value, size_t size,
+                       int flags, __u64 valid)
+{
+        struct ll_sb_info *sbi = ll_i2sbi(inode);
+        struct ptlrpc_request *req;
+        struct ll_fid fid;
+        int xattr_type, rc;
+        ENTRY;
+
+        lprocfs_counter_incr(sbi->ll_stats, LPROC_LL_SETXATTR);
+
+        xattr_type = get_xattr_type(name);
+        if (xattr_type == XATTR_USER_T && !(sbi->ll_flags & LL_SBI_USER_XATTR))
+                RETURN(-EOPNOTSUPP);
+        if (xattr_type == XATTR_TRUSTED_T && !capable(CAP_SYS_ADMIN))
+                RETURN(-EPERM);
+        if (xattr_type == XATTR_OTHER_T)
+                RETURN(-EOPNOTSUPP);
+
+        ll_inode2fid(&fid, inode);
+        rc = mdc_setxattr(sbi->ll_mdc_exp, &fid, valid,
+                          name, value, size, 0, flags, &req);
+        if (rc) {
+                if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
+                        CWARN("disable user_xattr from now on\n");
+                        sbi->ll_flags &= ~LL_SBI_USER_XATTR;
+                }
+                RETURN(rc);
+        }
+
+        ptlrpc_req_finished(req);
+        RETURN(0);
+}
+
+int ll_setxattr(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags)
+{
+        struct inode *inode = dentry->d_inode;
+
+        LASSERT(inode);
+        LASSERT(name);
+
+        CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
+               inode->i_ino, inode->i_generation, inode, name);
+
+        return ll_setxattr_common(inode, name, value, size, flags,
+                                  OBD_MD_FLXATTR);
+}
+
+int ll_removexattr(struct dentry *dentry, const char *name)
+{
+        struct inode *inode = dentry->d_inode;
+
+        LASSERT(inode);
+        LASSERT(name);
+
+        CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
+               inode->i_ino, inode->i_generation, inode, name);
+
+        return ll_setxattr_common(inode, name, NULL, 0, 0,
+                                  OBD_MD_FLXATTRRM);
+}
+
+static
+int ll_getxattr_common(struct inode *inode, const char *name,
+                       void *buffer, size_t size, __u64 valid)
+{
+        struct ll_sb_info *sbi = ll_i2sbi(inode);
+        struct ptlrpc_request *req = NULL;
+        struct mds_body *body;
+        struct ll_fid fid;
+        void *xdata;
+        int xattr_type, rc;
+        ENTRY;
+
+        CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
+               inode->i_ino, inode->i_generation, inode);
+
+        lprocfs_counter_incr(sbi->ll_stats, LPROC_LL_GETXATTR);
+
+        if (!name)
+                goto do_getxattr;
+
+        xattr_type = get_xattr_type(name);
+        if (xattr_type == XATTR_USER_T && !(sbi->ll_flags & LL_SBI_USER_XATTR))
+                RETURN(-EOPNOTSUPP);
+        if (xattr_type == XATTR_TRUSTED_T && !capable(CAP_SYS_ADMIN))
+                RETURN(-EPERM);
+        if (xattr_type == XATTR_OTHER_T)
+                RETURN(-EOPNOTSUPP);
+
+do_getxattr:
+        ll_inode2fid(&fid, inode);
+        rc = mdc_getxattr(sbi->ll_mdc_exp, &fid, valid, name, NULL, 0,
+                          size, &req);
+        if (rc) {
+                if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
+                        CWARN("disable user_xattr from now on\n");
+                        sbi->ll_flags &= ~LL_SBI_USER_XATTR;
+                }
+                RETURN(rc);
+        }
+
+        body = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*body));
+        LASSERT(body);
+        LASSERT_REPSWABBED(req, 0);
+
+        /* only detect the xattr size */
+        if (size == 0)
+                GOTO(out, rc = body->eadatasize);
+
+        if (size < body->eadatasize) {
+                CERROR("server bug: replied size %u > %u\n",
+                       body->eadatasize, size);
+                GOTO(out, rc = -ERANGE);
+        }
+
+        if (req->rq_repmsg->bufcount < 2) {
+                CERROR("reply bufcount %u\n", req->rq_repmsg->bufcount);
+                GOTO(out, rc = -EFAULT);
+        }
+
+        /* do not need swab xattr data */
+        LASSERT_REPSWAB(req, 1);
+        xdata = lustre_msg_buf(req->rq_repmsg, 1, body->eadatasize);
+        if (!xdata) {
+                CERROR("can't extract: %u : %u\n", body->eadatasize,
+                       lustre_msg_buflen(req->rq_repmsg, 1));
+                GOTO(out, rc = -EFAULT);
+        }
+
+        LASSERT(buffer);
+        memcpy(buffer, xdata, body->eadatasize);
+        rc = body->eadatasize;
+out:
+        ptlrpc_req_finished(req);
+        RETURN(rc);
+}
+
+int ll_getxattr(struct dentry *dentry, const char *name,
+               void *buffer, size_t size)
+{
+        struct inode *inode = dentry->d_inode;
+
+        LASSERT(inode);
+        LASSERT(name);
+
+        CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
+               inode->i_ino, inode->i_generation, inode, name);
+
+        return ll_getxattr_common(inode, name, buffer, size, OBD_MD_FLXATTR);
+}
+
+int ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+        struct inode *inode = dentry->d_inode;
+
+        LASSERT(inode);
+
+        CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
+               inode->i_ino, inode->i_generation, inode);
+
+        return ll_getxattr_common(inode, NULL, buffer, size, OBD_MD_FLXATTRLS);
+}
+
index b13724d..25ada73 100644 (file)
 #include <linux/ext3_extents.h>
 #endif
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7))
-# define lock_24kernel() lock_kernel()
-# define unlock_24kernel() unlock_kernel()
-#else
-# define lock_24kernel() do {} while (0)
-# define unlock_24kernel() do {} while (0)
-#endif
-
 static kmem_cache_t *fcb_cache;
 
 struct fsfilt_cb_data {
@@ -79,7 +71,6 @@ struct fsfilt_cb_data {
 #ifndef EXT3_XATTR_INDEX_TRUSTED        /* temporary until we hit l28 kernel */
 #define EXT3_XATTR_INDEX_TRUSTED        4
 #endif
-#define XATTR_LUSTRE_MDS_LOV_EA         "lov"
 
 /*
  * We don't currently need any additional blocks for rmdir and
index 434d114..dbd78ae 100644 (file)
@@ -212,6 +212,110 @@ int mdc_getattr_name(struct obd_export *exp, struct ll_fid *fid,
         RETURN(rc);
 }
 
+static
+int mdc_xattr_common(struct obd_export *exp, struct ll_fid *fid,
+                     int opcode, obd_valid valid, const char *xattr_name,
+                     const char *input, int input_size, int output_size,
+                     int flags, struct ptlrpc_request **request)
+{
+        struct ptlrpc_request *req;
+        struct mds_body *body;
+        int size[3] = {sizeof(*body)}, bufcnt = 1;
+        int xattr_namelen = 0, rc;
+        void *tmp;
+        ENTRY;
+
+        if (xattr_name) {
+                xattr_namelen = strlen(xattr_name) + 1;
+                size[bufcnt++] = xattr_namelen;
+        }
+        if (input_size) {
+                LASSERT(input);
+                size[bufcnt++] = input_size;
+        }
+
+        req = ptlrpc_prep_req(class_exp2cliimp(exp), opcode,
+                              bufcnt, size, NULL);
+        if (!req)
+                GOTO(out, rc = -ENOMEM);
+
+        /* request data */
+        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*body));
+        memcpy(&body->fid1, fid, sizeof(*fid));
+        body->valid = valid;
+        body->eadatasize = output_size;
+        body->flags = flags;
+        mdc_pack_req_body(req);
+
+        if (xattr_name) {
+                tmp = lustre_msg_buf(req->rq_reqmsg, 1, xattr_namelen);
+                memcpy(tmp, xattr_name, xattr_namelen);
+        }
+        if (input_size) {
+                tmp = lustre_msg_buf(req->rq_reqmsg, bufcnt - 1, input_size);
+                memcpy(tmp, input, input_size);
+        }
+
+        /* reply buffers */
+        if (opcode == MDS_GETXATTR) {
+                size[0] = sizeof(*body);
+                bufcnt = 1;
+        } else {
+                bufcnt = 0;
+        }
+
+        if (output_size)
+                size[bufcnt++] = output_size;
+        req->rq_replen = lustre_msg_size(bufcnt, size);
+
+        /* make rpc */
+        if (opcode == MDS_SETXATTR)
+                mdc_get_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
+
+        rc = ptlrpc_queue_wait(req);
+
+        if (opcode == MDS_SETXATTR)
+                mdc_put_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
+
+        if (rc != 0)
+                GOTO(err_out, rc);
+
+        if (opcode == MDS_GETXATTR) {
+                body = lustre_swab_repbuf(req, 0, sizeof(*body),
+                                          lustre_swab_mds_body);
+                if (body == NULL) {
+                        CERROR ("Can't unpack mds_body\n");
+                        GOTO(err_out, rc = -EPROTO);
+                }
+        }
+out:
+        *request = req;
+        RETURN (rc);
+err_out:
+        ptlrpc_req_finished(req);
+        req = NULL;
+        goto out;
+}
+
+int mdc_setxattr(struct obd_export *exp, struct ll_fid *fid,
+                 obd_valid valid, const char *xattr_name,
+                 const char *input, int input_size,
+                 int output_size, int flags,
+                 struct ptlrpc_request **request)
+{
+        return mdc_xattr_common(exp, fid, MDS_SETXATTR, valid, xattr_name,
+                                input, input_size, output_size, flags, request);
+}
+
+int mdc_getxattr(struct obd_export *exp, struct ll_fid *fid,
+                 obd_valid valid, const char *xattr_name,
+                 const char *input, int input_size,
+                 int output_size, struct ptlrpc_request **request)
+{
+        return mdc_xattr_common(exp, fid, MDS_GETXATTR, valid, xattr_name,
+                                input, input_size, output_size, 0, request);
+}
+
 /* This should be called with both the request and the reply still packed. */
 void mdc_store_inode_generation(struct ptlrpc_request *req, int reqoff,
                                 int repoff)
@@ -1099,6 +1203,8 @@ EXPORT_SYMBOL(mdc_set_open_replay_data);
 EXPORT_SYMBOL(mdc_clear_open_replay_data);
 EXPORT_SYMBOL(mdc_store_inode_generation);
 EXPORT_SYMBOL(mdc_init_ea_size);
+EXPORT_SYMBOL(mdc_getxattr);
+EXPORT_SYMBOL(mdc_setxattr);
 
 module_init(mdc_init);
 module_exit(mdc_exit);
index 3e8cff6..25eb6f0 100644 (file)
@@ -1,6 +1,6 @@
 MODULES := mds
 mds-objs := mds_log.o mds_unlink_open.o mds_lov.o handler.o mds_reint.o
-mds-objs += mds_fs.o lproc_mds.o mds_open.o mds_lib.o
+mds-objs += mds_fs.o lproc_mds.o mds_open.o mds_lib.o mds_xattr.o
 
 ifeq ($(PATCHLEVEL),6)
 #mds-objs += quota_master.o
index 97a3642..a42abb5 100644 (file)
@@ -790,10 +790,8 @@ static int mds_getattr(int offset, struct ptlrpc_request *req)
 
         body = lustre_swab_reqbuf(req, offset, sizeof(*body),
                                   lustre_swab_mds_body);
-        if (body == NULL) {
-                CERROR("Can't unpack body\n");
+        if (body == NULL)
                 RETURN(-EFAULT);
-        }
 
         rc = mds_init_ucred(&uc, req, offset);
         if (rc)
@@ -1186,6 +1184,18 @@ int mds_handle(struct ptlrpc_request *req)
                 rc = mds_getattr(0, req);
                 break;
 
+        case MDS_SETXATTR:
+                DEBUG_REQ(D_INODE, req, "setxattr");
+                OBD_FAIL_RETURN(OBD_FAIL_MDS_SETXATTR_NET, 0);
+                rc = mds_setxattr(req);
+                break;
+
+        case MDS_GETXATTR:
+                DEBUG_REQ(D_INODE, req, "getxattr");
+                OBD_FAIL_RETURN(OBD_FAIL_MDS_GETXATTR_NET, 0);
+                rc = mds_getxattr(req);
+                break;
+
         case MDS_GETATTR_NAME: {
                 struct lustre_handle lockh;
                 DEBUG_REQ(D_INODE, req, "getattr_name");
index 6fffb8b..1aa5967 100644 (file)
@@ -197,6 +197,10 @@ void mds_pack_inode2fid(struct ll_fid *fid, struct inode *inode);
 void mds_pack_inode2body(struct mds_body *body, struct inode *inode);
 #endif
 
+/* mds/mds_xattr.c */
+int mds_setxattr(struct ptlrpc_request *req);
+int mds_getxattr(struct ptlrpc_request *req);
+
 /* mds/quota_master.c */
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) && defined (HAVE_QUOTA_SUPPORT)
 int lustre_dquot_init(void);
diff --git a/lustre/mds/mds_xattr.c b/lustre/mds/mds_xattr.c
new file mode 100644 (file)
index 0000000..a96d397
--- /dev/null
@@ -0,0 +1,335 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  linux/mds/mds_xattr.c
+ *  Lustre Metadata Server (mds) extended attributes handling
+ *
+ *  Copyright (C) 2004-2005 Cluster File Systems, Inc.
+ *
+ *   This file is part of the Lustre file system, http://www.lustre.org
+ *   Lustre is a trademark of Cluster File Systems, Inc.
+ *
+ *   You may have signed or agreed to another license before downloading
+ *   this software.  If so, you are bound by the terms and conditions
+ *   of that agreement, and the following does not apply to you.  See the
+ *   LICENSE file included with this distribution for more information.
+ *
+ *   If you did not agree to a different license, then this copy of Lustre
+ *   is open source software; you can redistribute it and/or modify it
+ *   under the terms of version 2 of the GNU General Public License as
+ *   published by the Free Software Foundation.
+ *
+ *   In either case, Lustre is distributed in the hope that it will be
+ *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   license text for more details.
+ */
+
+#ifndef EXPORT_SYMTAB
+# define EXPORT_SYMTAB
+#endif
+#define DEBUG_SUBSYSTEM S_MDS
+
+#include <linux/fs.h>
+#include <linux/obd_support.h>
+#include <linux/obd_class.h>
+#include <linux/obd.h>
+#include <linux/lustre_lib.h>
+#include <linux/lustre_idl.h>
+#include <linux/lustre_mds.h>
+#include <linux/lustre_dlm.h>
+#include <linux/lustre_fsfilt.h>
+#include <linux/lustre_ucache.h>
+
+#include "mds_internal.h"
+
+static int mds_getxattr_pack_msg(struct ptlrpc_request *req,
+                                 struct dentry *de,
+                                 struct mds_body *body)
+{
+        struct inode *inode = de->d_inode;
+        int size[2] = {sizeof(*body)}, bufcnt = 1;
+        char *xattr_name;
+        int rc = -EOPNOTSUPP, rc2;
+
+        if (inode == NULL)
+                return -ENOENT;
+
+        if (body->valid & OBD_MD_FLXATTR) {
+                xattr_name = lustre_msg_string(req->rq_reqmsg, 1, 0);
+                if (!xattr_name) {
+                        CERROR("can't extract xattr name\n");
+                        return -EFAULT;
+                }
+
+                if (inode->i_op && inode->i_op->getxattr)
+                        rc = inode->i_op->getxattr(de, xattr_name, NULL, 0);
+        } else if (body->valid & OBD_MD_FLXATTRLS) {
+                if (inode->i_op && inode->i_op->listxattr)
+                        rc = inode->i_op->listxattr(de, NULL, 0);
+        } else {
+                CERROR("valid bits: "LPX64"\n", body->valid);
+                return -EINVAL;
+        }
+
+        if (rc < 0) {
+                if (rc != -ENODATA && rc != -EOPNOTSUPP)
+                        CWARN("get inode %lu EA size error: %d\n",
+                              inode->i_ino, rc);
+                bufcnt = 0;
+        } else {
+                size[bufcnt++] = min_t(int, body->eadatasize, rc);
+        }
+
+        if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETXATTR_PACK)) {
+                CERROR("failed MDS_GETXATTR_PACK test\n");
+                req->rq_status = -ENOMEM;
+                return -ENOMEM;
+        }
+
+        rc2 = lustre_pack_reply(req, bufcnt, size, NULL);
+        if (rc2)
+                return rc2;
+
+        if (rc < 0)
+                req->rq_status = rc;
+        return 0;
+}
+
+static int mds_getxattr_internal(struct obd_device *obd,
+                                 struct dentry *dentry,
+                                 struct ptlrpc_request *req,
+                                 struct mds_body *reqbody)
+{
+        struct mds_body *repbody;
+        struct inode *inode = dentry->d_inode;
+        char *xattr_name;
+        void *buf = NULL;
+        int buflen, rc = -EOPNOTSUPP;
+        ENTRY;
+
+        if (inode == NULL)
+                GOTO(out, rc = -ENOENT);
+
+        repbody = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*repbody));
+        LASSERT(repbody != NULL);
+
+        buflen = lustre_msg_buflen(req->rq_repmsg, 1);
+        if (buflen)
+                buf = lustre_msg_buf(req->rq_repmsg, 1, buflen);
+
+        if (reqbody->valid & OBD_MD_FLXATTR) {
+                xattr_name = lustre_msg_string(req->rq_reqmsg, 1, 0);
+                DEBUG_REQ(D_INODE, req, "getxattr %s\n", xattr_name);
+
+                if (inode->i_op && inode->i_op->getxattr) {
+                        lock_24kernel();
+                        rc = inode->i_op->getxattr(dentry, xattr_name,
+                                                   buf, buflen);
+                        unlock_24kernel();
+                }
+
+                if (rc < 0 && rc != -ENODATA && rc != -EOPNOTSUPP &&
+                    rc != -ERANGE)
+                        CDEBUG(D_OTHER, "getxattr failed: %d\n", rc);
+        } else if (reqbody->valid & OBD_MD_FLXATTRLS) {
+                DEBUG_REQ(D_INODE, req, "listxattr\n");
+
+                if (inode->i_op && inode->i_op->listxattr) {
+                        lock_24kernel();
+                        rc = inode->i_op->listxattr(dentry, buf, buflen);
+                        unlock_24kernel();
+                }
+                if (rc < 0)
+                        CDEBUG(D_OTHER, "listxattr failed: %d\n", rc);
+        } else
+                LBUG();
+
+        if (rc >= 0) {
+                repbody->eadatasize = rc;
+                rc = 0;
+        }
+out:
+        req->rq_status = rc;
+        RETURN(0);
+}
+
+int mds_getxattr(struct ptlrpc_request *req)
+{
+        struct mds_obd *mds = mds_req2mds(req);
+        struct obd_device *obd = req->rq_export->exp_obd;
+        struct lvfs_run_ctxt saved;
+        struct dentry *de;
+        struct mds_body *body;
+        struct lvfs_ucred uc = {NULL,};
+        int rc = 0;
+        ENTRY;
+
+        body = lustre_swab_reqbuf(req, 0, sizeof(*body), lustre_swab_mds_body);
+        if (body == NULL)
+                RETURN(-EFAULT);
+
+        rc = mds_init_ucred(&uc, req, 0);
+        if (rc)
+                GOTO(out_ucred, rc);
+
+        push_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
+        de = mds_fid2dentry(mds, &body->fid1, NULL);
+        if (IS_ERR(de)) {
+                rc = req->rq_status = PTR_ERR(de);
+                GOTO(out_pop, rc);
+        }
+
+        rc = mds_getxattr_pack_msg(req, de, body);
+        if (rc != 0 || req->rq_status)
+                GOTO(out_dput, rc);
+
+        rc = mds_getxattr_internal(obd, de, req, body);
+
+out_dput:
+        l_dput(de);
+out_pop:
+        pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
+out_ucred:
+        mds_exit_ucred(&uc, mds);
+        return rc;
+}
+
+static
+int mds_setxattr_internal(struct ptlrpc_request *req, struct mds_body *body)
+{
+        struct mds_obd *mds = mds_req2mds(req);
+        struct obd_device *obd = req->rq_export->exp_obd;
+        struct dentry *de;
+        struct inode *inode = NULL;
+        struct lustre_handle lockh;
+        void *handle = NULL;
+        char *xattr_name;
+        char *xattr = NULL;
+        int xattrlen;
+        int rc = -EOPNOTSUPP, err = 0;
+        ENTRY;
+
+        body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*body));
+        LASSERT(body);
+
+        DEBUG_REQ(D_INODE, req, "setxattr "LPU64"/%u",
+                  body->fid1.id, body->fid1.generation);
+
+        MDS_CHECK_RESENT(req, mds_reconstruct_generic(req));
+
+        de = mds_fid2locked_dentry(obd, &body->fid1, NULL, LCK_PW,
+                                   &lockh, NULL, 0);
+        if (IS_ERR(de))
+                GOTO(out, rc = PTR_ERR(de));
+
+        inode = de->d_inode;
+        LASSERT(inode);
+
+        OBD_FAIL_WRITE(OBD_FAIL_MDS_SETXATTR_WRITE, inode->i_sb);
+
+        xattr_name = lustre_msg_string(req->rq_reqmsg, 1, 0);
+        if (!xattr_name) {
+                CERROR("can't extract xattr name\n");
+                GOTO(out_dput, rc = -EPROTO);
+        }
+
+        DEBUG_REQ(D_INODE, req, "%sxattr %s\n",
+                  body->valid & OBD_MD_FLXATTR ? "set" : "remove",
+                  xattr_name);
+
+        if (!strncmp(xattr_name, "trusted.", 8)) {
+                if (!strcmp(xattr_name, "trusted."XATTR_LUSTRE_MDS_LOV_EA))
+                        GOTO(out_dput, rc = -EACCES);
+        }
+
+        /* filter_op simply use setattr one */
+        handle = fsfilt_start(obd, inode, FSFILT_OP_SETATTR, NULL);
+        if (IS_ERR(handle))
+                GOTO(out_dput, rc = PTR_ERR(handle));
+
+        if (body->valid & OBD_MD_FLXATTR) {
+                if (inode->i_op && inode->i_op->setxattr) {
+                        if (req->rq_reqmsg->bufcount < 3) {
+                                CERROR("no xattr data supplied\n");
+                                GOTO(out_trans, rc = -EFAULT);
+                        }
+
+                        xattrlen = lustre_msg_buflen(req->rq_reqmsg, 2);
+                        if (xattrlen)
+                                xattr = lustre_msg_buf(req->rq_reqmsg, 2,
+                                                       xattrlen);
+
+                        down(&inode->i_sem);
+                        lock_24kernel();
+                        rc = inode->i_op->setxattr(de, xattr_name, xattr,
+                                                   xattrlen, body->flags);
+                        unlock_24kernel();
+                        up(&inode->i_sem);
+                }
+        } else if (body->valid & OBD_MD_FLXATTRRM) {
+                if (inode->i_op && inode->i_op->removexattr) {
+                        down(&inode->i_sem);
+                        lock_24kernel();
+                        rc = inode->i_op->removexattr(de, xattr_name);
+                        unlock_24kernel();
+                        up(&inode->i_sem);
+                }
+        } else {
+                CERROR("valid bits: "LPX64"\n", body->valid);
+                rc = -EINVAL;
+        }
+
+        LASSERT(rc <= 0);
+out_trans:
+        err = mds_finish_transno(mds, inode, handle, req, rc, 0);
+
+out_dput:
+        l_dput(de);
+        if (rc)
+                ldlm_lock_decref(&lockh, LCK_PW);
+        else
+                ptlrpc_save_lock (req, &lockh, LCK_PW);
+
+        if (err && !rc)
+                rc = err;
+out:
+        req->rq_status = rc;
+        return 0;
+}
+
+int mds_setxattr(struct ptlrpc_request *req)
+{
+        struct mds_obd *mds = mds_req2mds(req);
+        struct obd_device *obd = req->rq_export->exp_obd;
+        struct lvfs_run_ctxt saved;
+        struct mds_body *body;
+        struct lvfs_ucred uc = {NULL,};
+        int rc;
+        ENTRY;
+
+        body = lustre_swab_reqbuf(req, 0, sizeof(*body), lustre_swab_mds_body);
+        if (body == NULL)
+                RETURN(-EFAULT);
+
+        if (req->rq_reqmsg->bufcount < 2)
+                RETURN(-EFAULT);
+
+        rc = mds_init_ucred(&uc, req, 0);
+        if (rc)
+                GOTO(out_ucred, rc);
+
+        push_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
+
+        rc = lustre_pack_reply(req, 0, NULL, NULL);
+        if (rc)
+                GOTO(out_pop, rc);
+
+        rc = mds_setxattr_internal(req, body);
+
+out_pop:
+        pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
+out_ucred:
+        mds_exit_ucred(&uc, mds);
+        return rc;
+}
index 04cc661..3bc0ad7 100644 (file)
@@ -74,6 +74,8 @@ struct ll_rpc_opcode {
         { MDS_SET_INFO,     "mds_set_info" },
         { MDS_QUOTACHECK,   "mds_quotacheck" },
         { MDS_QUOTACTL,     "mds_quotactl" },
+        { MDS_GETXATTR,     "mds_getxattr" },
+        { MDS_SETXATTR,     "mds_setxattr" },
         { LDLM_ENQUEUE,     "ldlm_enqueue" },
         { LDLM_CONVERT,     "ldlm_convert" },
         { LDLM_CANCEL,      "ldlm_cancel" },
index 3e3667f..1d66084 100644 (file)
@@ -851,8 +851,8 @@ void lustre_swab_qdata(struct qunit_data *d)
 void lustre_assert_wire_constants(void)
 {
         /* Wire protocol assertions generated by 'wirecheck'
-         * running on Linux schnapps.adilger.int 2.4.28 #2 Thu Dec 16 14:35:03 MST 2004 i686 i686 i38
-         * with gcc version 3.3.2 20040108 (Red Hat Linux 3.3.2-6) */
+         * running on Linux mustang 2.6.12-1.1456_FC4smp #1 SMP Thu Sep 22 02:22:14 EDT 2005 i686 i68
+         * with gcc version 4.0.1 20050727 (Red Hat 4.0.1-5) */
 
 
         /* Constants... */
@@ -952,7 +952,7 @@ void lustre_assert_wire_constants(void)
                  (long long)MDS_QUOTACHECK);
         LASSERTF(MDS_QUOTACTL == 48, " found %lld\n",
                  (long long)MDS_QUOTACTL);
-        LASSERTF(MDS_LAST_OPC == 49, " found %lld\n",
+        LASSERTF(MDS_LAST_OPC == 51, " found %lld\n",
                  (long long)MDS_LAST_OPC);
         LASSERTF(REINT_SETATTR == 1, " found %lld\n",
                  (long long)REINT_SETATTR);
@@ -1504,6 +1504,8 @@ void lustre_assert_wire_constants(void)
                  (long long)OBD_BRW_SYNC);
         LASSERTF(OBD_BRW_FROM_GRANT == 32, " found %lld\n",
                  (long long)OBD_BRW_FROM_GRANT);
+        LASSERTF(OBD_BRW_NOQUOTA == 256, " found %lld\n",
+                 (long long)OBD_BRW_NOQUOTA);
 
         /* Checks for struct ost_body */
         LASSERTF((int)sizeof(struct ost_body) == 208, " found %lld\n",
@@ -1958,10 +1960,6 @@ void lustre_assert_wire_constants(void)
                  (long long)(int)offsetof(struct ldlm_flock, end));
         LASSERTF((int)sizeof(((struct ldlm_flock *)0)->end) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_flock *)0)->end));
-        LASSERTF((int)offsetof(struct ldlm_flock, blocking_export) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_flock, blocking_export));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->blocking_export) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_flock *)0)->blocking_export));
         LASSERTF((int)offsetof(struct ldlm_flock, blocking_pid) == 24, " found %lld\n",
                  (long long)(int)offsetof(struct ldlm_flock, blocking_pid));
         LASSERTF((int)sizeof(((struct ldlm_flock *)0)->blocking_pid) == 4, " found %lld\n",
index ab52aed..5dbd9d1 100755 (executable)
@@ -17,6 +17,8 @@ NETTYPE=${NETTYPE:-tcp}
 OSTDEV=${OSTDEV:-$TMP/ost1-`hostname`}
 OSTSIZE=${OSTSIZE:-400000}
 
+CLIENTOPT=${CLIENTOPT:-"user_xattr"}
+
 # specific journal size for the ost, in MB
 JSIZE=${JSIZE:-0}
 [ "$JSIZE" -gt 0 ] && JARG="--journal_size $JSIZE"
@@ -53,6 +55,9 @@ ${LMC} --add ost --node localhost --lov lov1 --fstype $FSTYPE \
        $OST_MOUNT_OPTS --size $OSTSIZE $JARG $OSTOPT || exit 30
 
 # create client config
+[ "x$CLIENTOPT" != "x" ] &&
+    CLIENTOPT="--clientoptions $CLIENTOPT"
+
 ${LMC} --add mtpt --node localhost --path $MOUNT \
        --mds mds1 --lov lov1 $CLIENTOPT || exit 40
 ${LMC} --add mtpt --node client --path $MOUNT2 \
index b2c2acc..40e02f2 100644 (file)
@@ -2712,6 +2712,47 @@ test_101() {
 }
 run_test 101 "check read-ahead for random reads ==========="
 
+test_102() {
+       local testfile=$DIR/xattr_testfile
+
+       rm -f $testfile
+        touch $testfile
+
+       echo "set/get xattr..."
+        setfattr -n trusted.name1 -v value1 $testfile || error
+        [ "`getfattr -n trusted.name1 $testfile 2> /dev/null | \
+        grep "trusted.name1"`" == "trusted.name1=\"value1\"" ] || error
+        setfattr -n user.author1 -v author1 $testfile || error
+        [ "`getfattr -n user.author1 $testfile 2> /dev/null | \
+        grep "user.author1"`" == "user.author1=\"author1\"" ] || error
+
+       echo "listxattr..."
+        setfattr -n trusted.name2 -v value2 $testfile || error
+        setfattr -n trusted.name3 -v value3 $testfile || error
+        [ `getfattr -d -m "^trusted" $testfile 2> /dev/null | \
+        grep "trusted.name" | wc -l` -eq 3 ] || error
+
+        setfattr -n user.author2 -v author2 $testfile || error
+        setfattr -n user.author3 -v author3 $testfile || error
+        [ `getfattr -d -m "^user" $testfile 2> /dev/null | \
+        grep "user" | wc -l` -eq 3 ] || error
+
+       echo "remove xattr..."
+        setfattr -x trusted.name1 $testfile || error
+        getfattr -d -m trusted $testfile 2> /dev/null | \
+        grep "trusted.name1" && error || true
+
+        setfattr -x user.author1 $testfile || error
+        getfattr -d -m user $testfile 2> /dev/null | \
+        grep "user.author1" && error || true
+
+       echo "set lustre specific xattr (should be denied)..."
+       setfattr -n "trusted.lov" -v "invalid value" $testfile || true
+}
+run_test 102 "user xattr test ====================="
+
 TMPDIR=$OLDTMPDIR
 TMP=$OLDTMP
 HOME=$OLDHOME
index 1a83a71..0da540e 100755 (executable)
@@ -1054,6 +1054,8 @@ def def_mount_options(fstype, target):
                 mountfsoptions = "%s,asyncdel" % (mountfsoptions)
             #else:
             #    mountfsoptions = "%s,extents,mballoc" % (mountfsoptions)
+        elif target == 'mds':
+            mountfsoptions = "%s,user_xattr" % (mountfsoptions)
         return mountfsoptions
     return ""
 
index 84d5e68..525f995 100644 (file)
@@ -74,7 +74,8 @@ void usage(FILE *out)
                 "\t\tlocal_nid=0xNNNN: client ID (default ipaddr or nodenum)\n"
                 "\t\tserver_nid=0xNNNN: server node ID (default mdsnode)\n"
                 "\t\tport=NNN: server port (default 988 for tcp)\n"
-                "\t\troute=<gw>[-<gw>]:<low>[-<high>]: portal route to MDS\n");
+                "\t\troute=<gw>[-<gw>]:<low>[-<high>]: portal route to MDS\n"
+                "\t\tuser_xattr: enable manipulating user xattr\n");
         exit(out != stdout);
 }
 
@@ -271,6 +272,7 @@ static const struct opt_map opt_map[] = {
   { "_netdev",  0, 0, 0, 0         },      /* Device accessible only via network */
   { "flock",    0, 0, 0, LMD_FLG_FLOCK},   /* Enable flock support */
   { "noflock",  1, 1, 0, LMD_FLG_FLOCK},   /* Disable flock support */
+  { "user_xattr", 0, 0, 0, LMD_FLG_USER_XATTR}, /* Enable get/set user xattr */
   { NULL,       0, 0, 0, 0         }
 };
 /****************************************************************************/
index 922ecd6..a6dab8e 100644 (file)
@@ -25,8 +25,8 @@ int main()
 void lustre_assert_wire_constants(void)
 {
         /* Wire protocol assertions generated by 'wirecheck'
-         * running on Linux schnapps.adilger.int 2.4.28 #2 Thu Dec 16 14:35:03 MST 2004 i686 i686 i38
-         * with gcc version 3.3.2 20040108 (Red Hat Linux 3.3.2-6) */
+         * running on Linux mustang 2.6.12-1.1456_FC4smp #1 SMP Thu Sep 22 02:22:14 EDT 2005 i686 i68
+         * with gcc version 4.0.1 20050727 (Red Hat 4.0.1-5) */
 
 
         /* Constants... */
@@ -126,7 +126,7 @@ void lustre_assert_wire_constants(void)
                  (long long)MDS_QUOTACHECK);
         LASSERTF(MDS_QUOTACTL == 48, " found %lld\n",
                  (long long)MDS_QUOTACTL);
-        LASSERTF(MDS_LAST_OPC == 49, " found %lld\n",
+        LASSERTF(MDS_LAST_OPC == 51, " found %lld\n",
                  (long long)MDS_LAST_OPC);
         LASSERTF(REINT_SETATTR == 1, " found %lld\n",
                  (long long)REINT_SETATTR);
@@ -678,6 +678,8 @@ void lustre_assert_wire_constants(void)
                  (long long)OBD_BRW_SYNC);
         LASSERTF(OBD_BRW_FROM_GRANT == 32, " found %lld\n",
                  (long long)OBD_BRW_FROM_GRANT);
+        LASSERTF(OBD_BRW_NOQUOTA == 256, " found %lld\n",
+                 (long long)OBD_BRW_NOQUOTA);
 
         /* Checks for struct ost_body */
         LASSERTF((int)sizeof(struct ost_body) == 208, " found %lld\n",
@@ -1132,10 +1134,6 @@ void lustre_assert_wire_constants(void)
                  (long long)(int)offsetof(struct ldlm_flock, end));
         LASSERTF((int)sizeof(((struct ldlm_flock *)0)->end) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_flock *)0)->end));
-        LASSERTF((int)offsetof(struct ldlm_flock, blocking_export) == 16, " found %lld\n",
-                 (long long)(int)offsetof(struct ldlm_flock, blocking_export));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->blocking_export) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_flock *)0)->blocking_export));
         LASSERTF((int)offsetof(struct ldlm_flock, blocking_pid) == 24, " found %lld\n",
                  (long long)(int)offsetof(struct ldlm_flock, blocking_pid));
         LASSERTF((int)sizeof(((struct ldlm_flock *)0)->blocking_pid) == 4, " found %lld\n",