aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm/core.c
diff options
context:
space:
mode:
authorRakesh Pandit <rakesh@tuxera.com>2017-10-13 08:45:51 -0400
committerJens Axboe <axboe@kernel.dk>2017-10-13 10:34:57 -0400
commitbb6aa6f08268bbce4e0185b18cab9e04505d6695 (patch)
tree2a4c98b15e109ff7306ad6aa9acdc7939825374e /drivers/lightnvm/core.c
parent900148296b78c61aa8c443dc594c0da968c3be53 (diff)
lightnvm: prevent bd removal if busy
When a virtual block device is formatted and mounted after creating with "nvme lnvm create... -t pblk", a removal from "nvm lnvm remove" would result in this: 446416.309757] bdi-block not registered [446416.309773] ------------[ cut here ]------------ [446416.309780] WARNING: CPU: 3 PID: 4319 at fs/fs-writeback.c:2159 __mark_inode_dirty+0x268/0x340 Ideally removal should return -EBUSY as block device is mounted after formatting. This patch tries to address this checking if whole device or any partition of it already mounted or not before removal. Whole device is checked using "bd_super" member of block device. This member is always set once block device has been mounted using a filesystem. Another member "bd_part_count" takes care of checking any if any partitions are under use. "bd_part_count" is only updated under locks when partitions are opened or closed (first open and last release). This at least does take care sending -EBUSY if removal is being attempted while whole block device or any partition is mounted. Signed-off-by: Rakesh Pandit <rakesh@tuxera.com> Reviewed-by: Javier González <javier@cnexlabs.com> Signed-off-by: Matias Bjørling <m@bjorling.me> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/lightnvm/core.c')
-rw-r--r--drivers/lightnvm/core.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 60e163be5a89..c490711cf0f4 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -373,6 +373,7 @@ static void __nvm_remove_target(struct nvm_target *t)
373static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove) 373static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)
374{ 374{
375 struct nvm_target *t; 375 struct nvm_target *t;
376 struct block_device *bdev;
376 377
377 mutex_lock(&dev->mlock); 378 mutex_lock(&dev->mlock);
378 t = nvm_find_target(dev, remove->tgtname); 379 t = nvm_find_target(dev, remove->tgtname);
@@ -380,6 +381,19 @@ static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)
380 mutex_unlock(&dev->mlock); 381 mutex_unlock(&dev->mlock);
381 return 1; 382 return 1;
382 } 383 }
384 bdev = bdget_disk(t->disk, 0);
385 if (!bdev) {
386 pr_err("nvm: removal failed, allocating bd failed\n");
387 mutex_unlock(&dev->mlock);
388 return -ENOMEM;
389 }
390 if (bdev->bd_super || bdev->bd_part_count) {
391 pr_err("nvm: removal failed, block device busy\n");
392 bdput(bdev);
393 mutex_unlock(&dev->mlock);
394 return -EBUSY;
395 }
396 bdput(bdev);
383 __nvm_remove_target(t); 397 __nvm_remove_target(t);
384 mutex_unlock(&dev->mlock); 398 mutex_unlock(&dev->mlock);
385 399