diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fs-writeback.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 9e72d04e706e..e8063c938dd2 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -630,6 +630,7 @@ static long wb_writeback(struct bdi_writeback *wb, | |||
630 | }; | 630 | }; |
631 | unsigned long oldest_jif; | 631 | unsigned long oldest_jif; |
632 | long wrote = 0; | 632 | long wrote = 0; |
633 | long write_chunk; | ||
633 | struct inode *inode; | 634 | struct inode *inode; |
634 | 635 | ||
635 | if (wbc.for_kupdate) { | 636 | if (wbc.for_kupdate) { |
@@ -642,6 +643,24 @@ static long wb_writeback(struct bdi_writeback *wb, | |||
642 | wbc.range_end = LLONG_MAX; | 643 | wbc.range_end = LLONG_MAX; |
643 | } | 644 | } |
644 | 645 | ||
646 | /* | ||
647 | * WB_SYNC_ALL mode does livelock avoidance by syncing dirty | ||
648 | * inodes/pages in one big loop. Setting wbc.nr_to_write=LONG_MAX | ||
649 | * here avoids calling into writeback_inodes_wb() more than once. | ||
650 | * | ||
651 | * The intended call sequence for WB_SYNC_ALL writeback is: | ||
652 | * | ||
653 | * wb_writeback() | ||
654 | * __writeback_inodes_sb() <== called only once | ||
655 | * write_cache_pages() <== called once for each inode | ||
656 | * (quickly) tag currently dirty pages | ||
657 | * (maybe slowly) sync all tagged pages | ||
658 | */ | ||
659 | if (wbc.sync_mode == WB_SYNC_NONE) | ||
660 | write_chunk = MAX_WRITEBACK_PAGES; | ||
661 | else | ||
662 | write_chunk = LONG_MAX; | ||
663 | |||
645 | wbc.wb_start = jiffies; /* livelock avoidance */ | 664 | wbc.wb_start = jiffies; /* livelock avoidance */ |
646 | for (;;) { | 665 | for (;;) { |
647 | /* | 666 | /* |
@@ -668,7 +687,7 @@ static long wb_writeback(struct bdi_writeback *wb, | |||
668 | break; | 687 | break; |
669 | 688 | ||
670 | wbc.more_io = 0; | 689 | wbc.more_io = 0; |
671 | wbc.nr_to_write = MAX_WRITEBACK_PAGES; | 690 | wbc.nr_to_write = write_chunk; |
672 | wbc.pages_skipped = 0; | 691 | wbc.pages_skipped = 0; |
673 | 692 | ||
674 | trace_wbc_writeback_start(&wbc, wb->bdi); | 693 | trace_wbc_writeback_start(&wbc, wb->bdi); |
@@ -678,8 +697,8 @@ static long wb_writeback(struct bdi_writeback *wb, | |||
678 | writeback_inodes_wb(wb, &wbc); | 697 | writeback_inodes_wb(wb, &wbc); |
679 | trace_wbc_writeback_written(&wbc, wb->bdi); | 698 | trace_wbc_writeback_written(&wbc, wb->bdi); |
680 | 699 | ||
681 | work->nr_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write; | 700 | work->nr_pages -= write_chunk - wbc.nr_to_write; |
682 | wrote += MAX_WRITEBACK_PAGES - wbc.nr_to_write; | 701 | wrote += write_chunk - wbc.nr_to_write; |
683 | 702 | ||
684 | /* | 703 | /* |
685 | * If we consumed everything, see if we have more | 704 | * If we consumed everything, see if we have more |
@@ -694,7 +713,7 @@ static long wb_writeback(struct bdi_writeback *wb, | |||
694 | /* | 713 | /* |
695 | * Did we write something? Try for more | 714 | * Did we write something? Try for more |
696 | */ | 715 | */ |
697 | if (wbc.nr_to_write < MAX_WRITEBACK_PAGES) | 716 | if (wbc.nr_to_write < write_chunk) |
698 | continue; | 717 | continue; |
699 | /* | 718 | /* |
700 | * Nothing written. Wait for some inode to | 719 | * Nothing written. Wait for some inode to |