result; \
})
+/* ACL */
+struct posix_acl_entry {
+ short e_tag;
+ unsigned short e_perm;
+ unsigned int e_id;
+};
+
+struct posix_acl {
+ atomic_t a_refcount;
+ unsigned int a_count;
+ struct posix_acl_entry a_entries[0];
+};
+
+typedef struct {
+ __u16 e_tag;
+ __u16 e_perm;
+ __u32 e_id;
+} xattr_acl_entry;
+
+typedef struct {
+ __u32 a_version;
+ xattr_acl_entry a_entries[0];
+} xattr_acl_header;
+
+static inline size_t xattr_acl_size(int count)
+{
+ return sizeof(xattr_acl_header) + count * sizeof(xattr_acl_entry);
+}
+
+static inline
+struct posix_acl * posix_acl_from_xattr(const void *value, size_t size)
+{
+ return NULL;
+}
+
+static inline
+int posix_acl_valid(const struct posix_acl *acl)
+{
+ return 0;
+}
+
+static inline
+void posix_acl_release(struct posix_acl *acl)
+{
+}
+
#ifndef ENOTSUPP
#define ENOTSUPP ENOTSUP
#endif
#define LMD_FLG_FLOCK 0x0001
#define LMD_FLG_USER_XATTR 0x0002
+#define LMD_FLG_ACL 0x0004
#endif // _LUSTRE_CFG_H
/* Connect flags */
-#define OBD_CONNECT_RDONLY 0x1ULL
-#define OBD_CONNECT_SRVLOCK 0x10ULL /* server takes locks for client */
-
-#define MDS_CONNECT_SUPPORTED (OBD_CONNECT_RDONLY)
+#define OBD_CONNECT_RDONLY 0x0001ULL
+#define OBD_CONNECT_SRVLOCK 0x0010ULL /* server takes locks for client */
+#define OBD_CONNECT_ACL 0x0080ULL
+#define OBD_CONNECT_USER_XATTR 0x0100ULL
+
+#define MDS_CONNECT_SUPPORTED (OBD_CONNECT_RDONLY | \
+ OBD_CONNECT_ACL | \
+ OBD_CONNECT_USER_XATTR)
#define OST_CONNECT_SUPPORTED (OBD_CONNECT_SRVLOCK)
#define ECHO_CONNECT_SUPPORTED (0)
#define OBD_MD_FLXATTR (0x0000001000000000ULL) /* xattr */
#define OBD_MD_FLXATTRLS (0x0000002000000000ULL) /* xattr list */
#define OBD_MD_FLXATTRRM (0x0000004000000000ULL) /* xattr remove */
+#define OBD_MD_FLACL (0x0000008000000000ULL) /* ACL */
#define OBD_MD_FLGETATTR (OBD_MD_FLID | OBD_MD_FLATIME | OBD_MD_FLMTIME | \
OBD_MD_FLCTIME | OBD_MD_FLSIZE | OBD_MD_FLBLKSZ | \
__u32 generation;
__u32 suppgid;
__u32 eadatasize;
- __u32 padding_1; /* also fix lustre_swab_mds_body */
+ __u32 aclsize;
__u32 padding_2; /* also fix lustre_swab_mds_body */
__u32 padding_3; /* also fix lustre_swab_mds_body */
__u32 padding_4; /* also fix lustre_swab_mds_body */
#ifdef __KERNEL__
# include <linux/fs.h>
# include <linux/dcache.h>
+# include <linux/xattr_acl.h>
#endif
#include <linux/lustre_handles.h>
#include <libcfs/kp30.h>
#define LUSTRE_MDC_NAME "mdc"
struct lustre_md {
- struct mds_body *body;
- struct lov_stripe_md *lsm;
+ struct mds_body *body;
+ struct lov_stripe_md *lsm;
+ struct posix_acl *posix_acl;
};
struct mdc_op_data {
struct dentry *mfd_dentry;
};
+/* ACL */
+#define LUSTRE_POSIX_ACL_MAX_ENTRIES (32)
+#define LUSTRE_POSIX_ACL_MAX_SIZE \
+ (xattr_acl_size(LUSTRE_POSIX_ACL_MAX_ENTRIES))
+
/* mds/mds_reint.c */
int mds_reint_rec(struct mds_update_record *r, int offset,
struct ptlrpc_request *req, struct lustre_handle *);
int mdc_init_ea_size(struct obd_export *mdc_exp, struct obd_export *lov_exp);
int mdc_req2lustre_md(struct ptlrpc_request *req, int offset,
struct obd_export *exp, struct lustre_md *md);
+void mdc_free_lustre_md(struct obd_export *exp, struct lustre_md *md);
int mdc_getstatus(struct obd_export *exp, struct ll_fid *rootfid);
int mdc_getattr(struct obd_export *exp, struct ll_fid *fid,
obd_valid valid, unsigned int ea_size,
char **bufs);
int lustre_pack_reply(struct ptlrpc_request *, int count, int *lens,
char **bufs);
+void lustre_shrink_reply(struct ptlrpc_request *req,
+ int segment, unsigned int newlen, int move_data);
void lustre_free_reply_state(struct ptlrpc_reply_state *rs);
int lustre_msg_size(int count, int *lengths);
int lustre_unpack_msg(struct lustre_msg *m, int len);
int mds_has_lov_desc;
struct lov_desc mds_lov_desc;
obd_id *mds_lov_objids;
- int mds_lov_objids_valid;
int mds_lov_nextid_set;
struct file *mds_lov_objid_filp;
unsigned long *mds_client_bitmap;
struct lustre_quota_ctxt mds_quota_ctxt;
atomic_t mds_quotachecking;
struct semaphore mds_health_sem;
+ unsigned long mds_lov_objids_valid:1,
+ mds_fl_user_xattr:1,
+ mds_fl_acl:1;
};
struct echo_obd {
rc = mdc_req2lustre_md(req, 1, exp, &md);
if (rc)
GOTO(out, rc);
- ll_update_inode(f->f_dentry->d_inode, md.body, md.lsm);
+ ll_update_inode(f->f_dentry->d_inode, &md);
rc = ll_local_open(f, &oit, fd);
if (rc)
struct ptlrpc_request *req = NULL;
struct ll_sb_info *sbi = ll_i2sbi(dentry->d_inode);
struct ll_fid fid;
- unsigned long valid = OBD_MD_FLGETATTR;
+ obd_valid valid = OBD_MD_FLGETATTR;
int ealen = 0;
if (S_ISREG(inode->i_mode)) {
}
#endif
+static
+int lustre_check_acl(struct inode *inode, int mask)
+{
+ struct ll_inode_info *lli = ll_i2info(inode);
+ struct posix_acl *acl;
+ int rc;
+ ENTRY;
+
+ spin_lock(&lli->lli_lock);
+ acl = posix_acl_dup(lli->lli_posix_acl);
+ spin_unlock(&lli->lli_lock);
+
+ if (!acl)
+ RETURN(-EAGAIN);
+
+ rc = posix_acl_permission(inode, acl, mask);
+ posix_acl_release(acl);
+
+ RETURN(rc);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
+int ll_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), mask %o\n",
+ inode->i_ino, inode->i_generation, inode, mask);
+ return generic_permission(inode, mask, lustre_check_acl);
+}
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+int ll_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
+#else
+int ll_inode_permission(struct inode *inode, int mask)
+#endif
+{
+ int mode = inode->i_mode;
+ int rc;
+
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), mask %o\n",
+ inode->i_ino, inode->i_generation, inode, mask);
+
+ if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
+ (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+ return -EROFS;
+ if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
+ return -EACCES;
+ if (current->fsuid == inode->i_uid) {
+ mode >>= 6;
+ } else if (1) {
+ if (((mode >> 3) & mask & S_IRWXO) != mask)
+ goto check_groups;
+ rc = lustre_check_acl(inode, mask);
+ if (rc == -EAGAIN)
+ goto check_groups;
+ if (rc == -EACCES)
+ goto check_capabilities;
+ return rc;
+ } else {
+check_groups:
+ if (in_group_p(inode->i_gid))
+ mode >>= 3;
+ }
+ if ((mode & mask & S_IRWXO) == mask)
+ return 0;
+
+check_capabilities:
+ if (!(mask & MAY_EXEC) ||
+ (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
+ if (capable(CAP_DAC_OVERRIDE))
+ return 0;
+
+ if (capable(CAP_DAC_READ_SEARCH) && ((mask == MAY_READ) ||
+ (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))))
+ return 0;
+ return -EACCES;
+}
+#endif
+
struct file_operations ll_file_operations = {
.read = ll_file_read,
.write = ll_file_write,
#else
.revalidate_it = ll_inode_revalidate_it,
#endif
+ .permission = ll_inode_permission,
.setxattr = ll_setxattr,
.getxattr = ll_getxattr,
.listxattr = ll_listxattr,
struct file_operations *ll_save_ffop;
struct file_operations *ll_save_wfop;
struct file_operations *ll_save_wrfop;
+
+ struct posix_acl *lli_posix_acl;
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
struct inode lli_vfs_inode;
#endif
};
/* flags for sbi->ll_flags */
-#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 */
+#define LL_SBI_NOLCK 0x01 /* DLM locking disabled (directio-only) */
+#define LL_SBI_CHECKSUM 0x02 /* checksum each page as it's written */
+#define LL_SBI_FLOCK 0x04
+#define LL_SBI_USER_XATTR 0x08 /* support user xattr */
+#define LL_SBI_ACL 0x10 /* support ACL */
struct ll_sb_info {
struct list_head ll_list;
struct lookup_intent *it, struct kstat *stat);
#endif
struct ll_file_data *ll_file_data_get(void);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+int ll_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
+#else
+int ll_inode_permission(struct inode *inode, int mask);
+#endif
/* llite/dcache.c */
void ll_intent_drop_lock(struct lookup_intent *);
int ll_statfs(struct super_block *sb, struct kstatfs *sfs);
int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs,
unsigned long maxage);
-void ll_update_inode(struct inode *inode, struct mds_body *body,
- struct lov_stripe_md *lsm);
+void ll_update_inode(struct inode *inode, struct lustre_md *md);
void ll_read_inode2(struct inode *inode, void *opaque);
int ll_iocontrol(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
/* 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);
+ssize_t ll_getxattr(struct dentry *dentry, const char *name,
+ void *buffer, size_t size);
+ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size);
int ll_removexattr(struct dentry *dentry, const char *name);
#endif /* LLITE_INTERNAL_H */
if (sb->s_flags & MS_RDONLY)
data->ocd_connect_flags |= OBD_CONNECT_RDONLY;
+ if (sbi->ll_flags & LL_SBI_USER_XATTR)
+ data->ocd_connect_flags |= OBD_CONNECT_USER_XATTR;
+ if (sbi->ll_flags & LL_SBI_ACL)
+ data->ocd_connect_flags |= OBD_CONNECT_ACL;
if (sbi->ll_flags & LL_SBI_FLOCK) {
sbi->ll_fop = &ll_file_operations_flock;
if (err)
GOTO(out_mdc, err);
+ /* async connect is surely finished by now */
+ *data = class_exp2cliimp(sbi->ll_mdc_exp)->imp_connect_data;
+
LASSERT(osfs.os_bsize);
sb->s_blocksize = osfs.os_bsize;
sb->s_blocksize_bits = log2(osfs.os_bsize);
sb->s_maxbytes = PAGE_CACHE_MAXBYTES;
sbi->ll_namelen = osfs.os_namelen;
+ if ((sbi->ll_flags & LL_SBI_USER_XATTR) &&
+ !(data->ocd_connect_flags & OBD_CONNECT_USER_XATTR)) {
+ LCONSOLE_INFO("Disabling user_xattr feature because "
+ "it is not supported on the server\n");
+ sbi->ll_flags &= ~LL_SBI_USER_XATTR;
+ }
+
+ if (((sbi->ll_flags & LL_SBI_ACL) == 0) !=
+ ((data->ocd_connect_flags & OBD_CONNECT_ACL) == 0)) {
+ CERROR("Server return unexpected ACL flags\n");
+ GOTO(out_mdc, err = -EBADE);
+ }
+
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
/* We set sb->s_dev equal on all lustre clients in order to support
* NFS export clustering. NFSD requires that the FSID be the same
/* make root inode
* XXX: move this to after cbd setup? */
err = mdc_getattr(sbi->ll_mdc_exp, &rootfid,
- OBD_MD_FLGETATTR | OBD_MD_FLBLOCKS, 0, &request);
+ OBD_MD_FLGETATTR | OBD_MD_FLBLOCKS | OBD_MD_FLACL,
+ 0, &request);
if (err) {
CERROR("mdc_getattr failed for root: rc = %d\n", err);
GOTO(out_osc, err);
ptlrpc_req_finished(request);
if (root == NULL || is_bad_inode(root)) {
- if (md.lsm != NULL)
- obd_free_memmd(sbi->ll_osc_exp, &md.lsm);
+ mdc_free_lustre_md(sbi->ll_osc_exp, &md);
CERROR("lustre_lite: bad iget4 for root\n");
GOTO(out_root, err = -EBADF);
}
*flags &= ~tmp;
continue;
}
+ tmp = ll_set_opt("acl", this_char, LL_SBI_ACL);
+ if (tmp) {
+ *flags |= tmp;
+ continue;
+ }
+ tmp = ll_set_opt("noacl", this_char, LL_SBI_ACL);
+ if (tmp) {
+ *flags &= ~tmp;
+ continue;
+ }
}
EXIT;
}
class_uuid_t uuid;
struct obd_uuid mdc_uuid;
struct llog_ctxt *ctxt;
+ struct obd_connect_data *ocd = NULL;
int rc = 0;
int err;
ENTRY;
rc = class_process_config(lcfg);
lustre_cfg_free(lcfg);
if (rc < 0)
- GOTO(out, err);
+ GOTO(out, rc);
lustre_cfg_bufs_reset(&bufs, name);
lustre_cfg_bufs_set_string(&bufs, 1, LUSTRE_MDC_NAME);
if (rc)
GOTO(out_cleanup, rc);
- rc = obd_connect(&mdc_conn, obd, &mdc_uuid, NULL /* ocd */);
+ if (lmd->lmd_flags & LMD_FLG_ACL) {
+ OBD_ALLOC(ocd, sizeof(*ocd));
+ if (ocd == NULL)
+ GOTO(out_cleanup, rc = -ENOMEM);
+ ocd->ocd_connect_flags |= OBD_CONNECT_ACL;
+ }
+
+ rc = obd_connect(&mdc_conn, obd, &mdc_uuid, ocd);
if (rc) {
CERROR("cannot connect to %s: rc = %d\n", lmd->lmd_mds, rc);
GOTO(out_cleanup, rc);
CERROR("del MDC UUID failed: rc = %d\n", err);
out:
-
+ if (ocd)
+ OBD_FREE(ocd, sizeof(*ocd));
RETURN(rc);
}
sbi->ll_flags |= LL_SBI_FLOCK;
if (lmd->lmd_flags & LMD_FLG_USER_XATTR)
sbi->ll_flags |= LL_SBI_USER_XATTR;
+ if (lmd->lmd_flags & LMD_FLG_ACL)
+ sbi->ll_flags |= LL_SBI_ACL;
/* generate a string unique to this super, let's try
the address of the super itself.*/
strlen(lli->lli_symlink_name) + 1);
lli->lli_symlink_name = NULL;
}
+
+ if (lli->lli_posix_acl) {
+ LASSERT(atomic_read(&lli->lli_posix_acl->a_refcount) == 1);
+ posix_acl_release(lli->lli_posix_acl);
+ lli->lli_posix_acl = NULL;
+ }
+
lli->lli_inode_magic = LLI_INODE_DEAD;
EXIT;
* (bug 6196) */
inode_setattr(inode, attr);
- ll_update_inode(inode, md.body, md.lsm);
+ ll_update_inode(inode, &md);
ptlrpc_req_finished(request);
if (!lsm || !S_ISREG(inode->i_mode)) {
up(&lli->lli_size_sem);
}
-void ll_update_inode(struct inode *inode, struct mds_body *body,
- struct lov_stripe_md *lsm)
+void ll_update_inode(struct inode *inode, struct lustre_md *md)
{
struct ll_inode_info *lli = ll_i2info(inode);
+ struct mds_body *body = md->body;
+ struct lov_stripe_md *lsm = md->lsm;
LASSERT ((lsm != NULL) == ((body->valid & OBD_MD_FLEASIZE) != 0));
if (lsm != NULL) {
inode->i_sb->s_blocksize);
}
+ LASSERT(!md->posix_acl || (body->valid & OBD_MD_FLACL));
+ if (body->valid & OBD_MD_FLACL) {
+ spin_lock(&lli->lli_lock);
+ if (lli->lli_posix_acl)
+ posix_acl_release(lli->lli_posix_acl);
+ lli->lli_posix_acl = md->posix_acl;
+ spin_unlock(&lli->lli_lock);
+ }
+
if (body->valid & OBD_MD_FLID)
inode->i_ino = body->ino;
if (body->valid & OBD_MD_FLATIME)
LTIME_S(inode->i_atime) = 0;
LTIME_S(inode->i_ctime) = 0;
inode->i_rdev = 0;
- ll_update_inode(inode, md->body, md->lsm);
+ ll_update_inode(inode, md);
/* OIDEBUG(inode); */
RETURN(rc);
if (*inode) {
- ll_update_inode(*inode, md.body, md.lsm);
+ ll_update_inode(*inode, &md);
} else {
LASSERT(sb);
*inode = ll_iget(sb, md.body->ino, &md);
if (*inode == NULL || is_bad_inode(*inode)) {
- /* free the lsm if we allocated one above */
- if (md.lsm != NULL)
- obd_free_memmd(exp, &md.lsm);
+ mdc_free_lustre_md(exp, &md);
rc = -ENOMEM;
CERROR("new_inode -fatal: rc %d\n", rc);
}
/* Apply the attributes in 'opaque' to this inode */
if (!(inode->i_state & (I_FREEING | I_CLEAR)))
- ll_update_inode(inode, md->body, md->lsm);
+ ll_update_inode(inode, md);
return 1;
}
.create = ll_create_nd,
.getattr_it = ll_getattr,
#endif
+ .permission = ll_inode_permission,
.setxattr = ll_setxattr,
.getxattr = ll_getxattr,
.listxattr = ll_listxattr,
#else
.revalidate_it = ll_inode_revalidate_it,
#endif
+ .permission = ll_inode_permission,
.setxattr = ll_setxattr,
.getxattr = ll_getxattr,
.listxattr = ll_listxattr,
#else
.getattr_it = ll_getattr,
#endif
+ .permission = ll_inode_permission,
.setxattr = ll_setxattr,
.getxattr = ll_getxattr,
.listxattr = ll_listxattr,
#define XATTR_USER_T (1)
#define XATTR_TRUSTED_T (2)
#define XATTR_SECURITY_T (3)
-#define XATTR_POSIXACL_T (4)
+#define XATTR_ACL_T (4)
#define XATTR_OTHER_T (5)
static
{
if (!strcmp(name, XATTR_NAME_ACL_ACCESS) ||
!strcmp(name, XATTR_NAME_ACL_DEFAULT))
- return XATTR_POSIXACL_T;
+ return XATTR_ACL_T;
if (!strncmp(name, XATTR_USER_PREFIX,
sizeof(XATTR_USER_PREFIX) - 1))
}
static
+int xattr_type_filter(struct ll_sb_info *sbi, int xattr_type)
+{
+ if (xattr_type == XATTR_ACL_T && !(sbi->ll_flags & LL_SBI_ACL))
+ return -EOPNOTSUPP;
+ 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;
+
+ return 0;
+}
+
+static
int ll_setxattr_common(struct inode *inode, const char *name,
const void *value, size_t size,
int flags, __u64 valid)
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);
+ rc = xattr_type_filter(sbi, xattr_type);
+ if (rc)
+ RETURN(rc);
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");
+ LCONSOLE_INFO("Disabling user_xattr feature because "
+ "it is not supported on the server\n");
sbi->ll_flags &= ~LL_SBI_USER_XATTR;
}
RETURN(rc);
}
int ll_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
+ const void *value, size_t size, int flags)
{
struct inode *inode = dentry->d_inode;
}
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);
+ rc = xattr_type_filter(sbi, xattr_type);
+ if (rc)
+ RETURN(rc);
do_getxattr:
ll_inode2fid(&fid, inode);
size, &req);
if (rc) {
if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
- CWARN("disable user_xattr from now on\n");
+ LCONSOLE_INFO("Disabling user_xattr feature because "
+ "it is not supported on the server\n");
sbi->ll_flags &= ~LL_SBI_USER_XATTR;
}
RETURN(rc);
RETURN(rc);
}
-int ll_getxattr(struct dentry *dentry, const char *name,
- void *buffer, size_t size)
+ssize_t ll_getxattr(struct dentry *dentry, const char *name,
+ void *buffer, size_t size)
{
struct inode *inode = dentry->d_inode;
return ll_getxattr_common(inode, name, buffer, size, OBD_MD_FLXATTR);
}
-int ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
+ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
{
struct inode *inode = dentry->d_inode;
ldlm_policy_data_t policy = { .l_inodebits = { MDS_INODELOCK_LOOKUP } };
int size[5] = {sizeof(struct ldlm_request), sizeof(struct ldlm_intent)};
int rc, flags = extra_lock_flags | LDLM_FL_HAS_INTENT;
- int repsize[4] = {sizeof(struct ldlm_reply),
- sizeof(struct mds_body),
- obddev->u.cli.cl_max_mds_easize,
- obddev->u.cli.cl_max_mds_cookiesize};
+ int repbufcnt = 3, repsize[4] = {sizeof(struct ldlm_reply),
+ sizeof(struct mds_body),
+ obddev->u.cli.cl_max_mds_easize};
struct ldlm_reply *dlm_rep;
struct ldlm_intent *lit;
struct ldlm_request *lockreq;
void *eadata;
unsigned long irqflags;
- int reply_buffers = 0;
ENTRY;
// LDLM_DEBUG_NOLOCK("mdsintent=%s,name=%s,dir=%lu",
/* pack the intended request */
mdc_open_pack(req, 2, data, it->it_create_mode, 0,
it->it_flags, lmm, lmmsize);
- /* get ready for the reply */
- reply_buffers = 3;
- req->rq_replen = lustre_msg_size(3, repsize);
+
+ repsize[repbufcnt++] = LUSTRE_POSIX_ACL_MAX_SIZE;
} else if (it->it_op & IT_UNLINK) {
size[2] = sizeof(struct mds_rec_unlink);
size[3] = data->namelen + 1;
/* pack the intended request */
mdc_unlink_pack(req, 2, data);
- /* get ready for the reply */
- reply_buffers = 4;
- req->rq_replen = lustre_msg_size(4, repsize);
+
+ repsize[repbufcnt++] = obddev->u.cli.cl_max_mds_cookiesize;
} else if (it->it_op & (IT_GETATTR | IT_LOOKUP)) {
- obd_valid valid = OBD_MD_FLGETATTR | OBD_MD_FLEASIZE;
+ obd_valid valid = OBD_MD_FLGETATTR | OBD_MD_FLEASIZE |
+ OBD_MD_FLACL;
size[2] = sizeof(struct mds_body);
size[3] = data->namelen + 1;
/* pack the intended request */
mdc_getattr_pack(req, valid, 2, it->it_flags, data);
- /* get ready for the reply */
- reply_buffers = 3;
- req->rq_replen = lustre_msg_size(3, repsize);
+
+ repsize[repbufcnt++] = LUSTRE_POSIX_ACL_MAX_SIZE;
} else if (it->it_op == IT_READDIR) {
policy.l_inodebits.bits = MDS_INODELOCK_UPDATE;
req = ptlrpc_prep_req(class_exp2cliimp(exp), LDLM_ENQUEUE, 1,
if (!req)
RETURN(-ENOMEM);
- /* get ready for the reply */
- reply_buffers = 1;
- req->rq_replen = lustre_msg_size(1, repsize);
- } else {
+ repbufcnt = 1;
+ } else {
LBUG();
RETURN(-EINVAL);
}
+ /* get ready for the reply */
+ req->rq_replen = lustre_msg_size(repbufcnt, repsize);
+
mdc_get_rpc_lock(obddev->u.cli.cl_rpc_lock, it);
rc = ldlm_cli_enqueue(exp, req, obddev->obd_namespace, res_id,
lock_type,&policy,lock_mode, &flags,cb_blocking,
it->it_op,it->d.lustre.it_disposition,it->d.lustre.it_status);
/* We know what to expect, so we do any byte flipping required here */
- LASSERT(reply_buffers == 4 || reply_buffers == 3 || reply_buffers == 1);
- if (reply_buffers >= 3) {
+ LASSERT(repbufcnt == 4 || repbufcnt == 1);
+ if (repbufcnt == 4) {
struct mds_body *body;
body = lustre_swab_repbuf(req, 1, sizeof (*body),
0);
}
+static
int mdc_getattr_common(struct obd_export *exp, unsigned int ea_size,
- struct ptlrpc_request *req)
+ unsigned int acl_size, struct ptlrpc_request *req)
{
struct mds_body *body;
void *eadata;
int rc;
- int size[2] = {sizeof(*body), 0};
+ int size[3] = {sizeof(*body)};
int bufcount = 1;
ENTRY;
CDEBUG(D_INODE, "reserved %u bytes for MD/symlink in packet\n",
ea_size);
}
+ if (acl_size) {
+ size[bufcount++] = acl_size;
+ CDEBUG(D_INODE, "reserved %u bytes for ACL\n", acl_size);
+ }
+
req->rq_replen = lustre_msg_size(bufcount, size);
mdc_get_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
struct ptlrpc_request *req;
struct mds_body *body;
int size = sizeof(*body);
- int rc;
+ int acl_size = 0, rc;
ENTRY;
/* XXX do we need to make another request here? We just did a getattr
body->eadatasize = ea_size;
mdc_pack_req_body(req);
- rc = mdc_getattr_common(exp, ea_size, req);
+ /* currently only root inode will call us with FLACL */
+ if (valid & OBD_MD_FLACL)
+ acl_size = LUSTRE_POSIX_ACL_MAX_SIZE;
+
+ rc = mdc_getattr_common(exp, ea_size, acl_size, req);
if (rc != 0) {
ptlrpc_req_finished (req);
req = NULL;
LASSERT (strnlen (filename, namelen) == namelen - 1);
memcpy(lustre_msg_buf(req->rq_reqmsg, 1, namelen), filename, namelen);
- rc = mdc_getattr_common(exp, ea_size, req);
+ rc = mdc_getattr_common(exp, ea_size, 0, req);
if (rc != 0) {
ptlrpc_req_finished (req);
req = NULL;
rec->cr_replayfid.generation, rec->cr_replayfid.id);
}
+static
+int mdc_unpack_acl(struct obd_export *exp, struct ptlrpc_request *req,
+ struct lustre_md *md, unsigned int offset)
+{
+ struct mds_body *body = md->body;
+ struct posix_acl *acl;
+ void *buf;
+ int rc;
+
+ if (!body->aclsize)
+ return 0;
+
+ buf = lustre_msg_buf(req->rq_repmsg, offset, body->aclsize);
+ if (!buf) {
+ CERROR("aclsize %u, bufcount %u, bufsize %u\n",
+ body->aclsize, req->rq_repmsg->bufcount,
+ (req->rq_repmsg->bufcount <= offset) ? -1 :
+ req->rq_repmsg->buflens[offset]);
+ return -EPROTO;
+ }
+
+ acl = posix_acl_from_xattr(buf, body->aclsize);
+ if (IS_ERR(acl)) {
+ rc = PTR_ERR(acl);
+ CERROR("convert xattr to acl: %d\n", rc);
+ return rc;
+ }
+
+ rc = posix_acl_valid(acl);
+ if (rc) {
+ CERROR("validate acl: %d\n", rc);
+ posix_acl_release(acl);
+ return rc;
+ }
+
+ md->posix_acl = acl;
+ return 0;
+}
+
int mdc_req2lustre_md(struct ptlrpc_request *req, int offset,
struct obd_export *exp,
struct lustre_md *md)
md->body = lustre_msg_buf(req->rq_repmsg, offset, sizeof (*md->body));
LASSERT (md->body != NULL);
LASSERT_REPSWABBED (req, offset);
+ offset++;
if (md->body->valid & OBD_MD_FLEASIZE) {
int lmmsize;
RETURN(-EPROTO);
}
lmmsize = md->body->eadatasize;
- lmm = lustre_msg_buf(req->rq_repmsg, offset + 1, lmmsize);
+ lmm = lustre_msg_buf(req->rq_repmsg, offset, lmmsize);
LASSERT (lmm != NULL);
- LASSERT_REPSWABBED (req, offset + 1);
+ LASSERT_REPSWABBED (req, offset);
rc = obd_unpackmd(exp, &md->lsm, lmm, lmmsize);
- if (rc >= 0) {
- LASSERT (rc >= sizeof (*md->lsm));
- rc = 0;
- }
+ if (rc < 0)
+ RETURN(rc);
+
+ LASSERT (rc >= sizeof (*md->lsm));
+ rc = 0;
+
+ offset++;
}
+
+ /* for ACL, it's possible that FLACL is set but aclsize is zero.
+ * only when aclsize != 0 there's an actual segment for ACL in
+ * reply buffer.
+ */
+ if ((md->body->valid & OBD_MD_FLACL) && md->body->aclsize) {
+ rc = mdc_unpack_acl(exp, req, md, offset);
+ if (rc)
+ GOTO(err_out, rc);
+ offset++;
+ }
+out:
RETURN(rc);
+
+err_out:
+ if (md->lsm)
+ obd_free_memmd(exp, &md->lsm);
+ goto out;
+}
+
+void mdc_free_lustre_md(struct obd_export *exp, struct lustre_md *md)
+{
+ if (md->lsm)
+ obd_free_memmd(exp, &md->lsm);
+
+ if (md->posix_acl) {
+ posix_acl_release(md->posix_acl);
+ md->posix_acl = NULL;
+ }
}
static void mdc_commit_open(struct ptlrpc_request *req)
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(mdc_req2lustre_md);
+EXPORT_SYMBOL(mdc_free_lustre_md);
EXPORT_SYMBOL(mdc_change_cbdata);
EXPORT_SYMBOL(mdc_getstatus);
EXPORT_SYMBOL(mdc_getattr);
{
struct obd_export *exp;
struct mds_export_data *med;
- struct mds_client_data *mcd;
+ struct mds_client_data *mcd = NULL;
int rc, abort_recovery;
ENTRY;
if (data != NULL) {
data->ocd_connect_flags &= MDS_CONNECT_SUPPORTED;
+
+ if (!obd->u.mds.mds_fl_user_xattr)
+ data->ocd_connect_flags &= ~OBD_CONNECT_USER_XATTR;
+
exp->exp_connect_flags = data->ocd_connect_flags;
}
+ if ((obd->u.mds.mds_fl_acl == 0) !=
+ ((exp->exp_connect_flags & OBD_CONNECT_ACL) == 0)) {
+ CWARN("%s require ACL support but %s doesn't\n",
+ obd->u.mds.mds_fl_acl ? "MDS" : "client",
+ obd->u.mds.mds_fl_acl ? "client" : "MDS");
+ GOTO(out, rc = -EBADE);
+ }
+
OBD_ALLOC(mcd, sizeof(*mcd));
if (!mcd) {
CERROR("mds: out of memory for client data\n");
RETURN(rc);
}
+static
+int mds_pack_posix_acl(struct inode *inode, struct lustre_msg *repmsg,
+ struct mds_body *repbody, int repoff)
+{
+ struct dentry de = { .d_inode = inode };
+ int buflen, rc;
+ ENTRY;
+
+ LASSERT(repbody->aclsize == 0);
+ LASSERT(repmsg->bufcount > repoff);
+
+ buflen = lustre_msg_buflen(repmsg, repoff);
+ if (!buflen)
+ GOTO(out, 0);
+
+ if (!inode->i_op || !inode->i_op->getxattr)
+ GOTO(out, 0);
+
+ lock_24kernel();
+ rc = inode->i_op->getxattr(&de, XATTR_NAME_ACL_ACCESS,
+ lustre_msg_buf(repmsg, repoff, buflen),
+ buflen);
+ unlock_24kernel();
+
+ if (rc >= 0)
+ repbody->aclsize = rc;
+ else if (rc != -ENODATA) {
+ CERROR("buflen %d, get acl: %d\n", buflen, rc);
+ RETURN(rc);
+ }
+ EXIT;
+out:
+ repbody->valid |= OBD_MD_FLACL;
+ return 0;
+}
+
+int mds_pack_acl(struct mds_export_data *med, struct inode *inode,
+ struct lustre_msg *repmsg, struct mds_body *repbody,
+ int repoff)
+{
+ return mds_pack_posix_acl(inode, repmsg, repbody, repoff);
+}
+
static int mds_getattr_internal(struct obd_device *obd, struct dentry *dentry,
struct ptlrpc_request *req,
struct mds_body *reqbody, int reply_off)
mds_pack_inode2fid(&body->fid1, inode);
mds_pack_inode2body(body, inode);
+ reply_off++;
if ((S_ISREG(inode->i_mode) && (reqbody->valid & OBD_MD_FLEASIZE)) ||
(S_ISDIR(inode->i_mode) && (reqbody->valid & OBD_MD_FLDIREA))) {
- rc = mds_pack_md(obd, req->rq_repmsg, reply_off + 1, body,
+ rc = mds_pack_md(obd, req->rq_repmsg, reply_off, body,
inode, 1);
/* If we have LOV EA data, the OST holds size, atime, mtime */
!(body->valid & OBD_MD_FLDIREA))
body->valid |= (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS |
OBD_MD_FLATIME | OBD_MD_FLMTIME);
+
+ lustre_shrink_reply(req, reply_off, body->eadatasize, 0);
+ if (body->eadatasize)
+ reply_off++;
} else if (S_ISLNK(inode->i_mode) &&
(reqbody->valid & OBD_MD_LINKNAME) != 0) {
- char *symname = lustre_msg_buf(req->rq_repmsg, reply_off + 1,0);
+ char *symname = lustre_msg_buf(req->rq_repmsg, reply_off, 0);
int len;
LASSERT (symname != NULL); /* caller prepped reply */
- len = req->rq_repmsg->buflens[reply_off + 1];
+ len = req->rq_repmsg->buflens[reply_off];
rc = inode->i_op->readlink(dentry, symname, len);
if (rc < 0) {
symname[rc] = 0; /* NULL terminate */
rc = 0;
}
+ reply_off++;
+ }
+
+ if (rc)
+ RETURN(rc);
+
+ if ((req->rq_export->exp_connect_flags & OBD_CONNECT_ACL) &&
+ (reqbody->valid & OBD_MD_FLACL)) {
+ rc = mds_pack_acl(&req->rq_export->exp_mds_data,
+ inode, req->rq_repmsg,
+ body, reply_off);
+
+ lustre_shrink_reply(req, reply_off, body->aclsize, 0);
+ if (body->aclsize)
+ reply_off++;
}
RETURN(rc);
{
struct mds_obd *mds = mds_req2mds(req);
struct mds_body *body;
- int rc = 0, size[2] = {sizeof(*body)}, bufcount = 1;
+ int rc, size[2] = {sizeof(*body)}, bufcount = 1;
ENTRY;
body = lustre_msg_buf(req->rq_reqmsg, offset, sizeof (*body));
if ((S_ISREG(inode->i_mode) && (body->valid & OBD_MD_FLEASIZE)) ||
(S_ISDIR(inode->i_mode) && (body->valid & OBD_MD_FLDIREA))) {
- int ret;
down(&inode->i_sem);
- ret = fsfilt_get_md(req->rq_export->exp_obd, inode, NULL, 0);
+ rc = fsfilt_get_md(req->rq_export->exp_obd, inode, NULL, 0);
up(&inode->i_sem);
CDEBUG(D_INODE, "got %d bytes MD data for inode %lu\n",
rc, inode->i_ino);
- if (ret < 0) {
- if (ret != -ENODATA) {
+ if (rc < 0) {
+ if (rc != -ENODATA) {
CERROR("error getting inode %lu MD: rc = %d\n",
- inode->i_ino, ret);
- /* should we return ret in req->rq_status? */
+ inode->i_ino, rc);
+ RETURN(rc);
}
size[bufcount] = 0;
- } else if (ret > mds->mds_max_mdsize) {
+ } else if (rc > mds->mds_max_mdsize) {
size[bufcount] = 0;
CERROR("MD size %d larger than maximum possible %u\n",
- ret, mds->mds_max_mdsize);
+ rc, mds->mds_max_mdsize);
} else {
- size[bufcount] = ret;
+ size[bufcount] = rc;
}
bufcount++;
} else if (S_ISLNK(inode->i_mode) && (body->valid & OBD_MD_LINKNAME)) {
inode->i_size + 1, body->eadatasize);
}
+ if ((req->rq_export->exp_connect_flags & OBD_CONNECT_ACL) &&
+ (body->valid & OBD_MD_FLACL)) {
+ struct dentry de = { .d_inode = inode };
+
+ size[bufcount] = 0;
+ if (inode->i_op && inode->i_op->getxattr) {
+ lock_24kernel();
+ rc = inode->i_op->getxattr(&de, XATTR_NAME_ACL_ACCESS,
+ NULL, 0);
+ unlock_24kernel();
+
+ if (rc < 0) {
+ if (rc != -ENODATA) {
+ CERROR("got acl size: %d\n", rc);
+ RETURN(rc);
+ }
+ } else
+ size[bufcount] = rc;
+ }
+ bufcount++;
+ }
+
if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETATTR_PACK)) {
CERROR("failed MDS_GETATTR_PACK test\n");
req->rq_status = -ENOMEM;
- GOTO(out, rc = -ENOMEM);
+ RETURN(-ENOMEM);
}
rc = lustre_pack_reply(req, bufcount, size, NULL);
if (rc) {
CERROR("lustre_pack_reply failed: rc %d\n", rc);
- GOTO(out, req->rq_status = rc);
+ req->rq_status = rc;
+ RETURN(rc);
}
- EXIT;
- out:
- return(rc);
+ RETURN(0);
}
static int mds_getattr_name(int offset, struct ptlrpc_request *req,
RETURN(rc);
}
+static
+void fsoptions_to_mds_flags(struct mds_obd *mds, const char *options)
+{
+ const char *p = options;
+
+ while (*options) {
+ while (*p && *p != ',')
+ p++;
+
+ if ((p - options == sizeof("user_xattr") - 1) &&
+ !memcmp(options, "user_xattr", sizeof("user_xattr") - 1))
+ mds->mds_fl_user_xattr = 1;
+ else if ((p - options == sizeof("acl") - 1) &&
+ !memcmp(options, "acl", sizeof("acl") - 1))
+ mds->mds_fl_acl = 1;
+
+ options = ++p;
+ }
+}
/* mount the file system (secretly). lustre_cfg parameters are:
* 1 = device
* should be moved to somewhere else like startup scripts or lconf. */
sprintf(options, "iopen_nopriv");
- if (LUSTRE_CFG_BUFLEN(lcfg, 4) > 0 && lustre_cfg_buf(lcfg, 4))
+ if (LUSTRE_CFG_BUFLEN(lcfg, 4) > 0 && lustre_cfg_buf(lcfg, 4)) {
sprintf(options + strlen(options), ",%s",
lustre_cfg_string(lcfg, 4));
+ fsoptions_to_mds_flags(mds, options);
+ }
mnt = do_kern_mount(lustre_cfg_string(lcfg, 2), 0,
lustre_cfg_string(lcfg, 1), (void *)options);
struct lustre_handle lockh = { 0 };
struct ldlm_lock *new_lock = NULL;
int getattr_part = MDS_INODELOCK_UPDATE;
- int rc, offset = 2, repsize[4] = {sizeof(struct ldlm_reply),
- sizeof(struct mds_body),
- mds->mds_max_mdsize,
- mds->mds_max_cookiesize};
+ int rc, offset = 2;
+ int repbufcnt = 3, repsize[4] = {sizeof(struct ldlm_reply),
+ sizeof(struct mds_body),
+ mds->mds_max_mdsize};
ENTRY;
LASSERT(req != NULL);
LDLM_DEBUG(lock, "intent policy, opc: %s", ldlm_it2str(it->opc));
- rc = lustre_pack_reply(req, it->opc == IT_UNLINK ? 4 : 3, repsize,
- NULL);
+ if ((req->rq_export->exp_connect_flags & OBD_CONNECT_ACL) &&
+ (it->opc & (IT_OPEN | IT_GETATTR | IT_LOOKUP)))
+ repsize[repbufcnt++] = LUSTRE_POSIX_ACL_MAX_SIZE;
+ else if (it->opc & IT_UNLINK)
+ repsize[repbufcnt++] = mds->mds_max_cookiesize;
+
+ rc = lustre_pack_reply(req, repbufcnt, repsize, NULL);
if (rc)
RETURN(req->rq_status = rc);
void mds_pack_inode2fid(struct ll_fid *fid, struct inode *inode);
void mds_pack_inode2body(struct mds_body *body, struct inode *inode);
#endif
+int mds_pack_acl(struct mds_export_data *med, struct inode *inode,
+ struct lustre_msg *repmsg, struct mds_body *repbody,
+ int repoff);
/* mds/mds_xattr.c */
int mds_setxattr(struct ptlrpc_request *req);
OBD_MD_FLATIME | OBD_MD_FLMTIME);
}
+ lustre_shrink_reply(req, 2, body->eadatasize, 0);
+
+ if (req->rq_export->exp_connect_flags & OBD_CONNECT_ACL) {
+ int acl_off = body->eadatasize ? 3 : 2;
+
+ rc = mds_pack_acl(med, dchild->d_inode, req->rq_repmsg,
+ body, acl_off);
+ lustre_shrink_reply(req, acl_off, body->aclsize, 0);
+ if (!req->rq_status && rc)
+ req->rq_status = rc;
+ }
+
/* If we have -EEXIST as the status, and we were asked to create
* exclusively, we can tell we failed because the file already existed.
*/
}
up(&dchild->d_inode->i_sem);
+ lustre_shrink_reply(req, 2, body->eadatasize, 0);
+
+ if (req->rq_export->exp_connect_flags & OBD_CONNECT_ACL) {
+ int acl_off = body->eadatasize ? 3 : 2;
+
+ rc = mds_pack_acl(&req->rq_export->exp_mds_data,
+ dchild->d_inode, req->rq_repmsg,
+ body, acl_off);
+ lustre_shrink_reply(req, acl_off, body->aclsize, 0);
+ if (rc)
+ RETURN(rc);
+ }
+
intent_set_disposition(rep, DISP_OPEN_OPEN);
mfd = mds_dentry_open(dchild, mds->mds_vfsmnt, flags, req);
if (IS_ERR(mfd))
return -EFAULT;
}
+ if (!(req->rq_export->exp_connect_flags &
+ OBD_CONNECT_USER_XATTR) &&
+ (strncmp(xattr_name, "user.", 5) == 0))
+ return -EOPNOTSUPP;
+
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) {
body->valid & OBD_MD_FLXATTR ? "set" : "remove",
xattr_name);
- if (!strncmp(xattr_name, "trusted.", 8)) {
+ if (strncmp(xattr_name, "trusted.", 8) == 0) {
if (!strcmp(xattr_name, "trusted."XATTR_LUSTRE_MDS_LOV_EA))
GOTO(out_dput, rc = -EACCES);
}
+ if (!(req->rq_export->exp_connect_flags & OBD_CONNECT_USER_XATTR) &&
+ (strncmp(xattr_name, "user.", 5) == 0)) {
+ GOTO(out_dput, rc = -EOPNOTSUPP);
+ }
+
/* filter_op simply use setattr one */
handle = fsfilt_start(obd, inode, FSFILT_OP_SETATTR, NULL);
if (IS_ERR(handle))
RETURN (0);
}
+/*
+ * shrink @segment to size @newlen. if @move_data is non-zero, we also move
+ * data forward from @segment + 1.
+ *
+ * if @newlen == 0, we remove the segment completely, but we still keep the
+ * totally bufcount the same to save possible data moving. this will leave a
+ * unused segment with size 0 at the tail, but that's ok.
+ *
+ * CAUTION:
+ * + if any buffers higher than @segment has been filled in, must call shrink
+ * with non-zero @move_data.
+ * + caller should NOT keep pointers to msg buffers which higher than @segment
+ * after call shrink.
+ */
+void lustre_shrink_reply(struct ptlrpc_request *req,
+ int segment, unsigned int newlen, int move_data)
+{
+ struct lustre_msg *msg = req->rq_repmsg;
+ char *tail = NULL, *newpos;
+ int tail_len = 0, n;
+
+ LASSERT(req->rq_reply_state);
+ LASSERT(msg);
+ LASSERT(msg->bufcount > segment);
+ LASSERT(msg->buflens[segment] >= newlen);
+
+ if (msg->buflens[segment] == newlen)
+ return;
+
+ if (move_data && msg->bufcount > segment + 1) {
+ tail = lustre_msg_buf(msg, segment + 1, 0);
+ for (n = segment + 1; n < msg->bufcount; n++)
+ tail_len += size_round(msg->buflens[n]);
+ }
+
+ msg->buflens[segment] = newlen;
+
+ if (tail && tail_len) {
+ newpos = lustre_msg_buf(msg, segment + 1, 0);
+ LASSERT(newpos <= tail);
+ if (newpos != tail)
+ memcpy(newpos, tail, tail_len);
+ }
+
+ if (newlen == 0 && msg->bufcount > segment + 1) {
+ memmove(&msg->buflens[segment], &msg->buflens[segment + 1],
+ (msg->bufcount - segment - 1) * sizeof(__u32));
+ msg->buflens[msg->bufcount - 1] = 0;
+ }
+
+ req->rq_replen = lustre_msg_size(msg->bufcount, msg->buflens);
+}
+
void lustre_free_reply_state (struct ptlrpc_reply_state *rs)
{
PTLRPC_RS_DEBUG_LRU_DEL(rs);
__swab32s (&b->generation);
__swab32s (&b->suppgid);
__swab32s (&b->eadatasize);
- __swab32s (&b->padding_1);
+ __swab32s (&b->aclsize);
__swab32s (&b->padding_2);
__swab32s (&b->padding_3);
__swab32s (&b->padding_4);
(long long)(int)offsetof(struct mds_body, eadatasize));
LASSERTF((int)sizeof(((struct mds_body *)0)->eadatasize) == 4, " found %lld\n",
(long long)(int)sizeof(((struct mds_body *)0)->eadatasize));
+ LASSERTF((int)offsetof(struct mds_body, aclsize) == 152, " found %lld\n",
+ (long long)(int)offsetof(struct mds_body, aclsize));
+ LASSERTF((int)sizeof(((struct mds_body *)0)->aclsize) == 4, " found %lld\n",
+ (long long)(int)sizeof(((struct mds_body *)0)->aclsize));
LASSERTF(FMODE_READ == 1, " found %lld\n",
(long long)FMODE_READ);
LASSERTF(FMODE_WRITE == 2, " found %lld\n",
EXPORT_SYMBOL(lustre_msg_swabbed);
EXPORT_SYMBOL(lustre_pack_request);
EXPORT_SYMBOL(lustre_pack_reply);
+EXPORT_SYMBOL(lustre_shrink_reply);
EXPORT_SYMBOL(lustre_free_reply_state);
EXPORT_SYMBOL(lustre_msg_size);
EXPORT_SYMBOL(lustre_unpack_msg);
TIMEOUT=${TIMEOUT:-20}
UPCALL=${UPCALL:-DEFAULT}
+MDSOPT=${MDSOPT:-"user_xattr,acl"}
+CLIENTOPT=${CLIENTOPT:-"user_xattr,acl"}
+MOUNTOPT=${MOUNTOPT:-"user_xattr,acl"}
+
STRIPE_BYTES=${STRIPE_BYTES:-1048576}
STRIPES_PER_OBJ=${STRIPES_PER_OBJ:-0}
[ -d $MOUNT ] || mkdir -p $MOUNT
$LCONF --nosetup --node client_facet $XMLCONFIG > /dev/null
- llmount -o nettype=$NETTYPE $mds_HOST://mds_svc/client_facet $MOUNT && exit 1
+ llmount -o nettype=$NETTYPE,$MOUNTOPT $mds_HOST://mds_svc/client_facet $MOUNT && exit 1
# cleanup client modules
$LCONF --cleanup --nosetup --node client_facet $XMLCONFIG > /dev/null
[ -d $MOUNT ] || mkdir -p $MOUNT
$LCONF --nosetup --node client_facet $XMLCONFIG > /dev/null
- llmount -o nettype=$NETTYPE $mds_HOST://wrong_mds_svc/client_facet $MOUNT && return 1
+ llmount -o nettype=$NETTYPE,$MOUNTOPT $mds_HOST://wrong_mds_svc/client_facet $MOUNT && return 1
# cleanup client modules
$LCONF --cleanup --nosetup --node client_facet $XMLCONFIG > /dev/null
[ -d $MOUNT ] || mkdir -p $MOUNT
$LCONF --nosetup --node client_facet $XMLCONFIG > /dev/null
- llmount -o nettype=$NETTYPE $mds_HOST://mds_svc/client_facet $MOUNT || return 1
+ llmount -o nettype=$NETTYPE,$MOUNTOPT $mds_HOST://mds_svc/client_facet $MOUNT || return 1
umount $MOUNT || return 2
# cleanup client modules
$conf_opt || exit 2
if [ "$MOUNT2" ]; then
- $LLMOUNT -v `hostname`:/mds1/client $MOUNT2 || exit 3
+ $LLMOUNT -v -o user_xattr,acl `hostname`:/mds1/client $MOUNT2 || exit 3
fi
[ $DEBUG ] && sysctl -w lnet.debug=$DEBUG
if [ "$MOUNT2" ]; then
- $LLMOUNT -v `hostname`:/mds1/client $MOUNT2 || exit 3
+ $LLMOUNT -v -o user_xattr,acl `hostname`:/mds1/client $MOUNT2 || exit 3
fi
OSTDEV=${OSTDEV:-$TMP/ost1-`hostname`}
OSTSIZE=${OSTSIZE:-400000}
-CLIENTOPT="user_xattr,${CLIENTOPT:-""}"
+MDS_MOUNT_OPTS="user_xattr,acl,${MDS_MOUNT_OPTS:-""}"
+CLIENTOPT="user_xattr,acl,${CLIENTOPT:-""}"
# specific journal size for the ost, in MB
JSIZE=${JSIZE:-0}
${LMC} --add net --node $HOSTNAME --nid `h2$NETTYPE $HOSTNAME` --nettype $NETTYPE || exit 11
${LMC} --add net --node client --nid '*' --nettype $NETTYPE || exit 12
+# configure mds server
[ "x$MDS_MOUNT_OPTS" != "x" ] &&
MDS_MOUNT_OPTS="--mountfsoptions $MDS_MOUNT_OPTS"
-# configure mds server
${LMC} --add mds --node $HOSTNAME --mds mds1 --fstype $FSTYPE \
- --dev $MDSDEV \
- $MDS_MOUNT_OPTS --size $MDSSIZE $JARG $IARG $MDSOPT || exit 20
+ --dev $MDSDEV $MDS_MOUNT_OPTS \
+ --size $MDSSIZE $JARG $IARG $MDSOPT || exit 20
[ "x$OST_MOUNT_OPTS" != "x" ] &&
OST_MOUNT_OPTS="--mountfsoptions $OST_MOUNT_OPTS"
STRIPE_BYTES=${STRIPE_BYTES:-1048576}
STRIPES_PER_OBJ=${STRIPES_PER_OBJ:-$((OSTCOUNT -1))}
-CLIENTOPT="user_xattr,${CLIENTOPT:-""}"
+MDS_MOUNT_OPTS="user_xattr,acl,${MDS_MOUNT_OPTS:-""}"
+CLIENTOPT="user_xattr,acl,${CLIENTOPT:-""}"
# specific journal size for the ost, in MB
JSIZE=${JSIZE:-0}
${LMC} --add net --node client --nid '*' --nettype $NETTYPE || exit 12
# configure mds server
+[ "x$MDS_MOUNT_OPTS" != "x" ] &&
+ MDS_MOUNT_OPTS="--mountfsoptions $MDS_MOUNT_OPTS"
+
${LMC} --format --add mds --node $HOSTNAME --mds mds1 --fstype $FSTYPE \
- --dev $MDSDEV --size $MDSSIZE $MDSOPT || exit 20
+ --dev $MDSDEV $MDS_MOUNT_OPTS --size $MDSSIZE $MDSOPT || exit 20
# configure ost
${LMC} --add lov --lov lov1 --mds mds1 --stripe_sz $STRIPE_BYTES \
}
run_test 102 "user xattr test ====================="
+run_acl_subtest()
+{
+ $SAVE_PWD/acl/run $SAVE_PWD/acl/$1.test
+ return $?
+}
+
+test_103 () {
+ SAVE_UMASK=`umask`
+ umask 0022
+ cd $DIR
+
+ [ "$UID" != 0 ] && echo "skipping $TESTNAME (must run as root)" && return
+ [ -z "`mount | grep " $DIR .*\<acl\>"`" ] && echo "skipping $TESTNAME (must have acl)" && return
+
+ echo "performing cp ..."
+ run_acl_subtest cp || error
+ echo "performing getfacl-noacl..."
+ run_acl_subtest getfacl-noacl || error
+ echo "performing misc..."
+ run_acl_subtest misc || error
+# XXX add back permission test when we support supplementary groups.
+# echo "performing permissions..."
+# run_acl_subtest permissions || error
+ echo "performing setfacl..."
+ run_acl_subtest setfacl || error
+
+ # inheritance test got from HP
+ echo "performing inheritance..."
+ cp $SAVE_PWD/acl/make-tree . || error
+ chmod +x make-tree || error
+ run_acl_subtest inheritance || error
+ rm -f make-tree
+
+ cd $SAVED_PWD
+ umask $SAVE_UMASK
+}
+run_test 103 "==============acl test ============="
+
TMPDIR=$OLDTMPDIR
TMP=$OLDTMP
HOME=$OLDHOME
}
zconf_mount() {
+ local OPTIONS
client=$1
mnt=$2
# Only supply -o to mount if we have options
if [ -n "$MOUNTOPT" ]; then
- MOUNTOPT="-o $MOUNTOPT"
+ OPTIONS="-o $MOUNTOPT"
fi
if [ -x /sbin/mount.lustre ] ; then
- do_node $client mount -t lustre $MOUNTOPT \
+ do_node $client mount -t lustre $OPTIONS \
`facet_nid mds`:/mds_svc/client_facet $mnt || return 1
else
# this is so cheating
do_node $client $LCONF --nosetup --node client_facet $XMLCONFIG > \
/dev/null || return 2
- do_node $client $LLMOUNT $MOUNTOPT \
+ do_node $client $LLMOUNT $OPTIONS \
`facet_nid mds`:/mds_svc/client_facet $mnt || return 4
fi
}
add_mds() {
- facet=$1
+ local MOUNT_OPTS
+ local facet=$1
shift
rm -f ${facet}active
add_facet $facet
+ [ "x$MDSOPT" != "x" ] && MOUNT_OPTS="--mountfsoptions $MDSOPT"
do_lmc --add mds --node ${facet}_facet --mds ${facet}_svc \
- --fstype $FSTYPE $* $MDSOPT
+ --fstype $FSTYPE $* $MOUNT_OPTS
}
add_mdsfailover() {
- facet=$1
+ local MOUNT_OPTS
+ local facet=$1
shift
add_facet ${facet}failover --lustre_upcall $UPCALL
+ [ "x$MDSOPT" != "x" ] && MOUNT_OPTS="--mountfsoptions $MDSOPT"
do_lmc --add mds --node ${facet}failover_facet --mds ${facet}_svc \
- --fstype $FSTYPE $* $MDSOPT
+ --fstype $FSTYPE $* $MOUNT_OPTS
}
add_ost() {
}
add_client() {
- facet=$1
+ local MOUNT_OPTS
+ local facet=$1
mds=$2
shift; shift
+ [ "x$CLIENTOPT" != "x" ] && MOUNT_OPTS="--clientoptions $CLIENTOPT"
add_facet $facet --lustre_upcall $UPCALL
- do_lmc --add mtpt --node ${facet}_facet --mds ${mds}_svc $* $CLIENTOPT
+ do_lmc --add mtpt --node ${facet}_facet --mds ${mds}_svc $* $MOUNT_OPTS
}
MOUNT=${MOUNT:-/mnt/lustre}
FSTYPE=${FSTYPE:-ext3}
-CLIENTOPT="user_xattr,${CLIENTOPT:-""}"
+MDS_MOUNT_OPTS="user_xattr,acl,${MDS_MOUNT_OPTS:-""}"
+CLIENTOPT="user_xattr,acl,${CLIENTOPT:-""}"
NETTYPE=${NETTYPE:-tcp}
NIDTYPE=${NIDTYPE:-$NETTYPE}
done
# configure mds server
+[ "x$MDS_MOUNT_OPTS" != "x" ] &&
+ MDS_MOUNT_OPTS="--mountfsoptions $MDS_MOUNT_OPTS"
+
echo; echo "adding MDS on: $MDSNODE"
${LMC} -m $config --add mds --node $MDSNODE --mds mds1 --fstype $FSTYPE \
- --dev $MDSDEV --size $MDSSIZE $MDSOPT || exit 10
+ --dev $MDSDEV $MDS_MOUNT_OPTS --size $MDSSIZE $MDSOPT || exit 10
# configure ost
${LMC} -m $config --add lov --lov lov1 --mds mds1 --stripe_sz $STRIPE_BYTES \
#else:
# mountfsoptions = "%s,extents,mballoc" % (mountfsoptions)
elif target == 'mds':
- mountfsoptions = "%s,user_xattr" % (mountfsoptions)
+ if config.user_xattr:
+ mountfsoptions = "%s,user_xattr" % (mountfsoptions)
+ if config.acl:
+ mountfsoptions = "%s,acl" % (mountfsoptions)
return mountfsoptions
return ""
mounting (currently OST-only). Can be repeated.""",
PARAMLIST),
('user_xattr', """Enable user_xattr support on MDS""", FLAG, 0),
+ ('acl', """Enable ACL support on MDS""", FLAG, 0),
]
def main():
"\t-o: filesystem mount options:\n"
"\t\tflock/noflock: enable/disable flock support\n"
"\t\tuser_xattr/nouser_xattr: enable/disable user extended attributes\n"
+ "\t\t{no}acl: enable/disable ACL support\n"
);
exit(out != stdout);
}
{ "noflock", 1, 1, 0, LMD_FLG_FLOCK}, /* Disable flock support */
{ "user_xattr", 0, 0, 0, LMD_FLG_USER_XATTR}, /* Enable get/set user xattr */
{ "nouser_xattr", 1, 1, 0, LMD_FLG_USER_XATTR}, /* Disable user xattr */
+ { "acl", 0, 0, 0, LMD_FLG_ACL}, /* Enable ACL support */
+ { "noacl", 1, 1, 0, LMD_FLG_ACL}, /* Disable ACL support */
/* please add new mount options to usage message */
{ NULL, 0, 0, 0, 0 }
};
CHECK_MEMBER(mds_body, generation);
CHECK_MEMBER(mds_body, suppgid);
CHECK_MEMBER(mds_body, eadatasize);
+ CHECK_MEMBER(mds_body, aclsize);
+ CHECK_MEMBER(mds_body, padding_2);
+ CHECK_MEMBER(mds_body, padding_3);
+ CHECK_MEMBER(mds_body, padding_4);
CHECK_VALUE(FMODE_READ);
CHECK_VALUE(FMODE_WRITE);
(long long)(int)offsetof(struct mds_body, eadatasize));
LASSERTF((int)sizeof(((struct mds_body *)0)->eadatasize) == 4, " found %lld\n",
(long long)(int)sizeof(((struct mds_body *)0)->eadatasize));
+ LASSERTF((int)offsetof(struct mds_body, aclsize) == 152, " found %lld\n",
+ (long long)(int)offsetof(struct mds_body, aclsize));
+ LASSERTF((int)sizeof(((struct mds_body *)0)->aclsize) == 4, " found %lld\n",
+ (long long)(int)sizeof(((struct mds_body *)0)->aclsize));
LASSERTF(FMODE_READ == 1, " found %lld\n",
(long long)FMODE_READ);
LASSERTF(FMODE_WRITE == 2, " found %lld\n",