Skip to content

Commit 8395ae0

Browse files
committed
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull more SCSI updates from James Bottomley: "Mostly small bug fixes and small updates. The only things of note is a qla2xxx fix for crash on hotplug and timeout and the addition of a user exposed abstraction layer for persistent reservation error return handling (which necessitates the conversion of nvme.c as well as SCSI)" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: qla2xxx: Fix crash when I/O abort times out nvme: Convert NVMe errors to PR errors scsi: sd: Convert SCSI errors to PR errors scsi: core: Rename status_byte to sg_status_byte block: Add error codes for common PR failures scsi: sd: sd_zbc: Trace zone append emulation scsi: libfc: Include the correct header
2 parents ff75ec4 + 68ad831 commit 8395ae0

File tree

11 files changed

+187
-11
lines changed

11 files changed

+187
-11
lines changed

drivers/nvme/host/core.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2117,11 +2117,34 @@ static int nvme_send_ns_pr_command(struct nvme_ns *ns, struct nvme_command *c,
21172117
return nvme_submit_sync_cmd(ns->queue, c, data, 16);
21182118
}
21192119

2120+
static int nvme_sc_to_pr_err(int nvme_sc)
2121+
{
2122+
if (nvme_is_path_error(nvme_sc))
2123+
return PR_STS_PATH_FAILED;
2124+
2125+
switch (nvme_sc) {
2126+
case NVME_SC_SUCCESS:
2127+
return PR_STS_SUCCESS;
2128+
case NVME_SC_RESERVATION_CONFLICT:
2129+
return PR_STS_RESERVATION_CONFLICT;
2130+
case NVME_SC_ONCS_NOT_SUPPORTED:
2131+
return -EOPNOTSUPP;
2132+
case NVME_SC_BAD_ATTRIBUTES:
2133+
case NVME_SC_INVALID_OPCODE:
2134+
case NVME_SC_INVALID_FIELD:
2135+
case NVME_SC_INVALID_NS:
2136+
return -EINVAL;
2137+
default:
2138+
return PR_STS_IOERR;
2139+
}
2140+
}
2141+
21202142
static int nvme_pr_command(struct block_device *bdev, u32 cdw10,
21212143
u64 key, u64 sa_key, u8 op)
21222144
{
21232145
struct nvme_command c = { };
21242146
u8 data[16] = { 0, };
2147+
int ret;
21252148

21262149
put_unaligned_le64(key, &data[0]);
21272150
put_unaligned_le64(sa_key, &data[8]);
@@ -2131,8 +2154,14 @@ static int nvme_pr_command(struct block_device *bdev, u32 cdw10,
21312154

21322155
if (IS_ENABLED(CONFIG_NVME_MULTIPATH) &&
21332156
bdev->bd_disk->fops == &nvme_ns_head_ops)
2134-
return nvme_send_ns_head_pr_command(bdev, &c, data);
2135-
return nvme_send_ns_pr_command(bdev->bd_disk->private_data, &c, data);
2157+
ret = nvme_send_ns_head_pr_command(bdev, &c, data);
2158+
else
2159+
ret = nvme_send_ns_pr_command(bdev->bd_disk->private_data, &c,
2160+
data);
2161+
if (ret < 0)
2162+
return ret;
2163+
2164+
return nvme_sc_to_pr_err(ret);
21362165
}
21372166

21382167
static int nvme_pr_register(struct block_device *bdev, u64 old,

drivers/scsi/libfc/fc_disc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#include <linux/slab.h>
2525
#include <linux/err.h>
2626
#include <linux/export.h>
27-
#include <linux/rculist.h>
27+
#include <linux/list.h>
2828

2929
#include <asm/unaligned.h>
3030

drivers/scsi/qla2xxx/qla_init.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ static void qla24xx_abort_iocb_timeout(void *data)
110110
struct qla_qpair *qpair = sp->qpair;
111111
u32 handle;
112112
unsigned long flags;
113+
int sp_found = 0, cmdsp_found = 0;
113114

114115
if (sp->cmd_sp)
115116
ql_dbg(ql_dbg_async, sp->vha, 0x507c,
@@ -124,27 +125,32 @@ static void qla24xx_abort_iocb_timeout(void *data)
124125
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
125126
for (handle = 1; handle < qpair->req->num_outstanding_cmds; handle++) {
126127
if (sp->cmd_sp && (qpair->req->outstanding_cmds[handle] ==
127-
sp->cmd_sp))
128+
sp->cmd_sp)) {
128129
qpair->req->outstanding_cmds[handle] = NULL;
130+
cmdsp_found = 1;
131+
}
129132

130133
/* removing the abort */
131134
if (qpair->req->outstanding_cmds[handle] == sp) {
132135
qpair->req->outstanding_cmds[handle] = NULL;
136+
sp_found = 1;
133137
break;
134138
}
135139
}
136140
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
137141

138-
if (sp->cmd_sp) {
142+
if (cmdsp_found && sp->cmd_sp) {
139143
/*
140144
* This done function should take care of
141145
* original command ref: INIT
142146
*/
143147
sp->cmd_sp->done(sp->cmd_sp, QLA_OS_TIMER_EXPIRED);
144148
}
145149

146-
abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT);
147-
sp->done(sp, QLA_OS_TIMER_EXPIRED);
150+
if (sp_found) {
151+
abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT);
152+
sp->done(sp, QLA_OS_TIMER_EXPIRED);
153+
}
148154
}
149155

