]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
s390/dasd: use blk_mq_rq_from_pdu for per request data
authorSebastian Ott <sebott@linux.ibm.com>
Tue, 15 May 2018 12:05:13 +0000 (14:05 +0200)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Mon, 14 Jan 2019 09:28:55 +0000 (09:28 +0000)
BugLink: http://bugs.launchpad.net/bugs/1808185
[ Upstream commit f0f59a2fab8e52b9d582b39da39f22230ca80aee ]

Dasd uses completion_data from struct request to store per request
private data - this is problematic since this member is part of a
union which is also used by IO schedulers.
Let the block layer maintain space for per request data behind each
struct request.

Fixes crashes on block layer timeouts like this one:

Unable to handle kernel pointer dereference in virtual kernel address space
Failing address: 0000000000000000 TEID: 0000000000000483
Fault in home space mode while using kernel ASCE.
AS:0000000001308007 R3:00000000fffc8007 S:00000000fffcc000 P:000000000000013d
Oops: 0004 ilc:2 [#1] PREEMPT SMP
Modules linked in: [...]
CPU: 0 PID: 1480 Comm: kworker/0:2H Not tainted 4.17.0-rc4-00046-gaa3bcd43b5af #203
Hardware name: IBM 3906 M02 702 (LPAR)
Workqueue: kblockd blk_mq_timeout_work
Krnl PSW : 0000000067ac406b 00000000b6960308 (do_raw_spin_trylock+0x30/0x78)
           R:0 T:1 IO:0 EX:0 Key:0 M:1 W:0 P:0 AS:3 CC:2 PM:0 RI:0 EA:3
Krnl GPRS: 0000000000000c00 0000000000000000 0000000000000000 0000000000000001
           0000000000b9d3c8 0000000000000000 0000000000000001 00000000cf9639d8
           0000000000000000 0700000000000000 0000000000000000 000000000099f09e
           0000000000000000 000000000076e9d0 000000006247bb08 000000006247bae0
Krnl Code: 00000000001c159cb90400c2           lgr     %r12,%r2
           00000000001c15a0a7180000           lhi     %r1,0
          #00000000001c15a4583003a4           l       %r3,932
          >00000000001c15a8ba132000           cs      %r1,%r3,0(%r2)
           00000000001c15aca7180001           lhi     %r1,1
           00000000001c15b0a784000b           brc     8,1c15c6
           00000000001c15b4c0e5004e72aa       brasl   %r14,b8fb08
           00000000001c15ba: 1812               lr      %r1,%r2
Call Trace:
([<0700000000000000>] 0x700000000000000)
 [<0000000000b9d3d2>] _raw_spin_lock_irqsave+0x7a/0xb8
 [<000000000099f09e>] dasd_times_out+0x46/0x278
 [<000000000076ea6e>] blk_mq_terminate_expired+0x9e/0x108
 [<000000000077497a>] bt_for_each+0x102/0x130
 [<0000000000774e54>] blk_mq_queue_tag_busy_iter+0x74/0xd8
 [<000000000076fea0>] blk_mq_timeout_work+0x260/0x320
 [<0000000000169dd4>] process_one_work+0x3bc/0x708
 [<000000000016a382>] worker_thread+0x262/0x408
 [<00000000001723a8>] kthread+0x160/0x178
 [<0000000000b9e73a>] kernel_thread_starter+0x6/0xc
 [<0000000000b9e734>] kernel_thread_starter+0x0/0xc
INFO: lockdep is turned off.
Last Breaking-Event-Address:
 [<0000000000b9d3cc>] _raw_spin_lock_irqsave+0x74/0xb8

Kernel panic - not syncing: Fatal exception: panic_on_oops

Signed-off-by: Sebastian Ott <sebott@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/s390/block/dasd.c

index 68cab79e9ef613728731027af1f5ade97cf45204..80489b484a2edf82a15a851310e4080e3aadf363 100644 (file)
@@ -3046,7 +3046,8 @@ static blk_status_t do_dasd_request(struct blk_mq_hw_ctx *hctx,
        cqr->callback_data = req;
        cqr->status = DASD_CQR_FILLED;
        cqr->dq = dq;
-       req->completion_data = cqr;
+       *((struct dasd_ccw_req **) blk_mq_rq_to_pdu(req)) = cqr;
+
        blk_mq_start_request(req);
        spin_lock(&block->queue_lock);
        list_add_tail(&cqr->blocklist, &block->ccw_queue);
@@ -3070,12 +3071,13 @@ out:
  */
 enum blk_eh_timer_return dasd_times_out(struct request *req, bool reserved)
 {
-       struct dasd_ccw_req *cqr = req->completion_data;
        struct dasd_block *block = req->q->queuedata;
        struct dasd_device *device;
+       struct dasd_ccw_req *cqr;
        unsigned long flags;
        int rc = 0;
 
+       cqr = *((struct dasd_ccw_req **) blk_mq_rq_to_pdu(req));
        if (!cqr)
                return BLK_EH_NOT_HANDLED;
 
@@ -3181,6 +3183,7 @@ static int dasd_alloc_queue(struct dasd_block *block)
        int rc;
 
        block->tag_set.ops = &dasd_mq_ops;
+       block->tag_set.cmd_size = sizeof(struct dasd_ccw_req *);
        block->tag_set.nr_hw_queues = DASD_NR_HW_QUEUES;
        block->tag_set.queue_depth = DASD_MAX_LCU_DEV * DASD_REQ_PER_DEV;
        block->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;