.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * vvvvvvvvvvvvvvvvvvvvvvv Original vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv |
---|
3 | 4 | * Copyright (C) 1992 Eric Youngdale |
---|
.. | .. |
---|
6 | 7 | * anything out of the ordinary is seen. |
---|
7 | 8 | * ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
---|
8 | 9 | * |
---|
9 | | - * Copyright (C) 2001 - 2018 Douglas Gilbert |
---|
| 10 | + * Copyright (C) 2001 - 2020 Douglas Gilbert |
---|
10 | 11 | * |
---|
11 | | - * This program is free software; you can redistribute it and/or modify |
---|
12 | | - * it under the terms of the GNU General Public License as published by |
---|
13 | | - * the Free Software Foundation; either version 2, or (at your option) |
---|
14 | | - * any later version. |
---|
15 | | - * |
---|
16 | | - * For documentation see http://sg.danny.cz/sg/sdebug26.html |
---|
17 | | - * |
---|
| 12 | + * For documentation see http://sg.danny.cz/sg/scsi_debug.html |
---|
18 | 13 | */ |
---|
19 | 14 | |
---|
20 | 15 | |
---|
.. | .. |
---|
43 | 38 | #include <linux/hrtimer.h> |
---|
44 | 39 | #include <linux/uuid.h> |
---|
45 | 40 | #include <linux/t10-pi.h> |
---|
| 41 | +#include <linux/msdos_partition.h> |
---|
| 42 | +#include <linux/random.h> |
---|
| 43 | +#include <linux/xarray.h> |
---|
| 44 | +#include <linux/prefetch.h> |
---|
46 | 45 | |
---|
47 | 46 | #include <net/checksum.h> |
---|
48 | 47 | |
---|
.. | .. |
---|
61 | 60 | #include "scsi_logging.h" |
---|
62 | 61 | |
---|
63 | 62 | /* make sure inq_product_rev string corresponds to this version */ |
---|
64 | | -#define SDEBUG_VERSION "0188" /* format to fit INQUIRY revision field */ |
---|
65 | | -static const char *sdebug_version_date = "20190125"; |
---|
| 63 | +#define SDEBUG_VERSION "0190" /* format to fit INQUIRY revision field */ |
---|
| 64 | +static const char *sdebug_version_date = "20200710"; |
---|
66 | 65 | |
---|
67 | 66 | #define MY_NAME "scsi_debug" |
---|
68 | 67 | |
---|
.. | .. |
---|
76 | 75 | #define LBA_OUT_OF_RANGE 0x21 |
---|
77 | 76 | #define INVALID_FIELD_IN_CDB 0x24 |
---|
78 | 77 | #define INVALID_FIELD_IN_PARAM_LIST 0x26 |
---|
| 78 | +#define WRITE_PROTECTED 0x27 |
---|
79 | 79 | #define UA_RESET_ASC 0x29 |
---|
80 | 80 | #define UA_CHANGED_ASC 0x2a |
---|
81 | 81 | #define TARGET_CHANGED_ASC 0x3f |
---|
.. | .. |
---|
94 | 94 | #define MICROCODE_CHANGED_ASCQ 0x1 /* with TARGET_CHANGED_ASC */ |
---|
95 | 95 | #define MICROCODE_CHANGED_WO_RESET_ASCQ 0x16 |
---|
96 | 96 | #define WRITE_ERROR_ASC 0xc |
---|
| 97 | +#define UNALIGNED_WRITE_ASCQ 0x4 |
---|
| 98 | +#define WRITE_BOUNDARY_ASCQ 0x5 |
---|
| 99 | +#define READ_INVDATA_ASCQ 0x6 |
---|
| 100 | +#define READ_BOUNDARY_ASCQ 0x7 |
---|
| 101 | +#define INSUFF_ZONE_ASCQ 0xe |
---|
97 | 102 | |
---|
98 | 103 | /* Additional Sense Code Qualifier (ASCQ) */ |
---|
99 | 104 | #define ACK_NAK_TO 0x3 |
---|
.. | .. |
---|
108 | 113 | #define DEF_ATO 1 |
---|
109 | 114 | #define DEF_CDB_LEN 10 |
---|
110 | 115 | #define DEF_JDELAY 1 /* if > 0 unit is a jiffy */ |
---|
| 116 | +#define DEF_DEV_SIZE_PRE_INIT 0 |
---|
111 | 117 | #define DEF_DEV_SIZE_MB 8 |
---|
| 118 | +#define DEF_ZBC_DEV_SIZE_MB 128 |
---|
112 | 119 | #define DEF_DIF 0 |
---|
113 | 120 | #define DEF_DIX 0 |
---|
| 121 | +#define DEF_PER_HOST_STORE false |
---|
114 | 122 | #define DEF_D_SENSE 0 |
---|
115 | 123 | #define DEF_EVERY_NTH 0 |
---|
116 | 124 | #define DEF_FAKE_RW 0 |
---|
.. | .. |
---|
129 | 137 | #define DEF_PHYSBLK_EXP 0 |
---|
130 | 138 | #define DEF_OPT_XFERLEN_EXP 0 |
---|
131 | 139 | #define DEF_PTYPE TYPE_DISK |
---|
| 140 | +#define DEF_RANDOM false |
---|
132 | 141 | #define DEF_REMOVABLE false |
---|
133 | 142 | #define DEF_SCSI_LEVEL 7 /* INQUIRY, byte2 [6->SPC-4; 7->SPC-5] */ |
---|
134 | 143 | #define DEF_SECTOR_SIZE 512 |
---|
.. | .. |
---|
142 | 151 | #define DEF_STRICT 0 |
---|
143 | 152 | #define DEF_STATISTICS false |
---|
144 | 153 | #define DEF_SUBMIT_QUEUES 1 |
---|
| 154 | +#define DEF_TUR_MS_TO_READY 0 |
---|
145 | 155 | #define DEF_UUID_CTL 0 |
---|
146 | 156 | #define JDELAY_OVERRIDDEN -9999 |
---|
| 157 | + |
---|
| 158 | +/* Default parameters for ZBC drives */ |
---|
| 159 | +#define DEF_ZBC_ZONE_SIZE_MB 128 |
---|
| 160 | +#define DEF_ZBC_MAX_OPEN_ZONES 8 |
---|
| 161 | +#define DEF_ZBC_NR_CONV_ZONES 1 |
---|
147 | 162 | |
---|
148 | 163 | #define SDEBUG_LUN_0_VAL 0 |
---|
149 | 164 | |
---|
.. | .. |
---|
173 | 188 | SDEBUG_OPT_SHORT_TRANSFER | \ |
---|
174 | 189 | SDEBUG_OPT_HOST_BUSY | \ |
---|
175 | 190 | SDEBUG_OPT_CMD_ABORT) |
---|
176 | | -/* When "every_nth" > 0 then modulo "every_nth" commands: |
---|
177 | | - * - a missing response is simulated if SDEBUG_OPT_TIMEOUT is set |
---|
178 | | - * - a RECOVERED_ERROR is simulated on successful read and write |
---|
179 | | - * commands if SDEBUG_OPT_RECOVERED_ERR is set. |
---|
180 | | - * - a TRANSPORT_ERROR is simulated on successful read and write |
---|
181 | | - * commands if SDEBUG_OPT_TRANSPORT_ERR is set. |
---|
182 | | - * - similarly for DIF_ERR, DIX_ERR, SHORT_TRANSFER, HOST_BUSY and |
---|
183 | | - * CMD_ABORT |
---|
184 | | - * |
---|
185 | | - * When "every_nth" < 0 then after "- every_nth" commands the selected |
---|
186 | | - * error will be injected. The error will be injected on every subsequent |
---|
187 | | - * command until some other action occurs; for example, the user writing |
---|
188 | | - * a new value (other than -1 or 1) to every_nth: |
---|
189 | | - * echo 0 > /sys/bus/pseudo/drivers/scsi_debug/every_nth |
---|
190 | | - */ |
---|
| 191 | +#define SDEBUG_OPT_RECOV_DIF_DIX (SDEBUG_OPT_RECOVERED_ERR | \ |
---|
| 192 | + SDEBUG_OPT_DIF_ERR | SDEBUG_OPT_DIX_ERR) |
---|
191 | 193 | |
---|
192 | 194 | /* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs) are returned in |
---|
193 | 195 | * priority order. In the subset implemented here lower numbers have higher |
---|
.. | .. |
---|
207 | 209 | #define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */ |
---|
208 | 210 | #define OPT_MEDIUM_ERR_NUM 10 /* number of consecutive medium errs */ |
---|
209 | 211 | |
---|
210 | | -/* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1) |
---|
211 | | - * or "peripheral device" addressing (value 0) */ |
---|
212 | | -#define SAM2_LUN_ADDRESS_METHOD 0 |
---|
213 | | - |
---|
214 | 212 | /* SDEBUG_CANQUEUE is the maximum number of commands that can be queued |
---|
215 | 213 | * (for response) per submit queue at one time. Can be reduced by max_queue |
---|
216 | 214 | * option. Command responses are not queued when jdelay=0 and ndelay=0. The |
---|
.. | .. |
---|
222 | 220 | #define SDEBUG_CANQUEUE (SDEBUG_CANQUEUE_WORDS * BITS_PER_LONG) |
---|
223 | 221 | #define DEF_CMD_PER_LUN 255 |
---|
224 | 222 | |
---|
225 | | -#define F_D_IN 1 |
---|
226 | | -#define F_D_OUT 2 |
---|
| 223 | +/* UA - Unit Attention; SA - Service Action; SSU - Start Stop Unit */ |
---|
| 224 | +#define F_D_IN 1 /* Data-in command (e.g. READ) */ |
---|
| 225 | +#define F_D_OUT 2 /* Data-out command (e.g. WRITE) */ |
---|
227 | 226 | #define F_D_OUT_MAYBE 4 /* WRITE SAME, NDOB bit */ |
---|
228 | 227 | #define F_D_UNKN 8 |
---|
229 | | -#define F_RL_WLUN_OK 0x10 |
---|
230 | | -#define F_SKIP_UA 0x20 |
---|
231 | | -#define F_DELAY_OVERR 0x40 |
---|
232 | | -#define F_SA_LOW 0x80 /* cdb byte 1, bits 4 to 0 */ |
---|
233 | | -#define F_SA_HIGH 0x100 /* as used by variable length cdbs */ |
---|
234 | | -#define F_INV_OP 0x200 |
---|
235 | | -#define F_FAKE_RW 0x400 |
---|
236 | | -#define F_M_ACCESS 0x800 /* media access */ |
---|
237 | | -#define F_SSU_DELAY 0x1000 |
---|
238 | | -#define F_SYNC_DELAY 0x2000 |
---|
| 228 | +#define F_RL_WLUN_OK 0x10 /* allowed with REPORT LUNS W-LUN */ |
---|
| 229 | +#define F_SKIP_UA 0x20 /* bypass UAs (e.g. INQUIRY command) */ |
---|
| 230 | +#define F_DELAY_OVERR 0x40 /* for commands like INQUIRY */ |
---|
| 231 | +#define F_SA_LOW 0x80 /* SA is in cdb byte 1, bits 4 to 0 */ |
---|
| 232 | +#define F_SA_HIGH 0x100 /* SA is in cdb bytes 8 and 9 */ |
---|
| 233 | +#define F_INV_OP 0x200 /* invalid opcode (not supported) */ |
---|
| 234 | +#define F_FAKE_RW 0x400 /* bypass resp_*() when fake_rw set */ |
---|
| 235 | +#define F_M_ACCESS 0x800 /* media access, reacts to SSU state */ |
---|
| 236 | +#define F_SSU_DELAY 0x1000 /* SSU command delay (long-ish) */ |
---|
| 237 | +#define F_SYNC_DELAY 0x2000 /* SYNCHRONIZE CACHE delay */ |
---|
239 | 238 | |
---|
| 239 | +/* Useful combinations of the above flags */ |
---|
240 | 240 | #define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR) |
---|
241 | 241 | #define FF_MEDIA_IO (F_M_ACCESS | F_FAKE_RW) |
---|
242 | 242 | #define FF_SA (F_SA_HIGH | F_SA_LOW) |
---|
.. | .. |
---|
246 | 246 | |
---|
247 | 247 | #define SDEBUG_MAX_CMD_LEN 32 |
---|
248 | 248 | |
---|
| 249 | +#define SDEB_XA_NOT_IN_USE XA_MARK_1 |
---|
| 250 | + |
---|
| 251 | +/* Zone types (zbcr05 table 25) */ |
---|
| 252 | +enum sdebug_z_type { |
---|
| 253 | + ZBC_ZONE_TYPE_CNV = 0x1, |
---|
| 254 | + ZBC_ZONE_TYPE_SWR = 0x2, |
---|
| 255 | + ZBC_ZONE_TYPE_SWP = 0x3, |
---|
| 256 | +}; |
---|
| 257 | + |
---|
| 258 | +/* enumeration names taken from table 26, zbcr05 */ |
---|
| 259 | +enum sdebug_z_cond { |
---|
| 260 | + ZBC_NOT_WRITE_POINTER = 0x0, |
---|
| 261 | + ZC1_EMPTY = 0x1, |
---|
| 262 | + ZC2_IMPLICIT_OPEN = 0x2, |
---|
| 263 | + ZC3_EXPLICIT_OPEN = 0x3, |
---|
| 264 | + ZC4_CLOSED = 0x4, |
---|
| 265 | + ZC6_READ_ONLY = 0xd, |
---|
| 266 | + ZC5_FULL = 0xe, |
---|
| 267 | + ZC7_OFFLINE = 0xf, |
---|
| 268 | +}; |
---|
| 269 | + |
---|
| 270 | +struct sdeb_zone_state { /* ZBC: per zone state */ |
---|
| 271 | + enum sdebug_z_type z_type; |
---|
| 272 | + enum sdebug_z_cond z_cond; |
---|
| 273 | + bool z_non_seq_resource; |
---|
| 274 | + unsigned int z_size; |
---|
| 275 | + sector_t z_start; |
---|
| 276 | + sector_t z_wp; |
---|
| 277 | +}; |
---|
249 | 278 | |
---|
250 | 279 | struct sdebug_dev_info { |
---|
251 | 280 | struct list_head dev_list; |
---|
.. | .. |
---|
256 | 285 | struct sdebug_host_info *sdbg_host; |
---|
257 | 286 | unsigned long uas_bm[1]; |
---|
258 | 287 | atomic_t num_in_q; |
---|
259 | | - atomic_t stopped; |
---|
| 288 | + atomic_t stopped; /* 1: by SSU, 2: device start */ |
---|
260 | 289 | bool used; |
---|
| 290 | + |
---|
| 291 | + /* For ZBC devices */ |
---|
| 292 | + enum blk_zoned_model zmodel; |
---|
| 293 | + unsigned int zsize; |
---|
| 294 | + unsigned int zsize_shift; |
---|
| 295 | + unsigned int nr_zones; |
---|
| 296 | + unsigned int nr_conv_zones; |
---|
| 297 | + unsigned int nr_imp_open; |
---|
| 298 | + unsigned int nr_exp_open; |
---|
| 299 | + unsigned int nr_closed; |
---|
| 300 | + unsigned int max_open; |
---|
| 301 | + ktime_t create_ts; /* time since bootup that this device was created */ |
---|
| 302 | + struct sdeb_zone_state *zstate; |
---|
261 | 303 | }; |
---|
262 | 304 | |
---|
263 | 305 | struct sdebug_host_info { |
---|
264 | 306 | struct list_head host_list; |
---|
| 307 | + int si_idx; /* sdeb_store_info (per host) xarray index */ |
---|
265 | 308 | struct Scsi_Host *shost; |
---|
266 | 309 | struct device dev; |
---|
267 | 310 | struct list_head dev_info_list; |
---|
| 311 | +}; |
---|
| 312 | + |
---|
| 313 | +/* There is an xarray of pointers to this struct's objects, one per host */ |
---|
| 314 | +struct sdeb_store_info { |
---|
| 315 | + rwlock_t macc_lck; /* for atomic media access on this store */ |
---|
| 316 | + u8 *storep; /* user data storage (ram) */ |
---|
| 317 | + struct t10_pi_tuple *dif_storep; /* protection info */ |
---|
| 318 | + void *map_storep; /* provisioning map */ |
---|
268 | 319 | }; |
---|
269 | 320 | |
---|
270 | 321 | #define to_sdebug_host(d) \ |
---|
.. | .. |
---|
278 | 329 | struct execute_work ew; |
---|
279 | 330 | int sqa_idx; /* index of sdebug_queue array */ |
---|
280 | 331 | int qc_idx; /* index of sdebug_queued_cmd array within sqa_idx */ |
---|
| 332 | + int hc_idx; /* hostwide tag index */ |
---|
281 | 333 | int issuing_cpu; |
---|
282 | 334 | bool init_hrt; |
---|
283 | 335 | bool init_wq; |
---|
.. | .. |
---|
291 | 343 | */ |
---|
292 | 344 | struct sdebug_defer *sd_dp; |
---|
293 | 345 | struct scsi_cmnd *a_cmnd; |
---|
294 | | - unsigned int inj_recovered:1; |
---|
295 | | - unsigned int inj_transport:1; |
---|
296 | | - unsigned int inj_dif:1; |
---|
297 | | - unsigned int inj_dix:1; |
---|
298 | | - unsigned int inj_short:1; |
---|
299 | | - unsigned int inj_host_busy:1; |
---|
300 | | - unsigned int inj_cmd_abort:1; |
---|
301 | 346 | }; |
---|
302 | 347 | |
---|
303 | 348 | struct sdebug_queue { |
---|
.. | .. |
---|
311 | 356 | static atomic_t sdebug_completions; /* count of deferred completions */ |
---|
312 | 357 | static atomic_t sdebug_miss_cpus; /* submission + completion cpus differ */ |
---|
313 | 358 | static atomic_t sdebug_a_tsf; /* 'almost task set full' counter */ |
---|
| 359 | +static atomic_t sdeb_inject_pending; |
---|
314 | 360 | |
---|
315 | 361 | struct opcode_info_t { |
---|
316 | 362 | u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff */ |
---|
.. | .. |
---|
342 | 388 | SDEB_I_SERV_ACT_OUT_16 = 13, /* add ...SERV_ACT_OUT_12 if needed */ |
---|
343 | 389 | SDEB_I_MAINT_IN = 14, |
---|
344 | 390 | SDEB_I_MAINT_OUT = 15, |
---|
345 | | - SDEB_I_VERIFY = 16, /* 10 only */ |
---|
| 391 | + SDEB_I_VERIFY = 16, /* VERIFY(10), VERIFY(16) */ |
---|
346 | 392 | SDEB_I_VARIABLE_LEN = 17, /* READ(32), WRITE(32), WR_SCAT(32) */ |
---|
347 | 393 | SDEB_I_RESERVE = 18, /* 6, 10 */ |
---|
348 | 394 | SDEB_I_RELEASE = 19, /* 6, 10 */ |
---|
.. | .. |
---|
351 | 397 | SDEB_I_ATA_PT = 22, /* 12, 16 */ |
---|
352 | 398 | SDEB_I_SEND_DIAG = 23, |
---|
353 | 399 | SDEB_I_UNMAP = 24, |
---|
354 | | - SDEB_I_XDWRITEREAD = 25, /* 10 only */ |
---|
355 | | - SDEB_I_WRITE_BUFFER = 26, |
---|
356 | | - SDEB_I_WRITE_SAME = 27, /* 10, 16 */ |
---|
357 | | - SDEB_I_SYNC_CACHE = 28, /* 10, 16 */ |
---|
358 | | - SDEB_I_COMP_WRITE = 29, |
---|
359 | | - SDEB_I_LAST_ELEMENT = 30, /* keep this last (previous + 1) */ |
---|
| 400 | + SDEB_I_WRITE_BUFFER = 25, |
---|
| 401 | + SDEB_I_WRITE_SAME = 26, /* 10, 16 */ |
---|
| 402 | + SDEB_I_SYNC_CACHE = 27, /* 10, 16 */ |
---|
| 403 | + SDEB_I_COMP_WRITE = 28, |
---|
| 404 | + SDEB_I_PRE_FETCH = 29, /* 10, 16 */ |
---|
| 405 | + SDEB_I_ZONE_OUT = 30, /* 0x94+SA; includes no data xfer */ |
---|
| 406 | + SDEB_I_ZONE_IN = 31, /* 0x95+SA; all have data-in */ |
---|
| 407 | + SDEB_I_LAST_ELEM_P1 = 32, /* keep this last (previous + 1) */ |
---|
360 | 408 | }; |
---|
361 | 409 | |
---|
362 | 410 | |
---|
.. | .. |
---|
372 | 420 | /* 0x20; 0x20->0x3f: 10 byte cdbs */ |
---|
373 | 421 | 0, 0, 0, 0, 0, SDEB_I_READ_CAPACITY, 0, 0, |
---|
374 | 422 | SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, SDEB_I_VERIFY, |
---|
375 | | - 0, 0, 0, 0, 0, SDEB_I_SYNC_CACHE, 0, 0, |
---|
| 423 | + 0, 0, 0, 0, SDEB_I_PRE_FETCH, SDEB_I_SYNC_CACHE, 0, 0, |
---|
376 | 424 | 0, 0, 0, SDEB_I_WRITE_BUFFER, 0, 0, 0, 0, |
---|
377 | 425 | /* 0x40; 0x40->0x5f: 10 byte cdbs */ |
---|
378 | 426 | 0, SDEB_I_WRITE_SAME, SDEB_I_UNMAP, 0, 0, 0, 0, 0, |
---|
379 | 427 | 0, 0, 0, 0, 0, SDEB_I_LOG_SENSE, 0, 0, |
---|
380 | | - 0, 0, 0, SDEB_I_XDWRITEREAD, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE, |
---|
| 428 | + 0, 0, 0, 0, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE, |
---|
381 | 429 | SDEB_I_RELEASE, |
---|
382 | 430 | 0, 0, SDEB_I_MODE_SENSE, 0, 0, 0, 0, 0, |
---|
383 | 431 | /* 0x60; 0x60->0x7d are reserved, 0x7e is "extended cdb" */ |
---|
.. | .. |
---|
386 | 434 | 0, SDEB_I_VARIABLE_LEN, |
---|
387 | 435 | /* 0x80; 0x80->0x9f: 16 byte cdbs */ |
---|
388 | 436 | 0, 0, 0, 0, 0, SDEB_I_ATA_PT, 0, 0, |
---|
389 | | - SDEB_I_READ, SDEB_I_COMP_WRITE, SDEB_I_WRITE, 0, 0, 0, 0, 0, |
---|
390 | | - 0, SDEB_I_SYNC_CACHE, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0, |
---|
| 437 | + SDEB_I_READ, SDEB_I_COMP_WRITE, SDEB_I_WRITE, 0, |
---|
| 438 | + 0, 0, 0, SDEB_I_VERIFY, |
---|
| 439 | + SDEB_I_PRE_FETCH, SDEB_I_SYNC_CACHE, 0, SDEB_I_WRITE_SAME, |
---|
| 440 | + SDEB_I_ZONE_OUT, SDEB_I_ZONE_IN, 0, 0, |
---|
391 | 441 | 0, 0, 0, 0, 0, 0, SDEB_I_SERV_ACT_IN_16, SDEB_I_SERV_ACT_OUT_16, |
---|
392 | 442 | /* 0xa0; 0xa0->0xbf: 12 byte cdbs */ |
---|
393 | 443 | SDEB_I_REPORT_LUNS, SDEB_I_ATA_PT, 0, SDEB_I_MAINT_IN, |
---|
.. | .. |
---|
428 | 478 | static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
429 | 479 | static int resp_rsup_opcodes(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
430 | 480 | static int resp_rsup_tmfs(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
| 481 | +static int resp_verify(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
431 | 482 | static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
432 | 483 | static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
433 | | -static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
434 | 484 | static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
435 | 485 | static int resp_write_buffer(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
436 | 486 | static int resp_sync_cache(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
| 487 | +static int resp_pre_fetch(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
| 488 | +static int resp_report_zones(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
| 489 | +static int resp_open_zone(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
| 490 | +static int resp_close_zone(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
| 491 | +static int resp_finish_zone(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
| 492 | +static int resp_rwp_zone(struct scsi_cmnd *, struct sdebug_dev_info *); |
---|
| 493 | + |
---|
| 494 | +static int sdebug_do_add_host(bool mk_new_store); |
---|
| 495 | +static int sdebug_add_host_helper(int per_host_idx); |
---|
| 496 | +static void sdebug_do_remove_host(bool the_end); |
---|
| 497 | +static int sdebug_add_store(void); |
---|
| 498 | +static void sdebug_erase_store(int idx, struct sdeb_store_info *sip); |
---|
| 499 | +static void sdebug_erase_all_stores(bool apart_from_first); |
---|
437 | 500 | |
---|
438 | 501 | /* |
---|
439 | 502 | * The following are overflow arrays for cdbs that "hit" the same index in |
---|
.. | .. |
---|
471 | 534 | {0, 0xaa, 0, F_D_OUT | FF_MEDIA_IO, resp_write_dt0, /* WRITE(12) */ |
---|
472 | 535 | NULL, {12, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
---|
473 | 536 | 0xbf, 0xc7, 0, 0, 0, 0} }, |
---|
| 537 | +}; |
---|
| 538 | + |
---|
| 539 | +static const struct opcode_info_t verify_iarr[] = { |
---|
| 540 | + {0, 0x2f, 0, F_D_OUT_MAYBE | FF_MEDIA_IO, resp_verify,/* VERIFY(10) */ |
---|
| 541 | + NULL, {10, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xc7, |
---|
| 542 | + 0, 0, 0, 0, 0, 0} }, |
---|
474 | 543 | }; |
---|
475 | 544 | |
---|
476 | 545 | static const struct opcode_info_t sa_in_16_iarr[] = { |
---|
.. | .. |
---|
519 | 588 | 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} }, /* SYNC_CACHE (16) */ |
---|
520 | 589 | }; |
---|
521 | 590 | |
---|
| 591 | +static const struct opcode_info_t pre_fetch_iarr[] = { |
---|
| 592 | + {0, 0x90, 0, F_SYNC_DELAY | FF_MEDIA_IO, resp_pre_fetch, NULL, |
---|
| 593 | + {16, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
---|
| 594 | + 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} }, /* PRE-FETCH (16) */ |
---|
| 595 | +}; |
---|
| 596 | + |
---|
| 597 | +static const struct opcode_info_t zone_out_iarr[] = { /* ZONE OUT(16) */ |
---|
| 598 | + {0, 0x94, 0x1, F_SA_LOW | F_M_ACCESS, resp_close_zone, NULL, |
---|
| 599 | + {16, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
---|
| 600 | + 0xff, 0, 0, 0xff, 0xff, 0x1, 0xc7} }, /* CLOSE ZONE */ |
---|
| 601 | + {0, 0x94, 0x2, F_SA_LOW | F_M_ACCESS, resp_finish_zone, NULL, |
---|
| 602 | + {16, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
---|
| 603 | + 0xff, 0, 0, 0xff, 0xff, 0x1, 0xc7} }, /* FINISH ZONE */ |
---|
| 604 | + {0, 0x94, 0x4, F_SA_LOW | F_M_ACCESS, resp_rwp_zone, NULL, |
---|
| 605 | + {16, 0x4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
---|
| 606 | + 0xff, 0, 0, 0xff, 0xff, 0x1, 0xc7} }, /* RESET WRITE POINTER */ |
---|
| 607 | +}; |
---|
| 608 | + |
---|
| 609 | +static const struct opcode_info_t zone_in_iarr[] = { /* ZONE IN(16) */ |
---|
| 610 | + {0, 0x95, 0x6, F_SA_LOW | F_D_IN | F_M_ACCESS, NULL, NULL, |
---|
| 611 | + {16, 0x6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
---|
| 612 | + 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} }, /* REPORT ZONES */ |
---|
| 613 | +}; |
---|
| 614 | + |
---|
522 | 615 | |
---|
523 | 616 | /* This array is accessed via SDEB_I_* values. Make sure all are mapped, |
---|
524 | 617 | * plus the terminating elements for logic that scans this table such as |
---|
525 | 618 | * REPORT SUPPORTED OPERATION CODES. */ |
---|
526 | | -static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = { |
---|
| 619 | +static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEM_P1 + 1] = { |
---|
527 | 620 | /* 0 */ |
---|
528 | 621 | {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* unknown opcodes */ |
---|
529 | 622 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, |
---|
.. | .. |
---|
573 | 666 | /* 15 */ |
---|
574 | 667 | {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* MAINT OUT */ |
---|
575 | 668 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, |
---|
576 | | - {0, 0x2f, 0, F_D_OUT_MAYBE | FF_MEDIA_IO, NULL, NULL, /* VERIFY(10) */ |
---|
577 | | - {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, |
---|
578 | | - 0, 0, 0, 0, 0, 0} }, |
---|
| 669 | + {ARRAY_SIZE(verify_iarr), 0x8f, 0, |
---|
| 670 | + F_D_OUT_MAYBE | FF_MEDIA_IO, resp_verify, /* VERIFY(16) */ |
---|
| 671 | + verify_iarr, {16, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
---|
| 672 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} }, |
---|
579 | 673 | {ARRAY_SIZE(vl_iarr), 0x7f, 0x9, F_SA_HIGH | F_D_IN | FF_MEDIA_IO, |
---|
580 | 674 | resp_read_dt0, vl_iarr, /* VARIABLE LENGTH, READ(32) */ |
---|
581 | 675 | {32, 0xc7, 0, 0, 0, 0, 0x3f, 0x18, 0x0, 0x9, 0xfe, 0, 0xff, 0xff, |
---|
.. | .. |
---|
600 | 694 | {0, 0x42, 0, F_D_OUT | FF_MEDIA_IO, resp_unmap, NULL, /* UNMAP */ |
---|
601 | 695 | {10, 0x1, 0, 0, 0, 0, 0x3f, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} }, |
---|
602 | 696 | /* 25 */ |
---|
603 | | - {0, 0x53, 0, F_D_IN | F_D_OUT | FF_MEDIA_IO, resp_xdwriteread_10, |
---|
604 | | - NULL, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, |
---|
605 | | - 0, 0, 0, 0, 0, 0} }, /* XDWRITEREAD(10) */ |
---|
606 | 697 | {0, 0x3b, 0, F_D_OUT_MAYBE, resp_write_buffer, NULL, |
---|
607 | 698 | {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, |
---|
608 | 699 | 0, 0, 0, 0} }, /* WRITE_BUFFER */ |
---|
.. | .. |
---|
617 | 708 | {0, 0x89, 0, F_D_OUT | FF_MEDIA_IO, resp_comp_write, NULL, |
---|
618 | 709 | {16, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, |
---|
619 | 710 | 0, 0xff, 0x3f, 0xc7} }, /* COMPARE AND WRITE */ |
---|
| 711 | + {ARRAY_SIZE(pre_fetch_iarr), 0x34, 0, F_SYNC_DELAY | FF_MEDIA_IO, |
---|
| 712 | + resp_pre_fetch, pre_fetch_iarr, |
---|
| 713 | + {10, 0x2, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, 0, 0, |
---|
| 714 | + 0, 0, 0, 0} }, /* PRE-FETCH (10) */ |
---|
620 | 715 | |
---|
621 | 716 | /* 30 */ |
---|
| 717 | + {ARRAY_SIZE(zone_out_iarr), 0x94, 0x3, F_SA_LOW | F_M_ACCESS, |
---|
| 718 | + resp_open_zone, zone_out_iarr, /* ZONE_OUT(16), OPEN ZONE) */ |
---|
| 719 | + {16, 0x3 /* SA */, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
---|
| 720 | + 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x1, 0xc7} }, |
---|
| 721 | + {ARRAY_SIZE(zone_in_iarr), 0x95, 0x0, F_SA_LOW | F_M_ACCESS, |
---|
| 722 | + resp_report_zones, zone_in_iarr, /* ZONE_IN(16), REPORT ZONES) */ |
---|
| 723 | + {16, 0x0 /* SA */, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
---|
| 724 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xc7} }, |
---|
| 725 | +/* sentinel */ |
---|
622 | 726 | {0xff, 0, 0, 0, NULL, NULL, /* terminating element */ |
---|
623 | 727 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, |
---|
624 | 728 | }; |
---|
625 | 729 | |
---|
626 | | -static int sdebug_add_host = DEF_NUM_HOST; |
---|
| 730 | +static int sdebug_num_hosts; |
---|
| 731 | +static int sdebug_add_host = DEF_NUM_HOST; /* in sysfs this is relative */ |
---|
627 | 732 | static int sdebug_ato = DEF_ATO; |
---|
628 | 733 | static int sdebug_cdb_len = DEF_CDB_LEN; |
---|
629 | 734 | static int sdebug_jdelay = DEF_JDELAY; /* if > 0 then unit is jiffies */ |
---|
630 | | -static int sdebug_dev_size_mb = DEF_DEV_SIZE_MB; |
---|
| 735 | +static int sdebug_dev_size_mb = DEF_DEV_SIZE_PRE_INIT; |
---|
631 | 736 | static int sdebug_dif = DEF_DIF; |
---|
632 | 737 | static int sdebug_dix = DEF_DIX; |
---|
633 | 738 | static int sdebug_dsense = DEF_D_SENSE; |
---|
634 | 739 | static int sdebug_every_nth = DEF_EVERY_NTH; |
---|
635 | 740 | static int sdebug_fake_rw = DEF_FAKE_RW; |
---|
636 | 741 | static unsigned int sdebug_guard = DEF_GUARD; |
---|
| 742 | +static int sdebug_host_max_queue; /* per host */ |
---|
637 | 743 | static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED; |
---|
638 | 744 | static int sdebug_max_luns = DEF_MAX_LUNS; |
---|
639 | 745 | static int sdebug_max_queue = SDEBUG_CANQUEUE; /* per submit queue */ |
---|
.. | .. |
---|
652 | 758 | static int sdebug_ptype = DEF_PTYPE; /* SCSI peripheral device type */ |
---|
653 | 759 | static int sdebug_scsi_level = DEF_SCSI_LEVEL; |
---|
654 | 760 | static int sdebug_sector_size = DEF_SECTOR_SIZE; |
---|
| 761 | +static int sdeb_tur_ms_to_ready = DEF_TUR_MS_TO_READY; |
---|
655 | 762 | static int sdebug_virtual_gb = DEF_VIRTUAL_GB; |
---|
656 | 763 | static int sdebug_vpd_use_hostno = DEF_VPD_USE_HOSTNO; |
---|
657 | 764 | static unsigned int sdebug_lbpu = DEF_LBPU; |
---|
.. | .. |
---|
664 | 771 | static unsigned int sdebug_unmap_max_desc = DEF_UNMAP_MAX_DESC; |
---|
665 | 772 | static unsigned int sdebug_write_same_length = DEF_WRITESAME_LENGTH; |
---|
666 | 773 | static int sdebug_uuid_ctl = DEF_UUID_CTL; |
---|
| 774 | +static bool sdebug_random = DEF_RANDOM; |
---|
| 775 | +static bool sdebug_per_host_store = DEF_PER_HOST_STORE; |
---|
667 | 776 | static bool sdebug_removable = DEF_REMOVABLE; |
---|
668 | 777 | static bool sdebug_clustering; |
---|
669 | 778 | static bool sdebug_host_lock = DEF_HOST_LOCK; |
---|
.. | .. |
---|
673 | 782 | static bool have_dif_prot; |
---|
674 | 783 | static bool write_since_sync; |
---|
675 | 784 | static bool sdebug_statistics = DEF_STATISTICS; |
---|
| 785 | +static bool sdebug_wp; |
---|
| 786 | +/* Following enum: 0: no zbc, def; 1: host aware; 2: host managed */ |
---|
| 787 | +static enum blk_zoned_model sdeb_zbc_model = BLK_ZONED_NONE; |
---|
| 788 | +static char *sdeb_zbc_model_s; |
---|
| 789 | + |
---|
| 790 | +enum sam_lun_addr_method {SAM_LUN_AM_PERIPHERAL = 0x0, |
---|
| 791 | + SAM_LUN_AM_FLAT = 0x1, |
---|
| 792 | + SAM_LUN_AM_LOGICAL_UNIT = 0x2, |
---|
| 793 | + SAM_LUN_AM_EXTENDED = 0x3}; |
---|
| 794 | +static enum sam_lun_addr_method sdebug_lun_am = SAM_LUN_AM_PERIPHERAL; |
---|
| 795 | +static int sdebug_lun_am_i = (int)SAM_LUN_AM_PERIPHERAL; |
---|
676 | 796 | |
---|
677 | 797 | static unsigned int sdebug_store_sectors; |
---|
678 | 798 | static sector_t sdebug_capacity; /* in sectors */ |
---|
.. | .. |
---|
686 | 806 | static LIST_HEAD(sdebug_host_list); |
---|
687 | 807 | static DEFINE_SPINLOCK(sdebug_host_list_lock); |
---|
688 | 808 | |
---|
689 | | -static unsigned char *fake_storep; /* ramdisk storage */ |
---|
690 | | -static struct t10_pi_tuple *dif_storep; /* protection info */ |
---|
691 | | -static void *map_storep; /* provisioning map */ |
---|
| 809 | +static struct xarray per_store_arr; |
---|
| 810 | +static struct xarray *per_store_ap = &per_store_arr; |
---|
| 811 | +static int sdeb_first_idx = -1; /* invalid index ==> none created */ |
---|
| 812 | +static int sdeb_most_recent_idx = -1; |
---|
| 813 | +static DEFINE_RWLOCK(sdeb_fake_rw_lck); /* need a RW lock when fake_rw=1 */ |
---|
692 | 814 | |
---|
693 | 815 | static unsigned long map_size; |
---|
694 | 816 | static int num_aborts; |
---|
.. | .. |
---|
700 | 822 | static int dix_reads; |
---|
701 | 823 | static int dif_errors; |
---|
702 | 824 | |
---|
| 825 | +/* ZBC global data */ |
---|
| 826 | +static bool sdeb_zbc_in_use; /* true for host-aware and host-managed disks */ |
---|
| 827 | +static int sdeb_zbc_zone_size_mb; |
---|
| 828 | +static int sdeb_zbc_max_open = DEF_ZBC_MAX_OPEN_ZONES; |
---|
| 829 | +static int sdeb_zbc_nr_conv = DEF_ZBC_NR_CONV_ZONES; |
---|
| 830 | + |
---|
703 | 831 | static int submit_queues = DEF_SUBMIT_QUEUES; /* > 1 for multi-queue (mq) */ |
---|
704 | 832 | static struct sdebug_queue *sdebug_q_arr; /* ptr to array of submit queues */ |
---|
705 | 833 | |
---|
706 | 834 | static DEFINE_RWLOCK(atomic_rw); |
---|
| 835 | +static DEFINE_RWLOCK(atomic_rw2); |
---|
| 836 | + |
---|
| 837 | +static rwlock_t *ramdisk_lck_a[2]; |
---|
707 | 838 | |
---|
708 | 839 | static char sdebug_proc_name[] = MY_NAME; |
---|
709 | 840 | static const char *my_name = MY_NAME; |
---|
.. | .. |
---|
724 | 855 | static const int device_qfull_result = |
---|
725 | 856 | (DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL; |
---|
726 | 857 | |
---|
| 858 | +static const int condition_met_result = SAM_STAT_CONDITION_MET; |
---|
| 859 | + |
---|
727 | 860 | |
---|
728 | 861 | /* Only do the extra work involved in logical block provisioning if one or |
---|
729 | 862 | * more of the lbpu, lbpws or lbpws10 parameters are given and we are doing |
---|
.. | .. |
---|
735 | 868 | (sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10); |
---|
736 | 869 | } |
---|
737 | 870 | |
---|
738 | | -static void *lba2fake_store(unsigned long long lba) |
---|
| 871 | +static void *lba2fake_store(struct sdeb_store_info *sip, |
---|
| 872 | + unsigned long long lba) |
---|
739 | 873 | { |
---|
740 | | - lba = do_div(lba, sdebug_store_sectors); |
---|
| 874 | + struct sdeb_store_info *lsip = sip; |
---|
741 | 875 | |
---|
742 | | - return fake_storep + lba * sdebug_sector_size; |
---|
| 876 | + lba = do_div(lba, sdebug_store_sectors); |
---|
| 877 | + if (!sip || !sip->storep) { |
---|
| 878 | + WARN_ON_ONCE(true); |
---|
| 879 | + lsip = xa_load(per_store_ap, 0); /* should never be NULL */ |
---|
| 880 | + } |
---|
| 881 | + return lsip->storep + lba * sdebug_sector_size; |
---|
743 | 882 | } |
---|
744 | 883 | |
---|
745 | | -static struct t10_pi_tuple *dif_store(sector_t sector) |
---|
| 884 | +static struct t10_pi_tuple *dif_store(struct sdeb_store_info *sip, |
---|
| 885 | + sector_t sector) |
---|
746 | 886 | { |
---|
747 | 887 | sector = sector_div(sector, sdebug_store_sectors); |
---|
748 | 888 | |
---|
749 | | - return dif_storep + sector; |
---|
| 889 | + return sip->dif_storep + sector; |
---|
750 | 890 | } |
---|
751 | 891 | |
---|
752 | 892 | static void sdebug_max_tgts_luns(void) |
---|
.. | .. |
---|
836 | 976 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_OPCODE, 0); |
---|
837 | 977 | } |
---|
838 | 978 | |
---|
839 | | -static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg) |
---|
| 979 | +static int scsi_debug_ioctl(struct scsi_device *dev, unsigned int cmd, |
---|
| 980 | + void __user *arg) |
---|
840 | 981 | { |
---|
841 | 982 | if (sdebug_verbose) { |
---|
842 | 983 | if (0x1261 == cmd) |
---|
.. | .. |
---|
1010 | 1151 | int arr_len) |
---|
1011 | 1152 | { |
---|
1012 | 1153 | int act_len; |
---|
1013 | | - struct scsi_data_buffer *sdb = scsi_in(scp); |
---|
| 1154 | + struct scsi_data_buffer *sdb = &scp->sdb; |
---|
1014 | 1155 | |
---|
1015 | 1156 | if (!sdb->length) |
---|
1016 | 1157 | return 0; |
---|
1017 | | - if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE)) |
---|
| 1158 | + if (scp->sc_data_direction != DMA_FROM_DEVICE) |
---|
1018 | 1159 | return DID_ERROR << 16; |
---|
1019 | 1160 | |
---|
1020 | 1161 | act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents, |
---|
1021 | 1162 | arr, arr_len); |
---|
1022 | | - sdb->resid = scsi_bufflen(scp) - act_len; |
---|
| 1163 | + scsi_set_resid(scp, scsi_bufflen(scp) - act_len); |
---|
1023 | 1164 | |
---|
1024 | 1165 | return 0; |
---|
1025 | 1166 | } |
---|
.. | .. |
---|
1032 | 1173 | static int p_fill_from_dev_buffer(struct scsi_cmnd *scp, const void *arr, |
---|
1033 | 1174 | int arr_len, unsigned int off_dst) |
---|
1034 | 1175 | { |
---|
1035 | | - int act_len, n; |
---|
1036 | | - struct scsi_data_buffer *sdb = scsi_in(scp); |
---|
| 1176 | + unsigned int act_len, n; |
---|
| 1177 | + struct scsi_data_buffer *sdb = &scp->sdb; |
---|
1037 | 1178 | off_t skip = off_dst; |
---|
1038 | 1179 | |
---|
1039 | 1180 | if (sdb->length <= off_dst) |
---|
1040 | 1181 | return 0; |
---|
1041 | | - if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE)) |
---|
| 1182 | + if (scp->sc_data_direction != DMA_FROM_DEVICE) |
---|
1042 | 1183 | return DID_ERROR << 16; |
---|
1043 | 1184 | |
---|
1044 | 1185 | act_len = sg_pcopy_from_buffer(sdb->table.sgl, sdb->table.nents, |
---|
1045 | 1186 | arr, arr_len, skip); |
---|
1046 | 1187 | pr_debug("%s: off_dst=%u, scsi_bufflen=%u, act_len=%u, resid=%d\n", |
---|
1047 | | - __func__, off_dst, scsi_bufflen(scp), act_len, sdb->resid); |
---|
1048 | | - n = (int)scsi_bufflen(scp) - ((int)off_dst + act_len); |
---|
1049 | | - sdb->resid = min(sdb->resid, n); |
---|
| 1188 | + __func__, off_dst, scsi_bufflen(scp), act_len, |
---|
| 1189 | + scsi_get_resid(scp)); |
---|
| 1190 | + n = scsi_bufflen(scp) - (off_dst + act_len); |
---|
| 1191 | + scsi_set_resid(scp, min_t(u32, scsi_get_resid(scp), n)); |
---|
1050 | 1192 | return 0; |
---|
1051 | 1193 | } |
---|
1052 | 1194 | |
---|
.. | .. |
---|
1058 | 1200 | { |
---|
1059 | 1201 | if (!scsi_bufflen(scp)) |
---|
1060 | 1202 | return 0; |
---|
1061 | | - if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE)) |
---|
| 1203 | + if (scp->sc_data_direction != DMA_TO_DEVICE) |
---|
1062 | 1204 | return -1; |
---|
1063 | 1205 | |
---|
1064 | 1206 | return scsi_sg_copy_to_buffer(scp, arr, arr_len); |
---|
.. | .. |
---|
1359 | 1501 | } |
---|
1360 | 1502 | |
---|
1361 | 1503 | /* Block device characteristics VPD page (SBC-3) */ |
---|
1362 | | -static int inquiry_vpd_b1(unsigned char *arr) |
---|
| 1504 | +static int inquiry_vpd_b1(struct sdebug_dev_info *devip, unsigned char *arr) |
---|
1363 | 1505 | { |
---|
1364 | 1506 | memset(arr, 0, 0x3c); |
---|
1365 | 1507 | arr[0] = 0; |
---|
1366 | 1508 | arr[1] = 1; /* non rotating medium (e.g. solid state) */ |
---|
1367 | 1509 | arr[2] = 0; |
---|
1368 | 1510 | arr[3] = 5; /* less than 1.8" */ |
---|
| 1511 | + if (devip->zmodel == BLK_ZONED_HA) |
---|
| 1512 | + arr[4] = 1 << 4; /* zoned field = 01b */ |
---|
1369 | 1513 | |
---|
1370 | 1514 | return 0x3c; |
---|
1371 | 1515 | } |
---|
.. | .. |
---|
1389 | 1533 | return 0x4; |
---|
1390 | 1534 | } |
---|
1391 | 1535 | |
---|
| 1536 | +/* Zoned block device characteristics VPD page (ZBC mandatory) */ |
---|
| 1537 | +static int inquiry_vpd_b6(struct sdebug_dev_info *devip, unsigned char *arr) |
---|
| 1538 | +{ |
---|
| 1539 | + memset(arr, 0, 0x3c); |
---|
| 1540 | + arr[0] = 0x1; /* set URSWRZ (unrestricted read in seq. wr req zone) */ |
---|
| 1541 | + /* |
---|
| 1542 | + * Set Optimal number of open sequential write preferred zones and |
---|
| 1543 | + * Optimal number of non-sequentially written sequential write |
---|
| 1544 | + * preferred zones fields to 'not reported' (0xffffffff). Leave other |
---|
| 1545 | + * fields set to zero, apart from Max. number of open swrz_s field. |
---|
| 1546 | + */ |
---|
| 1547 | + put_unaligned_be32(0xffffffff, &arr[4]); |
---|
| 1548 | + put_unaligned_be32(0xffffffff, &arr[8]); |
---|
| 1549 | + if (sdeb_zbc_model == BLK_ZONED_HM && devip->max_open) |
---|
| 1550 | + put_unaligned_be32(devip->max_open, &arr[12]); |
---|
| 1551 | + else |
---|
| 1552 | + put_unaligned_be32(0xffffffff, &arr[12]); |
---|
| 1553 | + return 0x3c; |
---|
| 1554 | +} |
---|
| 1555 | + |
---|
1392 | 1556 | #define SDEBUG_LONG_INQ_SZ 96 |
---|
1393 | 1557 | #define SDEBUG_MAX_INQ_ARR_SZ 584 |
---|
1394 | 1558 | |
---|
.. | .. |
---|
1397 | 1561 | unsigned char pq_pdt; |
---|
1398 | 1562 | unsigned char *arr; |
---|
1399 | 1563 | unsigned char *cmd = scp->cmnd; |
---|
1400 | | - int alloc_len, n, ret; |
---|
1401 | | - bool have_wlun, is_disk; |
---|
| 1564 | + u32 alloc_len, n; |
---|
| 1565 | + int ret; |
---|
| 1566 | + bool have_wlun, is_disk, is_zbc, is_disk_zbc; |
---|
1402 | 1567 | |
---|
1403 | 1568 | alloc_len = get_unaligned_be16(cmd + 3); |
---|
1404 | 1569 | arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC); |
---|
1405 | 1570 | if (! arr) |
---|
1406 | 1571 | return DID_REQUEUE << 16; |
---|
1407 | 1572 | is_disk = (sdebug_ptype == TYPE_DISK); |
---|
| 1573 | + is_zbc = (devip->zmodel != BLK_ZONED_NONE); |
---|
| 1574 | + is_disk_zbc = (is_disk || is_zbc); |
---|
1408 | 1575 | have_wlun = scsi_is_wlun(scp->device->lun); |
---|
1409 | 1576 | if (have_wlun) |
---|
1410 | 1577 | pq_pdt = TYPE_WLUN; /* present, wlun */ |
---|
.. | .. |
---|
1418 | 1585 | kfree(arr); |
---|
1419 | 1586 | return check_condition_result; |
---|
1420 | 1587 | } else if (0x1 & cmd[1]) { /* EVPD bit set */ |
---|
1421 | | - int lu_id_num, port_group_id, target_dev_id, len; |
---|
| 1588 | + int lu_id_num, port_group_id, target_dev_id; |
---|
| 1589 | + u32 len; |
---|
1422 | 1590 | char lu_id_str[6]; |
---|
1423 | 1591 | int host_no = devip->sdbg_host->shost->host_no; |
---|
1424 | 1592 | |
---|
.. | .. |
---|
1442 | 1610 | arr[n++] = 0x86; /* extended inquiry */ |
---|
1443 | 1611 | arr[n++] = 0x87; /* mode page policy */ |
---|
1444 | 1612 | arr[n++] = 0x88; /* SCSI ports */ |
---|
1445 | | - if (is_disk) { /* SBC only */ |
---|
| 1613 | + if (is_disk_zbc) { /* SBC or ZBC */ |
---|
1446 | 1614 | arr[n++] = 0x89; /* ATA information */ |
---|
1447 | 1615 | arr[n++] = 0xb0; /* Block limits */ |
---|
1448 | 1616 | arr[n++] = 0xb1; /* Block characteristics */ |
---|
1449 | | - arr[n++] = 0xb2; /* Logical Block Prov */ |
---|
| 1617 | + if (is_disk) |
---|
| 1618 | + arr[n++] = 0xb2; /* LB Provisioning */ |
---|
| 1619 | + if (is_zbc) |
---|
| 1620 | + arr[n++] = 0xb6; /* ZB dev. char. */ |
---|
1450 | 1621 | } |
---|
1451 | 1622 | arr[3] = n - 4; /* number of supported VPD pages */ |
---|
1452 | 1623 | } else if (0x80 == cmd[2]) { /* unit serial number */ |
---|
.. | .. |
---|
1485 | 1656 | } else if (0x88 == cmd[2]) { /* SCSI Ports */ |
---|
1486 | 1657 | arr[1] = cmd[2]; /*sanity */ |
---|
1487 | 1658 | arr[3] = inquiry_vpd_88(&arr[4], target_dev_id); |
---|
1488 | | - } else if (is_disk && 0x89 == cmd[2]) { /* ATA information */ |
---|
| 1659 | + } else if (is_disk_zbc && 0x89 == cmd[2]) { /* ATA info */ |
---|
1489 | 1660 | arr[1] = cmd[2]; /*sanity */ |
---|
1490 | 1661 | n = inquiry_vpd_89(&arr[4]); |
---|
1491 | 1662 | put_unaligned_be16(n, arr + 2); |
---|
1492 | | - } else if (is_disk && 0xb0 == cmd[2]) { /* Block limits */ |
---|
| 1663 | + } else if (is_disk_zbc && 0xb0 == cmd[2]) { /* Block limits */ |
---|
1493 | 1664 | arr[1] = cmd[2]; /*sanity */ |
---|
1494 | 1665 | arr[3] = inquiry_vpd_b0(&arr[4]); |
---|
1495 | | - } else if (is_disk && 0xb1 == cmd[2]) { /* Block char. */ |
---|
| 1666 | + } else if (is_disk_zbc && 0xb1 == cmd[2]) { /* Block char. */ |
---|
1496 | 1667 | arr[1] = cmd[2]; /*sanity */ |
---|
1497 | | - arr[3] = inquiry_vpd_b1(&arr[4]); |
---|
| 1668 | + arr[3] = inquiry_vpd_b1(devip, &arr[4]); |
---|
1498 | 1669 | } else if (is_disk && 0xb2 == cmd[2]) { /* LB Prov. */ |
---|
1499 | 1670 | arr[1] = cmd[2]; /*sanity */ |
---|
1500 | 1671 | arr[3] = inquiry_vpd_b2(&arr[4]); |
---|
| 1672 | + } else if (is_zbc && cmd[2] == 0xb6) { /* ZB dev. charact. */ |
---|
| 1673 | + arr[1] = cmd[2]; /*sanity */ |
---|
| 1674 | + arr[3] = inquiry_vpd_b6(devip, &arr[4]); |
---|
1501 | 1675 | } else { |
---|
1502 | 1676 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1); |
---|
1503 | 1677 | kfree(arr); |
---|
1504 | 1678 | return check_condition_result; |
---|
1505 | 1679 | } |
---|
1506 | | - len = min(get_unaligned_be16(arr + 2) + 4, alloc_len); |
---|
| 1680 | + len = min_t(u32, get_unaligned_be16(arr + 2) + 4, alloc_len); |
---|
1507 | 1681 | ret = fill_from_dev_buffer(scp, arr, |
---|
1508 | | - min(len, SDEBUG_MAX_INQ_ARR_SZ)); |
---|
| 1682 | + min_t(u32, len, SDEBUG_MAX_INQ_ARR_SZ)); |
---|
1509 | 1683 | kfree(arr); |
---|
1510 | 1684 | return ret; |
---|
1511 | 1685 | } |
---|
.. | .. |
---|
1535 | 1709 | } else if (sdebug_ptype == TYPE_TAPE) { /* SSC-4 rev 3 */ |
---|
1536 | 1710 | put_unaligned_be16(0x525, arr + n); |
---|
1537 | 1711 | n += 2; |
---|
| 1712 | + } else if (is_zbc) { /* ZBC BSR INCITS 536 revision 05 */ |
---|
| 1713 | + put_unaligned_be16(0x624, arr + n); |
---|
| 1714 | + n += 2; |
---|
1538 | 1715 | } |
---|
1539 | 1716 | put_unaligned_be16(0x2100, arr + n); /* SPL-4 no version claimed */ |
---|
1540 | 1717 | ret = fill_from_dev_buffer(scp, arr, |
---|
1541 | | - min(alloc_len, SDEBUG_LONG_INQ_SZ)); |
---|
| 1718 | + min_t(u32, alloc_len, SDEBUG_LONG_INQ_SZ)); |
---|
1542 | 1719 | kfree(arr); |
---|
1543 | 1720 | return ret; |
---|
1544 | 1721 | } |
---|
1545 | 1722 | |
---|
| 1723 | +/* See resp_iec_m_pg() for how this data is manipulated */ |
---|
1546 | 1724 | static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, |
---|
1547 | 1725 | 0, 0, 0x0, 0x0}; |
---|
1548 | 1726 | |
---|
1549 | 1727 | static int resp_requests(struct scsi_cmnd *scp, |
---|
1550 | 1728 | struct sdebug_dev_info *devip) |
---|
1551 | 1729 | { |
---|
1552 | | - unsigned char *sbuff; |
---|
1553 | 1730 | unsigned char *cmd = scp->cmnd; |
---|
1554 | | - unsigned char arr[SCSI_SENSE_BUFFERSIZE]; |
---|
1555 | | - bool dsense; |
---|
1556 | | - int len = 18; |
---|
| 1731 | + unsigned char arr[SCSI_SENSE_BUFFERSIZE]; /* assume >= 18 bytes */ |
---|
| 1732 | + bool dsense = !!(cmd[1] & 1); |
---|
| 1733 | + u32 alloc_len = cmd[4]; |
---|
| 1734 | + u32 len = 18; |
---|
| 1735 | + int stopped_state = atomic_read(&devip->stopped); |
---|
1557 | 1736 | |
---|
1558 | 1737 | memset(arr, 0, sizeof(arr)); |
---|
1559 | | - dsense = !!(cmd[1] & 1); |
---|
1560 | | - sbuff = scp->sense_buffer; |
---|
1561 | | - if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) { |
---|
| 1738 | + if (stopped_state > 0) { /* some "pollable" data [spc6r02: 5.12.2] */ |
---|
| 1739 | + if (dsense) { |
---|
| 1740 | + arr[0] = 0x72; |
---|
| 1741 | + arr[1] = NOT_READY; |
---|
| 1742 | + arr[2] = LOGICAL_UNIT_NOT_READY; |
---|
| 1743 | + arr[3] = (stopped_state == 2) ? 0x1 : 0x2; |
---|
| 1744 | + len = 8; |
---|
| 1745 | + } else { |
---|
| 1746 | + arr[0] = 0x70; |
---|
| 1747 | + arr[2] = NOT_READY; /* NO_SENSE in sense_key */ |
---|
| 1748 | + arr[7] = 0xa; /* 18 byte sense buffer */ |
---|
| 1749 | + arr[12] = LOGICAL_UNIT_NOT_READY; |
---|
| 1750 | + arr[13] = (stopped_state == 2) ? 0x1 : 0x2; |
---|
| 1751 | + } |
---|
| 1752 | + } else if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) { |
---|
| 1753 | + /* Information exceptions control mode page: TEST=1, MRIE=6 */ |
---|
1562 | 1754 | if (dsense) { |
---|
1563 | 1755 | arr[0] = 0x72; |
---|
1564 | 1756 | arr[1] = 0x0; /* NO_SENSE in sense_key */ |
---|
1565 | 1757 | arr[2] = THRESHOLD_EXCEEDED; |
---|
1566 | | - arr[3] = 0xff; /* TEST set and MRIE==6 */ |
---|
| 1758 | + arr[3] = 0xff; /* Failure prediction(false) */ |
---|
1567 | 1759 | len = 8; |
---|
1568 | 1760 | } else { |
---|
1569 | 1761 | arr[0] = 0x70; |
---|
1570 | 1762 | arr[2] = 0x0; /* NO_SENSE in sense_key */ |
---|
1571 | 1763 | arr[7] = 0xa; /* 18 byte sense buffer */ |
---|
1572 | 1764 | arr[12] = THRESHOLD_EXCEEDED; |
---|
1573 | | - arr[13] = 0xff; /* TEST set and MRIE==6 */ |
---|
| 1765 | + arr[13] = 0xff; /* Failure prediction(false) */ |
---|
1574 | 1766 | } |
---|
1575 | | - } else { |
---|
1576 | | - memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE); |
---|
1577 | | - if (arr[0] >= 0x70 && dsense == sdebug_dsense) |
---|
1578 | | - ; /* have sense and formats match */ |
---|
1579 | | - else if (arr[0] <= 0x70) { |
---|
1580 | | - if (dsense) { |
---|
1581 | | - memset(arr, 0, 8); |
---|
1582 | | - arr[0] = 0x72; |
---|
1583 | | - len = 8; |
---|
1584 | | - } else { |
---|
1585 | | - memset(arr, 0, 18); |
---|
1586 | | - arr[0] = 0x70; |
---|
1587 | | - arr[7] = 0xa; |
---|
1588 | | - } |
---|
1589 | | - } else if (dsense) { |
---|
1590 | | - memset(arr, 0, 8); |
---|
1591 | | - arr[0] = 0x72; |
---|
1592 | | - arr[1] = sbuff[2]; /* sense key */ |
---|
1593 | | - arr[2] = sbuff[12]; /* asc */ |
---|
1594 | | - arr[3] = sbuff[13]; /* ascq */ |
---|
| 1767 | + } else { /* nothing to report */ |
---|
| 1768 | + if (dsense) { |
---|
1595 | 1769 | len = 8; |
---|
| 1770 | + memset(arr, 0, len); |
---|
| 1771 | + arr[0] = 0x72; |
---|
1596 | 1772 | } else { |
---|
1597 | | - memset(arr, 0, 18); |
---|
| 1773 | + memset(arr, 0, len); |
---|
1598 | 1774 | arr[0] = 0x70; |
---|
1599 | | - arr[2] = sbuff[1]; |
---|
1600 | 1775 | arr[7] = 0xa; |
---|
1601 | | - arr[12] = sbuff[1]; |
---|
1602 | | - arr[13] = sbuff[3]; |
---|
1603 | 1776 | } |
---|
1604 | | - |
---|
1605 | 1777 | } |
---|
1606 | | - mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0); |
---|
1607 | | - return fill_from_dev_buffer(scp, arr, len); |
---|
| 1778 | + return fill_from_dev_buffer(scp, arr, min_t(u32, len, alloc_len)); |
---|
1608 | 1779 | } |
---|
1609 | 1780 | |
---|
1610 | | -static int resp_start_stop(struct scsi_cmnd *scp, |
---|
1611 | | - struct sdebug_dev_info *devip) |
---|
| 1781 | +static int resp_start_stop(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) |
---|
1612 | 1782 | { |
---|
1613 | 1783 | unsigned char *cmd = scp->cmnd; |
---|
1614 | | - int power_cond, stop; |
---|
| 1784 | + int power_cond, want_stop, stopped_state; |
---|
1615 | 1785 | bool changing; |
---|
1616 | 1786 | |
---|
1617 | 1787 | power_cond = (cmd[4] & 0xf0) >> 4; |
---|
.. | .. |
---|
1619 | 1789 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 7); |
---|
1620 | 1790 | return check_condition_result; |
---|
1621 | 1791 | } |
---|
1622 | | - stop = !(cmd[4] & 1); |
---|
1623 | | - changing = atomic_read(&devip->stopped) == !stop; |
---|
1624 | | - atomic_xchg(&devip->stopped, stop); |
---|
1625 | | - if (!changing || cmd[1] & 0x1) /* state unchanged or IMMED set */ |
---|
| 1792 | + want_stop = !(cmd[4] & 1); |
---|
| 1793 | + stopped_state = atomic_read(&devip->stopped); |
---|
| 1794 | + if (stopped_state == 2) { |
---|
| 1795 | + ktime_t now_ts = ktime_get_boottime(); |
---|
| 1796 | + |
---|
| 1797 | + if (ktime_to_ns(now_ts) > ktime_to_ns(devip->create_ts)) { |
---|
| 1798 | + u64 diff_ns = ktime_to_ns(ktime_sub(now_ts, devip->create_ts)); |
---|
| 1799 | + |
---|
| 1800 | + if (diff_ns >= ((u64)sdeb_tur_ms_to_ready * 1000000)) { |
---|
| 1801 | + /* tur_ms_to_ready timer extinguished */ |
---|
| 1802 | + atomic_set(&devip->stopped, 0); |
---|
| 1803 | + stopped_state = 0; |
---|
| 1804 | + } |
---|
| 1805 | + } |
---|
| 1806 | + if (stopped_state == 2) { |
---|
| 1807 | + if (want_stop) { |
---|
| 1808 | + stopped_state = 1; /* dummy up success */ |
---|
| 1809 | + } else { /* Disallow tur_ms_to_ready delay to be overridden */ |
---|
| 1810 | + mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 0 /* START bit */); |
---|
| 1811 | + return check_condition_result; |
---|
| 1812 | + } |
---|
| 1813 | + } |
---|
| 1814 | + } |
---|
| 1815 | + changing = (stopped_state != want_stop); |
---|
| 1816 | + if (changing) |
---|
| 1817 | + atomic_xchg(&devip->stopped, want_stop); |
---|
| 1818 | + if (!changing || (cmd[1] & 0x1)) /* state unchanged or IMMED bit set in cdb */ |
---|
1626 | 1819 | return SDEG_RES_IMMED_MASK; |
---|
1627 | 1820 | else |
---|
1628 | 1821 | return 0; |
---|
.. | .. |
---|
1664 | 1857 | { |
---|
1665 | 1858 | unsigned char *cmd = scp->cmnd; |
---|
1666 | 1859 | unsigned char arr[SDEBUG_READCAP16_ARR_SZ]; |
---|
1667 | | - int alloc_len; |
---|
| 1860 | + u32 alloc_len; |
---|
1668 | 1861 | |
---|
1669 | 1862 | alloc_len = get_unaligned_be32(cmd + 10); |
---|
1670 | 1863 | /* following just in case virtual_gb changed */ |
---|
.. | .. |
---|
1685 | 1878 | arr[14] |= 0x40; |
---|
1686 | 1879 | } |
---|
1687 | 1880 | |
---|
| 1881 | + /* |
---|
| 1882 | + * Since the scsi_debug READ CAPACITY implementation always reports the |
---|
| 1883 | + * total disk capacity, set RC BASIS = 1 for host-managed ZBC devices. |
---|
| 1884 | + */ |
---|
| 1885 | + if (devip->zmodel == BLK_ZONED_HM) |
---|
| 1886 | + arr[12] |= 1 << 4; |
---|
| 1887 | + |
---|
1688 | 1888 | arr[15] = sdebug_lowest_aligned & 0xff; |
---|
1689 | 1889 | |
---|
1690 | 1890 | if (have_dif_prot) { |
---|
.. | .. |
---|
1693 | 1893 | } |
---|
1694 | 1894 | |
---|
1695 | 1895 | return fill_from_dev_buffer(scp, arr, |
---|
1696 | | - min(alloc_len, SDEBUG_READCAP16_ARR_SZ)); |
---|
| 1896 | + min_t(u32, alloc_len, SDEBUG_READCAP16_ARR_SZ)); |
---|
1697 | 1897 | } |
---|
1698 | 1898 | |
---|
1699 | 1899 | #define SDEBUG_MAX_TGTPGS_ARR_SZ 1412 |
---|
.. | .. |
---|
1704 | 1904 | unsigned char *cmd = scp->cmnd; |
---|
1705 | 1905 | unsigned char *arr; |
---|
1706 | 1906 | int host_no = devip->sdbg_host->shost->host_no; |
---|
1707 | | - int n, ret, alen, rlen; |
---|
1708 | 1907 | int port_group_a, port_group_b, port_a, port_b; |
---|
| 1908 | + u32 alen, n, rlen; |
---|
| 1909 | + int ret; |
---|
1709 | 1910 | |
---|
1710 | 1911 | alen = get_unaligned_be32(cmd + 6); |
---|
1711 | 1912 | arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC); |
---|
.. | .. |
---|
1767 | 1968 | * - The constructed command length |
---|
1768 | 1969 | * - The maximum array size |
---|
1769 | 1970 | */ |
---|
1770 | | - rlen = min(alen,n); |
---|
| 1971 | + rlen = min(alen, n); |
---|
1771 | 1972 | ret = fill_from_dev_buffer(scp, arr, |
---|
1772 | | - min(rlen, SDEBUG_MAX_TGTPGS_ARR_SZ)); |
---|
| 1973 | + min_t(u32, rlen, SDEBUG_MAX_TGTPGS_ARR_SZ)); |
---|
1773 | 1974 | kfree(arr); |
---|
1774 | 1975 | return ret; |
---|
1775 | 1976 | } |
---|
.. | .. |
---|
2119 | 2320 | { |
---|
2120 | 2321 | int pcontrol, pcode, subpcode, bd_len; |
---|
2121 | 2322 | unsigned char dev_spec; |
---|
2122 | | - int alloc_len, offset, len, target_dev_id; |
---|
| 2323 | + u32 alloc_len, offset, len; |
---|
| 2324 | + int target_dev_id; |
---|
2123 | 2325 | int target = scp->device->id; |
---|
2124 | 2326 | unsigned char *ap; |
---|
2125 | 2327 | unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; |
---|
2126 | 2328 | unsigned char *cmd = scp->cmnd; |
---|
2127 | | - bool dbd, llbaa, msense_6, is_disk, bad_pcode; |
---|
| 2329 | + bool dbd, llbaa, msense_6, is_disk, is_zbc, bad_pcode; |
---|
2128 | 2330 | |
---|
2129 | 2331 | dbd = !!(cmd[1] & 0x8); /* disable block descriptors */ |
---|
2130 | 2332 | pcontrol = (cmd[2] & 0xc0) >> 6; |
---|
.. | .. |
---|
2133 | 2335 | msense_6 = (MODE_SENSE == cmd[0]); |
---|
2134 | 2336 | llbaa = msense_6 ? false : !!(cmd[1] & 0x10); |
---|
2135 | 2337 | is_disk = (sdebug_ptype == TYPE_DISK); |
---|
2136 | | - if (is_disk && !dbd) |
---|
| 2338 | + is_zbc = (devip->zmodel != BLK_ZONED_NONE); |
---|
| 2339 | + if ((is_disk || is_zbc) && !dbd) |
---|
2137 | 2340 | bd_len = llbaa ? 16 : 8; |
---|
2138 | 2341 | else |
---|
2139 | 2342 | bd_len = 0; |
---|
.. | .. |
---|
2145 | 2348 | } |
---|
2146 | 2349 | target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) + |
---|
2147 | 2350 | (devip->target * 1000) - 3; |
---|
2148 | | - /* for disks set DPOFUA bit and clear write protect (WP) bit */ |
---|
2149 | | - if (is_disk) |
---|
| 2351 | + /* for disks+zbc set DPOFUA bit and clear write protect (WP) bit */ |
---|
| 2352 | + if (is_disk || is_zbc) { |
---|
2150 | 2353 | dev_spec = 0x10; /* =0x90 if WP=1 implies read-only */ |
---|
2151 | | - else |
---|
| 2354 | + if (sdebug_wp) |
---|
| 2355 | + dev_spec |= 0x80; |
---|
| 2356 | + } else |
---|
2152 | 2357 | dev_spec = 0x0; |
---|
2153 | 2358 | if (msense_6) { |
---|
2154 | 2359 | arr[2] = dev_spec; |
---|
.. | .. |
---|
2204 | 2409 | bad_pcode = true; |
---|
2205 | 2410 | break; |
---|
2206 | 2411 | case 0x8: /* Caching page, direct access */ |
---|
2207 | | - if (is_disk) { |
---|
| 2412 | + if (is_disk || is_zbc) { |
---|
2208 | 2413 | len = resp_caching_pg(ap, pcontrol, target); |
---|
2209 | 2414 | offset += len; |
---|
2210 | 2415 | } else |
---|
.. | .. |
---|
2242 | 2447 | target); |
---|
2243 | 2448 | len += resp_caching_pg(ap + len, pcontrol, |
---|
2244 | 2449 | target); |
---|
| 2450 | + } else if (is_zbc) { |
---|
| 2451 | + len += resp_caching_pg(ap + len, pcontrol, |
---|
| 2452 | + target); |
---|
2245 | 2453 | } |
---|
2246 | 2454 | len += resp_ctrl_m_pg(ap + len, pcontrol, target); |
---|
2247 | 2455 | len += resp_sas_sf_m_pg(ap + len, pcontrol, target); |
---|
.. | .. |
---|
2269 | 2477 | arr[0] = offset - 1; |
---|
2270 | 2478 | else |
---|
2271 | 2479 | put_unaligned_be16((offset - 2), arr + 0); |
---|
2272 | | - return fill_from_dev_buffer(scp, arr, min(alloc_len, offset)); |
---|
| 2480 | + return fill_from_dev_buffer(scp, arr, min_t(u32, alloc_len, offset)); |
---|
2273 | 2481 | } |
---|
2274 | 2482 | |
---|
2275 | 2483 | #define SDEBUG_MAX_MSELECT_SZ 512 |
---|
.. | .. |
---|
2331 | 2539 | if (ctrl_m_pg[1] == arr[off + 1]) { |
---|
2332 | 2540 | memcpy(ctrl_m_pg + 2, arr + off + 2, |
---|
2333 | 2541 | sizeof(ctrl_m_pg) - 2); |
---|
| 2542 | + if (ctrl_m_pg[4] & 0x8) |
---|
| 2543 | + sdebug_wp = true; |
---|
| 2544 | + else |
---|
| 2545 | + sdebug_wp = false; |
---|
2334 | 2546 | sdebug_dsense = !!(ctrl_m_pg[2] & 0x4); |
---|
2335 | 2547 | goto set_mode_changed_ua; |
---|
2336 | 2548 | } |
---|
.. | .. |
---|
2380 | 2592 | static int resp_log_sense(struct scsi_cmnd *scp, |
---|
2381 | 2593 | struct sdebug_dev_info *devip) |
---|
2382 | 2594 | { |
---|
2383 | | - int ppc, sp, pcode, subpcode, alloc_len, len, n; |
---|
| 2595 | + int ppc, sp, pcode, subpcode; |
---|
| 2596 | + u32 alloc_len, len, n; |
---|
2384 | 2597 | unsigned char arr[SDEBUG_MAX_LSENSE_SZ]; |
---|
2385 | 2598 | unsigned char *cmd = scp->cmnd; |
---|
2386 | 2599 | |
---|
.. | .. |
---|
2450 | 2663 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1); |
---|
2451 | 2664 | return check_condition_result; |
---|
2452 | 2665 | } |
---|
2453 | | - len = min(get_unaligned_be16(arr + 2) + 4, alloc_len); |
---|
| 2666 | + len = min_t(u32, get_unaligned_be16(arr + 2) + 4, alloc_len); |
---|
2454 | 2667 | return fill_from_dev_buffer(scp, arr, |
---|
2455 | | - min(len, SDEBUG_MAX_INQ_ARR_SZ)); |
---|
| 2668 | + min_t(u32, len, SDEBUG_MAX_INQ_ARR_SZ)); |
---|
2456 | 2669 | } |
---|
2457 | 2670 | |
---|
2458 | | -static int check_device_access_params(struct scsi_cmnd *scp, |
---|
2459 | | - unsigned long long lba, unsigned int num) |
---|
| 2671 | +static inline bool sdebug_dev_is_zoned(struct sdebug_dev_info *devip) |
---|
2460 | 2672 | { |
---|
| 2673 | + return devip->nr_zones != 0; |
---|
| 2674 | +} |
---|
| 2675 | + |
---|
| 2676 | +static struct sdeb_zone_state *zbc_zone(struct sdebug_dev_info *devip, |
---|
| 2677 | + unsigned long long lba) |
---|
| 2678 | +{ |
---|
| 2679 | + return &devip->zstate[lba >> devip->zsize_shift]; |
---|
| 2680 | +} |
---|
| 2681 | + |
---|
| 2682 | +static inline bool zbc_zone_is_conv(struct sdeb_zone_state *zsp) |
---|
| 2683 | +{ |
---|
| 2684 | + return zsp->z_type == ZBC_ZONE_TYPE_CNV; |
---|
| 2685 | +} |
---|
| 2686 | + |
---|
| 2687 | +static void zbc_close_zone(struct sdebug_dev_info *devip, |
---|
| 2688 | + struct sdeb_zone_state *zsp) |
---|
| 2689 | +{ |
---|
| 2690 | + enum sdebug_z_cond zc; |
---|
| 2691 | + |
---|
| 2692 | + if (zbc_zone_is_conv(zsp)) |
---|
| 2693 | + return; |
---|
| 2694 | + |
---|
| 2695 | + zc = zsp->z_cond; |
---|
| 2696 | + if (!(zc == ZC2_IMPLICIT_OPEN || zc == ZC3_EXPLICIT_OPEN)) |
---|
| 2697 | + return; |
---|
| 2698 | + |
---|
| 2699 | + if (zc == ZC2_IMPLICIT_OPEN) |
---|
| 2700 | + devip->nr_imp_open--; |
---|
| 2701 | + else |
---|
| 2702 | + devip->nr_exp_open--; |
---|
| 2703 | + |
---|
| 2704 | + if (zsp->z_wp == zsp->z_start) { |
---|
| 2705 | + zsp->z_cond = ZC1_EMPTY; |
---|
| 2706 | + } else { |
---|
| 2707 | + zsp->z_cond = ZC4_CLOSED; |
---|
| 2708 | + devip->nr_closed++; |
---|
| 2709 | + } |
---|
| 2710 | +} |
---|
| 2711 | + |
---|
| 2712 | +static void zbc_close_imp_open_zone(struct sdebug_dev_info *devip) |
---|
| 2713 | +{ |
---|
| 2714 | + struct sdeb_zone_state *zsp = &devip->zstate[0]; |
---|
| 2715 | + unsigned int i; |
---|
| 2716 | + |
---|
| 2717 | + for (i = 0; i < devip->nr_zones; i++, zsp++) { |
---|
| 2718 | + if (zsp->z_cond == ZC2_IMPLICIT_OPEN) { |
---|
| 2719 | + zbc_close_zone(devip, zsp); |
---|
| 2720 | + return; |
---|
| 2721 | + } |
---|
| 2722 | + } |
---|
| 2723 | +} |
---|
| 2724 | + |
---|
| 2725 | +static void zbc_open_zone(struct sdebug_dev_info *devip, |
---|
| 2726 | + struct sdeb_zone_state *zsp, bool explicit) |
---|
| 2727 | +{ |
---|
| 2728 | + enum sdebug_z_cond zc; |
---|
| 2729 | + |
---|
| 2730 | + if (zbc_zone_is_conv(zsp)) |
---|
| 2731 | + return; |
---|
| 2732 | + |
---|
| 2733 | + zc = zsp->z_cond; |
---|
| 2734 | + if ((explicit && zc == ZC3_EXPLICIT_OPEN) || |
---|
| 2735 | + (!explicit && zc == ZC2_IMPLICIT_OPEN)) |
---|
| 2736 | + return; |
---|
| 2737 | + |
---|
| 2738 | + /* Close an implicit open zone if necessary */ |
---|
| 2739 | + if (explicit && zsp->z_cond == ZC2_IMPLICIT_OPEN) |
---|
| 2740 | + zbc_close_zone(devip, zsp); |
---|
| 2741 | + else if (devip->max_open && |
---|
| 2742 | + devip->nr_imp_open + devip->nr_exp_open >= devip->max_open) |
---|
| 2743 | + zbc_close_imp_open_zone(devip); |
---|
| 2744 | + |
---|
| 2745 | + if (zsp->z_cond == ZC4_CLOSED) |
---|
| 2746 | + devip->nr_closed--; |
---|
| 2747 | + if (explicit) { |
---|
| 2748 | + zsp->z_cond = ZC3_EXPLICIT_OPEN; |
---|
| 2749 | + devip->nr_exp_open++; |
---|
| 2750 | + } else { |
---|
| 2751 | + zsp->z_cond = ZC2_IMPLICIT_OPEN; |
---|
| 2752 | + devip->nr_imp_open++; |
---|
| 2753 | + } |
---|
| 2754 | +} |
---|
| 2755 | + |
---|
| 2756 | +static inline void zbc_set_zone_full(struct sdebug_dev_info *devip, |
---|
| 2757 | + struct sdeb_zone_state *zsp) |
---|
| 2758 | +{ |
---|
| 2759 | + switch (zsp->z_cond) { |
---|
| 2760 | + case ZC2_IMPLICIT_OPEN: |
---|
| 2761 | + devip->nr_imp_open--; |
---|
| 2762 | + break; |
---|
| 2763 | + case ZC3_EXPLICIT_OPEN: |
---|
| 2764 | + devip->nr_exp_open--; |
---|
| 2765 | + break; |
---|
| 2766 | + default: |
---|
| 2767 | + WARN_ONCE(true, "Invalid zone %llu condition %x\n", |
---|
| 2768 | + zsp->z_start, zsp->z_cond); |
---|
| 2769 | + break; |
---|
| 2770 | + } |
---|
| 2771 | + zsp->z_cond = ZC5_FULL; |
---|
| 2772 | +} |
---|
| 2773 | + |
---|
| 2774 | +static void zbc_inc_wp(struct sdebug_dev_info *devip, |
---|
| 2775 | + unsigned long long lba, unsigned int num) |
---|
| 2776 | +{ |
---|
| 2777 | + struct sdeb_zone_state *zsp = zbc_zone(devip, lba); |
---|
| 2778 | + unsigned long long n, end, zend = zsp->z_start + zsp->z_size; |
---|
| 2779 | + |
---|
| 2780 | + if (zbc_zone_is_conv(zsp)) |
---|
| 2781 | + return; |
---|
| 2782 | + |
---|
| 2783 | + if (zsp->z_type == ZBC_ZONE_TYPE_SWR) { |
---|
| 2784 | + zsp->z_wp += num; |
---|
| 2785 | + if (zsp->z_wp >= zend) |
---|
| 2786 | + zbc_set_zone_full(devip, zsp); |
---|
| 2787 | + return; |
---|
| 2788 | + } |
---|
| 2789 | + |
---|
| 2790 | + while (num) { |
---|
| 2791 | + if (lba != zsp->z_wp) |
---|
| 2792 | + zsp->z_non_seq_resource = true; |
---|
| 2793 | + |
---|
| 2794 | + end = lba + num; |
---|
| 2795 | + if (end >= zend) { |
---|
| 2796 | + n = zend - lba; |
---|
| 2797 | + zsp->z_wp = zend; |
---|
| 2798 | + } else if (end > zsp->z_wp) { |
---|
| 2799 | + n = num; |
---|
| 2800 | + zsp->z_wp = end; |
---|
| 2801 | + } else { |
---|
| 2802 | + n = num; |
---|
| 2803 | + } |
---|
| 2804 | + if (zsp->z_wp >= zend) |
---|
| 2805 | + zbc_set_zone_full(devip, zsp); |
---|
| 2806 | + |
---|
| 2807 | + num -= n; |
---|
| 2808 | + lba += n; |
---|
| 2809 | + if (num) { |
---|
| 2810 | + zsp++; |
---|
| 2811 | + zend = zsp->z_start + zsp->z_size; |
---|
| 2812 | + } |
---|
| 2813 | + } |
---|
| 2814 | +} |
---|
| 2815 | + |
---|
| 2816 | +static int check_zbc_access_params(struct scsi_cmnd *scp, |
---|
| 2817 | + unsigned long long lba, unsigned int num, bool write) |
---|
| 2818 | +{ |
---|
| 2819 | + struct scsi_device *sdp = scp->device; |
---|
| 2820 | + struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdp->hostdata; |
---|
| 2821 | + struct sdeb_zone_state *zsp = zbc_zone(devip, lba); |
---|
| 2822 | + struct sdeb_zone_state *zsp_end = zbc_zone(devip, lba + num - 1); |
---|
| 2823 | + |
---|
| 2824 | + if (!write) { |
---|
| 2825 | + if (devip->zmodel == BLK_ZONED_HA) |
---|
| 2826 | + return 0; |
---|
| 2827 | + /* For host-managed, reads cannot cross zone types boundaries */ |
---|
| 2828 | + if (zsp_end != zsp && |
---|
| 2829 | + zbc_zone_is_conv(zsp) && |
---|
| 2830 | + !zbc_zone_is_conv(zsp_end)) { |
---|
| 2831 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, |
---|
| 2832 | + LBA_OUT_OF_RANGE, |
---|
| 2833 | + READ_INVDATA_ASCQ); |
---|
| 2834 | + return check_condition_result; |
---|
| 2835 | + } |
---|
| 2836 | + return 0; |
---|
| 2837 | + } |
---|
| 2838 | + |
---|
| 2839 | + /* No restrictions for writes within conventional zones */ |
---|
| 2840 | + if (zbc_zone_is_conv(zsp)) { |
---|
| 2841 | + if (!zbc_zone_is_conv(zsp_end)) { |
---|
| 2842 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, |
---|
| 2843 | + LBA_OUT_OF_RANGE, |
---|
| 2844 | + WRITE_BOUNDARY_ASCQ); |
---|
| 2845 | + return check_condition_result; |
---|
| 2846 | + } |
---|
| 2847 | + return 0; |
---|
| 2848 | + } |
---|
| 2849 | + |
---|
| 2850 | + if (zsp->z_type == ZBC_ZONE_TYPE_SWR) { |
---|
| 2851 | + /* Writes cannot cross sequential zone boundaries */ |
---|
| 2852 | + if (zsp_end != zsp) { |
---|
| 2853 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, |
---|
| 2854 | + LBA_OUT_OF_RANGE, |
---|
| 2855 | + WRITE_BOUNDARY_ASCQ); |
---|
| 2856 | + return check_condition_result; |
---|
| 2857 | + } |
---|
| 2858 | + /* Cannot write full zones */ |
---|
| 2859 | + if (zsp->z_cond == ZC5_FULL) { |
---|
| 2860 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, |
---|
| 2861 | + INVALID_FIELD_IN_CDB, 0); |
---|
| 2862 | + return check_condition_result; |
---|
| 2863 | + } |
---|
| 2864 | + /* Writes must be aligned to the zone WP */ |
---|
| 2865 | + if (lba != zsp->z_wp) { |
---|
| 2866 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, |
---|
| 2867 | + LBA_OUT_OF_RANGE, |
---|
| 2868 | + UNALIGNED_WRITE_ASCQ); |
---|
| 2869 | + return check_condition_result; |
---|
| 2870 | + } |
---|
| 2871 | + } |
---|
| 2872 | + |
---|
| 2873 | + /* Handle implicit open of closed and empty zones */ |
---|
| 2874 | + if (zsp->z_cond == ZC1_EMPTY || zsp->z_cond == ZC4_CLOSED) { |
---|
| 2875 | + if (devip->max_open && |
---|
| 2876 | + devip->nr_exp_open >= devip->max_open) { |
---|
| 2877 | + mk_sense_buffer(scp, DATA_PROTECT, |
---|
| 2878 | + INSUFF_RES_ASC, |
---|
| 2879 | + INSUFF_ZONE_ASCQ); |
---|
| 2880 | + return check_condition_result; |
---|
| 2881 | + } |
---|
| 2882 | + zbc_open_zone(devip, zsp, false); |
---|
| 2883 | + } |
---|
| 2884 | + |
---|
| 2885 | + return 0; |
---|
| 2886 | +} |
---|
| 2887 | + |
---|
| 2888 | +static inline int check_device_access_params |
---|
| 2889 | + (struct scsi_cmnd *scp, unsigned long long lba, |
---|
| 2890 | + unsigned int num, bool write) |
---|
| 2891 | +{ |
---|
| 2892 | + struct scsi_device *sdp = scp->device; |
---|
| 2893 | + struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdp->hostdata; |
---|
| 2894 | + |
---|
2461 | 2895 | if (lba + num > sdebug_capacity) { |
---|
2462 | 2896 | mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); |
---|
2463 | 2897 | return check_condition_result; |
---|
.. | .. |
---|
2468 | 2902 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
---|
2469 | 2903 | return check_condition_result; |
---|
2470 | 2904 | } |
---|
| 2905 | + if (write && unlikely(sdebug_wp)) { |
---|
| 2906 | + mk_sense_buffer(scp, DATA_PROTECT, WRITE_PROTECTED, 0x2); |
---|
| 2907 | + return check_condition_result; |
---|
| 2908 | + } |
---|
| 2909 | + if (sdebug_dev_is_zoned(devip)) |
---|
| 2910 | + return check_zbc_access_params(scp, lba, num, write); |
---|
| 2911 | + |
---|
2471 | 2912 | return 0; |
---|
2472 | 2913 | } |
---|
2473 | 2914 | |
---|
| 2915 | +/* |
---|
| 2916 | + * Note: if BUG_ON() fires it usually indicates a problem with the parser |
---|
| 2917 | + * tables. Perhaps a missing F_FAKE_RW or FF_MEDIA_IO flag. Response functions |
---|
| 2918 | + * that access any of the "stores" in struct sdeb_store_info should call this |
---|
| 2919 | + * function with bug_if_fake_rw set to true. |
---|
| 2920 | + */ |
---|
| 2921 | +static inline struct sdeb_store_info *devip2sip(struct sdebug_dev_info *devip, |
---|
| 2922 | + bool bug_if_fake_rw) |
---|
| 2923 | +{ |
---|
| 2924 | + if (sdebug_fake_rw) { |
---|
| 2925 | + BUG_ON(bug_if_fake_rw); /* See note above */ |
---|
| 2926 | + return NULL; |
---|
| 2927 | + } |
---|
| 2928 | + return xa_load(per_store_ap, devip->sdbg_host->si_idx); |
---|
| 2929 | +} |
---|
| 2930 | + |
---|
2474 | 2931 | /* Returns number of bytes copied or -1 if error. */ |
---|
2475 | | -static int do_device_access(struct scsi_cmnd *scmd, u32 sg_skip, u64 lba, |
---|
2476 | | - u32 num, bool do_write) |
---|
| 2932 | +static int do_device_access(struct sdeb_store_info *sip, struct scsi_cmnd *scp, |
---|
| 2933 | + u32 sg_skip, u64 lba, u32 num, bool do_write) |
---|
2477 | 2934 | { |
---|
2478 | 2935 | int ret; |
---|
2479 | 2936 | u64 block, rest = 0; |
---|
2480 | | - struct scsi_data_buffer *sdb; |
---|
2481 | 2937 | enum dma_data_direction dir; |
---|
| 2938 | + struct scsi_data_buffer *sdb = &scp->sdb; |
---|
| 2939 | + u8 *fsp; |
---|
2482 | 2940 | |
---|
2483 | 2941 | if (do_write) { |
---|
2484 | | - sdb = scsi_out(scmd); |
---|
2485 | 2942 | dir = DMA_TO_DEVICE; |
---|
2486 | 2943 | write_since_sync = true; |
---|
2487 | 2944 | } else { |
---|
2488 | | - sdb = scsi_in(scmd); |
---|
2489 | 2945 | dir = DMA_FROM_DEVICE; |
---|
2490 | 2946 | } |
---|
2491 | 2947 | |
---|
2492 | | - if (!sdb->length) |
---|
| 2948 | + if (!sdb->length || !sip) |
---|
2493 | 2949 | return 0; |
---|
2494 | | - if (!(scsi_bidi_cmnd(scmd) || scmd->sc_data_direction == dir)) |
---|
| 2950 | + if (scp->sc_data_direction != dir) |
---|
2495 | 2951 | return -1; |
---|
| 2952 | + fsp = sip->storep; |
---|
2496 | 2953 | |
---|
2497 | 2954 | block = do_div(lba, sdebug_store_sectors); |
---|
2498 | 2955 | if (block + num > sdebug_store_sectors) |
---|
2499 | 2956 | rest = block + num - sdebug_store_sectors; |
---|
2500 | 2957 | |
---|
2501 | 2958 | ret = sg_copy_buffer(sdb->table.sgl, sdb->table.nents, |
---|
2502 | | - fake_storep + (block * sdebug_sector_size), |
---|
| 2959 | + fsp + (block * sdebug_sector_size), |
---|
2503 | 2960 | (num - rest) * sdebug_sector_size, sg_skip, do_write); |
---|
2504 | 2961 | if (ret != (num - rest) * sdebug_sector_size) |
---|
2505 | 2962 | return ret; |
---|
2506 | 2963 | |
---|
2507 | 2964 | if (rest) { |
---|
2508 | 2965 | ret += sg_copy_buffer(sdb->table.sgl, sdb->table.nents, |
---|
2509 | | - fake_storep, rest * sdebug_sector_size, |
---|
| 2966 | + fsp, rest * sdebug_sector_size, |
---|
2510 | 2967 | sg_skip + ((num - rest) * sdebug_sector_size), |
---|
2511 | 2968 | do_write); |
---|
2512 | 2969 | } |
---|
.. | .. |
---|
2514 | 2971 | return ret; |
---|
2515 | 2972 | } |
---|
2516 | 2973 | |
---|
2517 | | -/* If lba2fake_store(lba,num) compares equal to arr(num), then copy top half of |
---|
2518 | | - * arr into lba2fake_store(lba,num) and return true. If comparison fails then |
---|
| 2974 | +/* Returns number of bytes copied or -1 if error. */ |
---|
| 2975 | +static int do_dout_fetch(struct scsi_cmnd *scp, u32 num, u8 *doutp) |
---|
| 2976 | +{ |
---|
| 2977 | + struct scsi_data_buffer *sdb = &scp->sdb; |
---|
| 2978 | + |
---|
| 2979 | + if (!sdb->length) |
---|
| 2980 | + return 0; |
---|
| 2981 | + if (scp->sc_data_direction != DMA_TO_DEVICE) |
---|
| 2982 | + return -1; |
---|
| 2983 | + return sg_copy_buffer(sdb->table.sgl, sdb->table.nents, doutp, |
---|
| 2984 | + num * sdebug_sector_size, 0, true); |
---|
| 2985 | +} |
---|
| 2986 | + |
---|
| 2987 | +/* If sip->storep+lba compares equal to arr(num), then copy top half of |
---|
| 2988 | + * arr into sip->storep+lba and return true. If comparison fails then |
---|
2519 | 2989 | * return false. */ |
---|
2520 | | -static bool comp_write_worker(u64 lba, u32 num, const u8 *arr) |
---|
| 2990 | +static bool comp_write_worker(struct sdeb_store_info *sip, u64 lba, u32 num, |
---|
| 2991 | + const u8 *arr, bool compare_only) |
---|
2521 | 2992 | { |
---|
2522 | 2993 | bool res; |
---|
2523 | 2994 | u64 block, rest = 0; |
---|
2524 | 2995 | u32 store_blks = sdebug_store_sectors; |
---|
2525 | 2996 | u32 lb_size = sdebug_sector_size; |
---|
| 2997 | + u8 *fsp = sip->storep; |
---|
2526 | 2998 | |
---|
2527 | 2999 | block = do_div(lba, store_blks); |
---|
2528 | 3000 | if (block + num > store_blks) |
---|
2529 | 3001 | rest = block + num - store_blks; |
---|
2530 | 3002 | |
---|
2531 | | - res = !memcmp(fake_storep + (block * lb_size), arr, |
---|
2532 | | - (num - rest) * lb_size); |
---|
| 3003 | + res = !memcmp(fsp + (block * lb_size), arr, (num - rest) * lb_size); |
---|
2533 | 3004 | if (!res) |
---|
2534 | 3005 | return res; |
---|
2535 | 3006 | if (rest) |
---|
2536 | | - res = memcmp(fake_storep, arr + ((num - rest) * lb_size), |
---|
| 3007 | + res = memcmp(fsp, arr + ((num - rest) * lb_size), |
---|
2537 | 3008 | rest * lb_size); |
---|
2538 | 3009 | if (!res) |
---|
2539 | 3010 | return res; |
---|
| 3011 | + if (compare_only) |
---|
| 3012 | + return true; |
---|
2540 | 3013 | arr += num * lb_size; |
---|
2541 | | - memcpy(fake_storep + (block * lb_size), arr, (num - rest) * lb_size); |
---|
| 3014 | + memcpy(fsp + (block * lb_size), arr, (num - rest) * lb_size); |
---|
2542 | 3015 | if (rest) |
---|
2543 | | - memcpy(fake_storep, arr + ((num - rest) * lb_size), |
---|
2544 | | - rest * lb_size); |
---|
| 3016 | + memcpy(fsp, arr + ((num - rest) * lb_size), rest * lb_size); |
---|
2545 | 3017 | return res; |
---|
2546 | 3018 | } |
---|
2547 | 3019 | |
---|
.. | .. |
---|
2584 | 3056 | return 0; |
---|
2585 | 3057 | } |
---|
2586 | 3058 | |
---|
2587 | | -static void dif_copy_prot(struct scsi_cmnd *SCpnt, sector_t sector, |
---|
| 3059 | +static void dif_copy_prot(struct scsi_cmnd *scp, sector_t sector, |
---|
2588 | 3060 | unsigned int sectors, bool read) |
---|
2589 | 3061 | { |
---|
2590 | 3062 | size_t resid; |
---|
2591 | 3063 | void *paddr; |
---|
| 3064 | + struct sdeb_store_info *sip = devip2sip((struct sdebug_dev_info *) |
---|
| 3065 | + scp->device->hostdata, true); |
---|
| 3066 | + struct t10_pi_tuple *dif_storep = sip->dif_storep; |
---|
2592 | 3067 | const void *dif_store_end = dif_storep + sdebug_store_sectors; |
---|
2593 | 3068 | struct sg_mapping_iter miter; |
---|
2594 | 3069 | |
---|
2595 | 3070 | /* Bytes of protection data to copy into sgl */ |
---|
2596 | 3071 | resid = sectors * sizeof(*dif_storep); |
---|
2597 | 3072 | |
---|
2598 | | - sg_miter_start(&miter, scsi_prot_sglist(SCpnt), |
---|
2599 | | - scsi_prot_sg_count(SCpnt), SG_MITER_ATOMIC | |
---|
2600 | | - (read ? SG_MITER_TO_SG : SG_MITER_FROM_SG)); |
---|
| 3073 | + sg_miter_start(&miter, scsi_prot_sglist(scp), |
---|
| 3074 | + scsi_prot_sg_count(scp), SG_MITER_ATOMIC | |
---|
| 3075 | + (read ? SG_MITER_TO_SG : SG_MITER_FROM_SG)); |
---|
2601 | 3076 | |
---|
2602 | 3077 | while (sg_miter_next(&miter) && resid > 0) { |
---|
2603 | | - size_t len = min(miter.length, resid); |
---|
2604 | | - void *start = dif_store(sector); |
---|
| 3078 | + size_t len = min_t(size_t, miter.length, resid); |
---|
| 3079 | + void *start = dif_store(sip, sector); |
---|
2605 | 3080 | size_t rest = 0; |
---|
2606 | 3081 | |
---|
2607 | 3082 | if (dif_store_end < start + len) |
---|
.. | .. |
---|
2627 | 3102 | sg_miter_stop(&miter); |
---|
2628 | 3103 | } |
---|
2629 | 3104 | |
---|
2630 | | -static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, |
---|
| 3105 | +static int prot_verify_read(struct scsi_cmnd *scp, sector_t start_sec, |
---|
2631 | 3106 | unsigned int sectors, u32 ei_lba) |
---|
2632 | 3107 | { |
---|
2633 | 3108 | unsigned int i; |
---|
2634 | | - struct t10_pi_tuple *sdt; |
---|
2635 | 3109 | sector_t sector; |
---|
| 3110 | + struct sdeb_store_info *sip = devip2sip((struct sdebug_dev_info *) |
---|
| 3111 | + scp->device->hostdata, true); |
---|
| 3112 | + struct t10_pi_tuple *sdt; |
---|
2636 | 3113 | |
---|
2637 | 3114 | for (i = 0; i < sectors; i++, ei_lba++) { |
---|
2638 | 3115 | int ret; |
---|
2639 | 3116 | |
---|
2640 | 3117 | sector = start_sec + i; |
---|
2641 | | - sdt = dif_store(sector); |
---|
| 3118 | + sdt = dif_store(sip, sector); |
---|
2642 | 3119 | |
---|
2643 | 3120 | if (sdt->app_tag == cpu_to_be16(0xffff)) |
---|
2644 | 3121 | continue; |
---|
2645 | 3122 | |
---|
2646 | | - ret = dif_verify(sdt, lba2fake_store(sector), sector, ei_lba); |
---|
| 3123 | + ret = dif_verify(sdt, lba2fake_store(sip, sector), sector, |
---|
| 3124 | + ei_lba); |
---|
2647 | 3125 | if (ret) { |
---|
2648 | 3126 | dif_errors++; |
---|
2649 | 3127 | return ret; |
---|
2650 | 3128 | } |
---|
2651 | 3129 | } |
---|
2652 | 3130 | |
---|
2653 | | - dif_copy_prot(SCpnt, start_sec, sectors, true); |
---|
| 3131 | + dif_copy_prot(scp, start_sec, sectors, true); |
---|
2654 | 3132 | dix_reads++; |
---|
2655 | 3133 | |
---|
2656 | 3134 | return 0; |
---|
.. | .. |
---|
2658 | 3136 | |
---|
2659 | 3137 | static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) |
---|
2660 | 3138 | { |
---|
2661 | | - u8 *cmd = scp->cmnd; |
---|
2662 | | - struct sdebug_queued_cmd *sqcp; |
---|
2663 | | - u64 lba; |
---|
| 3139 | + bool check_prot; |
---|
2664 | 3140 | u32 num; |
---|
2665 | 3141 | u32 ei_lba; |
---|
2666 | | - unsigned long iflags; |
---|
2667 | 3142 | int ret; |
---|
2668 | | - bool check_prot; |
---|
| 3143 | + u64 lba; |
---|
| 3144 | + struct sdeb_store_info *sip = devip2sip(devip, true); |
---|
| 3145 | + rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck; |
---|
| 3146 | + u8 *cmd = scp->cmnd; |
---|
2669 | 3147 | |
---|
2670 | 3148 | switch (cmd[0]) { |
---|
2671 | 3149 | case READ_16: |
---|
.. | .. |
---|
2718 | 3196 | sdev_printk(KERN_ERR, scp->device, "Unprotected RD " |
---|
2719 | 3197 | "to DIF device\n"); |
---|
2720 | 3198 | } |
---|
2721 | | - if (unlikely(sdebug_any_injecting_opt)) { |
---|
2722 | | - sqcp = (struct sdebug_queued_cmd *)scp->host_scribble; |
---|
2723 | | - |
---|
2724 | | - if (sqcp) { |
---|
2725 | | - if (sqcp->inj_short) |
---|
2726 | | - num /= 2; |
---|
2727 | | - } |
---|
2728 | | - } else |
---|
2729 | | - sqcp = NULL; |
---|
2730 | | - |
---|
2731 | | - /* inline check_device_access_params() */ |
---|
2732 | | - if (unlikely(lba + num > sdebug_capacity)) { |
---|
2733 | | - mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); |
---|
2734 | | - return check_condition_result; |
---|
2735 | | - } |
---|
2736 | | - /* transfer length excessive (tie in to block limits VPD page) */ |
---|
2737 | | - if (unlikely(num > sdebug_store_sectors)) { |
---|
2738 | | - /* needs work to find which cdb byte 'num' comes from */ |
---|
2739 | | - mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
---|
2740 | | - return check_condition_result; |
---|
| 3199 | + if (unlikely((sdebug_opts & SDEBUG_OPT_SHORT_TRANSFER) && |
---|
| 3200 | + atomic_read(&sdeb_inject_pending))) { |
---|
| 3201 | + num /= 2; |
---|
| 3202 | + atomic_set(&sdeb_inject_pending, 0); |
---|
2741 | 3203 | } |
---|
2742 | 3204 | |
---|
| 3205 | + ret = check_device_access_params(scp, lba, num, false); |
---|
| 3206 | + if (ret) |
---|
| 3207 | + return ret; |
---|
2743 | 3208 | if (unlikely((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) && |
---|
2744 | 3209 | (lba <= (sdebug_medium_error_start + sdebug_medium_error_count - 1)) && |
---|
2745 | 3210 | ((lba + num) > sdebug_medium_error_start))) { |
---|
.. | .. |
---|
2756 | 3221 | return check_condition_result; |
---|
2757 | 3222 | } |
---|
2758 | 3223 | |
---|
2759 | | - read_lock_irqsave(&atomic_rw, iflags); |
---|
| 3224 | + read_lock(macc_lckp); |
---|
2760 | 3225 | |
---|
2761 | 3226 | /* DIX + T10 DIF */ |
---|
2762 | 3227 | if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) { |
---|
2763 | 3228 | int prot_ret = prot_verify_read(scp, lba, num, ei_lba); |
---|
2764 | 3229 | |
---|
2765 | 3230 | if (prot_ret) { |
---|
2766 | | - read_unlock_irqrestore(&atomic_rw, iflags); |
---|
| 3231 | + read_unlock(macc_lckp); |
---|
2767 | 3232 | mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, prot_ret); |
---|
2768 | 3233 | return illegal_condition_result; |
---|
2769 | 3234 | } |
---|
2770 | 3235 | } |
---|
2771 | 3236 | |
---|
2772 | | - ret = do_device_access(scp, 0, lba, num, false); |
---|
2773 | | - read_unlock_irqrestore(&atomic_rw, iflags); |
---|
| 3237 | + ret = do_device_access(sip, scp, 0, lba, num, false); |
---|
| 3238 | + read_unlock(macc_lckp); |
---|
2774 | 3239 | if (unlikely(ret == -1)) |
---|
2775 | 3240 | return DID_ERROR << 16; |
---|
2776 | 3241 | |
---|
2777 | | - scsi_in(scp)->resid = scsi_bufflen(scp) - ret; |
---|
| 3242 | + scsi_set_resid(scp, scsi_bufflen(scp) - ret); |
---|
2778 | 3243 | |
---|
2779 | | - if (unlikely(sqcp)) { |
---|
2780 | | - if (sqcp->inj_recovered) { |
---|
2781 | | - mk_sense_buffer(scp, RECOVERED_ERROR, |
---|
2782 | | - THRESHOLD_EXCEEDED, 0); |
---|
| 3244 | + if (unlikely((sdebug_opts & SDEBUG_OPT_RECOV_DIF_DIX) && |
---|
| 3245 | + atomic_read(&sdeb_inject_pending))) { |
---|
| 3246 | + if (sdebug_opts & SDEBUG_OPT_RECOVERED_ERR) { |
---|
| 3247 | + mk_sense_buffer(scp, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); |
---|
| 3248 | + atomic_set(&sdeb_inject_pending, 0); |
---|
2783 | 3249 | return check_condition_result; |
---|
2784 | | - } else if (sqcp->inj_transport) { |
---|
2785 | | - mk_sense_buffer(scp, ABORTED_COMMAND, |
---|
2786 | | - TRANSPORT_PROBLEM, ACK_NAK_TO); |
---|
2787 | | - return check_condition_result; |
---|
2788 | | - } else if (sqcp->inj_dif) { |
---|
| 3250 | + } else if (sdebug_opts & SDEBUG_OPT_DIF_ERR) { |
---|
2789 | 3251 | /* Logical block guard check failed */ |
---|
2790 | 3252 | mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1); |
---|
| 3253 | + atomic_set(&sdeb_inject_pending, 0); |
---|
2791 | 3254 | return illegal_condition_result; |
---|
2792 | | - } else if (sqcp->inj_dix) { |
---|
| 3255 | + } else if (SDEBUG_OPT_DIX_ERR & sdebug_opts) { |
---|
2793 | 3256 | mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1); |
---|
| 3257 | + atomic_set(&sdeb_inject_pending, 0); |
---|
2794 | 3258 | return illegal_condition_result; |
---|
2795 | 3259 | } |
---|
2796 | 3260 | } |
---|
.. | .. |
---|
2908 | 3372 | return lba; |
---|
2909 | 3373 | } |
---|
2910 | 3374 | |
---|
2911 | | -static unsigned int map_state(sector_t lba, unsigned int *num) |
---|
| 3375 | +static unsigned int map_state(struct sdeb_store_info *sip, sector_t lba, |
---|
| 3376 | + unsigned int *num) |
---|
2912 | 3377 | { |
---|
2913 | 3378 | sector_t end; |
---|
2914 | 3379 | unsigned int mapped; |
---|
.. | .. |
---|
2916 | 3381 | unsigned long next; |
---|
2917 | 3382 | |
---|
2918 | 3383 | index = lba_to_map_index(lba); |
---|
2919 | | - mapped = test_bit(index, map_storep); |
---|
| 3384 | + mapped = test_bit(index, sip->map_storep); |
---|
2920 | 3385 | |
---|
2921 | 3386 | if (mapped) |
---|
2922 | | - next = find_next_zero_bit(map_storep, map_size, index); |
---|
| 3387 | + next = find_next_zero_bit(sip->map_storep, map_size, index); |
---|
2923 | 3388 | else |
---|
2924 | | - next = find_next_bit(map_storep, map_size, index); |
---|
| 3389 | + next = find_next_bit(sip->map_storep, map_size, index); |
---|
2925 | 3390 | |
---|
2926 | 3391 | end = min_t(sector_t, sdebug_store_sectors, map_index_to_lba(next)); |
---|
2927 | 3392 | *num = end - lba; |
---|
2928 | 3393 | return mapped; |
---|
2929 | 3394 | } |
---|
2930 | 3395 | |
---|
2931 | | -static void map_region(sector_t lba, unsigned int len) |
---|
| 3396 | +static void map_region(struct sdeb_store_info *sip, sector_t lba, |
---|
| 3397 | + unsigned int len) |
---|
2932 | 3398 | { |
---|
2933 | 3399 | sector_t end = lba + len; |
---|
2934 | 3400 | |
---|
.. | .. |
---|
2936 | 3402 | unsigned long index = lba_to_map_index(lba); |
---|
2937 | 3403 | |
---|
2938 | 3404 | if (index < map_size) |
---|
2939 | | - set_bit(index, map_storep); |
---|
| 3405 | + set_bit(index, sip->map_storep); |
---|
2940 | 3406 | |
---|
2941 | 3407 | lba = map_index_to_lba(index + 1); |
---|
2942 | 3408 | } |
---|
2943 | 3409 | } |
---|
2944 | 3410 | |
---|
2945 | | -static void unmap_region(sector_t lba, unsigned int len) |
---|
| 3411 | +static void unmap_region(struct sdeb_store_info *sip, sector_t lba, |
---|
| 3412 | + unsigned int len) |
---|
2946 | 3413 | { |
---|
2947 | 3414 | sector_t end = lba + len; |
---|
| 3415 | + u8 *fsp = sip->storep; |
---|
2948 | 3416 | |
---|
2949 | 3417 | while (lba < end) { |
---|
2950 | 3418 | unsigned long index = lba_to_map_index(lba); |
---|
.. | .. |
---|
2952 | 3420 | if (lba == map_index_to_lba(index) && |
---|
2953 | 3421 | lba + sdebug_unmap_granularity <= end && |
---|
2954 | 3422 | index < map_size) { |
---|
2955 | | - clear_bit(index, map_storep); |
---|
| 3423 | + clear_bit(index, sip->map_storep); |
---|
2956 | 3424 | if (sdebug_lbprz) { /* for LBPRZ=2 return 0xff_s */ |
---|
2957 | | - memset(fake_storep + |
---|
2958 | | - lba * sdebug_sector_size, |
---|
| 3425 | + memset(fsp + lba * sdebug_sector_size, |
---|
2959 | 3426 | (sdebug_lbprz & 1) ? 0 : 0xff, |
---|
2960 | 3427 | sdebug_sector_size * |
---|
2961 | 3428 | sdebug_unmap_granularity); |
---|
2962 | 3429 | } |
---|
2963 | | - if (dif_storep) { |
---|
2964 | | - memset(dif_storep + lba, 0xff, |
---|
2965 | | - sizeof(*dif_storep) * |
---|
| 3430 | + if (sip->dif_storep) { |
---|
| 3431 | + memset(sip->dif_storep + lba, 0xff, |
---|
| 3432 | + sizeof(*sip->dif_storep) * |
---|
2966 | 3433 | sdebug_unmap_granularity); |
---|
2967 | 3434 | } |
---|
2968 | 3435 | } |
---|
.. | .. |
---|
2972 | 3439 | |
---|
2973 | 3440 | static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) |
---|
2974 | 3441 | { |
---|
2975 | | - u8 *cmd = scp->cmnd; |
---|
2976 | | - u64 lba; |
---|
| 3442 | + bool check_prot; |
---|
2977 | 3443 | u32 num; |
---|
2978 | 3444 | u32 ei_lba; |
---|
2979 | | - unsigned long iflags; |
---|
2980 | 3445 | int ret; |
---|
2981 | | - bool check_prot; |
---|
| 3446 | + u64 lba; |
---|
| 3447 | + struct sdeb_store_info *sip = devip2sip(devip, true); |
---|
| 3448 | + rwlock_t *macc_lckp = &sip->macc_lck; |
---|
| 3449 | + u8 *cmd = scp->cmnd; |
---|
2982 | 3450 | |
---|
2983 | 3451 | switch (cmd[0]) { |
---|
2984 | 3452 | case WRITE_16: |
---|
.. | .. |
---|
3032 | 3500 | "to DIF device\n"); |
---|
3033 | 3501 | } |
---|
3034 | 3502 | |
---|
3035 | | - /* inline check_device_access_params() */ |
---|
3036 | | - if (unlikely(lba + num > sdebug_capacity)) { |
---|
3037 | | - mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); |
---|
3038 | | - return check_condition_result; |
---|
| 3503 | + write_lock(macc_lckp); |
---|
| 3504 | + ret = check_device_access_params(scp, lba, num, true); |
---|
| 3505 | + if (ret) { |
---|
| 3506 | + write_unlock(macc_lckp); |
---|
| 3507 | + return ret; |
---|
3039 | 3508 | } |
---|
3040 | | - /* transfer length excessive (tie in to block limits VPD page) */ |
---|
3041 | | - if (unlikely(num > sdebug_store_sectors)) { |
---|
3042 | | - /* needs work to find which cdb byte 'num' comes from */ |
---|
3043 | | - mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
---|
3044 | | - return check_condition_result; |
---|
3045 | | - } |
---|
3046 | | - |
---|
3047 | | - write_lock_irqsave(&atomic_rw, iflags); |
---|
3048 | 3509 | |
---|
3049 | 3510 | /* DIX + T10 DIF */ |
---|
3050 | 3511 | if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) { |
---|
3051 | 3512 | int prot_ret = prot_verify_write(scp, lba, num, ei_lba); |
---|
3052 | 3513 | |
---|
3053 | 3514 | if (prot_ret) { |
---|
3054 | | - write_unlock_irqrestore(&atomic_rw, iflags); |
---|
| 3515 | + write_unlock(macc_lckp); |
---|
3055 | 3516 | mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, prot_ret); |
---|
3056 | 3517 | return illegal_condition_result; |
---|
3057 | 3518 | } |
---|
3058 | 3519 | } |
---|
3059 | 3520 | |
---|
3060 | | - ret = do_device_access(scp, 0, lba, num, true); |
---|
| 3521 | + ret = do_device_access(sip, scp, 0, lba, num, true); |
---|
3061 | 3522 | if (unlikely(scsi_debug_lbp())) |
---|
3062 | | - map_region(lba, num); |
---|
3063 | | - write_unlock_irqrestore(&atomic_rw, iflags); |
---|
| 3523 | + map_region(sip, lba, num); |
---|
| 3524 | + /* If ZBC zone then bump its write pointer */ |
---|
| 3525 | + if (sdebug_dev_is_zoned(devip)) |
---|
| 3526 | + zbc_inc_wp(devip, lba, num); |
---|
| 3527 | + write_unlock(macc_lckp); |
---|
3064 | 3528 | if (unlikely(-1 == ret)) |
---|
3065 | 3529 | return DID_ERROR << 16; |
---|
3066 | 3530 | else if (unlikely(sdebug_verbose && |
---|
.. | .. |
---|
3069 | 3533 | "%s: write: cdb indicated=%u, IO sent=%d bytes\n", |
---|
3070 | 3534 | my_name, num * sdebug_sector_size, ret); |
---|
3071 | 3535 | |
---|
3072 | | - if (unlikely(sdebug_any_injecting_opt)) { |
---|
3073 | | - struct sdebug_queued_cmd *sqcp = |
---|
3074 | | - (struct sdebug_queued_cmd *)scp->host_scribble; |
---|
3075 | | - |
---|
3076 | | - if (sqcp) { |
---|
3077 | | - if (sqcp->inj_recovered) { |
---|
3078 | | - mk_sense_buffer(scp, RECOVERED_ERROR, |
---|
3079 | | - THRESHOLD_EXCEEDED, 0); |
---|
3080 | | - return check_condition_result; |
---|
3081 | | - } else if (sqcp->inj_dif) { |
---|
3082 | | - /* Logical block guard check failed */ |
---|
3083 | | - mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1); |
---|
3084 | | - return illegal_condition_result; |
---|
3085 | | - } else if (sqcp->inj_dix) { |
---|
3086 | | - mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1); |
---|
3087 | | - return illegal_condition_result; |
---|
3088 | | - } |
---|
| 3536 | + if (unlikely((sdebug_opts & SDEBUG_OPT_RECOV_DIF_DIX) && |
---|
| 3537 | + atomic_read(&sdeb_inject_pending))) { |
---|
| 3538 | + if (sdebug_opts & SDEBUG_OPT_RECOVERED_ERR) { |
---|
| 3539 | + mk_sense_buffer(scp, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); |
---|
| 3540 | + atomic_set(&sdeb_inject_pending, 0); |
---|
| 3541 | + return check_condition_result; |
---|
| 3542 | + } else if (sdebug_opts & SDEBUG_OPT_DIF_ERR) { |
---|
| 3543 | + /* Logical block guard check failed */ |
---|
| 3544 | + mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1); |
---|
| 3545 | + atomic_set(&sdeb_inject_pending, 0); |
---|
| 3546 | + return illegal_condition_result; |
---|
| 3547 | + } else if (sdebug_opts & SDEBUG_OPT_DIX_ERR) { |
---|
| 3548 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1); |
---|
| 3549 | + atomic_set(&sdeb_inject_pending, 0); |
---|
| 3550 | + return illegal_condition_result; |
---|
3089 | 3551 | } |
---|
3090 | 3552 | } |
---|
3091 | 3553 | return 0; |
---|
.. | .. |
---|
3101 | 3563 | u8 *cmd = scp->cmnd; |
---|
3102 | 3564 | u8 *lrdp = NULL; |
---|
3103 | 3565 | u8 *up; |
---|
| 3566 | + struct sdeb_store_info *sip = devip2sip(devip, true); |
---|
| 3567 | + rwlock_t *macc_lckp = &sip->macc_lck; |
---|
3104 | 3568 | u8 wrprotect; |
---|
3105 | 3569 | u16 lbdof, num_lrd, k; |
---|
3106 | 3570 | u32 num, num_by, bt_len, lbdof_blen, sg_off, cum_lb; |
---|
3107 | 3571 | u32 lb_size = sdebug_sector_size; |
---|
3108 | 3572 | u32 ei_lba; |
---|
3109 | 3573 | u64 lba; |
---|
3110 | | - unsigned long iflags; |
---|
3111 | 3574 | int ret, res; |
---|
3112 | 3575 | bool is_16; |
---|
3113 | 3576 | static const u32 lrd_size = 32; /* + parameter list header size */ |
---|
.. | .. |
---|
3156 | 3619 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
---|
3157 | 3620 | return illegal_condition_result; |
---|
3158 | 3621 | } |
---|
3159 | | - lrdp = kzalloc(lbdof_blen, GFP_ATOMIC); |
---|
| 3622 | + lrdp = kzalloc(lbdof_blen, GFP_ATOMIC | __GFP_NOWARN); |
---|
3160 | 3623 | if (lrdp == NULL) |
---|
3161 | 3624 | return SCSI_MLQUEUE_HOST_BUSY; |
---|
3162 | 3625 | if (sdebug_verbose) |
---|
.. | .. |
---|
3169 | 3632 | goto err_out; |
---|
3170 | 3633 | } |
---|
3171 | 3634 | |
---|
3172 | | - write_lock_irqsave(&atomic_rw, iflags); |
---|
| 3635 | + write_lock(macc_lckp); |
---|
3173 | 3636 | sg_off = lbdof_blen; |
---|
3174 | 3637 | /* Spec says Buffer xfer Length field in number of LBs in dout */ |
---|
3175 | 3638 | cum_lb = 0; |
---|
.. | .. |
---|
3182 | 3645 | my_name, __func__, k, lba, num, sg_off); |
---|
3183 | 3646 | if (num == 0) |
---|
3184 | 3647 | continue; |
---|
3185 | | - ret = check_device_access_params(scp, lba, num); |
---|
| 3648 | + ret = check_device_access_params(scp, lba, num, true); |
---|
3186 | 3649 | if (ret) |
---|
3187 | 3650 | goto err_out_unlock; |
---|
3188 | 3651 | num_by = num * lb_size; |
---|
.. | .. |
---|
3212 | 3675 | } |
---|
3213 | 3676 | } |
---|
3214 | 3677 | |
---|
3215 | | - ret = do_device_access(scp, sg_off, lba, num, true); |
---|
| 3678 | + ret = do_device_access(sip, scp, sg_off, lba, num, true); |
---|
| 3679 | + /* If ZBC zone then bump its write pointer */ |
---|
| 3680 | + if (sdebug_dev_is_zoned(devip)) |
---|
| 3681 | + zbc_inc_wp(devip, lba, num); |
---|
3216 | 3682 | if (unlikely(scsi_debug_lbp())) |
---|
3217 | | - map_region(lba, num); |
---|
| 3683 | + map_region(sip, lba, num); |
---|
3218 | 3684 | if (unlikely(-1 == ret)) { |
---|
3219 | 3685 | ret = DID_ERROR << 16; |
---|
3220 | 3686 | goto err_out_unlock; |
---|
.. | .. |
---|
3223 | 3689 | "%s: write: cdb indicated=%u, IO sent=%d bytes\n", |
---|
3224 | 3690 | my_name, num_by, ret); |
---|
3225 | 3691 | |
---|
3226 | | - if (unlikely(sdebug_any_injecting_opt)) { |
---|
3227 | | - struct sdebug_queued_cmd *sqcp = |
---|
3228 | | - (struct sdebug_queued_cmd *)scp->host_scribble; |
---|
3229 | | - |
---|
3230 | | - if (sqcp) { |
---|
3231 | | - if (sqcp->inj_recovered) { |
---|
3232 | | - mk_sense_buffer(scp, RECOVERED_ERROR, |
---|
3233 | | - THRESHOLD_EXCEEDED, 0); |
---|
3234 | | - ret = illegal_condition_result; |
---|
3235 | | - goto err_out_unlock; |
---|
3236 | | - } else if (sqcp->inj_dif) { |
---|
3237 | | - /* Logical block guard check failed */ |
---|
3238 | | - mk_sense_buffer(scp, ABORTED_COMMAND, |
---|
3239 | | - 0x10, 1); |
---|
3240 | | - ret = illegal_condition_result; |
---|
3241 | | - goto err_out_unlock; |
---|
3242 | | - } else if (sqcp->inj_dix) { |
---|
3243 | | - mk_sense_buffer(scp, ILLEGAL_REQUEST, |
---|
3244 | | - 0x10, 1); |
---|
3245 | | - ret = illegal_condition_result; |
---|
3246 | | - goto err_out_unlock; |
---|
3247 | | - } |
---|
| 3692 | + if (unlikely((sdebug_opts & SDEBUG_OPT_RECOV_DIF_DIX) && |
---|
| 3693 | + atomic_read(&sdeb_inject_pending))) { |
---|
| 3694 | + if (sdebug_opts & SDEBUG_OPT_RECOVERED_ERR) { |
---|
| 3695 | + mk_sense_buffer(scp, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); |
---|
| 3696 | + atomic_set(&sdeb_inject_pending, 0); |
---|
| 3697 | + ret = check_condition_result; |
---|
| 3698 | + goto err_out_unlock; |
---|
| 3699 | + } else if (sdebug_opts & SDEBUG_OPT_DIF_ERR) { |
---|
| 3700 | + /* Logical block guard check failed */ |
---|
| 3701 | + mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1); |
---|
| 3702 | + atomic_set(&sdeb_inject_pending, 0); |
---|
| 3703 | + ret = illegal_condition_result; |
---|
| 3704 | + goto err_out_unlock; |
---|
| 3705 | + } else if (sdebug_opts & SDEBUG_OPT_DIX_ERR) { |
---|
| 3706 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1); |
---|
| 3707 | + atomic_set(&sdeb_inject_pending, 0); |
---|
| 3708 | + ret = illegal_condition_result; |
---|
| 3709 | + goto err_out_unlock; |
---|
3248 | 3710 | } |
---|
3249 | 3711 | } |
---|
3250 | 3712 | sg_off += num_by; |
---|
.. | .. |
---|
3252 | 3714 | } |
---|
3253 | 3715 | ret = 0; |
---|
3254 | 3716 | err_out_unlock: |
---|
3255 | | - write_unlock_irqrestore(&atomic_rw, iflags); |
---|
| 3717 | + write_unlock(macc_lckp); |
---|
3256 | 3718 | err_out: |
---|
3257 | 3719 | kfree(lrdp); |
---|
3258 | 3720 | return ret; |
---|
.. | .. |
---|
3261 | 3723 | static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, |
---|
3262 | 3724 | u32 ei_lba, bool unmap, bool ndob) |
---|
3263 | 3725 | { |
---|
3264 | | - int ret; |
---|
3265 | | - unsigned long iflags; |
---|
| 3726 | + struct scsi_device *sdp = scp->device; |
---|
| 3727 | + struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdp->hostdata; |
---|
3266 | 3728 | unsigned long long i; |
---|
3267 | | - u32 lb_size = sdebug_sector_size; |
---|
3268 | 3729 | u64 block, lbaa; |
---|
| 3730 | + u32 lb_size = sdebug_sector_size; |
---|
| 3731 | + int ret; |
---|
| 3732 | + struct sdeb_store_info *sip = devip2sip((struct sdebug_dev_info *) |
---|
| 3733 | + scp->device->hostdata, true); |
---|
| 3734 | + rwlock_t *macc_lckp = &sip->macc_lck; |
---|
3269 | 3735 | u8 *fs1p; |
---|
| 3736 | + u8 *fsp; |
---|
3270 | 3737 | |
---|
3271 | | - ret = check_device_access_params(scp, lba, num); |
---|
3272 | | - if (ret) |
---|
| 3738 | + write_lock(macc_lckp); |
---|
| 3739 | + |
---|
| 3740 | + ret = check_device_access_params(scp, lba, num, true); |
---|
| 3741 | + if (ret) { |
---|
| 3742 | + write_unlock(macc_lckp); |
---|
3273 | 3743 | return ret; |
---|
3274 | | - |
---|
3275 | | - write_lock_irqsave(&atomic_rw, iflags); |
---|
| 3744 | + } |
---|
3276 | 3745 | |
---|
3277 | 3746 | if (unmap && scsi_debug_lbp()) { |
---|
3278 | | - unmap_region(lba, num); |
---|
| 3747 | + unmap_region(sip, lba, num); |
---|
3279 | 3748 | goto out; |
---|
3280 | 3749 | } |
---|
3281 | 3750 | lbaa = lba; |
---|
3282 | 3751 | block = do_div(lbaa, sdebug_store_sectors); |
---|
3283 | 3752 | /* if ndob then zero 1 logical block, else fetch 1 logical block */ |
---|
3284 | | - fs1p = fake_storep + (block * lb_size); |
---|
| 3753 | + fsp = sip->storep; |
---|
| 3754 | + fs1p = fsp + (block * lb_size); |
---|
3285 | 3755 | if (ndob) { |
---|
3286 | 3756 | memset(fs1p, 0, lb_size); |
---|
3287 | 3757 | ret = 0; |
---|
.. | .. |
---|
3289 | 3759 | ret = fetch_to_dev_buffer(scp, fs1p, lb_size); |
---|
3290 | 3760 | |
---|
3291 | 3761 | if (-1 == ret) { |
---|
3292 | | - write_unlock_irqrestore(&atomic_rw, iflags); |
---|
| 3762 | + write_unlock(&sip->macc_lck); |
---|
3293 | 3763 | return DID_ERROR << 16; |
---|
3294 | 3764 | } else if (sdebug_verbose && !ndob && (ret < lb_size)) |
---|
3295 | 3765 | sdev_printk(KERN_INFO, scp->device, |
---|
.. | .. |
---|
3300 | 3770 | for (i = 1 ; i < num ; i++) { |
---|
3301 | 3771 | lbaa = lba + i; |
---|
3302 | 3772 | block = do_div(lbaa, sdebug_store_sectors); |
---|
3303 | | - memmove(fake_storep + (block * lb_size), fs1p, lb_size); |
---|
| 3773 | + memmove(fsp + (block * lb_size), fs1p, lb_size); |
---|
3304 | 3774 | } |
---|
3305 | 3775 | if (scsi_debug_lbp()) |
---|
3306 | | - map_region(lba, num); |
---|
| 3776 | + map_region(sip, lba, num); |
---|
| 3777 | + /* If ZBC zone then bump its write pointer */ |
---|
| 3778 | + if (sdebug_dev_is_zoned(devip)) |
---|
| 3779 | + zbc_inc_wp(devip, lba, num); |
---|
3307 | 3780 | out: |
---|
3308 | | - write_unlock_irqrestore(&atomic_rw, iflags); |
---|
| 3781 | + write_unlock(macc_lckp); |
---|
3309 | 3782 | |
---|
3310 | 3783 | return 0; |
---|
3311 | 3784 | } |
---|
.. | .. |
---|
3417 | 3890 | { |
---|
3418 | 3891 | u8 *cmd = scp->cmnd; |
---|
3419 | 3892 | u8 *arr; |
---|
3420 | | - u8 *fake_storep_hold; |
---|
| 3893 | + struct sdeb_store_info *sip = devip2sip(devip, true); |
---|
| 3894 | + rwlock_t *macc_lckp = &sip->macc_lck; |
---|
3421 | 3895 | u64 lba; |
---|
3422 | 3896 | u32 dnum; |
---|
3423 | 3897 | u32 lb_size = sdebug_sector_size; |
---|
3424 | 3898 | u8 num; |
---|
3425 | | - unsigned long iflags; |
---|
3426 | 3899 | int ret; |
---|
3427 | 3900 | int retval = 0; |
---|
3428 | 3901 | |
---|
.. | .. |
---|
3440 | 3913 | (cmd[1] & 0xe0) == 0) |
---|
3441 | 3914 | sdev_printk(KERN_ERR, scp->device, "Unprotected WR " |
---|
3442 | 3915 | "to DIF device\n"); |
---|
3443 | | - |
---|
3444 | | - /* inline check_device_access_params() */ |
---|
3445 | | - if (lba + num > sdebug_capacity) { |
---|
3446 | | - mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); |
---|
3447 | | - return check_condition_result; |
---|
3448 | | - } |
---|
3449 | | - /* transfer length excessive (tie in to block limits VPD page) */ |
---|
3450 | | - if (num > sdebug_store_sectors) { |
---|
3451 | | - /* needs work to find which cdb byte 'num' comes from */ |
---|
3452 | | - mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
---|
3453 | | - return check_condition_result; |
---|
3454 | | - } |
---|
| 3916 | + ret = check_device_access_params(scp, lba, num, false); |
---|
| 3917 | + if (ret) |
---|
| 3918 | + return ret; |
---|
3455 | 3919 | dnum = 2 * num; |
---|
3456 | 3920 | arr = kcalloc(lb_size, dnum, GFP_ATOMIC); |
---|
3457 | 3921 | if (NULL == arr) { |
---|
.. | .. |
---|
3460 | 3924 | return check_condition_result; |
---|
3461 | 3925 | } |
---|
3462 | 3926 | |
---|
3463 | | - write_lock_irqsave(&atomic_rw, iflags); |
---|
| 3927 | + write_lock(macc_lckp); |
---|
3464 | 3928 | |
---|
3465 | | - /* trick do_device_access() to fetch both compare and write buffers |
---|
3466 | | - * from data-in into arr. Safe (atomic) since write_lock held. */ |
---|
3467 | | - fake_storep_hold = fake_storep; |
---|
3468 | | - fake_storep = arr; |
---|
3469 | | - ret = do_device_access(scp, 0, 0, dnum, true); |
---|
3470 | | - fake_storep = fake_storep_hold; |
---|
| 3929 | + ret = do_dout_fetch(scp, dnum, arr); |
---|
3471 | 3930 | if (ret == -1) { |
---|
3472 | 3931 | retval = DID_ERROR << 16; |
---|
3473 | 3932 | goto cleanup; |
---|
.. | .. |
---|
3475 | 3934 | sdev_printk(KERN_INFO, scp->device, "%s: compare_write: cdb " |
---|
3476 | 3935 | "indicated=%u, IO sent=%d bytes\n", my_name, |
---|
3477 | 3936 | dnum * lb_size, ret); |
---|
3478 | | - if (!comp_write_worker(lba, num, arr)) { |
---|
| 3937 | + if (!comp_write_worker(sip, lba, num, arr, false)) { |
---|
3479 | 3938 | mk_sense_buffer(scp, MISCOMPARE, MISCOMPARE_VERIFY_ASC, 0); |
---|
3480 | 3939 | retval = check_condition_result; |
---|
3481 | 3940 | goto cleanup; |
---|
3482 | 3941 | } |
---|
3483 | 3942 | if (scsi_debug_lbp()) |
---|
3484 | | - map_region(lba, num); |
---|
| 3943 | + map_region(sip, lba, num); |
---|
3485 | 3944 | cleanup: |
---|
3486 | | - write_unlock_irqrestore(&atomic_rw, iflags); |
---|
| 3945 | + write_unlock(macc_lckp); |
---|
3487 | 3946 | kfree(arr); |
---|
3488 | 3947 | return retval; |
---|
3489 | 3948 | } |
---|
.. | .. |
---|
3498 | 3957 | { |
---|
3499 | 3958 | unsigned char *buf; |
---|
3500 | 3959 | struct unmap_block_desc *desc; |
---|
| 3960 | + struct sdeb_store_info *sip = devip2sip(devip, true); |
---|
| 3961 | + rwlock_t *macc_lckp = &sip->macc_lck; |
---|
3501 | 3962 | unsigned int i, payload_len, descriptors; |
---|
3502 | 3963 | int ret; |
---|
3503 | | - unsigned long iflags; |
---|
3504 | | - |
---|
3505 | 3964 | |
---|
3506 | 3965 | if (!scsi_debug_lbp()) |
---|
3507 | 3966 | return 0; /* fib and say its done */ |
---|
.. | .. |
---|
3528 | 3987 | |
---|
3529 | 3988 | desc = (void *)&buf[8]; |
---|
3530 | 3989 | |
---|
3531 | | - write_lock_irqsave(&atomic_rw, iflags); |
---|
| 3990 | + write_lock(macc_lckp); |
---|
3532 | 3991 | |
---|
3533 | 3992 | for (i = 0 ; i < descriptors ; i++) { |
---|
3534 | 3993 | unsigned long long lba = get_unaligned_be64(&desc[i].lba); |
---|
3535 | 3994 | unsigned int num = get_unaligned_be32(&desc[i].blocks); |
---|
3536 | 3995 | |
---|
3537 | | - ret = check_device_access_params(scp, lba, num); |
---|
| 3996 | + ret = check_device_access_params(scp, lba, num, true); |
---|
3538 | 3997 | if (ret) |
---|
3539 | 3998 | goto out; |
---|
3540 | 3999 | |
---|
3541 | | - unmap_region(lba, num); |
---|
| 4000 | + unmap_region(sip, lba, num); |
---|
3542 | 4001 | } |
---|
3543 | 4002 | |
---|
3544 | 4003 | ret = 0; |
---|
3545 | 4004 | |
---|
3546 | 4005 | out: |
---|
3547 | | - write_unlock_irqrestore(&atomic_rw, iflags); |
---|
| 4006 | + write_unlock(macc_lckp); |
---|
3548 | 4007 | kfree(buf); |
---|
3549 | 4008 | |
---|
3550 | 4009 | return ret; |
---|
.. | .. |
---|
3558 | 4017 | u8 *cmd = scp->cmnd; |
---|
3559 | 4018 | u64 lba; |
---|
3560 | 4019 | u32 alloc_len, mapped, num; |
---|
3561 | | - u8 arr[SDEBUG_GET_LBA_STATUS_LEN]; |
---|
3562 | 4020 | int ret; |
---|
| 4021 | + u8 arr[SDEBUG_GET_LBA_STATUS_LEN]; |
---|
3563 | 4022 | |
---|
3564 | 4023 | lba = get_unaligned_be64(cmd + 2); |
---|
3565 | 4024 | alloc_len = get_unaligned_be32(cmd + 10); |
---|
.. | .. |
---|
3567 | 4026 | if (alloc_len < 24) |
---|
3568 | 4027 | return 0; |
---|
3569 | 4028 | |
---|
3570 | | - ret = check_device_access_params(scp, lba, 1); |
---|
| 4029 | + ret = check_device_access_params(scp, lba, 1, false); |
---|
3571 | 4030 | if (ret) |
---|
3572 | 4031 | return ret; |
---|
3573 | 4032 | |
---|
3574 | | - if (scsi_debug_lbp()) |
---|
3575 | | - mapped = map_state(lba, &num); |
---|
3576 | | - else { |
---|
| 4033 | + if (scsi_debug_lbp()) { |
---|
| 4034 | + struct sdeb_store_info *sip = devip2sip(devip, true); |
---|
| 4035 | + |
---|
| 4036 | + mapped = map_state(sip, lba, &num); |
---|
| 4037 | + } else { |
---|
3577 | 4038 | mapped = 1; |
---|
3578 | 4039 | /* following just in case virtual_gb changed */ |
---|
3579 | 4040 | sdebug_capacity = get_sdebug_capacity(); |
---|
.. | .. |
---|
3611 | 4072 | mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); |
---|
3612 | 4073 | return check_condition_result; |
---|
3613 | 4074 | } |
---|
3614 | | - if (!write_since_sync || cmd[1] & 0x2) |
---|
| 4075 | + if (!write_since_sync || (cmd[1] & 0x2)) |
---|
3615 | 4076 | res = SDEG_RES_IMMED_MASK; |
---|
3616 | 4077 | else /* delay if write_since_sync and IMMED clear */ |
---|
3617 | 4078 | write_since_sync = false; |
---|
3618 | 4079 | return res; |
---|
| 4080 | +} |
---|
| 4081 | + |
---|
| 4082 | +/* |
---|
| 4083 | + * Assuming the LBA+num_blocks is not out-of-range, this function will return |
---|
| 4084 | + * CONDITION MET if the specified blocks will/have fitted in the cache, and |
---|
| 4085 | + * a GOOD status otherwise. Model a disk with a big cache and yield |
---|
| 4086 | + * CONDITION MET. Actually tries to bring range in main memory into the |
---|
| 4087 | + * cache associated with the CPU(s). |
---|
| 4088 | + */ |
---|
| 4089 | +static int resp_pre_fetch(struct scsi_cmnd *scp, |
---|
| 4090 | + struct sdebug_dev_info *devip) |
---|
| 4091 | +{ |
---|
| 4092 | + int res = 0; |
---|
| 4093 | + u64 lba; |
---|
| 4094 | + u64 block, rest = 0; |
---|
| 4095 | + u32 nblks; |
---|
| 4096 | + u8 *cmd = scp->cmnd; |
---|
| 4097 | + struct sdeb_store_info *sip = devip2sip(devip, true); |
---|
| 4098 | + rwlock_t *macc_lckp = &sip->macc_lck; |
---|
| 4099 | + u8 *fsp = sip->storep; |
---|
| 4100 | + |
---|
| 4101 | + if (cmd[0] == PRE_FETCH) { /* 10 byte cdb */ |
---|
| 4102 | + lba = get_unaligned_be32(cmd + 2); |
---|
| 4103 | + nblks = get_unaligned_be16(cmd + 7); |
---|
| 4104 | + } else { /* PRE-FETCH(16) */ |
---|
| 4105 | + lba = get_unaligned_be64(cmd + 2); |
---|
| 4106 | + nblks = get_unaligned_be32(cmd + 10); |
---|
| 4107 | + } |
---|
| 4108 | + if (lba + nblks > sdebug_capacity) { |
---|
| 4109 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); |
---|
| 4110 | + return check_condition_result; |
---|
| 4111 | + } |
---|
| 4112 | + if (!fsp) |
---|
| 4113 | + goto fini; |
---|
| 4114 | + /* PRE-FETCH spec says nothing about LBP or PI so skip them */ |
---|
| 4115 | + block = do_div(lba, sdebug_store_sectors); |
---|
| 4116 | + if (block + nblks > sdebug_store_sectors) |
---|
| 4117 | + rest = block + nblks - sdebug_store_sectors; |
---|
| 4118 | + |
---|
| 4119 | + /* Try to bring the PRE-FETCH range into CPU's cache */ |
---|
| 4120 | + read_lock(macc_lckp); |
---|
| 4121 | + prefetch_range(fsp + (sdebug_sector_size * block), |
---|
| 4122 | + (nblks - rest) * sdebug_sector_size); |
---|
| 4123 | + if (rest) |
---|
| 4124 | + prefetch_range(fsp, rest * sdebug_sector_size); |
---|
| 4125 | + read_unlock(macc_lckp); |
---|
| 4126 | +fini: |
---|
| 4127 | + if (cmd[1] & 0x2) |
---|
| 4128 | + res = SDEG_RES_IMMED_MASK; |
---|
| 4129 | + return res | condition_met_result; |
---|
3619 | 4130 | } |
---|
3620 | 4131 | |
---|
3621 | 4132 | #define RL_BUCKET_ELEMS 8 |
---|
.. | .. |
---|
3701 | 4212 | if ((k * RL_BUCKET_ELEMS) + j > lun_cnt) |
---|
3702 | 4213 | break; |
---|
3703 | 4214 | int_to_scsilun(lun++, lun_p); |
---|
| 4215 | + if (lun > 1 && sdebug_lun_am == SAM_LUN_AM_FLAT) |
---|
| 4216 | + lun_p->scsi_lun[0] |= 0x40; |
---|
3704 | 4217 | } |
---|
3705 | 4218 | if (j < RL_BUCKET_ELEMS) |
---|
3706 | 4219 | break; |
---|
.. | .. |
---|
3719 | 4232 | return res; |
---|
3720 | 4233 | } |
---|
3721 | 4234 | |
---|
3722 | | -static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, |
---|
3723 | | - unsigned int num, struct sdebug_dev_info *devip) |
---|
| 4235 | +static int resp_verify(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) |
---|
3724 | 4236 | { |
---|
3725 | | - int j; |
---|
3726 | | - unsigned char *kaddr, *buf; |
---|
3727 | | - unsigned int offset; |
---|
3728 | | - struct scsi_data_buffer *sdb = scsi_in(scp); |
---|
3729 | | - struct sg_mapping_iter miter; |
---|
| 4237 | + bool is_bytchk3 = false; |
---|
| 4238 | + u8 bytchk; |
---|
| 4239 | + int ret, j; |
---|
| 4240 | + u32 vnum, a_num, off; |
---|
| 4241 | + const u32 lb_size = sdebug_sector_size; |
---|
| 4242 | + u64 lba; |
---|
| 4243 | + u8 *arr; |
---|
| 4244 | + u8 *cmd = scp->cmnd; |
---|
| 4245 | + struct sdeb_store_info *sip = devip2sip(devip, true); |
---|
| 4246 | + rwlock_t *macc_lckp = &sip->macc_lck; |
---|
3730 | 4247 | |
---|
3731 | | - /* better not to use temporary buffer. */ |
---|
3732 | | - buf = kzalloc(scsi_bufflen(scp), GFP_ATOMIC); |
---|
3733 | | - if (!buf) { |
---|
| 4248 | + bytchk = (cmd[1] >> 1) & 0x3; |
---|
| 4249 | + if (bytchk == 0) { |
---|
| 4250 | + return 0; /* always claim internal verify okay */ |
---|
| 4251 | + } else if (bytchk == 2) { |
---|
| 4252 | + mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 2); |
---|
| 4253 | + return check_condition_result; |
---|
| 4254 | + } else if (bytchk == 3) { |
---|
| 4255 | + is_bytchk3 = true; /* 1 block sent, compared repeatedly */ |
---|
| 4256 | + } |
---|
| 4257 | + switch (cmd[0]) { |
---|
| 4258 | + case VERIFY_16: |
---|
| 4259 | + lba = get_unaligned_be64(cmd + 2); |
---|
| 4260 | + vnum = get_unaligned_be32(cmd + 10); |
---|
| 4261 | + break; |
---|
| 4262 | + case VERIFY: /* is VERIFY(10) */ |
---|
| 4263 | + lba = get_unaligned_be32(cmd + 2); |
---|
| 4264 | + vnum = get_unaligned_be16(cmd + 7); |
---|
| 4265 | + break; |
---|
| 4266 | + default: |
---|
| 4267 | + mk_sense_invalid_opcode(scp); |
---|
| 4268 | + return check_condition_result; |
---|
| 4269 | + } |
---|
| 4270 | + if (vnum == 0) |
---|
| 4271 | + return 0; /* not an error */ |
---|
| 4272 | + a_num = is_bytchk3 ? 1 : vnum; |
---|
| 4273 | + /* Treat following check like one for read (i.e. no write) access */ |
---|
| 4274 | + ret = check_device_access_params(scp, lba, a_num, false); |
---|
| 4275 | + if (ret) |
---|
| 4276 | + return ret; |
---|
| 4277 | + |
---|
| 4278 | + arr = kcalloc(lb_size, vnum, GFP_ATOMIC | __GFP_NOWARN); |
---|
| 4279 | + if (!arr) { |
---|
3734 | 4280 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, |
---|
3735 | 4281 | INSUFF_RES_ASCQ); |
---|
3736 | 4282 | return check_condition_result; |
---|
3737 | 4283 | } |
---|
| 4284 | + /* Not changing store, so only need read access */ |
---|
| 4285 | + read_lock(macc_lckp); |
---|
3738 | 4286 | |
---|
3739 | | - scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp)); |
---|
3740 | | - |
---|
3741 | | - offset = 0; |
---|
3742 | | - sg_miter_start(&miter, sdb->table.sgl, sdb->table.nents, |
---|
3743 | | - SG_MITER_ATOMIC | SG_MITER_TO_SG); |
---|
3744 | | - |
---|
3745 | | - while (sg_miter_next(&miter)) { |
---|
3746 | | - kaddr = miter.addr; |
---|
3747 | | - for (j = 0; j < miter.length; j++) |
---|
3748 | | - *(kaddr + j) ^= *(buf + offset + j); |
---|
3749 | | - |
---|
3750 | | - offset += miter.length; |
---|
| 4287 | + ret = do_dout_fetch(scp, a_num, arr); |
---|
| 4288 | + if (ret == -1) { |
---|
| 4289 | + ret = DID_ERROR << 16; |
---|
| 4290 | + goto cleanup; |
---|
| 4291 | + } else if (sdebug_verbose && (ret < (a_num * lb_size))) { |
---|
| 4292 | + sdev_printk(KERN_INFO, scp->device, |
---|
| 4293 | + "%s: %s: cdb indicated=%u, IO sent=%d bytes\n", |
---|
| 4294 | + my_name, __func__, a_num * lb_size, ret); |
---|
3751 | 4295 | } |
---|
3752 | | - sg_miter_stop(&miter); |
---|
3753 | | - kfree(buf); |
---|
3754 | | - |
---|
3755 | | - return 0; |
---|
| 4296 | + if (is_bytchk3) { |
---|
| 4297 | + for (j = 1, off = lb_size; j < vnum; ++j, off += lb_size) |
---|
| 4298 | + memcpy(arr + off, arr, lb_size); |
---|
| 4299 | + } |
---|
| 4300 | + ret = 0; |
---|
| 4301 | + if (!comp_write_worker(sip, lba, vnum, arr, true)) { |
---|
| 4302 | + mk_sense_buffer(scp, MISCOMPARE, MISCOMPARE_VERIFY_ASC, 0); |
---|
| 4303 | + ret = check_condition_result; |
---|
| 4304 | + goto cleanup; |
---|
| 4305 | + } |
---|
| 4306 | +cleanup: |
---|
| 4307 | + read_unlock(macc_lckp); |
---|
| 4308 | + kfree(arr); |
---|
| 4309 | + return ret; |
---|
3756 | 4310 | } |
---|
3757 | 4311 | |
---|
3758 | | -static int resp_xdwriteread_10(struct scsi_cmnd *scp, |
---|
3759 | | - struct sdebug_dev_info *devip) |
---|
3760 | | -{ |
---|
3761 | | - u8 *cmd = scp->cmnd; |
---|
3762 | | - u64 lba; |
---|
3763 | | - u32 num; |
---|
3764 | | - int errsts; |
---|
| 4312 | +#define RZONES_DESC_HD 64 |
---|
3765 | 4313 | |
---|
3766 | | - if (!scsi_bidi_cmnd(scp)) { |
---|
| 4314 | +/* Report zones depending on start LBA nad reporting options */ |
---|
| 4315 | +static int resp_report_zones(struct scsi_cmnd *scp, |
---|
| 4316 | + struct sdebug_dev_info *devip) |
---|
| 4317 | +{ |
---|
| 4318 | + unsigned int i, max_zones, rep_max_zones, nrz = 0; |
---|
| 4319 | + int ret = 0; |
---|
| 4320 | + u32 alloc_len, rep_opts, rep_len; |
---|
| 4321 | + bool partial; |
---|
| 4322 | + u64 lba, zs_lba; |
---|
| 4323 | + u8 *arr = NULL, *desc; |
---|
| 4324 | + u8 *cmd = scp->cmnd; |
---|
| 4325 | + struct sdeb_zone_state *zsp; |
---|
| 4326 | + struct sdeb_store_info *sip = devip2sip(devip, false); |
---|
| 4327 | + rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck; |
---|
| 4328 | + |
---|
| 4329 | + if (!sdebug_dev_is_zoned(devip)) { |
---|
| 4330 | + mk_sense_invalid_opcode(scp); |
---|
| 4331 | + return check_condition_result; |
---|
| 4332 | + } |
---|
| 4333 | + zs_lba = get_unaligned_be64(cmd + 2); |
---|
| 4334 | + alloc_len = get_unaligned_be32(cmd + 10); |
---|
| 4335 | + if (alloc_len == 0) |
---|
| 4336 | + return 0; /* not an error */ |
---|
| 4337 | + rep_opts = cmd[14] & 0x3f; |
---|
| 4338 | + partial = cmd[14] & 0x80; |
---|
| 4339 | + |
---|
| 4340 | + if (zs_lba >= sdebug_capacity) { |
---|
| 4341 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); |
---|
| 4342 | + return check_condition_result; |
---|
| 4343 | + } |
---|
| 4344 | + |
---|
| 4345 | + max_zones = devip->nr_zones - (zs_lba >> devip->zsize_shift); |
---|
| 4346 | + rep_max_zones = min((alloc_len - 64) >> ilog2(RZONES_DESC_HD), |
---|
| 4347 | + max_zones); |
---|
| 4348 | + |
---|
| 4349 | + arr = kzalloc(alloc_len, GFP_ATOMIC | __GFP_NOWARN); |
---|
| 4350 | + if (!arr) { |
---|
3767 | 4351 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, |
---|
3768 | 4352 | INSUFF_RES_ASCQ); |
---|
3769 | 4353 | return check_condition_result; |
---|
3770 | 4354 | } |
---|
3771 | | - errsts = resp_read_dt0(scp, devip); |
---|
3772 | | - if (errsts) |
---|
3773 | | - return errsts; |
---|
3774 | | - if (!(cmd[1] & 0x4)) { /* DISABLE_WRITE is not set */ |
---|
3775 | | - errsts = resp_write_dt0(scp, devip); |
---|
3776 | | - if (errsts) |
---|
3777 | | - return errsts; |
---|
| 4355 | + |
---|
| 4356 | + read_lock(macc_lckp); |
---|
| 4357 | + |
---|
| 4358 | + desc = arr + 64; |
---|
| 4359 | + for (i = 0; i < max_zones; i++) { |
---|
| 4360 | + lba = zs_lba + devip->zsize * i; |
---|
| 4361 | + if (lba > sdebug_capacity) |
---|
| 4362 | + break; |
---|
| 4363 | + zsp = zbc_zone(devip, lba); |
---|
| 4364 | + switch (rep_opts) { |
---|
| 4365 | + case 0x00: |
---|
| 4366 | + /* All zones */ |
---|
| 4367 | + break; |
---|
| 4368 | + case 0x01: |
---|
| 4369 | + /* Empty zones */ |
---|
| 4370 | + if (zsp->z_cond != ZC1_EMPTY) |
---|
| 4371 | + continue; |
---|
| 4372 | + break; |
---|
| 4373 | + case 0x02: |
---|
| 4374 | + /* Implicit open zones */ |
---|
| 4375 | + if (zsp->z_cond != ZC2_IMPLICIT_OPEN) |
---|
| 4376 | + continue; |
---|
| 4377 | + break; |
---|
| 4378 | + case 0x03: |
---|
| 4379 | + /* Explicit open zones */ |
---|
| 4380 | + if (zsp->z_cond != ZC3_EXPLICIT_OPEN) |
---|
| 4381 | + continue; |
---|
| 4382 | + break; |
---|
| 4383 | + case 0x04: |
---|
| 4384 | + /* Closed zones */ |
---|
| 4385 | + if (zsp->z_cond != ZC4_CLOSED) |
---|
| 4386 | + continue; |
---|
| 4387 | + break; |
---|
| 4388 | + case 0x05: |
---|
| 4389 | + /* Full zones */ |
---|
| 4390 | + if (zsp->z_cond != ZC5_FULL) |
---|
| 4391 | + continue; |
---|
| 4392 | + break; |
---|
| 4393 | + case 0x06: |
---|
| 4394 | + case 0x07: |
---|
| 4395 | + case 0x10: |
---|
| 4396 | + /* |
---|
| 4397 | + * Read-only, offline, reset WP recommended are |
---|
| 4398 | + * not emulated: no zones to report; |
---|
| 4399 | + */ |
---|
| 4400 | + continue; |
---|
| 4401 | + case 0x11: |
---|
| 4402 | + /* non-seq-resource set */ |
---|
| 4403 | + if (!zsp->z_non_seq_resource) |
---|
| 4404 | + continue; |
---|
| 4405 | + break; |
---|
| 4406 | + case 0x3f: |
---|
| 4407 | + /* Not write pointer (conventional) zones */ |
---|
| 4408 | + if (!zbc_zone_is_conv(zsp)) |
---|
| 4409 | + continue; |
---|
| 4410 | + break; |
---|
| 4411 | + default: |
---|
| 4412 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, |
---|
| 4413 | + INVALID_FIELD_IN_CDB, 0); |
---|
| 4414 | + ret = check_condition_result; |
---|
| 4415 | + goto fini; |
---|
| 4416 | + } |
---|
| 4417 | + |
---|
| 4418 | + if (nrz < rep_max_zones) { |
---|
| 4419 | + /* Fill zone descriptor */ |
---|
| 4420 | + desc[0] = zsp->z_type; |
---|
| 4421 | + desc[1] = zsp->z_cond << 4; |
---|
| 4422 | + if (zsp->z_non_seq_resource) |
---|
| 4423 | + desc[1] |= 1 << 1; |
---|
| 4424 | + put_unaligned_be64((u64)zsp->z_size, desc + 8); |
---|
| 4425 | + put_unaligned_be64((u64)zsp->z_start, desc + 16); |
---|
| 4426 | + put_unaligned_be64((u64)zsp->z_wp, desc + 24); |
---|
| 4427 | + desc += 64; |
---|
| 4428 | + } |
---|
| 4429 | + |
---|
| 4430 | + if (partial && nrz >= rep_max_zones) |
---|
| 4431 | + break; |
---|
| 4432 | + |
---|
| 4433 | + nrz++; |
---|
3778 | 4434 | } |
---|
3779 | | - lba = get_unaligned_be32(cmd + 2); |
---|
3780 | | - num = get_unaligned_be16(cmd + 7); |
---|
3781 | | - return resp_xdwriteread(scp, lba, num, devip); |
---|
| 4435 | + |
---|
| 4436 | + /* Report header */ |
---|
| 4437 | + put_unaligned_be32(nrz * RZONES_DESC_HD, arr + 0); |
---|
| 4438 | + put_unaligned_be64(sdebug_capacity - 1, arr + 8); |
---|
| 4439 | + |
---|
| 4440 | + rep_len = (unsigned long)desc - (unsigned long)arr; |
---|
| 4441 | + ret = fill_from_dev_buffer(scp, arr, min_t(u32, alloc_len, rep_len)); |
---|
| 4442 | + |
---|
| 4443 | +fini: |
---|
| 4444 | + read_unlock(macc_lckp); |
---|
| 4445 | + kfree(arr); |
---|
| 4446 | + return ret; |
---|
| 4447 | +} |
---|
| 4448 | + |
---|
| 4449 | +/* Logic transplanted from tcmu-runner, file_zbc.c */ |
---|
| 4450 | +static void zbc_open_all(struct sdebug_dev_info *devip) |
---|
| 4451 | +{ |
---|
| 4452 | + struct sdeb_zone_state *zsp = &devip->zstate[0]; |
---|
| 4453 | + unsigned int i; |
---|
| 4454 | + |
---|
| 4455 | + for (i = 0; i < devip->nr_zones; i++, zsp++) { |
---|
| 4456 | + if (zsp->z_cond == ZC4_CLOSED) |
---|
| 4457 | + zbc_open_zone(devip, &devip->zstate[i], true); |
---|
| 4458 | + } |
---|
| 4459 | +} |
---|
| 4460 | + |
---|
| 4461 | +static int resp_open_zone(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) |
---|
| 4462 | +{ |
---|
| 4463 | + int res = 0; |
---|
| 4464 | + u64 z_id; |
---|
| 4465 | + enum sdebug_z_cond zc; |
---|
| 4466 | + u8 *cmd = scp->cmnd; |
---|
| 4467 | + struct sdeb_zone_state *zsp; |
---|
| 4468 | + bool all = cmd[14] & 0x01; |
---|
| 4469 | + struct sdeb_store_info *sip = devip2sip(devip, false); |
---|
| 4470 | + rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck; |
---|
| 4471 | + |
---|
| 4472 | + if (!sdebug_dev_is_zoned(devip)) { |
---|
| 4473 | + mk_sense_invalid_opcode(scp); |
---|
| 4474 | + return check_condition_result; |
---|
| 4475 | + } |
---|
| 4476 | + |
---|
| 4477 | + write_lock(macc_lckp); |
---|
| 4478 | + |
---|
| 4479 | + if (all) { |
---|
| 4480 | + /* Check if all closed zones can be open */ |
---|
| 4481 | + if (devip->max_open && |
---|
| 4482 | + devip->nr_exp_open + devip->nr_closed > devip->max_open) { |
---|
| 4483 | + mk_sense_buffer(scp, DATA_PROTECT, INSUFF_RES_ASC, |
---|
| 4484 | + INSUFF_ZONE_ASCQ); |
---|
| 4485 | + res = check_condition_result; |
---|
| 4486 | + goto fini; |
---|
| 4487 | + } |
---|
| 4488 | + /* Open all closed zones */ |
---|
| 4489 | + zbc_open_all(devip); |
---|
| 4490 | + goto fini; |
---|
| 4491 | + } |
---|
| 4492 | + |
---|
| 4493 | + /* Open the specified zone */ |
---|
| 4494 | + z_id = get_unaligned_be64(cmd + 2); |
---|
| 4495 | + if (z_id >= sdebug_capacity) { |
---|
| 4496 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); |
---|
| 4497 | + res = check_condition_result; |
---|
| 4498 | + goto fini; |
---|
| 4499 | + } |
---|
| 4500 | + |
---|
| 4501 | + zsp = zbc_zone(devip, z_id); |
---|
| 4502 | + if (z_id != zsp->z_start) { |
---|
| 4503 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
---|
| 4504 | + res = check_condition_result; |
---|
| 4505 | + goto fini; |
---|
| 4506 | + } |
---|
| 4507 | + if (zbc_zone_is_conv(zsp)) { |
---|
| 4508 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
---|
| 4509 | + res = check_condition_result; |
---|
| 4510 | + goto fini; |
---|
| 4511 | + } |
---|
| 4512 | + |
---|
| 4513 | + zc = zsp->z_cond; |
---|
| 4514 | + if (zc == ZC3_EXPLICIT_OPEN || zc == ZC5_FULL) |
---|
| 4515 | + goto fini; |
---|
| 4516 | + |
---|
| 4517 | + if (devip->max_open && devip->nr_exp_open >= devip->max_open) { |
---|
| 4518 | + mk_sense_buffer(scp, DATA_PROTECT, INSUFF_RES_ASC, |
---|
| 4519 | + INSUFF_ZONE_ASCQ); |
---|
| 4520 | + res = check_condition_result; |
---|
| 4521 | + goto fini; |
---|
| 4522 | + } |
---|
| 4523 | + |
---|
| 4524 | + zbc_open_zone(devip, zsp, true); |
---|
| 4525 | +fini: |
---|
| 4526 | + write_unlock(macc_lckp); |
---|
| 4527 | + return res; |
---|
| 4528 | +} |
---|
| 4529 | + |
---|
| 4530 | +static void zbc_close_all(struct sdebug_dev_info *devip) |
---|
| 4531 | +{ |
---|
| 4532 | + unsigned int i; |
---|
| 4533 | + |
---|
| 4534 | + for (i = 0; i < devip->nr_zones; i++) |
---|
| 4535 | + zbc_close_zone(devip, &devip->zstate[i]); |
---|
| 4536 | +} |
---|
| 4537 | + |
---|
| 4538 | +static int resp_close_zone(struct scsi_cmnd *scp, |
---|
| 4539 | + struct sdebug_dev_info *devip) |
---|
| 4540 | +{ |
---|
| 4541 | + int res = 0; |
---|
| 4542 | + u64 z_id; |
---|
| 4543 | + u8 *cmd = scp->cmnd; |
---|
| 4544 | + struct sdeb_zone_state *zsp; |
---|
| 4545 | + bool all = cmd[14] & 0x01; |
---|
| 4546 | + struct sdeb_store_info *sip = devip2sip(devip, false); |
---|
| 4547 | + rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck; |
---|
| 4548 | + |
---|
| 4549 | + if (!sdebug_dev_is_zoned(devip)) { |
---|
| 4550 | + mk_sense_invalid_opcode(scp); |
---|
| 4551 | + return check_condition_result; |
---|
| 4552 | + } |
---|
| 4553 | + |
---|
| 4554 | + write_lock(macc_lckp); |
---|
| 4555 | + |
---|
| 4556 | + if (all) { |
---|
| 4557 | + zbc_close_all(devip); |
---|
| 4558 | + goto fini; |
---|
| 4559 | + } |
---|
| 4560 | + |
---|
| 4561 | + /* Close specified zone */ |
---|
| 4562 | + z_id = get_unaligned_be64(cmd + 2); |
---|
| 4563 | + if (z_id >= sdebug_capacity) { |
---|
| 4564 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); |
---|
| 4565 | + res = check_condition_result; |
---|
| 4566 | + goto fini; |
---|
| 4567 | + } |
---|
| 4568 | + |
---|
| 4569 | + zsp = zbc_zone(devip, z_id); |
---|
| 4570 | + if (z_id != zsp->z_start) { |
---|
| 4571 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
---|
| 4572 | + res = check_condition_result; |
---|
| 4573 | + goto fini; |
---|
| 4574 | + } |
---|
| 4575 | + if (zbc_zone_is_conv(zsp)) { |
---|
| 4576 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
---|
| 4577 | + res = check_condition_result; |
---|
| 4578 | + goto fini; |
---|
| 4579 | + } |
---|
| 4580 | + |
---|
| 4581 | + zbc_close_zone(devip, zsp); |
---|
| 4582 | +fini: |
---|
| 4583 | + write_unlock(macc_lckp); |
---|
| 4584 | + return res; |
---|
| 4585 | +} |
---|
| 4586 | + |
---|
| 4587 | +static void zbc_finish_zone(struct sdebug_dev_info *devip, |
---|
| 4588 | + struct sdeb_zone_state *zsp, bool empty) |
---|
| 4589 | +{ |
---|
| 4590 | + enum sdebug_z_cond zc = zsp->z_cond; |
---|
| 4591 | + |
---|
| 4592 | + if (zc == ZC4_CLOSED || zc == ZC2_IMPLICIT_OPEN || |
---|
| 4593 | + zc == ZC3_EXPLICIT_OPEN || (empty && zc == ZC1_EMPTY)) { |
---|
| 4594 | + if (zc == ZC2_IMPLICIT_OPEN || zc == ZC3_EXPLICIT_OPEN) |
---|
| 4595 | + zbc_close_zone(devip, zsp); |
---|
| 4596 | + if (zsp->z_cond == ZC4_CLOSED) |
---|
| 4597 | + devip->nr_closed--; |
---|
| 4598 | + zsp->z_wp = zsp->z_start + zsp->z_size; |
---|
| 4599 | + zsp->z_cond = ZC5_FULL; |
---|
| 4600 | + } |
---|
| 4601 | +} |
---|
| 4602 | + |
---|
| 4603 | +static void zbc_finish_all(struct sdebug_dev_info *devip) |
---|
| 4604 | +{ |
---|
| 4605 | + unsigned int i; |
---|
| 4606 | + |
---|
| 4607 | + for (i = 0; i < devip->nr_zones; i++) |
---|
| 4608 | + zbc_finish_zone(devip, &devip->zstate[i], false); |
---|
| 4609 | +} |
---|
| 4610 | + |
---|
| 4611 | +static int resp_finish_zone(struct scsi_cmnd *scp, |
---|
| 4612 | + struct sdebug_dev_info *devip) |
---|
| 4613 | +{ |
---|
| 4614 | + struct sdeb_zone_state *zsp; |
---|
| 4615 | + int res = 0; |
---|
| 4616 | + u64 z_id; |
---|
| 4617 | + u8 *cmd = scp->cmnd; |
---|
| 4618 | + bool all = cmd[14] & 0x01; |
---|
| 4619 | + struct sdeb_store_info *sip = devip2sip(devip, false); |
---|
| 4620 | + rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck; |
---|
| 4621 | + |
---|
| 4622 | + if (!sdebug_dev_is_zoned(devip)) { |
---|
| 4623 | + mk_sense_invalid_opcode(scp); |
---|
| 4624 | + return check_condition_result; |
---|
| 4625 | + } |
---|
| 4626 | + |
---|
| 4627 | + write_lock(macc_lckp); |
---|
| 4628 | + |
---|
| 4629 | + if (all) { |
---|
| 4630 | + zbc_finish_all(devip); |
---|
| 4631 | + goto fini; |
---|
| 4632 | + } |
---|
| 4633 | + |
---|
| 4634 | + /* Finish the specified zone */ |
---|
| 4635 | + z_id = get_unaligned_be64(cmd + 2); |
---|
| 4636 | + if (z_id >= sdebug_capacity) { |
---|
| 4637 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); |
---|
| 4638 | + res = check_condition_result; |
---|
| 4639 | + goto fini; |
---|
| 4640 | + } |
---|
| 4641 | + |
---|
| 4642 | + zsp = zbc_zone(devip, z_id); |
---|
| 4643 | + if (z_id != zsp->z_start) { |
---|
| 4644 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
---|
| 4645 | + res = check_condition_result; |
---|
| 4646 | + goto fini; |
---|
| 4647 | + } |
---|
| 4648 | + if (zbc_zone_is_conv(zsp)) { |
---|
| 4649 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
---|
| 4650 | + res = check_condition_result; |
---|
| 4651 | + goto fini; |
---|
| 4652 | + } |
---|
| 4653 | + |
---|
| 4654 | + zbc_finish_zone(devip, zsp, true); |
---|
| 4655 | +fini: |
---|
| 4656 | + write_unlock(macc_lckp); |
---|
| 4657 | + return res; |
---|
| 4658 | +} |
---|
| 4659 | + |
---|
| 4660 | +static void zbc_rwp_zone(struct sdebug_dev_info *devip, |
---|
| 4661 | + struct sdeb_zone_state *zsp) |
---|
| 4662 | +{ |
---|
| 4663 | + enum sdebug_z_cond zc; |
---|
| 4664 | + struct sdeb_store_info *sip = devip2sip(devip, false); |
---|
| 4665 | + |
---|
| 4666 | + if (zbc_zone_is_conv(zsp)) |
---|
| 4667 | + return; |
---|
| 4668 | + |
---|
| 4669 | + zc = zsp->z_cond; |
---|
| 4670 | + if (zc == ZC2_IMPLICIT_OPEN || zc == ZC3_EXPLICIT_OPEN) |
---|
| 4671 | + zbc_close_zone(devip, zsp); |
---|
| 4672 | + |
---|
| 4673 | + if (zsp->z_cond == ZC4_CLOSED) |
---|
| 4674 | + devip->nr_closed--; |
---|
| 4675 | + |
---|
| 4676 | + if (zsp->z_wp > zsp->z_start) |
---|
| 4677 | + memset(sip->storep + zsp->z_start * sdebug_sector_size, 0, |
---|
| 4678 | + (zsp->z_wp - zsp->z_start) * sdebug_sector_size); |
---|
| 4679 | + |
---|
| 4680 | + zsp->z_non_seq_resource = false; |
---|
| 4681 | + zsp->z_wp = zsp->z_start; |
---|
| 4682 | + zsp->z_cond = ZC1_EMPTY; |
---|
| 4683 | +} |
---|
| 4684 | + |
---|
| 4685 | +static void zbc_rwp_all(struct sdebug_dev_info *devip) |
---|
| 4686 | +{ |
---|
| 4687 | + unsigned int i; |
---|
| 4688 | + |
---|
| 4689 | + for (i = 0; i < devip->nr_zones; i++) |
---|
| 4690 | + zbc_rwp_zone(devip, &devip->zstate[i]); |
---|
| 4691 | +} |
---|
| 4692 | + |
---|
| 4693 | +static int resp_rwp_zone(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) |
---|
| 4694 | +{ |
---|
| 4695 | + struct sdeb_zone_state *zsp; |
---|
| 4696 | + int res = 0; |
---|
| 4697 | + u64 z_id; |
---|
| 4698 | + u8 *cmd = scp->cmnd; |
---|
| 4699 | + bool all = cmd[14] & 0x01; |
---|
| 4700 | + struct sdeb_store_info *sip = devip2sip(devip, false); |
---|
| 4701 | + rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck; |
---|
| 4702 | + |
---|
| 4703 | + if (!sdebug_dev_is_zoned(devip)) { |
---|
| 4704 | + mk_sense_invalid_opcode(scp); |
---|
| 4705 | + return check_condition_result; |
---|
| 4706 | + } |
---|
| 4707 | + |
---|
| 4708 | + write_lock(macc_lckp); |
---|
| 4709 | + |
---|
| 4710 | + if (all) { |
---|
| 4711 | + zbc_rwp_all(devip); |
---|
| 4712 | + goto fini; |
---|
| 4713 | + } |
---|
| 4714 | + |
---|
| 4715 | + z_id = get_unaligned_be64(cmd + 2); |
---|
| 4716 | + if (z_id >= sdebug_capacity) { |
---|
| 4717 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); |
---|
| 4718 | + res = check_condition_result; |
---|
| 4719 | + goto fini; |
---|
| 4720 | + } |
---|
| 4721 | + |
---|
| 4722 | + zsp = zbc_zone(devip, z_id); |
---|
| 4723 | + if (z_id != zsp->z_start) { |
---|
| 4724 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
---|
| 4725 | + res = check_condition_result; |
---|
| 4726 | + goto fini; |
---|
| 4727 | + } |
---|
| 4728 | + if (zbc_zone_is_conv(zsp)) { |
---|
| 4729 | + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
---|
| 4730 | + res = check_condition_result; |
---|
| 4731 | + goto fini; |
---|
| 4732 | + } |
---|
| 4733 | + |
---|
| 4734 | + zbc_rwp_zone(devip, zsp); |
---|
| 4735 | +fini: |
---|
| 4736 | + write_unlock(macc_lckp); |
---|
| 4737 | + return res; |
---|
3782 | 4738 | } |
---|
3783 | 4739 | |
---|
3784 | 4740 | static struct sdebug_queue *get_queue(struct scsi_cmnd *cmnd) |
---|
3785 | 4741 | { |
---|
| 4742 | + u16 hwq; |
---|
3786 | 4743 | u32 tag = blk_mq_unique_tag(cmnd->request); |
---|
3787 | | - u16 hwq = blk_mq_unique_tag_to_hwq(tag); |
---|
| 4744 | + |
---|
| 4745 | + hwq = blk_mq_unique_tag_to_hwq(tag); |
---|
3788 | 4746 | |
---|
3789 | 4747 | pr_debug("tag=%#x, hwq=%d\n", tag, hwq); |
---|
3790 | 4748 | if (WARN_ON_ONCE(hwq >= submit_queues)) |
---|
3791 | 4749 | hwq = 0; |
---|
| 4750 | + |
---|
3792 | 4751 | return sdebug_q_arr + hwq; |
---|
| 4752 | +} |
---|
| 4753 | + |
---|
| 4754 | +static u32 get_tag(struct scsi_cmnd *cmnd) |
---|
| 4755 | +{ |
---|
| 4756 | + return blk_mq_unique_tag(cmnd->request); |
---|
3793 | 4757 | } |
---|
3794 | 4758 | |
---|
3795 | 4759 | /* Queued (deferred) command completions converge here. */ |
---|
.. | .. |
---|
3823 | 4787 | scp = sqcp->a_cmnd; |
---|
3824 | 4788 | if (unlikely(scp == NULL)) { |
---|
3825 | 4789 | spin_unlock_irqrestore(&sqp->qc_lock, iflags); |
---|
3826 | | - pr_err("scp is NULL, sqa_idx=%d, qc_idx=%d\n", |
---|
3827 | | - sd_dp->sqa_idx, qc_idx); |
---|
| 4790 | + pr_err("scp is NULL, sqa_idx=%d, qc_idx=%d, hc_idx=%d\n", |
---|
| 4791 | + sd_dp->sqa_idx, qc_idx, sd_dp->hc_idx); |
---|
3828 | 4792 | return; |
---|
3829 | 4793 | } |
---|
3830 | 4794 | devip = (struct sdebug_dev_info *)scp->device->hostdata; |
---|
.. | .. |
---|
3886 | 4850 | static bool got_shared_uuid; |
---|
3887 | 4851 | static uuid_t shared_uuid; |
---|
3888 | 4852 | |
---|
| 4853 | +static int sdebug_device_create_zones(struct sdebug_dev_info *devip) |
---|
| 4854 | +{ |
---|
| 4855 | + struct sdeb_zone_state *zsp; |
---|
| 4856 | + sector_t capacity = get_sdebug_capacity(); |
---|
| 4857 | + sector_t zstart = 0; |
---|
| 4858 | + unsigned int i; |
---|
| 4859 | + |
---|
| 4860 | + /* |
---|
| 4861 | + * Set the zone size: if sdeb_zbc_zone_size_mb is not set, figure out |
---|
| 4862 | + * a zone size allowing for at least 4 zones on the device. Otherwise, |
---|
| 4863 | + * use the specified zone size checking that at least 2 zones can be |
---|
| 4864 | + * created for the device. |
---|
| 4865 | + */ |
---|
| 4866 | + if (!sdeb_zbc_zone_size_mb) { |
---|
| 4867 | + devip->zsize = (DEF_ZBC_ZONE_SIZE_MB * SZ_1M) |
---|
| 4868 | + >> ilog2(sdebug_sector_size); |
---|
| 4869 | + while (capacity < devip->zsize << 2 && devip->zsize >= 2) |
---|
| 4870 | + devip->zsize >>= 1; |
---|
| 4871 | + if (devip->zsize < 2) { |
---|
| 4872 | + pr_err("Device capacity too small\n"); |
---|
| 4873 | + return -EINVAL; |
---|
| 4874 | + } |
---|
| 4875 | + } else { |
---|
| 4876 | + if (!is_power_of_2(sdeb_zbc_zone_size_mb)) { |
---|
| 4877 | + pr_err("Zone size is not a power of 2\n"); |
---|
| 4878 | + return -EINVAL; |
---|
| 4879 | + } |
---|
| 4880 | + devip->zsize = (sdeb_zbc_zone_size_mb * SZ_1M) |
---|
| 4881 | + >> ilog2(sdebug_sector_size); |
---|
| 4882 | + if (devip->zsize >= capacity) { |
---|
| 4883 | + pr_err("Zone size too large for device capacity\n"); |
---|
| 4884 | + return -EINVAL; |
---|
| 4885 | + } |
---|
| 4886 | + } |
---|
| 4887 | + |
---|
| 4888 | + devip->zsize_shift = ilog2(devip->zsize); |
---|
| 4889 | + devip->nr_zones = (capacity + devip->zsize - 1) >> devip->zsize_shift; |
---|
| 4890 | + |
---|
| 4891 | + if (sdeb_zbc_nr_conv >= devip->nr_zones) { |
---|
| 4892 | + pr_err("Number of conventional zones too large\n"); |
---|
| 4893 | + return -EINVAL; |
---|
| 4894 | + } |
---|
| 4895 | + devip->nr_conv_zones = sdeb_zbc_nr_conv; |
---|
| 4896 | + |
---|
| 4897 | + if (devip->zmodel == BLK_ZONED_HM) { |
---|
| 4898 | + /* zbc_max_open_zones can be 0, meaning "not reported" */ |
---|
| 4899 | + if (sdeb_zbc_max_open >= devip->nr_zones - 1) |
---|
| 4900 | + devip->max_open = (devip->nr_zones - 1) / 2; |
---|
| 4901 | + else |
---|
| 4902 | + devip->max_open = sdeb_zbc_max_open; |
---|
| 4903 | + } |
---|
| 4904 | + |
---|
| 4905 | + devip->zstate = kcalloc(devip->nr_zones, |
---|
| 4906 | + sizeof(struct sdeb_zone_state), GFP_KERNEL); |
---|
| 4907 | + if (!devip->zstate) |
---|
| 4908 | + return -ENOMEM; |
---|
| 4909 | + |
---|
| 4910 | + for (i = 0; i < devip->nr_zones; i++) { |
---|
| 4911 | + zsp = &devip->zstate[i]; |
---|
| 4912 | + |
---|
| 4913 | + zsp->z_start = zstart; |
---|
| 4914 | + |
---|
| 4915 | + if (i < devip->nr_conv_zones) { |
---|
| 4916 | + zsp->z_type = ZBC_ZONE_TYPE_CNV; |
---|
| 4917 | + zsp->z_cond = ZBC_NOT_WRITE_POINTER; |
---|
| 4918 | + zsp->z_wp = (sector_t)-1; |
---|
| 4919 | + } else { |
---|
| 4920 | + if (devip->zmodel == BLK_ZONED_HM) |
---|
| 4921 | + zsp->z_type = ZBC_ZONE_TYPE_SWR; |
---|
| 4922 | + else |
---|
| 4923 | + zsp->z_type = ZBC_ZONE_TYPE_SWP; |
---|
| 4924 | + zsp->z_cond = ZC1_EMPTY; |
---|
| 4925 | + zsp->z_wp = zsp->z_start; |
---|
| 4926 | + } |
---|
| 4927 | + |
---|
| 4928 | + if (zsp->z_start + devip->zsize < capacity) |
---|
| 4929 | + zsp->z_size = devip->zsize; |
---|
| 4930 | + else |
---|
| 4931 | + zsp->z_size = capacity - zsp->z_start; |
---|
| 4932 | + |
---|
| 4933 | + zstart += zsp->z_size; |
---|
| 4934 | + } |
---|
| 4935 | + |
---|
| 4936 | + return 0; |
---|
| 4937 | +} |
---|
| 4938 | + |
---|
3889 | 4939 | static struct sdebug_dev_info *sdebug_device_create( |
---|
3890 | 4940 | struct sdebug_host_info *sdbg_host, gfp_t flags) |
---|
3891 | 4941 | { |
---|
.. | .. |
---|
3905 | 4955 | } |
---|
3906 | 4956 | } |
---|
3907 | 4957 | devip->sdbg_host = sdbg_host; |
---|
| 4958 | + if (sdeb_zbc_in_use) { |
---|
| 4959 | + devip->zmodel = sdeb_zbc_model; |
---|
| 4960 | + if (sdebug_device_create_zones(devip)) { |
---|
| 4961 | + kfree(devip); |
---|
| 4962 | + return NULL; |
---|
| 4963 | + } |
---|
| 4964 | + } else { |
---|
| 4965 | + devip->zmodel = BLK_ZONED_NONE; |
---|
| 4966 | + } |
---|
| 4967 | + devip->sdbg_host = sdbg_host; |
---|
| 4968 | + devip->create_ts = ktime_get_boottime(); |
---|
| 4969 | + atomic_set(&devip->stopped, (sdeb_tur_ms_to_ready > 0 ? 2 : 0)); |
---|
3908 | 4970 | list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list); |
---|
3909 | 4971 | } |
---|
3910 | 4972 | return devip; |
---|
.. | .. |
---|
3921 | 4983 | pr_err("Host info NULL\n"); |
---|
3922 | 4984 | return NULL; |
---|
3923 | 4985 | } |
---|
| 4986 | + |
---|
3924 | 4987 | list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { |
---|
3925 | 4988 | if ((devip->used) && (devip->channel == sdev->channel) && |
---|
3926 | 4989 | (devip->target == sdev->id) && |
---|
.. | .. |
---|
3954 | 5017 | if (sdebug_verbose) |
---|
3955 | 5018 | pr_info("slave_alloc <%u %u %u %llu>\n", |
---|
3956 | 5019 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); |
---|
3957 | | - blk_queue_flag_set(QUEUE_FLAG_BIDI, sdp->request_queue); |
---|
3958 | 5020 | return 0; |
---|
3959 | 5021 | } |
---|
3960 | 5022 | |
---|
.. | .. |
---|
3974 | 5036 | return 1; /* no resources, will be marked offline */ |
---|
3975 | 5037 | } |
---|
3976 | 5038 | sdp->hostdata = devip; |
---|
3977 | | - blk_queue_max_segment_size(sdp->request_queue, -1U); |
---|
3978 | 5039 | if (sdebug_no_uld) |
---|
3979 | 5040 | sdp->no_uld_attach = 1; |
---|
3980 | 5041 | config_cdb_len(sdp); |
---|
.. | .. |
---|
4233 | 5294 | return SUCCESS; |
---|
4234 | 5295 | } |
---|
4235 | 5296 | |
---|
4236 | | -static void __init sdebug_build_parts(unsigned char *ramp, |
---|
4237 | | - unsigned long store_size) |
---|
| 5297 | +static void sdebug_build_parts(unsigned char *ramp, unsigned long store_size) |
---|
4238 | 5298 | { |
---|
4239 | | - struct partition *pp; |
---|
4240 | | - int starts[SDEBUG_MAX_PARTS + 2]; |
---|
| 5299 | + struct msdos_partition *pp; |
---|
| 5300 | + int starts[SDEBUG_MAX_PARTS + 2], max_part_secs; |
---|
4241 | 5301 | int sectors_per_part, num_sectors, k; |
---|
4242 | 5302 | int heads_by_sects, start_sec, end_sec; |
---|
4243 | 5303 | |
---|
.. | .. |
---|
4248 | 5308 | sdebug_num_parts = SDEBUG_MAX_PARTS; |
---|
4249 | 5309 | pr_warn("reducing partitions to %d\n", SDEBUG_MAX_PARTS); |
---|
4250 | 5310 | } |
---|
4251 | | - num_sectors = (int)sdebug_store_sectors; |
---|
| 5311 | + num_sectors = (int)get_sdebug_capacity(); |
---|
4252 | 5312 | sectors_per_part = (num_sectors - sdebug_sectors_per) |
---|
4253 | 5313 | / sdebug_num_parts; |
---|
4254 | 5314 | heads_by_sects = sdebug_heads * sdebug_sectors_per; |
---|
4255 | 5315 | starts[0] = sdebug_sectors_per; |
---|
4256 | | - for (k = 1; k < sdebug_num_parts; ++k) |
---|
| 5316 | + max_part_secs = sectors_per_part; |
---|
| 5317 | + for (k = 1; k < sdebug_num_parts; ++k) { |
---|
4257 | 5318 | starts[k] = ((k * sectors_per_part) / heads_by_sects) |
---|
4258 | 5319 | * heads_by_sects; |
---|
| 5320 | + if (starts[k] - starts[k - 1] < max_part_secs) |
---|
| 5321 | + max_part_secs = starts[k] - starts[k - 1]; |
---|
| 5322 | + } |
---|
4259 | 5323 | starts[sdebug_num_parts] = num_sectors; |
---|
4260 | 5324 | starts[sdebug_num_parts + 1] = 0; |
---|
4261 | 5325 | |
---|
4262 | 5326 | ramp[510] = 0x55; /* magic partition markings */ |
---|
4263 | 5327 | ramp[511] = 0xAA; |
---|
4264 | | - pp = (struct partition *)(ramp + 0x1be); |
---|
| 5328 | + pp = (struct msdos_partition *)(ramp + 0x1be); |
---|
4265 | 5329 | for (k = 0; starts[k + 1]; ++k, ++pp) { |
---|
4266 | 5330 | start_sec = starts[k]; |
---|
4267 | | - end_sec = starts[k + 1] - 1; |
---|
| 5331 | + end_sec = starts[k] + max_part_secs - 1; |
---|
4268 | 5332 | pp->boot_ind = 0; |
---|
4269 | 5333 | |
---|
4270 | 5334 | pp->cyl = start_sec / heads_by_sects; |
---|
.. | .. |
---|
4316 | 5380 | atomic_set(&sdebug_a_tsf, 0); |
---|
4317 | 5381 | } |
---|
4318 | 5382 | |
---|
4319 | | -static void setup_inject(struct sdebug_queue *sqp, |
---|
4320 | | - struct sdebug_queued_cmd *sqcp) |
---|
| 5383 | +static bool inject_on_this_cmd(void) |
---|
4321 | 5384 | { |
---|
4322 | | - if ((atomic_read(&sdebug_cmnd_count) % abs(sdebug_every_nth)) > 0) { |
---|
4323 | | - if (sdebug_every_nth > 0) |
---|
4324 | | - sqcp->inj_recovered = sqcp->inj_transport |
---|
4325 | | - = sqcp->inj_dif |
---|
4326 | | - = sqcp->inj_dix = sqcp->inj_short |
---|
4327 | | - = sqcp->inj_host_busy = sqcp->inj_cmd_abort = 0; |
---|
4328 | | - return; |
---|
4329 | | - } |
---|
4330 | | - sqcp->inj_recovered = !!(SDEBUG_OPT_RECOVERED_ERR & sdebug_opts); |
---|
4331 | | - sqcp->inj_transport = !!(SDEBUG_OPT_TRANSPORT_ERR & sdebug_opts); |
---|
4332 | | - sqcp->inj_dif = !!(SDEBUG_OPT_DIF_ERR & sdebug_opts); |
---|
4333 | | - sqcp->inj_dix = !!(SDEBUG_OPT_DIX_ERR & sdebug_opts); |
---|
4334 | | - sqcp->inj_short = !!(SDEBUG_OPT_SHORT_TRANSFER & sdebug_opts); |
---|
4335 | | - sqcp->inj_host_busy = !!(SDEBUG_OPT_HOST_BUSY & sdebug_opts); |
---|
4336 | | - sqcp->inj_cmd_abort = !!(SDEBUG_OPT_CMD_ABORT & sdebug_opts); |
---|
| 5385 | + if (sdebug_every_nth == 0) |
---|
| 5386 | + return false; |
---|
| 5387 | + return (atomic_read(&sdebug_cmnd_count) % abs(sdebug_every_nth)) == 0; |
---|
4337 | 5388 | } |
---|
| 5389 | + |
---|
| 5390 | +#define INCLUSIVE_TIMING_MAX_NS 1000000 /* 1 millisecond */ |
---|
4338 | 5391 | |
---|
4339 | 5392 | /* Complete the processing of the thread that queued a SCSI command to this |
---|
4340 | 5393 | * driver. It either completes the command by calling cmnd_done() or |
---|
.. | .. |
---|
4347 | 5400 | struct sdebug_dev_info *), |
---|
4348 | 5401 | int delta_jiff, int ndelay) |
---|
4349 | 5402 | { |
---|
| 5403 | + bool new_sd_dp; |
---|
| 5404 | + bool inject = false; |
---|
| 5405 | + int k, num_in_q, qdepth; |
---|
4350 | 5406 | unsigned long iflags; |
---|
4351 | | - int k, num_in_q, qdepth, inject; |
---|
| 5407 | + u64 ns_from_boot = 0; |
---|
4352 | 5408 | struct sdebug_queue *sqp; |
---|
4353 | 5409 | struct sdebug_queued_cmd *sqcp; |
---|
4354 | 5410 | struct scsi_device *sdp; |
---|
.. | .. |
---|
4364 | 5420 | if (delta_jiff == 0) |
---|
4365 | 5421 | goto respond_in_thread; |
---|
4366 | 5422 | |
---|
4367 | | - /* schedule the response at a later time if resources permit */ |
---|
4368 | 5423 | sqp = get_queue(cmnd); |
---|
4369 | 5424 | spin_lock_irqsave(&sqp->qc_lock, iflags); |
---|
4370 | 5425 | if (unlikely(atomic_read(&sqp->blocked))) { |
---|
.. | .. |
---|
4373 | 5428 | } |
---|
4374 | 5429 | num_in_q = atomic_read(&devip->num_in_q); |
---|
4375 | 5430 | qdepth = cmnd->device->queue_depth; |
---|
4376 | | - inject = 0; |
---|
4377 | 5431 | if (unlikely((qdepth > 0) && (num_in_q >= qdepth))) { |
---|
4378 | 5432 | if (scsi_result) { |
---|
4379 | 5433 | spin_unlock_irqrestore(&sqp->qc_lock, iflags); |
---|
.. | .. |
---|
4387 | 5441 | (atomic_inc_return(&sdebug_a_tsf) >= |
---|
4388 | 5442 | abs(sdebug_every_nth))) { |
---|
4389 | 5443 | atomic_set(&sdebug_a_tsf, 0); |
---|
4390 | | - inject = 1; |
---|
| 5444 | + inject = true; |
---|
4391 | 5445 | scsi_result = device_qfull_result; |
---|
4392 | 5446 | } |
---|
4393 | 5447 | } |
---|
.. | .. |
---|
4410 | 5464 | else |
---|
4411 | 5465 | return SCSI_MLQUEUE_HOST_BUSY; |
---|
4412 | 5466 | } |
---|
4413 | | - __set_bit(k, sqp->in_use_bm); |
---|
| 5467 | + set_bit(k, sqp->in_use_bm); |
---|
4414 | 5468 | atomic_inc(&devip->num_in_q); |
---|
4415 | 5469 | sqcp = &sqp->qc_arr[k]; |
---|
4416 | 5470 | sqcp->a_cmnd = cmnd; |
---|
4417 | 5471 | cmnd->host_scribble = (unsigned char *)sqcp; |
---|
4418 | 5472 | sd_dp = sqcp->sd_dp; |
---|
4419 | 5473 | spin_unlock_irqrestore(&sqp->qc_lock, iflags); |
---|
4420 | | - if (unlikely(sdebug_every_nth && sdebug_any_injecting_opt)) |
---|
4421 | | - setup_inject(sqp, sqcp); |
---|
4422 | | - if (sd_dp == NULL) { |
---|
| 5474 | + if (!sd_dp) { |
---|
4423 | 5475 | sd_dp = kzalloc(sizeof(*sd_dp), GFP_ATOMIC); |
---|
4424 | | - if (sd_dp == NULL) |
---|
| 5476 | + if (!sd_dp) { |
---|
| 5477 | + atomic_dec(&devip->num_in_q); |
---|
| 5478 | + clear_bit(k, sqp->in_use_bm); |
---|
4425 | 5479 | return SCSI_MLQUEUE_HOST_BUSY; |
---|
| 5480 | + } |
---|
| 5481 | + new_sd_dp = true; |
---|
| 5482 | + } else { |
---|
| 5483 | + new_sd_dp = false; |
---|
4426 | 5484 | } |
---|
4427 | 5485 | |
---|
4428 | | - cmnd->result = pfp != NULL ? pfp(cmnd, devip) : 0; |
---|
| 5486 | + /* Set the hostwide tag */ |
---|
| 5487 | + if (sdebug_host_max_queue) |
---|
| 5488 | + sd_dp->hc_idx = get_tag(cmnd); |
---|
| 5489 | + |
---|
| 5490 | + if (ndelay > 0 && ndelay < INCLUSIVE_TIMING_MAX_NS) |
---|
| 5491 | + ns_from_boot = ktime_get_boottime_ns(); |
---|
| 5492 | + |
---|
| 5493 | + /* one of the resp_*() response functions is called here */ |
---|
| 5494 | + cmnd->result = pfp ? pfp(cmnd, devip) : 0; |
---|
4429 | 5495 | if (cmnd->result & SDEG_RES_IMMED_MASK) { |
---|
4430 | | - /* |
---|
4431 | | - * This is the F_DELAY_OVERR case. No delay. |
---|
4432 | | - */ |
---|
4433 | 5496 | cmnd->result &= ~SDEG_RES_IMMED_MASK; |
---|
4434 | 5497 | delta_jiff = ndelay = 0; |
---|
4435 | 5498 | } |
---|
4436 | 5499 | if (cmnd->result == 0 && scsi_result != 0) |
---|
4437 | 5500 | cmnd->result = scsi_result; |
---|
| 5501 | + if (cmnd->result == 0 && unlikely(sdebug_opts & SDEBUG_OPT_TRANSPORT_ERR)) { |
---|
| 5502 | + if (atomic_read(&sdeb_inject_pending)) { |
---|
| 5503 | + mk_sense_buffer(cmnd, ABORTED_COMMAND, TRANSPORT_PROBLEM, ACK_NAK_TO); |
---|
| 5504 | + atomic_set(&sdeb_inject_pending, 0); |
---|
| 5505 | + cmnd->result = check_condition_result; |
---|
| 5506 | + } |
---|
| 5507 | + } |
---|
4438 | 5508 | |
---|
4439 | 5509 | if (unlikely(sdebug_verbose && cmnd->result)) |
---|
4440 | 5510 | sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n", |
---|
.. | .. |
---|
4444 | 5514 | ktime_t kt; |
---|
4445 | 5515 | |
---|
4446 | 5516 | if (delta_jiff > 0) { |
---|
4447 | | - kt = ns_to_ktime((u64)delta_jiff * (NSEC_PER_SEC / HZ)); |
---|
4448 | | - } else |
---|
4449 | | - kt = ndelay; |
---|
| 5517 | + u64 ns = jiffies_to_nsecs(delta_jiff); |
---|
| 5518 | + |
---|
| 5519 | + if (sdebug_random && ns < U32_MAX) { |
---|
| 5520 | + ns = prandom_u32_max((u32)ns); |
---|
| 5521 | + } else if (sdebug_random) { |
---|
| 5522 | + ns >>= 12; /* scale to 4 usec precision */ |
---|
| 5523 | + if (ns < U32_MAX) /* over 4 hours max */ |
---|
| 5524 | + ns = prandom_u32_max((u32)ns); |
---|
| 5525 | + ns <<= 12; |
---|
| 5526 | + } |
---|
| 5527 | + kt = ns_to_ktime(ns); |
---|
| 5528 | + } else { /* ndelay has a 4.2 second max */ |
---|
| 5529 | + kt = sdebug_random ? prandom_u32_max((u32)ndelay) : |
---|
| 5530 | + (u32)ndelay; |
---|
| 5531 | + if (ndelay < INCLUSIVE_TIMING_MAX_NS) { |
---|
| 5532 | + u64 d = ktime_get_boottime_ns() - ns_from_boot; |
---|
| 5533 | + |
---|
| 5534 | + if (kt <= d) { /* elapsed duration >= kt */ |
---|
| 5535 | + spin_lock_irqsave(&sqp->qc_lock, iflags); |
---|
| 5536 | + sqcp->a_cmnd = NULL; |
---|
| 5537 | + atomic_dec(&devip->num_in_q); |
---|
| 5538 | + clear_bit(k, sqp->in_use_bm); |
---|
| 5539 | + spin_unlock_irqrestore(&sqp->qc_lock, iflags); |
---|
| 5540 | + if (new_sd_dp) |
---|
| 5541 | + kfree(sd_dp); |
---|
| 5542 | + /* call scsi_done() from this thread */ |
---|
| 5543 | + cmnd->scsi_done(cmnd); |
---|
| 5544 | + return 0; |
---|
| 5545 | + } |
---|
| 5546 | + /* otherwise reduce kt by elapsed time */ |
---|
| 5547 | + kt -= d; |
---|
| 5548 | + } |
---|
| 5549 | + } |
---|
4450 | 5550 | if (!sd_dp->init_hrt) { |
---|
4451 | 5551 | sd_dp->init_hrt = true; |
---|
4452 | 5552 | sqcp->sd_dp = sd_dp; |
---|
.. | .. |
---|
4459 | 5559 | if (sdebug_statistics) |
---|
4460 | 5560 | sd_dp->issuing_cpu = raw_smp_processor_id(); |
---|
4461 | 5561 | sd_dp->defer_t = SDEB_DEFER_HRT; |
---|
| 5562 | + /* schedule the invocation of scsi_done() for a later time */ |
---|
4462 | 5563 | hrtimer_start(&sd_dp->hrt, kt, HRTIMER_MODE_REL_PINNED); |
---|
4463 | 5564 | } else { /* jdelay < 0, use work queue */ |
---|
4464 | 5565 | if (!sd_dp->init_wq) { |
---|
.. | .. |
---|
4471 | 5572 | if (sdebug_statistics) |
---|
4472 | 5573 | sd_dp->issuing_cpu = raw_smp_processor_id(); |
---|
4473 | 5574 | sd_dp->defer_t = SDEB_DEFER_WQ; |
---|
4474 | | - if (unlikely(sqcp->inj_cmd_abort)) |
---|
| 5575 | + if (unlikely((sdebug_opts & SDEBUG_OPT_CMD_ABORT) && |
---|
| 5576 | + atomic_read(&sdeb_inject_pending))) |
---|
4475 | 5577 | sd_dp->aborted = true; |
---|
4476 | 5578 | schedule_work(&sd_dp->ew.work); |
---|
4477 | | - if (unlikely(sqcp->inj_cmd_abort)) { |
---|
4478 | | - sdev_printk(KERN_INFO, sdp, "abort request tag %d\n", |
---|
4479 | | - cmnd->request->tag); |
---|
| 5579 | + if (unlikely((sdebug_opts & SDEBUG_OPT_CMD_ABORT) && |
---|
| 5580 | + atomic_read(&sdeb_inject_pending))) { |
---|
| 5581 | + sdev_printk(KERN_INFO, sdp, "abort request tag %d\n", cmnd->request->tag); |
---|
4480 | 5582 | blk_abort_request(cmnd->request); |
---|
| 5583 | + atomic_set(&sdeb_inject_pending, 0); |
---|
4481 | 5584 | } |
---|
4482 | 5585 | } |
---|
4483 | | - if (unlikely((SDEBUG_OPT_Q_NOISE & sdebug_opts) && |
---|
4484 | | - (scsi_result == device_qfull_result))) |
---|
4485 | | - sdev_printk(KERN_INFO, sdp, |
---|
4486 | | - "%s: num_in_q=%d +1, %s%s\n", __func__, |
---|
4487 | | - num_in_q, (inject ? "<inject> " : ""), |
---|
4488 | | - "status: TASK SET FULL"); |
---|
| 5586 | + if (unlikely((SDEBUG_OPT_Q_NOISE & sdebug_opts) && scsi_result == device_qfull_result)) |
---|
| 5587 | + sdev_printk(KERN_INFO, sdp, "%s: num_in_q=%d +1, %s%s\n", __func__, |
---|
| 5588 | + num_in_q, (inject ? "<inject> " : ""), "status: TASK SET FULL"); |
---|
4489 | 5589 | return 0; |
---|
4490 | 5590 | |
---|
4491 | 5591 | respond_in_thread: /* call back to mid-layer using invocation thread */ |
---|
.. | .. |
---|
4516 | 5616 | module_param_named(fake_rw, sdebug_fake_rw, int, S_IRUGO | S_IWUSR); |
---|
4517 | 5617 | module_param_named(guard, sdebug_guard, uint, S_IRUGO); |
---|
4518 | 5618 | module_param_named(host_lock, sdebug_host_lock, bool, S_IRUGO | S_IWUSR); |
---|
4519 | | -module_param_string(inq_vendor, sdebug_inq_vendor_id, |
---|
4520 | | - sizeof(sdebug_inq_vendor_id), S_IRUGO|S_IWUSR); |
---|
| 5619 | +module_param_named(host_max_queue, sdebug_host_max_queue, int, S_IRUGO); |
---|
4521 | 5620 | module_param_string(inq_product, sdebug_inq_product_id, |
---|
4522 | | - sizeof(sdebug_inq_product_id), S_IRUGO|S_IWUSR); |
---|
| 5621 | + sizeof(sdebug_inq_product_id), S_IRUGO | S_IWUSR); |
---|
4523 | 5622 | module_param_string(inq_rev, sdebug_inq_product_rev, |
---|
4524 | | - sizeof(sdebug_inq_product_rev), S_IRUGO|S_IWUSR); |
---|
| 5623 | + sizeof(sdebug_inq_product_rev), S_IRUGO | S_IWUSR); |
---|
| 5624 | +module_param_string(inq_vendor, sdebug_inq_vendor_id, |
---|
| 5625 | + sizeof(sdebug_inq_vendor_id), S_IRUGO | S_IWUSR); |
---|
| 5626 | +module_param_named(lbprz, sdebug_lbprz, int, S_IRUGO); |
---|
4525 | 5627 | module_param_named(lbpu, sdebug_lbpu, int, S_IRUGO); |
---|
4526 | 5628 | module_param_named(lbpws, sdebug_lbpws, int, S_IRUGO); |
---|
4527 | 5629 | module_param_named(lbpws10, sdebug_lbpws10, int, S_IRUGO); |
---|
4528 | | -module_param_named(lbprz, sdebug_lbprz, int, S_IRUGO); |
---|
4529 | 5630 | module_param_named(lowest_aligned, sdebug_lowest_aligned, int, S_IRUGO); |
---|
| 5631 | +module_param_named(lun_format, sdebug_lun_am_i, int, S_IRUGO | S_IWUSR); |
---|
4530 | 5632 | module_param_named(max_luns, sdebug_max_luns, int, S_IRUGO | S_IWUSR); |
---|
4531 | 5633 | module_param_named(max_queue, sdebug_max_queue, int, S_IRUGO | S_IWUSR); |
---|
4532 | | -module_param_named(medium_error_start, sdebug_medium_error_start, int, S_IRUGO | S_IWUSR); |
---|
4533 | | -module_param_named(medium_error_count, sdebug_medium_error_count, int, S_IRUGO | S_IWUSR); |
---|
| 5634 | +module_param_named(medium_error_count, sdebug_medium_error_count, int, |
---|
| 5635 | + S_IRUGO | S_IWUSR); |
---|
| 5636 | +module_param_named(medium_error_start, sdebug_medium_error_start, int, |
---|
| 5637 | + S_IRUGO | S_IWUSR); |
---|
4534 | 5638 | module_param_named(ndelay, sdebug_ndelay, int, S_IRUGO | S_IWUSR); |
---|
4535 | 5639 | module_param_named(no_lun_0, sdebug_no_lun_0, int, S_IRUGO | S_IWUSR); |
---|
4536 | 5640 | module_param_named(no_uld, sdebug_no_uld, int, S_IRUGO); |
---|
4537 | 5641 | module_param_named(num_parts, sdebug_num_parts, int, S_IRUGO); |
---|
4538 | 5642 | module_param_named(num_tgts, sdebug_num_tgts, int, S_IRUGO | S_IWUSR); |
---|
4539 | 5643 | module_param_named(opt_blks, sdebug_opt_blks, int, S_IRUGO); |
---|
4540 | | -module_param_named(opts, sdebug_opts, int, S_IRUGO | S_IWUSR); |
---|
4541 | | -module_param_named(physblk_exp, sdebug_physblk_exp, int, S_IRUGO); |
---|
4542 | 5644 | module_param_named(opt_xferlen_exp, sdebug_opt_xferlen_exp, int, S_IRUGO); |
---|
| 5645 | +module_param_named(opts, sdebug_opts, int, S_IRUGO | S_IWUSR); |
---|
| 5646 | +module_param_named(per_host_store, sdebug_per_host_store, bool, |
---|
| 5647 | + S_IRUGO | S_IWUSR); |
---|
| 5648 | +module_param_named(physblk_exp, sdebug_physblk_exp, int, S_IRUGO); |
---|
4543 | 5649 | module_param_named(ptype, sdebug_ptype, int, S_IRUGO | S_IWUSR); |
---|
| 5650 | +module_param_named(random, sdebug_random, bool, S_IRUGO | S_IWUSR); |
---|
4544 | 5651 | module_param_named(removable, sdebug_removable, bool, S_IRUGO | S_IWUSR); |
---|
4545 | 5652 | module_param_named(scsi_level, sdebug_scsi_level, int, S_IRUGO); |
---|
4546 | 5653 | module_param_named(sector_size, sdebug_sector_size, int, S_IRUGO); |
---|
4547 | 5654 | module_param_named(statistics, sdebug_statistics, bool, S_IRUGO | S_IWUSR); |
---|
4548 | 5655 | module_param_named(strict, sdebug_strict, bool, S_IRUGO | S_IWUSR); |
---|
4549 | 5656 | module_param_named(submit_queues, submit_queues, int, S_IRUGO); |
---|
| 5657 | +module_param_named(tur_ms_to_ready, sdeb_tur_ms_to_ready, int, S_IRUGO); |
---|
4550 | 5658 | module_param_named(unmap_alignment, sdebug_unmap_alignment, int, S_IRUGO); |
---|
4551 | 5659 | module_param_named(unmap_granularity, sdebug_unmap_granularity, int, S_IRUGO); |
---|
4552 | 5660 | module_param_named(unmap_max_blocks, sdebug_unmap_max_blocks, int, S_IRUGO); |
---|
4553 | 5661 | module_param_named(unmap_max_desc, sdebug_unmap_max_desc, int, S_IRUGO); |
---|
4554 | | -module_param_named(virtual_gb, sdebug_virtual_gb, int, S_IRUGO | S_IWUSR); |
---|
4555 | 5662 | module_param_named(uuid_ctl, sdebug_uuid_ctl, int, S_IRUGO); |
---|
| 5663 | +module_param_named(virtual_gb, sdebug_virtual_gb, int, S_IRUGO | S_IWUSR); |
---|
4556 | 5664 | module_param_named(vpd_use_hostno, sdebug_vpd_use_hostno, int, |
---|
4557 | 5665 | S_IRUGO | S_IWUSR); |
---|
| 5666 | +module_param_named(wp, sdebug_wp, bool, S_IRUGO | S_IWUSR); |
---|
4558 | 5667 | module_param_named(write_same_length, sdebug_write_same_length, int, |
---|
4559 | 5668 | S_IRUGO | S_IWUSR); |
---|
| 5669 | +module_param_named(zbc, sdeb_zbc_model_s, charp, S_IRUGO); |
---|
| 5670 | +module_param_named(zone_max_open, sdeb_zbc_max_open, int, S_IRUGO); |
---|
| 5671 | +module_param_named(zone_nr_conv, sdeb_zbc_nr_conv, int, S_IRUGO); |
---|
| 5672 | +module_param_named(zone_size_mb, sdeb_zbc_zone_size_mb, int, S_IRUGO); |
---|
4560 | 5673 | |
---|
4561 | 5674 | MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); |
---|
4562 | 5675 | MODULE_DESCRIPTION("SCSI debug adapter driver"); |
---|
4563 | 5676 | MODULE_LICENSE("GPL"); |
---|
4564 | 5677 | MODULE_VERSION(SDEBUG_VERSION); |
---|
4565 | 5678 | |
---|
4566 | | -MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)"); |
---|
| 5679 | +MODULE_PARM_DESC(add_host, "add n hosts, in sysfs if negative remove host(s) (def=1)"); |
---|
4567 | 5680 | MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)"); |
---|
4568 | 5681 | MODULE_PARM_DESC(cdb_len, "suggest CDB lengths to drivers (def=10)"); |
---|
4569 | 5682 | MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)"); |
---|
.. | .. |
---|
4576 | 5689 | MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)"); |
---|
4577 | 5690 | MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)"); |
---|
4578 | 5691 | MODULE_PARM_DESC(host_lock, "host_lock is ignored (def=0)"); |
---|
4579 | | -MODULE_PARM_DESC(inq_vendor, "SCSI INQUIRY vendor string (def=\"Linux\")"); |
---|
| 5692 | +MODULE_PARM_DESC(host_max_queue, |
---|
| 5693 | + "host max # of queued cmds (0 to max(def) [max_queue fixed equal for !0])"); |
---|
4580 | 5694 | MODULE_PARM_DESC(inq_product, "SCSI INQUIRY product string (def=\"scsi_debug\")"); |
---|
4581 | 5695 | MODULE_PARM_DESC(inq_rev, "SCSI INQUIRY revision string (def=\"" |
---|
4582 | 5696 | SDEBUG_VERSION "\")"); |
---|
| 5697 | +MODULE_PARM_DESC(inq_vendor, "SCSI INQUIRY vendor string (def=\"Linux\")"); |
---|
| 5698 | +MODULE_PARM_DESC(lbprz, |
---|
| 5699 | + "on read unmapped LBs return 0 when 1 (def), return 0xff when 2"); |
---|
4583 | 5700 | MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)"); |
---|
4584 | 5701 | MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)"); |
---|
4585 | 5702 | MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)"); |
---|
4586 | | -MODULE_PARM_DESC(lbprz, |
---|
4587 | | - "on read unmapped LBs return 0 when 1 (def), return 0xff when 2"); |
---|
4588 | 5703 | MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)"); |
---|
4589 | 5704 | MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)"); |
---|
| 5705 | +MODULE_PARM_DESC(lun_format, "LUN format: 0->peripheral (def); 1 --> flat address method"); |
---|
4590 | 5706 | MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))"); |
---|
4591 | | -MODULE_PARM_DESC(medium_error_start, "starting sector number to return MEDIUM error"); |
---|
4592 | 5707 | MODULE_PARM_DESC(medium_error_count, "count of sectors to return follow on MEDIUM error"); |
---|
| 5708 | +MODULE_PARM_DESC(medium_error_start, "starting sector number to return MEDIUM error"); |
---|
4593 | 5709 | MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)"); |
---|
4594 | 5710 | MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)"); |
---|
4595 | 5711 | MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))"); |
---|
4596 | 5712 | MODULE_PARM_DESC(num_parts, "number of partitions(def=0)"); |
---|
4597 | 5713 | MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)"); |
---|
4598 | 5714 | MODULE_PARM_DESC(opt_blks, "optimal transfer length in blocks (def=1024)"); |
---|
4599 | | -MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)"); |
---|
4600 | | -MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)"); |
---|
4601 | 5715 | MODULE_PARM_DESC(opt_xferlen_exp, "optimal transfer length granularity exponent (def=physblk_exp)"); |
---|
| 5716 | +MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)"); |
---|
| 5717 | +MODULE_PARM_DESC(per_host_store, "If set, next positive add_host will get new store (def=0)"); |
---|
| 5718 | +MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)"); |
---|
4602 | 5719 | MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); |
---|
| 5720 | +MODULE_PARM_DESC(random, "If set, uniformly randomize command duration between 0 and delay_in_ns"); |
---|
4603 | 5721 | MODULE_PARM_DESC(removable, "claim to have removable media (def=0)"); |
---|
4604 | 5722 | MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=7[SPC-5])"); |
---|
4605 | 5723 | MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)"); |
---|
4606 | 5724 | MODULE_PARM_DESC(statistics, "collect statistics on commands, queues (def=0)"); |
---|
4607 | 5725 | MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)"); |
---|
4608 | 5726 | MODULE_PARM_DESC(submit_queues, "support for block multi-queue (def=1)"); |
---|
| 5727 | +MODULE_PARM_DESC(tur_ms_to_ready, "TEST UNIT READY millisecs before initial good status (def=0)"); |
---|
4609 | 5728 | MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)"); |
---|
4610 | 5729 | MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)"); |
---|
4611 | 5730 | MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)"); |
---|
.. | .. |
---|
4614 | 5733 | "1->use uuid for lu name, 0->don't, 2->all use same (def=0)"); |
---|
4615 | 5734 | MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size_mb)"); |
---|
4616 | 5735 | MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); |
---|
| 5736 | +MODULE_PARM_DESC(wp, "Write Protect (def=0)"); |
---|
4617 | 5737 | MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)"); |
---|
| 5738 | +MODULE_PARM_DESC(zbc, "'none' [0]; 'aware' [1]; 'managed' [2] (def=0). Can have 'host-' prefix"); |
---|
| 5739 | +MODULE_PARM_DESC(zone_max_open, "Maximum number of open zones; [0] for no limit (def=auto)"); |
---|
| 5740 | +MODULE_PARM_DESC(zone_nr_conv, "Number of conventional zones (def=1)"); |
---|
| 5741 | +MODULE_PARM_DESC(zone_size_mb, "Zone size in MiB (def=auto)"); |
---|
4618 | 5742 | |
---|
4619 | 5743 | #define SDEBUG_INFO_LEN 256 |
---|
4620 | 5744 | static char sdebug_info[SDEBUG_INFO_LEN]; |
---|
.. | .. |
---|
4663 | 5787 | { |
---|
4664 | 5788 | int f, j, l; |
---|
4665 | 5789 | struct sdebug_queue *sqp; |
---|
| 5790 | + struct sdebug_host_info *sdhp; |
---|
4666 | 5791 | |
---|
4667 | 5792 | seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n", |
---|
4668 | 5793 | SDEBUG_VERSION, sdebug_version_date); |
---|
.. | .. |
---|
4696 | 5821 | l = find_last_bit(sqp->in_use_bm, sdebug_max_queue); |
---|
4697 | 5822 | seq_printf(m, " in_use_bm BUSY: %s: %d,%d\n", |
---|
4698 | 5823 | "first,last bits", f, l); |
---|
| 5824 | + } |
---|
| 5825 | + } |
---|
| 5826 | + |
---|
| 5827 | + seq_printf(m, "this host_no=%d\n", host->host_no); |
---|
| 5828 | + if (!xa_empty(per_store_ap)) { |
---|
| 5829 | + bool niu; |
---|
| 5830 | + int idx; |
---|
| 5831 | + unsigned long l_idx; |
---|
| 5832 | + struct sdeb_store_info *sip; |
---|
| 5833 | + |
---|
| 5834 | + seq_puts(m, "\nhost list:\n"); |
---|
| 5835 | + j = 0; |
---|
| 5836 | + list_for_each_entry(sdhp, &sdebug_host_list, host_list) { |
---|
| 5837 | + idx = sdhp->si_idx; |
---|
| 5838 | + seq_printf(m, " %d: host_no=%d, si_idx=%d\n", j, |
---|
| 5839 | + sdhp->shost->host_no, idx); |
---|
| 5840 | + ++j; |
---|
| 5841 | + } |
---|
| 5842 | + seq_printf(m, "\nper_store array [most_recent_idx=%d]:\n", |
---|
| 5843 | + sdeb_most_recent_idx); |
---|
| 5844 | + j = 0; |
---|
| 5845 | + xa_for_each(per_store_ap, l_idx, sip) { |
---|
| 5846 | + niu = xa_get_mark(per_store_ap, l_idx, |
---|
| 5847 | + SDEB_XA_NOT_IN_USE); |
---|
| 5848 | + idx = (int)l_idx; |
---|
| 5849 | + seq_printf(m, " %d: idx=%d%s\n", j, idx, |
---|
| 5850 | + (niu ? " not_in_use" : "")); |
---|
| 5851 | + ++j; |
---|
4699 | 5852 | } |
---|
4700 | 5853 | } |
---|
4701 | 5854 | return 0; |
---|
.. | .. |
---|
4821 | 5974 | { |
---|
4822 | 5975 | int n; |
---|
4823 | 5976 | |
---|
| 5977 | + /* Cannot change from or to TYPE_ZBC with sysfs */ |
---|
| 5978 | + if (sdebug_ptype == TYPE_ZBC) |
---|
| 5979 | + return -EINVAL; |
---|
| 5980 | + |
---|
4824 | 5981 | if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { |
---|
| 5982 | + if (n == TYPE_ZBC) |
---|
| 5983 | + return -EINVAL; |
---|
4825 | 5984 | sdebug_ptype = n; |
---|
4826 | 5985 | return count; |
---|
4827 | 5986 | } |
---|
.. | .. |
---|
4853 | 6012 | static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf, |
---|
4854 | 6013 | size_t count) |
---|
4855 | 6014 | { |
---|
4856 | | - int n; |
---|
| 6015 | + int n, idx; |
---|
4857 | 6016 | |
---|
4858 | 6017 | if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { |
---|
| 6018 | + bool want_store = (n == 0); |
---|
| 6019 | + struct sdebug_host_info *sdhp; |
---|
| 6020 | + |
---|
4859 | 6021 | n = (n > 0); |
---|
4860 | 6022 | sdebug_fake_rw = (sdebug_fake_rw > 0); |
---|
4861 | | - if (sdebug_fake_rw != n) { |
---|
4862 | | - if ((0 == n) && (NULL == fake_storep)) { |
---|
4863 | | - unsigned long sz = |
---|
4864 | | - (unsigned long)sdebug_dev_size_mb * |
---|
4865 | | - 1048576; |
---|
| 6023 | + if (sdebug_fake_rw == n) |
---|
| 6024 | + return count; /* not transitioning so do nothing */ |
---|
4866 | 6025 | |
---|
4867 | | - fake_storep = vzalloc(sz); |
---|
4868 | | - if (NULL == fake_storep) { |
---|
4869 | | - pr_err("out of memory, 9\n"); |
---|
4870 | | - return -ENOMEM; |
---|
| 6026 | + if (want_store) { /* 1 --> 0 transition, set up store */ |
---|
| 6027 | + if (sdeb_first_idx < 0) { |
---|
| 6028 | + idx = sdebug_add_store(); |
---|
| 6029 | + if (idx < 0) |
---|
| 6030 | + return idx; |
---|
| 6031 | + } else { |
---|
| 6032 | + idx = sdeb_first_idx; |
---|
| 6033 | + xa_clear_mark(per_store_ap, idx, |
---|
| 6034 | + SDEB_XA_NOT_IN_USE); |
---|
| 6035 | + } |
---|
| 6036 | + /* make all hosts use same store */ |
---|
| 6037 | + list_for_each_entry(sdhp, &sdebug_host_list, |
---|
| 6038 | + host_list) { |
---|
| 6039 | + if (sdhp->si_idx != idx) { |
---|
| 6040 | + xa_set_mark(per_store_ap, sdhp->si_idx, |
---|
| 6041 | + SDEB_XA_NOT_IN_USE); |
---|
| 6042 | + sdhp->si_idx = idx; |
---|
4871 | 6043 | } |
---|
4872 | 6044 | } |
---|
4873 | | - sdebug_fake_rw = n; |
---|
| 6045 | + sdeb_most_recent_idx = idx; |
---|
| 6046 | + } else { /* 0 --> 1 transition is trigger for shrink */ |
---|
| 6047 | + sdebug_erase_all_stores(true /* apart from first */); |
---|
4874 | 6048 | } |
---|
| 6049 | + sdebug_fake_rw = n; |
---|
4875 | 6050 | return count; |
---|
4876 | 6051 | } |
---|
4877 | 6052 | return -EINVAL; |
---|
.. | .. |
---|
4919 | 6094 | } |
---|
4920 | 6095 | static DRIVER_ATTR_RO(dev_size_mb); |
---|
4921 | 6096 | |
---|
| 6097 | +static ssize_t per_host_store_show(struct device_driver *ddp, char *buf) |
---|
| 6098 | +{ |
---|
| 6099 | + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_per_host_store); |
---|
| 6100 | +} |
---|
| 6101 | + |
---|
| 6102 | +static ssize_t per_host_store_store(struct device_driver *ddp, const char *buf, |
---|
| 6103 | + size_t count) |
---|
| 6104 | +{ |
---|
| 6105 | + bool v; |
---|
| 6106 | + |
---|
| 6107 | + if (kstrtobool(buf, &v)) |
---|
| 6108 | + return -EINVAL; |
---|
| 6109 | + |
---|
| 6110 | + sdebug_per_host_store = v; |
---|
| 6111 | + return count; |
---|
| 6112 | +} |
---|
| 6113 | +static DRIVER_ATTR_RW(per_host_store); |
---|
| 6114 | + |
---|
4922 | 6115 | static ssize_t num_parts_show(struct device_driver *ddp, char *buf) |
---|
4923 | 6116 | { |
---|
4924 | 6117 | return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_num_parts); |
---|
.. | .. |
---|
4933 | 6126 | size_t count) |
---|
4934 | 6127 | { |
---|
4935 | 6128 | int nth; |
---|
| 6129 | + char work[20]; |
---|
4936 | 6130 | |
---|
4937 | | - if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) { |
---|
4938 | | - sdebug_every_nth = nth; |
---|
4939 | | - if (nth && !sdebug_statistics) { |
---|
4940 | | - pr_info("every_nth needs statistics=1, set it\n"); |
---|
4941 | | - sdebug_statistics = true; |
---|
| 6131 | + if (sscanf(buf, "%10s", work) == 1) { |
---|
| 6132 | + if (strncasecmp(work, "0x", 2) == 0) { |
---|
| 6133 | + if (kstrtoint(work + 2, 16, &nth) == 0) |
---|
| 6134 | + goto every_nth_done; |
---|
| 6135 | + } else { |
---|
| 6136 | + if (kstrtoint(work, 10, &nth) == 0) |
---|
| 6137 | + goto every_nth_done; |
---|
4942 | 6138 | } |
---|
4943 | | - tweak_cmnd_count(); |
---|
| 6139 | + } |
---|
| 6140 | + return -EINVAL; |
---|
| 6141 | + |
---|
| 6142 | +every_nth_done: |
---|
| 6143 | + sdebug_every_nth = nth; |
---|
| 6144 | + if (nth && !sdebug_statistics) { |
---|
| 6145 | + pr_info("every_nth needs statistics=1, set it\n"); |
---|
| 6146 | + sdebug_statistics = true; |
---|
| 6147 | + } |
---|
| 6148 | + tweak_cmnd_count(); |
---|
| 6149 | + return count; |
---|
| 6150 | +} |
---|
| 6151 | +static DRIVER_ATTR_RW(every_nth); |
---|
| 6152 | + |
---|
| 6153 | +static ssize_t lun_format_show(struct device_driver *ddp, char *buf) |
---|
| 6154 | +{ |
---|
| 6155 | + return scnprintf(buf, PAGE_SIZE, "%d\n", (int)sdebug_lun_am); |
---|
| 6156 | +} |
---|
| 6157 | +static ssize_t lun_format_store(struct device_driver *ddp, const char *buf, |
---|
| 6158 | + size_t count) |
---|
| 6159 | +{ |
---|
| 6160 | + int n; |
---|
| 6161 | + bool changed; |
---|
| 6162 | + |
---|
| 6163 | + if (kstrtoint(buf, 0, &n)) |
---|
| 6164 | + return -EINVAL; |
---|
| 6165 | + if (n >= 0) { |
---|
| 6166 | + if (n > (int)SAM_LUN_AM_FLAT) { |
---|
| 6167 | + pr_warn("only LUN address methods 0 and 1 are supported\n"); |
---|
| 6168 | + return -EINVAL; |
---|
| 6169 | + } |
---|
| 6170 | + changed = ((int)sdebug_lun_am != n); |
---|
| 6171 | + sdebug_lun_am = n; |
---|
| 6172 | + if (changed && sdebug_scsi_level >= 5) { /* >= SPC-3 */ |
---|
| 6173 | + struct sdebug_host_info *sdhp; |
---|
| 6174 | + struct sdebug_dev_info *dp; |
---|
| 6175 | + |
---|
| 6176 | + spin_lock(&sdebug_host_list_lock); |
---|
| 6177 | + list_for_each_entry(sdhp, &sdebug_host_list, host_list) { |
---|
| 6178 | + list_for_each_entry(dp, &sdhp->dev_info_list, dev_list) { |
---|
| 6179 | + set_bit(SDEBUG_UA_LUNS_CHANGED, dp->uas_bm); |
---|
| 6180 | + } |
---|
| 6181 | + } |
---|
| 6182 | + spin_unlock(&sdebug_host_list_lock); |
---|
| 6183 | + } |
---|
4944 | 6184 | return count; |
---|
4945 | 6185 | } |
---|
4946 | 6186 | return -EINVAL; |
---|
4947 | 6187 | } |
---|
4948 | | -static DRIVER_ATTR_RW(every_nth); |
---|
| 6188 | +static DRIVER_ATTR_RW(lun_format); |
---|
4949 | 6189 | |
---|
4950 | 6190 | static ssize_t max_luns_show(struct device_driver *ddp, char *buf) |
---|
4951 | 6191 | { |
---|
.. | .. |
---|
4999 | 6239 | struct sdebug_queue *sqp; |
---|
5000 | 6240 | |
---|
5001 | 6241 | if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) && |
---|
5002 | | - (n <= SDEBUG_CANQUEUE)) { |
---|
| 6242 | + (n <= SDEBUG_CANQUEUE) && |
---|
| 6243 | + (sdebug_host_max_queue == 0)) { |
---|
5003 | 6244 | block_unblock_all_queues(true); |
---|
5004 | 6245 | k = 0; |
---|
5005 | 6246 | for (j = 0, sqp = sdebug_q_arr; j < submit_queues; |
---|
.. | .. |
---|
5022 | 6263 | } |
---|
5023 | 6264 | static DRIVER_ATTR_RW(max_queue); |
---|
5024 | 6265 | |
---|
| 6266 | +static ssize_t host_max_queue_show(struct device_driver *ddp, char *buf) |
---|
| 6267 | +{ |
---|
| 6268 | + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_host_max_queue); |
---|
| 6269 | +} |
---|
| 6270 | + |
---|
| 6271 | +/* |
---|
| 6272 | + * Since this is used for .can_queue, and we get the hc_idx tag from the bitmap |
---|
| 6273 | + * in range [0, sdebug_host_max_queue), we can't change it. |
---|
| 6274 | + */ |
---|
| 6275 | +static DRIVER_ATTR_RO(host_max_queue); |
---|
| 6276 | + |
---|
5025 | 6277 | static ssize_t no_uld_show(struct device_driver *ddp, char *buf) |
---|
5026 | 6278 | { |
---|
5027 | 6279 | return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_no_uld); |
---|
.. | .. |
---|
5043 | 6295 | { |
---|
5044 | 6296 | int n; |
---|
5045 | 6297 | bool changed; |
---|
| 6298 | + |
---|
| 6299 | + /* Ignore capacity change for ZBC drives for now */ |
---|
| 6300 | + if (sdeb_zbc_in_use) |
---|
| 6301 | + return -ENOTSUPP; |
---|
5046 | 6302 | |
---|
5047 | 6303 | if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { |
---|
5048 | 6304 | changed = (sdebug_virtual_gb != n); |
---|
.. | .. |
---|
5071 | 6327 | |
---|
5072 | 6328 | static ssize_t add_host_show(struct device_driver *ddp, char *buf) |
---|
5073 | 6329 | { |
---|
5074 | | - return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_add_host); |
---|
| 6330 | + /* absolute number of hosts currently active is what is shown */ |
---|
| 6331 | + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_num_hosts); |
---|
5075 | 6332 | } |
---|
5076 | | - |
---|
5077 | | -static int sdebug_add_adapter(void); |
---|
5078 | | -static void sdebug_remove_adapter(void); |
---|
5079 | 6333 | |
---|
5080 | 6334 | static ssize_t add_host_store(struct device_driver *ddp, const char *buf, |
---|
5081 | 6335 | size_t count) |
---|
5082 | 6336 | { |
---|
| 6337 | + bool found; |
---|
| 6338 | + unsigned long idx; |
---|
| 6339 | + struct sdeb_store_info *sip; |
---|
| 6340 | + bool want_phs = (sdebug_fake_rw == 0) && sdebug_per_host_store; |
---|
5083 | 6341 | int delta_hosts; |
---|
5084 | 6342 | |
---|
5085 | 6343 | if (sscanf(buf, "%d", &delta_hosts) != 1) |
---|
5086 | 6344 | return -EINVAL; |
---|
5087 | 6345 | if (delta_hosts > 0) { |
---|
5088 | 6346 | do { |
---|
5089 | | - sdebug_add_adapter(); |
---|
| 6347 | + found = false; |
---|
| 6348 | + if (want_phs) { |
---|
| 6349 | + xa_for_each_marked(per_store_ap, idx, sip, |
---|
| 6350 | + SDEB_XA_NOT_IN_USE) { |
---|
| 6351 | + sdeb_most_recent_idx = (int)idx; |
---|
| 6352 | + found = true; |
---|
| 6353 | + break; |
---|
| 6354 | + } |
---|
| 6355 | + if (found) /* re-use case */ |
---|
| 6356 | + sdebug_add_host_helper((int)idx); |
---|
| 6357 | + else |
---|
| 6358 | + sdebug_do_add_host(true); |
---|
| 6359 | + } else { |
---|
| 6360 | + sdebug_do_add_host(false); |
---|
| 6361 | + } |
---|
5090 | 6362 | } while (--delta_hosts); |
---|
5091 | 6363 | } else if (delta_hosts < 0) { |
---|
5092 | 6364 | do { |
---|
5093 | | - sdebug_remove_adapter(); |
---|
| 6365 | + sdebug_do_remove_host(false); |
---|
5094 | 6366 | } while (++delta_hosts); |
---|
5095 | 6367 | } |
---|
5096 | 6368 | return count; |
---|
.. | .. |
---|
5174 | 6446 | |
---|
5175 | 6447 | static ssize_t map_show(struct device_driver *ddp, char *buf) |
---|
5176 | 6448 | { |
---|
5177 | | - ssize_t count; |
---|
| 6449 | + ssize_t count = 0; |
---|
5178 | 6450 | |
---|
5179 | 6451 | if (!scsi_debug_lbp()) |
---|
5180 | 6452 | return scnprintf(buf, PAGE_SIZE, "0-%u\n", |
---|
5181 | 6453 | sdebug_store_sectors); |
---|
5182 | 6454 | |
---|
5183 | | - count = scnprintf(buf, PAGE_SIZE - 1, "%*pbl", |
---|
5184 | | - (int)map_size, map_storep); |
---|
| 6455 | + if (sdebug_fake_rw == 0 && !xa_empty(per_store_ap)) { |
---|
| 6456 | + struct sdeb_store_info *sip = xa_load(per_store_ap, 0); |
---|
| 6457 | + |
---|
| 6458 | + if (sip) |
---|
| 6459 | + count = scnprintf(buf, PAGE_SIZE - 1, "%*pbl", |
---|
| 6460 | + (int)map_size, sip->map_storep); |
---|
| 6461 | + } |
---|
5185 | 6462 | buf[count++] = '\n'; |
---|
5186 | 6463 | buf[count] = '\0'; |
---|
5187 | 6464 | |
---|
5188 | 6465 | return count; |
---|
5189 | 6466 | } |
---|
5190 | 6467 | static DRIVER_ATTR_RO(map); |
---|
| 6468 | + |
---|
| 6469 | +static ssize_t random_show(struct device_driver *ddp, char *buf) |
---|
| 6470 | +{ |
---|
| 6471 | + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_random); |
---|
| 6472 | +} |
---|
| 6473 | + |
---|
| 6474 | +static ssize_t random_store(struct device_driver *ddp, const char *buf, |
---|
| 6475 | + size_t count) |
---|
| 6476 | +{ |
---|
| 6477 | + bool v; |
---|
| 6478 | + |
---|
| 6479 | + if (kstrtobool(buf, &v)) |
---|
| 6480 | + return -EINVAL; |
---|
| 6481 | + |
---|
| 6482 | + sdebug_random = v; |
---|
| 6483 | + return count; |
---|
| 6484 | +} |
---|
| 6485 | +static DRIVER_ATTR_RW(random); |
---|
5191 | 6486 | |
---|
5192 | 6487 | static ssize_t removable_show(struct device_driver *ddp, char *buf) |
---|
5193 | 6488 | { |
---|
.. | .. |
---|
5265 | 6560 | } |
---|
5266 | 6561 | static DRIVER_ATTR_RW(cdb_len); |
---|
5267 | 6562 | |
---|
| 6563 | +static const char * const zbc_model_strs_a[] = { |
---|
| 6564 | + [BLK_ZONED_NONE] = "none", |
---|
| 6565 | + [BLK_ZONED_HA] = "host-aware", |
---|
| 6566 | + [BLK_ZONED_HM] = "host-managed", |
---|
| 6567 | +}; |
---|
| 6568 | + |
---|
| 6569 | +static const char * const zbc_model_strs_b[] = { |
---|
| 6570 | + [BLK_ZONED_NONE] = "no", |
---|
| 6571 | + [BLK_ZONED_HA] = "aware", |
---|
| 6572 | + [BLK_ZONED_HM] = "managed", |
---|
| 6573 | +}; |
---|
| 6574 | + |
---|
| 6575 | +static const char * const zbc_model_strs_c[] = { |
---|
| 6576 | + [BLK_ZONED_NONE] = "0", |
---|
| 6577 | + [BLK_ZONED_HA] = "1", |
---|
| 6578 | + [BLK_ZONED_HM] = "2", |
---|
| 6579 | +}; |
---|
| 6580 | + |
---|
| 6581 | +static int sdeb_zbc_model_str(const char *cp) |
---|
| 6582 | +{ |
---|
| 6583 | + int res = sysfs_match_string(zbc_model_strs_a, cp); |
---|
| 6584 | + |
---|
| 6585 | + if (res < 0) { |
---|
| 6586 | + res = sysfs_match_string(zbc_model_strs_b, cp); |
---|
| 6587 | + if (res < 0) { |
---|
| 6588 | + res = sysfs_match_string(zbc_model_strs_c, cp); |
---|
| 6589 | + if (res < 0) |
---|
| 6590 | + return -EINVAL; |
---|
| 6591 | + } |
---|
| 6592 | + } |
---|
| 6593 | + return res; |
---|
| 6594 | +} |
---|
| 6595 | + |
---|
| 6596 | +static ssize_t zbc_show(struct device_driver *ddp, char *buf) |
---|
| 6597 | +{ |
---|
| 6598 | + return scnprintf(buf, PAGE_SIZE, "%s\n", |
---|
| 6599 | + zbc_model_strs_a[sdeb_zbc_model]); |
---|
| 6600 | +} |
---|
| 6601 | +static DRIVER_ATTR_RO(zbc); |
---|
| 6602 | + |
---|
| 6603 | +static ssize_t tur_ms_to_ready_show(struct device_driver *ddp, char *buf) |
---|
| 6604 | +{ |
---|
| 6605 | + return scnprintf(buf, PAGE_SIZE, "%d\n", sdeb_tur_ms_to_ready); |
---|
| 6606 | +} |
---|
| 6607 | +static DRIVER_ATTR_RO(tur_ms_to_ready); |
---|
5268 | 6608 | |
---|
5269 | 6609 | /* Note: The following array creates attribute files in the |
---|
5270 | 6610 | /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these |
---|
5271 | 6611 | files (over those found in the /sys/module/scsi_debug/parameters |
---|
5272 | 6612 | directory) is that auxiliary actions can be triggered when an attribute |
---|
5273 | | - is changed. For example see: sdebug_add_host_store() above. |
---|
| 6613 | + is changed. For example see: add_host_store() above. |
---|
5274 | 6614 | */ |
---|
5275 | 6615 | |
---|
5276 | 6616 | static struct attribute *sdebug_drv_attrs[] = { |
---|
.. | .. |
---|
5279 | 6619 | &driver_attr_ptype.attr, |
---|
5280 | 6620 | &driver_attr_dsense.attr, |
---|
5281 | 6621 | &driver_attr_fake_rw.attr, |
---|
| 6622 | + &driver_attr_host_max_queue.attr, |
---|
5282 | 6623 | &driver_attr_no_lun_0.attr, |
---|
5283 | 6624 | &driver_attr_num_tgts.attr, |
---|
5284 | 6625 | &driver_attr_dev_size_mb.attr, |
---|
5285 | 6626 | &driver_attr_num_parts.attr, |
---|
5286 | 6627 | &driver_attr_every_nth.attr, |
---|
| 6628 | + &driver_attr_lun_format.attr, |
---|
5287 | 6629 | &driver_attr_max_luns.attr, |
---|
5288 | 6630 | &driver_attr_max_queue.attr, |
---|
5289 | 6631 | &driver_attr_no_uld.attr, |
---|
5290 | 6632 | &driver_attr_scsi_level.attr, |
---|
5291 | 6633 | &driver_attr_virtual_gb.attr, |
---|
5292 | 6634 | &driver_attr_add_host.attr, |
---|
| 6635 | + &driver_attr_per_host_store.attr, |
---|
5293 | 6636 | &driver_attr_vpd_use_hostno.attr, |
---|
5294 | 6637 | &driver_attr_sector_size.attr, |
---|
5295 | 6638 | &driver_attr_statistics.attr, |
---|
.. | .. |
---|
5299 | 6642 | &driver_attr_guard.attr, |
---|
5300 | 6643 | &driver_attr_ato.attr, |
---|
5301 | 6644 | &driver_attr_map.attr, |
---|
| 6645 | + &driver_attr_random.attr, |
---|
5302 | 6646 | &driver_attr_removable.attr, |
---|
5303 | 6647 | &driver_attr_host_lock.attr, |
---|
5304 | 6648 | &driver_attr_ndelay.attr, |
---|
5305 | 6649 | &driver_attr_strict.attr, |
---|
5306 | 6650 | &driver_attr_uuid_ctl.attr, |
---|
5307 | 6651 | &driver_attr_cdb_len.attr, |
---|
| 6652 | + &driver_attr_tur_ms_to_ready.attr, |
---|
| 6653 | + &driver_attr_zbc.attr, |
---|
5308 | 6654 | NULL, |
---|
5309 | 6655 | }; |
---|
5310 | 6656 | ATTRIBUTE_GROUPS(sdebug_drv); |
---|
.. | .. |
---|
5313 | 6659 | |
---|
5314 | 6660 | static int __init scsi_debug_init(void) |
---|
5315 | 6661 | { |
---|
| 6662 | + bool want_store = (sdebug_fake_rw == 0); |
---|
5316 | 6663 | unsigned long sz; |
---|
5317 | | - int host_to_add; |
---|
5318 | | - int k; |
---|
5319 | | - int ret; |
---|
| 6664 | + int k, ret, hosts_to_add; |
---|
| 6665 | + int idx = -1; |
---|
5320 | 6666 | |
---|
| 6667 | + ramdisk_lck_a[0] = &atomic_rw; |
---|
| 6668 | + ramdisk_lck_a[1] = &atomic_rw2; |
---|
5321 | 6669 | atomic_set(&retired_max_queue, 0); |
---|
5322 | 6670 | |
---|
5323 | 6671 | if (sdebug_ndelay >= 1000 * 1000 * 1000) { |
---|
.. | .. |
---|
5370 | 6718 | pr_err("invalid physblk_exp %u\n", sdebug_physblk_exp); |
---|
5371 | 6719 | return -EINVAL; |
---|
5372 | 6720 | } |
---|
| 6721 | + |
---|
| 6722 | + sdebug_lun_am = sdebug_lun_am_i; |
---|
| 6723 | + if (sdebug_lun_am > SAM_LUN_AM_FLAT) { |
---|
| 6724 | + pr_warn("Invalid LUN format %u, using default\n", (int)sdebug_lun_am); |
---|
| 6725 | + sdebug_lun_am = SAM_LUN_AM_PERIPHERAL; |
---|
| 6726 | + } |
---|
| 6727 | + |
---|
5373 | 6728 | if (sdebug_max_luns > 256) { |
---|
5374 | | - pr_warn("max_luns can be no more than 256, use default\n"); |
---|
5375 | | - sdebug_max_luns = DEF_MAX_LUNS; |
---|
| 6729 | + if (sdebug_max_luns > 16384) { |
---|
| 6730 | + pr_warn("max_luns can be no more than 16384, use default\n"); |
---|
| 6731 | + sdebug_max_luns = DEF_MAX_LUNS; |
---|
| 6732 | + } |
---|
| 6733 | + sdebug_lun_am = SAM_LUN_AM_FLAT; |
---|
5376 | 6734 | } |
---|
5377 | 6735 | |
---|
5378 | 6736 | if (sdebug_lowest_aligned > 0x3fff) { |
---|
.. | .. |
---|
5390 | 6748 | return -EINVAL; |
---|
5391 | 6749 | } |
---|
5392 | 6750 | |
---|
| 6751 | + if ((sdebug_host_max_queue > SDEBUG_CANQUEUE) || |
---|
| 6752 | + (sdebug_host_max_queue < 0)) { |
---|
| 6753 | + pr_err("host_max_queue must be in range [0 %d]\n", |
---|
| 6754 | + SDEBUG_CANQUEUE); |
---|
| 6755 | + return -EINVAL; |
---|
| 6756 | + } |
---|
| 6757 | + |
---|
| 6758 | + if (sdebug_host_max_queue && |
---|
| 6759 | + (sdebug_max_queue != sdebug_host_max_queue)) { |
---|
| 6760 | + sdebug_max_queue = sdebug_host_max_queue; |
---|
| 6761 | + pr_warn("fixing max submit queue depth to host max queue depth, %d\n", |
---|
| 6762 | + sdebug_max_queue); |
---|
| 6763 | + } |
---|
| 6764 | + |
---|
5393 | 6765 | sdebug_q_arr = kcalloc(submit_queues, sizeof(struct sdebug_queue), |
---|
5394 | 6766 | GFP_KERNEL); |
---|
5395 | 6767 | if (sdebug_q_arr == NULL) |
---|
.. | .. |
---|
5397 | 6769 | for (k = 0; k < submit_queues; ++k) |
---|
5398 | 6770 | spin_lock_init(&sdebug_q_arr[k].qc_lock); |
---|
5399 | 6771 | |
---|
| 6772 | + /* |
---|
| 6773 | + * check for host managed zoned block device specified with |
---|
| 6774 | + * ptype=0x14 or zbc=XXX. |
---|
| 6775 | + */ |
---|
| 6776 | + if (sdebug_ptype == TYPE_ZBC) { |
---|
| 6777 | + sdeb_zbc_model = BLK_ZONED_HM; |
---|
| 6778 | + } else if (sdeb_zbc_model_s && *sdeb_zbc_model_s) { |
---|
| 6779 | + k = sdeb_zbc_model_str(sdeb_zbc_model_s); |
---|
| 6780 | + if (k < 0) { |
---|
| 6781 | + ret = k; |
---|
| 6782 | + goto free_q_arr; |
---|
| 6783 | + } |
---|
| 6784 | + sdeb_zbc_model = k; |
---|
| 6785 | + switch (sdeb_zbc_model) { |
---|
| 6786 | + case BLK_ZONED_NONE: |
---|
| 6787 | + case BLK_ZONED_HA: |
---|
| 6788 | + sdebug_ptype = TYPE_DISK; |
---|
| 6789 | + break; |
---|
| 6790 | + case BLK_ZONED_HM: |
---|
| 6791 | + sdebug_ptype = TYPE_ZBC; |
---|
| 6792 | + break; |
---|
| 6793 | + default: |
---|
| 6794 | + pr_err("Invalid ZBC model\n"); |
---|
| 6795 | + ret = -EINVAL; |
---|
| 6796 | + goto free_q_arr; |
---|
| 6797 | + } |
---|
| 6798 | + } |
---|
| 6799 | + if (sdeb_zbc_model != BLK_ZONED_NONE) { |
---|
| 6800 | + sdeb_zbc_in_use = true; |
---|
| 6801 | + if (sdebug_dev_size_mb == DEF_DEV_SIZE_PRE_INIT) |
---|
| 6802 | + sdebug_dev_size_mb = DEF_ZBC_DEV_SIZE_MB; |
---|
| 6803 | + } |
---|
| 6804 | + |
---|
| 6805 | + if (sdebug_dev_size_mb == DEF_DEV_SIZE_PRE_INIT) |
---|
| 6806 | + sdebug_dev_size_mb = DEF_DEV_SIZE_MB; |
---|
5400 | 6807 | if (sdebug_dev_size_mb < 1) |
---|
5401 | 6808 | sdebug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ |
---|
5402 | 6809 | sz = (unsigned long)sdebug_dev_size_mb * 1048576; |
---|
.. | .. |
---|
5419 | 6826 | sdebug_cylinders_per = (unsigned long)sdebug_capacity / |
---|
5420 | 6827 | (sdebug_sectors_per * sdebug_heads); |
---|
5421 | 6828 | } |
---|
5422 | | - |
---|
5423 | | - if (sdebug_fake_rw == 0) { |
---|
5424 | | - fake_storep = vzalloc(sz); |
---|
5425 | | - if (NULL == fake_storep) { |
---|
5426 | | - pr_err("out of memory, 1\n"); |
---|
5427 | | - ret = -ENOMEM; |
---|
5428 | | - goto free_q_arr; |
---|
5429 | | - } |
---|
5430 | | - if (sdebug_num_parts > 0) |
---|
5431 | | - sdebug_build_parts(fake_storep, sz); |
---|
5432 | | - } |
---|
5433 | | - |
---|
5434 | | - if (sdebug_dix) { |
---|
5435 | | - int dif_size; |
---|
5436 | | - |
---|
5437 | | - dif_size = sdebug_store_sectors * sizeof(struct t10_pi_tuple); |
---|
5438 | | - dif_storep = vmalloc(dif_size); |
---|
5439 | | - |
---|
5440 | | - pr_err("dif_storep %u bytes @ %p\n", dif_size, dif_storep); |
---|
5441 | | - |
---|
5442 | | - if (dif_storep == NULL) { |
---|
5443 | | - pr_err("out of mem. (DIX)\n"); |
---|
5444 | | - ret = -ENOMEM; |
---|
5445 | | - goto free_vm; |
---|
5446 | | - } |
---|
5447 | | - |
---|
5448 | | - memset(dif_storep, 0xff, dif_size); |
---|
5449 | | - } |
---|
5450 | | - |
---|
5451 | | - /* Logical Block Provisioning */ |
---|
5452 | 6829 | if (scsi_debug_lbp()) { |
---|
5453 | 6830 | sdebug_unmap_max_blocks = |
---|
5454 | 6831 | clamp(sdebug_unmap_max_blocks, 0U, 0xffffffffU); |
---|
.. | .. |
---|
5464 | 6841 | sdebug_unmap_alignment) { |
---|
5465 | 6842 | pr_err("ERR: unmap_granularity <= unmap_alignment\n"); |
---|
5466 | 6843 | ret = -EINVAL; |
---|
5467 | | - goto free_vm; |
---|
| 6844 | + goto free_q_arr; |
---|
5468 | 6845 | } |
---|
5469 | | - |
---|
5470 | | - map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1; |
---|
5471 | | - map_storep = vmalloc(array_size(sizeof(long), |
---|
5472 | | - BITS_TO_LONGS(map_size))); |
---|
5473 | | - |
---|
5474 | | - pr_info("%lu provisioning blocks\n", map_size); |
---|
5475 | | - |
---|
5476 | | - if (map_storep == NULL) { |
---|
5477 | | - pr_err("out of mem. (MAP)\n"); |
---|
5478 | | - ret = -ENOMEM; |
---|
5479 | | - goto free_vm; |
---|
| 6846 | + } |
---|
| 6847 | + xa_init_flags(per_store_ap, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ); |
---|
| 6848 | + if (want_store) { |
---|
| 6849 | + idx = sdebug_add_store(); |
---|
| 6850 | + if (idx < 0) { |
---|
| 6851 | + ret = idx; |
---|
| 6852 | + goto free_q_arr; |
---|
5480 | 6853 | } |
---|
5481 | | - |
---|
5482 | | - bitmap_zero(map_storep, map_size); |
---|
5483 | | - |
---|
5484 | | - /* Map first 1KB for partition table */ |
---|
5485 | | - if (sdebug_num_parts) |
---|
5486 | | - map_region(0, 2); |
---|
5487 | 6854 | } |
---|
5488 | 6855 | |
---|
5489 | 6856 | pseudo_primary = root_device_register("pseudo_0"); |
---|
.. | .. |
---|
5503 | 6870 | goto bus_unreg; |
---|
5504 | 6871 | } |
---|
5505 | 6872 | |
---|
5506 | | - host_to_add = sdebug_add_host; |
---|
| 6873 | + hosts_to_add = sdebug_add_host; |
---|
5507 | 6874 | sdebug_add_host = 0; |
---|
5508 | 6875 | |
---|
5509 | | - for (k = 0; k < host_to_add; k++) { |
---|
5510 | | - if (sdebug_add_adapter()) { |
---|
5511 | | - pr_err("sdebug_add_adapter failed k=%d\n", k); |
---|
5512 | | - break; |
---|
| 6876 | + for (k = 0; k < hosts_to_add; k++) { |
---|
| 6877 | + if (want_store && k == 0) { |
---|
| 6878 | + ret = sdebug_add_host_helper(idx); |
---|
| 6879 | + if (ret < 0) { |
---|
| 6880 | + pr_err("add_host_helper k=%d, error=%d\n", |
---|
| 6881 | + k, -ret); |
---|
| 6882 | + break; |
---|
| 6883 | + } |
---|
| 6884 | + } else { |
---|
| 6885 | + ret = sdebug_do_add_host(want_store && |
---|
| 6886 | + sdebug_per_host_store); |
---|
| 6887 | + if (ret < 0) { |
---|
| 6888 | + pr_err("add_host k=%d error=%d\n", k, -ret); |
---|
| 6889 | + break; |
---|
| 6890 | + } |
---|
5513 | 6891 | } |
---|
5514 | 6892 | } |
---|
5515 | | - |
---|
5516 | 6893 | if (sdebug_verbose) |
---|
5517 | | - pr_info("built %d host(s)\n", sdebug_add_host); |
---|
| 6894 | + pr_info("built %d host(s)\n", sdebug_num_hosts); |
---|
5518 | 6895 | |
---|
5519 | 6896 | return 0; |
---|
5520 | 6897 | |
---|
.. | .. |
---|
5523 | 6900 | dev_unreg: |
---|
5524 | 6901 | root_device_unregister(pseudo_primary); |
---|
5525 | 6902 | free_vm: |
---|
5526 | | - vfree(map_storep); |
---|
5527 | | - vfree(dif_storep); |
---|
5528 | | - vfree(fake_storep); |
---|
| 6903 | + sdebug_erase_store(idx, NULL); |
---|
5529 | 6904 | free_q_arr: |
---|
5530 | 6905 | kfree(sdebug_q_arr); |
---|
5531 | 6906 | return ret; |
---|
.. | .. |
---|
5533 | 6908 | |
---|
5534 | 6909 | static void __exit scsi_debug_exit(void) |
---|
5535 | 6910 | { |
---|
5536 | | - int k = sdebug_add_host; |
---|
| 6911 | + int k = sdebug_num_hosts; |
---|
5537 | 6912 | |
---|
5538 | 6913 | stop_all_queued(); |
---|
5539 | 6914 | for (; k; k--) |
---|
5540 | | - sdebug_remove_adapter(); |
---|
| 6915 | + sdebug_do_remove_host(true); |
---|
5541 | 6916 | free_all_queued(); |
---|
5542 | 6917 | driver_unregister(&sdebug_driverfs_driver); |
---|
5543 | 6918 | bus_unregister(&pseudo_lld_bus); |
---|
5544 | 6919 | root_device_unregister(pseudo_primary); |
---|
5545 | 6920 | |
---|
5546 | | - vfree(map_storep); |
---|
5547 | | - vfree(dif_storep); |
---|
5548 | | - vfree(fake_storep); |
---|
| 6921 | + sdebug_erase_all_stores(false); |
---|
| 6922 | + xa_destroy(per_store_ap); |
---|
5549 | 6923 | kfree(sdebug_q_arr); |
---|
5550 | 6924 | } |
---|
5551 | 6925 | |
---|
.. | .. |
---|
5560 | 6934 | kfree(sdbg_host); |
---|
5561 | 6935 | } |
---|
5562 | 6936 | |
---|
5563 | | -static int sdebug_add_adapter(void) |
---|
| 6937 | +/* idx must be valid, if sip is NULL then it will be obtained using idx */ |
---|
| 6938 | +static void sdebug_erase_store(int idx, struct sdeb_store_info *sip) |
---|
5564 | 6939 | { |
---|
5565 | | - int k, devs_per_host; |
---|
5566 | | - int error = 0; |
---|
| 6940 | + if (idx < 0) |
---|
| 6941 | + return; |
---|
| 6942 | + if (!sip) { |
---|
| 6943 | + if (xa_empty(per_store_ap)) |
---|
| 6944 | + return; |
---|
| 6945 | + sip = xa_load(per_store_ap, idx); |
---|
| 6946 | + if (!sip) |
---|
| 6947 | + return; |
---|
| 6948 | + } |
---|
| 6949 | + vfree(sip->map_storep); |
---|
| 6950 | + vfree(sip->dif_storep); |
---|
| 6951 | + vfree(sip->storep); |
---|
| 6952 | + xa_erase(per_store_ap, idx); |
---|
| 6953 | + kfree(sip); |
---|
| 6954 | +} |
---|
| 6955 | + |
---|
| 6956 | +/* Assume apart_from_first==false only in shutdown case. */ |
---|
| 6957 | +static void sdebug_erase_all_stores(bool apart_from_first) |
---|
| 6958 | +{ |
---|
| 6959 | + unsigned long idx; |
---|
| 6960 | + struct sdeb_store_info *sip = NULL; |
---|
| 6961 | + |
---|
| 6962 | + xa_for_each(per_store_ap, idx, sip) { |
---|
| 6963 | + if (apart_from_first) |
---|
| 6964 | + apart_from_first = false; |
---|
| 6965 | + else |
---|
| 6966 | + sdebug_erase_store(idx, sip); |
---|
| 6967 | + } |
---|
| 6968 | + if (apart_from_first) |
---|
| 6969 | + sdeb_most_recent_idx = sdeb_first_idx; |
---|
| 6970 | +} |
---|
| 6971 | + |
---|
| 6972 | +/* |
---|
| 6973 | + * Returns store xarray new element index (idx) if >=0 else negated errno. |
---|
| 6974 | + * Limit the number of stores to 65536. |
---|
| 6975 | + */ |
---|
| 6976 | +static int sdebug_add_store(void) |
---|
| 6977 | +{ |
---|
| 6978 | + int res; |
---|
| 6979 | + u32 n_idx; |
---|
| 6980 | + unsigned long iflags; |
---|
| 6981 | + unsigned long sz = (unsigned long)sdebug_dev_size_mb * 1048576; |
---|
| 6982 | + struct sdeb_store_info *sip = NULL; |
---|
| 6983 | + struct xa_limit xal = { .max = 1 << 16, .min = 0 }; |
---|
| 6984 | + |
---|
| 6985 | + sip = kzalloc(sizeof(*sip), GFP_KERNEL); |
---|
| 6986 | + if (!sip) |
---|
| 6987 | + return -ENOMEM; |
---|
| 6988 | + |
---|
| 6989 | + xa_lock_irqsave(per_store_ap, iflags); |
---|
| 6990 | + res = __xa_alloc(per_store_ap, &n_idx, sip, xal, GFP_ATOMIC); |
---|
| 6991 | + if (unlikely(res < 0)) { |
---|
| 6992 | + xa_unlock_irqrestore(per_store_ap, iflags); |
---|
| 6993 | + kfree(sip); |
---|
| 6994 | + pr_warn("%s: xa_alloc() errno=%d\n", __func__, -res); |
---|
| 6995 | + return res; |
---|
| 6996 | + } |
---|
| 6997 | + sdeb_most_recent_idx = n_idx; |
---|
| 6998 | + if (sdeb_first_idx < 0) |
---|
| 6999 | + sdeb_first_idx = n_idx; |
---|
| 7000 | + xa_unlock_irqrestore(per_store_ap, iflags); |
---|
| 7001 | + |
---|
| 7002 | + res = -ENOMEM; |
---|
| 7003 | + sip->storep = vzalloc(sz); |
---|
| 7004 | + if (!sip->storep) { |
---|
| 7005 | + pr_err("user data oom\n"); |
---|
| 7006 | + goto err; |
---|
| 7007 | + } |
---|
| 7008 | + if (sdebug_num_parts > 0) |
---|
| 7009 | + sdebug_build_parts(sip->storep, sz); |
---|
| 7010 | + |
---|
| 7011 | + /* DIF/DIX: what T10 calls Protection Information (PI) */ |
---|
| 7012 | + if (sdebug_dix) { |
---|
| 7013 | + int dif_size; |
---|
| 7014 | + |
---|
| 7015 | + dif_size = sdebug_store_sectors * sizeof(struct t10_pi_tuple); |
---|
| 7016 | + sip->dif_storep = vmalloc(dif_size); |
---|
| 7017 | + |
---|
| 7018 | + pr_info("dif_storep %u bytes @ %pK\n", dif_size, |
---|
| 7019 | + sip->dif_storep); |
---|
| 7020 | + |
---|
| 7021 | + if (!sip->dif_storep) { |
---|
| 7022 | + pr_err("DIX oom\n"); |
---|
| 7023 | + goto err; |
---|
| 7024 | + } |
---|
| 7025 | + memset(sip->dif_storep, 0xff, dif_size); |
---|
| 7026 | + } |
---|
| 7027 | + /* Logical Block Provisioning */ |
---|
| 7028 | + if (scsi_debug_lbp()) { |
---|
| 7029 | + map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1; |
---|
| 7030 | + sip->map_storep = vmalloc(array_size(sizeof(long), |
---|
| 7031 | + BITS_TO_LONGS(map_size))); |
---|
| 7032 | + |
---|
| 7033 | + pr_info("%lu provisioning blocks\n", map_size); |
---|
| 7034 | + |
---|
| 7035 | + if (!sip->map_storep) { |
---|
| 7036 | + pr_err("LBP map oom\n"); |
---|
| 7037 | + goto err; |
---|
| 7038 | + } |
---|
| 7039 | + |
---|
| 7040 | + bitmap_zero(sip->map_storep, map_size); |
---|
| 7041 | + |
---|
| 7042 | + /* Map first 1KB for partition table */ |
---|
| 7043 | + if (sdebug_num_parts) |
---|
| 7044 | + map_region(sip, 0, 2); |
---|
| 7045 | + } |
---|
| 7046 | + |
---|
| 7047 | + rwlock_init(&sip->macc_lck); |
---|
| 7048 | + return (int)n_idx; |
---|
| 7049 | +err: |
---|
| 7050 | + sdebug_erase_store((int)n_idx, sip); |
---|
| 7051 | + pr_warn("%s: failed, errno=%d\n", __func__, -res); |
---|
| 7052 | + return res; |
---|
| 7053 | +} |
---|
| 7054 | + |
---|
| 7055 | +static int sdebug_add_host_helper(int per_host_idx) |
---|
| 7056 | +{ |
---|
| 7057 | + int k, devs_per_host, idx; |
---|
| 7058 | + int error = -ENOMEM; |
---|
5567 | 7059 | struct sdebug_host_info *sdbg_host; |
---|
5568 | 7060 | struct sdebug_dev_info *sdbg_devinfo, *tmp; |
---|
5569 | 7061 | |
---|
5570 | 7062 | sdbg_host = kzalloc(sizeof(*sdbg_host), GFP_KERNEL); |
---|
5571 | | - if (sdbg_host == NULL) { |
---|
5572 | | - pr_err("out of memory at line %d\n", __LINE__); |
---|
| 7063 | + if (!sdbg_host) |
---|
5573 | 7064 | return -ENOMEM; |
---|
5574 | | - } |
---|
| 7065 | + idx = (per_host_idx < 0) ? sdeb_first_idx : per_host_idx; |
---|
| 7066 | + if (xa_get_mark(per_store_ap, idx, SDEB_XA_NOT_IN_USE)) |
---|
| 7067 | + xa_clear_mark(per_store_ap, idx, SDEB_XA_NOT_IN_USE); |
---|
| 7068 | + sdbg_host->si_idx = idx; |
---|
5575 | 7069 | |
---|
5576 | 7070 | INIT_LIST_HEAD(&sdbg_host->dev_info_list); |
---|
5577 | 7071 | |
---|
5578 | 7072 | devs_per_host = sdebug_num_tgts * sdebug_max_luns; |
---|
5579 | 7073 | for (k = 0; k < devs_per_host; k++) { |
---|
5580 | 7074 | sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL); |
---|
5581 | | - if (!sdbg_devinfo) { |
---|
5582 | | - pr_err("out of memory at line %d\n", __LINE__); |
---|
5583 | | - error = -ENOMEM; |
---|
| 7075 | + if (!sdbg_devinfo) |
---|
5584 | 7076 | goto clean; |
---|
5585 | | - } |
---|
5586 | 7077 | } |
---|
5587 | 7078 | |
---|
5588 | 7079 | spin_lock(&sdebug_host_list_lock); |
---|
.. | .. |
---|
5592 | 7083 | sdbg_host->dev.bus = &pseudo_lld_bus; |
---|
5593 | 7084 | sdbg_host->dev.parent = pseudo_primary; |
---|
5594 | 7085 | sdbg_host->dev.release = &sdebug_release_adapter; |
---|
5595 | | - dev_set_name(&sdbg_host->dev, "adapter%d", sdebug_add_host); |
---|
| 7086 | + dev_set_name(&sdbg_host->dev, "adapter%d", sdebug_num_hosts); |
---|
5596 | 7087 | |
---|
5597 | 7088 | error = device_register(&sdbg_host->dev); |
---|
5598 | | - |
---|
5599 | | - if (error) |
---|
| 7089 | + if (error) { |
---|
| 7090 | + spin_lock(&sdebug_host_list_lock); |
---|
| 7091 | + list_del(&sdbg_host->host_list); |
---|
| 7092 | + spin_unlock(&sdebug_host_list_lock); |
---|
5600 | 7093 | goto clean; |
---|
| 7094 | + } |
---|
5601 | 7095 | |
---|
5602 | | - ++sdebug_add_host; |
---|
5603 | | - return error; |
---|
| 7096 | + ++sdebug_num_hosts; |
---|
| 7097 | + return 0; |
---|
5604 | 7098 | |
---|
5605 | 7099 | clean: |
---|
5606 | 7100 | list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list, |
---|
5607 | 7101 | dev_list) { |
---|
5608 | 7102 | list_del(&sdbg_devinfo->dev_list); |
---|
| 7103 | + kfree(sdbg_devinfo->zstate); |
---|
5609 | 7104 | kfree(sdbg_devinfo); |
---|
5610 | 7105 | } |
---|
5611 | | - |
---|
5612 | | - kfree(sdbg_host); |
---|
| 7106 | + if (sdbg_host->dev.release) |
---|
| 7107 | + put_device(&sdbg_host->dev); |
---|
| 7108 | + else |
---|
| 7109 | + kfree(sdbg_host); |
---|
| 7110 | + pr_warn("%s: failed, errno=%d\n", __func__, -error); |
---|
5613 | 7111 | return error; |
---|
5614 | 7112 | } |
---|
5615 | 7113 | |
---|
5616 | | -static void sdebug_remove_adapter(void) |
---|
| 7114 | +static int sdebug_do_add_host(bool mk_new_store) |
---|
5617 | 7115 | { |
---|
| 7116 | + int ph_idx = sdeb_most_recent_idx; |
---|
| 7117 | + |
---|
| 7118 | + if (mk_new_store) { |
---|
| 7119 | + ph_idx = sdebug_add_store(); |
---|
| 7120 | + if (ph_idx < 0) |
---|
| 7121 | + return ph_idx; |
---|
| 7122 | + } |
---|
| 7123 | + return sdebug_add_host_helper(ph_idx); |
---|
| 7124 | +} |
---|
| 7125 | + |
---|
| 7126 | +static void sdebug_do_remove_host(bool the_end) |
---|
| 7127 | +{ |
---|
| 7128 | + int idx = -1; |
---|
5618 | 7129 | struct sdebug_host_info *sdbg_host = NULL; |
---|
| 7130 | + struct sdebug_host_info *sdbg_host2; |
---|
5619 | 7131 | |
---|
5620 | 7132 | spin_lock(&sdebug_host_list_lock); |
---|
5621 | 7133 | if (!list_empty(&sdebug_host_list)) { |
---|
5622 | 7134 | sdbg_host = list_entry(sdebug_host_list.prev, |
---|
5623 | 7135 | struct sdebug_host_info, host_list); |
---|
5624 | | - list_del(&sdbg_host->host_list); |
---|
| 7136 | + idx = sdbg_host->si_idx; |
---|
5625 | 7137 | } |
---|
| 7138 | + if (!the_end && idx >= 0) { |
---|
| 7139 | + bool unique = true; |
---|
| 7140 | + |
---|
| 7141 | + list_for_each_entry(sdbg_host2, &sdebug_host_list, host_list) { |
---|
| 7142 | + if (sdbg_host2 == sdbg_host) |
---|
| 7143 | + continue; |
---|
| 7144 | + if (idx == sdbg_host2->si_idx) { |
---|
| 7145 | + unique = false; |
---|
| 7146 | + break; |
---|
| 7147 | + } |
---|
| 7148 | + } |
---|
| 7149 | + if (unique) { |
---|
| 7150 | + xa_set_mark(per_store_ap, idx, SDEB_XA_NOT_IN_USE); |
---|
| 7151 | + if (idx == sdeb_most_recent_idx) |
---|
| 7152 | + --sdeb_most_recent_idx; |
---|
| 7153 | + } |
---|
| 7154 | + } |
---|
| 7155 | + if (sdbg_host) |
---|
| 7156 | + list_del(&sdbg_host->host_list); |
---|
5626 | 7157 | spin_unlock(&sdebug_host_list_lock); |
---|
5627 | 7158 | |
---|
5628 | 7159 | if (!sdbg_host) |
---|
5629 | 7160 | return; |
---|
5630 | 7161 | |
---|
5631 | 7162 | device_unregister(&sdbg_host->dev); |
---|
5632 | | - --sdebug_add_host; |
---|
| 7163 | + --sdebug_num_hosts; |
---|
5633 | 7164 | } |
---|
5634 | 7165 | |
---|
5635 | 7166 | static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth) |
---|
.. | .. |
---|
5674 | 7205 | return false; |
---|
5675 | 7206 | } |
---|
5676 | 7207 | |
---|
5677 | | -static bool fake_host_busy(struct scsi_cmnd *scp) |
---|
| 7208 | +/* Response to TUR or media access command when device stopped */ |
---|
| 7209 | +static int resp_not_ready(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) |
---|
5678 | 7210 | { |
---|
5679 | | - return (sdebug_opts & SDEBUG_OPT_HOST_BUSY) && |
---|
5680 | | - (atomic_read(&sdebug_cmnd_count) % abs(sdebug_every_nth)) == 0; |
---|
| 7211 | + int stopped_state; |
---|
| 7212 | + u64 diff_ns = 0; |
---|
| 7213 | + ktime_t now_ts = ktime_get_boottime(); |
---|
| 7214 | + struct scsi_device *sdp = scp->device; |
---|
| 7215 | + |
---|
| 7216 | + stopped_state = atomic_read(&devip->stopped); |
---|
| 7217 | + if (stopped_state == 2) { |
---|
| 7218 | + if (ktime_to_ns(now_ts) > ktime_to_ns(devip->create_ts)) { |
---|
| 7219 | + diff_ns = ktime_to_ns(ktime_sub(now_ts, devip->create_ts)); |
---|
| 7220 | + if (diff_ns >= ((u64)sdeb_tur_ms_to_ready * 1000000)) { |
---|
| 7221 | + /* tur_ms_to_ready timer extinguished */ |
---|
| 7222 | + atomic_set(&devip->stopped, 0); |
---|
| 7223 | + return 0; |
---|
| 7224 | + } |
---|
| 7225 | + } |
---|
| 7226 | + mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x1); |
---|
| 7227 | + if (sdebug_verbose) |
---|
| 7228 | + sdev_printk(KERN_INFO, sdp, |
---|
| 7229 | + "%s: Not ready: in process of becoming ready\n", my_name); |
---|
| 7230 | + if (scp->cmnd[0] == TEST_UNIT_READY) { |
---|
| 7231 | + u64 tur_nanosecs_to_ready = (u64)sdeb_tur_ms_to_ready * 1000000; |
---|
| 7232 | + |
---|
| 7233 | + if (diff_ns <= tur_nanosecs_to_ready) |
---|
| 7234 | + diff_ns = tur_nanosecs_to_ready - diff_ns; |
---|
| 7235 | + else |
---|
| 7236 | + diff_ns = tur_nanosecs_to_ready; |
---|
| 7237 | + /* As per 20-061r2 approved for spc6 by T10 on 20200716 */ |
---|
| 7238 | + do_div(diff_ns, 1000000); /* diff_ns becomes milliseconds */ |
---|
| 7239 | + scsi_set_sense_information(scp->sense_buffer, SCSI_SENSE_BUFFERSIZE, |
---|
| 7240 | + diff_ns); |
---|
| 7241 | + return check_condition_result; |
---|
| 7242 | + } |
---|
| 7243 | + } |
---|
| 7244 | + mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2); |
---|
| 7245 | + if (sdebug_verbose) |
---|
| 7246 | + sdev_printk(KERN_INFO, sdp, "%s: Not ready: initializing command required\n", |
---|
| 7247 | + my_name); |
---|
| 7248 | + return check_condition_result; |
---|
5681 | 7249 | } |
---|
5682 | 7250 | |
---|
5683 | 7251 | static int scsi_debug_queuecommand(struct Scsi_Host *shost, |
---|
.. | .. |
---|
5693 | 7261 | int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *) = NULL; |
---|
5694 | 7262 | int k, na; |
---|
5695 | 7263 | int errsts = 0; |
---|
| 7264 | + u64 lun_index = sdp->lun & 0x3FFF; |
---|
5696 | 7265 | u32 flags; |
---|
5697 | 7266 | u16 sa; |
---|
5698 | 7267 | u8 opcode = cmd[0]; |
---|
5699 | 7268 | bool has_wlun_rl; |
---|
| 7269 | + bool inject_now; |
---|
5700 | 7270 | |
---|
5701 | 7271 | scsi_set_resid(scp, 0); |
---|
5702 | | - if (sdebug_statistics) |
---|
| 7272 | + if (sdebug_statistics) { |
---|
5703 | 7273 | atomic_inc(&sdebug_cmnd_count); |
---|
| 7274 | + inject_now = inject_on_this_cmd(); |
---|
| 7275 | + } else { |
---|
| 7276 | + inject_now = false; |
---|
| 7277 | + } |
---|
5704 | 7278 | if (unlikely(sdebug_verbose && |
---|
5705 | 7279 | !(SDEBUG_OPT_NO_CDB_NOISE & sdebug_opts))) { |
---|
5706 | 7280 | char b[120]; |
---|
.. | .. |
---|
5718 | 7292 | sdev_printk(KERN_INFO, sdp, "%s: tag=%#x, cmd %s\n", my_name, |
---|
5719 | 7293 | blk_mq_unique_tag(scp->request), b); |
---|
5720 | 7294 | } |
---|
5721 | | - if (fake_host_busy(scp)) |
---|
| 7295 | + if (unlikely(inject_now && (sdebug_opts & SDEBUG_OPT_HOST_BUSY))) |
---|
5722 | 7296 | return SCSI_MLQUEUE_HOST_BUSY; |
---|
5723 | 7297 | has_wlun_rl = (sdp->lun == SCSI_W_LUN_REPORT_LUNS); |
---|
5724 | | - if (unlikely((sdp->lun >= sdebug_max_luns) && !has_wlun_rl)) |
---|
| 7298 | + if (unlikely(lun_index >= sdebug_max_luns && !has_wlun_rl)) |
---|
5725 | 7299 | goto err_out; |
---|
5726 | 7300 | |
---|
5727 | 7301 | sdeb_i = opcode_ind_arr[opcode]; /* fully mapped */ |
---|
.. | .. |
---|
5732 | 7306 | if (NULL == devip) |
---|
5733 | 7307 | goto err_out; |
---|
5734 | 7308 | } |
---|
| 7309 | + if (unlikely(inject_now && !atomic_read(&sdeb_inject_pending))) |
---|
| 7310 | + atomic_set(&sdeb_inject_pending, 1); |
---|
| 7311 | + |
---|
5735 | 7312 | na = oip->num_attached; |
---|
5736 | 7313 | r_pfp = oip->pfp; |
---|
5737 | 7314 | if (na) { /* multiple commands with this opcode */ |
---|
.. | .. |
---|
5796 | 7373 | if (errsts) |
---|
5797 | 7374 | goto check_cond; |
---|
5798 | 7375 | } |
---|
5799 | | - if (unlikely((F_M_ACCESS & flags) && atomic_read(&devip->stopped))) { |
---|
5800 | | - mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2); |
---|
5801 | | - if (sdebug_verbose) |
---|
5802 | | - sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: " |
---|
5803 | | - "%s\n", my_name, "initializing command " |
---|
5804 | | - "required"); |
---|
5805 | | - errsts = check_condition_result; |
---|
5806 | | - goto fini; |
---|
| 7376 | + if (unlikely(((F_M_ACCESS & flags) || scp->cmnd[0] == TEST_UNIT_READY) && |
---|
| 7377 | + atomic_read(&devip->stopped))) { |
---|
| 7378 | + errsts = resp_not_ready(scp, devip); |
---|
| 7379 | + if (errsts) |
---|
| 7380 | + goto fini; |
---|
5807 | 7381 | } |
---|
5808 | 7382 | if (sdebug_fake_rw && (F_FAKE_RW & flags)) |
---|
5809 | 7383 | goto fini; |
---|
.. | .. |
---|
5817 | 7391 | pfp = r_pfp; /* if leaf function ptr NULL, try the root's */ |
---|
5818 | 7392 | |
---|
5819 | 7393 | fini: |
---|
5820 | | - if (F_DELAY_OVERR & flags) |
---|
| 7394 | + if (F_DELAY_OVERR & flags) /* cmds like INQUIRY respond asap */ |
---|
5821 | 7395 | return schedule_resp(scp, devip, errsts, pfp, 0, 0); |
---|
5822 | 7396 | else if ((flags & F_LONG_DELAY) && (sdebug_jdelay > 0 || |
---|
5823 | 7397 | sdebug_ndelay > 10000)) { |
---|
.. | .. |
---|
5863 | 7437 | .sg_tablesize = SG_MAX_SEGMENTS, |
---|
5864 | 7438 | .cmd_per_lun = DEF_CMD_PER_LUN, |
---|
5865 | 7439 | .max_sectors = -1U, |
---|
5866 | | - .use_clustering = DISABLE_CLUSTERING, |
---|
| 7440 | + .max_segment_size = -1U, |
---|
5867 | 7441 | .module = THIS_MODULE, |
---|
5868 | 7442 | .track_queue_depth = 1, |
---|
5869 | 7443 | }; |
---|
.. | .. |
---|
5878 | 7452 | sdbg_host = to_sdebug_host(dev); |
---|
5879 | 7453 | |
---|
5880 | 7454 | sdebug_driver_template.can_queue = sdebug_max_queue; |
---|
5881 | | - if (sdebug_clustering) |
---|
5882 | | - sdebug_driver_template.use_clustering = ENABLE_CLUSTERING; |
---|
| 7455 | + if (!sdebug_clustering) |
---|
| 7456 | + sdebug_driver_template.dma_boundary = PAGE_SIZE - 1; |
---|
| 7457 | + |
---|
5883 | 7458 | hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host)); |
---|
5884 | 7459 | if (NULL == hpnt) { |
---|
5885 | 7460 | pr_err("scsi_host_alloc failed\n"); |
---|
.. | .. |
---|
5891 | 7466 | my_name, submit_queues, nr_cpu_ids); |
---|
5892 | 7467 | submit_queues = nr_cpu_ids; |
---|
5893 | 7468 | } |
---|
5894 | | - /* Decide whether to tell scsi subsystem that we want mq */ |
---|
5895 | | - /* Following should give the same answer for each host */ |
---|
5896 | | - if (shost_use_blk_mq(hpnt)) |
---|
5897 | | - hpnt->nr_hw_queues = submit_queues; |
---|
| 7469 | + /* |
---|
| 7470 | + * Decide whether to tell scsi subsystem that we want mq. The |
---|
| 7471 | + * following should give the same answer for each host. |
---|
| 7472 | + */ |
---|
| 7473 | + hpnt->nr_hw_queues = submit_queues; |
---|
| 7474 | + if (sdebug_host_max_queue) |
---|
| 7475 | + hpnt->host_tagset = 1; |
---|
5898 | 7476 | |
---|
5899 | 7477 | sdbg_host->shost = hpnt; |
---|
5900 | 7478 | *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host; |
---|
.. | .. |
---|
5959 | 7537 | pr_err("scsi_add_host failed\n"); |
---|
5960 | 7538 | error = -ENODEV; |
---|
5961 | 7539 | scsi_host_put(hpnt); |
---|
5962 | | - } else |
---|
| 7540 | + } else { |
---|
5963 | 7541 | scsi_scan_host(hpnt); |
---|
| 7542 | + } |
---|
5964 | 7543 | |
---|
5965 | 7544 | return error; |
---|
5966 | 7545 | } |
---|
.. | .. |
---|
5982 | 7561 | list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list, |
---|
5983 | 7562 | dev_list) { |
---|
5984 | 7563 | list_del(&sdbg_devinfo->dev_list); |
---|
| 7564 | + kfree(sdbg_devinfo->zstate); |
---|
5985 | 7565 | kfree(sdbg_devinfo); |
---|
5986 | 7566 | } |
---|
5987 | 7567 | |
---|