150156
static void qla24xx_abort_sp_done(srb_t *sp, int res)

drivers/scsi/scsi_ioctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ static int scsi_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
376376
* fill in all the output members
377377
*/
378378
hdr->status = scmd->result & 0xff;
379-
hdr->masked_status = status_byte(scmd->result);
379+
hdr->masked_status = sg_status_byte(scmd->result);
380380
hdr->msg_status = COMMAND_COMPLETE;
381381
hdr->host_status = host_byte(scmd->result);
382382
hdr->driver_status = 0;

drivers/scsi/sd.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1709,6 +1709,36 @@ static char sd_pr_type(enum pr_type type)
17091709
}
17101710
};
17111711

1712+
static int sd_scsi_to_pr_err(struct scsi_sense_hdr *sshdr, int result)
1713+
{
1714+
switch (host_byte(result)) {
1715+
case DID_TRANSPORT_MARGINAL:
1716+
case DID_TRANSPORT_DISRUPTED:
1717+
case DID_BUS_BUSY:
1718+
return PR_STS_RETRY_PATH_FAILURE;
1719+
case DID_NO_CONNECT:
1720+
return PR_STS_PATH_FAILED;
1721+
case DID_TRANSPORT_FAILFAST:
1722+
return PR_STS_PATH_FAST_FAILED;
1723+
}
1724+
1725+
switch (status_byte(result)) {
1726+
case SAM_STAT_RESERVATION_CONFLICT:
1727+
return PR_STS_RESERVATION_CONFLICT;
1728+
case SAM_STAT_CHECK_CONDITION:
1729+
if (!scsi_sense_valid(sshdr))
1730+
return PR_STS_IOERR;
1731+
1732+
if (sshdr->sense_key == ILLEGAL_REQUEST &&
1733+
(sshdr->asc == 0x26 || sshdr->asc == 0x24))
1734+
return -EINVAL;
1735+
1736+
fallthrough;
1737+
default:
1738+
return PR_STS_IOERR;
1739+
}
1740+
}
1741+
17121742
static int sd_pr_command(struct block_device *bdev, u8 sa,
17131743
u64 key, u64 sa_key, u8 type, u8 flags)
17141744
{
@@ -1737,7 +1767,10 @@ static int sd_pr_command(struct block_device *bdev, u8 sa,
17371767
scsi_print_sense_hdr(sdev, NULL, &sshdr);
17381768
}
17391769

1740-
return result;
1770+
if (result <= 0)
1771+
return result;
1772+
1773+
return sd_scsi_to_pr_err(&sshdr, result);
17411774
}
17421775

17431776
static int sd_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,

