Whamcloud - gitweb
land b_hd_remote_acl: support get/set ACL from remote client.
authorericm <ericm>
Sun, 31 Jul 2005 04:49:34 +0000 (04:49 +0000)
committerericm <ericm>
Sun, 31 Jul 2005 04:49:34 +0000 (04:49 +0000)
31 files changed:
lustre/cobd/cache_obd.c
lustre/include/linux/lustre_acl.h
lustre/include/linux/lustre_mds.h
lustre/include/linux/obd.h
lustre/include/linux/obd_class.h
lustre/include/lustre/liblustreapi.h
lustre/include/lustre/lustre_user.h
lustre/kernel_patches/patches/export-2.6-fc3.patch
lustre/liblustre/super.c
lustre/llite/dir.c
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/llite_nfs.c
lustre/llite/symlink.c
lustre/lmv/lmv_obd.c
lustre/lmv/lmv_objmgr.c
lustre/mdc/mdc_reint.c
lustre/mdc/mdc_request.c
lustre/mds/Makefile.in
lustre/mds/handler.c
lustre/mds/lproc_mds.c
lustre/mds/mds_acl.c [new file with mode: 0644]
lustre/mds/mds_internal.h
lustre/mds/mds_reint.c
lustre/sec/upcall_cache.c
lustre/utils/Makefile.am
lustre/utils/lacl_upcall.c [new file with mode: 0644]
lustre/utils/lconf
lustre/utils/lfs.c
lustre/utils/liblustreapi.c

index 409e6eb..d7007ba 100644 (file)
@@ -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, 
index 2267997..26e0d87 100644 (file)
@@ -23,7 +23,9 @@
 #ifndef _LUSTRE_ACL_H_
 #define _LUSTRE_ACL_H_
 
+#ifdef __KERNEL__
 #include <linux/xattr_acl.h>
+#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
index 40acf00..dcbda8a 100644 (file)
@@ -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);
index 292ce23..7a64c7a 100644 (file)
@@ -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 *,
index 04ba76f..592eac5 100644 (file)
@@ -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);
 }
index d639751..78bb204 100644 (file)
@@ -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
index 0a9fb94..65a18d4 100644 (file)
@@ -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 */
index d969e7d..3e67af1 100644 (file)
@@ -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;
index dec96c3..111f038 100644 (file)
@@ -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);
index f3d5e23..55e6e79 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/lustre_lite.h>
 #include <linux/lustre_dlm.h>
 #include <linux/lustre_sec.h>
+#include <linux/lustre_acl.h>
 #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:
index 3e5a830..c534173 100644 (file)
@@ -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);
index 363df56..1fa8429 100644 (file)
@@ -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 *,
index 26bc072..bc2d413 100644 (file)
@@ -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));
index c9ddcdc..e7138c2 100644 (file)
@@ -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);
index 66a980e..443f782 100644 (file)
@@ -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)
index 49da01a..3cd91d8 100644 (file)
@@ -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);
index 85f2ef7..04595e6 100644 (file)
@@ -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));
index 6cd50d2..88ec501 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <linux/obd_class.h>
 #include <linux/lustre_mds.h>
+#include <linux/lustre_acl.h>
 #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;
index a4584eb..e062bc5 100644 (file)
@@ -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) {
index 98f9e75..a7278e2 100644 (file)
@@ -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@
index 30d8251..8765df4 100644 (file)
@@ -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);
index f658434..fa8cbe6 100644 (file)
@@ -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(&param, buffer, count)) {
+                CERROR("broken downcall\n");
+                goto do_err_downcall;
+        }
+
+do_downcall:
+        upcall_cache_downcall(cache, param.key, &param);
+        return count;
+
+do_err_downcall:
+        memset(&param, 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 (file)
index 0000000..68eddf0
--- /dev/null
@@ -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 <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/kmod.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/version.h>
+#include <linux/unistd.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <asm/segment.h>
+
+#include <libcfs/list.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
+#include <linux/lustre_mds.h>
+#include <linux/lustre_ucache.h>
+
+#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(&current->fs->lock);
+        mnt = mntget(current->fs->rootmnt);
+        read_unlock(&current->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);
+}
index 5948655..c66c23d 100644 (file)
@@ -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 */
index 0d3e4c2..51c1a24 100644 (file)
@@ -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;
index c3b0dbb..ad4686a 100644 (file)
@@ -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);
index 623fc2e..f4beb73 100644 (file)
@@ -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 (file)
index 0000000..dec19f4
--- /dev/null
@@ -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 <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <liblustre.h>
+#include <linux/lustre_idl.h>
+#include <linux/obd.h>
+#include <linux/lustre_mds.h>
+#include <linux/obd_support.h>
+
+#include <portals/ptlctl.h>
+#include <portals/types.h>
+
+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;
+}
index c84cd07..bd47b63 100755 (executable)
@@ -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
index 1bc3d83..91f8f0e 100644 (file)
@@ -29,6 +29,8 @@
 #include <getopt.h>
 #include <string.h>
 #include <mntent.h>
+#include <dirent.h>
+#include <libgen.h>
 #include <portals/ptlctl.h>
 
 #include <liblustre.h>
@@ -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;
index b7c2a66..bcba4ae 100644 (file)
@@ -52,6 +52,7 @@
 #include <liblustre.h>
 #include <linux/obd.h>
 #include <linux/lustre_lib.h>
+#include <linux/lustre_acl.h>
 #include <lustre/lustre_user.h>
 #include <linux/obd_lov.h>
 
@@ -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);