Whamcloud - gitweb
LU-7623 Update obd iocontrol methods with __user attribute
[fs/lustre-release.git] / lustre / mdt / mdt_handler.c
index a8b9c48..9ffd9c7 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) 2010, 2014, Intel Corporation.
+ * Copyright (c) 2010, 2015, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
 #define DEBUG_SUBSYSTEM S_MDS
 
 #include <linux/module.h>
-/*
- * struct OBD_{ALLOC,FREE}*()
- */
-#include <obd_support.h>
+
+#include <dt_object.h>
+#include <lustre_acl.h>
+#include <lustre_export.h>
 #include <lustre_ioctl.h>
-/* struct ptlrpc_request */
+#include <lustre_lfsck.h>
+#include <lustre_log.h>
 #include <lustre_net.h>
-/* struct obd_export */
-#include <lustre_export.h>
-/* struct obd_device */
-#include <obd.h>
-/* lu2dt_dev() */
-#include <dt_object.h>
+#include <lustre_nodemap.h>
 #include <lustre_mds.h>
-#include <lustre_log.h>
-#include "mdt_internal.h"
-#include <lustre_acl.h>
 #include <lustre_param.h>
 #include <lustre_quota.h>
-#include <lustre_lfsck.h>
-#include <lustre_nodemap.h>
+#include <lustre_swab.h>
+#include <obd.h>
+#include <obd_support.h>
+
+#include "mdt_internal.h"
+
 
 static unsigned int max_mod_rpcs_per_client = 8;
 CFS_MODULE_PARM(max_mod_rpcs_per_client, "i", uint, 0644,
@@ -86,15 +83,15 @@ mdl_mode_t mdt_mdl_lock_modes[] = {
         [LCK_GROUP]   = MDL_GROUP
 };
 
-ldlm_mode_t mdt_dlm_lock_modes[] = {
-        [MDL_MINMODE] = LCK_MINMODE,
-        [MDL_EX]      = LCK_EX,
-        [MDL_PW]      = LCK_PW,
-        [MDL_PR]      = LCK_PR,
-        [MDL_CW]      = LCK_CW,
-        [MDL_CR]      = LCK_CR,
-        [MDL_NL]      = LCK_NL,
-        [MDL_GROUP]   = LCK_GROUP
+enum ldlm_mode mdt_dlm_lock_modes[] = {
+       [MDL_MINMODE]   = LCK_MINMODE,
+       [MDL_EX]        = LCK_EX,
+       [MDL_PW]        = LCK_PW,
+       [MDL_PR]        = LCK_PR,
+       [MDL_CW]        = LCK_CW,
+       [MDL_CR]        = LCK_CR,
+       [MDL_NL]        = LCK_NL,
+       [MDL_GROUP]     = LCK_GROUP
 };
 
 static struct mdt_device *mdt_dev(struct lu_device *d);
@@ -161,18 +158,19 @@ void mdt_set_disposition(struct mdt_thread_info *info,
                rep->lock_policy_res1 |= op_flag;
 }
 
-void mdt_lock_reg_init(struct mdt_lock_handle *lh, ldlm_mode_t lm)
+void mdt_lock_reg_init(struct mdt_lock_handle *lh, enum ldlm_mode lm)
 {
-        lh->mlh_pdo_hash = 0;
-        lh->mlh_reg_mode = lm;
+       lh->mlh_pdo_hash = 0;
+       lh->mlh_reg_mode = lm;
        lh->mlh_rreg_mode = lm;
-        lh->mlh_type = MDT_REG_LOCK;
+       lh->mlh_type = MDT_REG_LOCK;
 }
 
-void mdt_lock_pdo_init(struct mdt_lock_handle *lh, ldlm_mode_t lock_mode,
+void mdt_lock_pdo_init(struct mdt_lock_handle *lh, enum ldlm_mode lock_mode,
                       const struct lu_name *lname)
 {
        lh->mlh_reg_mode = lock_mode;
+       lh->mlh_pdo_mode = LCK_MINMODE;
        lh->mlh_rreg_mode = lock_mode;
        lh->mlh_type = MDT_PDO_LOCK;
 
@@ -897,10 +895,11 @@ static int mdt_getattr_internal(struct mdt_thread_info *info,
        }
 
        /* if file is released, check if a restore is running */
-       if ((ma->ma_valid & MA_HSM) && (ma->ma_hsm.mh_flags & HS_RELEASED) &&
-           mdt_hsm_restore_is_running(info, mdt_object_fid(o))) {
-               repbody->mbo_t_state = MS_RESTORE;
+       if (ma->ma_valid & MA_HSM) {
                repbody->mbo_valid |= OBD_MD_TSTATE;
+               if ((ma->ma_hsm.mh_flags & HS_RELEASED) &&
+                   mdt_hsm_restore_is_running(info, mdt_object_fid(o)))
+                       repbody->mbo_t_state = MS_RESTORE;
        }
 
        is_root = lu_fid_eq(mdt_object_fid(o), &info->mti_mdt->mdt_md_root_fid);
@@ -1435,6 +1434,13 @@ static int mdt_getattr_name_lock(struct mdt_thread_info *info,
                GOTO(out_parent, rc = PTR_ERR(child));
 
        OBD_FAIL_TIMEOUT(OBD_FAIL_MDS_RESEND, obd_timeout * 2);
+       if (!mdt_object_exists(child)) {
+               LU_OBJECT_DEBUG(D_INODE, info->mti_env,
+                               &child->mot_obj,
+                               "Object doesn't exist!\n");
+               GOTO(out_child, rc = -ENOENT);
+       }
+
        rc = mdt_check_resent_lock(info, child, lhc);
        if (rc < 0) {
                GOTO(out_child, rc);
@@ -1443,13 +1449,6 @@ static int mdt_getattr_name_lock(struct mdt_thread_info *info,
                mdt_lock_reg_init(lhc, LCK_PR);
                try_layout = false;
 
-               if (!mdt_object_exists(child)) {
-                       LU_OBJECT_DEBUG(D_INODE, info->mti_env,
-                                       &child->mot_obj,
-                                       "Object doesn't exist!\n");
-                       GOTO(out_child, rc = -ENOENT);
-               }
-
                if (!(child_bits & MDS_INODELOCK_UPDATE) &&
                      mdt_object_exists(child) && !mdt_object_remote(child)) {
                         struct md_attr *ma = &info->mti_attr;
@@ -1554,7 +1553,7 @@ static int mdt_getattr_name(struct tgt_session_info *tsi)
        repbody->mbo_eadatasize = 0;
        repbody->mbo_aclsize = 0;
 
-        rc = mdt_init_ucred(info, reqbody);
+        rc = mdt_init_ucred_intent_getattr(info, reqbody);
         if (unlikely(rc))
                 GOTO(out_shrink, rc);
 
@@ -1575,7 +1574,7 @@ out_shrink:
 }
 
 static int mdt_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
-                         void *karg, void *uarg);
+                        void *karg, void __user *uarg);
 
 static int mdt_set_info(struct tgt_session_info *tsi)
 {
@@ -1629,6 +1628,9 @@ static int mdt_set_info(struct tgt_session_info *tsi)
 
                rc = mdt_iocontrol(OBD_IOC_CHANGELOG_CLEAR, req->rq_export,
                                   vallen, val, NULL);
+       } else if (KEY_IS(KEY_EVICT_BY_NID)) {
+               if (vallen > 0)
+                       obd_export_evict_by_nid(req->rq_export->exp_obd, val);
        } else {
                RETURN(-EINVAL);
        }
@@ -2154,11 +2156,14 @@ static void mdt_device_commit_async(const struct lu_env *env,
 {
        struct dt_device *dt = mdt->mdt_bottom;
        int rc;
+       ENTRY;
 
        rc = dt->dd_ops->dt_commit_async(env, dt);
        if (unlikely(rc != 0))
                CWARN("%s: async commit start failed: rc = %d\n",
                      mdt_obd_name(mdt), rc);
+       atomic_inc(&mdt->mdt_async_commit_count);
+       EXIT;
 }
 
 /**
@@ -2214,17 +2219,22 @@ int mdt_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 
         if (flag == LDLM_CB_CANCELING)
                 RETURN(0);
+
         lock_res_and_lock(lock);
         if (lock->l_blocking_ast != mdt_blocking_ast) {
                 unlock_res_and_lock(lock);
                 RETURN(0);
         }
-        if (mdt_cos_is_enabled(mdt) &&
-            lock->l_req_mode & (LCK_PW | LCK_EX) &&
-            lock->l_blocking_lock != NULL &&
-            lock->l_client_cookie != lock->l_blocking_lock->l_client_cookie) {
-                mdt_set_lock_sync(lock);
-        }
+       if (lock->l_req_mode & (LCK_PW | LCK_EX) &&
+           lock->l_blocking_lock != NULL) {
+               if (mdt_cos_is_enabled(mdt) &&
+                   lock->l_client_cookie !=
+                   lock->l_blocking_lock->l_client_cookie)
+                       mdt_set_lock_sync(lock);
+               else if (mdt_slc_is_enabled(mdt) &&
+                        ldlm_is_cos_incompat(lock->l_blocking_lock))
+                       mdt_set_lock_sync(lock);
+       }
         rc = ldlm_blocking_ast_nocheck(lock);
 
         /* There is no lock conflict if l_blocking_lock == NULL,
@@ -2245,17 +2255,30 @@ int mdt_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
         RETURN(rc);
 }
 
-/* Used for cross-MDT lock */
+/*
+ * Blocking AST for cross-MDT lock
+ *
+ * Discard lock from uncommitted_slc_locks and cancel it.
+ *
+ * \param lock the lock which blocks a request or cancelling lock
+ * \param desc unused
+ * \param data unused
+ * \param flag indicates whether this cancelling or blocking callback
+ * \retval     0 on success
+ * \retval     negative number on error
+ */
 int mdt_remote_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
                            void *data, int flag)
 {
        struct lustre_handle lockh;
        int               rc;
+       ENTRY;
 
        switch (flag) {
        case LDLM_CB_BLOCKING:
                ldlm_lock2handle(lock, &lockh);
-               rc = ldlm_cli_cancel(&lockh, LCF_ASYNC);
+               rc = ldlm_cli_cancel(&lockh,
+                       ldlm_is_atomic_cb(lock) ? 0 : LCF_ASYNC);
                if (rc < 0) {
                        CDEBUG(D_INODE, "ldlm_cli_cancel: %d\n", rc);
                        RETURN(rc);
@@ -2263,10 +2286,14 @@ int mdt_remote_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
                break;
        case LDLM_CB_CANCELING:
                LDLM_DEBUG(lock, "Revoke remote lock\n");
+               /* discard slc lock here so that it can be cleaned anytime,
+                * especially for cleanup_resource() */
+               tgt_discard_slc_lock(lock);
                break;
        default:
                LBUG();
        }
+
        RETURN(0);
 }
 
@@ -2305,13 +2332,12 @@ int mdt_check_resent_lock(struct mdt_thread_info *info,
        return 1;
 }
 
-int mdt_remote_object_lock(struct mdt_thread_info *mti,
-                          struct mdt_object *o, const struct lu_fid *fid,
-                          struct lustre_handle *lh, ldlm_mode_t mode,
-                          __u64 ibits)
+int mdt_remote_object_lock(struct mdt_thread_info *mti, struct mdt_object *o,
+                          const struct lu_fid *fid, struct lustre_handle *lh,
+                          enum ldlm_mode mode, __u64 ibits, bool nonblock)
 {
        struct ldlm_enqueue_info *einfo = &mti->mti_einfo;
-       ldlm_policy_data_t *policy = &mti->mti_policy;
+       union ldlm_policy_data *policy = &mti->mti_policy;
        struct ldlm_res_id *res_id = &mti->mti_res_id;
        int rc = 0;
        ENTRY;
@@ -2327,6 +2353,8 @@ int mdt_remote_object_lock(struct mdt_thread_info *mti,
        einfo->ei_cb_cp = ldlm_completion_ast;
        einfo->ei_enq_slave = 0;
        einfo->ei_res_id = res_id;
+       if (nonblock)
+               einfo->ei_nonblock = 1;
 
        memset(policy, 0, sizeof(*policy));
        policy->l_inodebits.bits = ibits;
@@ -2339,20 +2367,28 @@ int mdt_remote_object_lock(struct mdt_thread_info *mti,
 static int mdt_object_local_lock(struct mdt_thread_info *info,
                                 struct mdt_object *o,
                                 struct mdt_lock_handle *lh, __u64 ibits,
-                                bool nonblock)
+                                bool nonblock, bool cos_incompat)
 {
-        struct ldlm_namespace *ns = info->mti_mdt->mdt_namespace;
-        ldlm_policy_data_t *policy = &info->mti_policy;
-        struct ldlm_res_id *res_id = &info->mti_res_id;
-       __u64 dlmflags;
-        int rc;
-        ENTRY;
+       struct ldlm_namespace *ns = info->mti_mdt->mdt_namespace;
+       union ldlm_policy_data *policy = &info->mti_policy;
+       struct ldlm_res_id *res_id = &info->mti_res_id;
+       __u64 dlmflags = 0;
+       int rc;
+       ENTRY;
 
         LASSERT(!lustre_handle_is_used(&lh->mlh_reg_lh));
         LASSERT(!lustre_handle_is_used(&lh->mlh_pdo_lh));
         LASSERT(lh->mlh_reg_mode != LCK_MINMODE);
         LASSERT(lh->mlh_type != MDT_NUL_LOCK);
 
+       if (cos_incompat) {
+               LASSERT(lh->mlh_reg_mode == LCK_PW ||
+                       lh->mlh_reg_mode == LCK_EX);
+               dlmflags |= LDLM_FL_COS_INCOMPAT;
+       } else if (mdt_cos_is_enabled(info->mti_mdt)) {
+               dlmflags |= LDLM_FL_COS_ENABLED;
+       }
+
        /* Only enqueue LOOKUP lock for remote object */
        if (mdt_object_remote(o))
                LASSERT(ibits == MDS_INODELOCK_LOOKUP);
@@ -2372,7 +2408,7 @@ static int mdt_object_local_lock(struct mdt_thread_info *info,
         memset(policy, 0, sizeof(*policy));
         fid_build_reg_res_name(mdt_object_fid(o), res_id);
 
-       dlmflags = LDLM_FL_ATOMIC_CB;
+       dlmflags |= LDLM_FL_ATOMIC_CB;
        if (nonblock)
                dlmflags |= LDLM_FL_BLOCK_NOWAIT;
 
@@ -2429,18 +2465,33 @@ out_unlock:
 
 static int
 mdt_object_lock_internal(struct mdt_thread_info *info, struct mdt_object *o,
-                        struct mdt_lock_handle *lh, __u64 ibits,
-                        bool nonblock)
+                        struct mdt_lock_handle *lh, __u64 ibits, bool nonblock,
+                        bool cos_incompat)
 {
+       struct mdt_lock_handle *local_lh = NULL;
        int rc;
        ENTRY;
 
-       if (!mdt_object_remote(o))
-               return mdt_object_local_lock(info, o, lh, ibits, nonblock);
+       if (!mdt_object_remote(o)) {
+               rc = mdt_object_local_lock(info, o, lh, ibits, nonblock,
+                                          cos_incompat);
+               RETURN(rc);
+       }
 
        /* XXX do not support PERM/LAYOUT/XATTR lock for remote object yet */
        ibits &= ~(MDS_INODELOCK_PERM | MDS_INODELOCK_LAYOUT |
                   MDS_INODELOCK_XATTR);
+
+       /* Only enqueue LOOKUP lock for remote object */
+       if (ibits & MDS_INODELOCK_LOOKUP) {
+               rc = mdt_object_local_lock(info, o, lh, MDS_INODELOCK_LOOKUP,
+                                          nonblock, cos_incompat);
+               if (rc != ELDLM_OK)
+                       RETURN(rc);
+
+               local_lh = lh;
+       }
+
        if (ibits & MDS_INODELOCK_UPDATE) {
                /* Sigh, PDO needs to enqueue 2 locks right now, but
                 * enqueue RPC can only request 1 lock, to avoid extra
@@ -2458,18 +2509,12 @@ mdt_object_lock_internal(struct mdt_thread_info *info, struct mdt_object *o,
                rc = mdt_remote_object_lock(info, o, mdt_object_fid(o),
                                            &lh->mlh_rreg_lh,
                                            lh->mlh_rreg_mode,
-                                           MDS_INODELOCK_UPDATE);
-               if (rc != ELDLM_OK)
-                       RETURN(rc);
-       }
-
-       /* Only enqueue LOOKUP lock for remote object */
-       if (ibits & MDS_INODELOCK_LOOKUP) {
-               rc = mdt_object_local_lock(info, o, lh,
-                                          MDS_INODELOCK_LOOKUP,
-                                          nonblock);
-               if (rc != ELDLM_OK)
+                                           MDS_INODELOCK_UPDATE, nonblock);
+               if (rc != ELDLM_OK) {
+                       if (local_lh != NULL)
+                               mdt_object_unlock(info, o, local_lh, rc);
                        RETURN(rc);
+               }
        }
 
        RETURN(0);
@@ -2478,7 +2523,16 @@ mdt_object_lock_internal(struct mdt_thread_info *info, struct mdt_object *o,
 int mdt_object_lock(struct mdt_thread_info *info, struct mdt_object *o,
                    struct mdt_lock_handle *lh, __u64 ibits)
 {
-       return mdt_object_lock_internal(info, o, lh, ibits, false);
+       return mdt_object_lock_internal(info, o, lh, ibits, false, false);
+}
+
+int mdt_reint_object_lock(struct mdt_thread_info *info, struct mdt_object *o,
+                         struct mdt_lock_handle *lh, __u64 ibits,
+                         bool cos_incompat)
+{
+       LASSERT(lh->mlh_reg_mode == LCK_PW || lh->mlh_reg_mode == LCK_EX);
+       return mdt_object_lock_internal(info, o, lh, ibits, false,
+                                       cos_incompat);
 }
 
 int mdt_object_lock_try(struct mdt_thread_info *info, struct mdt_object *o,
@@ -2487,7 +2541,22 @@ int mdt_object_lock_try(struct mdt_thread_info *info, struct mdt_object *o,
        struct mdt_lock_handle tmp = *lh;
        int rc;
 
-       rc = mdt_object_lock_internal(info, o, &tmp, ibits, true);
+       rc = mdt_object_lock_internal(info, o, &tmp, ibits, true, false);
+       if (rc == 0)
+               *lh = tmp;
+
+       return rc == 0;
+}
+
+int mdt_reint_object_lock_try(struct mdt_thread_info *info,
+                             struct mdt_object *o, struct mdt_lock_handle *lh,
+                             __u64 ibits, bool cos_incompat)
+{
+       struct mdt_lock_handle tmp = *lh;
+       int rc;
+
+       LASSERT(lh->mlh_reg_mode == LCK_PW || lh->mlh_reg_mode == LCK_EX);
+       rc = mdt_object_lock_internal(info, o, &tmp, ibits, true, cos_incompat);
        if (rc == 0)
                *lh = tmp;
 
@@ -2507,38 +2576,40 @@ int mdt_object_lock_try(struct mdt_thread_info *info, struct mdt_object *o,
  * \param mode lock mode
  * \param decref force immediate lock releasing
  */
-static
-void mdt_save_lock(struct mdt_thread_info *info, struct lustre_handle *h,
-                   ldlm_mode_t mode, int decref)
+static void mdt_save_lock(struct mdt_thread_info *info, struct lustre_handle *h,
+                         enum ldlm_mode mode, int decref)
 {
-        ENTRY;
+       ENTRY;
 
-        if (lustre_handle_is_used(h)) {
-                if (decref || !info->mti_has_trans ||
-                    !(mode & (LCK_PW | LCK_EX))){
-                        mdt_fid_unlock(h, mode);
-                } else {
-                        struct mdt_device *mdt = info->mti_mdt;
-                        struct ldlm_lock *lock = ldlm_handle2lock(h);
-                        struct ptlrpc_request *req = mdt_info_req(info);
-                        int no_ack = 0;
+       if (lustre_handle_is_used(h)) {
+               if (decref || !info->mti_has_trans ||
+                   !(mode & (LCK_PW | LCK_EX))) {
+                       mdt_fid_unlock(h, mode);
+               } else {
+                       struct mdt_device *mdt = info->mti_mdt;
+                       struct ldlm_lock *lock = ldlm_handle2lock(h);
+                       struct ptlrpc_request *req = mdt_info_req(info);
+                       int cos;
+
+                       cos = (mdt_cos_is_enabled(mdt) ||
+                              mdt_slc_is_enabled(mdt));
+
+                       LASSERTF(lock != NULL, "no lock for cookie "LPX64"\n",
+                                h->cookie);
 
-                        LASSERTF(lock != NULL, "no lock for cookie "LPX64"\n",
-                                 h->cookie);
                        /* there is no request if mdt_object_unlock() is called
                         * from mdt_export_cleanup()->mdt_add_dirty_flag() */
                        if (likely(req != NULL)) {
                                CDEBUG(D_HA, "request = %p reply state = %p"
                                       " transno = "LPD64"\n", req,
                                       req->rq_reply_state, req->rq_transno);
-                               if (mdt_cos_is_enabled(mdt)) {
-                                       no_ack = 1;
+                               if (cos) {
                                        ldlm_lock_downgrade(lock, LCK_COS);
                                        mode = LCK_COS;
                                }
-                               ptlrpc_save_lock(req, h, mode, no_ack);
+                               ptlrpc_save_lock(req, h, mode, cos);
                        } else {
-                               ldlm_lock_decref(h, mode);
+                               mdt_fid_unlock(h, mode);
                        }
                         if (mdt_is_lock_sync(lock)) {
                                 CDEBUG(D_HA, "found sync-lock,"
@@ -2555,6 +2626,41 @@ void mdt_save_lock(struct mdt_thread_info *info, struct lustre_handle *h,
 }
 
 /**
+ * Save cross-MDT lock in uncommitted_slc_locks
+ *
+ * Keep the lock referenced until transaction commit happens or release the lock
+ * immediately depending on input parameters.
+ *
+ * \param info thead info object
+ * \param h lock handle
+ * \param mode lock mode
+ * \param decref force immediate lock releasing
+ */
+static void mdt_save_remote_lock(struct mdt_thread_info *info,
+                                struct lustre_handle *h, enum ldlm_mode mode,
+                                int decref)
+{
+       ENTRY;
+
+       if (lustre_handle_is_used(h)) {
+               if (decref || !info->mti_has_trans ||
+                   !(mode & (LCK_PW | LCK_EX))) {
+                       ldlm_lock_decref_and_cancel(h, mode);
+               } else {
+                       struct ldlm_lock *lock = ldlm_handle2lock(h);
+                       struct ptlrpc_request *req = mdt_info_req(info);
+
+                       LASSERT(req != NULL);
+                       tgt_save_slc_lock(lock, req->rq_transno);
+                       ldlm_lock_decref(h, mode);
+               }
+               h->cookie = 0ull;
+       }
+
+       EXIT;
+}
+
+/**
  * Unlock mdt object.
  *
  * Immeditely release the regular lock and the PDO lock or save the
@@ -2567,17 +2673,15 @@ void mdt_save_lock(struct mdt_thread_info *info, struct lustre_handle *h,
  * \param decref force immediate lock releasing
  */
 void mdt_object_unlock(struct mdt_thread_info *info, struct mdt_object *o,
-                       struct mdt_lock_handle *lh, int decref)
+                      struct mdt_lock_handle *lh, int decref)
 {
-        ENTRY;
-
-        mdt_save_lock(info, &lh->mlh_pdo_lh, lh->mlh_pdo_mode, decref);
-        mdt_save_lock(info, &lh->mlh_reg_lh, lh->mlh_reg_mode, decref);
+       ENTRY;
 
-       if (lustre_handle_is_used(&lh->mlh_rreg_lh))
-               ldlm_lock_decref(&lh->mlh_rreg_lh, lh->mlh_rreg_mode);
+       mdt_save_lock(info, &lh->mlh_pdo_lh, lh->mlh_pdo_mode, decref);
+       mdt_save_lock(info, &lh->mlh_reg_lh, lh->mlh_reg_mode, decref);
+       mdt_save_remote_lock(info, &lh->mlh_rreg_lh, lh->mlh_rreg_mode, decref);
 
-        EXIT;
+       EXIT;
 }
 
 struct mdt_object *mdt_object_find_lock(struct mdt_thread_info *info,
@@ -2740,6 +2844,7 @@ void mdt_thread_info_init(struct ptlrpc_request *req,
         info->mti_spec.no_create = 0;
        info->mti_spec.sp_rm_entry = 0;
        info->mti_spec.sp_permitted = 0;
+       info->mti_spec.sp_migrate_close = 0;
 
        info->mti_spec.u.sp_ea.eadata = NULL;
        info->mti_spec.u.sp_ea.eadatalen = 0;
@@ -3159,6 +3264,7 @@ static int mdt_intent_layout(enum mdt_it_code opcode,
        struct layout_intent *layout;
        struct lu_fid *fid;
        struct mdt_object *obj = NULL;
+       int layout_size = 0;
        int rc = 0;
        ENTRY;
 
@@ -3168,6 +3274,16 @@ static int mdt_intent_layout(enum mdt_it_code opcode,
                RETURN(-EINVAL);
        }
 
+       layout = req_capsule_client_get(info->mti_pill, &RMF_LAYOUT_INTENT);
+       if (layout == NULL)
+               RETURN(-EPROTO);
+
+       if (layout->li_opc != LAYOUT_INTENT_ACCESS) {
+               CERROR("%s: Unsupported layout intent opc %d\n",
+                      mdt_obd_name(info->mti_mdt), layout->li_opc);
+               RETURN(-EINVAL);
+       }
+
        fid = &info->mti_tmp_fid2;
        fid_extract_from_res_name(fid, &(*lockp)->l_resource->lr_name);
 
@@ -3176,40 +3292,33 @@ static int mdt_intent_layout(enum mdt_it_code opcode,
 
        obj = mdt_object_find(info->mti_env, info->mti_mdt, fid);
        if (IS_ERR(obj))
-               RETURN(PTR_ERR(obj));
+               GOTO(out, rc = PTR_ERR(obj));
 
        if (mdt_object_exists(obj) && !mdt_object_remote(obj)) {
-               /* get the length of lsm */
-               rc = mdt_attr_get_eabuf_size(info, obj);
-               if (rc < 0) {
-                       mdt_object_put(info->mti_env, obj);
-                       RETURN(rc);
-               }
+               layout_size = mdt_attr_get_eabuf_size(info, obj);
+               if (layout_size < 0)
+                       GOTO(out_obj, rc = layout_size);
 
-               if (rc > info->mti_mdt->mdt_max_mdsize)
-                       info->mti_mdt->mdt_max_mdsize = rc;
+               if (layout_size > info->mti_mdt->mdt_max_mdsize)
+                       info->mti_mdt->mdt_max_mdsize = layout_size;
        }
 
-       mdt_object_put(info->mti_env, obj);
-
        (*lockp)->l_lvb_type = LVB_T_LAYOUT;
-       req_capsule_set_size(info->mti_pill, &RMF_DLM_LVB, RCL_SERVER, rc);
+       req_capsule_set_size(info->mti_pill, &RMF_DLM_LVB, RCL_SERVER,
+                            layout_size);
        rc = req_capsule_server_pack(info->mti_pill);
-       if (rc != 0)
-               RETURN(-EINVAL);
+       GOTO(out_obj, rc);
+
+out_obj:
+       mdt_object_put(info->mti_env, obj);
 
-       if (lustre_handle_is_used(&lhc->mlh_reg_lh))
+       if (rc == 0 && lustre_handle_is_used(&lhc->mlh_reg_lh))
                rc = mdt_intent_lock_replace(info, lockp, lhc, flags);
 
-       layout = req_capsule_client_get(info->mti_pill, &RMF_LAYOUT_INTENT);
-       LASSERT(layout != NULL);
-       if (layout->li_opc == LAYOUT_INTENT_ACCESS)
-               /* return to normal/resent ldlm handling */
-               RETURN(rc);
+out:
+       lhc->mlh_reg_lh.cookie = 0;
 
-       CERROR("%s: Unsupported layout intent (%d)\n",
-               mdt_obd_name(info->mti_mdt), layout->li_opc);
-       RETURN(-EINVAL);
+       return rc;
 }
 
 static int mdt_intent_reint(enum mdt_it_code opcode,
@@ -3266,8 +3375,9 @@ static int mdt_intent_reint(enum mdt_it_code opcode,
        rep->lock_policy_res2 = clear_serious(rc);
 
         if (rep->lock_policy_res2 == -ENOENT &&
-            mdt_get_disposition(rep, DISP_LOOKUP_NEG))
-                rep->lock_policy_res2 = 0;
+           mdt_get_disposition(rep, DISP_LOOKUP_NEG) &&
+           !mdt_get_disposition(rep, DISP_OPEN_CREATE))
+               rep->lock_policy_res2 = 0;
 
        lhc->mlh_reg_lh.cookie = 0ull;
         if (rc == -ENOTCONN || rc == -ENODEV ||
@@ -3287,54 +3397,55 @@ static int mdt_intent_reint(enum mdt_it_code opcode,
        RETURN(ELDLM_LOCK_ABORTED);
 }
 
-static int mdt_intent_code(long itcode)
+static int mdt_intent_code(enum ldlm_intent_flags itcode)
 {
-        int rc;
+       int rc;
 
-        switch(itcode) {
-        case IT_OPEN:
-                rc = MDT_IT_OPEN;
-                break;
-        case IT_OPEN|IT_CREAT:
-                rc = MDT_IT_OCREAT;
-                break;
-        case IT_CREAT:
-                rc = MDT_IT_CREATE;
-                break;
-        case IT_READDIR:
-                rc = MDT_IT_READDIR;
-                break;
-        case IT_GETATTR:
-                rc = MDT_IT_GETATTR;
-                break;
-        case IT_LOOKUP:
-                rc = MDT_IT_LOOKUP;
-                break;
-        case IT_UNLINK:
-                rc = MDT_IT_UNLINK;
-                break;
-        case IT_TRUNC:
-                rc = MDT_IT_TRUNC;
-                break;
-        case IT_GETXATTR:
-                rc = MDT_IT_GETXATTR;
-                break;
-        case IT_LAYOUT:
-                rc = MDT_IT_LAYOUT;
-                break;
+       switch (itcode) {
+       case IT_OPEN:
+               rc = MDT_IT_OPEN;
+               break;
+       case IT_OPEN|IT_CREAT:
+               rc = MDT_IT_OCREAT;
+               break;
+       case IT_CREAT:
+               rc = MDT_IT_CREATE;
+               break;
+       case IT_READDIR:
+               rc = MDT_IT_READDIR;
+               break;
+       case IT_GETATTR:
+               rc = MDT_IT_GETATTR;
+               break;
+       case IT_LOOKUP:
+               rc = MDT_IT_LOOKUP;
+               break;
+       case IT_UNLINK:
+               rc = MDT_IT_UNLINK;
+               break;
+       case IT_TRUNC:
+               rc = MDT_IT_TRUNC;
+               break;
+       case IT_GETXATTR:
+               rc = MDT_IT_GETXATTR;
+               break;
+       case IT_LAYOUT:
+               rc = MDT_IT_LAYOUT;
+               break;
        case IT_QUOTA_DQACQ:
        case IT_QUOTA_CONN:
                rc = MDT_IT_QUOTA;
                break;
-        default:
-                CERROR("Unknown intent opcode: %ld\n", itcode);
-                rc = -EINVAL;
-                break;
-        }
-        return rc;
+       default:
+               CERROR("Unknown intent opcode: 0x%08x\n", itcode);
+               rc = -EINVAL;
+               break;
+       }
+       return rc;
 }
 
-static int mdt_intent_opc(long itopc, struct mdt_thread_info *info,
+static int mdt_intent_opc(enum ldlm_intent_flags itopc,
+                         struct mdt_thread_info *info,
                          struct ldlm_lock **lockp, __u64 flags)
 {
        struct req_capsule      *pill = info->mti_pill;
@@ -3377,6 +3488,8 @@ static int mdt_intent_opc(long itopc, struct mdt_thread_info *info,
        if (flv->it_act != NULL) {
                struct ldlm_reply *rep;
 
+               OBD_FAIL_TIMEOUT(OBD_FAIL_MDS_INTENT_DELAY, 10);
+
                /* execute policy */
                rc = flv->it_act(opc, info, lockp, flags);
 
@@ -3393,8 +3506,8 @@ static int mdt_intent_opc(long itopc, struct mdt_thread_info *info,
 }
 
 static int mdt_intent_policy(struct ldlm_namespace *ns,
-                             struct ldlm_lock **lockp, void *req_cookie,
-                            ldlm_mode_t mode, __u64 flags, void *data)
+                            struct ldlm_lock **lockp, void *req_cookie,
+                            enum ldlm_mode mode, __u64 flags, void *data)
 {
        struct tgt_session_info *tsi;
        struct mdt_thread_info  *info;
@@ -3879,7 +3992,7 @@ static int mdt_stack_init(const struct lu_env *env, struct mdt_device *mdt,
 
        lcfg = lustre_cfg_new(LCFG_ATTACH, bufs);
        if (lcfg == NULL)
-               GOTO(free_bufs, rc = -ENOMEM);
+               GOTO(put_profile, rc = -ENOMEM);
 
        rc = class_attach(lcfg);
        if (rc)
@@ -3939,6 +4052,8 @@ class_detach:
                class_detach(obd, lcfg);
 lcfg_cleanup:
        lustre_cfg_free(lcfg);
+put_profile:
+       class_put_profile(lprof);
 free_bufs:
        OBD_FREE_PTR(bufs);
 cleanup_mem:
@@ -4009,7 +4124,7 @@ static int mdt_quota_init(const struct lu_env *env, struct mdt_device *mdt,
 
        lcfg = lustre_cfg_new(LCFG_ATTACH, bufs);
        if (lcfg == NULL)
-               GOTO(cleanup_mem, rc = -ENOMEM);
+               GOTO(put_profile, rc = -ENOMEM);
 
        rc = class_attach(lcfg);
        if (rc)
@@ -4071,6 +4186,8 @@ class_detach:
                class_detach(obd, lcfg);
 lcfg_cleanup:
        lustre_cfg_free(lcfg);
+put_profile:
+       class_put_profile(lprof);
 cleanup_mem:
        if (bufs)
                OBD_FREE_PTR(bufs);
@@ -4232,9 +4349,9 @@ static void mdt_fini(const struct lu_env *env, struct mdt_device *m)
        stop.ls_flags = 0;
        next->md_ops->mdo_iocontrol(env, next, OBD_IOC_STOP_LFSCK, 0, &stop);
 
+       mdt_stack_pre_fini(env, m, md2lu_dev(m->mdt_child));
        target_recovery_fini(obd);
        ping_evictor_stop();
-       mdt_stack_pre_fini(env, m, md2lu_dev(m->mdt_child));
 
        if (m->mdt_opts.mo_coordinator)
                mdt_hsm_cdt_stop(m);
@@ -4243,6 +4360,11 @@ static void mdt_fini(const struct lu_env *env, struct mdt_device *m)
 
        mdt_llog_ctxt_unclone(env, m, LLOG_AGENT_ORIG_CTXT);
         mdt_llog_ctxt_unclone(env, m, LLOG_CHANGELOG_ORIG_CTXT);
+
+       if (m->mdt_namespace != NULL)
+               ldlm_namespace_free_prior(m->mdt_namespace, NULL,
+                                         d->ld_obd->obd_force);
+
         obd_exports_barrier(obd);
         obd_zombie_barrier();
 
@@ -4253,11 +4375,10 @@ static void mdt_fini(const struct lu_env *env, struct mdt_device *m)
         upcall_cache_cleanup(m->mdt_identity_cache);
         m->mdt_identity_cache = NULL;
 
-        if (m->mdt_namespace != NULL) {
-                ldlm_namespace_free(m->mdt_namespace, NULL,
-                                    d->ld_obd->obd_force);
-                d->ld_obd->obd_namespace = m->mdt_namespace = NULL;
-        }
+       if (m->mdt_namespace != NULL) {
+               ldlm_namespace_free_post(m->mdt_namespace);
+               d->ld_obd->obd_namespace = m->mdt_namespace = NULL;
+       }
 
        mdt_quota_fini(env, m);
 
@@ -4318,7 +4439,7 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m,
         LASSERT(obd != NULL);
 
         m->mdt_max_mdsize = MAX_MD_SIZE; /* 4 stripes */
-
+       m->mdt_opts.mo_evict_tgt_nids = 1;
         m->mdt_opts.mo_cos = MDT_COS_DEFAULT;
 
        /* default is coordinator off, it is started through conf_param
@@ -4335,6 +4456,9 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m,
                 LASSERT(num);
                 node_id = simple_strtol(num, NULL, 10);
                obd->u.obt.obt_magic = OBT_MAGIC;
+               if (lsi->lsi_lmd != NULL &&
+                   lsi->lsi_lmd->lmd_flags & LMD_FLG_SKIP_LFSCK)
+                       m->mdt_skip_lfsck = 1;
        }
 
        m->mdt_squash.rsi_uid = 0;
@@ -4346,6 +4470,9 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m,
        m->mdt_enable_remote_dir = 0;
        m->mdt_enable_remote_dir_gid = 0;
 
+       atomic_set(&m->mdt_mds_mds_conns, 0);
+       atomic_set(&m->mdt_async_commit_count, 0);
+
        m->mdt_lu_dev.ld_ops = &mdt_lu_ops;
        m->mdt_lu_dev.ld_obd = obd;
        /* Set this lu_device to obd for error handling purposes. */
@@ -4975,6 +5102,18 @@ static int mdt_export_cleanup(struct obd_export *exp)
         RETURN(rc);
 }
 
+static inline void mdt_enable_slc(struct mdt_device *mdt)
+{
+       if (mdt->mdt_lut.lut_sync_lock_cancel == NEVER_SYNC_ON_CANCEL)
+               mdt->mdt_lut.lut_sync_lock_cancel = BLOCKING_SYNC_ON_CANCEL;
+}
+
+static inline void mdt_disable_slc(struct mdt_device *mdt)
+{
+       if (mdt->mdt_lut.lut_sync_lock_cancel == BLOCKING_SYNC_ON_CANCEL)
+               mdt->mdt_lut.lut_sync_lock_cancel = NEVER_SYNC_ON_CANCEL;
+}
+
 static int mdt_obd_disconnect(struct obd_export *exp)
 {
         int rc;
@@ -4983,12 +5122,20 @@ static int mdt_obd_disconnect(struct obd_export *exp)
         LASSERT(exp);
         class_export_get(exp);
 
-       nodemap_del_member(exp);
+       if ((exp_connect_flags(exp) & OBD_CONNECT_MDS_MDS) &&
+           !(exp_connect_flags(exp) & OBD_CONNECT_LIGHTWEIGHT)) {
+               struct mdt_device *mdt = mdt_dev(exp->exp_obd->obd_lu_dev);
+
+               if (atomic_dec_and_test(&mdt->mdt_mds_mds_conns))
+                       mdt_disable_slc(mdt);
+       }
+
        rc = server_disconnect_export(exp);
        if (rc != 0)
                CDEBUG(D_IOCTL, "server disconnect error: rc = %d\n", rc);
 
        rc = mdt_export_cleanup(exp);
+       nodemap_del_member(exp);
        class_export_put(exp);
        RETURN(rc);
 }
@@ -5013,6 +5160,12 @@ static int mdt_obd_connect(const struct lu_env *env,
 
        mdt = mdt_dev(obd->obd_lu_dev);
 
+       if ((data->ocd_connect_flags & OBD_CONNECT_MDS_MDS) &&
+           !(data->ocd_connect_flags & OBD_CONNECT_LIGHTWEIGHT)) {
+               atomic_inc(&mdt->mdt_mds_mds_conns);
+               mdt_enable_slc(mdt);
+       }
+
        /*
         * first, check whether the stack is ready to handle requests
         * XXX: probably not very appropriate method is used now
@@ -5036,6 +5189,10 @@ static int mdt_obd_connect(const struct lu_env *env,
        lexp = class_conn2export(&conn);
        LASSERT(lexp != NULL);
 
+       rc = nodemap_add_member(*client_nid, lexp);
+       if (rc != 0 && rc != -EEXIST)
+               GOTO(out, rc);
+
        rc = mdt_connect_internal(lexp, mdt, data);
        if (rc == 0) {
                struct lsd_client_data *lcd = lexp->exp_target_data.ted_lcd;
@@ -5043,17 +5200,13 @@ static int mdt_obd_connect(const struct lu_env *env,
                LASSERT(lcd);
                memcpy(lcd->lcd_uuid, cluuid, sizeof lcd->lcd_uuid);
                rc = tgt_client_new(env, lexp);
-               if (rc == 0) {
-                       rc = nodemap_add_member(*client_nid, lexp);
-                       if (rc != 0 && rc != -EEXIST)
-                               goto out;
-
+               if (rc == 0)
                        mdt_export_stats_init(obd, lexp, localdata);
-               }
        }
 out:
        if (rc != 0) {
                class_disconnect(lexp);
+               nodemap_del_member(lexp);
                *exp = NULL;
        } else {
                *exp = lexp;
@@ -5075,12 +5228,15 @@ static int mdt_obd_reconnect(const struct lu_env *env,
        if (exp == NULL || obd == NULL || cluuid == NULL)
                RETURN(-EINVAL);
 
+       rc = nodemap_add_member(*client_nid, exp);
+       if (rc != 0 && rc != -EEXIST)
+               RETURN(rc);
+
        rc = mdt_connect_internal(exp, mdt_dev(obd->obd_lu_dev), data);
-       if (rc == 0) {
-               rc = nodemap_add_member(*client_nid, exp);
-               if (rc == 0 || rc == -EEXIST)
-                       mdt_export_stats_init(obd, exp, localdata);
-       }
+       if (rc == 0)
+               mdt_export_stats_init(obd, exp, localdata);
+       else
+               nodemap_del_member(exp);
 
        RETURN(rc);
 }
@@ -5554,7 +5710,7 @@ static int mdt_ioc_version_get(struct mdt_thread_info *mti, void *karg)
 
 /* ioctls on obd dev */
 static int mdt_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
-                         void *karg, void *uarg)
+                        void *karg, void __user *uarg)
 {
         struct lu_env      env;
         struct obd_device *obd = exp->exp_obd;
@@ -5577,7 +5733,7 @@ static int mdt_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                 break;
        case OBD_IOC_ABORT_RECOVERY:
                CERROR("%s: Aborting recovery for device\n", mdt_obd_name(mdt));
-               obd->obd_force_abort_recovery = 1;
+               obd->obd_abort_recovery = 1;
                target_stop_recovery_thread(obd);
                rc = 0;
                break;
@@ -5650,18 +5806,21 @@ static int mdt_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 static int mdt_postrecov(const struct lu_env *env, struct mdt_device *mdt)
 {
        struct lu_device *ld = md2lu_dev(mdt->mdt_child);
-       struct lfsck_start_param lsp;
        int rc;
        ENTRY;
 
-       lsp.lsp_start = NULL;
-       lsp.lsp_index_valid = 0;
-       rc = mdt->mdt_child->md_ops->mdo_iocontrol(env, mdt->mdt_child,
-                                                  OBD_IOC_START_LFSCK,
-                                                  0, &lsp);
-       if (rc != 0 && rc != -EALREADY)
-               CWARN("%s: auto trigger paused LFSCK failed: rc = %d\n",
-                     mdt_obd_name(mdt), rc);
+       if (!mdt->mdt_skip_lfsck) {
+               struct lfsck_start_param lsp;
+
+               lsp.lsp_start = NULL;
+               lsp.lsp_index_valid = 0;
+               rc = mdt->mdt_child->md_ops->mdo_iocontrol(env, mdt->mdt_child,
+                                                          OBD_IOC_START_LFSCK,
+                                                          0, &lsp);
+               if (rc != 0 && rc != -EALREADY)
+                       CWARN("%s: auto trigger paused LFSCK failed: rc = %d\n",
+                             mdt_obd_name(mdt), rc);
+       }
 
        rc = ld->ld_ops->ldo_recovery_complete(env, ld);
        RETURN(rc);
@@ -5815,7 +5974,7 @@ static struct lu_device_type mdt_device_type = {
         .ldt_ctx_tags = LCT_MD_THREAD
 };
 
-static int __init mdt_mod_init(void)
+static int __init mdt_init(void)
 {
        int rc;
 
@@ -5844,17 +6003,17 @@ mds_fini:
        return rc;
 }
 
-static void __exit mdt_mod_exit(void)
+static void __exit mdt_exit(void)
 {
        class_unregister_type(LUSTRE_MDT_NAME);
        mds_mod_exit();
        lu_kmem_fini(mdt_caches);
 }
 
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
+MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
 MODULE_DESCRIPTION("Lustre Metadata Target ("LUSTRE_MDT_NAME")");
 MODULE_VERSION(LUSTRE_VERSION_STRING);
 MODULE_LICENSE("GPL");
 
-module_init(mdt_mod_init);
-module_exit(mdt_mod_exit);
+module_init(mdt_init);
+module_exit(mdt_exit);