diff options
author | Christoph Hellwig <hch@lst.de> | 2015-01-14 04:42:33 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-01-20 16:02:59 -0500 |
commit | 564f00f6c03a9339c259eb71a5b3aa8ef7ff1c2e (patch) | |
tree | 58efd5b836e7d6942af954a11e2dce202a5e805a /fs/block_dev.c | |
parent | b4caecd48005fbed3949dde6c1cb233142fd69e9 (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.c | 31 |
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 | } |
50 | EXPORT_SYMBOL(I_BDEV); | 50 | EXPORT_SYMBOL(I_BDEV); |
51 | 51 | ||
52 | static 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); | |||
56 | static void bdev_inode_switch_bdi(struct inode *inode, | 67 | static 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 | } |