From 761ab6a5cd758638df384d6bf9985cb063ef0fd8 Mon Sep 17 00:00:00 2001 From: ericm Date: Sun, 31 Jul 2005 04:49:34 +0000 Subject: [PATCH] land b_hd_remote_acl: support get/set ACL from remote client. --- lustre/cobd/cache_obd.c | 7 +- lustre/include/linux/lustre_acl.h | 6 + lustre/include/linux/lustre_mds.h | 31 +- lustre/include/linux/obd.h | 4 +- lustre/include/linux/obd_class.h | 2 + lustre/include/lustre/liblustreapi.h | 2 + lustre/include/lustre/lustre_user.h | 11 + lustre/kernel_patches/patches/export-2.6-fc3.patch | 12 + lustre/liblustre/super.c | 6 +- lustre/llite/dir.c | 155 +++++++++- lustre/llite/file.c | 22 +- lustre/llite/llite_internal.h | 10 +- lustre/llite/llite_lib.c | 5 +- lustre/llite/llite_nfs.c | 2 +- lustre/llite/symlink.c | 4 +- lustre/lmv/lmv_obd.c | 6 +- lustre/lmv/lmv_objmgr.c | 2 +- lustre/mdc/mdc_reint.c | 13 +- lustre/mdc/mdc_request.c | 21 +- lustre/mds/Makefile.in | 1 + lustre/mds/handler.c | 89 ++++-- lustre/mds/lproc_mds.c | 53 ++++ lustre/mds/mds_acl.c | 316 +++++++++++++++++++++ lustre/mds/mds_internal.h | 14 +- lustre/mds/mds_reint.c | 90 +++++- lustre/sec/upcall_cache.c | 1 - lustre/utils/Makefile.am | 7 +- lustre/utils/lacl_upcall.c | 309 ++++++++++++++++++++ lustre/utils/lconf | 8 + lustre/utils/lfs.c | 139 +++++++++ lustre/utils/liblustreapi.c | 65 +++++ 31 files changed, 1341 insertions(+), 72 deletions(-) create mode 100644 lustre/mds/mds_acl.c create mode 100644 lustre/utils/lacl_upcall.c diff --git a/lustre/cobd/cache_obd.c b/lustre/cobd/cache_obd.c index 409e6eb..d7007ba 100644 --- a/lustre/cobd/cache_obd.c +++ b/lustre/cobd/cache_obd.c @@ -967,7 +967,9 @@ static int cobd_md_getstatus(struct obd_export *exp, static int cobd_md_getattr(struct obd_export *exp, struct lustre_id *id, __u64 valid, const char *xattr_name, - unsigned int ea_size, struct ptlrpc_request **request) + const void *xattr_data, unsigned int xattr_datalen, + unsigned int ea_size, + struct ptlrpc_request **request) { struct obd_device *obd = class_exp2obd(exp); struct obd_export *cobd_exp; @@ -978,7 +980,8 @@ static int cobd_md_getattr(struct obd_export *exp, struct lustre_id *id, return -EINVAL; } cobd_exp = cobd_get_exp(obd); - return md_getattr(cobd_exp, id, valid, xattr_name, ea_size, request); + return md_getattr(cobd_exp, id, valid, xattr_name, + xattr_data, xattr_datalen, ea_size, request); } static int cobd_md_req2lustre_md(struct obd_export *mdc_exp, diff --git a/lustre/include/linux/lustre_acl.h b/lustre/include/linux/lustre_acl.h index 2267997..26e0d87 100644 --- a/lustre/include/linux/lustre_acl.h +++ b/lustre/include/linux/lustre_acl.h @@ -23,7 +23,9 @@ #ifndef _LUSTRE_ACL_H_ #define _LUSTRE_ACL_H_ +#ifdef __KERNEL__ #include +#endif /* * the value of LL_ACL_MAX_ENTRIES and LL_ACL_NOT_CACHED should be @@ -33,4 +35,8 @@ #define LL_ACL_MAX_ENTRIES 32 // EXT3_ACL_MAX_ENTRIES #define LL_ACL_NOT_CACHED ((void *)-1) //EXT3_ACL_NOT_CACHED +/* remote acl */ +#define XATTR_NAME_LUSTRE_ACL "system.lustre_acl" +#define LUSTRE_ACL_SIZE_MAX (4096) + #endif diff --git a/lustre/include/linux/lustre_mds.h b/lustre/include/linux/lustre_mds.h index 40acf00..dcbda8a 100644 --- a/lustre/include/linux/lustre_mds.h +++ b/lustre/include/linux/lustre_mds.h @@ -241,6 +241,32 @@ struct lsd_downcall_args { struct lsd_permission *perms; }; +/* remote acl upcall */ +struct rmtacl_upcall_desc { + int status; /* helper execution status */ + int upcall_status; /* error in upcall itself */ + int get; /* is getfacl */ + char *cmd; /* cmdline (up) */ + __u32 cmdlen; /* cmdline length (up) */ + char *res; /* output (down) */ + __u32 reslen; /* output length (down) */ + /* upcall internal use */ + uid_t uid; + char *root; +}; + +struct rmtacl_upcall_entry { + struct upcall_cache_entry base; + struct rmtacl_upcall_desc *desc; +}; + +struct rmtacl_downcall_args { + __u64 key; + char *res; /* output text */ + __u32 reslen; /* output text length */ + int status; /* helper exit code */ +}; + /* mds/mds_reint.c */ int mds_reint_rec(struct mds_update_record *r, int offset, struct ptlrpc_request *req, struct lustre_handle *); @@ -301,8 +327,9 @@ int mdc_req2lustre_md(struct obd_export *exp_lmv, struct ptlrpc_request *req, struct lustre_md *md); int mdc_getstatus(struct obd_export *exp, struct lustre_id *rootid); int mdc_getattr(struct obd_export *exp, struct lustre_id *id, - __u64 valid, const char *xattr_name, unsigned int ea_size, - struct ptlrpc_request **request); + __u64 valid, const char *xattr_name, + const void *xattr_data, unsigned int xattr_datalen, + unsigned int ea_size, struct ptlrpc_request **request); int mdc_getattr_lock(struct obd_export *exp, struct lustre_id *id, char *filename, int namelen, __u64 valid, unsigned int ea_size, struct ptlrpc_request **request); diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h index 292ce23..7a64c7a 100644 --- a/lustre/include/linux/obd.h +++ b/lustre/include/linux/obd.h @@ -901,8 +901,8 @@ struct md_ops { void *, int, ldlm_completion_callback, ldlm_blocking_callback, void *); int (*m_getattr)(struct obd_export *, struct lustre_id *, - __u64, const char *, unsigned int, - struct ptlrpc_request **); + __u64, const char *, const void *, unsigned int, + unsigned int, struct ptlrpc_request **); int (*m_access_check)(struct obd_export *, struct lustre_id *, struct ptlrpc_request **); int (*m_getattr_lock)(struct obd_export *, struct lustre_id *, diff --git a/lustre/include/linux/obd_class.h b/lustre/include/linux/obd_class.h index 04ba76f..592eac5 100644 --- a/lustre/include/linux/obd_class.h +++ b/lustre/include/linux/obd_class.h @@ -1180,6 +1180,7 @@ static inline int md_delete_inode(struct obd_export *exp, static inline int md_getattr(struct obd_export *exp, struct lustre_id *id, __u64 valid, const char *xattr_name, + const void *xattr_data, unsigned int xattr_datalen, unsigned int ea_size, struct ptlrpc_request **request) { @@ -1188,6 +1189,7 @@ static inline int md_getattr(struct obd_export *exp, struct lustre_id *id, EXP_CHECK_MD_OP(exp, getattr); MD_COUNTER_INCREMENT(exp->exp_obd, getattr); rc = MDP(exp->exp_obd, getattr)(exp, id, valid, xattr_name, + xattr_data, xattr_datalen, ea_size, request); RETURN(rc); } diff --git a/lustre/include/lustre/liblustreapi.h b/lustre/include/lustre/liblustreapi.h index d639751..78bb204 100644 --- a/lustre/include/lustre/liblustreapi.h +++ b/lustre/include/lustre/liblustreapi.h @@ -38,5 +38,7 @@ extern int llapi_target_check(int num_types, char **obd_types, char *dir); extern int llapi_catinfo(char *dir, char *keyword, char *node_name); extern int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count); extern int llapi_is_lustre_mnttype(char *type); +extern int llapi_getfacl(char *dir, char *cmd); +extern int llapi_setfacl(char *dir, char *cmd); #endif diff --git a/lustre/include/lustre/lustre_user.h b/lustre/include/lustre/lustre_user.h index 0a9fb94..65a18d4 100644 --- a/lustre/include/lustre/lustre_user.h +++ b/lustre/include/lustre/lustre_user.h @@ -63,6 +63,8 @@ #define LL_IOC_MDC_MKDIRSTRIPE _IOW ('f', 160, long) #define LL_IOC_GROUP_LOCK _IOW ('f', 161, long) #define LL_IOC_GROUP_UNLOCK _IOW ('f', 162, long) +#define LL_IOC_GETFACL _IOW ('f', 163, long) +#define LL_IOC_SETFACL _IOW ('f', 164, long) #define LL_IOC_FLUSH_CRED _IOW ('f', 170, long) @@ -137,4 +139,13 @@ static inline void obd_str2uuid(struct obd_uuid *uuid, char *tmp) uuid->uuid[sizeof(*uuid) - 1] = '\0'; } +/* remote acl ioctl */ +struct ll_acl_ioctl_data { + char *cmd; /* IN */ + unsigned long cmd_len; + char *res; /* OUT */ + unsigned long res_len; + int status; /* OUT */ +}; + #endif /* _LUSTRE_USER_H */ diff --git a/lustre/kernel_patches/patches/export-2.6-fc3.patch b/lustre/kernel_patches/patches/export-2.6-fc3.patch index d969e7d..3e67af1 100644 --- a/lustre/kernel_patches/patches/export-2.6-fc3.patch +++ b/lustre/kernel_patches/patches/export-2.6-fc3.patch @@ -189,3 +189,15 @@ Index: linux-2.6.10/include/linux/mm.h /* filemap.c */ extern unsigned long page_unuse(struct page *); extern void truncate_inode_pages(struct address_space *, loff_t); +Index: linux-2.6.10/fs/namespace.c +=================================================================== +--- linux-2.6.10/fs/namespace.c.symbol 2005-07-28 13:16:56.000000000 -0600 ++++ linux-2.6.10/fs/namespace.c 2005-07-28 13:17:24.000000000 -0600 +@@ -38,6 +38,7 @@ static inline int sysfs_init(void) + + /* spinlock for vfsmount related operations, inplace of dcache_lock */ + spinlock_t vfsmount_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; ++EXPORT_SYMBOL(vfsmount_lock); + + static struct list_head *mount_hashtable; + static int hash_mask, hash_bits; diff --git a/lustre/liblustre/super.c b/lustre/liblustre/super.c index dec96c3..111f038 100644 --- a/lustre/liblustre/super.c +++ b/lustre/liblustre/super.c @@ -447,7 +447,7 @@ static int llu_inode_revalidate(struct inode *inode) } ll_inode2id(&id, inode); rc = mdc_getattr(sbi->ll_md_exp, &id, valid, NULL, 0, - ealen, &req); + NULL, ealen, &req); if (rc) { CERROR("failure %d inode %lu\n", rc, lli->lli_st_ino); RETURN(-abs(rc)); @@ -878,7 +878,7 @@ static int llu_readlink_internal(struct inode *inode, ll_inode2id(&id, inode); rc = mdc_getattr(sbi->ll_md_exp, &id, - OBD_MD_LINKNAME, NULL, 0, symlen, request); + OBD_MD_LINKNAME, NULL, 0, NULL, symlen, request); if (rc) { CERROR("inode %lu: rc = %d\n", lli->lli_st_ino, rc); RETURN(rc); @@ -1533,7 +1533,7 @@ llu_fsswop_mount(const char *source, /* fetch attr of root inode */ err = mdc_getattr(sbi->ll_md_exp, &rootid, OBD_MD_FLNOTOBD|OBD_MD_FLBLOCKS, NULL, 0, - 0, &request); + NULL, 0, &request); if (err) { CERROR("mdc_getattr failed for root: rc = %d\n", err); GOTO(out_lov, err); diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index f3d5e23..55e6e79 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -51,6 +51,7 @@ #include #include #include +#include #include "llite_internal.h" typedef struct ext2_dir_entry_2 ext2_dirent; @@ -435,6 +436,126 @@ out: return err; } +/* + * we don't call getxattr_internal/setxattr_internal because we + * need more precisely control. + */ +static int ll_ioctl_getfacl(struct inode *inode, + struct file *file, + struct ll_acl_ioctl_data *ioc) +{ + struct ptlrpc_request *req = NULL; + struct mds_body *body; + char *cmd, *res; + struct lustre_id id; + int rc; + ENTRY; + + if (!ioc->cmd || !ioc->cmd_len || + !ioc->res || !ioc->res_len) { + CERROR("error: cmd %p, len %lu, res %p, len %lu\n", + ioc->cmd, ioc->cmd_len, ioc->res, ioc->res_len); + RETURN(-EINVAL); + } + + OBD_ALLOC(cmd, ioc->cmd_len); + if (!cmd) + RETURN(-ENOMEM); + if (copy_from_user(cmd, ioc->cmd, ioc->cmd_len)) + GOTO(out, rc = -EFAULT); + + /* we didn't call ll_getxattr_internal() because we'd like to + * copy from reply buffer to user space directly. + */ + ll_inode2id(&id, inode); + rc = md_getattr(ll_i2sbi(inode)->ll_md_exp, &id, OBD_MD_FLXATTR, + XATTR_NAME_LUSTRE_ACL, + cmd, ioc->cmd_len, ioc->res_len, &req); + if (rc < 0) { + CERROR("rc: %d\n", rc); + GOTO(out, rc); + } + + res = lustre_msg_buf(req->rq_repmsg, 1, ioc->res_len); + LASSERT(res); + if (copy_to_user(ioc->res, res, ioc->res_len)) + rc = -EFAULT; + + body = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*body)); + LASSERT(body); + ioc->status = (__s32) body->flags; + + EXIT; +out: + if (req) + ptlrpc_req_finished(req); + OBD_FREE(cmd, ioc->cmd_len); + + return rc; +} + +static int ll_ioctl_setfacl(struct inode *inode, + struct file *file, + struct ll_acl_ioctl_data *ioc) +{ + struct ptlrpc_request *req = NULL; + struct mdc_op_data op_data; + struct mds_body *body; + struct iattr attr; + char *cmd; + int replen, rc; + ENTRY; + + if (!ioc->cmd || !ioc->cmd_len) { + CERROR("error: cmd %p, len %lu\n", ioc->cmd, ioc->cmd_len); + RETURN(-EINVAL); + } + + OBD_ALLOC(cmd, ioc->cmd_len); + if (!cmd) + RETURN(-ENOMEM); + if (copy_from_user(cmd, ioc->cmd, ioc->cmd_len)) + GOTO(out, rc = -EFAULT); + + memset(&attr, 0x0, sizeof(attr)); + attr.ia_valid |= ATTR_EA; + attr.ia_attr_flags = 0; + + ll_prepare_mdc_data(&op_data, inode, NULL, NULL, 0, 0); + + rc = md_setattr(ll_i2sbi(inode)->ll_md_exp, &op_data, &attr, + (void*) XATTR_NAME_LUSTRE_ACL, + sizeof(XATTR_NAME_LUSTRE_ACL), + (void*) cmd, ioc->cmd_len, &req); + if (rc) { + CERROR("md_setattr fails: rc = %d\n", rc); + GOTO(out, rc); + } + + body = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*body)); + LASSERT(body); + ioc->status = (__s32) body->flags; + + LASSERT(req->rq_repmsg->bufcount == 2); + replen = req->rq_repmsg->buflens[1]; + LASSERT(replen <= LUSTRE_ACL_SIZE_MAX); + if (replen) { + if (replen > ioc->res_len) + replen = ioc->res_len; + if (copy_to_user(ioc->res, + lustre_msg_buf(req->rq_repmsg, 1, replen), + replen)) + rc = -EFAULT; + } + EXIT; +out: + if (req) + ptlrpc_req_finished(req); + OBD_FREE(cmd, ioc->cmd_len); + + return rc; +} + static int ll_dir_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -538,7 +659,7 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file, valid |= OBD_MD_FLDIREA; ll_inode2id(&id, inode); - rc = md_getattr(sbi->ll_md_exp, &id, valid, NULL, + rc = md_getattr(sbi->ll_md_exp, &id, valid, NULL, NULL, 0, obd_size_diskmd(sbi->ll_dt_exp, NULL), &request); if (rc < 0) { @@ -728,6 +849,38 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file, obd_ioctl_freedata(buf, len); RETURN(rc); } + case LL_IOC_GETFACL: { + struct ll_acl_ioctl_data ioc, *uioc; + int rc; + + if (copy_from_user(&ioc, (void *) arg, sizeof(ioc))) + RETURN(-EFAULT); + + rc = ll_ioctl_getfacl(inode, file, &ioc); + if (!rc) { + uioc = (struct ll_acl_ioctl_data *) arg; + if (copy_to_user(&uioc->status, &ioc.status, + sizeof(ioc.status))) + rc = -EFAULT; + } + RETURN(rc); + } + case LL_IOC_SETFACL: { + struct ll_acl_ioctl_data ioc, *uioc; + int rc; + + if (copy_from_user(&ioc, (void *) arg, sizeof(ioc))) + RETURN(-EFAULT); + + rc = ll_ioctl_setfacl(inode, file, &ioc); + if (!rc) { + uioc = (struct ll_acl_ioctl_data *) arg; + if (copy_to_user(&uioc->status, &ioc.status, + sizeof(ioc.status))) + rc = -EFAULT; + } + RETURN(rc); + } case LL_IOC_FLUSH_CRED: RETURN(ll_flush_cred(inode)); default: diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 3e5a830..c534173 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -1807,6 +1807,9 @@ int ll_setxattr_internal(struct inode *inode, const char *name, CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu\n", inode->i_ino); lprocfs_counter_incr(ll_i2sbi(inode)->ll_stats, LPROC_LL_SETXATTR); + if (sbi->ll_remote && !strcmp(name, XATTR_NAME_ACL_ACCESS)) + RETURN(-EOPNOTSUPP); + memset(&attr, 0x0, sizeof(attr)); attr.ia_valid |= valid; attr.ia_attr_flags = flags; @@ -1814,12 +1817,10 @@ int ll_setxattr_internal(struct inode *inode, const char *name, ll_prepare_mdc_data(&op_data, inode, NULL, NULL, 0, 0); rc = md_setattr(sbi->ll_md_exp, &op_data, &attr, - (void*) name, strnlen(name, XATTR_NAME_MAX)+1, + (void*) name, strnlen(name, XATTR_NAME_MAX) + 1, (void*) value, size, &request); - if (rc) { - CERROR("md_setattr fails: rc = %d\n", rc); + if (rc) GOTO(out, rc); - } out: ptlrpc_req_finished(request); @@ -1836,7 +1837,7 @@ int ll_setxattr(struct dentry *dentry, const char *name, const void *value, rc = ll_setxattr_internal(dentry->d_inode, name, value, size, flags, ATTR_EA); - + /* update inode's acl info */ if (rc == 0 && strcmp(name, XATTR_NAME_ACL_ACCESS) == 0) { if (value) { @@ -1889,12 +1890,15 @@ int ll_getxattr_internal(struct inode *inode, const char *name, lprocfs_counter_incr(ll_i2sbi(inode)->ll_stats, LPROC_LL_GETXATTR); + if (sbi->ll_remote && !strcmp(name, XATTR_NAME_ACL_ACCESS)) + RETURN(-EOPNOTSUPP); + ll_inode2id(&id, inode); - rc = md_getattr(sbi->ll_md_exp, &id, valid, name, + rc = md_getattr(sbi->ll_md_exp, &id, valid, name, NULL, 0, size, &request); if (rc) { if (rc != -ENODATA && rc != -EOPNOTSUPP) - CERROR("md_getattr fails: rc = %d\n", rc); + CERROR("rc = %d\n", rc); GOTO(out, rc); } @@ -1903,11 +1907,10 @@ int ll_getxattr_internal(struct inode *inode, const char *name, LASSERT_REPSWABBED(request, 0); ea_size = body->eadatasize; - LASSERT(ea_size <= request->rq_repmsg->buflens[0]); - if (size == 0) GOTO(out, rc = ea_size); + LASSERT(ea_size <= request->rq_repmsg->buflens[1]); ea_data = lustre_msg_buf(request->rq_repmsg, 1, ea_size); LASSERT(ea_data != NULL); LASSERT_REPSWABBED(request, 1); @@ -1915,6 +1918,7 @@ int ll_getxattr_internal(struct inode *inode, const char *name, if (value) memcpy(value, ea_data, ea_size); rc = ea_size; + out: ptlrpc_req_finished(request); RETURN(rc); diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 363df56..1fa8429 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -269,11 +269,11 @@ extern struct inode_operations ll_file_inode_operations; int ll_md_real_close(struct obd_export *md_exp, struct inode *inode, int flags); extern int ll_inode_revalidate_it(struct dentry *); -extern int ll_setxattr(struct dentry *, const char *, const void *, - size_t, int); -extern int ll_getxattr(struct dentry *, const char *, void *, size_t); -extern int ll_listxattr(struct dentry *, char *, size_t); -extern int ll_removexattr(struct dentry *, const char *); +int ll_setxattr(struct dentry *, const char *, const void *, + size_t, int); +int ll_getxattr(struct dentry *, const char *, void *, size_t); +int ll_listxattr(struct dentry *, char *, size_t); +int ll_removexattr(struct dentry *, const char *); extern int ll_inode_permission(struct inode *, int, struct nameidata *); int ll_refresh_lsm(struct inode *inode, struct lov_stripe_md *lsm); int ll_extent_lock(struct ll_file_data *, struct inode *, diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 26bc072..bc2d413 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -312,7 +312,7 @@ int lustre_common_fill_super(struct super_block *sb, char *lmv, char *lov, /* make root inode */ err = md_getattr(sbi->ll_md_exp, &sbi->ll_rootid, (OBD_MD_FLNOTOBD | OBD_MD_FLBLOCKS | OBD_MD_FID), - NULL, 0, &request); + NULL, NULL, 0, 0, &request); if (err) { CERROR("md_getattr failed for root: rc = %d\n", err); GOTO(out_lov, err); @@ -2085,7 +2085,8 @@ int ll_iocontrol(struct inode *inode, struct file *file, struct mds_body *body; ll_inode2id(&id, inode); - rc = md_getattr(sbi->ll_md_exp, &id, valid, NULL, 0, &req); + rc = md_getattr(sbi->ll_md_exp, &id, valid, NULL, NULL, 0, 0, + &req); if (rc) { CERROR("failure %d inode %lu\n", rc, inode->i_ino); RETURN(-abs(rc)); diff --git a/lustre/llite/llite_nfs.c b/lustre/llite/llite_nfs.c index c9ddcdc..e7138c2 100644 --- a/lustre/llite/llite_nfs.c +++ b/lustre/llite/llite_nfs.c @@ -79,7 +79,7 @@ static struct inode * search_inode_for_lustre(struct super_block *sb, id_ino(&id) = (__u64)ino; id_gen(&id) = generation; - rc = md_getattr(sbi->ll_md_exp, &id, valid, NULL, + rc = md_getattr(sbi->ll_md_exp, &id, valid, NULL, NULL, 0, eadatalen, &req); if (rc) { CERROR("failure %d inode %lu\n", rc, ino); diff --git a/lustre/llite/symlink.c b/lustre/llite/symlink.c index 66a980e..443f782 100644 --- a/lustre/llite/symlink.c +++ b/lustre/llite/symlink.c @@ -49,8 +49,8 @@ static int ll_readlink_internal(struct inode *inode, } ll_inode2id(&id, inode); - rc = md_getattr(sbi->ll_md_exp, &id, OBD_MD_LINKNAME, NULL, symlen, - request); + rc = md_getattr(sbi->ll_md_exp, &id, OBD_MD_LINKNAME, NULL, NULL, 0, + symlen, request); if (rc) { if (rc != -ENOENT) diff --git a/lustre/lmv/lmv_obd.c b/lustre/lmv/lmv_obd.c index 49da01a..3cd91d8 100644 --- a/lustre/lmv/lmv_obd.c +++ b/lustre/lmv/lmv_obd.c @@ -684,6 +684,7 @@ static int lmv_getstatus(struct obd_export *exp, struct lustre_id *id) static int lmv_getattr(struct obd_export *exp, struct lustre_id *id, __u64 valid, const char *xattr_name, + const void *xattr_data, unsigned int xattr_datalen, unsigned int ea_size, struct ptlrpc_request **request) { struct obd_device *obd = exp->exp_obd; @@ -699,7 +700,8 @@ static int lmv_getattr(struct obd_export *exp, struct lustre_id *id, LASSERT(i < lmv->desc.ld_tgt_count); - rc = md_getattr(lmv->tgts[i].ltd_exp, id, valid, xattr_name, + rc = md_getattr(lmv->tgts[i].ltd_exp, id, valid, + xattr_name, xattr_data, xattr_datalen, ea_size, request); if (rc) RETURN(rc); @@ -887,7 +889,7 @@ int lmv_get_mea_and_update_object(struct obd_export *exp, /* time to update mea of parent id */ rc = md_getattr(lmv->tgts[id_group(id)].ltd_exp, - id, valid, NULL, mealen, &req); + id, valid, NULL, NULL, 0, mealen, &req); if (rc) { CERROR("md_getattr() failed, error %d\n", rc); GOTO(cleanup, rc); diff --git a/lustre/lmv/lmv_objmgr.c b/lustre/lmv/lmv_objmgr.c index 85f2ef7..04595e6 100644 --- a/lustre/lmv/lmv_objmgr.c +++ b/lustre/lmv/lmv_objmgr.c @@ -310,7 +310,7 @@ lmv_create_obj(struct obd_export *exp, struct lustre_id *id, struct mea *mea) valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA | OBD_MD_MEA; rc = md_getattr(lmv->tgts[id_group(id)].ltd_exp, - id, valid, NULL, mealen, &req); + id, valid, NULL, NULL, 0, mealen, &req); if (rc) { CERROR("md_getattr() failed, error %d\n", rc); GOTO(cleanup, obj = ERR_PTR(rc)); diff --git a/lustre/mdc/mdc_reint.c b/lustre/mdc/mdc_reint.c index 6cd50d2..88ec501 100644 --- a/lustre/mdc/mdc_reint.c +++ b/lustre/mdc/mdc_reint.c @@ -34,6 +34,7 @@ #include #include +#include #include "mdc_internal.h" /* this function actually sends request to desired target. */ @@ -108,8 +109,18 @@ int mdc_setattr(struct obd_export *exp, struct mdc_op_data *data, mdc_setattr_pack(req->rq_reqmsg, 1, data, iattr, ea, ealen, ea2, ea2len); + /* prepare the reply buffer + */ + bufcount = 1; size[0] = sizeof(struct mds_body); - req->rq_replen = lustre_msg_size(1, size); + + /* This is a hack for setfacl remotely. XXX */ + if (ealen == sizeof(XATTR_NAME_LUSTRE_ACL) && + !strncmp((char *) ea, XATTR_NAME_LUSTRE_ACL, ealen)) { + size[bufcount++] = LUSTRE_ACL_SIZE_MAX; + } + + req->rq_replen = lustre_msg_size(bufcount, size); rc = mdc_reint(req, rpc_lock, LUSTRE_IMP_FULL); *request = req; diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index a4584eb..e062bc5 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -150,7 +150,7 @@ int mdc_getattr_common(struct obd_export *exp, unsigned int ea_size, CERROR ("Missing/short eadata\n"); RETURN (-EPROTO); } - } + } RETURN (0); } @@ -168,21 +168,29 @@ static int mdc_cancel_unused(struct obd_export *exp, int mdc_getattr(struct obd_export *exp, struct lustre_id *id, __u64 valid, const char *xattr_name, + const void *xattr_data, unsigned int xattr_datalen, unsigned int ea_size, struct ptlrpc_request **request) { struct ptlrpc_request *req; struct mds_body *body; int xattr_namelen = xattr_name ? strlen(xattr_name) + 1 : 0; + int size[4] = {0, sizeof(*body)}; int bufcount = 2; - int size[3] = {0, sizeof(*body)}; int rc; ENTRY; size[0] = lustre_secdesc_size(); - if (valid & OBD_MD_FLXATTR) + if (valid & OBD_MD_FLXATTR) { size[bufcount++] = xattr_namelen; + if (xattr_datalen > 0) { + LASSERT(xattr_data); + size[bufcount++] = xattr_datalen; + } + } else + LASSERT(!xattr_data && !xattr_datalen); + req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION, MDS_GETATTR, bufcount, size, NULL); if (!req) @@ -195,10 +203,13 @@ int mdc_getattr(struct obd_export *exp, struct lustre_id *id, body->valid = valid; body->eadatasize = ea_size; - - if (valid & OBD_MD_FLXATTR) + if (valid & OBD_MD_FLXATTR) { memcpy(lustre_msg_buf(req->rq_reqmsg, 2, xattr_namelen), xattr_name, xattr_namelen); + if (xattr_datalen) + memcpy(lustre_msg_buf(req->rq_reqmsg, 3, xattr_datalen), + xattr_data, xattr_datalen); + } rc = mdc_getattr_common(exp, ea_size, req); if (rc != 0) { diff --git a/lustre/mds/Makefile.in b/lustre/mds/Makefile.in index 98f9e75..a7278e2 100644 --- a/lustre/mds/Makefile.in +++ b/lustre/mds/Makefile.in @@ -1,5 +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_lmv.o mds_lsd.o +mds-objs += mds_acl.o @INCLUDE_RULES@ diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index 30d8251..8765df4 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -967,8 +967,8 @@ int mds_pack_link(struct dentry *dentry, struct ptlrpc_request *req, RETURN(rc); } -int mds_pack_ea(struct dentry *dentry, struct ptlrpc_request *req, - struct mds_body *repbody, int req_off, int reply_off) +int mds_pack_xattr(struct dentry *dentry, struct ptlrpc_request *req, + struct mds_body *repbody, int req_off, int reply_off) { struct inode *inode = dentry->d_inode; char *ea_name; @@ -982,7 +982,42 @@ int mds_pack_ea(struct dentry *dentry, struct ptlrpc_request *req, value = lustre_msg_buf(req->rq_repmsg, reply_off + 1, len); rc = -EOPNOTSUPP; - if (inode->i_op && inode->i_op->getxattr) + + if (!strcmp(ea_name, XATTR_NAME_LUSTRE_ACL)) { + struct rmtacl_upcall_desc desc; + + if (len != LUSTRE_ACL_SIZE_MAX || !value) { + CERROR("no reply buffer prepared\n"); + RETURN(-EFAULT); + } + + memset(&desc, 0, sizeof(desc)); + desc.get = 1; + desc.cmd = lustre_msg_string(req->rq_reqmsg, req_off + 2, 0); + desc.cmdlen = req->rq_reqmsg->buflens[req_off + 2]; + desc.res = (char *) value; + desc.reslen = LUSTRE_ACL_SIZE_MAX; + + mds_do_remote_acl_upcall(&desc); + + if (desc.upcall_status) + RETURN(desc.upcall_status); + + if (desc.reslen > LUSTRE_ACL_SIZE_MAX) { + CERROR("downcall claim reslen %u\n", desc.reslen); + RETURN(-EINVAL); + } + /* like remote setfacl, steal "flags" in mds_body as the + * exececution status + */ + repbody->flags = desc.status; + repbody->valid |= OBD_MD_FLXATTR; + repbody->eadatasize = desc.reslen; + + RETURN(0); + } + + if (inode->i_op && inode->i_op->getxattr) rc = inode->i_op->getxattr(dentry, ea_name, value, len); if (rc < 0) { @@ -994,11 +1029,11 @@ int mds_pack_ea(struct dentry *dentry, struct ptlrpc_request *req, rc = 0; } - RETURN(rc); + RETURN(rc); } -int mds_pack_ealist(struct dentry *dentry, struct ptlrpc_request *req, - struct mds_body *repbody, int reply_off) +int mds_pack_xattr_list(struct dentry *dentry, struct ptlrpc_request *req, + struct mds_body *repbody, int reply_off) { struct inode *inode = dentry->d_inode; void *value = NULL; @@ -1172,9 +1207,9 @@ static int mds_getattr_internal(struct obd_device *obd, struct dentry *dentry, (reqbody->valid & OBD_MD_LINKNAME) != 0) { rc = mds_pack_link(dentry, req, body, reply_off); } else if (reqbody->valid & OBD_MD_FLXATTR) { - rc = mds_pack_ea(dentry, req, body, req_off, reply_off); + rc = mds_pack_xattr(dentry, req, body, req_off, reply_off); } else if (reqbody->valid & OBD_MD_FLXATTRLIST) { - rc = mds_pack_ealist(dentry, req, body, reply_off); + rc = mds_pack_xattr_list(dentry, req, body, reply_off); } if (reqbody->valid & OBD_MD_FLACL) { @@ -1258,16 +1293,23 @@ static int mds_getattr_pack_msg(struct ptlrpc_request *req, struct dentry *de, char *ea_name = lustre_msg_string(req->rq_reqmsg, offset + 1, 0); rc = -EOPNOTSUPP; - if (inode->i_op && inode->i_op->getxattr) - rc = inode->i_op->getxattr(de, ea_name, NULL, 0); - - if (rc < 0) { - if (rc != -ENODATA && rc != -EOPNOTSUPP) - CERROR("error getting inode %lu EA: rc = %d\n", - inode->i_ino, rc); - size[bufcount] = 0; + + if (!strcmp(ea_name, XATTR_NAME_LUSTRE_ACL)) { + size[bufcount] = LUSTRE_ACL_SIZE_MAX; } else { - size[bufcount] = min_t(int, body->eadatasize, rc); + if (inode->i_op && inode->i_op->getxattr) + rc = inode->i_op->getxattr(de, ea_name, + NULL, 0); + + if (rc < 0) { + if (rc != -ENODATA && rc != -EOPNOTSUPP) + CERROR("error get inode %lu EA: %d\n", + inode->i_ino, rc); + size[bufcount] = 0; + } else { + size[bufcount] = min_t(int, + body->eadatasize, rc); + } } bufcount++; } else if (body->valid & OBD_MD_FLXATTRLIST) { @@ -3003,9 +3045,14 @@ int mds_handle(struct ptlrpc_request *req) else bufcount = 1; - rc = lustre_pack_reply(req, bufcount, size, NULL); - if (rc) - break; + /* for SETATTR: I have different reply setting for + * remote setfacl, so delay the reply buffer allocation. + */ + if (opc != REINT_SETATTR) { + rc = lustre_pack_reply(req, bufcount, size, NULL); + if (rc) + break; + } rc = mds_reint(req, MDS_REQ_REC_OFF, NULL); fail = OBD_FAIL_MDS_REINT_NET_REP; @@ -4415,6 +4462,7 @@ static int __init mds_init(void) struct lprocfs_static_vars lvars; mds_init_lsd_cache(); + mds_init_rmtacl_upcall_cache(); lprocfs_init_multi_vars(0, &lvars); class_register_type(&mds_obd_ops, NULL, lvars.module_vars, @@ -4428,6 +4476,7 @@ static int __init mds_init(void) static void /*__exit*/ mds_exit(void) { + mds_cleanup_rmtacl_upcall_cache(); mds_cleanup_lsd_cache(); class_unregister_type(OBD_MDS_DEVICENAME); diff --git a/lustre/mds/lproc_mds.c b/lustre/mds/lproc_mds.c index f658434..fa8cbe6 100644 --- a/lustre/mds/lproc_mds.c +++ b/lustre/mds/lproc_mds.c @@ -294,6 +294,55 @@ static int lprocfs_wr_lsd_flush(struct file *file, const char *buffer, return count; } +/* + * remote acl proc handling + */ +static int lprocfs_rd_lacl_upcall(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct upcall_cache *cache = __mds_get_global_rmtacl_upcall_cache(); + + *eof = 1; + return snprintf(page, count, "%s\n", cache->uc_upcall); +} + +static int lprocfs_wr_lacl_upcall(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct upcall_cache *cache = __mds_get_global_rmtacl_upcall_cache(); + + if (count < UC_CACHE_UPCALL_MAXPATH) { + sscanf(buffer, "%1024s", cache->uc_upcall); + cache->uc_upcall[UC_CACHE_UPCALL_MAXPATH - 1] = 0; + } + return count; +} + +static int lprocfs_wr_lacl_downcall(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct upcall_cache *cache = __mds_get_global_rmtacl_upcall_cache(); + struct rmtacl_downcall_args param; + + if (count != sizeof(param)) { + CERROR("invalid data size %lu\n", count); + goto do_err_downcall; + } + if (copy_from_user(¶m, buffer, count)) { + CERROR("broken downcall\n"); + goto do_err_downcall; + } + +do_downcall: + upcall_cache_downcall(cache, param.key, ¶m); + return count; + +do_err_downcall: + memset(¶m, 0, sizeof(param)); + param.status = -EINVAL; + goto do_downcall; +} + struct lprocfs_vars lprocfs_mds_module_vars[] = { { "num_refs", lprocfs_rd_numrefs, 0, 0 }, /* LSD stuff */ @@ -305,6 +354,10 @@ struct lprocfs_vars lprocfs_mds_module_vars[] = { lprocfs_wr_lsd_upcall, 0}, { "lsd_flush", 0, lprocfs_wr_lsd_flush, 0}, { "lsd_downcall", 0, lprocfs_wr_lsd_downcall, 0}, + /* remote acl */ + { "lacl_upcall", lprocfs_rd_lacl_upcall, + lprocfs_wr_lacl_upcall, 0}, + { "lacl_downcall", 0, lprocfs_wr_lacl_downcall, 0}, { 0 } }; diff --git a/lustre/mds/mds_acl.c b/lustre/mds/mds_acl.c new file mode 100644 index 0000000..68eddf0 --- /dev/null +++ b/lustre/mds/mds_acl.c @@ -0,0 +1,316 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (c) 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. + */ + +#define DEBUG_SUBSYSTEM S_MDS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mds_internal.h" + +/**************************************** + * handle remote getfacl/setfacl upcall * + ****************************************/ + +#define RMTACL_UPCALL_HASHSIZE (1) +static struct upcall_cache _rmtacl_upcall_cache; +static struct list_head _rmtacl_upcall_hashtable[RMTACL_UPCALL_HASHSIZE]; + +#define RMTACL_UPCALL_PATH "/usr/bin/lacl_upcall" +#define RMTACL_ACQUIRE_EXPIRE (15) +#define RMTACL_ENTRY_EXPIRE (0) +#define RMTACL_ERR_ENTRY_EXPIRE (0) + +struct upcall_cache *__mds_get_global_rmtacl_upcall_cache() +{ + return &_rmtacl_upcall_cache; +} + +static unsigned int rmtacl_hash(struct upcall_cache *cache, __u64 key) +{ + LASSERT(cache == &_rmtacl_upcall_cache); + return 0; +} + +static struct upcall_cache_entry * +rmtacl_alloc_entry(struct upcall_cache *cache, __u64 key) +{ + struct rmtacl_upcall_entry *entry; + + OBD_ALLOC(entry, sizeof(*entry)); + if (!entry) + return NULL; + + upcall_cache_init_entry(cache, &entry->base, key); + entry->desc = (struct rmtacl_upcall_desc *) ((unsigned long) key); + + return &entry->base; +} + +static void rmtacl_free_entry(struct upcall_cache *cache, + struct upcall_cache_entry *entry) +{ + struct rmtacl_upcall_entry *rentry; + + rentry = container_of(entry, struct rmtacl_upcall_entry, base); + OBD_FREE(rentry, sizeof(*rentry)); +} + +static int rmtacl_make_upcall(struct upcall_cache *cache, + struct upcall_cache_entry *entry) +{ + struct rmtacl_upcall_entry *rentry; + struct rmtacl_upcall_desc *desc; + char *argv[7]; + char *envp[3]; + char keystr[20]; + char uidstr[16]; + int rc; + + rentry = container_of(entry, struct rmtacl_upcall_entry, base); + desc = rentry->desc; + + snprintf(keystr, 20, LPX64, entry->ue_key); + snprintf(uidstr, 16, "%u", desc->uid); + + argv[0] = cache->uc_upcall; + argv[1] = keystr; + argv[2] = uidstr; + argv[3] = desc->root; + argv[4] = desc->get ? "get" : "set"; + argv[5] = desc->cmd; + argv[6] = NULL; + + envp[0] = "HOME=/"; + envp[1] = "PATH=/bin:/usr/bin:/usr/local/bin"; + envp[2] = NULL; + + rc = USERMODEHELPER(argv[0], argv, envp); + if (rc < 0) { + CERROR("Error invoking upcall %s: %d; check " + "/proc/fs/lustre/mds/lacl_upcall\n", + argv[0], rc); + } else { + CDEBUG(D_SEC, "Invoked upcall %s %s %s %s\n", + argv[0], argv[1], argv[2], argv[3]); + } + return rc; +} + +static int rmtacl_parse_downcall(struct upcall_cache *cache, + struct upcall_cache_entry *entry, + void *args) +{ + struct rmtacl_upcall_entry *rentry; + struct rmtacl_upcall_desc *desc; + struct rmtacl_downcall_args *rargs; + + LASSERT(args); + + rentry = container_of(entry, struct rmtacl_upcall_entry, base); + desc = rentry->desc; + rargs = (struct rmtacl_downcall_args *) args; + + desc->status = rargs->status; + + if (desc->reslen < rargs->reslen) { + CERROR("bufsize %u, while %u passed down\n", + desc->reslen, rargs->reslen); + desc->upcall_status = -ENOMEM; + goto out; + } + + desc->reslen = rargs->reslen; + if (!rargs->reslen) + goto out; + + if (copy_from_user(desc->res, rargs->res, rargs->reslen)) { + desc->upcall_status = -EFAULT; + goto out; + } + +out: + return 0; +} + +static void mds_rmtacl_upcall(struct rmtacl_upcall_desc *desc) +{ + struct upcall_cache *cache = &_rmtacl_upcall_cache; + struct upcall_cache_entry *entry; + + desc->upcall_status = 0; + + entry = upcall_cache_get_entry(cache, (__u64) ((unsigned long) desc)); + if (!entry) { + desc->upcall_status = -EINVAL; + return; + } + + UC_CACHE_SET_EXPIRED(entry); + upcall_cache_put_entry(entry); +} + +int mds_init_rmtacl_upcall_cache() +{ + struct upcall_cache *cache = &_rmtacl_upcall_cache; + int i; + ENTRY; + + cache->uc_hashtable = _rmtacl_upcall_hashtable; + cache->uc_hashsize = RMTACL_UPCALL_HASHSIZE; + cache->uc_hashlock = RW_LOCK_UNLOCKED; + for (i = 0; i < cache->uc_hashsize; i++) + INIT_LIST_HEAD(&cache->uc_hashtable[i]); + cache->uc_name = "RMTACL_UPCALL"; + + /* set default value, proc tunable */ + sprintf(cache->uc_upcall, RMTACL_UPCALL_PATH); + cache->uc_acquire_expire = RMTACL_ACQUIRE_EXPIRE; + cache->uc_entry_expire = RMTACL_ENTRY_EXPIRE; + cache->uc_err_entry_expire = RMTACL_ERR_ENTRY_EXPIRE; + + cache->hash = rmtacl_hash; + cache->alloc_entry = rmtacl_alloc_entry; + cache->free_entry = rmtacl_free_entry; + cache->make_upcall = rmtacl_make_upcall; + cache->parse_downcall = rmtacl_parse_downcall; + + RETURN(0); +} + +void mds_cleanup_rmtacl_upcall_cache() +{ + struct upcall_cache *cache = &_rmtacl_upcall_cache; + + LASSERT(list_empty(&cache->uc_hashtable[0])); +} + +/**************************************** + * exported helper functions * + ****************************************/ + +/* + * traverse through the mountpoint to find lustre mountpoint + */ +static struct vfsmount *mds_get_lustre_mnt(void) +{ + struct vfsmount *mnt, *lmnt = NULL; + + LASSERT(current->fs); + read_lock(¤t->fs->lock); + mnt = mntget(current->fs->rootmnt); + read_unlock(¤t->fs->lock); + LASSERT(mnt); + + spin_lock(&vfsmount_lock); +check_point: + if (!strcmp(mnt->mnt_sb->s_type->name, "lustre") || + !strcmp(mnt->mnt_sb->s_type->name, "llite")) { + lmnt = mntget(mnt); + goto break_out; + } + + if (!list_empty(&mnt->mnt_mounts)) { + mnt = list_entry(mnt->mnt_mounts.next, + struct vfsmount, mnt_child); + goto check_point; + } + +follow_siblings: + /* check siblings */ + if (list_empty(&mnt->mnt_child) || + mnt->mnt_child.next == &mnt->mnt_parent->mnt_mounts) { + /* we are the last child */ + LASSERT(mnt->mnt_parent != NULL); + if (list_empty(&mnt->mnt_child) || + mnt->mnt_parent == NULL) + goto break_out; + mnt = mnt->mnt_parent; + goto follow_siblings; + } + + mnt = list_entry(mnt->mnt_child.next, struct vfsmount, mnt_child); + goto check_point; + +break_out: + spin_unlock(&vfsmount_lock); + + return lmnt; +} + +void mds_do_remote_acl_upcall(struct rmtacl_upcall_desc *desc) +{ + struct fs_struct *fs = current->fs; + struct vfsmount *lmnt; + char *buf = NULL, *mntpnt; + + lmnt = mds_get_lustre_mnt(); + if (!lmnt) { + desc->upcall_status = -EOPNOTSUPP; + return; + } + + OBD_ALLOC(buf, PAGE_SIZE); + if (!buf) { + desc->upcall_status = -ENOMEM; + goto out; + } + + mntpnt = __d_path(lmnt->mnt_root, lmnt, fs->root, fs->rootmnt, + buf, PAGE_SIZE); + if (IS_ERR(mntpnt)) { + desc->upcall_status = PTR_ERR(mntpnt); + goto out; + } + + desc->root = mntpnt; + desc->uid = current->uid; + + mds_rmtacl_upcall(desc); + +out: + if (buf) + OBD_FREE(buf, PAGE_SIZE); + mntput(lmnt); +} diff --git a/lustre/mds/mds_internal.h b/lustre/mds/mds_internal.h index 5948655..c66c23d 100644 --- a/lustre/mds/mds_internal.h +++ b/lustre/mds/mds_internal.h @@ -236,10 +236,10 @@ int mds_pack_md(struct obd_device *, struct lustre_msg *, int offset, struct mds_body *, struct inode *, int lock, int mea); int mds_pack_link(struct dentry *dentry, struct ptlrpc_request *req, struct mds_body *repbody, int reply_off); -int mds_pack_ea(struct dentry *dentry, struct ptlrpc_request *req, - struct mds_body *repbody, int req_off, int reply_off); -int mds_pack_ealist(struct dentry *dentry, struct ptlrpc_request *req, - struct mds_body *repbody, int reply_off); +int mds_pack_xattr(struct dentry *dentry, struct ptlrpc_request *req, + struct mds_body *repbody, int req_off, int reply_off); +int mds_pack_xattr_list(struct dentry *dentry, struct ptlrpc_request *req, + struct mds_body *repbody, int reply_off); int mds_pack_acl(struct ptlrpc_request *req, int reply_off, struct mds_body *body, struct inode *inode); int mds_pack_inode2id(struct obd_device *, struct lustre_id *, @@ -283,4 +283,10 @@ struct lustre_sec_desc * mds_get_lsd(__u32 uid); void mds_put_lsd(struct lustre_sec_desc *lsd); void mds_flush_lsd(__u32 id); +/* mds_acl.c */ +struct upcall_cache *__mds_get_global_rmtacl_upcall_cache(void); +int mds_init_rmtacl_upcall_cache(void); +void mds_cleanup_rmtacl_upcall_cache(void); +void mds_do_remote_acl_upcall(struct rmtacl_upcall_desc *desc); + #endif /* _MDS_INTERNAL_H */ diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index 0d3e4c2..51c1a24 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -394,6 +394,65 @@ static void reconstruct_reint_setattr(struct mds_update_record *rec, l_dput(de); } + +static int mds_reint_remote_setfacl(struct obd_device *obd, + struct mds_export_data *med, + struct mds_update_record *rec, + struct ptlrpc_request *req) +{ + struct rmtacl_upcall_desc desc; + struct dentry *de; + struct inode *inode; + struct mds_body *body; + int rc = 0; + int repsize[2] = { sizeof(*body), LUSTRE_ACL_SIZE_MAX }; + ENTRY; + + rc = lustre_pack_reply(req, 2, repsize, NULL); + if (rc) + RETURN(rc); + + de = mds_id2dentry(obd, rec->ur_id1, NULL); + if (IS_ERR(de)) + GOTO(out, rc = PTR_ERR(de)); + + inode = de->d_inode; + LASSERT(inode); + + /* setxattr from remote client: + */ + memset(&desc, 0, sizeof(desc)); + desc.cmd = (char *) rec->ur_ea2data; + desc.cmdlen = rec->ur_ea2datalen; + desc.res = lustre_msg_buf(req->rq_repmsg, 1, LUSTRE_ACL_SIZE_MAX); + desc.reslen = LUSTRE_ACL_SIZE_MAX; + + mds_do_remote_acl_upcall(&desc); + if (desc.upcall_status) + GOTO(out_put, rc = desc.upcall_status); + + if (desc.status < 0) + desc.status = -desc.status; + + body = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*body)); + LASSERT(body); + + /* client (lmv) will do limited checking upon replied mds_body, + * we pack it as normal, but "steal" field "flags" field to store + * the acl execution status. + */ + mds_pack_inode2body(obd, body, inode, 1); + body->flags = desc.status; + mds_body_do_reverse_map(med, body); + + EXIT; +out_put: + l_dput(de); +out: + req->rq_status = rc; + return 0; +} + /*This is a tmp fix for cmobd setattr reint*/ #define XATTR_LUSTRE_MDS_LOV_EA "lov" @@ -432,7 +491,7 @@ static int mds_reint_setattr(struct mds_update_record *rec, int offset, void *handle = NULL; struct mds_logcancel_data *mlcd = NULL; int rc = 0, cleanup_phase = 0, err; - int locked = 0; + int repsize = sizeof(*body), locked = 0; ENTRY; LASSERT(offset == 1); @@ -441,6 +500,16 @@ static int mds_reint_setattr(struct mds_update_record *rec, int offset, id_ino(rec->ur_id1), id_gen(rec->ur_id1), rec->ur_iattr.ia_valid); + /* remote setfacl need special handling */ + if ((rec->ur_iattr.ia_valid & ATTR_EA) && + !strcmp(rec->ur_eadata, XATTR_NAME_LUSTRE_ACL)) { + return mds_reint_remote_setfacl(obd, med, rec, req); + } + + rc = lustre_pack_reply(req, 1, &repsize, NULL); + if (rc) + RETURN(rc); + MDS_CHECK_RESENT(req, reconstruct_reint_setattr(rec, offset, req)); MD_COUNTER_INCREMENT(obd, setattr); @@ -508,17 +577,22 @@ static int mds_reint_setattr(struct mds_update_record *rec, int offset, if (rc == 0) { if (rec->ur_iattr.ia_valid & ATTR_EA) { - int flags = (int)rec->ur_iattr.ia_attr_flags; + int flags = (int) rec->ur_iattr.ia_attr_flags; rc = -EOPNOTSUPP; - if (inode->i_op && inode->i_op->setxattr) - rc = inode->i_op->setxattr(de, rec->ur_eadata, - rec->ur_ea2data, rec->ur_ea2datalen, - flags); + if (!med->med_remote && inode->i_op && + inode->i_op->setxattr) + rc = inode->i_op->setxattr( + de, rec->ur_eadata, + rec->ur_ea2data, + rec->ur_ea2datalen, + flags); } else if (rec->ur_iattr.ia_valid & ATTR_EA_RM) { rc = -EOPNOTSUPP; - if (inode->i_op && inode->i_op->removexattr) - rc = inode->i_op->removexattr(de, rec->ur_eadata); + if (!med->med_remote && inode->i_op && + inode->i_op->removexattr) + rc = inode->i_op->removexattr( + de, rec->ur_eadata); } else if (rec->ur_iattr.ia_valid & ATTR_EA_CMOBD) { char *name; int type; diff --git a/lustre/sec/upcall_cache.c b/lustre/sec/upcall_cache.c index c3b0dbb..ad4686a 100644 --- a/lustre/sec/upcall_cache.c +++ b/lustre/sec/upcall_cache.c @@ -263,7 +263,6 @@ find_again: } /* Now we know it's good */ - LASSERT(UC_CACHE_IS_VALID(entry)); write_unlock(&cache->uc_hashlock); RETURN(entry); diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am index 623fc2e..f4beb73 100644 --- a/lustre/utils/Makefile.am +++ b/lustre/utils/Makefile.am @@ -14,7 +14,8 @@ bin_scripts = lfind lstripe if UTILS rootsbin_SCRIPTS = mount.lustre -sbin_PROGRAMS = lctl obdio obdbarrier lload wirecheck wiretest llmount lsd_upcall +sbin_PROGRAMS = lctl obdio obdbarrier lload wirecheck wiretest llmount \ + lsd_upcall lacl_upcall bin_PROGRAMS = lfs lkinit lib_LIBRARIES = liblustreapi.a sbin_SCRIPTS = $(sbin_scripts) @@ -48,6 +49,10 @@ lsd_upcall_SOURCES = lsd_upcall.c lsd_upcall_LDADD = $(LIBREADLINE) $(LIBPTLCTL) lsd_upcall_DEPENDENCIES := $(LIBPTLCTL) +lacl_upcall_SOURCES = lacl_upcall.c +lacl_upcall_LDADD = $(LIBREADLINE) $(LIBPTLCTL) +lacl_upcall_DEPENDENCIES := $(LIBPTLCTL) + EXTRA_DIST = $(bin_scripts) $(sbin_scripts) # NOTE: this should only be run on i386. diff --git a/lustre/utils/lacl_upcall.c b/lustre/utils/lacl_upcall.c new file mode 100644 index 0000000..dec19f4 --- /dev/null +++ b/lustre/utils/lacl_upcall.c @@ -0,0 +1,309 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (C) 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +int switch_user_identity(uid_t uid) +{ + gid_t gid; + struct passwd *pw; + int maxgroups, ngroups = 0; + gid_t *groups; + struct group *gr; + int i; + + /* originally must be root */ + if (getuid() != 0 || geteuid() != 0) + return -EPERM; + + /* nothing more is needed for root */ + if (uid == 0) + return 0; + + /* - groups + * - gid + * - uid + */ + maxgroups = sysconf(_SC_NGROUPS_MAX); + groups = malloc(maxgroups * sizeof(gid_t)); + if (!groups) + return -ENOMEM; + + pw = getpwuid(uid); + if (!pw) + return -EPERM; + + gid = pw->pw_gid; + + while ((gr = getgrent())) { + if (!gr->gr_mem) + continue; + for (i = 0; gr->gr_mem[i]; i++) { + if (strcmp(gr->gr_mem[i], pw->pw_name)) + continue; + groups[ngroups++] = gr->gr_gid; + break; + } + if (ngroups == maxgroups) + break; + } + endgrent(); + + if (setgroups(ngroups, groups) == -1) { + free(groups); + return -EPERM; + } + free(groups); + + if (setgid(gid) == -1) { + return -EPERM; + } + + if (setuid(uid) == -1) { + return -EPERM; + } + + return 0; +} + +/* + * caller guarantee args not empty + */ +int compose_command_line(char *cmdline, char *op, char *args) +{ + char *p, *params, *file; + + /* skip the white space at the tail */ + p = args + strlen(args) - 1; + + while (p >= args) { + if (*p != ' ' && *p != '\t') + break; + p--; + } + + /* not allow empty args */ + if (p < args) + return -1; + + *(p + 1) = '\0'; + + /* find next space */ + while (p >= args) { + if (*p == ' ' || *p == '\t') + break; + p--; + } + + if (p >= args) { + *p = '\0'; + file = p + 1; /* file name */ + params = args; + } else { + file = args; + params = ""; + } + + /* backward path not allowed */ + if (strstr(file, "..")) + return -EPERM; + + /* absolute path not allowed */ + if (file[0] == '/') + return -EPERM; + + snprintf(cmdline, PATH_MAX, "%sfacl %s %s", + op, params, file); + return 0; +} + +void do_acl_command(uid_t uid, char *lroot, char *cmdline) +{ + if (switch_user_identity(uid)) { + printf("MDS: invalid user %u\n", uid); + return; + } + + if (chdir(lroot) < 0) { + printf("MDS: can't change dir\n"); + return; + } + + execl("/bin/sh", "sh", "-c", cmdline, NULL); + printf("MDS: can't execute\n"); +} + +#define ERRSTR_NO_CMDLINE "No command line supplied\n" +#define ERRSTR_INVALID_ARGS "Invalid arguments\n" +#define ERRSTR_MDS_PROCESS "MDS procession error\n" + +/* + * The args passed in are: + * 1. key (in hex) + * 2. uid (in uint) + * 3. lustre root + * 4. get/set + * 5. command line + */ +#define OUTPUT_BUFSIZE 8192 +int main (int argc, char **argv) +{ + struct rmtacl_downcall_args dc_args; + char *dc_name = "/proc/fs/lustre/mds/lacl_downcall"; + int dc_fd; + int uid; + char output[OUTPUT_BUFSIZE]; + char cmdline[PATH_MAX]; + int pipeout[2], pipeerr[2], pid; + int output_size, rd, childret; + + if (argc != 6) + return -1; + + if (strcmp(argv[4], "get") && strcmp(argv[4], "set")) + return -1; + + dc_args.key = strtoull(argv[1], NULL, 16); + dc_args.res = output; + dc_args.reslen = 0; + dc_args.status = -1; /* default return error */ + + uid = atoi(argv[2]); + + if (strlen(argv[5]) == 0) { + dc_args.reslen = sizeof(ERRSTR_NO_CMDLINE); + memcpy(output, ERRSTR_NO_CMDLINE, dc_args.reslen); + goto downcall; + } + + if (compose_command_line(cmdline, argv[4], argv[5])) { + dc_args.reslen = sizeof(ERRSTR_INVALID_ARGS); + memcpy(output, ERRSTR_INVALID_ARGS, dc_args.reslen); + goto downcall; + } + + /* create pipe */ + if (pipe(pipeout) < 0 || pipe(pipeerr) < 0) { + dc_args.reslen = sizeof(ERRSTR_MDS_PROCESS); + memcpy(output, ERRSTR_MDS_PROCESS, dc_args.reslen); + goto downcall; + } + + if ((pid = fork()) < 0) { + dc_args.reslen = sizeof(ERRSTR_MDS_PROCESS); + memcpy(output, ERRSTR_MDS_PROCESS, dc_args.reslen); + goto downcall; + } else if (pid == 0) { + close(pipeout[0]); + if (pipeout[1] != STDOUT_FILENO) { + dup2(pipeout[1], STDOUT_FILENO); + close(pipeout[1]); + } + + close(pipeerr[0]); + if (pipeerr[1] != STDERR_FILENO) { + dup2(pipeerr[1], STDERR_FILENO); + close(pipeerr[1]); + } + + close(STDIN_FILENO); + + do_acl_command(uid, argv[3], cmdline); + exit(-1); + } + + /* parent process handling */ + close(pipeout[1]); + close(pipeerr[1]); + + output[0] = 0; + output_size = 0; + while (1) { + rd = read(pipeout[0], output + output_size, + OUTPUT_BUFSIZE - output_size); + if (rd < 0) { + output_size = sizeof(ERRSTR_MDS_PROCESS); + memcpy(output, ERRSTR_MDS_PROCESS, dc_args.reslen); + break; + } + if (rd == 0) + break; + output_size += rd; + if (output_size >= OUTPUT_BUFSIZE) + break; + } + + /* if we got standard output, just leave; otherwise collect + * error output. + */ + if (output_size != 0) + goto wait_child; + + while (1) { + rd = read(pipeerr[0], output + output_size, + OUTPUT_BUFSIZE - output_size); + if (rd < 0) { + output_size = sizeof(ERRSTR_MDS_PROCESS); + memcpy(output, ERRSTR_MDS_PROCESS, dc_args.reslen); + break; + } + if (rd == 0) + break; + output_size += rd; + if (output_size >= OUTPUT_BUFSIZE) + break; + } + +wait_child: + wait(&childret); + + dc_args.status = childret; + dc_args.reslen = output_size; + +downcall: + dc_fd = open(dc_name, O_WRONLY); + if (dc_fd != -1) { + write(dc_fd, &dc_args, sizeof(dc_args)); + close(dc_fd); + } + + return 0; +} diff --git a/lustre/utils/lconf b/lustre/utils/lconf index c84cd07..bd47b63 100755 --- a/lustre/utils/lconf +++ b/lustre/utils/lconf @@ -2154,12 +2154,20 @@ class MDSDEV(Module): lctl.newdev("mdt", 'MDT', 'MDT_UUID', setup ="") if development_mode(): + # set lsd upcall path procentry = "/proc/fs/lustre/mds/lsd_upcall" upcall = os.path.abspath(os.path.dirname(sys.argv[0]) + "/lsd_upcall") if not (os.access(procentry, os.R_OK) and os.access(upcall, os.R_OK)): print "MDS Warning: failed to set lsd cache upcall" else: run("echo ", upcall, " > ", procentry) + # set lacl upcall path + procentry = "/proc/fs/lustre/mds/lacl_upcall" + upcall = os.path.abspath(os.path.dirname(sys.argv[0]) + "/lacl_upcall") + if not (os.access(procentry, os.R_OK) and os.access(upcall, os.R_OK)): + print "MDS Warning: failed to set remote acl upcall" + else: + run("echo ", upcall, " > ", procentry) if config.root_squash == None: config.root_squash = self.root_squash diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 1bc3d83..91f8f0e 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include @@ -48,6 +50,8 @@ static int lfs_showfid(int argc, char **argv); static int lfs_osts(int argc, char **argv); static int lfs_check(int argc, char **argv); static int lfs_catinfo(int argc, char **argv); +static int lfs_getfacl(int argc, char **argv); +static int lfs_setfacl(int argc, char **argv); /* all avaialable commands */ command_t cmdlist[] = { @@ -85,6 +89,12 @@ command_t cmdlist[] = { "usage: catinfo {keyword} [node name]\n" "\tkeywords are one of followings: config, deletions.\n" "\tnode name must be provided when use keyword config."}, + {"getfacl", lfs_getfacl, 0, + "Get file access control lists.\n" + "usage: getfacl [-dRLPvh] file"}, + {"setfacl", lfs_setfacl, 0, + "Set file access control lists.\n" + "usage: setfacl [-bkndRLPvh] [{-m|-x} acl_spec] [{-M|-X} acl_file] file ..."}, {"osts", lfs_osts, 0, "osts"}, {"help", Parser_help, 0, "help"}, {"exit", Parser_quit, 0, "quit"}, @@ -464,6 +474,135 @@ static int lfs_catinfo(int argc, char **argv) return rc; } +/* + * We assume one and only one filename is supplied as the + * last parameter. + */ +static int acl_cmd_parse(int argc, char **argv, + char *dirbuf, char *cmdbuf) +{ + char path[PATH_MAX]; + char path2[PATH_MAX]; + FILE *fp; + struct mntent *mnt = NULL; + char *dir, *tgt; + int found = 0, i; + + if (argc < 2) + return -1; + + /* get path prefix */ + strncpy(path, argv[argc - 1], PATH_MAX); + dir = dirname(path); + + /* try to resolve the pathname into relative to the + * root of the mounted lustre filesystem. + * FIXME we simply suppose there's no sub-mounted filesystems + * under this mounted lustre tree. + */ + if (getcwd(path2, PATH_MAX) == NULL) { + fprintf(stderr, "getcwd old: %s\n", strerror(errno)); + return -1; + } + + if (chdir(dir) == -1) { + fprintf(stderr, "chdir to %s: %s\n", + dir, strerror(errno)); + return -1; + } + + if (getcwd(path, PATH_MAX) == NULL) { + fprintf(stderr, "getcwd new: %s\n", strerror(errno)); + return -1; + } + + if (chdir(path2) == -1) { + fprintf(stderr, "chdir back: %s\n", strerror(errno)); + return -1; + } + + fp = setmntent(MOUNTED, "r"); + if (fp == NULL) { + fprintf(stderr, "setmntent(%s): %s\n", MOUNTED, + strerror(errno)); + return -1; + } + + while (1) { + mnt = getmntent(fp); + if (!mnt) + break; + + if (!llapi_is_lustre_mnttype(mnt->mnt_type)) + continue; + + if (!strncmp(mnt->mnt_dir, path, strlen(mnt->mnt_dir))) { + char *p; + + /* save the mountpoint dir part */ + strncpy(dirbuf, mnt->mnt_dir, PATH_MAX); + + /* get rest of path under the mountpoint, + * don't start with slash. + */ + p = path + strlen(mnt->mnt_dir); + while (*p == '/') + p++; + snprintf(path2, PATH_MAX, "%s", p); + + /* remove trailing slash */ + if (path2[strlen(path2)] == '/') + path2[strlen(path2)] = '\0'; + found = 1; + /* continue try to match more proper fs */ + } + } + endmntent(fp); + + if (!found) { + fprintf(stderr, "no mounted lustre fs\n"); + return -1; + } + + /* get base name of target */ + strncpy(path, argv[argc - 1], PATH_MAX); + tgt = basename(path); + + cmdbuf[0] = '\0'; + for (i = 1; i < argc - 1; i++) { + strncat(cmdbuf, argv[i], PATH_MAX); + strncat(cmdbuf, " ", PATH_MAX); + } + strncat(cmdbuf, path2, PATH_MAX); + if (path2[0] != '\0') + strncat(cmdbuf, "/", PATH_MAX); + strncat(cmdbuf, tgt, PATH_MAX); + + return 0; +} + +static int lfs_getfacl(int argc, char **argv) +{ + char dir[PATH_MAX]; + char cmd[PATH_MAX]; + + if (acl_cmd_parse(argc, argv, dir, cmd)) + return CMD_HELP; + + return llapi_getfacl(dir, cmd); +} + +static int lfs_setfacl(int argc, char **argv) +{ + char dir[PATH_MAX]; + char cmd[PATH_MAX]; + + if (acl_cmd_parse(argc, argv, dir, cmd)) + return CMD_HELP; + + return llapi_setfacl(dir, cmd); +} + int main(int argc, char **argv) { int rc; diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index b7c2a66..bcba4ae 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -832,6 +833,70 @@ int llapi_catinfo(char *dir, char *keyword, char *node_name) return rc; } +int llapi_getfacl(char *dir, char *cmd) +{ + struct ll_acl_ioctl_data data; + char out[LUSTRE_ACL_SIZE_MAX]; + int fd, rc; + + data.cmd = cmd; + data.cmd_len = strlen(cmd) + 1; + data.res = out; + data.res_len = sizeof(out); + data.status = 0; + + fd = open(dir, O_RDONLY | O_DIRECTORY); + if (fd == -1) { + err_msg("can't open dir %s", dir); + return -1; + } + + rc = ioctl(fd, LL_IOC_GETFACL, &data); + if (rc) + err_msg("getfacl failed"); + else { + out[sizeof(out) - 1] = '\0'; + printf("%s", out); + rc = data.status; + } + + close(fd); + + return rc; +} + +int llapi_setfacl(char *dir, char *cmd) +{ + struct ll_acl_ioctl_data data; + char out[LUSTRE_ACL_SIZE_MAX]; + int fd, rc; + + data.cmd = cmd; + data.cmd_len = strlen(cmd) + 1; + data.res = out; + data.res_len = sizeof(out); + data.status = 0; + + fd = open(dir, O_RDONLY | O_DIRECTORY); + if (fd == -1) { + err_msg("can't open dir %s", dir); + return -1; + } + + rc = ioctl(fd, LL_IOC_SETFACL, &data); + if (rc) + err_msg("setfacl failed"); + else { + out[sizeof(out) - 1] = '\0'; + printf("%s", out); + rc = data.status; + } + + close(fd); + + return rc; +} + int llapi_is_lustre_mnttype(char *type) { return (strcmp(type,"lustre") == 0 || strcmp(type,"lustre_lite") == 0); -- 1.8.3.1