2011-08-01 04:05:09 +08:00
|
|
|
/*
|
|
|
|
* BSG helper library
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008 James Smart, Emulex Corporation
|
|
|
|
* Copyright (C) 2011 Red Hat, Inc. All rights reserved.
|
|
|
|
* Copyright (C) 2011 Mike Christie
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#ifndef _BLK_BSG_
|
|
|
|
#define _BLK_BSG_
|
|
|
|
|
|
|
|
#include <linux/blkdev.h>
|
bsg-lib: fix kernel panic resulting from missing allocation of reply-buffer
Since we split the scsi_request out of struct request bsg fails to
provide a reply-buffer for the drivers. This was done via the pointer
for sense-data, that is not preallocated anymore.
Failing to allocate/assign it results in illegal dereferences because
LLDs use this pointer unquestioned.
An example panic on s390x, using the zFCP driver, looks like this (I had
debugging on, otherwise NULL-pointer dereferences wouldn't even panic on
s390x):
Unable to handle kernel pointer dereference in virtual kernel address space
Failing address: 6b6b6b6b6b6b6000 TEID: 6b6b6b6b6b6b6403
Fault in home space mode while using kernel ASCE.
AS:0000000001590007 R3:0000000000000024
Oops: 0038 ilc:2 [#1] PREEMPT SMP DEBUG_PAGEALLOC
Modules linked in: <Long List>
CPU: 2 PID: 0 Comm: swapper/2 Not tainted 4.12.0-bsg-regression+ #3
Hardware name: IBM 2964 N96 702 (z/VM 6.4.0)
task: 0000000065cb0100 task.stack: 0000000065cb4000
Krnl PSW : 0704e00180000000 000003ff801e4156 (zfcp_fc_ct_els_job_handler+0x16/0x58 [zfcp])
R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:2 PM:0 RI:0 EA:3
Krnl GPRS: 0000000000000001 000000005fa9d0d0 000000005fa9d078 0000000000e16866
000003ff00000290 6b6b6b6b6b6b6b6b 0000000059f78f00 000000000000000f
00000000593a0958 00000000593a0958 0000000060d88800 000000005ddd4c38
0000000058b50100 07000000659cba08 000003ff801e8556 00000000659cb9a8
Krnl Code: 000003ff801e4146: e31020500004 lg %r1,80(%r2)
000003ff801e414c: 58402040 l %r4,64(%r2)
#000003ff801e4150: e35020200004 lg %r5,32(%r2)
>000003ff801e4156: 50405004 st %r4,4(%r5)
000003ff801e415a: e54c50080000 mvhi 8(%r5),0
000003ff801e4160: e33010280012 lt %r3,40(%r1)
000003ff801e4166: a718fffb lhi %r1,-5
000003ff801e416a: 1803 lr %r0,%r3
Call Trace:
([<000003ff801e8556>] zfcp_fsf_req_complete+0x726/0x768 [zfcp])
[<000003ff801ea82a>] zfcp_fsf_reqid_check+0x102/0x180 [zfcp]
[<000003ff801eb980>] zfcp_qdio_int_resp+0x230/0x278 [zfcp]
[<00000000009b91b6>] qdio_kick_handler+0x2ae/0x2c8
[<00000000009b9e3e>] __tiqdio_inbound_processing+0x406/0xc10
[<00000000001684c2>] tasklet_action+0x15a/0x1d8
[<0000000000bd28ec>] __do_softirq+0x3ec/0x848
[<00000000001675a4>] irq_exit+0x74/0xf8
[<000000000010dd6a>] do_IRQ+0xba/0xf0
[<0000000000bd19e8>] io_int_handler+0x104/0x2d4
[<00000000001033b6>] enabled_wait+0xb6/0x188
([<000000000010339e>] enabled_wait+0x9e/0x188)
[<000000000010396a>] arch_cpu_idle+0x32/0x50
[<0000000000bd0112>] default_idle_call+0x52/0x68
[<00000000001cd0fa>] do_idle+0x102/0x188
[<00000000001cd41e>] cpu_startup_entry+0x3e/0x48
[<0000000000118c64>] smp_start_secondary+0x11c/0x130
[<0000000000bd2016>] restart_int_handler+0x62/0x78
[<0000000000000000>] (null)
INFO: lockdep is turned off.
Last Breaking-Event-Address:
[<000003ff801e41d6>] zfcp_fc_ct_job_handler+0x3e/0x48 [zfcp]
Kernel panic - not syncing: Fatal exception in interrupt
This patch moves bsg-lib to allocate and setup struct bsg_job ahead of
time, including the allocation of a buffer for the reply-data.
This means, struct bsg_job is not allocated separately anymore, but as part
of struct request allocation - similar to struct scsi_cmd. Reflect this in
the function names that used to handle creation/destruction of struct
bsg_job.
Reported-by: Steffen Maier <maier@linux.vnet.ibm.com>
Suggested-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Benjamin Block <bblock@linux.vnet.ibm.com>
Fixes: 82ed4db499b8 ("block: split scsi_request out of struct request")
Cc: <stable@vger.kernel.org> #4.11+
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2017-08-24 07:57:56 +08:00
|
|
|
#include <scsi/scsi_request.h>
|
2011-08-01 04:05:09 +08:00
|
|
|
|
|
|
|
struct request;
|
|
|
|
struct device;
|
|
|
|
struct scatterlist;
|
|
|
|
struct request_queue;
|
|
|
|
|
|
|
|
struct bsg_buffer {
|
|
|
|
unsigned int payload_len;
|
|
|
|
int sg_cnt;
|
|
|
|
struct scatterlist *sg_list;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct bsg_job {
|
|
|
|
struct device *dev;
|
|
|
|
|
2016-11-17 17:31:18 +08:00
|
|
|
struct kref kref;
|
|
|
|
|
2018-03-14 00:28:39 +08:00
|
|
|
unsigned int timeout;
|
|
|
|
|
2011-08-01 04:05:09 +08:00
|
|
|
/* Transport/driver specific request/reply structs */
|
|
|
|
void *request;
|
|
|
|
void *reply;
|
|
|
|
|
|
|
|
unsigned int request_len;
|
|
|
|
unsigned int reply_len;
|
|
|
|
/*
|
|
|
|
* On entry : reply_len indicates the buffer size allocated for
|
|
|
|
* the reply.
|
|
|
|
*
|
|
|
|
* Upon completion : the message handler must set reply_len
|
|
|
|
* to indicates the size of the reply to be returned to the
|
|
|
|
* caller.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* DMA payloads for the request/response */
|
|
|
|
struct bsg_buffer request_payload;
|
|
|
|
struct bsg_buffer reply_payload;
|
|
|
|
|
2018-03-14 00:28:41 +08:00
|
|
|
int result;
|
|
|
|
unsigned int reply_payload_rcv_len;
|
|
|
|
|
2011-08-01 04:05:09 +08:00
|
|
|
void *dd_data; /* Used for driver-specific storage */
|
|
|
|
};
|
|
|
|
|
|
|
|
void bsg_job_done(struct bsg_job *job, int result,
|
|
|
|
unsigned int reply_payload_rcv_len);
|
2017-08-25 23:37:38 +08:00
|
|
|
struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
|
|
|
|
bsg_job_fn *job_fn, int dd_job_size,
|
|
|
|
void (*release)(struct device *));
|
2016-11-17 17:31:23 +08:00
|
|
|
void bsg_job_put(struct bsg_job *job);
|
|
|
|
int __must_check bsg_job_get(struct bsg_job *job);
|
2011-08-01 04:05:09 +08:00
|
|
|
|
|
|
|
#endif
|