* simplify block device claiming
@ 2020-07-02 8:49 Christoph Hellwig
2020-07-02 8:49 ` [PATCH 1/4] block: simplify the restart case in __blkdev_get Christoph Hellwig
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Christoph Hellwig @ 2020-07-02 8:49 UTC (permalink / raw)
To: Jens Axboe; +Cc: Tejun Heo, linux-block
Hi Jens,
this series simplifies how we claim block devices for exclusive opens.
Diffstat:
drivers/block/loop.c | 7 -
fs/block_dev.c | 231 ++++++++++++++++---------------------------------
include/linux/blkdev.h | 3
3 files changed, 81 insertions(+), 160 deletions(-)
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/4] block: simplify the restart case in __blkdev_get
2020-07-02 8:49 simplify block device claiming Christoph Hellwig
@ 2020-07-02 8:49 ` Christoph Hellwig
2020-07-02 8:49 ` [PATCH 2/4] block: refactor bd_start_claiming Christoph Hellwig
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Christoph Hellwig @ 2020-07-02 8:49 UTC (permalink / raw)
To: Jens Axboe; +Cc: Tejun Heo, linux-block
Insted of duplicating all the cleanup logic jump to the code that cleans
up anyway, and restart after that.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/block_dev.c | 25 ++++++++++---------------
1 file changed, 10 insertions(+), 15 deletions(-)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 2d2fcb50e78eac..175161359664ca 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1533,7 +1533,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
int ret;
int partno;
int perm = 0;
- bool first_open = false;
+ bool first_open = false, need_restart;
if (mode & FMODE_READ)
perm |= MAY_READ;
@@ -1549,7 +1549,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
}
restart:
-
+ need_restart = false;
ret = -ENXIO;
disk = bdev_get_gendisk(bdev, &partno);
if (!disk)
@@ -1572,19 +1572,12 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
ret = 0;
if (disk->fops->open) {
ret = disk->fops->open(bdev, mode);
- if (ret == -ERESTARTSYS) {
- /* Lost a race with 'disk' being
- * deleted, try again.
- * See md.c
- */
- disk_put_part(bdev->bd_part);
- bdev->bd_part = NULL;
- bdev->bd_disk = NULL;
- mutex_unlock(&bdev->bd_mutex);
- disk_unblock_events(disk);
- put_disk_and_module(disk);
- goto restart;
- }
+ /*
+ * If we lost a race with 'disk' being deleted,
+ * try again. See md.c
+ */
+ if (ret == -ERESTARTSYS)
+ need_restart = true;
}
if (!ret) {
@@ -1663,6 +1656,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
mutex_unlock(&bdev->bd_mutex);
disk_unblock_events(disk);
put_disk_and_module(disk);
+ if (need_restart)
+ goto restart;
out:
return ret;
--
2.26.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/4] block: refactor bd_start_claiming
2020-07-02 8:49 simplify block device claiming Christoph Hellwig
2020-07-02 8:49 ` [PATCH 1/4] block: simplify the restart case in __blkdev_get Christoph Hellwig
@ 2020-07-02 8:49 ` Christoph Hellwig
2020-07-02 8:49 ` [PATCH 3/4] block: use bd_prepare_to_claim directly in the loop driver Christoph Hellwig
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Christoph Hellwig @ 2020-07-02 8:49 UTC (permalink / raw)
To: Jens Axboe; +Cc: Tejun Heo, linux-block
Move the locking and assignment of bd_claiming from bd_start_claiming to
bd_prepare_to_claim.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/block_dev.c | 33 +++++++++++++--------------------
1 file changed, 13 insertions(+), 20 deletions(-)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 175161359664ca..1c9da1f08011b0 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1015,19 +1015,14 @@ static bool bd_may_claim(struct block_device *bdev, struct block_device *whole,
}
/**
- * bd_prepare_to_claim - prepare to claim a block device
+ * bd_prepare_to_claim - claim a block device
* @bdev: block device of interest
* @whole: the whole device containing @bdev, may equal @bdev
* @holder: holder trying to claim @bdev
*
- * Prepare to claim @bdev. This function fails if @bdev is already
- * claimed by another holder and waits if another claiming is in
- * progress. This function doesn't actually claim. On successful
- * return, the caller has ownership of bd_claiming and bd_holder[s].
- *
- * CONTEXT:
- * spin_lock(&bdev_lock). Might release bdev_lock, sleep and regrab
- * it multiple times.
+ * Claim @bdev. This function fails if @bdev is already claimed by another
+ * holder and waits if another claiming is in progress. return, the caller
+ * has ownership of bd_claiming and bd_holder[s].
*
* RETURNS:
* 0 if @bdev can be claimed, -EBUSY otherwise.
@@ -1036,9 +1031,12 @@ static int bd_prepare_to_claim(struct block_device *bdev,
struct block_device *whole, void *holder)
{
retry:
+ spin_lock(&bdev_lock);
/* if someone else claimed, fail */
- if (!bd_may_claim(bdev, whole, holder))
+ if (!bd_may_claim(bdev, whole, holder)) {
+ spin_unlock(&bdev_lock);
return -EBUSY;
+ }
/* if claiming is already in progress, wait for it to finish */
if (whole->bd_claiming) {
@@ -1049,11 +1047,12 @@ static int bd_prepare_to_claim(struct block_device *bdev,
spin_unlock(&bdev_lock);
schedule();
finish_wait(wq, &wait);
- spin_lock(&bdev_lock);
goto retry;
}
/* yay, all mine */
+ whole->bd_claiming = holder;
+ spin_unlock(&bdev_lock);
return 0;
}
@@ -1134,19 +1133,13 @@ struct block_device *bd_start_claiming(struct block_device *bdev, void *holder)
if (!whole)
return ERR_PTR(-ENOMEM);
- /* prepare to claim, if successful, mark claiming in progress */
- spin_lock(&bdev_lock);
-
err = bd_prepare_to_claim(bdev, whole, holder);
- if (err == 0) {
- whole->bd_claiming = holder;
- spin_unlock(&bdev_lock);
- return whole;
- } else {
- spin_unlock(&bdev_lock);
+ if (err) {
bdput(whole);
return ERR_PTR(err);
}
+
+ return whole;
}
EXPORT_SYMBOL(bd_start_claiming);
--
2.26.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/4] block: use bd_prepare_to_claim directly in the loop driver
2020-07-02 8:49 simplify block device claiming Christoph Hellwig
2020-07-02 8:49 ` [PATCH 1/4] block: simplify the restart case in __blkdev_get Christoph Hellwig
2020-07-02 8:49 ` [PATCH 2/4] block: refactor bd_start_claiming Christoph Hellwig
@ 2020-07-02 8:49 ` Christoph Hellwig
2020-07-02 8:49 ` [PATCH 4/4] block: integrate bd_start_claiming into __blkdev_get Christoph Hellwig
2020-07-10 15:42 ` simplify block device claiming Christoph Hellwig
4 siblings, 0 replies; 9+ messages in thread
From: Christoph Hellwig @ 2020-07-02 8:49 UTC (permalink / raw)
To: Jens Axboe; +Cc: Tejun Heo, linux-block
The arcane magic in bd_start_claiming is only needed to be able to claim
a block_device that hasn't been fully set up. Switch the loop driver
that claims from the ioctl path with a fully set up struct block_device
to just use the much simpler bd_prepare_to_claim directly.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/block/loop.c | 7 +++----
fs/block_dev.c | 9 +++++----
include/linux/blkdev.h | 3 ++-
3 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index a943207705ddf1..d181601462260b 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1090,11 +1090,10 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
* here to avoid changing device under exclusive owner.
*/
if (!(mode & FMODE_EXCL)) {
- claimed_bdev = bd_start_claiming(bdev, loop_configure);
- if (IS_ERR(claimed_bdev)) {
- error = PTR_ERR(claimed_bdev);
+ claimed_bdev = bdev->bd_contains;
+ error = bd_prepare_to_claim(bdev, claimed_bdev, loop_configure);
+ if (error)
goto out_putf;
- }
}
error = mutex_lock_killable(&loop_ctl_mutex);
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 1c9da1f08011b0..7075004d36997b 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1027,8 +1027,8 @@ static bool bd_may_claim(struct block_device *bdev, struct block_device *whole,
* RETURNS:
* 0 if @bdev can be claimed, -EBUSY otherwise.
*/
-static int bd_prepare_to_claim(struct block_device *bdev,
- struct block_device *whole, void *holder)
+int bd_prepare_to_claim(struct block_device *bdev, struct block_device *whole,
+ void *holder)
{
retry:
spin_lock(&bdev_lock);
@@ -1055,6 +1055,7 @@ static int bd_prepare_to_claim(struct block_device *bdev,
spin_unlock(&bdev_lock);
return 0;
}
+EXPORT_SYMBOL_GPL(bd_prepare_to_claim); /* only for the loop driver */
static struct gendisk *bdev_get_gendisk(struct block_device *bdev, int *partno)
{
@@ -1100,7 +1101,8 @@ static struct gendisk *bdev_get_gendisk(struct block_device *bdev, int *partno)
* Pointer to the block device containing @bdev on success, ERR_PTR()
* value on failure.
*/
-struct block_device *bd_start_claiming(struct block_device *bdev, void *holder)
+static struct block_device *bd_start_claiming(struct block_device *bdev,
+ void *holder)
{
struct gendisk *disk;
struct block_device *whole;
@@ -1141,7 +1143,6 @@ struct block_device *bd_start_claiming(struct block_device *bdev, void *holder)
return whole;
}
-EXPORT_SYMBOL(bd_start_claiming);
static void bd_clear_claiming(struct block_device *whole, void *holder)
{
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 408eb66a82fdc7..6489a0c478165b 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1921,7 +1921,8 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder);
struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,
void *holder);
struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder);
-struct block_device *bd_start_claiming(struct block_device *bdev, void *holder);
+int bd_prepare_to_claim(struct block_device *bdev, struct block_device *whole,
+ void *holder);
void bd_abort_claiming(struct block_device *bdev, struct block_device *whole,
void *holder);
void blkdev_put(struct block_device *bdev, fmode_t mode);
--
2.26.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/4] block: integrate bd_start_claiming into __blkdev_get
2020-07-02 8:49 simplify block device claiming Christoph Hellwig
` (2 preceding siblings ...)
2020-07-02 8:49 ` [PATCH 3/4] block: use bd_prepare_to_claim directly in the loop driver Christoph Hellwig
@ 2020-07-02 8:49 ` Christoph Hellwig
2020-07-10 15:42 ` simplify block device claiming Christoph Hellwig
4 siblings, 0 replies; 9+ messages in thread
From: Christoph Hellwig @ 2020-07-02 8:49 UTC (permalink / raw)
To: Jens Axboe; +Cc: Tejun Heo, linux-block
bd_start_claiming duplicates a lot of the work done in __blkdev_get.
Integrate the two functions to avoid the duplicate work, and to do the
right thing for the md -ERESTARTSYS corner case.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/block_dev.c | 177 +++++++++++++++----------------------------------
1 file changed, 55 insertions(+), 122 deletions(-)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 7075004d36997b..6fa987c77e0a1b 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1078,72 +1078,6 @@ static struct gendisk *bdev_get_gendisk(struct block_device *bdev, int *partno)
return disk;
}
-/**
- * bd_start_claiming - start claiming a block device
- * @bdev: block device of interest
- * @holder: holder trying to claim @bdev
- *
- * @bdev is about to be opened exclusively. Check @bdev can be opened
- * exclusively and mark that an exclusive open is in progress. Each
- * successful call to this function must be matched with a call to
- * either bd_finish_claiming() or bd_abort_claiming() (which do not
- * fail).
- *
- * This function is used to gain exclusive access to the block device
- * without actually causing other exclusive open attempts to fail. It
- * should be used when the open sequence itself requires exclusive
- * access but may subsequently fail.
- *
- * CONTEXT:
- * Might sleep.
- *
- * RETURNS:
- * Pointer to the block device containing @bdev on success, ERR_PTR()
- * value on failure.
- */
-static struct block_device *bd_start_claiming(struct block_device *bdev,
- void *holder)
-{
- struct gendisk *disk;
- struct block_device *whole;
- int partno, err;
-
- might_sleep();
-
- /*
- * @bdev might not have been initialized properly yet, look up
- * and grab the outer block device the hard way.
- */
- disk = bdev_get_gendisk(bdev, &partno);
- if (!disk)
- return ERR_PTR(-ENXIO);
-
- /*
- * Normally, @bdev should equal what's returned from bdget_disk()
- * if partno is 0; however, some drivers (floppy) use multiple
- * bdev's for the same physical device and @bdev may be one of the
- * aliases. Keep @bdev if partno is 0. This means claimer
- * tracking is broken for those devices but it has always been that
- * way.
- */
- if (partno)
- whole = bdget_disk(disk, 0);
- else
- whole = bdgrab(bdev);
-
- put_disk_and_module(disk);
- if (!whole)
- return ERR_PTR(-ENOMEM);
-
- err = bd_prepare_to_claim(bdev, whole, holder);
- if (err) {
- bdput(whole);
- return ERR_PTR(err);
- }
-
- return whole;
-}
-
static void bd_clear_claiming(struct block_device *whole, void *holder)
{
lockdep_assert_held(&bdev_lock);
@@ -1156,7 +1090,7 @@ static void bd_clear_claiming(struct block_device *whole, void *holder)
/**
* bd_finish_claiming - finish claiming of a block device
* @bdev: block device of interest
- * @whole: whole block device (returned from bd_start_claiming())
+ * @whole: whole block device
* @holder: holder that has claimed @bdev
*
* Finish exclusive open of a block device. Mark the device as exlusively
@@ -1182,7 +1116,7 @@ static void bd_finish_claiming(struct block_device *bdev,
/**
* bd_abort_claiming - abort claiming of a block device
* @bdev: block device of interest
- * @whole: whole block device (returned from bd_start_claiming())
+ * @whole: whole block device
* @holder: holder that has claimed @bdev
*
* Abort claiming of a block device when the exclusive open failed. This can be
@@ -1521,13 +1455,15 @@ EXPORT_SYMBOL_GPL(bdev_disk_changed);
* mutex_lock_nested(whole->bd_mutex, 1)
*/
-static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
+static int __blkdev_get(struct block_device *bdev, fmode_t mode, void *holder,
+ int for_part)
{
+ struct block_device *whole = NULL, *claiming = NULL;
struct gendisk *disk;
int ret;
int partno;
int perm = 0;
- bool first_open = false, need_restart;
+ bool first_open = false, unblock_events = true, need_restart;
if (mode & FMODE_READ)
perm |= MAY_READ;
@@ -1549,6 +1485,25 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
if (!disk)
goto out;
+ if (partno) {
+ whole = bdget_disk(disk, 0);
+ if (!whole) {
+ ret = -ENOMEM;
+ goto out_put_disk;
+ }
+ }
+
+ if (!for_part && (mode & FMODE_EXCL)) {
+ WARN_ON_ONCE(!holder);
+ if (whole)
+ claiming = whole;
+ else
+ claiming = bdev;
+ ret = bd_prepare_to_claim(bdev, claiming, holder);
+ if (ret)
+ goto out_put_whole;
+ }
+
disk_block_events(disk);
mutex_lock_nested(&bdev->bd_mutex, for_part);
if (!bdev->bd_openers) {
@@ -1592,18 +1547,11 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
if (ret)
goto out_clear;
} else {
- struct block_device *whole;
- whole = bdget_disk(disk, 0);
- ret = -ENOMEM;
- if (!whole)
- goto out_clear;
BUG_ON(for_part);
- ret = __blkdev_get(whole, mode, 1);
- if (ret) {
- bdput(whole);
+ ret = __blkdev_get(whole, mode, NULL, 1);
+ if (ret)
goto out_clear;
- }
- bdev->bd_contains = whole;
+ bdev->bd_contains = bdgrab(whole);
bdev->bd_part = disk_get_part(disk, partno);
if (!(disk->flags & GENHD_FL_UP) ||
!bdev->bd_part || !bdev->bd_part->nr_sects) {
@@ -1632,11 +1580,30 @@ 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 (claiming)
+ bd_finish_claiming(bdev, claiming, holder);
+
+ /*
+ * Block event polling for write claims if requested. Any write holder
+ * makes the write_holder state stick until all are released. This is
+ * good enough and tracking individual writeable reference is too
+ * fragile given the way @mode is used in blkdev_get/put().
+ */
+ if (claiming && (mode & FMODE_WRITE) && !bdev->bd_write_holder &&
+ (disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE)) {
+ bdev->bd_write_holder = true;
+ unblock_events = false;
+ }
mutex_unlock(&bdev->bd_mutex);
- disk_unblock_events(disk);
+
+ if (unblock_events)
+ disk_unblock_events(disk);
+
/* only one opener holds refs to the module and disk */
if (!first_open)
put_disk_and_module(disk);
+ if (whole)
+ bdput(whole);
return 0;
out_clear:
@@ -1647,13 +1614,18 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
__blkdev_put(bdev->bd_contains, mode, 1);
bdev->bd_contains = NULL;
out_unlock_bdev:
+ if (claiming)
+ bd_abort_claiming(bdev, claiming, holder);
mutex_unlock(&bdev->bd_mutex);
disk_unblock_events(disk);
+ out_put_whole:
+ if (whole)
+ bdput(whole);
+ out_put_disk:
put_disk_and_module(disk);
if (need_restart)
goto restart;
out:
-
return ret;
}
@@ -1678,50 +1650,11 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
*/
int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
{
- struct block_device *whole = NULL;
int res;
- WARN_ON_ONCE((mode & FMODE_EXCL) && !holder);
-
- if ((mode & FMODE_EXCL) && holder) {
- whole = bd_start_claiming(bdev, holder);
- if (IS_ERR(whole)) {
- bdput(bdev);
- return PTR_ERR(whole);
- }
- }
-
- res = __blkdev_get(bdev, mode, 0);
-
- if (whole) {
- struct gendisk *disk = whole->bd_disk;
-
- /* finish claiming */
- mutex_lock(&bdev->bd_mutex);
- if (!res)
- bd_finish_claiming(bdev, whole, holder);
- else
- bd_abort_claiming(bdev, whole, holder);
- /*
- * Block event polling for write claims if requested. Any
- * write holder makes the write_holder state stick until
- * all are released. This is good enough and tracking
- * individual writeable reference is too fragile given the
- * way @mode is used in blkdev_get/put().
- */
- if (!res && (mode & FMODE_WRITE) && !bdev->bd_write_holder &&
- (disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE)) {
- bdev->bd_write_holder = true;
- disk_block_events(disk);
- }
-
- mutex_unlock(&bdev->bd_mutex);
- bdput(whole);
- }
-
+ res =__blkdev_get(bdev, mode, holder, 0);
if (res)
bdput(bdev);
-
return res;
}
EXPORT_SYMBOL(blkdev_get);
--
2.26.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: simplify block device claiming
2020-07-02 8:49 simplify block device claiming Christoph Hellwig
` (3 preceding siblings ...)
2020-07-02 8:49 ` [PATCH 4/4] block: integrate bd_start_claiming into __blkdev_get Christoph Hellwig
@ 2020-07-10 15:42 ` Christoph Hellwig
4 siblings, 0 replies; 9+ messages in thread
From: Christoph Hellwig @ 2020-07-10 15:42 UTC (permalink / raw)
To: Jens Axboe; +Cc: Tejun Heo, linux-block
Any comments?
On Thu, Jul 02, 2020 at 10:49:15AM +0200, Christoph Hellwig wrote:
> Hi Jens,
>
> this series simplifies how we claim block devices for exclusive opens.
>
> Diffstat:
> drivers/block/loop.c | 7 -
> fs/block_dev.c | 231 ++++++++++++++++---------------------------------
> include/linux/blkdev.h | 3
> 3 files changed, 81 insertions(+), 160 deletions(-)
---end quoted text---
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 4/4] block: integrate bd_start_claiming into __blkdev_get
2020-07-16 14:33 ` [PATCH 4/4] block: integrate bd_start_claiming into __blkdev_get Christoph Hellwig
2020-07-16 15:02 ` Tejun Heo
@ 2020-07-16 17:47 ` Hannes Reinecke
1 sibling, 0 replies; 9+ messages in thread
From: Hannes Reinecke @ 2020-07-16 17:47 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe; +Cc: Tejun Heo, linux-block
On 7/16/20 4:33 PM, Christoph Hellwig wrote:
> bd_start_claiming duplicates a lot of the work done in __blkdev_get.
> Integrate the two functions to avoid the duplicate work, and to do the
> right thing for the md -ERESTARTSYS corner case.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> fs/block_dev.c | 177 +++++++++++++++----------------------------------
> 1 file changed, 55 insertions(+), 122 deletions(-)
>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cheers,
Hannes
--
Dr. Hannes Reinecke Teamlead Storage & Networking
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 4/4] block: integrate bd_start_claiming into __blkdev_get
2020-07-16 14:33 ` [PATCH 4/4] block: integrate bd_start_claiming into __blkdev_get Christoph Hellwig
@ 2020-07-16 15:02 ` Tejun Heo
2020-07-16 17:47 ` Hannes Reinecke
1 sibling, 0 replies; 9+ messages in thread
From: Tejun Heo @ 2020-07-16 15:02 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Jens Axboe, linux-block
On Thu, Jul 16, 2020 at 04:33:10PM +0200, Christoph Hellwig wrote:
> bd_start_claiming duplicates a lot of the work done in __blkdev_get.
> Integrate the two functions to avoid the duplicate work, and to do the
> right thing for the md -ERESTARTSYS corner case.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
For 3 and 4,
Acked-by: Tejun Heo <tj@kernel.org>
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/4] block: integrate bd_start_claiming into __blkdev_get
2020-07-16 14:33 simplify block device claiming (resend) Christoph Hellwig
@ 2020-07-16 14:33 ` Christoph Hellwig
2020-07-16 15:02 ` Tejun Heo
2020-07-16 17:47 ` Hannes Reinecke
0 siblings, 2 replies; 9+ messages in thread
From: Christoph Hellwig @ 2020-07-16 14:33 UTC (permalink / raw)
To: Jens Axboe; +Cc: Tejun Heo, linux-block
bd_start_claiming duplicates a lot of the work done in __blkdev_get.
Integrate the two functions to avoid the duplicate work, and to do the
right thing for the md -ERESTARTSYS corner case.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/block_dev.c | 177 +++++++++++++++----------------------------------
1 file changed, 55 insertions(+), 122 deletions(-)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index ee80bd81af748d..3f94a06a094675 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1078,72 +1078,6 @@ static struct gendisk *bdev_get_gendisk(struct block_device *bdev, int *partno)
return disk;
}
-/**
- * bd_start_claiming - start claiming a block device
- * @bdev: block device of interest
- * @holder: holder trying to claim @bdev
- *
- * @bdev is about to be opened exclusively. Check @bdev can be opened
- * exclusively and mark that an exclusive open is in progress. Each
- * successful call to this function must be matched with a call to
- * either bd_finish_claiming() or bd_abort_claiming() (which do not
- * fail).
- *
- * This function is used to gain exclusive access to the block device
- * without actually causing other exclusive open attempts to fail. It
- * should be used when the open sequence itself requires exclusive
- * access but may subsequently fail.
- *
- * CONTEXT:
- * Might sleep.
- *
- * RETURNS:
- * Pointer to the block device containing @bdev on success, ERR_PTR()
- * value on failure.
- */
-static struct block_device *bd_start_claiming(struct block_device *bdev,
- void *holder)
-{
- struct gendisk *disk;
- struct block_device *whole;
- int partno, err;
-
- might_sleep();
-
- /*
- * @bdev might not have been initialized properly yet, look up
- * and grab the outer block device the hard way.
- */
- disk = bdev_get_gendisk(bdev, &partno);
- if (!disk)
- return ERR_PTR(-ENXIO);
-
- /*
- * Normally, @bdev should equal what's returned from bdget_disk()
- * if partno is 0; however, some drivers (floppy) use multiple
- * bdev's for the same physical device and @bdev may be one of the
- * aliases. Keep @bdev if partno is 0. This means claimer
- * tracking is broken for those devices but it has always been that
- * way.
- */
- if (partno)
- whole = bdget_disk(disk, 0);
- else
- whole = bdgrab(bdev);
-
- put_disk_and_module(disk);
- if (!whole)
- return ERR_PTR(-ENOMEM);
-
- err = bd_prepare_to_claim(bdev, whole, holder);
- if (err) {
- bdput(whole);
- return ERR_PTR(err);
- }
-
- return whole;
-}
-
static void bd_clear_claiming(struct block_device *whole, void *holder)
{
lockdep_assert_held(&bdev_lock);
@@ -1156,7 +1090,7 @@ static void bd_clear_claiming(struct block_device *whole, void *holder)
/**
* bd_finish_claiming - finish claiming of a block device
* @bdev: block device of interest
- * @whole: whole block device (returned from bd_start_claiming())
+ * @whole: whole block device
* @holder: holder that has claimed @bdev
*
* Finish exclusive open of a block device. Mark the device as exlusively
@@ -1182,7 +1116,7 @@ static void bd_finish_claiming(struct block_device *bdev,
/**
* bd_abort_claiming - abort claiming of a block device
* @bdev: block device of interest
- * @whole: whole block device (returned from bd_start_claiming())
+ * @whole: whole block device
* @holder: holder that has claimed @bdev
*
* Abort claiming of a block device when the exclusive open failed. This can be
@@ -1505,13 +1439,15 @@ EXPORT_SYMBOL_GPL(bdev_disk_changed);
* mutex_lock_nested(whole->bd_mutex, 1)
*/
-static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
+static int __blkdev_get(struct block_device *bdev, fmode_t mode, void *holder,
+ int for_part)
{
+ struct block_device *whole = NULL, *claiming = NULL;
struct gendisk *disk;
int ret;
int partno;
int perm = 0;
- bool first_open = false, need_restart;
+ bool first_open = false, unblock_events = true, need_restart;
if (mode & FMODE_READ)
perm |= MAY_READ;
@@ -1533,6 +1469,25 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
if (!disk)
goto out;
+ if (partno) {
+ whole = bdget_disk(disk, 0);
+ if (!whole) {
+ ret = -ENOMEM;
+ goto out_put_disk;
+ }
+ }
+
+ if (!for_part && (mode & FMODE_EXCL)) {
+ WARN_ON_ONCE(!holder);
+ if (whole)
+ claiming = whole;
+ else
+ claiming = bdev;
+ ret = bd_prepare_to_claim(bdev, claiming, holder);
+ if (ret)
+ goto out_put_whole;
+ }
+
disk_block_events(disk);
mutex_lock_nested(&bdev->bd_mutex, for_part);
if (!bdev->bd_openers) {
@@ -1576,18 +1531,11 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
if (ret)
goto out_clear;
} else {
- struct block_device *whole;
- whole = bdget_disk(disk, 0);
- ret = -ENOMEM;
- if (!whole)
- goto out_clear;
BUG_ON(for_part);
- ret = __blkdev_get(whole, mode, 1);
- if (ret) {
- bdput(whole);
+ ret = __blkdev_get(whole, mode, NULL, 1);
+ if (ret)
goto out_clear;
- }
- bdev->bd_contains = whole;
+ bdev->bd_contains = bdgrab(whole);
bdev->bd_part = disk_get_part(disk, partno);
if (!(disk->flags & GENHD_FL_UP) ||
!bdev->bd_part || !bdev->bd_part->nr_sects) {
@@ -1616,11 +1564,30 @@ 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 (claiming)
+ bd_finish_claiming(bdev, claiming, holder);
+
+ /*
+ * Block event polling for write claims if requested. Any write holder
+ * makes the write_holder state stick until all are released. This is
+ * good enough and tracking individual writeable reference is too
+ * fragile given the way @mode is used in blkdev_get/put().
+ */
+ if (claiming && (mode & FMODE_WRITE) && !bdev->bd_write_holder &&
+ (disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE)) {
+ bdev->bd_write_holder = true;
+ unblock_events = false;
+ }
mutex_unlock(&bdev->bd_mutex);
- disk_unblock_events(disk);
+
+ if (unblock_events)
+ disk_unblock_events(disk);
+
/* only one opener holds refs to the module and disk */
if (!first_open)
put_disk_and_module(disk);
+ if (whole)
+ bdput(whole);
return 0;
out_clear:
@@ -1631,13 +1598,18 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
__blkdev_put(bdev->bd_contains, mode, 1);
bdev->bd_contains = NULL;
out_unlock_bdev:
+ if (claiming)
+ bd_abort_claiming(bdev, claiming, holder);
mutex_unlock(&bdev->bd_mutex);
disk_unblock_events(disk);
+ out_put_whole:
+ if (whole)
+ bdput(whole);
+ out_put_disk:
put_disk_and_module(disk);
if (need_restart)
goto restart;
out:
-
return ret;
}
@@ -1662,50 +1634,11 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
*/
int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
{
- struct block_device *whole = NULL;
int res;
- WARN_ON_ONCE((mode & FMODE_EXCL) && !holder);
-
- if ((mode & FMODE_EXCL) && holder) {
- whole = bd_start_claiming(bdev, holder);
- if (IS_ERR(whole)) {
- bdput(bdev);
- return PTR_ERR(whole);
- }
- }
-
- res = __blkdev_get(bdev, mode, 0);
-
- if (whole) {
- struct gendisk *disk = whole->bd_disk;
-
- /* finish claiming */
- mutex_lock(&bdev->bd_mutex);
- if (!res)
- bd_finish_claiming(bdev, whole, holder);
- else
- bd_abort_claiming(bdev, whole, holder);
- /*
- * Block event polling for write claims if requested. Any
- * write holder makes the write_holder state stick until
- * all are released. This is good enough and tracking
- * individual writeable reference is too fragile given the
- * way @mode is used in blkdev_get/put().
- */
- if (!res && (mode & FMODE_WRITE) && !bdev->bd_write_holder &&
- (disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE)) {
- bdev->bd_write_holder = true;
- disk_block_events(disk);
- }
-
- mutex_unlock(&bdev->bd_mutex);
- bdput(whole);
- }
-
+ res =__blkdev_get(bdev, mode, holder, 0);
if (res)
bdput(bdev);
-
return res;
}
EXPORT_SYMBOL(blkdev_get);
--
2.27.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2020-07-16 17:48 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-02 8:49 simplify block device claiming Christoph Hellwig
2020-07-02 8:49 ` [PATCH 1/4] block: simplify the restart case in __blkdev_get Christoph Hellwig
2020-07-02 8:49 ` [PATCH 2/4] block: refactor bd_start_claiming Christoph Hellwig
2020-07-02 8:49 ` [PATCH 3/4] block: use bd_prepare_to_claim directly in the loop driver Christoph Hellwig
2020-07-02 8:49 ` [PATCH 4/4] block: integrate bd_start_claiming into __blkdev_get Christoph Hellwig
2020-07-10 15:42 ` simplify block device claiming Christoph Hellwig
2020-07-16 14:33 simplify block device claiming (resend) Christoph Hellwig
2020-07-16 14:33 ` [PATCH 4/4] block: integrate bd_start_claiming into __blkdev_get Christoph Hellwig
2020-07-16 15:02 ` Tejun Heo
2020-07-16 17:47 ` Hannes Reinecke
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.