Whamcloud - gitweb
LU-2263 ptlrpc: deadlock of obd_import::imp_lock
authorLiang Zhen <liang@whamcloud.com>
Fri, 21 Dec 2012 06:27:57 +0000 (14:27 +0800)
committerAndreas Dilger <andreas.dilger@intel.com>
Mon, 14 Jan 2013 20:13:29 +0000 (15:13 -0500)
ptlrpc_at_recv_early_reply() calls ptlrpc_at_set_req_timeout() with
hold of ptlrpc_request::rq_lock, and
ptlrpc_at_set_req_timeout()->import_at_get_index() requires imp_lock,
it violates locking-order rule of Lustre, which assumes rq_lock can
nest in imp_lock.

Signed-off-by: Liang Zhen <liang@whamcloud.com>
Change-Id: I924839b59ca1fa1cdf01568872de867ce3985f8b
Reviewed-on: http://review.whamcloud.com/4880
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Alex Zhuravlev <bzzz@whamcloud.com>
lustre/ptlrpc/client.c

index 55818fe..5ebdef3 100644 (file)
@@ -354,27 +354,28 @@ static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req)
 
         sptlrpc_cli_finish_early_reply(early_req);
 
-       spin_lock(&req->rq_lock);
+       if (rc != 0) {
+               spin_lock(&req->rq_lock);
+               RETURN(rc);
+       }
 
-        if (rc == 0) {
-                /* Adjust the local timeout for this req */
-                ptlrpc_at_set_req_timeout(req);
-
-                olddl = req->rq_deadline;
-                /* server assumes it now has rq_timeout from when it sent the
-                   early reply, so client should give it at least that long. */
-                req->rq_deadline = cfs_time_current_sec() + req->rq_timeout +
-                            ptlrpc_at_get_net_latency(req);
-
-                DEBUG_REQ(D_ADAPTTO, req,
-                          "Early reply #%d, new deadline in "CFS_DURATION_T"s "
-                          "("CFS_DURATION_T"s)", req->rq_early_count,
-                          cfs_time_sub(req->rq_deadline,
-                                       cfs_time_current_sec()),
-                          cfs_time_sub(req->rq_deadline, olddl));
-        }
+       /* Adjust the local timeout for this req */
+       ptlrpc_at_set_req_timeout(req);
 
-        RETURN(rc);
+       spin_lock(&req->rq_lock);
+       olddl = req->rq_deadline;
+       /* server assumes it now has rq_timeout from when it sent the
+        * early reply, so client should give it at least that long. */
+       req->rq_deadline = cfs_time_current_sec() + req->rq_timeout +
+                          ptlrpc_at_get_net_latency(req);
+
+       DEBUG_REQ(D_ADAPTTO, req,
+                 "Early reply #%d, new deadline in "CFS_DURATION_T"s "
+                 "("CFS_DURATION_T"s)", req->rq_early_count,
+                 cfs_time_sub(req->rq_deadline, cfs_time_current_sec()),
+                 cfs_time_sub(req->rq_deadline, olddl));
+
+       RETURN(rc);
 }
 
 /**