Whamcloud - gitweb
LU-6386 tgt: don't update client data with smaller transno
[fs/lustre-release.git] / lustre / target / tgt_lastrcvd.c
index a152f05..878246e 100644 (file)
@@ -1131,7 +1131,7 @@ static int tgt_last_rcvd_update(const struct lu_env *env, struct lu_target *tgt,
        struct tg_export_data   *ted;
        __u64                   *transno_p;
        int                      rc = 0;
-       bool                     lw_client, update = false;
+       bool                     lw_client;
 
        ENTRY;
 
@@ -1190,27 +1190,21 @@ static int tgt_last_rcvd_update(const struct lu_env *env, struct lu_target *tgt,
                spin_lock(&tgt->lut_translock);
                if (tti->tti_transno > tgt->lut_lsd.lsd_last_transno) {
                        tgt->lut_lsd.lsd_last_transno = tti->tti_transno;
-                       update = true;
+                       spin_unlock(&tgt->lut_translock);
+                       /* Although lightweight (LW) connections have no slot
+                        * in the last_rcvd, we still want to maintain
+                        * the in-memory lsd_client_data structure in order to
+                        * properly handle reply reconstruction. */
+                       rc = tgt_server_data_write(env, tgt, th);
+               } else {
+                       spin_unlock(&tgt->lut_translock);
                }
-               spin_unlock(&tgt->lut_translock);
-               /* Although lightweight (LW) connections have no slot in
-                * last_rcvd, we still want to maintain the in-memory
-                * lsd_client_data structure in order to properly handle reply
-                * reconstruction. */
        } else if (ted->ted_lr_off == 0) {
                CERROR("%s: client idx %d has offset %lld\n",
                       tgt_name(tgt), ted->ted_lr_idx, ted->ted_lr_off);
                RETURN(-EINVAL);
        }
 
-       /* if the export has already been disconnected, we have no last_rcvd
-        * slot, update server data with latest transno then */
-       if (ted->ted_lcd == NULL) {
-               CWARN("commit transaction for disconnected client %s: rc %d\n",
-                     exp->exp_client_uuid.uuid, rc);
-               GOTO(srv_update, rc = 0);
-       }
-
        /* Target that supports multiple reply data */
        if (tgt_is_multimodrpcs_client(exp)) {
                struct tg_reply_data    *trd;
@@ -1220,7 +1214,7 @@ static int tgt_last_rcvd_update(const struct lu_env *env, struct lu_target *tgt,
 
                OBD_ALLOC_PTR(trd);
                if (unlikely(trd == NULL))
-                       GOTO(srv_update, rc = -ENOMEM);
+                       RETURN(-ENOMEM);
 
                /* fill reply data information */
                lrd = &trd->trd_reply;
@@ -1251,12 +1245,14 @@ static int tgt_last_rcvd_update(const struct lu_env *env, struct lu_target *tgt,
                }
 
                rc = tgt_add_reply_data(env, tgt, ted, trd, th, write_update);
-               GOTO(srv_update, rc);
+               if (rc < 0)
+                       OBD_FREE_PTR(trd);
+               return rc;
        }
 
        /* Enough for update replay, let's return */
        if (req == NULL)
-               GOTO(srv_update, rc);
+               RETURN(rc);
 
        mutex_lock(&ted->ted_lcd_lock);
        LASSERT(ergo(tti->tti_transno == 0, th->th_result != 0));
@@ -1284,21 +1280,27 @@ static int tgt_last_rcvd_update(const struct lu_env *env, struct lu_target *tgt,
 
        /* Update transno in slot only if non-zero number, i.e. no errors */
        if (likely(tti->tti_transno != 0)) {
-               if (*transno_p > tti->tti_transno &&
-                   !tgt->lut_no_reconstruct) {
-                       CERROR("%s: trying to overwrite bigger transno:"
-                              "on-disk: "LPU64", new: "LPU64" replay: %d. "
-                              "see LU-617.\n", tgt_name(tgt), *transno_p,
-                              tti->tti_transno, req_is_replay(req));
-                       if (req_is_replay(req)) {
-                               spin_lock(&req->rq_export->exp_lock);
-                               req->rq_export->exp_vbr_failed = 1;
-                               spin_unlock(&req->rq_export->exp_lock);
+               /* Don't overwrite bigger transaction number with lower one.
+                * That is not sign of problem in all cases, but in any case
+                * this value should be monotonically increased only. */
+               if (*transno_p > tti->tti_transno) {
+                       if (!tgt->lut_no_reconstruct) {
+                               CERROR("%s: trying to overwrite bigger transno:"
+                                      "on-disk: "LPU64", new: "LPU64" replay: "
+                                      "%d. See LU-617.\n", tgt_name(tgt),
+                                      *transno_p, tti->tti_transno,
+                                      req_is_replay(req));
+                               if (req_is_replay(req)) {
+                                       spin_lock(&req->rq_export->exp_lock);
+                                       req->rq_export->exp_vbr_failed = 1;
+                                       spin_unlock(&req->rq_export->exp_lock);
+                               }
+                               mutex_unlock(&ted->ted_lcd_lock);
+                               RETURN(req_is_replay(req) ? -EOVERFLOW : 0);
                        }
-                       mutex_unlock(&ted->ted_lcd_lock);
-                       RETURN(req_is_replay(req) ? -EOVERFLOW : 0);
+               } else {
+                       *transno_p = tti->tti_transno;
                }
-               *transno_p = tti->tti_transno;
        }
 
        if (!lw_client) {
@@ -1310,11 +1312,7 @@ static int tgt_last_rcvd_update(const struct lu_env *env, struct lu_target *tgt,
                }
        }
        mutex_unlock(&ted->ted_lcd_lock);
-       EXIT;
-srv_update:
-       if (update)
-               rc = tgt_server_data_write(env, tgt, th);
-       return rc;
+       RETURN(rc);
 }
 
 /*