Commit 76792055 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe

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: default avatarChristoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20220215094514.3828912-2-hch@lst.deSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 34841e6f
...@@ -526,6 +526,7 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk, ...@@ -526,6 +526,7 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
disk_update_readahead(disk); disk_update_readahead(disk);
disk_add_events(disk); disk_add_events(disk);
set_bit(GD_ADDED, &disk->state);
return 0; return 0;
out_unregister_bdi: out_unregister_bdi:
...@@ -1119,6 +1120,10 @@ static void disk_release(struct device *dev) ...@@ -1119,6 +1120,10 @@ static void disk_release(struct device *dev)
xa_destroy(&disk->part_tbl); xa_destroy(&disk->part_tbl);
disk->queue->disk = NULL; disk->queue->disk = NULL;
blk_put_queue(disk->queue); 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 */ iput(disk->part0->bd_inode); /* frees the disk */
} }
......
...@@ -146,6 +146,7 @@ struct gendisk { ...@@ -146,6 +146,7 @@ struct gendisk {
#define GD_READ_ONLY 1 #define GD_READ_ONLY 1
#define GD_DEAD 2 #define GD_DEAD 2
#define GD_NATIVE_CAPACITY 3 #define GD_NATIVE_CAPACITY 3
#define GD_ADDED 4
struct mutex open_mutex; /* open/close mutex */ struct mutex open_mutex; /* open/close mutex */
unsigned open_partitions; /* number of open partitions */ unsigned open_partitions; /* number of open partitions */
...@@ -1464,6 +1465,7 @@ struct block_device_operations { ...@@ -1464,6 +1465,7 @@ struct block_device_operations {
void (*unlock_native_capacity) (struct gendisk *); void (*unlock_native_capacity) (struct gendisk *);
int (*getgeo)(struct block_device *, struct hd_geometry *); int (*getgeo)(struct block_device *, struct hd_geometry *);
int (*set_read_only)(struct block_device *bdev, bool ro); 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 */ /* this callback is with swap_lock and sometimes page table lock held */
void (*swap_slot_free_notify) (struct block_device *, unsigned long); void (*swap_slot_free_notify) (struct block_device *, unsigned long);
int (*report_zones)(struct gendisk *, sector_t sector, int (*report_zones)(struct gendisk *, sector_t sector,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment