diff options
Diffstat (limited to 'block/partitions')
-rw-r--r-- | block/partitions/core.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/block/partitions/core.c b/block/partitions/core.c index 873999e2e2f2..8d8c87207fc2 100644 --- a/block/partitions/core.c +++ b/block/partitions/core.c @@ -288,6 +288,12 @@ static void hd_struct_free_work(struct work_struct *work) static void hd_struct_free(struct percpu_ref *ref) { struct hd_struct *part = container_of(ref, struct hd_struct, ref); + struct gendisk *disk = part_to_disk(part); + struct disk_part_tbl *ptbl = + rcu_dereference_protected(disk->part_tbl, 1); + + rcu_assign_pointer(ptbl->last_lookup, NULL); + put_device(disk_to_dev(disk)); INIT_RCU_WORK(&part->rcu_work, hd_struct_free_work); queue_rcu_work(system_wq, &part->rcu_work); @@ -309,8 +315,12 @@ void delete_partition(struct gendisk *disk, struct hd_struct *part) struct disk_part_tbl *ptbl = rcu_dereference_protected(disk->part_tbl, 1); + /* + * ->part_tbl is referenced in this part's release handler, so + * we have to hold the disk device + */ + get_device(disk_to_dev(part_to_disk(part))); rcu_assign_pointer(ptbl->part[part->partno], NULL); - rcu_assign_pointer(ptbl->last_lookup, NULL); kobject_put(part->holder_dir); device_del(part_to_dev(part)); |