aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fs-writeback.c
diff options
context:
space:
mode:
authorJens Axboe <jens.axboe@oracle.com>2009-09-24 09:25:11 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-09-25 12:08:26 -0400
commit9ecc2738ac2371f88dff5d48914b4e35c45203cd (patch)
tree12cd500172561fb43e5cbe1ee1993945a4ac2c5c /fs/fs-writeback.c
parentcf137307cd9827495b65e7d74ea2b610daa9898b (diff)
writeback: make the super_block pinning more efficient
Currently we pin the inode->i_sb for every single inode. This increases cache traffic on sb->s_umount sem. Lets instead cache the inode sb pin state and keep the super_block pinned for as long as keep writing out inodes from the same super_block. Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'fs/fs-writeback.c')
-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}