block: add an optional probe callback to major_names

Add a callback to the major_names array that allows a driver to override
how to probe for dev_t that doesn't currently have a gendisk registered.
This will help separating the lookup of the gendisk by dev_t vs probe
action for a not currently registered dev_t.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Christoph Hellwig 2020-10-29 15:58:28 +01:00 committed by Jens Axboe
parent bd8eff3ba2
commit a160c6159d
2 changed files with 22 additions and 4 deletions

View File

@ -402,6 +402,7 @@ static struct blk_major_name {
struct blk_major_name *next; struct blk_major_name *next;
int major; int major;
char name[16]; char name[16];
void (*probe)(dev_t devt);
} *major_names[BLKDEV_MAJOR_HASH_SIZE]; } *major_names[BLKDEV_MAJOR_HASH_SIZE];
static DEFINE_MUTEX(major_names_lock); static DEFINE_MUTEX(major_names_lock);
@ -444,7 +445,8 @@ void blkdev_show(struct seq_file *seqf, off_t offset)
* See Documentation/admin-guide/devices.txt for the list of allocated * See Documentation/admin-guide/devices.txt for the list of allocated
* major numbers. * major numbers.
*/ */
int register_blkdev(unsigned int major, const char *name) int __register_blkdev(unsigned int major, const char *name,
void (*probe)(dev_t devt))
{ {
struct blk_major_name **n, *p; struct blk_major_name **n, *p;
int index, ret = 0; int index, ret = 0;
@ -483,6 +485,7 @@ int register_blkdev(unsigned int major, const char *name)
} }
p->major = major; p->major = major;
p->probe = probe;
strlcpy(p->name, name, sizeof(p->name)); strlcpy(p->name, name, sizeof(p->name));
p->next = NULL; p->next = NULL;
index = major_to_index(major); index = major_to_index(major);
@ -505,8 +508,7 @@ out:
mutex_unlock(&major_names_lock); mutex_unlock(&major_names_lock);
return ret; return ret;
} }
EXPORT_SYMBOL(__register_blkdev);
EXPORT_SYMBOL(register_blkdev);
void unregister_blkdev(unsigned int major, const char *name) void unregister_blkdev(unsigned int major, const char *name)
{ {
@ -1033,6 +1035,19 @@ static ssize_t disk_badblocks_store(struct device *dev,
static void request_gendisk_module(dev_t devt) static void request_gendisk_module(dev_t devt)
{ {
unsigned int major = MAJOR(devt);
struct blk_major_name **n;
mutex_lock(&major_names_lock);
for (n = &major_names[major_to_index(major)]; *n; n = &(*n)->next) {
if ((*n)->major == major && (*n)->probe) {
(*n)->probe(devt);
mutex_unlock(&major_names_lock);
return;
}
}
mutex_unlock(&major_names_lock);
if (request_module("block-major-%d-%d", MAJOR(devt), MINOR(devt)) > 0) if (request_module("block-major-%d-%d", MAJOR(devt), MINOR(devt)) > 0)
/* Make old-style 2.4 aliases work */ /* Make old-style 2.4 aliases work */
request_module("block-major-%d", MAJOR(devt)); request_module("block-major-%d", MAJOR(devt));

View File

@ -367,7 +367,10 @@ extern void blk_unregister_region(dev_t devt, unsigned long range);
#define alloc_disk(minors) alloc_disk_node(minors, NUMA_NO_NODE) #define alloc_disk(minors) alloc_disk_node(minors, NUMA_NO_NODE)
int register_blkdev(unsigned int major, const char *name); int __register_blkdev(unsigned int major, const char *name,
void (*probe)(dev_t devt));
#define register_blkdev(major, name) \
__register_blkdev(major, name, NULL)
void unregister_blkdev(unsigned int major, const char *name); void unregister_blkdev(unsigned int major, const char *name);
void revalidate_disk_size(struct gendisk *disk, bool verbose); void revalidate_disk_size(struct gendisk *disk, bool verbose);