aboutsummaryrefslogtreecommitdiffstats
path: root/fs/block_dev.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-01-14 04:42:33 -0500
committerJens Axboe <axboe@fb.com>2015-01-20 16:02:59 -0500
commit564f00f6c03a9339c259eb71a5b3aa8ef7ff1c2e (patch)
tree58efd5b836e7d6942af954a11e2dce202a5e805a /fs/block_dev.c
parentb4caecd48005fbed3949dde6c1cb233142fd69e9 (diff)
block_dev: only write bdev inode on close
Since 018a17bdc865 ("bdi: reimplement bdev_inode_switch_bdi()") the block device code writes out all dirty data whenever switching the backing_dev_info for a block device inode. But a block device inode can only be dirtied when it is in use, which means we only have to write it out on the final blkdev_put, but not when doing a blkdev_get. Factoring out the write out from the bdi list switch prepares from removing the list switch later in the series. Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Tejun Heo <tj@kernel.org> Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r--fs/block_dev.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index b48c41bf0f86..026ca7b8431c 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -49,6 +49,17 @@ inline struct block_device *I_BDEV(struct inode *inode)
49} 49}
50EXPORT_SYMBOL(I_BDEV); 50EXPORT_SYMBOL(I_BDEV);
51 51
52static void bdev_write_inode(struct inode *inode)
53{
54 spin_lock(&inode->i_lock);
55 while (inode->i_state & I_DIRTY) {
56 spin_unlock(&inode->i_lock);
57 WARN_ON_ONCE(write_inode_now(inode, true));
58 spin_lock(&inode->i_lock);
59 }
60 spin_unlock(&inode->i_lock);
61}
62
52/* 63/*
53 * Move the inode from its current bdi to a new bdi. Make sure the inode 64 * Move the inode from its current bdi to a new bdi. Make sure the inode
54 * is clean before moving so that it doesn't linger on the old bdi. 65 * is clean before moving so that it doesn't linger on the old bdi.
@@ -56,16 +67,10 @@ EXPORT_SYMBOL(I_BDEV);
56static void bdev_inode_switch_bdi(struct inode *inode, 67static void bdev_inode_switch_bdi(struct inode *inode,
57 struct backing_dev_info *dst) 68 struct backing_dev_info *dst)
58{ 69{
59 while (true) { 70 spin_lock(&inode->i_lock);
60 spin_lock(&inode->i_lock); 71 WARN_ON_ONCE(inode->i_state & I_DIRTY);
61 if (!(inode->i_state & I_DIRTY)) { 72 inode->i_data.backing_dev_info = dst;
62 inode->i_data.backing_dev_info = dst; 73 spin_unlock(&inode->i_lock);
63 spin_unlock(&inode->i_lock);
64 return;
65 }
66 spin_unlock(&inode->i_lock);
67 WARN_ON_ONCE(write_inode_now(inode, true));
68 }
69} 74}
70 75
71/* Kill _all_ buffers and pagecache , dirty or not.. */ 76/* Kill _all_ buffers and pagecache , dirty or not.. */
@@ -1464,9 +1469,11 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
1464 WARN_ON_ONCE(bdev->bd_holders); 1469 WARN_ON_ONCE(bdev->bd_holders);
1465 sync_blockdev(bdev); 1470 sync_blockdev(bdev);
1466 kill_bdev(bdev); 1471 kill_bdev(bdev);
1467 /* ->release can cause the old bdi to disappear, 1472 /*
1468 * so must switch it out first 1473 * ->release can cause the queue to disappear, so flush all
1474 * dirty data before.
1469 */ 1475 */
1476 bdev_write_inode(bdev->bd_inode);
1470 bdev_inode_switch_bdi(bdev->bd_inode, 1477 bdev_inode_switch_bdi(bdev->bd_inode,
1471 &default_backing_dev_info); 1478 &default_backing_dev_info);
1472 } 1479 }