Whamcloud - gitweb
LU-4870 lfsck: lock old MDT-object in migrating
[fs/lustre-release.git] / lustre / mdd / mdd_dir.c
index bccc16d..6344e40 100644 (file)
@@ -27,7 +27,7 @@
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2013, Intel Corporation.
+ * Copyright (c) 2011, 2014, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -119,7 +119,8 @@ int mdd_lookup(const struct lu_env *env,
        if (rc != 0)
                RETURN(rc);
 
-       rc = __mdd_lookup(env, pobj, pattr, lname, fid, MAY_EXEC);
+       rc = __mdd_lookup(env, pobj, pattr, lname, fid,
+                         (spec != NULL && spec->sp_permitted) ? 0 : MAY_EXEC);
         RETURN(rc);
 }
 
@@ -380,17 +381,16 @@ int mdd_may_unlink(const struct lu_env *env, struct mdd_object *pobj,
        if (mdd_is_dead_obj(pobj))
                RETURN(-ENOENT);
 
-       if ((attr->la_valid & LA_FLAGS) &&
-           (attr->la_flags & (LUSTRE_APPEND_FL | LUSTRE_IMMUTABLE_FL)))
+       if (attr->la_flags & (LUSTRE_APPEND_FL | LUSTRE_IMMUTABLE_FL))
                RETURN(-EPERM);
 
        rc = mdd_permission_internal_locked(env, pobj, pattr,
                                            MAY_WRITE | MAY_EXEC,
                                            MOR_TGT_PARENT);
-       if (rc)
+       if (rc != 0)
                RETURN(rc);
 
-       if (mdd_is_append(pobj))
+       if (pattr->la_flags & LUSTRE_APPEND_FL)
                RETURN(-EPERM);
 
        RETURN(rc);
@@ -445,7 +445,7 @@ static int mdd_may_delete_entry(const struct lu_env *env,
                        RETURN(rc);
        }
 
-       if (mdd_is_append(pobj))
+       if (pattr->la_flags & LUSTRE_APPEND_FL)
                RETURN(-EPERM);
 
        RETURN(0);
@@ -482,11 +482,7 @@ int mdd_may_delete(const struct lu_env *env, struct mdd_object *tpobj,
        if (mdd_is_sticky(env, tpobj, tpattr, tobj, tattr))
                RETURN(-EPERM);
 
-       if (mdd_is_immutable(tobj) || mdd_is_append(tobj))
-               RETURN(-EPERM);
-
-       if ((tattr->la_valid & LA_FLAGS) &&
-           (tattr->la_flags & (LUSTRE_APPEND_FL | LUSTRE_IMMUTABLE_FL)))
+       if (tattr->la_flags & (LUSTRE_APPEND_FL | LUSTRE_IMMUTABLE_FL))
                RETURN(-EPERM);
 
        /* additional check the rename case */
@@ -546,11 +542,11 @@ static int mdd_link_sanity_check(const struct lu_env *env,
        if (rc < 0)
                RETURN(rc);
 
-        if (mdd_is_immutable(src_obj) || mdd_is_append(src_obj))
-                RETURN(-EPERM);
+       if (cattr->la_flags & (LUSTRE_IMMUTABLE_FL | LUSTRE_APPEND_FL))
+               RETURN(-EPERM);
 
-        if (S_ISDIR(mdd_object_type(src_obj)))
-                RETURN(-EPERM);
+       if (S_ISDIR(mdd_object_type(src_obj)))
+               RETURN(-EPERM);
 
        LASSERT(src_obj != tgt_obj);
        rc = mdd_may_create(env, tgt_obj, tattr, NULL, true);
@@ -1101,7 +1097,7 @@ int mdd_links_read(const struct lu_env *env, struct mdd_object *mdd_obj,
 struct lu_buf *mdd_links_get(const struct lu_env *env,
                             struct mdd_object *mdd_obj)
 {
-       struct linkea_data ldata = { 0 };
+       struct linkea_data ldata = { NULL };
        int rc;
 
        rc = mdd_links_read(env, mdd_obj, &ldata);
@@ -1113,16 +1109,35 @@ int mdd_links_write(const struct lu_env *env, struct mdd_object *mdd_obj,
 {
        const struct lu_buf *buf = mdd_buf_get_const(env, ldata->ld_buf->lb_buf,
                                                     ldata->ld_leh->leh_len);
+       int                 rc;
 
        if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_NO_LINKEA))
                return 0;
 
-       return mdo_xattr_set(env, mdd_obj, buf, XATTR_NAME_LINK, 0, handle,
-                            mdd_object_capa(env, mdd_obj));
+       rc = mdo_xattr_set(env, mdd_obj, buf, XATTR_NAME_LINK, 0, handle,
+                          mdd_object_capa(env, mdd_obj));
+       if (unlikely(rc == -ENOSPC) && S_ISREG(mdd_object_type(mdd_obj)) &&
+           mdd_object_remote(mdd_obj) == 0) {
+               struct lfsck_request *lr = &mdd_env_info(env)->mti_lr;
+
+               /* XXX: If the linkEA is overflow, then we need to notify the
+                *      namespace LFSCK to skip "nlink" attribute verification
+                *      on this object to avoid the "nlink" to be shrinked by
+                *      wrong. It may be not good an interaction with LFSCK
+                *      like this. We will consider to replace it with other
+                *      mechanism in future. LU-5802. */
+               lfsck_pack_rfa(lr, mdo2fid(mdd_obj), LE_SKIP_NLINK,
+                              LFSCK_TYPE_NAMESPACE);
+               lfsck_in_notify(env, mdo2mdd(&mdd_obj->mod_obj)->mdd_bottom,
+                               lr, handle);
+       }
+
+       return rc;
 }
 
 int mdd_declare_links_add(const struct lu_env *env, struct mdd_object *mdd_obj,
-                         struct thandle *handle, struct linkea_data *ldata)
+                         struct thandle *handle, struct linkea_data *ldata,
+                         enum mdd_links_add_overflow overflow)
 {
        int     rc;
        int     ea_len;
@@ -1140,6 +1155,25 @@ int mdd_declare_links_add(const struct lu_env *env, struct mdd_object *mdd_obj,
        rc = mdo_declare_xattr_set(env, mdd_obj,
                                   mdd_buf_get_const(env, linkea, ea_len),
                                   XATTR_NAME_LINK, 0, handle);
+       if (rc != 0)
+               return rc;
+
+       if (mdd_object_remote(mdd_obj) == 0 && overflow == MLAO_CHECK) {
+               struct lfsck_request *lr = &mdd_env_info(env)->mti_lr;
+
+               /* XXX: If the linkEA is overflow, then we need to notify the
+                *      namespace LFSCK to skip "nlink" attribute verification
+                *      on this object to avoid the "nlink" to be shrinked by
+                *      wrong. It may be not good an interaction with LFSCK
+                *      like this. We will consider to replace it with other
+                *      mechanism in future. LU-5802. */
+               lfsck_pack_rfa(lr, mdo2fid(mdd_obj), LE_SKIP_NLINK_DECLARE,
+                              LFSCK_TYPE_NAMESPACE);
+               rc = lfsck_in_notify(env,
+                                    mdo2mdd(&mdd_obj->mod_obj)->mdd_bottom,
+                                    lr, handle);
+       }
+
        return rc;
 }
 
@@ -1152,7 +1186,7 @@ static inline int mdd_declare_links_del(const struct lu_env *env,
        /* For directory, the linkEA will be removed together
         * with the object. */
        if (!S_ISDIR(mdd_object_type(c)))
-               rc = mdd_declare_links_add(env, c, handle, NULL);
+               rc = mdd_declare_links_add(env, c, handle, NULL, MLAO_IGNORE);
 
        return rc;
 }
@@ -1174,9 +1208,15 @@ static int mdd_declare_link(const struct lu_env *env,
                return rc;
 
        rc = mdo_declare_ref_add(env, c, handle);
-       if (rc)
+       if (rc != 0)
                return rc;
 
+       if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_MORE_NLINK)) {
+               rc = mdo_declare_ref_add(env, c, handle);
+               if (rc != 0)
+                       return rc;
+       }
+
        la->la_valid = LA_CTIME | LA_MTIME;
        rc = mdo_declare_attr_set(env, p, la, handle);
        if (rc != 0)
@@ -1184,11 +1224,12 @@ static int mdd_declare_link(const struct lu_env *env,
 
        la->la_valid = LA_CTIME;
        rc = mdo_declare_attr_set(env, c, la, handle);
-       if (rc)
+       if (rc != 0)
                return rc;
 
-       rc = mdd_declare_links_add(env, c, handle, data);
-       if (rc)
+       rc = mdd_declare_links_add(env, c, handle, data,
+                       S_ISREG(mdd_object_type(c)) ? MLAO_CHECK : MLAO_IGNORE);
+       if (rc != 0)
                return rc;
 
        rc = mdd_declare_changelog_store(env, mdd, name, NULL, handle);
@@ -1244,10 +1285,17 @@ static int mdd_link(const struct lu_env *env, struct md_object *tgt_obj,
        if (rc)
                GOTO(out_unlock, rc);
 
-       rc = mdo_ref_add(env, mdd_sobj, handle);
-       if (rc)
-               GOTO(out_unlock, rc);
+       if (!OBD_FAIL_CHECK(OBD_FAIL_LFSCK_LESS_NLINK)) {
+               rc = mdo_ref_add(env, mdd_sobj, handle);
+               if (rc != 0)
+                       GOTO(out_unlock, rc);
+       }
 
+       if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_MORE_NLINK)) {
+               rc = mdo_ref_add(env, mdd_sobj, handle);
+               if (rc != 0)
+                       GOTO(out_unlock, rc);
+       }
 
        if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_DANGLING3)) {
                struct lu_fid tfid = *mdo2fid(mdd_sobj);
@@ -1795,19 +1843,9 @@ static int mdd_object_initialize(const struct lu_env *env,
                                 struct lu_attr *attr, struct thandle *handle,
                                 const struct md_op_spec *spec)
 {
-        int rc;
-        ENTRY;
-
-        /*
-         * Update attributes for child.
-         *
-         * FIXME:
-         *  (1) the valid bits should be converted between Lustre and Linux;
-         *  (2) maybe, the child attributes should be set in OSD when creation.
-         */
+       int rc = 0;
+       ENTRY;
 
-       rc = mdd_attr_set_internal(env, child, attr, handle, 0);
-       /* arguments are supposed to stay the same */
        if (S_ISDIR(attr->la_mode)) {
                 /* Add "." and ".." for newly created dir */
                 mdo_ref_add(env, child, handle);
@@ -2027,7 +2065,7 @@ static int mdd_declare_create(const struct lu_env *env, struct mdd_device *mdd,
                if (rc != 0)
                        return rc;
 
-               rc = mdd_declare_links_add(env, c, handle, ldata);
+               rc = mdd_declare_links_add(env, c, handle, ldata, MLAO_IGNORE);
                if (rc)
                        return rc;
 
@@ -2131,9 +2169,11 @@ static int mdd_object_create(const struct lu_env *env, struct mdd_object *pobj,
        /* During creation, there are only a few cases we need do xattr_set to
         * create stripes.
         * 1. regular file: see comments above.
-        * 2. create striped directory with provided stripeEA.
-        * 3. create striped directory because inherit default layout from the
-        * parent. */
+        * 2. dir: inherit default striping or pool settings from parent.
+        * 3. create striped directory with provided stripeEA.
+        * 4. create striped directory because inherit default layout from the
+        * parent.
+        */
        if (spec->no_create ||
            (S_ISREG(attr->la_mode) && spec->sp_cr_flags & MDS_OPEN_HAS_EA) ||
            S_ISDIR(attr->la_mode)) {
@@ -2297,7 +2337,7 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj,
        mdd_object_make_hint(env, mdd_pobj, son, attr, spec, hint);
 
        memset(ldata, 0, sizeof(*ldata));
-       if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_BAD_PARENT2)) {
+       if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_BAD_PARENT)) {
                struct lu_fid tfid = *mdd_object_fid(mdd_pobj);
 
                tfid.f_oid--;
@@ -2564,7 +2604,8 @@ static int mdd_declare_rename(const struct lu_env *env,
        if (rc)
                return rc;
 
-       rc = mdd_declare_links_add(env, mdd_sobj, handle, ldata);
+       rc = mdd_declare_links_add(env, mdd_sobj, handle, ldata,
+               S_ISREG(mdd_object_type(mdd_sobj)) ? MLAO_CHECK : MLAO_IGNORE);
        if (rc)
                return rc;
 
@@ -2936,7 +2977,7 @@ static int mdd_linkea_update_child_internal(const struct lu_env *env,
                                            bool declare)
 {
        struct mdd_thread_info  *info = mdd_env_info(env);
-       struct linkea_data      ldata = {0};
+       struct linkea_data      ldata = { NULL };
        struct lu_buf           *buf = &info->mti_link_buf;
        int                     count;
        int                     rc = 0;
@@ -2981,7 +3022,8 @@ static int mdd_linkea_update_child_internal(const struct lu_env *env,
                linkea_entry_pack(ldata.ld_lee, &lname,
                                  mdd_object_fid(parent));
                if (declare)
-                       rc = mdd_declare_links_add(env, child, handle, &ldata);
+                       rc = mdd_declare_links_add(env, child, handle, &ldata,
+                                                  MLAO_IGNORE);
                else
                        rc = mdd_links_write(env, child, &ldata, handle);
                break;
@@ -3031,7 +3073,8 @@ static int mdd_update_linkea_internal(const struct lu_env *env,
        }
 
        if (declare)
-               rc = mdd_declare_links_add(env, mdd_tobj, handle, ldata);
+               rc = mdd_declare_links_add(env, mdd_tobj, handle, ldata,
+                                          MLAO_IGNORE);
        else
                rc = mdd_links_write(env, mdd_tobj, ldata, handle);
 
@@ -3296,7 +3339,6 @@ static int mdd_declare_migrate_create(const struct lu_env *env,
 
        la_flag->la_valid = LA_FLAGS;
        la_flag->la_flags = la->la_flags | LUSTRE_IMMUTABLE_FL;
-       mdd_flags_xlate(mdd_sobj, la_flag->la_flags);
        rc = mdo_declare_attr_set(env, mdd_sobj, la_flag, handle);
 
        return rc;
@@ -3311,8 +3353,8 @@ static int mdd_migrate_create(const struct lu_env *env,
        struct mdd_thread_info  *info = mdd_env_info(env);
        struct mdd_device       *mdd = mdo2mdd(&mdd_sobj->mod_obj);
        struct md_op_spec       *spec = &info->mti_spec;
-       struct lu_buf           lmm_buf = { 0 };
-       struct lu_buf           link_buf = { 0 };
+       struct lu_buf           lmm_buf = { NULL };
+       struct lu_buf           link_buf = { NULL };
        const struct lu_buf     *buf;
        struct thandle          *handle;
        struct lmv_mds_md_v1    *mgr_ea;
@@ -3406,7 +3448,6 @@ static int mdd_migrate_create(const struct lu_env *env,
         * flag and approve the migration */
        la_flag->la_valid = LA_FLAGS;
        la_flag->la_flags = la->la_flags | LUSTRE_IMMUTABLE_FL;
-       mdd_flags_xlate(mdd_sobj, la_flag->la_flags);
        rc = mdo_attr_set(env, mdd_sobj, la_flag, handle,
                          mdd_object_capa(env, mdd_sobj));
 stop_trans:
@@ -3664,7 +3705,6 @@ static int mdd_declare_migrate_update_name(const struct lu_env *env,
        /* Revert IMMUTABLE flag */
        la_flag->la_valid = LA_FLAGS;
        la_flag->la_flags = la->la_flags & ~LUSTRE_IMMUTABLE_FL;
-       mdd_flags_xlate(mdd_sobj, la_flag->la_flags);
        rc = mdo_declare_attr_set(env, mdd_sobj, la_flag, handle);
        if (rc != 0)
                return rc;
@@ -3783,7 +3823,6 @@ static int mdd_migrate_update_name(const struct lu_env *env,
        /* Revert IMMUTABLE flag */
        la_flag->la_valid = LA_FLAGS;
        la_flag->la_flags = so_attr->la_flags & ~LUSTRE_IMMUTABLE_FL;
-       mdd_flags_xlate(mdd_sobj, la_flag->la_flags);
        rc = mdo_attr_set(env, mdd_sobj, la_flag, handle,
                          mdd_object_capa(env, mdd_pobj));
        if (rc != 0)
@@ -3894,7 +3933,6 @@ static int mdd_migrate_sanity_check(const struct lu_env *env,
                        struct mdd_device *mdd = mdo2mdd(&sobj->mod_obj);
 
                        sattr->la_flags &= ~LUSTRE_IMMUTABLE_FL;
-                       sobj->mod_flags &= ~IMMUTE_OBJ;
                        CDEBUG(D_HA, "%s: "DFID" override IMMUTE FLAG\n",
                               mdd2obd_dev(mdd)->obd_name,
                               PFID(mdd_object_fid(sobj)));
@@ -4047,6 +4085,8 @@ static int mdd_migrate(const struct lu_env *env, struct md_object *pobj,
                if (unlikely(OBD_FAIL_CHECK_RESET(OBD_FAIL_MIGRATE_NET_REP,
                                                  OBD_FAIL_MDS_REINT_NET_REP)))
                        GOTO(put, rc = 0);
+       } else {
+               OBD_FAIL_TIMEOUT(OBD_FAIL_MIGRATE_DELAY, cfs_fail_val);
        }
 
        /* step 4: update name entry to the new object */