From: Chuck Lever Date: Wed, 8 Feb 2017 22:00:51 +0000 (-0500) Subject: sunrpc: Allow xprt->ops->timer method to sleep X-Git-Tag: v4.1.12-124.31.3~811 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=1de90feba85832365f81b69cacf35969e217bea0;p=users%2Fjedix%2Flinux-maple.git sunrpc: Allow xprt->ops->timer method to sleep 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 Signed-off-by: Anna Schumaker Orabug: 27587008 (cherry picked from commit b977b644ccf821ab1269582f7efe1d0d85faa1f6) Signed-off-by: Calum Mackay Signed-off-by: Brian Maly --- diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index e7459668732a..6e0d6d47f9b0 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -873,13 +873,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); } static inline int xprt_has_timer(struct rpc_xprt *xprt) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 389eb3f4f301..3e2fb395708b 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1621,7 +1621,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)