]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - fs/partitions/check.c
[PATCH] Driver core: add generic "subsystem" link to all devices
[mirror_ubuntu-bionic-kernel.git] / fs / partitions / check.c
index af0cb4b9e784e21b5c0b38921728d8b1e0f069b5..8851b81e7c5afb7a7d911cb606bb0d2c98512055 100644 (file)
@@ -329,9 +329,12 @@ void delete_partition(struct gendisk *disk, int part)
        p->ios[0] = p->ios[1] = 0;
        p->sectors[0] = p->sectors[1] = 0;
        devfs_remove("%s/part%d", disk->devfs_name, part);
+       sysfs_remove_link(&p->kobj, "subsystem");
        if (p->holder_dir)
                kobject_unregister(p->holder_dir);
-       kobject_unregister(&p->kobj);
+       kobject_uevent(&p->kobj, KOBJ_REMOVE);
+       kobject_del(&p->kobj);
+       kobject_put(&p->kobj);
 }
 
 void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
@@ -357,7 +360,11 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
                snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part);
        p->kobj.parent = &disk->kobj;
        p->kobj.ktype = &ktype_part;
-       kobject_register(&p->kobj);
+       kobject_init(&p->kobj);
+       kobject_add(&p->kobj);
+       if (!disk->part_uevent_suppress)
+               kobject_uevent(&p->kobj, KOBJ_ADD);
+       sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem");
        partition_sysfs_add_subdir(p);
        disk->part[part-1] = p;
 }
@@ -367,6 +374,7 @@ static char *make_block_name(struct gendisk *disk)
        char *name;
        static char *block_str = "block:";
        int size;
+       char *s;
 
        size = strlen(block_str) + strlen(disk->disk_name) + 1;
        name = kmalloc(size, GFP_KERNEL);
@@ -374,6 +382,10 @@ static char *make_block_name(struct gendisk *disk)
                return NULL;
        strcpy(name, block_str);
        strcat(name, disk->disk_name);
+       /* ewww... some of these buggers have / in name... */
+       s = strchr(name, '/');
+       if (s)
+               *s = '!';
        return name;
 }
 
@@ -388,6 +400,7 @@ static void disk_sysfs_symlinks(struct gendisk *disk)
                        kfree(disk_name);
                }
        }
+       sysfs_create_link(&disk->kobj, &block_subsys.kset.kobj, "subsystem");
 }
 
 /* Not exported, helper to add_disk(). */
@@ -395,6 +408,8 @@ void register_disk(struct gendisk *disk)
 {
        struct block_device *bdev;
        char *s;
+       int i;
+       struct hd_struct *p;
        int err;
 
        strlcpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN);
@@ -406,13 +421,12 @@ void register_disk(struct gendisk *disk)
                return;
        disk_sysfs_symlinks(disk);
        disk_sysfs_add_subdirs(disk);
-       kobject_uevent(&disk->kobj, KOBJ_ADD);
 
        /* No minors to use for partitions */
        if (disk->minors == 1) {
                if (disk->devfs_name[0] != '\0')
                        devfs_add_disk(disk);
-               return;
+               goto exit;
        }
 
        /* always add handle for the whole disk */
@@ -420,16 +434,32 @@ void register_disk(struct gendisk *disk)
 
        /* No such device (e.g., media were just removed) */
        if (!get_capacity(disk))
-               return;
+               goto exit;
 
        bdev = bdget_disk(disk, 0);
        if (!bdev)
-               return;
+               goto exit;
 
+       /* scan partition table, but suppress uevents */
        bdev->bd_invalidated = 1;
-       if (blkdev_get(bdev, FMODE_READ, 0) < 0)
-               return;
+       disk->part_uevent_suppress = 1;
+       err = blkdev_get(bdev, FMODE_READ, 0);
+       disk->part_uevent_suppress = 0;
+       if (err < 0)
+               goto exit;
        blkdev_put(bdev);
+
+exit:
+       /* announce disk after possible partitions are already created */
+       kobject_uevent(&disk->kobj, KOBJ_ADD);
+
+       /* announce possible partitions */
+       for (i = 1; i < disk->minors; i++) {
+               p = disk->part[i-1];
+               if (!p || !p->nr_sects)
+                       continue;
+               kobject_uevent(&p->kobj, KOBJ_ADD);
+       }
 }
 
 int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
@@ -506,6 +536,7 @@ void del_gendisk(struct gendisk *disk)
 
        devfs_remove_disk(disk);
 
+       kobject_uevent(&disk->kobj, KOBJ_REMOVE);
        if (disk->holder_dir)
                kobject_unregister(disk->holder_dir);
        if (disk->slave_dir)
@@ -518,7 +549,8 @@ void del_gendisk(struct gendisk *disk)
                        kfree(disk_name);
                }
                put_device(disk->driverfs_dev);
+               disk->driverfs_dev = NULL;
        }
-       kobject_uevent(&disk->kobj, KOBJ_REMOVE);
+       sysfs_remove_link(&disk->kobj, "subsystem");
        kobject_del(&disk->kobj);
 }