Whamcloud - gitweb
LU-11444 ptlrpc: resend may corrupt the data
[fs/lustre-release.git] / lustre / target / tgt_handler.c
index d9d5a81..e41c59c 100644 (file)
@@ -552,7 +552,7 @@ static int tgt_handle_recovery(struct ptlrpc_request *req, int reply_fail_id)
 
        /* sanity check: if the xid matches, the request must be marked as a
         * resent or replayed */
-       if (req_can_reconstruct(req, NULL)) {
+       if (req_can_reconstruct(req, NULL) == 1) {
                if (!(lustre_msg_get_flags(req->rq_reqmsg) &
                      (MSG_RESENT | MSG_REPLAY))) {
                        DEBUG_REQ(D_WARNING, req,
@@ -629,18 +629,20 @@ static struct tgt_handler *tgt_handler_find_check(struct ptlrpc_request *req)
 static int process_req_last_xid(struct ptlrpc_request *req)
 {
        __u64   last_xid;
+       int rc = 0;
+       struct obd_export *exp = req->rq_export;
+       struct tg_export_data *ted = &exp->exp_target_data;
+       bool need_lock = tgt_is_multimodrpcs_client(exp);
        ENTRY;
 
+       if (need_lock)
+               mutex_lock(&ted->ted_lcd_lock);
        /* check request's xid is consistent with export's last_xid */
        last_xid = lustre_msg_get_last_xid(req->rq_reqmsg);
-       if (last_xid > req->rq_export->exp_last_xid)
-               req->rq_export->exp_last_xid = last_xid;
+       if (last_xid > exp->exp_last_xid)
+               exp->exp_last_xid = last_xid;
 
-       if (req->rq_xid == 0 ||
-           (req->rq_xid <= req->rq_export->exp_last_xid)) {
-               DEBUG_REQ(D_WARNING, req,
-                         "unexpected rq_xid=%llx != exp_last_xid=%llx",
-                         req->rq_xid, req->rq_export->exp_last_xid);
+       if (req->rq_xid == 0 || req->rq_xid <= exp->exp_last_xid) {
                /* Some request is allowed to be sent during replay,
                 * such as OUT update requests, FLD requests, so it
                 * is possible that replay requests has smaller XID
@@ -657,7 +659,13 @@ static int process_req_last_xid(struct ptlrpc_request *req)
                 * - The former RPC got chance to be processed;
                 */
                if (!(lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY))
-                       RETURN(-EPROTO);
+                       rc = -EPROTO;
+
+               DEBUG_REQ(D_WARNING, req,
+                         "unexpected xid=%llx != exp_last_xid=%llx, rc = %d",
+                         req->rq_xid, exp->exp_last_xid, rc);
+               if (rc)
+                       GOTO(out, rc);
        }
 
        /* The "last_xid" is the minimum xid among unreplied requests,
@@ -671,18 +679,19 @@ static int process_req_last_xid(struct ptlrpc_request *req)
         */
        if (req->rq_export->exp_conn_cnt >
            lustre_msg_get_conn_cnt(req->rq_reqmsg))
-               RETURN(-ESTALE);
+               GOTO(out, rc = -ESTALE);
 
        /* try to release in-memory reply data */
-       if (tgt_is_multimodrpcs_client(req->rq_export)) {
-               tgt_handle_received_xid(req->rq_export,
-                               lustre_msg_get_last_xid(req->rq_reqmsg));
-               if (!(lustre_msg_get_flags(req->rq_reqmsg) &
-                     (MSG_RESENT | MSG_REPLAY)))
-                       tgt_handle_tag(req->rq_export,
-                                      lustre_msg_get_tag(req->rq_reqmsg));
+       if (tgt_is_multimodrpcs_client(exp)) {
+               tgt_handle_received_xid(exp, last_xid);
+               rc = tgt_handle_tag(req);
        }
-       RETURN(0);
+
+out:
+       if (need_lock)
+               mutex_unlock(&ted->ted_lcd_lock);
+
+       RETURN(rc);
 }
 
 int tgt_request_handle(struct ptlrpc_request *req)
@@ -2729,12 +2738,12 @@ EXPORT_SYMBOL(tgt_brw_write);
 /* Check if request can be reconstructed from saved reply data
  * A copy of the reply data is returned in @trd if the pointer is not NULL
  */
-bool req_can_reconstruct(struct ptlrpc_request *req,
+int req_can_reconstruct(struct ptlrpc_request *req,
                         struct tg_reply_data *trd)
 {
        struct tg_export_data *ted = &req->rq_export->exp_target_data;
        struct lsd_client_data *lcd = ted->ted_lcd;
-       bool found;
+       int found;
 
        if (tgt_is_multimodrpcs_client(req->rq_export))
                return tgt_lookup_reply(req, trd);