land b1_4_xattr: support manipulating user extended attributes.
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);
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.
*/
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);
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];
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) {
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
error = 0;
if (!EXT3_I(inode)->i_file_acl)
goto cleanup;
-@@ -330,11 +419,139 @@
+@@ -330,11 +419,149 @@
cleanup:
brelse(bh);
+ char *start, *end, *buf;
+ struct ext3_iloc iloc;
+ int storage_size;
++ size_t rest = buffer_size;
+ int ret;
+ int size = 0;
+
+ }
+ 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;
+ }
+
+ 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;
/*
* 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 @@
}
/*
* 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,
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.
*/
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);
}
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);
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;
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;
char lmd_profile[64];
};
-#define LMD_FLG_FLOCK 0x0001
+#define LMD_FLG_FLOCK 0x0001
+#define LMD_FLG_USER_XATTR 0x0002
#endif // _LUSTRE_CFG_H
#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
#else /* 2.4.. */
+#define lock_24kernel() lock_kernel()
+#define unlock_24kernel() unlock_kernel()
+
#ifdef HAVE_MM_INLINE
#include <linux/mm_inline.h>
#endif
int fso_bufcnt;
};
+#define XATTR_LUSTRE_MDS_LOV_EA "lov"
+
struct fsfilt_operations {
struct list_head fs_list;
struct module *fs_owner;
#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 | \
MDS_SET_INFO = 46,
MDS_QUOTACHECK = 47,
MDS_QUOTACTL = 48,
+ MDS_GETXATTR = 49,
+ MDS_SETXATTR = 50,
MDS_LAST_OPC
} mds_cmd_t;
#endif
LPROC_LL_STAFS,
LPROC_LL_ALLOC_INODE,
+ LPROC_LL_SETXATTR,
+ LPROC_LL_GETXATTR,
LPROC_LL_DIRECT_READ,
LPROC_LL_DIRECT_WRITE,
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 **);
#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: 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);
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.
*/
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);
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];
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) {
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
error = 0;
if (!EXT3_I(inode)->i_file_acl)
goto cleanup;
-@@ -330,11 +419,139 @@
+@@ -330,11 +419,149 @@
cleanup:
brelse(bh);
+ char *start, *end, *buf;
+ struct ext3_iloc iloc;
+ int storage_size;
++ size_t rest = buffer_size;
+ int ret;
+ int size = 0;
+
+ }
+ 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;
+ }
+
+ 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;
/*
* 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 @@
}
/*
* 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,
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.
*/
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);
}
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);
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;
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;
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
#else
.revalidate_it = ll_inode_revalidate_it,
#endif
+ .setxattr = ll_setxattr,
+ .getxattr = ll_getxattr,
+ .listxattr = ll_listxattr,
+ .removexattr = ll_removexattr,
};
#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;
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 */
*flags &= ~tmp;
continue;
}
+ tmp = ll_set_opt("user_xattr", this_char, LL_SBI_USER_XATTR);
+ if (tmp) {
+ *flags |= tmp;
+ continue;
+ }
}
EXIT;
}
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.*/
/* 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,
.create = ll_create_nd,
.getattr_it = ll_getattr,
#endif
+ .setxattr = ll_setxattr,
+ .getxattr = ll_getxattr,
+ .listxattr = ll_listxattr,
+ .removexattr = ll_removexattr,
};
#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 = {
.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,
};
--- /dev/null
+/* -*- 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);
+}
+
#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 {
#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
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)
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);
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
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)
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");
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);
--- /dev/null
+/* -*- 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;
+}
{ 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" },
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... */
(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);
(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",
(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",
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"
$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 \
}
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
mountfsoptions = "%s,asyncdel" % (mountfsoptions)
#else:
# mountfsoptions = "%s,extents,mballoc" % (mountfsoptions)
+ elif target == 'mds':
+ mountfsoptions = "%s,user_xattr" % (mountfsoptions)
return mountfsoptions
return ""
"\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);
}
{ "_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 }
};
/****************************************************************************/
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... */
(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);
(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",
(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",