From: Christoph Hellwig <hch@lst.de> Date: 2021-07-24 07:13:27
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.
Note that patch 1 is a 5.14 and -stable candidate.
Changes since v2:
- fix a double put_disk in the add_partition error path
- split a patch and better document the two new ones
- also remove partition bdev inodes a little earlier
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 | 13 ++-----
block/partitions/core.c | 37 +++++++++------------
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, 51 insertions(+), 108 deletions(-)
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-24 07:13:42
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-24 07:14:25
Unhash the block device inodes as early as possible. This ensures that
the inode and thus block_device an't be found in the inode hash as soon
as we start deleting the disk, instead of finding it and rejecting it
later because GENHD_FL_UP is cleared.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
block/genhd.c | 8 ++------
block/partitions/core.c | 8 ++------
2 files changed, 4 insertions(+), 12 deletions(-)
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-24 07:14:42
The GENHD_FL_UP check in blkdev_get_no_open is superflous. The actual
non-racy check happens later under open_mutex in blkdev_get_by_dev,
and the inodes are removed from the inode hash early in del_gendisk,
so it does not provide any useful short cut.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/block_dev.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-24 07:15:02
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>
Reviewed-by: Ming Lei <redacted>
---
block/partitions/core.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
@@ -382,6 +375,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-24 07:15:37
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 | 4 +++
fs/block_dev.c | 60 ++++++++++++++++-------------------------
2 files changed, 27 insertions(+), 37 deletions(-)
@@ -364,6 +365,9 @@ static struct block_device *add_partition(struct gendisk *disk, int partno,pdev->type=&part_type;pdev->parent=ddev;+/* ensure we always have a reference to the whole disk */+get_device(disk_to_dev(disk));+/* in consecutive minor range? */if(bdev->bd_partno<disk->minors){devt=MKDEV(disk->major,disk->first_minor+bdev->bd_partno);
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-24 07:16:02
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-24 07:16:19
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>
Reviewed-by: Chaitanya Kulkarni <redacted>
Reviewed-by: Ming Lei <redacted>
---
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-24 07:16:36
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-24 07:16:54
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>
Reviewed-by: Chaitanya Kulkarni <redacted>
---
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(-)
@@ -1077,7 +1077,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",
@@ -1262,7 +1262,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;
From: Christoph Hellwig <hch@lst.de> Date: 2021-07-24 07:22:27
On Sat, Jul 24, 2021 at 09:12:39AM +0200, Christoph Hellwig wrote:
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.
Note that patch 1 is a 5.14 and -stable candidate.
Oh, and patch 7 is on its way to Linus via the btrfs tree.
On Sat, Jul 24, 2021 at 09:12:39AM +0200, Christoph Hellwig wrote:
quoted
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.
Note that patch 1 is a 5.14 and -stable candidate.
Oh, and patch 7 is on its way to Linus via the btrfs tree.
Shall we get patch 1 queued up for next week, and then look at the rest
for the 5.15 block tree once the btrfs fix lands in mainline?
--
Jens Axboe
From: Damien Le Moal <hidden> Date: 2021-07-26 02:20:55
On 2021/07/24 16:15, Christoph Hellwig wrote:
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.
@@ -364,6 +365,9 @@ static struct block_device *add_partition(struct gendisk *disk, int partno,pdev->type=&part_type;pdev->parent=ddev;+/* ensure we always have a reference to the whole disk */+get_device(disk_to_dev(disk));+/* in consecutive minor range? */if(bdev->bd_partno<disk->minors){devt=MKDEV(disk->major,disk->first_minor+bdev->bd_partno);
On Sat, Jul 24, 2021 at 09:12:42AM +0200, Christoph Hellwig wrote:
Unhash the block device inodes as early as possible. This ensures that
the inode and thus block_device an't be found in the inode hash as soon
as we start deleting the disk, instead of finding it and rejecting it
later because GENHD_FL_UP is cleared.
Signed-off-by: Christoph Hellwig <hch@lst.de>
On Sat, Jul 24, 2021 at 09:12:45AM +0200, Christoph Hellwig wrote:
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.
On Sat, Jul 24, 2021 at 09:12:43AM +0200, Christoph Hellwig wrote:
The GENHD_FL_UP check in blkdev_get_no_open is superflous. The actual
non-racy check happens later under open_mutex in blkdev_get_by_dev,
and the inodes are removed from the inode hash early in del_gendisk,
so it does not provide any useful short cut.
Signed-off-by: Christoph Hellwig <hch@lst.de>