Message ID | 7e888cad9e6c35835559281d3ab9e05ea48836d0.1488393750.git.osandov@fb.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Mar 2, 2017 at 2:42 AM, Omar Sandoval <osandov@osandov.com> wrote: > From: Omar Sandoval <osandov@fb.com> > > loop_reread_partitions() needs to do I/O, but we just froze the queue, > so we end up waiting forever. This can easily be reproduced with losetup > -P. Fix it by moving the reread to after we unfreeze the queue. > > Fixes: ecdd09597a57 ("block/loop: fix race between I/O and set_status") > Reported-by: Tejun Heo <tj@kernel.org> > Cc: Ming Lei <tom.leiming@gmail.com> > Cc: stable@vger.kernel.org > Signed-off-by: Omar Sandoval <osandov@fb.com> Reviewed-by: Ming Lei <tom.leiming@gmail.com> Thanks, Ming
On 03/01/2017 11:42 AM, Omar Sandoval wrote: > From: Omar Sandoval <osandov@fb.com> > > loop_reread_partitions() needs to do I/O, but we just froze the queue, > so we end up waiting forever. This can easily be reproduced with losetup > -P. Fix it by moving the reread to after we unfreeze the queue. Thanks Omar, applied. That's a brown paper bag bug.
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 4b52a1690329..132c9f371dce 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1142,13 +1142,6 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) (info->lo_flags & LO_FLAGS_AUTOCLEAR)) lo->lo_flags ^= LO_FLAGS_AUTOCLEAR; - if ((info->lo_flags & LO_FLAGS_PARTSCAN) && - !(lo->lo_flags & LO_FLAGS_PARTSCAN)) { - lo->lo_flags |= LO_FLAGS_PARTSCAN; - lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN; - loop_reread_partitions(lo, lo->lo_device); - } - lo->lo_encrypt_key_size = info->lo_encrypt_key_size; lo->lo_init[0] = info->lo_init[0]; lo->lo_init[1] = info->lo_init[1]; @@ -1163,6 +1156,14 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) exit: blk_mq_unfreeze_queue(lo->lo_queue); + + if (!err && (info->lo_flags & LO_FLAGS_PARTSCAN) && + !(lo->lo_flags & LO_FLAGS_PARTSCAN)) { + lo->lo_flags |= LO_FLAGS_PARTSCAN; + lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN; + loop_reread_partitions(lo, lo->lo_device); + } + return err; }