Skip to content

Commit 6cd18e7

Browse files
neilbrownaxboe
authored andcommitted
block: destroy bdi before blockdev is unregistered.
Because of the peculiar way that md devices are created (automatically when the device node is opened), a new device can be created and registered immediately after the blk_unregister_region(disk_devt(disk), disk->minors); call in del_gendisk(). Therefore it is important that all visible artifacts of the previous device are removed before this call. In particular, the 'bdi'. Since: commit c4db59d Author: Christoph Hellwig <[email protected]> fs: don't reassign dirty inodes to default_backing_dev_info moved the device_unregister(bdi->dev); call from bdi_unregister() to bdi_destroy() it has been quite easy to lose a race and have a new (e.g.) "md127" be created after the blk_unregister_region() call and before bdi_destroy() is ultimately called by the final 'put_disk', which must come after del_gendisk(). The new device finds that the bdi name is already registered in sysfs and complains > [ 9627.630029] WARNING: CPU: 18 PID: 3330 at fs/sysfs/dir.c:31 sysfs_warn_dup+0x5a/0x70() > [ 9627.630032] sysfs: cannot create duplicate filename '/devices/virtual/bdi/9:127' We can fix this by moving the bdi_destroy() call out of blk_release_queue() (which can happen very late when a refcount reaches zero) and into blk_cleanup_queue() - which happens exactly when the md device driver calls it. Then it is only necessary for md to call blk_cleanup_queue() before del_gendisk(). As loop.c devices are also created on demand by opening the device node, we make the same change there. Fixes: c4db59d Reported-by: Azat Khuzhin <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: [email protected] (v4.0) Signed-off-by: NeilBrown <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 393a339 commit 6cd18e7

File tree

4 files changed

+5
-5
lines changed

4 files changed

+5
-5
lines changed

block/blk-core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,8 @@ void blk_cleanup_queue(struct request_queue *q)
552552
q->queue_lock = &q->__queue_lock;
553553
spin_unlock_irq(lock);
554554

555+
bdi_destroy(&q->backing_dev_info);
556+
555557
/* @q is and will stay empty, shutdown and put */
556558
blk_put_queue(q);
557559
}

block/blk-sysfs.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,8 +522,6 @@ static void blk_release_queue(struct kobject *kobj)
522522

523523
blk_trace_shutdown(q);
524524

525-
bdi_destroy(&q->backing_dev_info);
526-
527525
ida_simple_remove(&blk_queue_ida, q->id);
528526
call_rcu(&q->rcu_head, blk_free_queue_rcu);
529527
}

drivers/block/loop.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1620,8 +1620,8 @@ static int loop_add(struct loop_device **l, int i)
16201620

16211621
static void loop_remove(struct loop_device *lo)
16221622
{
1623-
del_gendisk(lo->lo_disk);
16241623
blk_cleanup_queue(lo->lo_queue);
1624+
del_gendisk(lo->lo_disk);
16251625
blk_mq_free_tag_set(&lo->tag_set);
16261626
put_disk(lo->lo_disk);
16271627
kfree(lo);

drivers/md/md.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4754,12 +4754,12 @@ static void md_free(struct kobject *ko)
47544754
if (mddev->sysfs_state)
47554755
sysfs_put(mddev->sysfs_state);
47564756

4757+
if (mddev->queue)
4758+
blk_cleanup_queue(mddev->queue);
47574759
if (mddev->gendisk) {
47584760
del_gendisk(mddev->gendisk);
47594761
put_disk(mddev->gendisk);
47604762
}
4761-
if (mddev->queue)
4762-
blk_cleanup_queue(mddev->queue);
47634763

47644764
kfree(mddev);
47654765
}

0 commit comments

Comments
 (0)