Just like open an exclusive opened block device for write, open a block device exclusively which has been opened for write by some other processes may also lead to potential data corruption. This patch record the write openers and give a hint if that happens. Signed-off-by: zhangyi (F) <yi.zhang@xxxxxxxxxx> --- fs/block_dev.c | 20 ++++++++++++++++++-- include/linux/fs.h | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index d92aa45..c278195 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1606,6 +1606,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) bdev->bd_openers++; if (for_part) bdev->bd_part_count++; + if (mode & FMODE_WRITE) + bdev->bd_write_openers++; mutex_unlock(&bdev->bd_mutex); disk_unblock_events(disk); /* only one opener holds refs to the module and disk */ @@ -1654,6 +1656,7 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder) { struct block_device *whole = NULL; int res; + char name[BDEVNAME_SIZE]; WARN_ON_ONCE((mode & FMODE_EXCL) && !holder); @@ -1673,6 +1676,19 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder) if (whole) { struct gendisk *disk = whole->bd_disk; + /* + * Open an write opened block device exclusively, the + * writing process may probability corrupt the device, + * such as a mounted file system, give a hint here. + */ + if (!res && (bdev->bd_write_openers > + ((mode & FMODE_WRITE) ? 1 : 0)) && !bdev->bd_holders) { + pr_info_ratelimited("VFS: Open an write opened " + "block device exclusively %s [%d %s].\n", + bdevname(bdev, name), current->pid, + current->comm); + } + /* finish claiming */ if (!res) { BUG_ON(!bd_may_claim(bdev, whole, holder)); @@ -1712,8 +1728,6 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder) bdput(whole); } else { if (!res && (mode & FMODE_WRITE) && bdev->bd_holders) { - char name[BDEVNAME_SIZE]; - /* * Open an exclusive opened device for write may * probability corrupt the device, such as a @@ -1848,6 +1862,8 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part) struct block_device *victim = NULL; mutex_lock_nested(&bdev->bd_mutex, for_part); + if (mode & FMODE_WRITE) + bdev->bd_write_openers--; if (for_part) bdev->bd_part_count--; diff --git a/include/linux/fs.h b/include/linux/fs.h index dd28e76..0dc066d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -463,6 +463,7 @@ struct request_queue; struct block_device { dev_t bd_dev; /* not a kdev_t - it's a search key */ int bd_openers; + int bd_write_openers; struct inode * bd_inode; /* will die */ struct super_block * bd_super; struct mutex bd_mutex; /* open/close mutex */ -- 2.7.4