loop: set GENHD_FL_NO_PART_SCAN after blkdev_reread_part()
Commit0da03cab87
("loop: Fix deadlock when calling blkdev_reread_part()") moves blkdev_reread_part() out of the loop_ctl_mutex. However, GENHD_FL_NO_PART_SCAN is set before __blkdev_reread_part(). As a result, __blkdev_reread_part() will fail the check of GENHD_FL_NO_PART_SCAN and will not rescan the loop device to delete all partitions. Below are steps to reproduce the issue: step1 # dd if=/dev/zero of=tmp.raw bs=1M count=100 step2 # losetup -P /dev/loop0 tmp.raw step3 # parted /dev/loop0 mklabel gpt step4 # parted -a none -s /dev/loop0 mkpart primary 64s 1 step5 # losetup -d /dev/loop0 Step5 will not be able to delete /dev/loop0p1 (introduced by step4) and there is below kernel warning message: [ 464.414043] __loop_clr_fd: partition scan of loop0 failed (rc=-22) This patch sets GENHD_FL_NO_PART_SCAN after blkdev_reread_part(). Fixes:0da03cab87
("loop: Fix deadlock when calling blkdev_reread_part()") Signed-off-by: Dongli Zhang <dongli.zhang@oracle.com> Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Родитель
40853d6fc6
Коммит
758a58d0bc
|
@ -1089,16 +1089,12 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
|
||||||
kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
|
kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
|
||||||
}
|
}
|
||||||
mapping_set_gfp_mask(filp->f_mapping, gfp);
|
mapping_set_gfp_mask(filp->f_mapping, gfp);
|
||||||
lo->lo_state = Lo_unbound;
|
|
||||||
/* This is safe: open() is still holding a reference. */
|
/* This is safe: open() is still holding a reference. */
|
||||||
module_put(THIS_MODULE);
|
module_put(THIS_MODULE);
|
||||||
blk_mq_unfreeze_queue(lo->lo_queue);
|
blk_mq_unfreeze_queue(lo->lo_queue);
|
||||||
|
|
||||||
partscan = lo->lo_flags & LO_FLAGS_PARTSCAN && bdev;
|
partscan = lo->lo_flags & LO_FLAGS_PARTSCAN && bdev;
|
||||||
lo_number = lo->lo_number;
|
lo_number = lo->lo_number;
|
||||||
lo->lo_flags = 0;
|
|
||||||
if (!part_shift)
|
|
||||||
lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
|
|
||||||
loop_unprepare_queue(lo);
|
loop_unprepare_queue(lo);
|
||||||
out_unlock:
|
out_unlock:
|
||||||
mutex_unlock(&loop_ctl_mutex);
|
mutex_unlock(&loop_ctl_mutex);
|
||||||
|
@ -1121,6 +1117,23 @@ out_unlock:
|
||||||
/* Device is gone, no point in returning error */
|
/* Device is gone, no point in returning error */
|
||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lo->lo_state is set to Lo_unbound here after above partscan has
|
||||||
|
* finished.
|
||||||
|
*
|
||||||
|
* There cannot be anybody else entering __loop_clr_fd() as
|
||||||
|
* lo->lo_backing_file is already cleared and Lo_rundown state
|
||||||
|
* protects us from all the other places trying to change the 'lo'
|
||||||
|
* device.
|
||||||
|
*/
|
||||||
|
mutex_lock(&loop_ctl_mutex);
|
||||||
|
lo->lo_flags = 0;
|
||||||
|
if (!part_shift)
|
||||||
|
lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
|
||||||
|
lo->lo_state = Lo_unbound;
|
||||||
|
mutex_unlock(&loop_ctl_mutex);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Need not hold loop_ctl_mutex to fput backing file.
|
* Need not hold loop_ctl_mutex to fput backing file.
|
||||||
* Calling fput holding loop_ctl_mutex triggers a circular
|
* Calling fput holding loop_ctl_mutex triggers a circular
|
||||||
|
|
Загрузка…
Ссылка в новой задаче