Skip to content

Commit

Permalink
loop: fix LO_FLAGS_PARTSCAN hang
Browse files Browse the repository at this point in the history
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: ecdd095 ("block/loop: fix race between I/O and set_status")
Reported-by: Tejun Heo <[email protected]>
Cc: [email protected]
Signed-off-by: Omar Sandoval <[email protected]>
Reviewed-by: Ming Lei <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
  • Loading branch information
osandov authored and axboe committed Mar 2, 2017
1 parent 302ad8c commit e02898b
Showing 1 changed file with 8 additions and 7 deletions.
15 changes: 8 additions & 7 deletions drivers/block/loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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;
}

Expand Down

0 comments on commit e02898b

Please sign in to comment.