sunrpc: Allow xprt->ops->timer method to sleep
authorChuck Lever <chuck.lever@oracle.com>
Wed, 8 Feb 2017 22:00:51 +0000 (17:00 -0500)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Fri, 10 Feb 2017 19:02:37 +0000 (14:02 -0500)
The transport lock is needed to protect the xprt_adjust_cwnd() call
in xs_udp_timer, but it is not necessary for accessing the
rq_reply_bytes_recvd or tk_status fields. It is correct to sublimate
the lock into UDP's xs_udp_timer method, where it is required.

The ->timer method has to take the transport lock if needed, but it
can now sleep safely, or even call back into the RPC scheduler.

This is more a clean-up than a fix, but the "issue" was introduced
by my transport switch patches back in 2005.

Fixes: 46c0ee8bc4ad ("RPC: separate xprt_timer implementations")
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c

index 9a6be030ca7d21dbfee63664536872cc395bdc55..b530a2852ba87ac042baec67bf64a3e57e1232b5 100644 (file)
@@ -897,13 +897,11 @@ static void xprt_timer(struct rpc_task *task)
                return;
        dprintk("RPC: %5u xprt_timer\n", task->tk_pid);
 
-       spin_lock_bh(&xprt->transport_lock);
        if (!req->rq_reply_bytes_recvd) {
                if (xprt->ops->timer)
                        xprt->ops->timer(xprt, task);
        } else
                task->tk_status = 0;
-       spin_unlock_bh(&xprt->transport_lock);
 }
 
 /**
index 810e9b59be167f1ddc6618bcc3d52a9442304a61..18b4e7ff8879c1c684d4040f25399f0bed0801e4 100644 (file)
@@ -1739,7 +1739,9 @@ static void xs_udp_set_buffer_size(struct rpc_xprt *xprt, size_t sndsize, size_t
  */
 static void xs_udp_timer(struct rpc_xprt *xprt, struct rpc_task *task)
 {
+       spin_lock_bh(&xprt->transport_lock);
        xprt_adjust_cwnd(xprt, task, -ETIMEDOUT);
+       spin_unlock_bh(&xprt->transport_lock);
 }
 
 static unsigned short xs_get_random_port(void)