1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <linux/tcp.h>
25#include <linux/sunrpc/xprt.h>
26
27#ifdef RPC_DEBUG
28#define RPCDBG_FACILITY RPCDBG_TRANS
29#endif
30
31#if defined(CONFIG_NFS_V4_1)
32
33
34
35
36
37static inline int xprt_need_to_requeue(struct rpc_xprt *xprt)
38{
39 return xprt->bc_alloc_count > 0;
40}
41
42static inline void xprt_inc_alloc_count(struct rpc_xprt *xprt, unsigned int n)
43{
44 xprt->bc_alloc_count += n;
45}
46
47static inline int xprt_dec_alloc_count(struct rpc_xprt *xprt, unsigned int n)
48{
49 return xprt->bc_alloc_count -= n;
50}
51
52
53
54
55
56static void xprt_free_allocation(struct rpc_rqst *req)
57{
58 struct xdr_buf *xbufp;
59
60 dprintk("RPC: free allocations for req= %p\n", req);
61 BUG_ON(test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state));
62 xbufp = &req->rq_private_buf;
63 free_page((unsigned long)xbufp->head[0].iov_base);
64 xbufp = &req->rq_snd_buf;
65 free_page((unsigned long)xbufp->head[0].iov_base);
66 list_del(&req->rq_bc_pa_list);
67 kfree(req);
68}
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88int xprt_setup_backchannel(struct rpc_xprt *xprt, unsigned int min_reqs)
89{
90 struct page *page_rcv = NULL, *page_snd = NULL;
91 struct xdr_buf *xbufp = NULL;
92 struct rpc_rqst *req, *tmp;
93 struct list_head tmp_list;
94 int i;
95
96 dprintk("RPC: setup backchannel transport\n");
97
98
99
100
101
102
103
104
105
106 INIT_LIST_HEAD(&tmp_list);
107 for (i = 0; i < min_reqs; i++) {
108
109 req = kzalloc(sizeof(struct rpc_rqst), GFP_KERNEL);
110 if (req == NULL) {
111 printk(KERN_ERR "Failed to create bc rpc_rqst\n");
112 goto out_free;
113 }
114
115
116 dprintk("RPC: adding req= %p\n", req);
117 list_add(&req->rq_bc_pa_list, &tmp_list);
118
119 req->rq_xprt = xprt;
120 INIT_LIST_HEAD(&req->rq_list);
121 INIT_LIST_HEAD(&req->rq_bc_list);
122
123
124 page_rcv = alloc_page(GFP_KERNEL);
125 if (page_rcv == NULL) {
126 printk(KERN_ERR "Failed to create bc receive xbuf\n");
127 goto out_free;
128 }
129 xbufp = &req->rq_rcv_buf;
130 xbufp->head[0].iov_base = page_address(page_rcv);
131 xbufp->head[0].iov_len = PAGE_SIZE;
132 xbufp->tail[0].iov_base = NULL;
133 xbufp->tail[0].iov_len = 0;
134 xbufp->page_len = 0;
135 xbufp->len = PAGE_SIZE;
136 xbufp->buflen = PAGE_SIZE;
137
138
139 page_snd = alloc_page(GFP_KERNEL);
140 if (page_snd == NULL) {
141 printk(KERN_ERR "Failed to create bc snd xbuf\n");
142 goto out_free;
143 }
144
145 xbufp = &req->rq_snd_buf;
146 xbufp->head[0].iov_base = page_address(page_snd);
147 xbufp->head[0].iov_len = 0;
148 xbufp->tail[0].iov_base = NULL;
149 xbufp->tail[0].iov_len = 0;
150 xbufp->page_len = 0;
151 xbufp->len = 0;
152 xbufp->buflen = PAGE_SIZE;
153 }
154
155
156
157
158 spin_lock_bh(&xprt->bc_pa_lock);
159 list_splice(&tmp_list, &xprt->bc_pa_list);
160 xprt_inc_alloc_count(xprt, min_reqs);
161 spin_unlock_bh(&xprt->bc_pa_lock);
162
163 dprintk("RPC: setup backchannel transport done\n");
164 return 0;
165
166out_free:
167
168
169
170 list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list)
171 xprt_free_allocation(req);
172
173 dprintk("RPC: setup backchannel transport failed\n");
174 return -1;
175}
176EXPORT_SYMBOL(xprt_setup_backchannel);
177
178
179
180
181
182
183
184
185
186void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs)
187{
188 struct rpc_rqst *req = NULL, *tmp = NULL;
189
190 dprintk("RPC: destroy backchannel transport\n");
191
192 BUG_ON(max_reqs == 0);
193 spin_lock_bh(&xprt->bc_pa_lock);
194 xprt_dec_alloc_count(xprt, max_reqs);
195 list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) {
196 dprintk("RPC: req=%p\n", req);
197 xprt_free_allocation(req);
198 if (--max_reqs == 0)
199 break;
200 }
201 spin_unlock_bh(&xprt->bc_pa_lock);
202
203 dprintk("RPC: backchannel list empty= %s\n",
204 list_empty(&xprt->bc_pa_list) ? "true" : "false");
205}
206EXPORT_SYMBOL(xprt_destroy_backchannel);
207
208
209
210
211
212
213
214
215
216
217
218
219struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt)
220{
221 struct rpc_rqst *req;
222
223 dprintk("RPC: allocate a backchannel request\n");
224 spin_lock(&xprt->bc_pa_lock);
225 if (!list_empty(&xprt->bc_pa_list)) {
226 req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst,
227 rq_bc_pa_list);
228 list_del(&req->rq_bc_pa_list);
229 } else {
230 req = NULL;
231 }
232 spin_unlock(&xprt->bc_pa_lock);
233
234 if (req != NULL) {
235 set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
236 req->rq_reply_bytes_recvd = 0;
237 req->rq_bytes_sent = 0;
238 memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
239 sizeof(req->rq_private_buf));
240 }
241 dprintk("RPC: backchannel req=%p\n", req);
242 return req;
243}
244
245
246
247
248
249void xprt_free_bc_request(struct rpc_rqst *req)
250{
251 struct rpc_xprt *xprt = req->rq_xprt;
252
253 dprintk("RPC: free backchannel req=%p\n", req);
254
255 smp_mb__before_clear_bit();
256 BUG_ON(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state));
257 clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
258 smp_mb__after_clear_bit();
259
260 if (!xprt_need_to_requeue(xprt)) {
261
262
263
264
265
266
267 dprintk("RPC: Last session removed req=%p\n", req);
268 xprt_free_allocation(req);
269 return;
270 }
271
272
273
274
275
276 spin_lock_bh(&xprt->bc_pa_lock);
277 list_add(&req->rq_bc_pa_list, &xprt->bc_pa_list);
278 spin_unlock_bh(&xprt->bc_pa_lock);
279}
280
281#endif
282