aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fs-writeback.c46
1 files changed, 29 insertions, 17 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 225c7316344e..c6bf775e641a 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -540,6 +540,17 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
540 return ret; 540 return ret;
541} 541}
542 542
543static void unpin_sb_for_writeback(struct super_block **psb)
544{
545 struct super_block *sb = *psb;
546
547 if (sb) {
548 up_read(&sb->s_umount);
549 put_super(sb);
550 *psb = NULL;
551 }
552}
553
543/* 554/*
544 * For WB_SYNC_NONE writeback, the caller does not have the sb pinned 555 * For WB_SYNC_NONE writeback, the caller does not have the sb pinned
545 * before calling writeback. So make sure that we do pin it, so it doesn't 556 * before calling writeback. So make sure that we do pin it, so it doesn't
@@ -549,11 +560,20 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
549 * 1 if we failed. 560 * 1 if we failed.
550 */ 561 */
551static int pin_sb_for_writeback(struct writeback_control *wbc, 562static int pin_sb_for_writeback(struct writeback_control *wbc,
552 struct inode *inode) 563 struct inode *inode, struct super_block **psb)
553{ 564{
554 struct super_block *sb = inode->i_sb; 565 struct super_block *sb = inode->i_sb;
555 566
556 /* 567 /*
568 * If this sb is already pinned, nothing more to do. If not and
569 * *psb is non-NULL, unpin the old one first
570 */
571 if (sb == *psb)
572 return 0;
573 else if (*psb)
574 unpin_sb_for_writeback(psb);
575
576 /*
557 * Caller must already hold the ref for this 577 * Caller must already hold the ref for this
558 */ 578 */
559 if (wbc->sync_mode == WB_SYNC_ALL) { 579 if (wbc->sync_mode == WB_SYNC_ALL) {
@@ -566,7 +586,7 @@ static int pin_sb_for_writeback(struct writeback_control *wbc,
566 if (down_read_trylock(&sb->s_umount)) { 586 if (down_read_trylock(&sb->s_umount)) {
567 if (sb->s_root) { 587 if (sb->s_root) {
568 spin_unlock(&sb_lock); 588 spin_unlock(&sb_lock);
569 return 0; 589 goto pinned;
570 } 590 }
571 /* 591 /*
572 * umounted, drop rwsem again and fall through to failure 592 * umounted, drop rwsem again and fall through to failure
@@ -577,24 +597,15 @@ static int pin_sb_for_writeback(struct writeback_control *wbc,
577 sb->s_count--; 597 sb->s_count--;
578 spin_unlock(&sb_lock); 598 spin_unlock(&sb_lock);
579 return 1; 599 return 1;
580} 600pinned:
581 601 *psb = sb;
582static void unpin_sb_for_writeback(struct writeback_control *wbc, 602 return 0;
583 struct inode *inode)
584{
585 struct super_block *sb = inode->i_sb;
586
587 if (wbc->sync_mode == WB_SYNC_ALL)
588 return;
589
590 up_read(&sb->s_umount);
591 put_super(sb);
592} 603}
593 604
594static void writeback_inodes_wb(struct bdi_writeback *wb, 605static void writeback_inodes_wb(struct bdi_writeback *wb,
595 struct writeback_control *wbc) 606 struct writeback_control *wbc)
596{ 607{
597 struct super_block *sb = wbc->sb; 608 struct super_block *sb = wbc->sb, *pin_sb = NULL;
598 const int is_blkdev_sb = sb_is_blkdev_sb(sb); 609 const int is_blkdev_sb = sb_is_blkdev_sb(sb);
599 const unsigned long start = jiffies; /* livelock avoidance */ 610 const unsigned long start = jiffies; /* livelock avoidance */
600 611
@@ -653,7 +664,7 @@ static void writeback_inodes_wb(struct bdi_writeback *wb,
653 if (inode_dirtied_after(inode, start)) 664 if (inode_dirtied_after(inode, start))
654 break; 665 break;
655 666
656 if (pin_sb_for_writeback(wbc, inode)) { 667 if (pin_sb_for_writeback(wbc, inode, &pin_sb)) {
657 requeue_io(inode); 668 requeue_io(inode);
658 continue; 669 continue;
659 } 670 }
@@ -662,7 +673,6 @@ static void writeback_inodes_wb(struct bdi_writeback *wb,
662 __iget(inode); 673 __iget(inode);
663 pages_skipped = wbc->pages_skipped; 674 pages_skipped = wbc->pages_skipped;
664 writeback_single_inode(inode, wbc); 675 writeback_single_inode(inode, wbc);
665 unpin_sb_for_writeback(wbc, inode);
666 if (wbc->pages_skipped != pages_skipped) { 676 if (wbc->pages_skipped != pages_skipped) {
667 /* 677 /*
668 * writeback is not making progress due to locked 678 * writeback is not making progress due to locked
@@ -682,6 +692,8 @@ static void writeback_inodes_wb(struct bdi_writeback *wb,
682 wbc->more_io = 1; 692 wbc->more_io = 1;
683 } 693 }
684 694
695 unpin_sb_for_writeback(&pin_sb);
696
685 spin_unlock(&inode_lock); 697 spin_unlock(&inode_lock);
686 /* Leave any unwritten inodes on b_io */ 698 /* Leave any unwritten inodes on b_io */
687} 699}