]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/5.0.4/sunrpc-fix-up-rpc-back-channel-transmission.patch
Linux 5.0.4
[thirdparty/kernel/stable-queue.git] / releases / 5.0.4 / sunrpc-fix-up-rpc-back-channel-transmission.patch
1 From 477687e1116ad16180caf8633dd830b296a5ce73 Mon Sep 17 00:00:00 2001
2 From: Trond Myklebust <trond.myklebust@hammerspace.com>
3 Date: Tue, 5 Mar 2019 07:30:48 -0500
4 Subject: SUNRPC: Fix up RPC back channel transmission
5
6 From: Trond Myklebust <trond.myklebust@hammerspace.com>
7
8 commit 477687e1116ad16180caf8633dd830b296a5ce73 upstream.
9
10 Now that transmissions happen through a queue, we require the RPC tasks
11 to handle error conditions that may have been set while they were
12 sleeping. The back channel does not currently do this, but assumes
13 that any error condition happens during its own call to xprt_transmit().
14
15 The solution is to ensure that the back channel splits out the
16 error handling just like the forward channel does.
17
18 Fixes: 89f90fe1ad8b ("SUNRPC: Allow calls to xprt_transmit() to drain...")
19 Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
20 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
21
22 ---
23 net/sunrpc/clnt.c | 61 +++++++++++++++++++++++++++++-------------------------
24 1 file changed, 33 insertions(+), 28 deletions(-)
25
26 --- a/net/sunrpc/clnt.c
27 +++ b/net/sunrpc/clnt.c
28 @@ -66,9 +66,6 @@ static void call_decode(struct rpc_task
29 static void call_bind(struct rpc_task *task);
30 static void call_bind_status(struct rpc_task *task);
31 static void call_transmit(struct rpc_task *task);
32 -#if defined(CONFIG_SUNRPC_BACKCHANNEL)
33 -static void call_bc_transmit(struct rpc_task *task);
34 -#endif /* CONFIG_SUNRPC_BACKCHANNEL */
35 static void call_status(struct rpc_task *task);
36 static void call_transmit_status(struct rpc_task *task);
37 static void call_refresh(struct rpc_task *task);
38 @@ -1131,6 +1128,8 @@ rpc_call_async(struct rpc_clnt *clnt, co
39 EXPORT_SYMBOL_GPL(rpc_call_async);
40
41 #if defined(CONFIG_SUNRPC_BACKCHANNEL)
42 +static void call_bc_encode(struct rpc_task *task);
43 +
44 /**
45 * rpc_run_bc_task - Allocate a new RPC task for backchannel use, then run
46 * rpc_execute against it
47 @@ -1152,7 +1151,7 @@ struct rpc_task *rpc_run_bc_task(struct
48 task = rpc_new_task(&task_setup_data);
49 xprt_init_bc_request(req, task);
50
51 - task->tk_action = call_bc_transmit;
52 + task->tk_action = call_bc_encode;
53 atomic_inc(&task->tk_count);
54 WARN_ON_ONCE(atomic_read(&task->tk_count) != 2);
55 rpc_execute(task);
56 @@ -2064,6 +2063,16 @@ call_transmit_status(struct rpc_task *ta
57 }
58
59 #if defined(CONFIG_SUNRPC_BACKCHANNEL)
60 +static void call_bc_transmit(struct rpc_task *task);
61 +static void call_bc_transmit_status(struct rpc_task *task);
62 +
63 +static void
64 +call_bc_encode(struct rpc_task *task)
65 +{
66 + xprt_request_enqueue_transmit(task);
67 + task->tk_action = call_bc_transmit;
68 +}
69 +
70 /*
71 * 5b. Send the backchannel RPC reply. On error, drop the reply. In
72 * addition, disconnect on connectivity errors.
73 @@ -2071,26 +2080,23 @@ call_transmit_status(struct rpc_task *ta
74 static void
75 call_bc_transmit(struct rpc_task *task)
76 {
77 - struct rpc_rqst *req = task->tk_rqstp;
78 -
79 - if (rpc_task_need_encode(task))
80 - xprt_request_enqueue_transmit(task);
81 - if (!test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate))
82 - goto out_wakeup;
83 -
84 - if (!xprt_prepare_transmit(task))
85 - goto out_retry;
86 -
87 - if (task->tk_status < 0) {
88 - printk(KERN_NOTICE "RPC: Could not send backchannel reply "
89 - "error: %d\n", task->tk_status);
90 - goto out_done;
91 + task->tk_action = call_bc_transmit_status;
92 + if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) {
93 + if (!xprt_prepare_transmit(task))
94 + return;
95 + task->tk_status = 0;
96 + xprt_transmit(task);
97 }
98 + xprt_end_transmit(task);
99 +}
100
101 - xprt_transmit(task);
102 +static void
103 +call_bc_transmit_status(struct rpc_task *task)
104 +{
105 + struct rpc_rqst *req = task->tk_rqstp;
106
107 - xprt_end_transmit(task);
108 dprint_status(task);
109 +
110 switch (task->tk_status) {
111 case 0:
112 /* Success */
113 @@ -2104,8 +2110,14 @@ call_bc_transmit(struct rpc_task *task)
114 case -ENOTCONN:
115 case -EPIPE:
116 break;
117 + case -ENOBUFS:
118 + rpc_delay(task, HZ>>2);
119 + /* fall through */
120 + case -EBADSLT:
121 case -EAGAIN:
122 - goto out_retry;
123 + task->tk_status = 0;
124 + task->tk_action = call_bc_transmit;
125 + return;
126 case -ETIMEDOUT:
127 /*
128 * Problem reaching the server. Disconnect and let the
129 @@ -2124,18 +2136,11 @@ call_bc_transmit(struct rpc_task *task)
130 * We were unable to reply and will have to drop the
131 * request. The server should reconnect and retransmit.
132 */
133 - WARN_ON_ONCE(task->tk_status == -EAGAIN);
134 printk(KERN_NOTICE "RPC: Could not send backchannel reply "
135 "error: %d\n", task->tk_status);
136 break;
137 }
138 -out_wakeup:
139 - rpc_wake_up_queued_task(&req->rq_xprt->pending, task);
140 -out_done:
141 task->tk_action = rpc_exit_task;
142 - return;
143 -out_retry:
144 - task->tk_status = 0;
145 }
146 #endif /* CONFIG_SUNRPC_BACKCHANNEL */
147