Whamcloud - gitweb
LU-15146 mdt: mdt_lvb2reply crash fix
[fs/lustre-release.git] / lustre / mdt / mdt_lvb.c
index 5c60471..729cb8e 100644 (file)
@@ -155,13 +155,10 @@ int mdt_dom_lvbo_update(struct ldlm_resource *res, struct ldlm_lock *lock,
        ENTRY;
 
        /* Before going further let's check that OBD and export are healthy.
+        * The condition matches one in ptlrpc_send_reply()
         */
-       if (exp != NULL &&
-           (exp->exp_disconnected || exp->exp_failed ||
-            exp->exp_obd->obd_stopping)) {
-               CDEBUG(D_INFO, "Skip LVB update, export is %s, obd is %s\n",
-                      exp->exp_failed ? "failed" : "disconnected",
-                      exp->exp_obd->obd_stopping ? "stopping" : "OK");
+       if (exp && exp->exp_obd && exp->exp_obd->obd_fail) {
+               CDEBUG(D_INFO, "Skip LVB update, obd is failing over\n");
                RETURN(0);
        }
 
@@ -184,10 +181,6 @@ int mdt_dom_lvbo_update(struct ldlm_resource *res, struct ldlm_lock *lock,
                if (!info)
                        GOTO(out_env, rc = -ENOMEM);
        }
-       if (!info->mti_exp)
-               info->mti_exp = req ? req->rq_export : NULL;
-       if (!info->mti_mdt)
-               info->mti_mdt = mdt;
 
        fid = &info->mti_tmp_fid2;
        fid_extract_from_res_name(fid, &res->lr_name);
@@ -285,7 +278,8 @@ static int mdt_lvbo_size(struct ldlm_lock *lock)
 
        /* resource on server side never changes. */
        mdt = ldlm_res_to_ns(lock->l_resource)->ns_lvbp;
-       LASSERT(mdt != NULL);
+       if (!mdt)
+               return 0;
 
        if (IS_LQUOTA_RES(lock->l_resource)) {
                if (mdt->mdt_qmt_dev == NULL)
@@ -295,6 +289,11 @@ static int mdt_lvbo_size(struct ldlm_lock *lock)
                return qmt_hdls.qmth_lvbo_size(mdt->mdt_qmt_dev, lock);
        }
 
+       /* Always prefer DoM LVB data because layout is never returned in
+        * LVB when lock bits are combined with DoM, this is either GETATTR
+        * or OPEN enqueue. Meanwhile GL AST can be issued on such combined
+        * lock bits and it uses LVB for DoM data.
+        */
        if (ldlm_has_dom(lock))
                return sizeof(struct ost_lvb);
 
@@ -335,6 +334,9 @@ static int mdt_lvbo_fill(struct ldlm_lock *lock,
        LASSERT(env);
 
        mdt = ldlm_lock_to_ns(lock)->ns_lvbp;
+       if (!mdt)
+               RETURN(0);
+
        if (IS_LQUOTA_RES(lock->l_resource)) {
                if (mdt->mdt_qmt_dev == NULL)
                        GOTO(out, rc = 0);
@@ -354,29 +356,24 @@ static int mdt_lvbo_fill(struct ldlm_lock *lock,
                if (!info)
                        GOTO(out, rc = -ENOMEM);
        }
-       if (!info->mti_env)
-               info->mti_env = env;
-       if (!info->mti_exp)
-               info->mti_exp = lock->l_export;
-       if (!info->mti_mdt)
-               info->mti_mdt = mdt;
-
-       /* LVB for DoM lock is needed only for glimpse,
-        * don't fill DoM data if there is layout lock */
+
+       /* DOM LVB is used by glimpse and IO completion when
+        * DoM bits is always alone.
+        * If DoM bit is combined with any other bit then it is
+        * intent OPEN or GETATTR lock which is not filling
+        * LVB buffer in reply neither for DoM nor for LAYOUT.
+        */
        if (ldlm_has_dom(lock)) {
                struct ldlm_resource *res = lock->l_resource;
                int lvb_len = sizeof(struct ost_lvb);
 
                if (!mdt_dom_lvb_is_valid(res))
-                       mdt_dom_lvbo_update(lock->l_resource, lock, NULL, 0);
-
-               if (lvb_len > *lvblen)
-                       lvb_len = *lvblen;
+                       mdt_dom_lvbo_update(res, lock, NULL, 0);
 
+               LASSERT(*lvblen >= lvb_len);
                lock_res(res);
                memcpy(lvb, res->lr_lvb_data, lvb_len);
                unlock_res(res);
-
                GOTO(out, rc = lvb_len);
        }
 
@@ -388,7 +385,7 @@ static int mdt_lvbo_fill(struct ldlm_lock *lock,
        fid = &info->mti_tmp_fid2;
        fid_extract_from_res_name(fid, &lock->l_resource->lr_name);
 
-       obj = mdt_object_find(env, info->mti_mdt, fid);
+       obj = mdt_object_find(env, mdt, fid);
        if (IS_ERR(obj))
                GOTO(out, rc = PTR_ERR(obj));
 
@@ -410,16 +407,21 @@ static int mdt_lvbo_fill(struct ldlm_lock *lock,
                         * and in that case mdt_max_mdsize is just updated
                         * but if EA size is less than mdt_max_mdsize then
                         * it is an error in lvblen value provided. */
-                       if (rc > info->mti_mdt->mdt_max_mdsize) {
-                               info->mti_mdt->mdt_max_mdsize = rc;
+                       if (rc > mdt->mdt_max_mdsize) {
+                               mdt->mdt_max_mdsize = rc;
                                level = D_INFO;
                        } else {
-                               level = D_ERROR;
+                               /* The PFL layout EA could be enlarged when
+                                * the corresponding layout of some IO range
+                                * is started to be written, which can cause
+                                * other thread to get incorrect layout size
+                                * at mdt_intent_layout, see LU-13261. */
+                               level = D_LAYOUT;
                        }
                        CDEBUG_LIMIT(level, "%s: small buffer size %d for EA "
                                     "%d (max_mdsize %d): rc = %d\n",
                                     mdt_obd_name(mdt), *lvblen, rc,
-                                    info->mti_mdt->mdt_max_mdsize, -ERANGE);
+                                    mdt->mdt_max_mdsize, -ERANGE);
                        *lvblen = rc;
                        GOTO(out_put, rc = -ERANGE);
                }
@@ -443,10 +445,10 @@ out:
 static int mdt_lvbo_free(struct ldlm_resource *res)
 {
        if (IS_LQUOTA_RES(res)) {
-               struct mdt_device       *mdt;
+               struct mdt_device *mdt;
 
                mdt = ldlm_res_to_ns(res)->ns_lvbp;
-               if (mdt->mdt_qmt_dev == NULL)
+               if (!mdt || !mdt->mdt_qmt_dev)
                        return 0;
 
                /* call lvbo free function of quota master */