diff options
author | Christoph Hellwig <hch@lst.de> | 2010-06-10 06:07:54 -0400 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2010-07-06 02:54:08 -0400 |
commit | edadfb10ba35da7253541e4155aa92eff758ebe6 (patch) | |
tree | a3c676f7b2c9b301d7e1948febeaba76ea1c5850 /fs | |
parent | 9c3a8ee8a1d72c5c0d7fbdf426d80e270ddfa54c (diff) |
writeback: split writeback_inodes_wb
The case where we have a superblock doesn't require a loop here as we scan
over all inodes in writeback_sb_inodes. Split it out into a separate helper
to make the code simpler. This also allows to get rid of the sb member in
struct writeback_control, which was rather out of place there.
Also update the comments in writeback_sb_inodes that explain the handling
of inodes from wrong superblocks.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fs-writeback.c | 82 |
1 files changed, 46 insertions, 36 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 94a602e98bb5..8cc06d5432b5 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -554,29 +554,41 @@ static bool pin_sb_for_writeback(struct super_block *sb) | |||
554 | 554 | ||
555 | /* | 555 | /* |
556 | * Write a portion of b_io inodes which belong to @sb. | 556 | * Write a portion of b_io inodes which belong to @sb. |
557 | * If @wbc->sb != NULL, then find and write all such | 557 | * |
558 | * If @only_this_sb is true, then find and write all such | ||
558 | * inodes. Otherwise write only ones which go sequentially | 559 | * inodes. Otherwise write only ones which go sequentially |
559 | * in reverse order. | 560 | * in reverse order. |
561 | * | ||
560 | * Return 1, if the caller writeback routine should be | 562 | * Return 1, if the caller writeback routine should be |
561 | * interrupted. Otherwise return 0. | 563 | * interrupted. Otherwise return 0. |
562 | */ | 564 | */ |
563 | static int writeback_sb_inodes(struct super_block *sb, | 565 | static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb, |
564 | struct bdi_writeback *wb, | 566 | struct writeback_control *wbc, bool only_this_sb) |
565 | struct writeback_control *wbc) | ||
566 | { | 567 | { |
567 | while (!list_empty(&wb->b_io)) { | 568 | while (!list_empty(&wb->b_io)) { |
568 | long pages_skipped; | 569 | long pages_skipped; |
569 | struct inode *inode = list_entry(wb->b_io.prev, | 570 | struct inode *inode = list_entry(wb->b_io.prev, |
570 | struct inode, i_list); | 571 | struct inode, i_list); |
571 | if (wbc->sb && sb != inode->i_sb) { | 572 | |
572 | /* super block given and doesn't | 573 | if (inode->i_sb != sb) { |
573 | match, skip this inode */ | 574 | if (only_this_sb) { |
574 | redirty_tail(inode); | 575 | /* |
575 | continue; | 576 | * We only want to write back data for this |
576 | } | 577 | * superblock, move all inodes not belonging |
577 | if (sb != inode->i_sb) | 578 | * to it back onto the dirty list. |
578 | /* finish with this superblock */ | 579 | */ |
580 | redirty_tail(inode); | ||
581 | continue; | ||
582 | } | ||
583 | |||
584 | /* | ||
585 | * The inode belongs to a different superblock. | ||
586 | * Bounce back to the caller to unpin this and | ||
587 | * pin the next superblock. | ||
588 | */ | ||
579 | return 0; | 589 | return 0; |
590 | } | ||
591 | |||
580 | if (inode->i_state & (I_NEW | I_WILL_FREE)) { | 592 | if (inode->i_state & (I_NEW | I_WILL_FREE)) { |
581 | requeue_io(inode); | 593 | requeue_io(inode); |
582 | continue; | 594 | continue; |
@@ -629,29 +641,12 @@ void writeback_inodes_wb(struct bdi_writeback *wb, | |||
629 | struct inode, i_list); | 641 | struct inode, i_list); |
630 | struct super_block *sb = inode->i_sb; | 642 | struct super_block *sb = inode->i_sb; |
631 | 643 | ||
632 | if (wbc->sb) { | 644 | if (!pin_sb_for_writeback(sb)) { |
633 | /* | 645 | requeue_io(inode); |
634 | * We are requested to write out inodes for a specific | 646 | continue; |
635 | * superblock. This means we already have s_umount | ||
636 | * taken by the caller which also waits for us to | ||
637 | * complete the writeout. | ||
638 | */ | ||
639 | if (sb != wbc->sb) { | ||
640 | redirty_tail(inode); | ||
641 | continue; | ||
642 | } | ||
643 | |||
644 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); | ||
645 | |||
646 | ret = writeback_sb_inodes(sb, wb, wbc); | ||
647 | } else { | ||
648 | if (!pin_sb_for_writeback(sb)) { | ||
649 | requeue_io(inode); | ||
650 | continue; | ||
651 | } | ||
652 | ret = writeback_sb_inodes(sb, wb, wbc); | ||
653 | drop_super(sb); | ||
654 | } | 647 | } |
648 | ret = writeback_sb_inodes(sb, wb, wbc, false); | ||
649 | drop_super(sb); | ||
655 | 650 | ||
656 | if (ret) | 651 | if (ret) |
657 | break; | 652 | break; |
@@ -660,6 +655,19 @@ void writeback_inodes_wb(struct bdi_writeback *wb, | |||
660 | /* Leave any unwritten inodes on b_io */ | 655 | /* Leave any unwritten inodes on b_io */ |
661 | } | 656 | } |
662 | 657 | ||
658 | static void __writeback_inodes_sb(struct super_block *sb, | ||
659 | struct bdi_writeback *wb, struct writeback_control *wbc) | ||
660 | { | ||
661 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); | ||
662 | |||
663 | wbc->wb_start = jiffies; /* livelock avoidance */ | ||
664 | spin_lock(&inode_lock); | ||
665 | if (!wbc->for_kupdate || list_empty(&wb->b_io)) | ||
666 | queue_io(wb, wbc->older_than_this); | ||
667 | writeback_sb_inodes(sb, wb, wbc, true); | ||
668 | spin_unlock(&inode_lock); | ||
669 | } | ||
670 | |||
663 | /* | 671 | /* |
664 | * The maximum number of pages to writeout in a single bdi flush/kupdate | 672 | * The maximum number of pages to writeout in a single bdi flush/kupdate |
665 | * operation. We do this so we don't hold I_SYNC against an inode for | 673 | * operation. We do this so we don't hold I_SYNC against an inode for |
@@ -698,7 +706,6 @@ static long wb_writeback(struct bdi_writeback *wb, | |||
698 | struct wb_writeback_args *args) | 706 | struct wb_writeback_args *args) |
699 | { | 707 | { |
700 | struct writeback_control wbc = { | 708 | struct writeback_control wbc = { |
701 | .sb = args->sb, | ||
702 | .sync_mode = args->sync_mode, | 709 | .sync_mode = args->sync_mode, |
703 | .older_than_this = NULL, | 710 | .older_than_this = NULL, |
704 | .for_kupdate = args->for_kupdate, | 711 | .for_kupdate = args->for_kupdate, |
@@ -736,7 +743,10 @@ static long wb_writeback(struct bdi_writeback *wb, | |||
736 | wbc.more_io = 0; | 743 | wbc.more_io = 0; |
737 | wbc.nr_to_write = MAX_WRITEBACK_PAGES; | 744 | wbc.nr_to_write = MAX_WRITEBACK_PAGES; |
738 | wbc.pages_skipped = 0; | 745 | wbc.pages_skipped = 0; |
739 | writeback_inodes_wb(wb, &wbc); | 746 | if (args->sb) |
747 | __writeback_inodes_sb(args->sb, wb, &wbc); | ||
748 | else | ||
749 | writeback_inodes_wb(wb, &wbc); | ||
740 | args->nr_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write; | 750 | args->nr_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write; |
741 | wrote += MAX_WRITEBACK_PAGES - wbc.nr_to_write; | 751 | wrote += MAX_WRITEBACK_PAGES - wbc.nr_to_write; |
742 | 752 | ||