Whamcloud - gitweb
LU-4703 mdd: do not skip xattr sanity check for all cases
[fs/lustre-release.git] / lustre / mdd / mdd_object.c
index 891628c..b44f6f1 100644 (file)
@@ -49,7 +49,6 @@
 #include <lprocfs_status.h>
 /* fid_be_cpu(), fid_cpu_to_be(). */
 #include <lustre_fid.h>
-#include <obd_lov.h>
 #include <lustre_idmap.h>
 #include <lustre_param.h>
 #include <lustre_mds.h>
@@ -88,7 +87,7 @@ int mdd_la_get(const struct lu_env *env, struct mdd_object *obj,
         return mdo_attr_get(env, obj, la, capa);
 }
 
-static void mdd_flags_xlate(struct mdd_object *obj, __u32 flags)
+void mdd_flags_xlate(struct mdd_object *obj, __u32 flags)
 {
         obj->mod_flags &= ~(APPEND_OBJ|IMMUTE_OBJ);
 
@@ -142,25 +141,25 @@ const struct lu_buf *mdd_buf_get_const(const struct lu_env *env,
 }
 
 struct lu_object *mdd_object_alloc(const struct lu_env *env,
-                                   const struct lu_object_header *hdr,
-                                   struct lu_device *d)
+                                  const struct lu_object_header *hdr,
+                                  struct lu_device *d)
 {
-        struct mdd_object *mdd_obj;
-
-       OBD_SLAB_ALLOC_PTR_GFP(mdd_obj, mdd_object_kmem, __GFP_IO);
-        if (mdd_obj != NULL) {
-                struct lu_object *o;
-
-                o = mdd2lu_obj(mdd_obj);
-                lu_object_init(o, NULL, d);
-                mdd_obj->mod_obj.mo_ops = &mdd_obj_ops;
-                mdd_obj->mod_obj.mo_dir_ops = &mdd_dir_ops;
-                mdd_obj->mod_count = 0;
-                o->lo_ops = &mdd_lu_obj_ops;
-                return o;
-        } else {
-                return NULL;
-        }
+       struct mdd_object *mdd_obj;
+
+       OBD_SLAB_ALLOC_PTR_GFP(mdd_obj, mdd_object_kmem, GFP_NOFS);
+       if (mdd_obj != NULL) {
+               struct lu_object *o;
+
+               o = mdd2lu_obj(mdd_obj);
+               lu_object_init(o, NULL, d);
+               mdd_obj->mod_obj.mo_ops = &mdd_obj_ops;
+               mdd_obj->mod_obj.mo_dir_ops = &mdd_dir_ops;
+               mdd_obj->mod_count = 0;
+               o->lo_ops = &mdd_lu_obj_ops;
+               return o;
+       } else {
+               return NULL;
+       }
 }
 
 static int mdd_object_init(const struct lu_env *env, struct lu_object *o,
@@ -189,7 +188,7 @@ static int mdd_object_start(const struct lu_env *env, struct lu_object *o)
 
        if (lu_object_exists(o)) {
                struct mdd_object *mdd_obj = lu2mdd_obj(o);
-               struct lu_attr *attr = MDD_ENV_VAR(env, cattr);
+               struct lu_attr *attr = MDD_ENV_VAR(env, la_for_start);
 
                rc = mdd_la_get(env, mdd_obj, attr, BYPASS_CAPA);
                if (rc == 0)
@@ -286,8 +285,8 @@ static int mdd_xattr_get(const struct lu_env *env,
  * Permission check is done when open,
  * no need check again.
  */
-static int mdd_readlink(const struct lu_env *env, struct md_object *obj,
-                        struct lu_buf *buf)
+int mdd_readlink(const struct lu_env *env, struct md_object *obj,
+                struct lu_buf *buf)
 {
         struct mdd_object *mdd_obj = md2mdd_obj(obj);
         struct dt_object  *next;
@@ -302,7 +301,10 @@ static int mdd_readlink(const struct lu_env *env, struct md_object *obj,
         }
 
         next = mdd_object_child(mdd_obj);
-        mdd_read_lock(env, mdd_obj, MOR_TGT_CHILD);
+       LASSERT(next != NULL);
+       LASSERT(next->do_body_ops != NULL);
+       LASSERT(next->do_body_ops->dbo_read != NULL);
+       mdd_read_lock(env, mdd_obj, MOR_TGT_CHILD);
         rc = next->do_body_ops->dbo_read(env, next, buf, &pos,
                                          mdd_object_capa(env, mdd_obj));
         mdd_read_unlock(env, mdd_obj);
@@ -332,10 +334,10 @@ int mdd_declare_object_create_internal(const struct lu_env *env,
                                       struct mdd_object *c,
                                       struct lu_attr *attr,
                                       struct thandle *handle,
-                                      const struct md_op_spec *spec)
+                                      const struct md_op_spec *spec,
+                                      struct dt_allocation_hint *hint)
 {
         struct dt_object_format *dof = &mdd_env_info(env)->mti_dof;
-       struct dt_allocation_hint *hint = &mdd_env_info(env)->mti_hint;
         const struct dt_index_features *feat = spec->sp_feat;
         int rc;
         ENTRY;
@@ -364,10 +366,10 @@ int mdd_declare_object_create_internal(const struct lu_env *env,
 
 int mdd_object_create_internal(const struct lu_env *env, struct mdd_object *p,
                               struct mdd_object *c, struct lu_attr *attr,
-                               struct thandle *handle,
-                               const struct md_op_spec *spec)
+                              struct thandle *handle,
+                              const struct md_op_spec *spec,
+                              struct dt_allocation_hint *hint)
 {
-        struct dt_allocation_hint *hint = &mdd_env_info(env)->mti_hint;
         struct dt_object_format *dof = &mdd_env_info(env)->mti_dof;
         int rc;
         ENTRY;
@@ -888,20 +890,24 @@ int mdd_attr_set(const struct lu_env *env, struct md_object *obj,
                 CDEBUG(D_INODE, "setting mtime "LPU64", ctime "LPU64"\n",
                       la->la_mtime, la->la_ctime);
 
-        if (la_copy->la_valid & LA_FLAGS) {
+       mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
+       if (la_copy->la_valid & LA_FLAGS) {
                rc = mdd_attr_set_internal(env, mdd_obj, la_copy, handle, 1);
-                if (rc == 0)
-                        mdd_flags_xlate(mdd_obj, la_copy->la_flags);
-        } else if (la_copy->la_valid) {            /* setattr */
+               if (rc == 0)
+                       mdd_flags_xlate(mdd_obj, la_copy->la_flags);
+       } else if (la_copy->la_valid) { /* setattr */
                rc = mdd_attr_set_internal(env, mdd_obj, la_copy, handle, 1);
-        }
+       }
+       mdd_write_unlock(env, mdd_obj);
+
+       if (rc == 0)
+               rc = mdd_attr_set_changelog(env, obj, handle, la->la_valid);
+
+       GOTO(stop, rc);
 
-        if (rc == 0)
-                rc = mdd_attr_set_changelog(env, obj, handle,
-                                           la->la_valid);
 stop:
-        mdd_trans_stop(env, mdd, rc, handle);
-        RETURN(rc);
+       mdd_trans_stop(env, mdd, rc, handle);
+       return rc;
 }
 
 static int mdd_xattr_sanity_check(const struct lu_env *env,
@@ -936,15 +942,14 @@ static int mdd_declare_xattr_set(const struct lu_env *env,
        /* Only record user and layout xattr changes */
        if (strncmp(XATTR_USER_PREFIX, name,
                    sizeof(XATTR_USER_PREFIX) - 1) == 0 ||
-           strncmp(XATTR_NAME_LOV, name,
-                   sizeof(XATTR_NAME_LOV) - 1) == 0) {
+           strcmp(XATTR_NAME_LOV, name) == 0) {
                rc = mdd_declare_changelog_store(env, mdd, NULL, handle);
                if (rc)
                        return rc;
        }
 
        /* If HSM data is modified, this could add a changelog */
-       if (strncmp(XATTR_NAME_HSM, name, sizeof(XATTR_NAME_HSM) - 1) == 0) {
+       if (strcmp(XATTR_NAME_HSM, name) == 0) {
                rc = mdd_declare_changelog_store(env, mdd, NULL, handle);
                if (rc)
                        return rc;
@@ -1036,15 +1041,15 @@ static int mdd_xattr_set(const struct lu_env *env, struct md_object *obj,
        if (rc)
                RETURN(rc);
 
+       rc = mdd_xattr_sanity_check(env, mdd_obj, attr);
+       if (rc)
+               RETURN(rc);
+
        if (!strcmp(name, XATTR_NAME_ACL_ACCESS)) {
                rc = mdd_acl_set(env, mdd_obj, attr, buf, fl);
                RETURN(rc);
        }
 
-       rc = mdd_xattr_sanity_check(env, mdd_obj, attr);
-       if (rc)
-               RETURN(rc);
-
        handle = mdd_trans_create(env, mdd);
        if (IS_ERR(handle))
                RETURN(PTR_ERR(handle));
@@ -1059,7 +1064,7 @@ static int mdd_xattr_set(const struct lu_env *env, struct md_object *obj,
 
        mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
 
-       if (strncmp(XATTR_NAME_HSM, name, sizeof(XATTR_NAME_HSM) - 1) == 0) {
+       if (strcmp(XATTR_NAME_HSM, name) == 0) {
                rc = mdd_hsm_update_locked(env, obj, buf, handle);
                if (rc) {
                        mdd_write_unlock(env, mdd_obj);
@@ -1073,7 +1078,7 @@ static int mdd_xattr_set(const struct lu_env *env, struct md_object *obj,
        if (rc)
                GOTO(stop, rc);
 
-       if (strncmp(XATTR_NAME_LOV, name, sizeof(XATTR_NAME_LOV) - 1) == 0)
+       if (strcmp(XATTR_NAME_LOV, name) == 0)
                rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, mdd_obj,
                                              handle);
        else if (strncmp(XATTR_USER_PREFIX, name,
@@ -1097,17 +1102,18 @@ static int mdd_declare_xattr_del(const struct lu_env *env,
                                  const char *name,
                                  struct thandle *handle)
 {
-        int rc;
+       int rc;
 
-        rc = mdo_declare_xattr_del(env, obj, name, handle);
-        if (rc)
-                return rc;
+       rc = mdo_declare_xattr_del(env, obj, name, handle);
+       if (rc)
+               return rc;
 
-        /* Only record user xattr changes */
-        if ((strncmp("user.", name, 5) == 0))
-                rc = mdd_declare_changelog_store(env, mdd, NULL, handle);
+       /* Only record user xattr changes */
+       if ((strncmp(XATTR_USER_PREFIX, name,
+                    sizeof(XATTR_USER_PREFIX) - 1) == 0))
+               rc = mdd_declare_changelog_store(env, mdd, NULL, handle);
 
-        return rc;
+       return rc;
 }
 
 /**
@@ -1171,12 +1177,11 @@ stop:
  * read lov EA of an object
  * return the lov EA in an allocated lu_buf
  */
-static int mdd_get_lov_ea(const struct lu_env *env,
-                         struct mdd_object *obj,
-                         struct lu_buf *lmm_buf)
+int mdd_get_lov_ea(const struct lu_env *env, struct mdd_object *obj,
+                  struct lu_buf *lmm_buf)
 {
        struct lu_buf   *buf = &mdd_env_info(env)->mti_big_buf;
-       int              rc, sz;
+       int              rc, bufsize;
        ENTRY;
 
 repeat:
@@ -1194,27 +1199,27 @@ repeat:
        }
 
        if (rc < 0)
-               GOTO(out, rc);
+               RETURN(rc);
 
        if (rc == 0)
-               GOTO(out, rc = -ENODATA);
+               RETURN(-ENODATA);
 
-       sz = rc;
+       bufsize = rc;
        if (memcmp(buf, &LU_BUF_NULL, sizeof(*buf)) == 0) {
                /* mti_big_buf was not allocated, so we have to
                 * allocate it based on the ea size */
                buf = lu_buf_check_and_alloc(&mdd_env_info(env)->mti_big_buf,
-                                            sz);
+                                            bufsize);
                if (buf->lb_buf == NULL)
                        GOTO(out, rc = -ENOMEM);
                goto repeat;
        }
 
-       lu_buf_alloc(lmm_buf, sz);
+       lu_buf_alloc(lmm_buf, bufsize);
        if (lmm_buf->lb_buf == NULL)
                GOTO(out, rc = -ENOMEM);
 
-       memcpy(lmm_buf->lb_buf, buf->lb_buf, sz);
+       memcpy(lmm_buf->lb_buf, buf->lb_buf, bufsize);
        rc = 0;
        EXIT;
 
@@ -1254,6 +1259,7 @@ static int mdd_xattr_hsm_replace(const struct lu_env *env,
 /*
  *  check if layout swapping between 2 objects is allowed
  *  the rules are:
+ *  - only normal FIDs or non-system IGIFs
  *  - same type of objects
  *  - same owner/group (so quotas are still valid)
  */
@@ -1269,9 +1275,21 @@ static int mdd_layout_swap_allowed(const struct lu_env *env,
        fid1 = mdo2fid(o1);
        fid2 = mdo2fid(o2);
 
-       if (!fid_is_norm(fid1) || !fid_is_norm(fid2) ||
-           (mdd_object_type(o1) != mdd_object_type(o2)))
-               RETURN(-EPERM);
+       if (!fid_is_norm(fid1) &&
+           (!fid_is_igif(fid1) || IS_ERR(mdd_links_get(env, o1))))
+               RETURN(-EBADF);
+
+       if (!fid_is_norm(fid2) &&
+           (!fid_is_igif(fid2) || IS_ERR(mdd_links_get(env, o2))))
+               RETURN(-EBADF);
+
+       if (mdd_object_type(o1) != mdd_object_type(o2)) {
+               if (S_ISDIR(mdd_object_type(o1)))
+                       RETURN(-ENOTDIR);
+               if (S_ISREG(mdd_object_type(o1)))
+                       RETURN(-EISDIR);
+               RETURN(-EBADF);
+       }
 
        if ((attr1->la_uid != attr2->la_uid) ||
            (attr1->la_gid != attr2->la_gid))
@@ -1546,12 +1564,28 @@ stop:
 }
 
 void mdd_object_make_hint(const struct lu_env *env, struct mdd_object *parent,
-               struct mdd_object *child, struct lu_attr *attr)
+                         struct mdd_object *child, const struct lu_attr *attr,
+                         const struct md_op_spec *spec,
+                         struct dt_allocation_hint *hint)
 {
-       struct dt_allocation_hint *hint = &mdd_env_info(env)->mti_hint;
-       struct dt_object *np = parent ? mdd_object_child(parent) : NULL;
+       struct dt_object *np = parent ?  mdd_object_child(parent) : NULL;
        struct dt_object *nc = mdd_object_child(child);
 
+       memset(hint, 0, sizeof(*hint));
+
+       /* For striped directory, give striping EA to lod_ah_init, which will
+        * decide the stripe_offset and stripe count by it. */
+       if (S_ISDIR(attr->la_mode) &&
+           unlikely(spec != NULL && spec->sp_cr_flags & MDS_OPEN_HAS_EA)) {
+               hint->dah_eadata = spec->u.sp_ea.eadata;
+               hint->dah_eadata_len = spec->u.sp_ea.eadatalen;
+       } else {
+               hint->dah_eadata = NULL;
+               hint->dah_eadata_len = 0;
+       }
+
+       CDEBUG(D_INFO, DFID" eadata %p len %d\n", PFID(mdd_object_fid(child)),
+              hint->dah_eadata, hint->dah_eadata_len);
        /* @hint will be initialized by underlying device. */
        nc->do_ops->do_ah_init(env, hint, np, nc, attr->la_mode & S_IFMT);
 }
@@ -2006,13 +2040,22 @@ static int mdd_object_lock(const struct lu_env *env,
                           struct md_object *obj,
                           struct lustre_handle *lh,
                           struct ldlm_enqueue_info *einfo,
-                          void *policy)
+                          ldlm_policy_data_t *policy)
 {
        struct mdd_object *mdd_obj = md2mdd_obj(obj);
        return dt_object_lock(env, mdd_object_child(mdd_obj), lh,
                              einfo, policy);
 }
 
+static int mdd_object_unlock(const struct lu_env *env,
+                            struct md_object *obj,
+                            struct ldlm_enqueue_info *einfo,
+                            ldlm_policy_data_t *policy)
+{
+       struct mdd_object *mdd_obj = md2mdd_obj(obj);
+       return dt_object_unlock(env, mdd_object_child(mdd_obj), einfo, policy);
+}
+
 const struct md_object_operations mdd_obj_ops = {
        .moo_permission         = mdd_permission,
        .moo_attr_get           = mdd_attr_get,
@@ -2030,4 +2073,5 @@ const struct md_object_operations mdd_obj_ops = {
        .moo_capa_get           = mdd_capa_get,
        .moo_object_sync        = mdd_object_sync,
        .moo_object_lock        = mdd_object_lock,
+       .moo_object_unlock      = mdd_object_unlock,
 };