@@ -309,15 +309,19 @@ int afs_fs_fetch_file_status(struct afs_server *server,
309
309
static int afs_deliver_fs_fetch_data (struct afs_call * call )
310
310
{
311
311
struct afs_vnode * vnode = call -> reply ;
312
+ struct afs_read * req = call -> reply3 ;
312
313
const __be32 * bp ;
313
- struct page * page ;
314
+ unsigned int size ;
314
315
void * buffer ;
315
316
int ret ;
316
317
317
- _enter ("{%u}" , call -> unmarshall );
318
+ _enter ("{%u,%zu/%u;%u/%llu}" ,
319
+ call -> unmarshall , call -> offset , call -> count ,
320
+ req -> remain , req -> actual_len );
318
321
319
322
switch (call -> unmarshall ) {
320
323
case 0 :
324
+ req -> actual_len = 0 ;
321
325
call -> offset = 0 ;
322
326
call -> unmarshall ++ ;
323
327
if (call -> operation_ID != FSFETCHDATA64 ) {
@@ -334,10 +338,8 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
334
338
if (ret < 0 )
335
339
return ret ;
336
340
337
- call -> count = ntohl (call -> tmp );
338
- _debug ("DATA length MSW: %u" , call -> count );
339
- if (call -> count > 0 )
340
- return - EBADMSG ;
341
+ req -> actual_len = ntohl (call -> tmp );
342
+ req -> actual_len <<= 32 ;
341
343
call -> offset = 0 ;
342
344
call -> unmarshall ++ ;
343
345
@@ -349,26 +351,52 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
349
351
if (ret < 0 )
350
352
return ret ;
351
353
352
- call -> count = ntohl (call -> tmp );
353
- _debug ("DATA length: %u" , call -> count );
354
- if (call -> count > PAGE_SIZE )
354
+ req -> actual_len |= ntohl (call -> tmp );
355
+ _debug ("DATA length: %llu" , req -> actual_len );
356
+ /* Check that the server didn't want to send us extra. We
357
+ * might want to just discard instead, but that requires
358
+ * cooperation from AF_RXRPC.
359
+ */
360
+ if (req -> actual_len > req -> len )
355
361
return - EBADMSG ;
356
- call -> offset = 0 ;
362
+
363
+ req -> remain = req -> actual_len ;
364
+ call -> offset = req -> pos & (PAGE_SIZE - 1 );
365
+ req -> index = 0 ;
366
+ if (req -> actual_len == 0 )
367
+ goto no_more_data ;
357
368
call -> unmarshall ++ ;
358
369
370
+ begin_page :
371
+ if (req -> remain > PAGE_SIZE - call -> offset )
372
+ size = PAGE_SIZE - call -> offset ;
373
+ else
374
+ size = req -> remain ;
375
+ call -> count = call -> offset + size ;
376
+ ASSERTCMP (call -> count , <=, PAGE_SIZE );
377
+ req -> remain -= size ;
378
+
359
379
/* extract the returned data */
360
380
case 3 :
361
- _debug ("extract data" );
362
- if (call -> count > 0 ) {
363
- page = call -> reply3 ;
364
- buffer = kmap (page );
365
- ret = afs_extract_data (call , buffer ,
366
- call -> count , true);
367
- kunmap (page );
368
- if (ret < 0 )
369
- return ret ;
381
+ _debug ("extract data %u/%llu %zu/%u" ,
382
+ req -> remain , req -> actual_len , call -> offset , call -> count );
383
+
384
+ buffer = kmap (req -> pages [req -> index ]);
385
+ ret = afs_extract_data (call , buffer , call -> count , true);
386
+ kunmap (req -> pages [req -> index ]);
387
+ if (ret < 0 )
388
+ return ret ;
389
+ if (call -> offset == PAGE_SIZE ) {
390
+ if (req -> page_done )
391
+ req -> page_done (call , req );
392
+ if (req -> remain > 0 ) {
393
+ req -> index ++ ;
394
+ call -> offset = 0 ;
395
+ goto begin_page ;
396
+ }
370
397
}
371
398
399
+ no_more_data :
372
400
call -> offset = 0 ;
373
401
call -> unmarshall ++ ;
374
402
@@ -393,32 +421,40 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
393
421
}
394
422
395
423
if (call -> count < PAGE_SIZE ) {
396
- _debug ("clear" );
397
- page = call -> reply3 ;
398
- buffer = kmap (page );
424
+ buffer = kmap (req -> pages [req -> index ]);
399
425
memset (buffer + call -> count , 0 , PAGE_SIZE - call -> count );
400
- kunmap (page );
426
+ kunmap (req -> pages [req -> index ]);
427
+ if (req -> page_done )
428
+ req -> page_done (call , req );
401
429
}
402
430
403
431
_leave (" = 0 [done]" );
404
432
return 0 ;
405
433
}
406
434
435
+ static void afs_fetch_data_destructor (struct afs_call * call )
436
+ {
437
+ struct afs_read * req = call -> reply3 ;
438
+
439
+ afs_put_read (req );
440
+ afs_flat_call_destructor (call );
441
+ }
442
+
407
443
/*
408
444
* FS.FetchData operation type
409
445
*/
410
446
static const struct afs_call_type afs_RXFSFetchData = {
411
447
.name = "FS.FetchData" ,
412
448
.deliver = afs_deliver_fs_fetch_data ,
413
449
.abort_to_error = afs_abort_to_error ,
414
- .destructor = afs_flat_call_destructor ,
450
+ .destructor = afs_fetch_data_destructor ,
415
451
};
416
452
417
453
static const struct afs_call_type afs_RXFSFetchData64 = {
418
454
.name = "FS.FetchData64" ,
419
455
.deliver = afs_deliver_fs_fetch_data ,
420
456
.abort_to_error = afs_abort_to_error ,
421
- .destructor = afs_flat_call_destructor ,
457
+ .destructor = afs_fetch_data_destructor ,
422
458
};
423
459
424
460
/*
@@ -427,25 +463,22 @@ static const struct afs_call_type afs_RXFSFetchData64 = {
427
463
static int afs_fs_fetch_data64 (struct afs_server * server ,
428
464
struct key * key ,
429
465
struct afs_vnode * vnode ,
430
- off_t offset , size_t length ,
431
- struct page * buffer ,
466
+ struct afs_read * req ,
432
467
const struct afs_wait_mode * wait_mode )
433
468
{
434
469
struct afs_call * call ;
435
470
__be32 * bp ;
436
471
437
472
_enter ("" );
438
473
439
- ASSERTCMP (length , < , ULONG_MAX );
440
-
441
474
call = afs_alloc_flat_call (& afs_RXFSFetchData64 , 32 , (21 + 3 + 6 ) * 4 );
442
475
if (!call )
443
476
return - ENOMEM ;
444
477
445
478
call -> key = key ;
446
479
call -> reply = vnode ;
447
480
call -> reply2 = NULL ; /* volsync */
448
- call -> reply3 = buffer ;
481
+ call -> reply3 = req ;
449
482
call -> service_id = FS_SERVICE ;
450
483
call -> port = htons (AFS_FS_PORT );
451
484
call -> operation_ID = FSFETCHDATA64 ;
@@ -456,11 +489,12 @@ static int afs_fs_fetch_data64(struct afs_server *server,
456
489
bp [1 ] = htonl (vnode -> fid .vid );
457
490
bp [2 ] = htonl (vnode -> fid .vnode );
458
491
bp [3 ] = htonl (vnode -> fid .unique );
459
- bp [4 ] = htonl (upper_32_bits (offset ));
460
- bp [5 ] = htonl (( u32 ) offset );
492
+ bp [4 ] = htonl (upper_32_bits (req -> pos ));
493
+ bp [5 ] = htonl (lower_32_bits ( req -> pos ) );
461
494
bp [6 ] = 0 ;
462
- bp [7 ] = htonl (( u32 ) length );
495
+ bp [7 ] = htonl (lower_32_bits ( req -> len ) );
463
496
497
+ atomic_inc (& req -> usage );
464
498
return afs_make_call (& server -> addr , call , GFP_NOFS , wait_mode );
465
499
}
466
500
@@ -470,16 +504,16 @@ static int afs_fs_fetch_data64(struct afs_server *server,
470
504
int afs_fs_fetch_data (struct afs_server * server ,
471
505
struct key * key ,
472
506
struct afs_vnode * vnode ,
473
- off_t offset , size_t length ,
474
- struct page * buffer ,
507
+ struct afs_read * req ,
475
508
const struct afs_wait_mode * wait_mode )
476
509
{
477
510
struct afs_call * call ;
478
511
__be32 * bp ;
479
512
480
- if (upper_32_bits (offset ) || upper_32_bits (offset + length ))
481
- return afs_fs_fetch_data64 (server , key , vnode , offset , length ,
482
- buffer , wait_mode );
513
+ if (upper_32_bits (req -> pos ) ||
514
+ upper_32_bits (req -> len ) ||
515
+ upper_32_bits (req -> pos + req -> len ))
516
+ return afs_fs_fetch_data64 (server , key , vnode , req , wait_mode );
483
517
484
518
_enter ("" );
485
519
@@ -490,7 +524,7 @@ int afs_fs_fetch_data(struct afs_server *server,
490
524
call -> key = key ;
491
525
call -> reply = vnode ;
492
526
call -> reply2 = NULL ; /* volsync */
493
- call -> reply3 = buffer ;
527
+ call -> reply3 = req ;
494
528
call -> service_id = FS_SERVICE ;
495
529
call -> port = htons (AFS_FS_PORT );
496
530
call -> operation_ID = FSFETCHDATA ;
@@ -501,9 +535,10 @@ int afs_fs_fetch_data(struct afs_server *server,
501
535
bp [1 ] = htonl (vnode -> fid .vid );
502
536
bp [2 ] = htonl (vnode -> fid .vnode );
503
537
bp [3 ] = htonl (vnode -> fid .unique );
504
- bp [4 ] = htonl (offset );
505
- bp [5 ] = htonl (length );
538
+ bp [4 ] = htonl (lower_32_bits ( req -> pos ) );
539
+ bp [5 ] = htonl (lower_32_bits ( req -> len ) );
506
540
541
+ atomic_inc (& req -> usage );
507
542
return afs_make_call (& server -> addr , call , GFP_NOFS , wait_mode );
508
543
}
509
544
0 commit comments