Whamcloud - gitweb
LU-1304 mdd: changes related to acl
authorAlex Zhuravlev <bzzz@whamcloud.com>
Tue, 4 Sep 2012 15:20:22 +0000 (19:20 +0400)
committerOleg Drokin <green@whamcloud.com>
Mon, 24 Sep 2012 06:16:54 +0000 (02:16 -0400)
ACL/i_mode consistency in maintained within MDD,
so that ACLs functionality do not depend on
OSD indirectly. required for ZFS backend.

Signed-off-by: Alex Zhuravlev <bzzz@whamcloud.com>
Change-Id: I8f20e21734097ee2d962cc487265d6e1d9b3b805
Reviewed-on: http://review.whamcloud.com/3866
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: wangdi <di.wang@whamcloud.com>
Reviewed-by: Fan Yong <yong.fan@whamcloud.com>
lustre/include/lustre_eacl.h
lustre/mdd/mdd_dir.c
lustre/mdd/mdd_internal.h
lustre/mdd/mdd_object.c
lustre/mdd/mdd_permission.c
lustre/obdclass/acl.c

index f7f86f3..2781e39 100644 (file)
@@ -81,6 +81,8 @@ extern int lustre_posix_acl_chmod_masq(posix_acl_xattr_entry *entry,
                                        __u32 mode, int count);
 extern int lustre_posix_acl_create_masq(posix_acl_xattr_entry *entry,
                                         __u32 *pmode, int count);
                                        __u32 mode, int count);
 extern int lustre_posix_acl_create_masq(posix_acl_xattr_entry *entry,
                                         __u32 *pmode, int count);
+extern int lustre_posix_acl_equiv_mode(posix_acl_xattr_entry *entry, mode_t *mode_p,
+                                      int count);
 
 extern ext_acl_xattr_header *
 lustre_posix_acl_xattr_2ext(posix_acl_xattr_header *header, int size);
 
 extern ext_acl_xattr_header *
 lustre_posix_acl_xattr_2ext(posix_acl_xattr_header *header, int size);
