Merge branch 'for-2.6.37/core' of git://git.kernel.dk/linux-2.6-block
[linux-2.6.git] / block / genhd.c
index 5c9c503..8313834 100644 (file)
@@ -541,13 +541,15 @@ void add_disk(struct gendisk *disk)
        disk->major = MAJOR(devt);
        disk->first_minor = MINOR(devt);
 
+       /* Register BDI before referencing it from bdev */ 
+       bdi = &disk->queue->backing_dev_info;
+       bdi_register_dev(bdi, disk_devt(disk));
+
        blk_register_region(disk_devt(disk), disk->minors, NULL,
                            exact_match, exact_lock, disk);
        register_disk(disk);
        blk_register_queue(disk);
 
-       bdi = &disk->queue->backing_dev_info;
-       bdi_register_dev(bdi, disk_devt(disk));
        retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj,
                                   "bdi");
        WARN_ON(retval);
@@ -930,8 +932,15 @@ static void disk_free_ptbl_rcu_cb(struct rcu_head *head)
 {
        struct disk_part_tbl *ptbl =
                container_of(head, struct disk_part_tbl, rcu_head);
+       struct gendisk *disk = ptbl->disk;
+       struct request_queue *q = disk->queue;
+       unsigned long flags;
 
        kfree(ptbl);
+
+       spin_lock_irqsave(q->queue_lock, flags);
+       elv_quiesce_end(q);
+       spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
 /**
@@ -949,11 +958,17 @@ static void disk_replace_part_tbl(struct gendisk *disk,
                                  struct disk_part_tbl *new_ptbl)
 {
        struct disk_part_tbl *old_ptbl = disk->part_tbl;
+       struct request_queue *q = disk->queue;
 
        rcu_assign_pointer(disk->part_tbl, new_ptbl);
 
        if (old_ptbl) {
                rcu_assign_pointer(old_ptbl->last_lookup, NULL);
+
+               spin_lock_irq(q->queue_lock);
+               elv_quiesce_start(q);
+               spin_unlock_irq(q->queue_lock);
+
                call_rcu(&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb);
        }
 }
@@ -994,6 +1009,7 @@ int disk_expand_part_tbl(struct gendisk *disk, int partno)
                return -ENOMEM;
 
        new_ptbl->len = target;
+       new_ptbl->disk = disk;
 
        for (i = 0; i < len; i++)
                rcu_assign_pointer(new_ptbl->part[i], old_ptbl->part[i]);