Now that there is just a single user of the kobj_map functionality left, merge it into the user to prepare for additional simplications. Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- block/genhd.c | 130 +++++++++++++++++++++++++++++---- drivers/base/Makefile | 2 +- drivers/base/map.c | 154 --------------------------------------- include/linux/kobj_map.h | 20 ----- 4 files changed, 118 insertions(+), 188 deletions(-) delete mode 100644 drivers/base/map.c delete mode 100644 include/linux/kobj_map.h diff --git a/block/genhd.c b/block/genhd.c index 99c64641c3148c..cb9a51be35b053 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -17,7 +17,6 @@ #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/kmod.h> -#include <linux/kobj_map.h> #include <linux/mutex.h> #include <linux/idr.h> #include <linux/log2.h> @@ -29,6 +28,16 @@ static DEFINE_MUTEX(block_class_lock); static struct kobject *block_depr; +struct bdev_map { + struct bdev_map *next; + dev_t dev; + unsigned long range; + struct module *owner; + struct kobject *(*probe)(dev_t, int *, void *); + int (*lock)(dev_t, void *); + void *data; +} *bdev_map[255]; + /* for extended dynamic devt allocation, currently only one major is used */ #define NR_EXT_DEVT (1 << MINORBITS) @@ -520,8 +529,6 @@ void unregister_blkdev(unsigned int major, const char *name) EXPORT_SYMBOL(unregister_blkdev); -static struct kobj_map *bdev_map; - /** * blk_mangle_minor - scatter minor numbers apart * @minor: minor number to mangle @@ -648,16 +655,60 @@ void blk_register_region(dev_t devt, unsigned long range, struct module *module, struct kobject *(*probe)(dev_t, int *, void *), int (*lock)(dev_t, void *), void *data) { - kobj_map(bdev_map, devt, range, module, probe, lock, data); -} + unsigned n = MAJOR(devt + range - 1) - MAJOR(devt) + 1; + unsigned index = MAJOR(devt); + unsigned i; + struct bdev_map *p; + + n = min(n, 255u); + p = kmalloc_array(n, sizeof(struct bdev_map), GFP_KERNEL); + if (p == NULL) + return; + for (i = 0; i < n; i++, p++) { + p->owner = module; + p->probe = probe; + p->lock = lock; + p->dev = devt; + p->range = range; + p->data = data; + } + + mutex_lock(&block_class_lock); + for (i = 0, p -= n; i < n; i++, p++, index++) { + struct bdev_map **s = &bdev_map[index % 255]; + while (*s && (*s)->range < range) + s = &(*s)->next; + p->next = *s; + *s = p; + } + mutex_unlock(&block_class_lock); +} EXPORT_SYMBOL(blk_register_region); void blk_unregister_region(dev_t devt, unsigned long range) { - kobj_unmap(bdev_map, devt, range); -} + unsigned n = MAJOR(devt + range - 1) - MAJOR(devt) + 1; + unsigned index = MAJOR(devt); + unsigned i; + struct bdev_map *found = NULL; + mutex_lock(&block_class_lock); + for (i = 0; i < min(n, 255u); i++, index++) { + struct bdev_map **s; + for (s = &bdev_map[index % 255]; *s; s = &(*s)->next) { + struct bdev_map *p = *s; + if (p->dev == devt && p->range == range) { + *s = p->next; + if (!found) + found = p; + break; + } + } + } + mutex_unlock(&block_class_lock); + kfree(found); +} EXPORT_SYMBOL(blk_unregister_region); static struct kobject *exact_match(dev_t devt, int *partno, void *data) @@ -983,6 +1034,47 @@ static ssize_t disk_badblocks_store(struct device *dev, return badblocks_store(disk->bb, page, len, 0); } +static struct gendisk *lookup_gendisk(dev_t dev, int *partno) +{ + struct kobject *kobj; + struct bdev_map *p; + unsigned long best = ~0UL; + +retry: + mutex_lock(&block_class_lock); + for (p = bdev_map[MAJOR(dev) % 255]; p; p = p->next) { + struct kobject *(*probe)(dev_t, int *, void *); + struct module *owner; + void *data; + + if (p->dev > dev || p->dev + p->range - 1 < dev) + continue; + if (p->range - 1 >= best) + break; + if (!try_module_get(p->owner)) + continue; + owner = p->owner; + data = p->data; + probe = p->probe; + best = p->range - 1; + *partno = dev - p->dev; + if (p->lock && p->lock(dev, data) < 0) { + module_put(owner); + continue; + } + mutex_unlock(&block_class_lock); + kobj = probe(dev, partno, data); + /* Currently ->owner protects _only_ ->probe() itself. */ + module_put(owner); + if (kobj) + return dev_to_disk(kobj_to_dev(kobj)); + goto retry; + } + mutex_unlock(&block_class_lock); + return NULL; +} + + /** * get_gendisk - get partitioning information for a given device * @devt: device to get partitioning information for @@ -1000,11 +1092,7 @@ struct gendisk *get_gendisk(dev_t devt, int *partno) might_sleep(); if (MAJOR(devt) != BLOCK_EXT_MAJOR) { - struct kobject *kobj; - - kobj = kobj_lookup(bdev_map, devt, partno); - if (kobj) - disk = dev_to_disk(kobj_to_dev(kobj)); + disk = lookup_gendisk(devt, partno); } else { struct hd_struct *part; @@ -1217,6 +1305,22 @@ static struct kobject *base_probe(dev_t devt, int *partno, void *data) return NULL; } +static void bdev_map_init(void) +{ + struct bdev_map *base; + int i; + + base = kzalloc(sizeof(*base), GFP_KERNEL); + if (!base) + panic("cannot allocate bdev_map"); + + base->dev = 1; + base->range = ~0 ; + base->probe = base_probe; + for (i = 0; i < 255; i++) + bdev_map[i] = base; +} + static int __init genhd_device_init(void) { int error; @@ -1225,7 +1329,7 @@ static int __init genhd_device_init(void) error = class_register(&block_class); if (unlikely(error)) return error; - bdev_map = kobj_map_init(base_probe, &block_class_lock); + bdev_map_init(); blk_dev_init(); register_blkdev(BLOCK_EXT_MAJOR, "blkext"); diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 157452080f3d7f..4ffd2a785f5ed3 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -3,7 +3,7 @@ obj-y := component.o core.o bus.o dd.o syscore.o \ driver.o class.o platform.o \ - cpu.o firmware.o init.o map.o devres.o \ + cpu.o firmware.o init.o devres.o \ attribute_container.o transport_class.o \ topology.o container.o property.o cacheinfo.o \ devcon.o swnode.o diff --git a/drivers/base/map.c b/drivers/base/map.c deleted file mode 100644 index 5650ab2b247ada..00000000000000 --- a/drivers/base/map.c +++ /dev/null @@ -1,154 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/drivers/base/map.c - * - * (C) Copyright Al Viro 2002,2003 - * - * NOTE: data structure needs to be changed. It works, but for large dev_t - * it will be too slow. It is isolated, though, so these changes will be - * local to that file. - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/mutex.h> -#include <linux/kdev_t.h> -#include <linux/kobject.h> -#include <linux/kobj_map.h> - -struct kobj_map { - struct probe { - struct probe *next; - dev_t dev; - unsigned long range; - struct module *owner; - kobj_probe_t *get; - int (*lock)(dev_t, void *); - void *data; - } *probes[255]; - struct mutex *lock; -}; - -int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, - struct module *module, kobj_probe_t *probe, - int (*lock)(dev_t, void *), void *data) -{ - unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; - unsigned index = MAJOR(dev); - unsigned i; - struct probe *p; - - if (n > 255) - n = 255; - - p = kmalloc_array(n, sizeof(struct probe), GFP_KERNEL); - if (p == NULL) - return -ENOMEM; - - for (i = 0; i < n; i++, p++) { - p->owner = module; - p->get = probe; - p->lock = lock; - p->dev = dev; - p->range = range; - p->data = data; - } - mutex_lock(domain->lock); - for (i = 0, p -= n; i < n; i++, p++, index++) { - struct probe **s = &domain->probes[index % 255]; - while (*s && (*s)->range < range) - s = &(*s)->next; - p->next = *s; - *s = p; - } - mutex_unlock(domain->lock); - return 0; -} - -void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range) -{ - unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; - unsigned index = MAJOR(dev); - unsigned i; - struct probe *found = NULL; - - if (n > 255) - n = 255; - - mutex_lock(domain->lock); - for (i = 0; i < n; i++, index++) { - struct probe **s; - for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) { - struct probe *p = *s; - if (p->dev == dev && p->range == range) { - *s = p->next; - if (!found) - found = p; - break; - } - } - } - mutex_unlock(domain->lock); - kfree(found); -} - -struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index) -{ - struct kobject *kobj; - struct probe *p; - unsigned long best = ~0UL; - -retry: - mutex_lock(domain->lock); - for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) { - struct kobject *(*probe)(dev_t, int *, void *); - struct module *owner; - void *data; - - if (p->dev > dev || p->dev + p->range - 1 < dev) - continue; - if (p->range - 1 >= best) - break; - if (!try_module_get(p->owner)) - continue; - owner = p->owner; - data = p->data; - probe = p->get; - best = p->range - 1; - *index = dev - p->dev; - if (p->lock && p->lock(dev, data) < 0) { - module_put(owner); - continue; - } - mutex_unlock(domain->lock); - kobj = probe(dev, index, data); - /* Currently ->owner protects _only_ ->probe() itself. */ - module_put(owner); - if (kobj) - return kobj; - goto retry; - } - mutex_unlock(domain->lock); - return NULL; -} - -struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct mutex *lock) -{ - struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL); - struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL); - int i; - - if ((p == NULL) || (base == NULL)) { - kfree(p); - kfree(base); - return NULL; - } - - base->dev = 1; - base->range = ~0; - base->get = base_probe; - for (i = 0; i < 255; i++) - p->probes[i] = base; - p->lock = lock; - return p; -} diff --git a/include/linux/kobj_map.h b/include/linux/kobj_map.h deleted file mode 100644 index c9919f8b22932c..00000000000000 --- a/include/linux/kobj_map.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * kobj_map.h - */ - -#ifndef _KOBJ_MAP_H_ -#define _KOBJ_MAP_H_ - -#include <linux/mutex.h> - -typedef struct kobject *kobj_probe_t(dev_t, int *, void *); -struct kobj_map; - -int kobj_map(struct kobj_map *, dev_t, unsigned long, struct module *, - kobj_probe_t *, int (*)(dev_t, void *), void *); -void kobj_unmap(struct kobj_map *, dev_t, unsigned long); -struct kobject *kobj_lookup(struct kobj_map *, dev_t, int *); -struct kobj_map *kobj_map_init(kobj_probe_t *, struct mutex *); - -#endif /* _KOBJ_MAP_H_ */ -- 2.28.0