Skip to content

Commit ef7e7c8

Browse files
Mikulas Patockaaxboe
Mikulas Patocka
authored andcommitted
loop: fix crash when using unassigned loop device
When the loop module is loaded, it creates 8 loop devices /dev/loop[0-7]. The devices have no request routine and thus, when they are used without being assigned, a crash happens. For example, these commands cause crash (assuming there are no used loop devices): Kernel Fault: Code=26 regs=000000007f420980 (Addr=0000000000000010) CPU: 1 PID: 50 Comm: kworker/1:1 Not tainted 3.11.0 #1 Workqueue: ksnaphd do_metadata [dm_snapshot] task: 000000007fcf4078 ti: 000000007f420000 task.ti: 000000007f420000 [ 116.319988] YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI PSW: 00001000000001001111111100001111 Not tainted r00-03 000000ff0804ff0f 00000000408bf5d0 00000000402d8204 000000007b7ff6c0 r04-07 00000000408a95d0 000000007f420950 000000007b7ff6c0 000000007d06c930 r08-11 000000007f4205c0 0000000000000001 000000007f4205c0 000000007f4204b8 r12-15 0000000000000010 0000000000000000 0000000000000000 0000000000000000 r16-19 000000001108dd48 000000004061cd7c 000000007d859800 000000000800000f r20-23 0000000000000000 0000000000000008 0000000000000000 0000000000000000 r24-27 00000000ffffffff 000000007b7ff6c0 000000007d859800 00000000408a95d0 r28-31 0000000000000000 000000007f420950 000000007f420980 000000007f4208e8 sr00-03 0000000000000000 0000000000000000 0000000000000000 0000000000303000 sr04-07 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 117.549988] IASQ: 0000000000000000 0000000000000000 IAOQ: 00000000402d82fc 00000000402d8300 IIR: 53820020 ISR: 0000000000000000 IOR: 0000000000000010 CPU: 1 CR30: 000000007f420000 CR31: ffffffffffffffff ORIG_R28: 0000000000000001 IAOQ[0]: generic_make_request+0x11c/0x1a0 IAOQ[1]: generic_make_request+0x120/0x1a0 RP(r2): generic_make_request+0x24/0x1a0 Backtrace: [<00000000402d83f0>] submit_bio+0x70/0x140 [<0000000011087c4c>] dispatch_io+0x234/0x478 [dm_mod] [<0000000011087f44>] sync_io+0xb4/0x190 [dm_mod] [<00000000110883bc>] dm_io+0x2c4/0x310 [dm_mod] [<00000000110bfcd0>] do_metadata+0x28/0xb0 [dm_snapshot] [<00000000401591d8>] process_one_work+0x160/0x460 [<0000000040159bc0>] worker_thread+0x300/0x478 [<0000000040161a70>] kthread+0x118/0x128 [<0000000040104020>] end_fault_vector+0x20/0x28 [<0000000040177220>] task_tick_fair+0x420/0x4d0 [<00000000401aa048>] invoke_rcu_core+0x50/0x60 [<00000000401ad5b8>] rcu_check_callbacks+0x210/0x8d8 [<000000004014aaa0>] update_process_times+0xa8/0xc0 [<00000000401ab86c>] rcu_process_callbacks+0x4b4/0x598 [<0000000040142408>] __do_softirq+0x250/0x2c0 [<00000000401789d0>] find_busiest_group+0x3c0/0xc70 [ 119.379988] Kernel panic - not syncing: Kernel Fault Rebooting in 1 seconds.. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Cc: stable@kernel.org Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent ea5ec76 commit ef7e7c8

File tree

1 file changed

+8
-7
lines changed

1 file changed

+8
-7
lines changed

drivers/block/loop.c

+8-7
Original file line numberDiff line numberDiff line change
@@ -894,13 +894,6 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
894894

895895
bio_list_init(&lo->lo_bio_list);
896896

897-
/*
898-
* set queue make_request_fn, and add limits based on lower level
899-
* device
900-
*/
901-
blk_queue_make_request(lo->lo_queue, loop_make_request);
902-
lo->lo_queue->queuedata = lo;
903-
904897
if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)
905898
blk_queue_flush(lo->lo_queue, REQ_FLUSH);
906899

@@ -1618,6 +1611,8 @@ static int loop_add(struct loop_device **l, int i)
16181611
if (!lo)
16191612
goto out;
16201613

1614+
lo->lo_state = Lo_unbound;
1615+
16211616
/* allocate id, if @id >= 0, we're requesting that specific id */
16221617
if (i >= 0) {
16231618
err = idr_alloc(&loop_index_idr, lo, i, i + 1, GFP_KERNEL);
@@ -1635,6 +1630,12 @@ static int loop_add(struct loop_device **l, int i)
16351630
if (!lo->lo_queue)
16361631
goto out_free_idr;
16371632

1633+
/*
1634+
* set queue make_request_fn
1635+
*/
1636+
blk_queue_make_request(lo->lo_queue, loop_make_request);
1637+
lo->lo_queue->queuedata = lo;
1638+
16381639
disk = lo->lo_disk = alloc_disk(1 << part_shift);
16391640
if (!disk)
16401641
goto out_free_queue;

0 commit comments

Comments
 (0)