From: Christoph Hellwig <hch@lst.de> Date: 2021-07-22 07:54:42
Hi Jens,
this series fixes up a possible race with the block_device lookup
changes, and the finishes off the conversion to stop using the inode
refcount for block devices.
Changes since v1:
- clean up btrfs even more by storing a bdev instead of the disk
- keep a persistent disk reference in the bdev
- a bunch of cleanups to make the above change easier
Diffstat:
block/genhd.c | 12 +-----
block/partitions/core.c | 34 ++++++++++---------
drivers/block/loop.c | 5 --
fs/block_dev.c | 83 ++++++++++++++----------------------------------
fs/btrfs/inode.c | 2 -
fs/btrfs/ordered-data.c | 2 -
fs/btrfs/ordered-data.h | 3 -
fs/btrfs/zoned.c | 12 ++----
include/linux/blkdev.h | 2 -
9 files changed, 52 insertions(+), 103 deletions(-)
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-22 07:55:02
blkdev_get_no_open acquires a reference to the block_device through
the block device inode and then tries to acquire a device model
reference to the gendisk. But at this point the disk migh already
be freed (although the race is free). Fix this by only freeing the
gendisk from the whole device bdevs ->free_inode callback as well.
Fixes: 22ae8ce8b892 ("block: simplify bdev/disk lookup in blkdev_get")
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Ming Lei <redacted>
---
block/genhd.c | 3 +--
fs/block_dev.c | 2 ++
2 files changed, 3 insertions(+), 2 deletions(-)
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-22 07:55:59
Add a lockdep assert instead of the outdated locking comment.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Ming Lei <redacted>
---
block/partitions/core.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-22 07:56:20
Unhash the whole device inode early in del_gendisk. This allows to
remove the first GENHD_FL_UP check in the open path as we simply
won't find a just removed inode. The second non-racy check after
taking open_mutex is still kept.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
block/genhd.c | 7 +------
fs/block_dev.c | 2 +-
2 files changed, 2 insertions(+), 7 deletions(-)
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-22 07:56:48
Move the allocation of bd_meta_info after initializing the struct device
to avoid the special bdput error handling path.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
block/partitions/core.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
@@ -386,6 +379,13 @@ static struct block_device *add_partition(struct gendisk *disk, int partno,}pdev->devt=devt;+if(info){+err=-ENOMEM;+bdev->bd_meta_info=kmemdup(info,sizeof(*info),GFP_KERNEL);+if(!bdev->bd_meta_info)+gotoout_put;+}+/* delay uevent until 'holders' subdir is created */dev_set_uevent_suppress(pdev,1);err=device_add(pdev);
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-22 07:57:11
Instead of acquiring an inode reference on open make sure partitions
always hold device model references to the disk while alive, and switch
open to grab only a device model reference to the opened block device.
If that is a partition the disk reference is transitively held by the
partition already.
---
block/partitions/core.c | 9 ++++++-
fs/block_dev.c | 60 ++++++++++++++++-------------------------
2 files changed, 31 insertions(+), 38 deletions(-)
@@ -349,9 +350,13 @@ static struct block_device *add_partition(struct gendisk *disk, int partno,if(xa_load(&disk->part_tbl,partno))returnERR_PTR(-EBUSY);+/* ensure we always have a reference to the whole disk */+get_device(disk_to_dev(disk));++err=-ENOMEM;bdev=bdev_alloc(disk,partno);if(!bdev)-returnERR_PTR(-ENOMEM);+gotoout_put_disk;bdev->bd_start_sect=start;bdev_set_nr_sectors(bdev,len);
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-22 07:57:37
Store the block device instead of the gendisk in the btrfs_ordered_extent
structure intead of acquiring a reference to it later.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/btrfs/inode.c | 2 +-
fs/btrfs/ordered-data.c | 2 --
fs/btrfs/ordered-data.h | 3 +--
fs/btrfs/zoned.c | 12 ++++--------
4 files changed, 6 insertions(+), 13 deletions(-)
@@ -1362,18 +1361,16 @@ void btrfs_rewrite_logical_zoned(struct btrfs_ordered_extent *ordered)structextent_map_tree*em_tree;structextent_map*em;structbtrfs_ordered_sum*sum;-structblock_device*bdev;u64orig_logical=ordered->disk_bytenr;u64*logical=NULL;intnr,stripe_len;/* Zoned devices should not have partitions. So, we can assume it is 0 */-ASSERT(ordered->partno==0);-bdev=bdgrab(ordered->disk->part0);-if(WARN_ON(!bdev))+ASSERT(!bdev_is_partition(ordered->bdev));+if(WARN_ON(!ordered->bdev))return;-if(WARN_ON(btrfs_rmap_block(fs_info,orig_logical,bdev,+if(WARN_ON(btrfs_rmap_block(fs_info,orig_logical,ordered->bdev,ordered->physical,&logical,&nr,&stripe_len)))gotoout;
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-22 07:58:10
The whole device block device won't be removed while the disk is still
alive, so don't bother to grab a reference to it.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
drivers/block/loop.c | 5 -----
1 file changed, 5 deletions(-)
@@ -1249,10 +1249,6 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,if(partscan)lo->lo_disk->flags&=~GENHD_FL_NO_PART_SCAN;-/* Grab the block_device to prevent its destruction after we-*put/dev/loopXXinode.Laterin__loop_clr_fd()webdput(bdev).-*/-bdgrab(bdev);mutex_unlock(&lo->lo_mutex);if(partscan)loop_reread_partitions(lo);
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-22 07:58:19
All callers are gone, and no one should grab a pure inode reference to
a block device anymore.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/block_dev.c | 15 ---------------
include/linux/blkdev.h | 1 -
2 files changed, 16 deletions(-)
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-22 07:58:57
Now that we've stopped using inode references for anything meaninful
in the block layer get rid of the helper to put it and just open code
the call to iput on the block_device inode.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
block/genhd.c | 4 ++--
block/partitions/core.c | 2 +-
fs/block_dev.c | 6 ------
include/linux/blkdev.h | 1 -
4 files changed, 3 insertions(+), 10 deletions(-)
@@ -1076,7 +1076,7 @@ static void disk_release(struct device *dev)xa_destroy(&disk->part_tbl);if(test_bit(GD_QUEUE_REF,&disk->state)&&disk->queue)blk_put_queue(disk->queue);-bdput(disk->part0);/* frees the disk */+iput(disk->part0->bd_inode);/* frees the disk */}structclassblock_class={.name="block",
@@ -1261,7 +1261,7 @@ struct gendisk *__alloc_disk_node(int minors, int node_id)out_destroy_part_tbl:xa_destroy(&disk->part_tbl);-bdput(disk->part0);+iput(disk->part0->bd_inode);out_free_disk:kfree(disk);returnNULL;
On Thu, Jul 22, 2021 at 09:53:56AM +0200, Christoph Hellwig wrote:
quoted hunk
Unhash the whole device inode early in del_gendisk. This allows to
remove the first GENHD_FL_UP check in the open path as we simply
won't find a just removed inode. The second non-racy check after
taking open_mutex is still kept.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
block/genhd.c | 7 +------
fs/block_dev.c | 2 +-
2 files changed, 2 insertions(+), 7 deletions(-)
But del_gendisk() can be called just between bdget() and checking GENHD_FL_UP.
And not see difference by moving remove_inode_hash() with disk open_mutex held.
Thanks,
Ming
On Thu, Jul 22, 2021 at 09:53:57AM +0200, Christoph Hellwig wrote:
Move the allocation of bd_meta_info after initializing the struct device
to avoid the special bdput error handling path.
Signed-off-by: Christoph Hellwig <hch@lst.de>
On Thu, Jul 22, 2021 at 09:53:58AM +0200, Christoph Hellwig wrote:
quoted hunk
Instead of acquiring an inode reference on open make sure partitions
always hold device model references to the disk while alive, and switch
open to grab only a device model reference to the opened block device.
If that is a partition the disk reference is transitively held by the
partition already.
---
block/partitions/core.c | 9 ++++++-
fs/block_dev.c | 60 ++++++++++++++++-------------------------
2 files changed, 31 insertions(+), 38 deletions(-)
@@ -349,9 +350,13 @@ static struct block_device *add_partition(struct gendisk *disk, int partno,if(xa_load(&disk->part_tbl,partno))returnERR_PTR(-EBUSY);+/* ensure we always have a reference to the whole disk */+get_device(disk_to_dev(disk));++err=-ENOMEM;bdev=bdev_alloc(disk,partno);if(!bdev)-returnERR_PTR(-ENOMEM);+gotoout_put_disk;bdev->bd_start_sect=start;bdev_set_nr_sectors(bdev,len);
put_disk() is only needed for failure of bdev_alloc(). Once bdev->bd_device
is initialized, the disk reference will be dropped via part_release().
Thanks,
Ming
On Thu, Jul 22, 2021 at 09:54:00AM +0200, Christoph Hellwig wrote:
The whole device block device won't be removed while the disk is still
alive, so don't bother to grab a reference to it.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
From: David Sterba <hidden> Date: 2021-07-22 13:01:46
On Thu, Jul 22, 2021 at 09:53:59AM +0200, Christoph Hellwig wrote:
Store the block device instead of the gendisk in the btrfs_ordered_extent
structure intead of acquiring a reference to it later.
instead
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: David Sterba <dsterba@suse.com>
I can add the patch to the next pull request so you can rebase your
series on top of it and don't need to carry it until the next merge
window.
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-22 13:05:23
On Thu, Jul 22, 2021 at 02:58:59PM +0200, David Sterba wrote:
On Thu, Jul 22, 2021 at 09:53:59AM +0200, Christoph Hellwig wrote:
quoted
Store the block device instead of the gendisk in the btrfs_ordered_extent
structure intead of acquiring a reference to it later.
instead
quoted
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: David Sterba <dsterba@suse.com>
I can add the patch to the next pull request so you can rebase your
series on top of it and don't need to carry it until the next merge
window.
Assuming Jens is fine with starting the block tree on -rc3 that would
be great.
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-22 13:12:32
On Thu, Jul 22, 2021 at 04:19:42PM +0800, Ming Lei wrote:
quoted
goto bdput;- if ((disk->flags & (GENHD_FL_UP | GENHD_FL_HIDDEN)) != GENHD_FL_UP)+ if (disk->flags & GENHD_FL_HIDDEN)
But del_gendisk() can be called just between bdget() and checking GENHD_FL_UP.
And not see difference by moving remove_inode_hash() with disk open_mutex held.
The difference is not about having the open_mutex held, but about doing
it earlier.
The only check that matters is the GENHD_FL_UP check in blkdev_get_by_dev.
The earlier check just reduces the amount of work we're doing for a disk
already being delete. With the early unhash there is no need for that
check as we won't even find the inode for a disk in del_gendisk. We still
need the non-racy check under the lock, but the patch doesn't touch that
one.
Maybe I need to split this into two patches and improve the commit log.
Add a lockdep assert instead of the outdated locking comment.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Ming Lei <redacted>
---
block/partitions/core.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
The whole device block device won't be removed while the disk is still
alive, so don't bother to grab a reference to it.
Signed-off-by: Christoph Hellwig<hch@lst.de>
Reviewed-by: Josef Bacik<josef@toxicpanda.com>
Now that we've stopped using inode references for anything meaninful
in the block layer get rid of the helper to put it and just open code
the call to iput on the block_device inode.
Signed-off-by: Christoph Hellwig<hch@lst.de>
Reviewed-by: Josef Bacik<josef@toxicpanda.com>
Hi Jens,
this series fixes up a possible race with the block_device lookup
changes, and the finishes off the conversion to stop using the inode
refcount for block devices.
Dropped the btrfs patch since it's in -git, and applied #1 to block-5.14,
rest for 5.15.
--
Jens Axboe