Whamcloud - gitweb
LU-15986 ptlrpc: protect rq_repmsg in ptlrpc_req_drop_rs() 39/47839/14
authorLei Feng <flei@whamcloud.com>
Thu, 30 Jun 2022 02:46:31 +0000 (10:46 +0800)
committerOleg Drokin <green@whamcloud.com>
Sat, 24 Sep 2022 20:28:01 +0000 (20:28 +0000)
There is a race condition that: on server side, one thread sent
reply message and is deleting the reply message, another is
searching for existing request and print some debug information
in _debug_req() if there is a duplicated request. They both operate on
req->rq_repmsg but it is not protected in ptlrpc_req_drop_rs().
So we protected it with req->rq_early_free_lock.

Signed-off-by: Lei Feng <flei@whamcloud.com>
Change-Id: Ied55427ee15c3ef84bdd2d579844eba398dbf010
Reviewed-on: https://review.whamcloud.com/47839
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Li Xi <lixi@ddn.com>
Reviewed-by: Qian Yingjin <qian@ddn.com>
Reviewed-by: Andrew Perepechko <andrew.perepechko@hpe.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/lustre_net.h
lustre/ptlrpc/service.c

index 897302c..105ef08 100644 (file)
@@ -2497,11 +2497,18 @@ ptlrpc_rs_decref(struct ptlrpc_reply_state *rs)
 /* Should only be called once per req */
 static inline void ptlrpc_req_drop_rs(struct ptlrpc_request *req)
 {
-        if (req->rq_reply_state == NULL)
-                return; /* shouldn't occur */
-        ptlrpc_rs_decref(req->rq_reply_state);
-        req->rq_reply_state = NULL;
-        req->rq_repmsg = NULL;
+       if (req->rq_reply_state == NULL)
+               return; /* shouldn't occur */
+
+       /* req_repmsg equals rq_reply_state->rs_msg,
+        * so set it to NULL before rq_reply_state is possibly freed
+        */
+       spin_lock(&req->rq_early_free_lock);
+       req->rq_repmsg = NULL;
+       spin_unlock(&req->rq_early_free_lock);
+
+       ptlrpc_rs_decref(req->rq_reply_state);
+       req->rq_reply_state = NULL;
 }
 
 static inline __u32 lustre_request_magic(struct ptlrpc_request *req)
index 9e7c34c..aeaaaca 100644 (file)
@@ -1446,6 +1446,7 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req)
                GOTO(out_free, rc = -ENOMEM);
 
        *reqcopy = *req;
+       spin_lock_init(&reqcopy->rq_early_free_lock);
        reqcopy->rq_reply_state = NULL;
        reqcopy->rq_rep_swab_mask = 0;
        reqcopy->rq_pack_bulk = 0;