index bb76584..69fd1dc 100644 (file)
@@ -1516,9 +1516,11 @@ static int mdd_declare_create(const struct lu_env *env,
                               const struct lu_name *name,
                               struct md_attr *ma,
                               int lmm_size,
                               const struct lu_name *name,
                               struct md_attr *ma,
                               int lmm_size,
+                             int got_def_acl,
                               struct thandle *handle,
                               const struct md_op_spec *spec)
 {
                               struct thandle *handle,
                               const struct md_op_spec *spec)
 {
+       struct mdd_thread_info *info = mdd_env_info(env);
         struct lu_buf *buf = &mdd_env_info(env)->mti_buf;
         int            rc = 0;
 
         struct lu_buf *buf = &mdd_env_info(env)->mti_buf;
         int            rc = 0;
 
@@ -1526,22 +1528,39 @@ static int mdd_declare_create(const struct lu_env *env,
         if (rc)
                 GOTO(out, rc);
 
         if (rc)
                 GOTO(out, rc);
 
+#ifdef CONFIG_FS_POSIX_ACL
+       if (got_def_acl > 0) {
+               struct lu_buf *acl_buf;
+
+               acl_buf = mdd_buf_get(env, NULL, got_def_acl);
+               /* if dir, then can inherit default ACl */
+               if (S_ISDIR(ma->ma_attr.la_mode)) {
+                       rc = mdo_declare_xattr_set(env, c, acl_buf,
+                                                  XATTR_NAME_ACL_DEFAULT,
+                                                  0, handle);
+                       if (rc)
+                               GOTO(out, rc);
+               }
+
+               rc = mdo_declare_attr_set(env, c, &info->mti_pattr, handle);
+               if (rc)
+                       GOTO(out, rc);
+
+               rc = mdo_declare_xattr_set(env, c, acl_buf,
+                                          XATTR_NAME_ACL_ACCESS, 0, handle);
+               if (rc)
+                       GOTO(out, rc);
+       }
+#endif
+
         /* if dir, then can inherit default ACl */
         buf->lb_buf = NULL;
         buf->lb_len = lmm_size;
         /* if dir, then can inherit default ACl */
         buf->lb_buf = NULL;
         buf->lb_len = lmm_size;
-        if (S_ISDIR(ma->ma_attr.la_mode)) {
-                rc = mdo_declare_xattr_set(env, c, buf, XATTR_NAME_ACL_DEFAULT,
-                                           0, handle);
-                if (rc == 0)
-                        rc = mdo_declare_ref_add(env, p, handle);
+       if (S_ISDIR(ma->ma_attr.la_mode)) {
+               rc = mdo_declare_ref_add(env, p, handle);
+               if (rc)
+                       GOTO(out, rc);
         }
         }
-        if (rc)
-                GOTO(out, rc);
-
-        rc = mdo_declare_xattr_set(env, c, buf, XATTR_NAME_ACL_ACCESS,
-                                   0, handle);
-        if (rc)
-                GOTO(out, rc);
 
         rc = mdd_declare_object_initialize(env, c, ma, handle);
         if (rc)
 
         rc = mdd_declare_object_initialize(env, c, ma, handle);
         if (rc)
@@ -1591,7 +1610,6 @@ static int mdd_create(const struct lu_env *env,
 {
         struct mdd_thread_info *info = mdd_env_info(env);
         struct lu_attr         *la = &info->mti_la_for_fix;
 {
         struct mdd_thread_info *info = mdd_env_info(env);
         struct lu_attr         *la = &info->mti_la_for_fix;
-        struct md_attr         *ma_acl = &info->mti_ma;
         struct mdd_object      *mdd_pobj = md2mdd_obj(pobj);
         struct mdd_object      *son = md2mdd_obj(child);
         struct mdd_device      *mdd = mdo2mdd(pobj);
         struct mdd_object      *mdd_pobj = md2mdd_obj(pobj);
         struct mdd_object      *son = md2mdd_obj(child);
         struct mdd_device      *mdd = mdo2mdd(pobj);
@@ -1716,18 +1734,18 @@ static int mdd_create(const struct lu_env *env,
         }
 
         if (!S_ISLNK(attr->la_mode)) {
         }
 
         if (!S_ISLNK(attr->la_mode)) {
-                ma_acl->ma_acl_size = sizeof info->mti_xattr_buf;
-                ma_acl->ma_acl = info->mti_xattr_buf;
-                ma_acl->ma_need = MA_ACL_DEF;
-                ma_acl->ma_valid = 0;
+               struct lu_buf *acl_buf;
 
 
+               acl_buf = mdd_buf_get(env, info->mti_xattr_buf,
+                               sizeof(info->mti_xattr_buf));
                 mdd_read_lock(env, mdd_pobj, MOR_TGT_PARENT);
                 mdd_read_lock(env, mdd_pobj, MOR_TGT_PARENT);
-                rc = mdd_def_acl_get(env, mdd_pobj, ma_acl);
+               rc = mdo_xattr_get(env, mdd_pobj, acl_buf,
+                               XATTR_NAME_ACL_DEFAULT, BYPASS_CAPA);
                 mdd_read_unlock(env, mdd_pobj);
                 mdd_read_unlock(env, mdd_pobj);
-                if (rc)
-                        GOTO(out_free, rc);
-                else if (ma_acl->ma_valid & MA_ACL_DEF)
-                        got_def_acl = 1;
+               if (rc > 0)
+                       got_def_acl = rc;
+               else if (rc < 0 && rc != -EOPNOTSUPP && rc != -ENODATA)
+                       GOTO(out_free, rc);
         }
 
        mdd_object_make_hint(env, mdd_pobj, son, attr);
         }
 
        mdd_object_make_hint(env, mdd_pobj, son, attr);
@@ -1737,7 +1755,7 @@ static int mdd_create(const struct lu_env *env,
                 GOTO(out_free, rc = PTR_ERR(handle));
 
         rc = mdd_declare_create(env, mdd, mdd_pobj, son, lname, ma,
                 GOTO(out_free, rc = PTR_ERR(handle));
 
         rc = mdd_declare_create(env, mdd, mdd_pobj, son, lname, ma,
-                                lmm_size, handle, spec);
+                               got_def_acl, lmm_size, handle, spec);
         if (rc)
                 GOTO(out_stop, rc);
 
         if (rc)
                 GOTO(out_stop, rc);
 
@@ -1760,17 +1778,14 @@ static int mdd_create(const struct lu_env *env,
 
 #ifdef CONFIG_FS_POSIX_ACL
         if (got_def_acl) {
 
 #ifdef CONFIG_FS_POSIX_ACL
         if (got_def_acl) {
-                struct lu_buf *acl_buf = &info->mti_buf;
-                acl_buf->lb_buf = ma_acl->ma_acl;
-                acl_buf->lb_len = ma_acl->ma_acl_size;
+               struct lu_buf *acl_buf;
 
 
-                rc = __mdd_acl_init(env, son, acl_buf, &attr->la_mode, handle);
-                if (rc) {
-                        mdd_write_unlock(env, son);
-                        GOTO(cleanup, rc);
-                } else {
-                        ma->ma_attr.la_valid |= LA_MODE;
-                }
+               acl_buf = mdd_buf_get(env, info->mti_xattr_buf, got_def_acl);
+               rc = __mdd_acl_init(env, son, acl_buf, &attr->la_mode, handle);
+               if (rc) {
+                       mdd_write_unlock(env, son);
+                       GOTO(cleanup, rc);
+               }
         }
 #endif
 
         }
 #endif
 
index 5a03b8c..09de0a1 100644 (file)
@@ -183,6 +183,8 @@ struct mdd_thread_info {
        /* mti_orph_ent and mti_orph_key must be conjoint,
         * then mti_orph_ent::lde_name will be mti_orph_key. */
        struct lu_dirent          mti_orph_ent;
        /* mti_orph_ent and mti_orph_key must be conjoint,
         * then mti_orph_ent::lde_name will be mti_orph_key. */
        struct lu_dirent          mti_orph_ent;
+       struct lu_attr            mti_pattr;
+       struct lu_attr            mti_cattr;
         char                      mti_orph_key[NAME_MAX + 1];
         struct obd_trans_info     mti_oti;
         struct lu_buf             mti_buf;
         char                      mti_orph_key[NAME_MAX + 1];
         struct obd_trans_info     mti_oti;
         struct lu_buf             mti_buf;
@@ -515,6 +517,8 @@ int mdd_acl_chmod(const struct lu_env *env, struct mdd_object *o, __u32 mode,
                   struct thandle *handle);
 int __mdd_declare_acl_init(const struct lu_env *env, struct mdd_object *obj,
                            int is_dir, struct thandle *handle);
                   struct thandle *handle);
 int __mdd_declare_acl_init(const struct lu_env *env, struct mdd_object *obj,
                            int is_dir, struct thandle *handle);
+int mdd_acl_set(const struct lu_env *env, struct mdd_object *obj,
+               const struct lu_buf *buf, int fl);
 int __mdd_acl_init(const struct lu_env *env, struct mdd_object *obj,
                    struct lu_buf *buf, __u32 *mode, struct thandle *handle);
 int __mdd_permission_internal(const struct lu_env *env, struct mdd_object *obj,
 int __mdd_acl_init(const struct lu_env *env, struct mdd_object *obj,
                    struct lu_buf *buf, __u32 *mode, struct thandle *handle);
 int __mdd_permission_internal(const struct lu_env *env, struct mdd_object *obj,
index f15697f..9aa7170 100644 (file)
@@ -1864,6 +1864,11 @@ static int mdd_xattr_set(const struct lu_env *env, struct md_object *obj,
         int  rc;
         ENTRY;
 
         int  rc;
         ENTRY;
 
+       if (!strcmp(name, XATTR_NAME_ACL_ACCESS)) {
+               rc = mdd_acl_set(env, mdd_obj, buf, fl);
+               RETURN(rc);
+       }
+
         rc = mdd_xattr_sanity_check(env, mdd_obj);
         if (rc)
                 RETURN(rc);
         rc = mdd_xattr_sanity_check(env, mdd_obj);
         if (rc)
                 RETURN(rc);
index 21e1659..1f3ba34 100644 (file)
@@ -81,40 +81,121 @@ int mdd_def_acl_get(const struct lu_env *env, struct mdd_object *mdd_obj,
  * Hold write_lock for o.
  */
 int mdd_acl_chmod(const struct lu_env *env, struct mdd_object *o, __u32 mode,
  * Hold write_lock for o.
  */
 int mdd_acl_chmod(const struct lu_env *env, struct mdd_object *o, __u32 mode,
-                  struct thandle *handle)
+                 struct thandle *handle)
 {
 {
-        struct lu_buf           *buf;
-        posix_acl_xattr_header  *head;
-        posix_acl_xattr_entry   *entry;
-        int                      entry_count;
-        int                      rc;
-
-        ENTRY;
-
-        buf = mdd_buf_get(env, mdd_env_info(env)->mti_xattr_buf,
-                          sizeof(mdd_env_info(env)->mti_xattr_buf));
-
-        rc = mdo_xattr_get(env, o, buf, XATTR_NAME_ACL_ACCESS, BYPASS_CAPA);
-        if ((rc == -EOPNOTSUPP) || (rc == -ENODATA))
-                RETURN(0);
-        else if (rc <= 0)
-                RETURN(rc);
-
-        buf->lb_len = rc;
-        head = (posix_acl_xattr_header *)(buf->lb_buf);
-        entry = head->a_entries;
-        entry_count = (buf->lb_len - sizeof(head->a_version)) /
-                      sizeof(posix_acl_xattr_entry);
-        if (entry_count <= 0)
-                RETURN(0);
-
-        rc = lustre_posix_acl_chmod_masq(entry, mode, entry_count);
-        if (rc)
-                RETURN(rc);
+       struct lu_buf           *buf;
+       posix_acl_xattr_header  *head;
+       posix_acl_xattr_entry   *entry;
+       int                      entry_count;
+       int                      rc;
+
+       ENTRY;
+
+       buf = mdd_buf_get(env, mdd_env_info(env)->mti_xattr_buf,
+                         sizeof(mdd_env_info(env)->mti_xattr_buf));
+
+       rc = mdo_xattr_get(env, o, buf, XATTR_NAME_ACL_ACCESS, BYPASS_CAPA);
+       if ((rc == -EOPNOTSUPP) || (rc == -ENODATA))
+               RETURN(0);
+       else if (rc <= 0)
+               RETURN(rc);
+
+       buf->lb_len = rc;
+       head = (posix_acl_xattr_header *)(buf->lb_buf);
+       entry = head->a_entries;
+       entry_count = (buf->lb_len - sizeof(head->a_version)) /
+               sizeof(posix_acl_xattr_entry);
+       if (entry_count <= 0)
+               RETURN(0);
+
+       rc = lustre_posix_acl_chmod_masq(entry, mode, entry_count);
+       if (rc)
+               RETURN(rc);
+
+       rc = mdo_xattr_set(env, o, buf, XATTR_NAME_ACL_ACCESS,
+                          0, handle, BYPASS_CAPA);
+       RETURN(rc);
+}
 
 
-        rc = mdo_xattr_set(env, o, buf, XATTR_NAME_ACL_ACCESS,
-                           0, handle, BYPASS_CAPA);
-        RETURN(rc);
+int mdd_acl_set(const struct lu_env *env, struct mdd_object *obj,
+               const struct lu_buf *buf, int fl)
+{
+       struct mdd_device       *mdd = mdd_obj2mdd_dev(obj);
+       struct lu_attr          *la = &mdd_env_info(env)->mti_la;
+       struct thandle          *handle;
+       posix_acl_xattr_header  *head;
+       posix_acl_xattr_entry   *entry;
+       int                      rc, entry_count;
+       bool                     not_equiv, mode_change;
+       mode_t                   mode;
+       ENTRY;
+
+       rc = mdd_la_get(env, obj, la, BYPASS_CAPA);
+       if (rc)
+               RETURN(rc);
+
+       head = (posix_acl_xattr_header *)(buf->lb_buf);
+       entry = head->a_entries;
+       entry_count = (buf->lb_len - sizeof(head->a_version)) /
+               sizeof(posix_acl_xattr_entry);
+       if (entry_count <= 0)
+               RETURN(0);
+
+       LASSERT(la->la_valid & LA_MODE);
+       mode = la->la_mode;
+       rc = lustre_posix_acl_equiv_mode(entry, &mode, entry_count);
+       if (rc < 0)
+               RETURN(rc);
+
+       not_equiv = (rc > 0);
+       mode_change = (mode != la->la_mode);
+
+       handle = mdd_trans_create(env, mdd);
+       if (IS_ERR(handle))
+               RETURN(PTR_ERR(handle));
+
+       /* rc tells whether ACL can be represented by i_mode only */
+       if (not_equiv)
+               rc = mdo_declare_xattr_set(env, obj, buf,
+                               XATTR_NAME_ACL_ACCESS, fl, handle);
+       else
+               rc = mdo_declare_xattr_del(env, obj, XATTR_NAME_ACL_ACCESS,
+                               handle);
+       if (rc)
+               GOTO(stop, rc);
+
+       if (mode_change) {
+               la->la_mode = mode;
+               rc = mdo_declare_attr_set(env, obj, la, handle);
+       }
+
+       rc = mdd_trans_start(env, mdd, handle);
+       if (rc)
+               GOTO(stop, rc);
+
+       mdd_write_lock(env, obj, MOR_TGT_CHILD);
+       /* whether ACL can be represented by i_mode only */
+       if (not_equiv)
+               rc = mdo_xattr_set(env, obj, buf, XATTR_NAME_ACL_ACCESS, fl,
+                               handle, mdd_object_capa(env, obj));
+       else
+               rc = mdo_xattr_del(env, obj, XATTR_NAME_ACL_ACCESS, handle,
+                               mdd_object_capa(env, obj));
+       if (rc)
+               GOTO(unlock, rc);
+
+       if (mode_change)
+               rc = mdo_attr_set(env, obj, la, handle,
+                               mdd_object_capa(env, obj));
+
+       /* security-replated changes may require sync */
+       handle->th_sync |= !!mdd->mdd_sync_permission;
+unlock:
+       mdd_write_unlock(env, obj);
+stop:
+       mdd_trans_stop(env, mdd, rc, handle);
+
+       RETURN(rc);
 }
 
 /*
 }
 
 /*
@@ -126,7 +207,8 @@ int __mdd_acl_init(const struct lu_env *env, struct mdd_object *obj,
         posix_acl_xattr_header  *head;
         posix_acl_xattr_entry   *entry;
         int                      entry_count;
         posix_acl_xattr_header  *head;
         posix_acl_xattr_entry   *entry;
         int                      entry_count;
-        int                      rc;
+       __u32                    old = *mode;
+       int                      rc, rc2;
 
         ENTRY;
 
 
         ENTRY;
 
@@ -145,12 +227,27 @@ int __mdd_acl_init(const struct lu_env *env, struct mdd_object *obj,
         }
 
         rc = lustre_posix_acl_create_masq(entry, mode, entry_count);
         }
 
         rc = lustre_posix_acl_create_masq(entry, mode, entry_count);
-        if (rc <= 0)
+       if (rc < 0)
                 RETURN(rc);
 
                 RETURN(rc);
 
-        rc = mdo_xattr_set(env, obj, buf, XATTR_NAME_ACL_ACCESS, 0, handle,
-                           BYPASS_CAPA);
-        RETURN(rc);
+       /* part of ACL went into i_mode */
+       if (*mode != old) {
+               struct mdd_thread_info  *info = mdd_env_info(env);
+               struct lu_attr          *pattr = &info->mti_pattr;
+
+               /* mode was initialized within object creation,
+                * so we need explict ->attr_set() to update it */
+               pattr->la_valid = LA_MODE;
+               pattr->la_mode = *mode;
+               rc2 = mdo_attr_set(env, obj, pattr, handle, BYPASS_CAPA);
+               if (rc2 < 0)
+                       rc = rc2;
+       }
+
+       if (rc > 0)
+               rc = mdo_xattr_set(env, obj, buf, XATTR_NAME_ACL_ACCESS, 0,
+                                  handle, BYPASS_CAPA);
+       RETURN(rc);
 }
 #endif
 
 }
 #endif
 
index b48acf8..7adbd59 100644 (file)
@@ -205,6 +205,49 @@ int lustre_posix_acl_chmod_masq(posix_acl_xattr_entry *entry, __u32 mode,
 EXPORT_SYMBOL(lustre_posix_acl_chmod_masq);
 
 /*
 EXPORT_SYMBOL(lustre_posix_acl_chmod_masq);
 
 /*
+ * Returns 0 if the acl can be exactly represented in the traditional
+ * file mode permission bits, or else 1. Returns -E... on error.
+ */
+       int
+lustre_posix_acl_equiv_mode(posix_acl_xattr_entry *entry, mode_t *mode_p,
+               int count)
+{
+       posix_acl_xattr_entry *pa, *pe;
+       mode_t                 mode = 0;
+       int                    not_equiv = 0;
+
+       for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
+               __u16 perm = le16_to_cpu(pa->e_perm);
+               switch (le16_to_cpu(pa->e_tag)) {
+                       case ACL_USER_OBJ:
+                               mode |= (perm & S_IRWXO) << 6;
+                               break;
+                       case ACL_GROUP_OBJ:
+                               mode |= (perm & S_IRWXO) << 3;
+                               break;
+                       case ACL_OTHER:
+                               mode |= perm & S_IRWXO;
+                               break;
+                       case ACL_MASK:
+                               mode = (mode & ~S_IRWXG) |
+                                       ((perm & S_IRWXO) << 3);
+                               not_equiv = 1;
+                               break;
+                       case ACL_USER:
+                       case ACL_GROUP:
+                               not_equiv = 1;
+                               break;
+                       default:
+                               return -EINVAL;
+               }
+       }
+       if (mode_p)
+               *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
+       return not_equiv;
+}
+EXPORT_SYMBOL(lustre_posix_acl_equiv_mode);
+
+/*
  * Modify acl when creating a new object.
  */
 int lustre_posix_acl_create_masq(posix_acl_xattr_entry *entry, __u32 *pmode,
  * Modify acl when creating a new object.
  */
 int lustre_posix_acl_create_masq(posix_acl_xattr_entry *entry, __u32 *pmode,