aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/rxrpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/afs/rxrpc.c')
-rw-r--r--fs/afs/rxrpc.c80
1 files changed, 76 insertions, 4 deletions
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index 222c1a3abbb8..04189c47d6a0 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -237,6 +237,70 @@ void afs_flat_call_destructor(struct afs_call *call)
237} 237}
238 238
239/* 239/*
240 * attach the data from a bunch of pages on an inode to a call
241 */
242int afs_send_pages(struct afs_call *call, struct msghdr *msg, struct kvec *iov)
243{
244 struct page *pages[8];
245 unsigned count, n, loop, offset, to;
246 pgoff_t first = call->first, last = call->last;
247 int ret;
248
249 _enter("");
250
251 offset = call->first_offset;
252 call->first_offset = 0;
253
254 do {
255 _debug("attach %lx-%lx", first, last);
256
257 count = last - first + 1;
258 if (count > ARRAY_SIZE(pages))
259 count = ARRAY_SIZE(pages);
260 n = find_get_pages_contig(call->mapping, first, count, pages);
261 ASSERTCMP(n, ==, count);
262
263 loop = 0;
264 do {
265 msg->msg_flags = 0;
266 to = PAGE_SIZE;
267 if (first + loop >= last)
268 to = call->last_to;
269 else
270 msg->msg_flags = MSG_MORE;
271 iov->iov_base = kmap(pages[loop]) + offset;
272 iov->iov_len = to - offset;
273 offset = 0;
274
275 _debug("- range %u-%u%s",
276 offset, to, msg->msg_flags ? " [more]" : "");
277 msg->msg_iov = (struct iovec *) iov;
278 msg->msg_iovlen = 1;
279
280 /* have to change the state *before* sending the last
281 * packet as RxRPC might give us the reply before it
282 * returns from sending the request */
283 if (first + loop >= last)
284 call->state = AFS_CALL_AWAIT_REPLY;
285 ret = rxrpc_kernel_send_data(call->rxcall, msg,
286 to - offset);
287 kunmap(pages[loop]);
288 if (ret < 0)
289 break;
290 } while (++loop < count);
291 first += count;
292
293 for (loop = 0; loop < count; loop++)
294 put_page(pages[loop]);
295 if (ret < 0)
296 break;
297 } while (first < last);
298
299 _leave(" = %d", ret);
300 return ret;
301}
302
303/*
240 * initiate a call 304 * initiate a call
241 */ 305 */
242int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp, 306int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
@@ -253,8 +317,9 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
253 ASSERT(call->type != NULL); 317 ASSERT(call->type != NULL);
254 ASSERT(call->type->name != NULL); 318 ASSERT(call->type->name != NULL);
255 319
256 _debug("MAKE %p{%s} [%d]", 320 _debug("____MAKE %p{%s,%x} [%d]____",
257 call, call->type->name, atomic_read(&afs_outstanding_calls)); 321 call, call->type->name, key_serial(call->key),
322 atomic_read(&afs_outstanding_calls));
258 323
259 call->wait_mode = wait_mode; 324 call->wait_mode = wait_mode;
260 INIT_WORK(&call->async_work, afs_process_async_call); 325 INIT_WORK(&call->async_work, afs_process_async_call);
@@ -289,16 +354,23 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
289 msg.msg_iovlen = 1; 354 msg.msg_iovlen = 1;
290 msg.msg_control = NULL; 355 msg.msg_control = NULL;
291 msg.msg_controllen = 0; 356 msg.msg_controllen = 0;
292 msg.msg_flags = 0; 357 msg.msg_flags = (call->send_pages ? MSG_MORE : 0);
293 358
294 /* have to change the state *before* sending the last packet as RxRPC 359 /* have to change the state *before* sending the last packet as RxRPC
295 * might give us the reply before it returns from sending the 360 * might give us the reply before it returns from sending the
296 * request */ 361 * request */
297 call->state = AFS_CALL_AWAIT_REPLY; 362 if (!call->send_pages)
363 call->state = AFS_CALL_AWAIT_REPLY;
298 ret = rxrpc_kernel_send_data(rxcall, &msg, call->request_size); 364 ret = rxrpc_kernel_send_data(rxcall, &msg, call->request_size);
299 if (ret < 0) 365 if (ret < 0)
300 goto error_do_abort; 366 goto error_do_abort;
301 367
368 if (call->send_pages) {
369 ret = afs_send_pages(call, &msg, iov);
370 if (ret < 0)
371 goto error_do_abort;
372 }
373
302 /* at this point, an async call may no longer exist as it may have 374 /* at this point, an async call may no longer exist as it may have
303 * already completed */ 375 * already completed */
304 return wait_mode->wait(call); 376 return wait_mode->wait(call);