From: Yufen Yu <yuyufen(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: 109288
CVE: NA
-------------------------------------------------
After calling add_disk, we have register new kobj map for sd device,
then we can remove old unused kobj map which probed by sd_remove.
Signed-off-by: Yufen Yu <yuyufen(a)huawei.com>
Reviewed-by: Hou Tao <houtao1(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
block/genhd.c | 8 ++++++++
drivers/base/map.c | 28 ++++++++++++++++++++++++++++
drivers/scsi/sd.c | 1 +
include/linux/genhd.h | 2 ++
include/linux/kobj_map.h | 2 ++
5 files changed, 41 insertions(+)
diff --git a/block/genhd.c b/block/genhd.c
index 408cda8af4eba..be938088c440f 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -570,6 +570,14 @@ void blk_unregister_region(dev_t devt, unsigned long range)
EXPORT_SYMBOL(blk_unregister_region);
+void blk_delete_region(dev_t devt, unsigned long range,
+ struct kobject *(*probe)(dev_t, int *, void *))
+{
+ kobj_delete(bdev_map, devt, range, probe);
+}
+
+EXPORT_SYMBOL(blk_delete_region);
+
static struct kobject *exact_match(dev_t devt, int *partno, void *data)
{
struct gendisk *p = data;
diff --git a/drivers/base/map.c b/drivers/base/map.c
index 5650ab2b247ad..551296d485020 100644
--- a/drivers/base/map.c
+++ b/drivers/base/map.c
@@ -92,6 +92,34 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
kfree(found);
}
+void kobj_delete(struct kobj_map *domain, dev_t dev, unsigned long range,
+ kobj_probe_t *probe)
+{
+ 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 && p->get == probe) {
+ *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;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index d466d5a4b3129..5fa02f8261cba 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -3354,6 +3354,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
blk_pm_runtime_init(sdp->request_queue, dev);
device_add_disk(dev, gd, NULL);
+ blk_delete_region(disk_devt(sdkp->disk), SD_MINORS, sd_default_probe);
if (sdkp->capacity)
sd_dif_config_host(sdkp);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index bf8523db1f4dd..0c0b9dd50f76e 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -649,6 +649,8 @@ extern void blk_register_region(dev_t devt, unsigned long range,
int (*lock)(dev_t, void *),
void *data);
extern void blk_unregister_region(dev_t devt, unsigned long range);
+extern void blk_delete_region(dev_t devt, unsigned long range,
+ struct kobject *(*probe)(dev_t, int *, void *));
extern ssize_t part_size_show(struct device *dev,
struct device_attribute *attr, char *buf);
diff --git a/include/linux/kobj_map.h b/include/linux/kobj_map.h
index c9919f8b22932..73361fe1c43ac 100644
--- a/include/linux/kobj_map.h
+++ b/include/linux/kobj_map.h
@@ -14,6 +14,8 @@ 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);
+void kobj_delete(struct kobj_map *, dev_t, unsigned long,
+ kobj_probe_t *);
struct kobject *kobj_lookup(struct kobj_map *, dev_t, int *);
struct kobj_map *kobj_map_init(kobj_probe_t *, struct mutex *);
--
2.25.1