summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2022-02-15 10:45:10 +0100
committerJens Axboe <axboe@kernel.dk>2022-02-16 19:44:24 -0700
commit76792055c4c8b2472ca1ae48e0ddaf8497529f08 (patch)
treed46b30e52e66b4f27ccb9c06a9cedf3d83abf546
parent34841e6fb125aa3f0e33e4eaac9f5eb86b2bb34b (diff)
block: add a ->free_disk method
Add a method to notify the driver that the gendisk is about to be freed. This allows drivers to tie the lifetime of their private data to that of the gendisk and thus deal with device removal races without expensive synchronization and boilerplate code. A new flag is added so that ->free_disk is only called after a successful call to add_disk, which significantly simplifies the error handling path during probing. Signed-off-by: Christoph Hellwig <hch@lst.de> Link: https://lore.kernel.org/r/20220215094514.3828912-2-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--block/genhd.c5
-rw-r--r--include/linux/blkdev.h2
2 files changed, 7 insertions, 0 deletions
diff --git a/block/genhd.c b/block/genhd.c
index 9589d1d59afa..e351fac41bf2 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -526,6 +526,7 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
disk_update_readahead(disk);
disk_add_events(disk);
+ set_bit(GD_ADDED, &disk->state);
return 0;
out_unregister_bdi:
@@ -1119,6 +1120,10 @@ static void disk_release(struct device *dev)
xa_destroy(&disk->part_tbl);
disk->queue->disk = NULL;
blk_put_queue(disk->queue);
+
+ if (test_bit(GD_ADDED, &disk->state) && disk->fops->free_disk)
+ disk->fops->free_disk(disk);
+
iput(disk->part0->bd_inode); /* frees the disk */
}
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 3bfc75a2a450..f757f9c2871f 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -146,6 +146,7 @@ struct gendisk {
#define GD_READ_ONLY 1
#define GD_DEAD 2
#define GD_NATIVE_CAPACITY 3
+#define GD_ADDED 4
struct mutex open_mutex; /* open/close mutex */
unsigned open_partitions; /* number of open partitions */
@@ -1464,6 +1465,7 @@ struct block_device_operations {
void (*unlock_native_capacity) (struct gendisk *);
int (*getgeo)(struct block_device *, struct hd_geometry *);
int (*set_read_only)(struct block_device *bdev, bool ro);
+ void (*free_disk)(struct gendisk *disk);
/* this callback is with swap_lock and sometimes page table lock held */
void (*swap_slot_free_notify) (struct block_device *, unsigned long);
int (*report_zones)(struct gendisk *, sector_t sector,