@@ -379,34 +379,6 @@ static void nfs_end_page_writeback(struct nfs_page *req)
379
379
clear_bdi_congested (inode_to_bdi (inode ), BLK_RW_ASYNC );
380
380
}
381
381
382
- /*
383
- * nfs_unroll_locks_and_wait - unlock all newly locked reqs and wait on @req
384
- *
385
- * this is a helper function for nfs_lock_and_join_requests
386
- *
387
- * @inode - inode associated with request page group, must be holding inode lock
388
- * @head - head request of page group, must be holding head lock
389
- * @req - request that couldn't lock and needs to wait on the req bit lock
390
- *
391
- * NOTE: this must be called holding page_group bit lock
392
- * which will be released before returning.
393
- *
394
- * returns 0 on success, < 0 on error.
395
- */
396
- static void
397
- nfs_unroll_locks (struct inode * inode , struct nfs_page * head ,
398
- struct nfs_page * req )
399
- {
400
- struct nfs_page * tmp ;
401
-
402
- /* relinquish all the locks successfully grabbed this run */
403
- for (tmp = head -> wb_this_page ; tmp != req ; tmp = tmp -> wb_this_page ) {
404
- if (!kref_read (& tmp -> wb_kref ))
405
- continue ;
406
- nfs_unlock_and_release_request (tmp );
407
- }
408
- }
409
-
410
382
/*
411
383
* nfs_destroy_unlinked_subrequests - destroy recently unlinked subrequests
412
384
*
@@ -487,7 +459,7 @@ nfs_lock_and_join_requests(struct page *page)
487
459
struct inode * inode = page_file_mapping (page )-> host ;
488
460
struct nfs_page * head , * subreq ;
489
461
struct nfs_page * destroy_list = NULL ;
490
- unsigned int total_bytes ;
462
+ unsigned int pgbase , off , bytes ;
491
463
int ret ;
492
464
493
465
try_again :
@@ -520,49 +492,30 @@ nfs_lock_and_join_requests(struct page *page)
520
492
goto release_request ;
521
493
522
494
/* lock each request in the page group */
523
- total_bytes = head -> wb_bytes ;
495
+ ret = nfs_page_group_lock_subrequests (head );
496
+ if (ret < 0 )
497
+ goto release_request ;
498
+
499
+ pgbase = head -> wb_pgbase ;
500
+ bytes = head -> wb_bytes ;
501
+ off = head -> wb_offset ;
524
502
for (subreq = head -> wb_this_page ; subreq != head ;
525
503
subreq = subreq -> wb_this_page ) {
526
-
527
- if (!kref_get_unless_zero (& subreq -> wb_kref )) {
528
- if (subreq -> wb_offset == head -> wb_offset + total_bytes )
529
- total_bytes += subreq -> wb_bytes ;
530
- continue ;
531
- }
532
-
533
- while (!nfs_lock_request (subreq )) {
534
- /*
535
- * Unlock page to allow nfs_page_group_sync_on_bit()
536
- * to succeed
537
- */
538
- nfs_page_group_unlock (head );
539
- ret = nfs_wait_on_request (subreq );
540
- if (!ret )
541
- ret = nfs_page_group_lock (head );
542
- if (ret < 0 ) {
543
- nfs_unroll_locks (inode , head , subreq );
544
- nfs_release_request (subreq );
545
- goto release_request ;
546
- }
547
- }
548
- /*
549
- * Subrequests are always contiguous, non overlapping
550
- * and in order - but may be repeated (mirrored writes).
551
- */
552
- if (subreq -> wb_offset == (head -> wb_offset + total_bytes )) {
553
- /* keep track of how many bytes this group covers */
554
- total_bytes += subreq -> wb_bytes ;
555
- } else if (WARN_ON_ONCE (subreq -> wb_offset < head -> wb_offset ||
556
- ((subreq -> wb_offset + subreq -> wb_bytes ) >
557
- (head -> wb_offset + total_bytes )))) {
558
- nfs_page_group_unlock (head );
559
- nfs_unroll_locks (inode , head , subreq );
560
- nfs_unlock_and_release_request (subreq );
561
- ret = - EIO ;
562
- goto release_request ;
504
+ /* Subrequests should always form a contiguous range */
505
+ if (pgbase > subreq -> wb_pgbase ) {
506
+ off -= pgbase - subreq -> wb_pgbase ;
507
+ bytes += pgbase - subreq -> wb_pgbase ;
508
+ pgbase = subreq -> wb_pgbase ;
563
509
}
510
+ bytes = max (subreq -> wb_pgbase + subreq -> wb_bytes
511
+ - pgbase , bytes );
564
512
}
565
513
514
+ /* Set the head request's range to cover the former page group */
515
+ head -> wb_pgbase = pgbase ;
516
+ head -> wb_bytes = bytes ;
517
+ head -> wb_offset = off ;
518
+
566
519
/* Now that all requests are locked, make sure they aren't on any list.
567
520
* Commit list removal accounting is done after locks are dropped */
568
521
subreq = head ;
@@ -576,10 +529,6 @@ nfs_lock_and_join_requests(struct page *page)
576
529
/* destroy list will be terminated by head */
577
530
destroy_list = head -> wb_this_page ;
578
531
head -> wb_this_page = head ;
579
-
580
- /* change head request to cover whole range that
581
- * the former page group covered */
582
- head -> wb_bytes = total_bytes ;
583
532
}
584
533
585
534
/* Postpone destruction of this request */
0 commit comments