Skip to content

Commit

Permalink
[PATCH] BLOCK: delay all uevents until partition table is scanned
Browse files Browse the repository at this point in the history
[BLOCK] delay all uevents until partition table is scanned

Here we delay the annoucement of all block device events until the
disk's partition table is scanned and all partition devices are already
created and sysfs is populated.

We have a bunch of old bugs for removable storage handling where we
probe successfully for a filesystem on the raw disk, but at the
same time the kernel recognizes a partition table and creates partition
devices.
Currently there is no sane way to tell if partitions will show up or not
at the time the disk device is announced to userspace. With the delayed
events we can simply skip any probe for a filesystem on the raw disk when
we find already present partitions.

Signed-off-by: Kay Sievers <kay.sievers@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Kay Sievers authored and Greg Kroah-Hartman committed Apr 14, 2006
1 parent 0f836ca commit d4d7e5d
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 8 deletions.
38 changes: 30 additions & 8 deletions fs/partitions/check.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,9 @@ void delete_partition(struct gendisk *disk, int part)
devfs_remove("%s/part%d", disk->devfs_name, part);
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)
Expand All @@ -357,7 +359,10 @@ 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);
partition_sysfs_add_subdir(p);
disk->part[part-1] = p;
}
Expand Down Expand Up @@ -395,6 +400,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);
Expand All @@ -406,30 +413,45 @@ 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 */
devfs_add_partitioned(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)
Expand Down
1 change: 1 addition & 0 deletions include/linux/genhd.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ struct gendisk {
* disks that can't be partitioned. */
char disk_name[32]; /* name of major driver */
struct hd_struct **part; /* [indexed by minor] */
int part_uevent_suppress;
struct block_device_operations *fops;
struct request_queue *queue;
void *private_data;
Expand Down

0 comments on commit d4d7e5d

Please sign in to comment.