drivers/scsi/sd_trace.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2022 Western Digital Corporation or its affiliates.
4+
*/
5+
#undef TRACE_SYSTEM
6+
#define TRACE_SYSTEM sd
7+
8+
#undef TRACE_INCLUDE_FILE
9+
#define TRACE_INCLUDE_FILE sd_trace
10+
11+
#if !defined(_SD_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
12+
#include <scsi/scsi_cmnd.h>
13+
#include <scsi/scsi_host.h>
14+
#include <linux/tracepoint.h>
15+
16+
TRACE_EVENT(scsi_prepare_zone_append,
17+
18+
TP_PROTO(struct scsi_cmnd *cmnd, sector_t lba,
19+
unsigned int wp_offset),
20+
21+
TP_ARGS(cmnd, lba, wp_offset),
22+
23+
TP_STRUCT__entry(
24+
__field( unsigned int, host_no )
25+
__field( unsigned int, channel )
26+
__field( unsigned int, id )
27+
__field( unsigned int, lun )
28+
__field( sector_t, lba )
29+
__field( unsigned int, wp_offset )
30+
),
31+
32+
TP_fast_assign(
33+
__entry->host_no = cmnd->device->host->host_no;
34+
__entry->channel = cmnd->device->channel;
35+
__entry->id = cmnd->device->id;
36+
__entry->lun = cmnd->device->lun;
37+
__entry->lba = lba;
38+
__entry->wp_offset = wp_offset;
39+
),
40+
41+
TP_printk("host_no=%u, channel=%u id=%u lun=%u lba=%llu wp_offset=%u",
42+
__entry->host_no, __entry->channel, __entry->id,
43+
__entry->lun, __entry->lba, __entry->wp_offset)
44+
);
45+
46+
TRACE_EVENT(scsi_zone_wp_update,
47+
48+
TP_PROTO(struct scsi_cmnd *cmnd, sector_t rq_sector,
49+
unsigned int wp_offset, unsigned int good_bytes),
50+
51+
TP_ARGS(cmnd, rq_sector, wp_offset, good_bytes),
52+
53+
TP_STRUCT__entry(
54+
__field( unsigned int, host_no )
55+
__field( unsigned int, channel )
56+
__field( unsigned int, id )
57+
__field( unsigned int, lun )
58+
__field( sector_t, rq_sector )
59+
__field( unsigned int, wp_offset )
60+
__field( unsigned int, good_bytes )
61+
),
62+
63+
TP_fast_assign(
64+
__entry->host_no = cmnd->device->host->host_no;
65+
__entry->channel = cmnd->device->channel;
66+
__entry->id = cmnd->device->id;
67+
__entry->lun = cmnd->device->lun;
68+
__entry->rq_sector = rq_sector;
69+
__entry->wp_offset = wp_offset;
70+
__entry->good_bytes = good_bytes;
71+
),
72+
73+
TP_printk("host_no=%u, channel=%u id=%u lun=%u rq_sector=%llu" \
74+
" wp_offset=%u good_bytes=%u",
75+
__entry->host_no, __entry->channel, __entry->id,
76+
__entry->lun, __entry->rq_sector, __entry->wp_offset,
77+
__entry->good_bytes)
78+
);
79+
#endif /* _SD_TRACE_H */
80+
81+
/* This part must be outside protection */
82+
#undef TRACE_INCLUDE_PATH
83+
#define TRACE_INCLUDE_PATH ../../drivers/scsi
84+
#include <trace/define_trace.h>

drivers/scsi/sd_zbc.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020

2121
#include "sd.h"
2222

23+
#define CREATE_TRACE_POINTS
24+
#include "sd_trace.h"
25+
2326
/**
2427
* sd_zbc_get_zone_wp_offset - Get zone write pointer offset.
2528
* @zone: Zone for which to return the write pointer offset.
@@ -450,6 +453,7 @@ blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
450453
break;
451454
}
452455

456+
trace_scsi_prepare_zone_append(cmd, *lba, wp_offset);
453457
*lba += wp_offset;
454458
}
455459
spin_unlock_irqrestore(&sdkp->zones_wp_offset_lock, flags);
@@ -558,6 +562,8 @@ static unsigned int sd_zbc_zone_wp_update(struct scsi_cmnd *cmd,
558562

559563
switch (op) {
560564
case REQ_OP_ZONE_APPEND:
565+
trace_scsi_zone_wp_update(cmd, rq->__sector,
566+
sdkp->zones_wp_offset[zno], good_bytes);
561567
rq->__sector += sdkp->zones_wp_offset[zno];
562568
fallthrough;
563569
case REQ_OP_WRITE_ZEROES:

drivers/scsi/sg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1349,7 +1349,7 @@ sg_rq_end_io(struct request *rq, blk_status_t status)
13491349
struct scsi_sense_hdr sshdr;
13501350

13511351
srp->header.status = 0xff & result;
1352-
srp->header.masked_status = status_byte(result);
1352+
srp->header.masked_status = sg_status_byte(result);
13531353
srp->header.msg_status = COMMAND_COMPLETE;
13541354
srp->header.host_status = host_byte(result);
13551355
srp->header.driver_status = driver_byte(result);

include/scsi/scsi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ enum scsi_disposition {
121121
* msg_byte (unused)
122122
* host_byte = set by low-level driver to indicate status.
123123
*/
124+
#define status_byte(result) (result & 0xff)
124125
#define host_byte(result) (((result) >> 16) & 0xff)
125126

126127
#define sense_class(sense) (((sense) >> 4) & 0x7)

include/scsi/sg.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ struct compat_sg_io_hdr {
159159
#define TASK_ABORTED 0x20
160160

161161
/* Obsolete status_byte() declaration */
162-
#define status_byte(result) (((result) >> 1) & 0x7f)
162+
#define sg_status_byte(result) (((result) >> 1) & 0x7f)
163163

164164
typedef struct sg_scsi_id { /* used by SG_GET_SCSI_ID ioctl() */
165165
int host_no; /* as in "scsi<n>" where 'n' is one of 0, 1, 2 etc */

0 commit comments

Comments
 (0)