aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVivek Goyal <vgoyal@redhat.com>2015-11-09 09:23:40 -0700
committerAlex Shi <alex.shi@linaro.org>2016-06-08 11:09:41 +0800
commitbe6f49f6f6a1bc9b446c149e594576dbbe319a77 (patch)
treedd95624eded1c7f839fde5e5e4a853d8792d1c5c
parent4ce5ef0261d7fb754c942fe753611f53422cdc3f (diff)
fs/block_dev.c: Remove WARN_ON() when inode writeback fails
If a block device is hot removed and later last reference to device is put, we try to writeback the dirty inode. But device is gone and that writeback fails. Currently we do a WARN_ON() which does not seem to be the right thing. Convert it to a ratelimited kernel warning. Reported-by: Andi Kleen <andi@firstfloor.org> Signed-off-by: Vivek Goyal <vgoyal@redhat.com> Acked-by: Tejun Heo <tj@kernel.org> [jmoyer@redhat.com: get rid of unnecessary name initialization, 80 cols] Signed-off-by: Jeff Moyer <jmoyer@redhat.com> Signed-off-by: Jens Axboe <axboe@fb.com> (cherry picked from commit dbd3ca50753e70e09cad747dce23b1a7683a3342) Signed-off-by: Alex Shi <alex.shi@linaro.org>
-rw-r--r--fs/block_dev.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 6f180ed2591a..ff14926d17e7 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -50,12 +50,21 @@ inline struct block_device *I_BDEV(struct inode *inode)
}
EXPORT_SYMBOL(I_BDEV);
-static void bdev_write_inode(struct inode *inode)
+static void bdev_write_inode(struct block_device *bdev)
{
+ struct inode *inode = bdev->bd_inode;
+ int ret;
+
spin_lock(&inode->i_lock);
while (inode->i_state & I_DIRTY) {
spin_unlock(&inode->i_lock);
- WARN_ON_ONCE(write_inode_now(inode, true));
+ ret = write_inode_now(inode, true);
+ if (ret) {
+ char name[BDEVNAME_SIZE];
+ pr_warn_ratelimited("VFS: Dirty inode writeback failed "
+ "for block device %s (err=%d).\n",
+ bdevname(bdev, name), ret);
+ }
spin_lock(&inode->i_lock);
}
spin_unlock(&inode->i_lock);
@@ -1494,7 +1503,7 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
* ->release can cause the queue to disappear, so flush all
* dirty data before.
*/
- bdev_write_inode(bdev->bd_inode);
+ bdev_write_inode(bdev);
}
if (bdev->bd_contains == bdev) {
if (disk->fops->release)