From 72352f764eb1c26c29a54040d79fbe37a8516e2a Mon Sep 17 00:00:00 2001 From: ericm Date: Thu, 13 Oct 2005 05:23:42 +0000 Subject: [PATCH] branch: b1_4 land b1_4_xattr: support manipulating user extended attributes. --- .../patches/ext3-ea-in-inode-2.6-rhel4.patch | 68 +++-- lustre/include/linux/lustre_cfg.h | 3 +- lustre/include/linux/lustre_compat25.h | 6 + lustre/include/linux/lustre_fsfilt.h | 2 + lustre/include/linux/lustre_idl.h | 10 +- lustre/include/linux/lustre_lite.h | 2 + lustre/include/linux/lustre_mds.h | 9 + lustre/include/linux/obd_support.h | 5 + .../patches/ext3-ea-in-inode-2.6-rhel4.patch | 68 +++-- lustre/llite/Makefile.in | 2 +- lustre/llite/file.c | 4 + lustre/llite/llite_internal.h | 9 + lustre/llite/llite_lib.c | 7 + lustre/llite/lproc_llite.c | 2 + lustre/llite/namei.c | 4 + lustre/llite/special.c | 4 + lustre/llite/symlink.c | 8 +- lustre/llite/xattr.c | 236 +++++++++++++++ lustre/lvfs/fsfilt_ext3.c | 9 - lustre/mdc/mdc_request.c | 106 +++++++ lustre/mds/Makefile.in | 2 +- lustre/mds/handler.c | 16 +- lustre/mds/mds_internal.h | 4 + lustre/mds/mds_xattr.c | 335 +++++++++++++++++++++ lustre/ptlrpc/lproc_ptlrpc.c | 2 + lustre/ptlrpc/pack_generic.c | 12 +- lustre/tests/local.sh | 5 + lustre/tests/sanity.sh | 41 +++ lustre/utils/lconf | 2 + lustre/utils/llmount.c | 4 +- lustre/utils/wiretest.c | 12 +- 31 files changed, 907 insertions(+), 92 deletions(-) create mode 100644 lustre/llite/xattr.c create mode 100644 lustre/mds/mds_xattr.c diff --git a/ldiskfs/kernel_patches/patches/ext3-ea-in-inode-2.6-rhel4.patch b/ldiskfs/kernel_patches/patches/ext3-ea-in-inode-2.6-rhel4.patch index 9d5bee1..507b044 100644 --- a/ldiskfs/kernel_patches/patches/ext3-ea-in-inode-2.6-rhel4.patch +++ b/ldiskfs/kernel_patches/patches/ext3-ea-in-inode-2.6-rhel4.patch @@ -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; diff --git a/lustre/include/linux/lustre_cfg.h b/lustre/include/linux/lustre_cfg.h index b32f6f8..a5232af 100644 --- a/lustre/include/linux/lustre_cfg.h +++ b/lustre/include/linux/lustre_cfg.h @@ -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 diff --git a/lustre/include/linux/lustre_compat25.h b/lustre/include/linux/lustre_compat25.h index bb01446..8788fe6 100644 --- a/lustre/include/linux/lustre_compat25.h +++ b/lustre/include/linux/lustre_compat25.h @@ -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 #endif diff --git a/lustre/include/linux/lustre_fsfilt.h b/lustre/include/linux/lustre_fsfilt.h index b82effc..a446c65 100644 --- a/lustre/include/linux/lustre_fsfilt.h +++ b/lustre/include/linux/lustre_fsfilt.h @@ -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; diff --git a/lustre/include/linux/lustre_idl.h b/lustre/include/linux/lustre_idl.h index b6fc6c5..87cc637 100644 --- a/lustre/include/linux/lustre_idl.h +++ b/lustre/include/linux/lustre_idl.h @@ -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; diff --git a/lustre/include/linux/lustre_lite.h b/lustre/include/linux/lustre_lite.h index ee62508..e6bb40b 100644 --- a/lustre/include/linux/lustre_lite.h +++ b/lustre/include/linux/lustre_lite.h @@ -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, diff --git a/lustre/include/linux/lustre_mds.h b/lustre/include/linux/lustre_mds.h index d3aae2c..5c43429 100644 --- a/lustre/include/linux/lustre_mds.h +++ b/lustre/include/linux/lustre_mds.h @@ -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 **); diff --git a/lustre/include/linux/obd_support.h b/lustre/include/linux/obd_support.h index 554461b..0bb7e55 100644 --- a/lustre/include/linux/obd_support.h +++ b/lustre/include/linux/obd_support.h @@ -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 diff --git a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.6-rhel4.patch b/lustre/kernel_patches/patches/ext3-ea-in-inode-2.6-rhel4.patch index 9d5bee1..507b044 100644 --- a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.6-rhel4.patch +++ b/lustre/kernel_patches/patches/ext3-ea-in-inode-2.6-rhel4.patch @@ -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; diff --git a/lustre/llite/Makefile.in b/lustre/llite/Makefile.in index 4daad42..7a908d7 100644 --- a/lustre/llite/Makefile.in +++ b/lustre/llite/Makefile.in @@ -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 diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 170f7a7..0c06efc 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -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, }; diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index dfefb72..346ef4c 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -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 */ diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 92759c3..f668c62 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -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.*/ diff --git a/lustre/llite/lproc_llite.c b/lustre/llite/lproc_llite.c index 54cb257..c445c91 100644 --- a/lustre/llite/lproc_llite.c +++ b/lustre/llite/lproc_llite.c @@ -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, diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 4ec2685..4511658 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -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, }; diff --git a/lustre/llite/special.c b/lustre/llite/special.c index 1e9355a..328801d 100644 --- a/lustre/llite/special.c +++ b/lustre/llite/special.c @@ -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 = { diff --git a/lustre/llite/symlink.c b/lustre/llite/symlink.c index 57dc9b3..0b5d990 100644 --- a/lustre/llite/symlink.c +++ b/lustre/llite/symlink.c @@ -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 index 0000000..b932648 --- /dev/null +++ b/lustre/llite/xattr.c @@ -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 +#include +#include +#include +#include + +#define DEBUG_SUBSYSTEM S_LLITE + +#include +#include +#include +#include +#include + +#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); +} + diff --git a/lustre/lvfs/fsfilt_ext3.c b/lustre/lvfs/fsfilt_ext3.c index b13724d..25ada73 100644 --- a/lustre/lvfs/fsfilt_ext3.c +++ b/lustre/lvfs/fsfilt_ext3.c @@ -58,14 +58,6 @@ #include #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 diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index 434d114..dbd78ae 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -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); diff --git a/lustre/mds/Makefile.in b/lustre/mds/Makefile.in index 3e8cff6..25eb6f0 100644 --- a/lustre/mds/Makefile.in +++ b/lustre/mds/Makefile.in @@ -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 diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index 97a3642..a42abb5 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -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"); diff --git a/lustre/mds/mds_internal.h b/lustre/mds/mds_internal.h index 6fffb8b..1aa5967 100644 --- a/lustre/mds/mds_internal.h +++ b/lustre/mds/mds_internal.h @@ -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 index 0000000..a96d397 --- /dev/null +++ b/lustre/mds/mds_xattr.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/lustre/ptlrpc/lproc_ptlrpc.c b/lustre/ptlrpc/lproc_ptlrpc.c index 04cc661..3bc0ad7 100644 --- a/lustre/ptlrpc/lproc_ptlrpc.c +++ b/lustre/ptlrpc/lproc_ptlrpc.c @@ -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" }, diff --git a/lustre/ptlrpc/pack_generic.c b/lustre/ptlrpc/pack_generic.c index 3e3667f..1d66084 100644 --- a/lustre/ptlrpc/pack_generic.c +++ b/lustre/ptlrpc/pack_generic.c @@ -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", diff --git a/lustre/tests/local.sh b/lustre/tests/local.sh index ab52aed..5dbd9d1 100755 --- a/lustre/tests/local.sh +++ b/lustre/tests/local.sh @@ -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 \ diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index b2c2acc..40e02f2 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -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 diff --git a/lustre/utils/lconf b/lustre/utils/lconf index 1a83a71..0da540e 100755 --- a/lustre/utils/lconf +++ b/lustre/utils/lconf @@ -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 "" diff --git a/lustre/utils/llmount.c b/lustre/utils/llmount.c index 84d5e68..525f995 100644 --- a/lustre/utils/llmount.c +++ b/lustre/utils/llmount.c @@ -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=[-]:[-]: portal route to MDS\n"); + "\t\troute=[-]:[-]: 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 } }; /****************************************************************************/ diff --git a/lustre/utils/wiretest.c b/lustre/utils/wiretest.c index 922ecd6..a6dab8e 100644 --- a/lustre/utils/wiretest.c +++ b/lustre/utils/wiretest.c @@ -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", -- 1.8.3.1