Print this page
5513 KM_NORMALPRI should be documented in kmem_alloc(9f) and kmem_cache_create(9f) man pages
14465 Present KM_NOSLEEP_LAZY as documented interface
Change-Id: I002ec28ddf390650f1fcba1ca94f6abfdb241439
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_scsi.c
+++ new/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_scsi.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
25 25 * Copyright (c) 2013 by Delphix. All rights reserved.
26 26 * Copyright 2019 Joyent, Inc.
27 27 */
28 28
29 29 #include <sys/conf.h>
30 30 #include <sys/file.h>
31 31 #include <sys/ddi.h>
32 32 #include <sys/sunddi.h>
33 33 #include <sys/modctl.h>
34 34 #include <sys/scsi/scsi.h>
35 35 #include <sys/scsi/impl/scsi_reset_notify.h>
36 36 #include <sys/scsi/generic/mode.h>
37 37 #include <sys/disp.h>
38 38 #include <sys/byteorder.h>
39 39 #include <sys/atomic.h>
40 40 #include <sys/sdt.h>
41 41 #include <sys/dkio.h>
42 42 #include <sys/dkioc_free_util.h>
43 43
44 44 #include <sys/stmf.h>
45 45 #include <sys/lpif.h>
46 46 #include <sys/portif.h>
47 47 #include <sys/stmf_ioctl.h>
48 48 #include <sys/stmf_sbd_ioctl.h>
49 49
50 50 #include "stmf_sbd.h"
51 51 #include "sbd_impl.h"
52 52
53 53 #define SCSI2_CONFLICT_FREE_CMDS(cdb) ( \
54 54 /* ----------------------- */ \
55 55 /* Refer Both */ \
56 56 /* SPC-2 (rev 20) Table 10 */ \
57 57 /* SPC-3 (rev 23) Table 31 */ \
58 58 /* ----------------------- */ \
59 59 ((cdb[0]) == SCMD_INQUIRY) || \
60 60 ((cdb[0]) == SCMD_LOG_SENSE_G1) || \
61 61 ((cdb[0]) == SCMD_RELEASE) || \
62 62 ((cdb[0]) == SCMD_RELEASE_G1) || \
63 63 ((cdb[0]) == SCMD_REPORT_LUNS) || \
64 64 ((cdb[0]) == SCMD_REQUEST_SENSE) || \
65 65 /* PREVENT ALLOW MEDIUM REMOVAL with prevent == 0 */ \
66 66 ((((cdb[0]) == SCMD_DOORLOCK) && (((cdb[4]) & 0x3) == 0))) || \
67 67 /* SERVICE ACTION IN with READ MEDIA SERIAL NUMBER (0x01) */ \
68 68 (((cdb[0]) == SCMD_SVC_ACTION_IN_G5) && ( \
69 69 ((cdb[1]) & 0x1F) == 0x01)) || \
70 70 /* MAINTENANCE IN with service actions REPORT ALIASES (0x0Bh) */ \
71 71 /* REPORT DEVICE IDENTIFIER (0x05) REPORT PRIORITY (0x0Eh) */ \
72 72 /* REPORT TARGET PORT GROUPS (0x0A) REPORT TIMESTAMP (0x0F) */ \
73 73 (((cdb[0]) == SCMD_MAINTENANCE_IN) && ( \
74 74 (((cdb[1]) & 0x1F) == 0x0B) || \
75 75 (((cdb[1]) & 0x1F) == 0x05) || \
76 76 (((cdb[1]) & 0x1F) == 0x0E) || \
77 77 (((cdb[1]) & 0x1F) == 0x0A) || \
78 78 (((cdb[1]) & 0x1F) == 0x0F))) || \
79 79 /* ----------------------- */ \
80 80 /* SBC-3 (rev 17) Table 3 */ \
81 81 /* ----------------------- */ \
82 82 /* READ CAPACITY(10) */ \
83 83 ((cdb[0]) == SCMD_READ_CAPACITY) || \
84 84 /* READ CAPACITY(16) */ \
85 85 (((cdb[0]) == SCMD_SVC_ACTION_IN_G4) && ( \
86 86 ((cdb[1]) & 0x1F) == 0x10)) || \
87 87 /* START STOP UNIT with START bit 0 and POWER CONDITION 0 */ \
88 88 (((cdb[0]) == SCMD_START_STOP) && ( \
89 89 (((cdb[4]) & 0xF0) == 0) && (((cdb[4]) & 0x01) == 0))))
90 90 /* End of SCSI2_CONFLICT_FREE_CMDS */
91 91
92 92 uint8_t HardwareAcceleratedInit = 1;
93 93 uint8_t sbd_unmap_enable = 1; /* allow unmap by default */
94 94
95 95 /*
96 96 * An /etc/system tunable which specifies the maximum number of LBAs supported
97 97 * in a single UNMAP operation. Default is 0x002000 blocks or 4MB in size.
98 98 */
99 99 int stmf_sbd_unmap_max_nblks = 0x002000;
100 100
101 101 /*
102 102 * An /etc/system tunable which indicates if READ ops can run on the standby
103 103 * path or return an error.
104 104 */
105 105 int stmf_standby_fail_reads = 0;
106 106
107 107 stmf_status_t sbd_lu_reset_state(stmf_lu_t *lu);
108 108 static void sbd_handle_sync_cache(struct scsi_task *task,
109 109 struct stmf_data_buf *initial_dbuf);
110 110 void sbd_handle_read_xfer_completion(struct scsi_task *task,
111 111 sbd_cmd_t *scmd, struct stmf_data_buf *dbuf);
112 112 void sbd_handle_short_write_xfer_completion(scsi_task_t *task,
113 113 stmf_data_buf_t *dbuf);
114 114 void sbd_handle_mode_select_xfer(scsi_task_t *task, uint8_t *buf,
115 115 uint32_t buflen);
116 116 void sbd_handle_mode_select(scsi_task_t *task, stmf_data_buf_t *dbuf);
117 117 void sbd_handle_identifying_info(scsi_task_t *task, stmf_data_buf_t *dbuf);
118 118
119 119 static void sbd_handle_unmap_xfer(scsi_task_t *task, uint8_t *buf,
120 120 uint32_t buflen);
121 121 static void sbd_handle_unmap(scsi_task_t *task, stmf_data_buf_t *dbuf);
122 122
123 123 extern void sbd_pgr_initialize_it(scsi_task_t *, sbd_it_data_t *);
124 124 extern int sbd_pgr_reservation_conflict(scsi_task_t *, struct sbd_lu *sl);
125 125 extern void sbd_pgr_reset(sbd_lu_t *);
126 126 extern void sbd_pgr_remove_it_handle(sbd_lu_t *, sbd_it_data_t *);
127 127 extern void sbd_handle_pgr_in_cmd(scsi_task_t *, stmf_data_buf_t *);
128 128 extern void sbd_handle_pgr_out_cmd(scsi_task_t *, stmf_data_buf_t *);
129 129 extern void sbd_handle_pgr_out_data(scsi_task_t *, stmf_data_buf_t *);
130 130 void sbd_do_sgl_write_xfer(struct scsi_task *task, sbd_cmd_t *scmd,
131 131 int first_xfer);
132 132 static void sbd_handle_write_same(scsi_task_t *task,
133 133 struct stmf_data_buf *initial_dbuf);
134 134 static void sbd_do_write_same_xfer(struct scsi_task *task, sbd_cmd_t *scmd,
135 135 struct stmf_data_buf *dbuf, uint8_t dbuf_reusable);
136 136 static void sbd_handle_write_same_xfer_completion(struct scsi_task *task,
137 137 sbd_cmd_t *scmd, struct stmf_data_buf *dbuf, uint8_t dbuf_reusable);
138 138 /*
139 139 * IMPORTANT NOTE:
140 140 * =================
141 141 * The whole world here is based on the assumption that everything within
142 142 * a scsi task executes in a single threaded manner, even the aborts.
143 143 * Dont ever change that. There wont be any performance gain but there
144 144 * will be tons of race conditions.
145 145 */
146 146
147 147 void
148 148 sbd_do_read_xfer(struct scsi_task *task, sbd_cmd_t *scmd,
149 149 struct stmf_data_buf *dbuf)
150 150 {
151 151 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
152 152 uint64_t laddr;
153 153 uint32_t len, buflen, iolen;
154 154 int ndx;
155 155 int bufs_to_take;
156 156
157 157 /* Lets try not to hog all the buffers the port has. */
158 158 bufs_to_take = ((task->task_max_nbufs > 2) &&
159 159 (task->task_cmd_xfer_length < (32 * 1024))) ? 2 :
160 160 task->task_max_nbufs;
161 161
162 162 len = ATOMIC32_GET(scmd->len) > dbuf->db_buf_size ?
163 163 dbuf->db_buf_size : ATOMIC32_GET(scmd->len);
164 164 laddr = scmd->addr + scmd->current_ro;
165 165
166 166 for (buflen = 0, ndx = 0; (buflen < len) &&
167 167 (ndx < dbuf->db_sglist_length); ndx++) {
168 168 iolen = min(len - buflen, dbuf->db_sglist[ndx].seg_length);
169 169 if (iolen == 0)
170 170 break;
171 171 if (sbd_data_read(sl, task, laddr, (uint64_t)iolen,
172 172 dbuf->db_sglist[ndx].seg_addr) != STMF_SUCCESS) {
173 173 scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
174 174 /* Do not need to do xfer anymore, just complete it */
175 175 dbuf->db_data_size = 0;
176 176 dbuf->db_xfer_status = STMF_SUCCESS;
177 177 sbd_handle_read_xfer_completion(task, scmd, dbuf);
178 178 return;
179 179 }
180 180 buflen += iolen;
181 181 laddr += (uint64_t)iolen;
182 182 }
183 183 dbuf->db_relative_offset = scmd->current_ro;
184 184 dbuf->db_data_size = buflen;
185 185 dbuf->db_flags = DB_DIRECTION_TO_RPORT;
186 186 (void) stmf_xfer_data(task, dbuf, 0);
187 187 atomic_add_32(&scmd->len, -buflen);
188 188 scmd->current_ro += buflen;
189 189 if (ATOMIC32_GET(scmd->len) &&
190 190 (ATOMIC8_GET(scmd->nbufs) < bufs_to_take)) {
191 191 uint32_t maxsize, minsize, old_minsize;
192 192
193 193 maxsize = (ATOMIC32_GET(scmd->len) > (128*1024)) ? 128 * 1024 :
194 194 ATOMIC32_GET(scmd->len);
195 195 minsize = maxsize >> 2;
196 196 do {
197 197 /*
198 198 * A bad port implementation can keep on failing the
199 199 * the request but keep on sending us a false
200 200 * minsize.
201 201 */
202 202 old_minsize = minsize;
203 203 dbuf = stmf_alloc_dbuf(task, maxsize, &minsize, 0);
204 204 } while ((dbuf == NULL) && (old_minsize > minsize) &&
205 205 (minsize >= 512));
206 206 if (dbuf == NULL) {
207 207 return;
208 208 }
209 209 atomic_inc_8(&scmd->nbufs);
210 210 sbd_do_read_xfer(task, scmd, dbuf);
211 211 }
212 212 }
213 213
214 214 /*
215 215 * sbd_zcopy: Bail-out switch for reduced copy path.
216 216 *
217 217 * 0 - read & write off
218 218 * 1 - read & write on
219 219 * 2 - only read on
220 220 * 4 - only write on
221 221 */
222 222 int sbd_zcopy = 1; /* enable zcopy read & write path */
223 223 uint32_t sbd_max_xfer_len = 0; /* Valid if non-zero */
224 224 uint32_t sbd_1st_xfer_len = 0; /* Valid if non-zero */
225 225 uint32_t sbd_copy_threshold = 0; /* Valid if non-zero */
226 226
227 227 static void
228 228 sbd_do_sgl_read_xfer(struct scsi_task *task, sbd_cmd_t *scmd, int first_xfer)
229 229 {
230 230 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
231 231 sbd_zvol_io_t *zvio;
232 232 int ret, final_xfer;
233 233 uint64_t offset;
234 234 uint32_t xfer_len, max_len, first_len;
235 235 stmf_status_t xstat;
236 236 stmf_data_buf_t *dbuf;
237 237 uint_t nblks;
238 238 uint64_t blksize = sl->sl_blksize;
239 239 size_t db_private_sz;
240 240 hrtime_t xfer_start;
241 241 uintptr_t pad;
242 242
243 243 ASSERT(rw_read_held(&sl->sl_access_state_lock));
244 244 ASSERT((sl->sl_flags & SL_MEDIA_LOADED) != 0);
245 245
246 246 /*
247 247 * Calculate the limits on xfer_len to the minimum of :
248 248 * - task limit
249 249 * - lun limit
250 250 * - sbd global limit if set
251 251 * - first xfer limit if set
252 252 *
253 253 * First, protect against silly over-ride value
254 254 */
255 255 if (sbd_max_xfer_len && ((sbd_max_xfer_len % DEV_BSIZE) != 0)) {
256 256 cmn_err(CE_WARN, "sbd_max_xfer_len invalid %d, resetting\n",
257 257 sbd_max_xfer_len);
258 258 sbd_max_xfer_len = 0;
259 259 }
260 260 if (sbd_1st_xfer_len && ((sbd_1st_xfer_len % DEV_BSIZE) != 0)) {
261 261 cmn_err(CE_WARN, "sbd_1st_xfer_len invalid %d, resetting\n",
262 262 sbd_1st_xfer_len);
263 263 sbd_1st_xfer_len = 0;
264 264 }
265 265
266 266 max_len = MIN(task->task_max_xfer_len, sl->sl_max_xfer_len);
267 267 if (sbd_max_xfer_len)
268 268 max_len = MIN(max_len, sbd_max_xfer_len);
269 269 /*
270 270 * Special case the first xfer if hints are set.
271 271 */
272 272 if (first_xfer && (sbd_1st_xfer_len || task->task_1st_xfer_len)) {
273 273 /* global over-ride has precedence */
274 274 if (sbd_1st_xfer_len)
275 275 first_len = sbd_1st_xfer_len;
276 276 else
277 277 first_len = task->task_1st_xfer_len;
278 278 } else {
279 279 first_len = 0;
280 280 }
281 281
282 282 while (ATOMIC32_GET(scmd->len) &&
283 283 ATOMIC8_GET(scmd->nbufs) < task->task_max_nbufs) {
284 284
285 285 xfer_len = MIN(max_len, ATOMIC32_GET(scmd->len));
286 286 if (first_len) {
287 287 xfer_len = MIN(xfer_len, first_len);
288 288 first_len = 0;
289 289 }
290 290 if (ATOMIC32_GET(scmd->len) == xfer_len) {
291 291 final_xfer = 1;
292 292 } else {
293 293 /*
294 294 * Attempt to end xfer on a block boundary.
295 295 * The only way this does not happen is if the
296 296 * xfer_len is small enough to stay contained
297 297 * within the same block.
298 298 */
299 299 uint64_t xfer_offset, xfer_aligned_end;
300 300
301 301 final_xfer = 0;
302 302 xfer_offset = scmd->addr + scmd->current_ro;
303 303 xfer_aligned_end =
304 304 P2ALIGN(xfer_offset+xfer_len, blksize);
305 305 if (xfer_aligned_end > xfer_offset)
306 306 xfer_len = xfer_aligned_end - xfer_offset;
307 307 }
308 308 /*
309 309 * Allocate object to track the read and reserve
310 310 * enough space for scatter/gather list.
311 311 */
312 312 offset = scmd->addr + scmd->current_ro;
313 313 nblks = sbd_zvol_numsegs(sl, offset, xfer_len);
314 314
315 315 db_private_sz = sizeof (*zvio) + sizeof (uintptr_t) /* PAD */ +
316 316 (nblks * sizeof (stmf_sglist_ent_t));
317 317 dbuf = stmf_alloc(STMF_STRUCT_DATA_BUF, db_private_sz,
318 318 AF_DONTZERO);
319 319 /*
320 320 * Setup the dbuf
321 321 *
322 322 * XXX Framework does not handle variable length sglists
323 323 * properly, so setup db_lu_private and db_port_private
324 324 * fields here. db_stmf_private is properly set for
325 325 * calls to stmf_free.
326 326 */
327 327 if (dbuf->db_port_private == NULL) {
328 328 /*
329 329 * XXX Framework assigns space to PP after db_sglist[0]
330 330 */
331 331 cmn_err(CE_PANIC, "db_port_private == NULL");
332 332 }
333 333 pad = (uintptr_t)&dbuf->db_sglist[nblks];
334 334 dbuf->db_lu_private = (void *)P2ROUNDUP(pad, sizeof (pad));
335 335 dbuf->db_port_private = NULL;
336 336 dbuf->db_buf_size = xfer_len;
337 337 dbuf->db_data_size = xfer_len;
338 338 dbuf->db_relative_offset = scmd->current_ro;
339 339 dbuf->db_sglist_length = (uint16_t)nblks;
340 340 dbuf->db_xfer_status = 0;
341 341 dbuf->db_handle = 0;
342 342
343 343 dbuf->db_flags = (DB_DONT_CACHE | DB_DONT_REUSE |
344 344 DB_DIRECTION_TO_RPORT | DB_LU_DATA_BUF);
345 345 if (final_xfer)
346 346 dbuf->db_flags |= DB_SEND_STATUS_GOOD;
347 347
348 348 zvio = dbuf->db_lu_private;
349 349 /* Need absolute offset for zvol access */
350 350 zvio->zvio_offset = offset;
351 351 zvio->zvio_flags = ZVIO_SYNC;
352 352
353 353 /*
354 354 * Accounting for start of read.
355 355 * Note there is no buffer address for the probe yet.
356 356 */
357 357 xfer_start = gethrtime();
358 358 DTRACE_PROBE5(backing__store__read__start, sbd_lu_t *, sl,
359 359 uint8_t *, NULL, uint64_t, xfer_len,
360 360 uint64_t, offset, scsi_task_t *, task);
361 361
362 362 ret = sbd_zvol_alloc_read_bufs(sl, dbuf);
363 363
364 364 stmf_lu_xfer_done(task, B_TRUE /* read */,
365 365 (gethrtime() - xfer_start));
366 366 DTRACE_PROBE6(backing__store__read__end, sbd_lu_t *, sl,
367 367 uint8_t *, NULL, uint64_t, xfer_len,
368 368 uint64_t, offset, int, ret, scsi_task_t *, task);
369 369
370 370 if (ret != 0) {
371 371 /*
372 372 * Read failure from the backend.
373 373 */
374 374 stmf_free(dbuf);
375 375 if (ATOMIC8_GET(scmd->nbufs) == 0) {
376 376 /* nothing queued, just finish */
377 377 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
378 378 sbd_ats_remove_by_task(task);
379 379 stmf_scsilib_send_status(task, STATUS_CHECK,
380 380 STMF_SAA_READ_ERROR);
381 381 rw_exit(&sl->sl_access_state_lock);
382 382 } else {
383 383 /* process failure when other dbufs finish */
384 384 scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
385 385 }
386 386 return;
387 387 }
388 388
389 389 /*
390 390 * Allow PP to do setup
391 391 */
392 392 xstat = stmf_setup_dbuf(task, dbuf, 0);
393 393 if (xstat != STMF_SUCCESS) {
394 394 /*
395 395 * This could happen if the driver cannot get the
396 396 * DDI resources it needs for this request.
397 397 * If other dbufs are queued, try again when the next
398 398 * one completes, otherwise give up.
399 399 */
400 400 sbd_zvol_rele_read_bufs(sl, dbuf);
401 401 stmf_free(dbuf);
402 402 if (ATOMIC8_GET(scmd->nbufs) > 0) {
403 403 /* completion of previous dbuf will retry */
404 404 return;
405 405 }
406 406 /*
407 407 * Done with this command.
408 408 */
409 409 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
410 410 sbd_ats_remove_by_task(task);
411 411 if (first_xfer)
412 412 stmf_scsilib_send_status(task, STATUS_QFULL, 0);
413 413 else
414 414 stmf_scsilib_send_status(task, STATUS_CHECK,
415 415 STMF_SAA_READ_ERROR);
416 416 rw_exit(&sl->sl_access_state_lock);
417 417 return;
418 418 }
419 419 /*
420 420 * dbuf is now queued on task
421 421 */
422 422 atomic_inc_8(&scmd->nbufs);
423 423
424 424 /* XXX leave this in for FW? */
425 425 DTRACE_PROBE4(sbd__xfer, struct scsi_task *, task,
426 426 struct stmf_data_buf *, dbuf, uint64_t, offset,
427 427 uint32_t, xfer_len);
428 428 /*
429 429 * Do not pass STMF_IOF_LU_DONE so that the zvol
430 430 * state can be released in the completion callback.
431 431 */
432 432 xstat = stmf_xfer_data(task, dbuf, 0);
433 433 switch (xstat) {
434 434 case STMF_SUCCESS:
435 435 break;
436 436 case STMF_BUSY:
437 437 /*
438 438 * The dbuf is queued on the task, but unknown
439 439 * to the PP, thus no completion will occur.
440 440 */
441 441 sbd_zvol_rele_read_bufs(sl, dbuf);
442 442 stmf_teardown_dbuf(task, dbuf);
443 443 stmf_free(dbuf);
444 444 atomic_dec_8(&scmd->nbufs);
445 445 if (ATOMIC8_GET(scmd->nbufs) > 0) {
446 446 /* completion of previous dbuf will retry */
447 447 return;
448 448 }
449 449 /*
450 450 * Done with this command.
451 451 */
452 452 rw_exit(&sl->sl_access_state_lock);
453 453 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
454 454 sbd_ats_remove_by_task(task);
455 455 if (first_xfer)
456 456 stmf_scsilib_send_status(task, STATUS_QFULL, 0);
457 457 else
458 458 stmf_scsilib_send_status(task, STATUS_CHECK,
459 459 STMF_SAA_READ_ERROR);
460 460 return;
461 461 case STMF_ABORTED:
462 462 /*
463 463 * Completion from task_done will cleanup
464 464 */
465 465 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
466 466 sbd_ats_remove_by_task(task);
467 467 return;
468 468 }
469 469 /*
470 470 * Update the xfer progress.
471 471 */
472 472 ASSERT(scmd->len >= xfer_len);
473 473 atomic_add_32(&scmd->len, -xfer_len);
474 474 scmd->current_ro += xfer_len;
475 475 }
476 476 }
477 477
478 478 void
479 479 sbd_handle_read_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
480 480 struct stmf_data_buf *dbuf)
481 481 {
482 482 if (dbuf->db_xfer_status != STMF_SUCCESS) {
483 483 stmf_abort(STMF_QUEUE_TASK_ABORT, task,
484 484 dbuf->db_xfer_status, NULL);
485 485 return;
486 486 }
487 487 task->task_nbytes_transferred += dbuf->db_data_size;
488 488 if (ATOMIC32_GET(scmd->len) == 0 ||
489 489 scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
490 490 stmf_free_dbuf(task, dbuf);
491 491 atomic_dec_8(&scmd->nbufs);
492 492 if (ATOMIC8_GET(scmd->nbufs))
493 493 return; /* wait for all buffers to complete */
494 494 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
495 495 sbd_ats_remove_by_task(task);
496 496 if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL)
497 497 stmf_scsilib_send_status(task, STATUS_CHECK,
498 498 STMF_SAA_READ_ERROR);
499 499 else
500 500 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
501 501 return;
502 502 }
503 503 if (dbuf->db_flags & DB_DONT_REUSE) {
504 504 /* allocate new dbuf */
505 505 uint32_t maxsize, minsize, old_minsize;
506 506 stmf_free_dbuf(task, dbuf);
507 507
508 508 maxsize = (ATOMIC32_GET(scmd->len) > (128*1024)) ?
509 509 128 * 1024 : ATOMIC32_GET(scmd->len);
510 510 minsize = maxsize >> 2;
511 511 do {
512 512 old_minsize = minsize;
513 513 dbuf = stmf_alloc_dbuf(task, maxsize, &minsize, 0);
514 514 } while ((dbuf == NULL) && (old_minsize > minsize) &&
515 515 (minsize >= 512));
516 516 if (dbuf == NULL) {
517 517 atomic_dec_8(&scmd->nbufs);
518 518 if (ATOMIC8_GET(scmd->nbufs) == 0) {
519 519 stmf_abort(STMF_QUEUE_TASK_ABORT, task,
520 520 STMF_ALLOC_FAILURE, NULL);
521 521 }
522 522 return;
523 523 }
524 524 }
525 525 sbd_do_read_xfer(task, scmd, dbuf);
526 526 }
527 527
528 528 /*
529 529 * This routine must release the DMU resources and free the dbuf
530 530 * in all cases. If this is the final dbuf of the task, then drop
531 531 * the reader lock on the LU state. If there are no errors and more
532 532 * work to do, then queue more xfer operations.
533 533 */
534 534 void
535 535 sbd_handle_sgl_read_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
536 536 struct stmf_data_buf *dbuf)
537 537 {
538 538 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
539 539 stmf_status_t xfer_status;
540 540 uint32_t data_size;
541 541 int scmd_err;
542 542
543 543 ASSERT(dbuf->db_lu_private);
544 544 ASSERT(scmd->cmd_type == SBD_CMD_SCSI_READ);
545 545
546 546 atomic_dec_8(&scmd->nbufs); /* account for this dbuf */
547 547 /*
548 548 * Release the DMU resources.
549 549 */
550 550 sbd_zvol_rele_read_bufs(sl, dbuf);
551 551 /*
552 552 * Release the dbuf after retrieving needed fields.
553 553 */
554 554 xfer_status = dbuf->db_xfer_status;
555 555 data_size = dbuf->db_data_size;
556 556 stmf_teardown_dbuf(task, dbuf);
557 557 stmf_free(dbuf);
558 558 /*
559 559 * Release the state lock if this is the last completion.
560 560 * If this is the last dbuf on task and all data has been
561 561 * transferred or an error encountered, then no more dbufs
562 562 * will be queued.
563 563 */
564 564 scmd_err = (((scmd->flags & SBD_SCSI_CMD_ACTIVE) == 0) ||
565 565 (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) ||
566 566 (xfer_status != STMF_SUCCESS));
567 567 if ((ATOMIC8_GET(scmd->nbufs) == 0) &&
568 568 (ATOMIC32_GET(scmd->len) == 0 || scmd_err)) {
569 569 /* all DMU state has been released */
570 570 rw_exit(&sl->sl_access_state_lock);
571 571 }
572 572
573 573 /*
574 574 * If there have been no errors, either complete the task
575 575 * or issue more data xfer operations.
576 576 */
577 577 if (!scmd_err) {
578 578 /*
579 579 * This chunk completed successfully
580 580 */
581 581 task->task_nbytes_transferred += data_size;
582 582 if (ATOMIC8_GET(scmd->nbufs) == 0 &&
583 583 ATOMIC32_GET(scmd->len) == 0) {
584 584 /*
585 585 * This command completed successfully
586 586 *
587 587 * Status was sent along with data, so no status
588 588 * completion will occur. Tell stmf we are done.
589 589 */
590 590 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
591 591 sbd_ats_remove_by_task(task);
592 592 stmf_task_lu_done(task);
593 593 return;
594 594 }
595 595 /*
596 596 * Start more xfers
597 597 */
598 598 sbd_do_sgl_read_xfer(task, scmd, 0);
599 599 return;
600 600 }
601 601 /*
602 602 * Sort out the failure
603 603 */
604 604 if (scmd->flags & SBD_SCSI_CMD_ACTIVE) {
605 605 /*
606 606 * If a previous error occurred, leave the command active
607 607 * and wait for the last completion to send the status check.
608 608 */
609 609 if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
610 610 if (ATOMIC8_GET(scmd->nbufs) == 0) {
611 611 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
612 612 sbd_ats_remove_by_task(task);
613 613 stmf_scsilib_send_status(task, STATUS_CHECK,
614 614 STMF_SAA_READ_ERROR);
615 615 }
616 616 return;
617 617 }
618 618 /*
619 619 * Must have been a failure on current dbuf
620 620 */
621 621 ASSERT(xfer_status != STMF_SUCCESS);
622 622
623 623 /*
624 624 * Actually this is a bug. stmf abort should have reset the
625 625 * active flag but since its been there for some time.
626 626 * I wont change it.
627 627 */
628 628 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
629 629 sbd_ats_remove_by_task(task);
630 630 stmf_abort(STMF_QUEUE_TASK_ABORT, task, xfer_status, NULL);
631 631 }
632 632 }
633 633
634 634 void
635 635 sbd_handle_sgl_write_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
636 636 struct stmf_data_buf *dbuf)
637 637 {
638 638 sbd_zvol_io_t *zvio = dbuf->db_lu_private;
639 639 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
640 640 int ret;
641 641 int scmd_err, scmd_xfer_done;
642 642 stmf_status_t xfer_status = dbuf->db_xfer_status;
643 643 uint32_t data_size = dbuf->db_data_size;
644 644 hrtime_t xfer_start;
645 645
646 646 ASSERT(zvio);
647 647
648 648 /*
649 649 * Allow PP to free up resources before releasing the write bufs
650 650 * as writing to the backend could take some time.
651 651 */
652 652 stmf_teardown_dbuf(task, dbuf);
653 653
654 654 atomic_dec_8(&scmd->nbufs); /* account for this dbuf */
655 655 /*
656 656 * All data was queued and this is the last completion,
657 657 * but there could still be an error.
658 658 */
659 659 scmd_xfer_done = (ATOMIC32_GET(scmd->len) == 0 &&
660 660 (ATOMIC8_GET(scmd->nbufs) == 0));
661 661 scmd_err = (((scmd->flags & SBD_SCSI_CMD_ACTIVE) == 0) ||
662 662 (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) ||
663 663 (xfer_status != STMF_SUCCESS));
664 664
665 665 xfer_start = gethrtime();
666 666 DTRACE_PROBE5(backing__store__write__start, sbd_lu_t *, sl,
667 667 uint8_t *, NULL, uint64_t, data_size,
668 668 uint64_t, zvio->zvio_offset, scsi_task_t *, task);
669 669
670 670 if (scmd_err) {
671 671 /* just return the write buffers */
672 672 sbd_zvol_rele_write_bufs_abort(sl, dbuf);
673 673 ret = 0;
674 674 } else {
675 675 if (scmd_xfer_done)
676 676 zvio->zvio_flags = ZVIO_COMMIT;
677 677 else
678 678 zvio->zvio_flags = 0;
679 679 /* write the data */
680 680 ret = sbd_zvol_rele_write_bufs(sl, dbuf);
681 681 }
682 682
683 683 stmf_lu_xfer_done(task, B_FALSE /* write */,
684 684 (gethrtime() - xfer_start));
685 685 DTRACE_PROBE6(backing__store__write__end, sbd_lu_t *, sl,
686 686 uint8_t *, NULL, uint64_t, data_size,
687 687 uint64_t, zvio->zvio_offset, int, ret, scsi_task_t *, task);
688 688
689 689 if (ret != 0) {
690 690 /* update the error flag */
691 691 scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
692 692 scmd_err = 1;
693 693 }
694 694
695 695 /* Release the dbuf */
696 696 stmf_free(dbuf);
697 697
698 698 /*
699 699 * Release the state lock if this is the last completion.
700 700 * If this is the last dbuf on task and all data has been
701 701 * transferred or an error encountered, then no more dbufs
702 702 * will be queued.
703 703 */
704 704 if ((ATOMIC8_GET(scmd->nbufs) == 0) &&
705 705 (ATOMIC32_GET(scmd->len) == 0 || scmd_err)) {
706 706 /* all DMU state has been released */
707 707 rw_exit(&sl->sl_access_state_lock);
708 708 }
709 709 /*
710 710 * If there have been no errors, either complete the task
711 711 * or issue more data xfer operations.
712 712 */
713 713 if (!scmd_err) {
714 714 /* This chunk completed successfully */
715 715 task->task_nbytes_transferred += data_size;
716 716 if (scmd_xfer_done) {
717 717 /* This command completed successfully */
718 718 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
719 719 sbd_ats_remove_by_task(task);
720 720 if ((scmd->flags & SBD_SCSI_CMD_SYNC_WRITE) &&
721 721 (sbd_flush_data_cache(sl, 0) != SBD_SUCCESS)) {
722 722 stmf_scsilib_send_status(task, STATUS_CHECK,
723 723 STMF_SAA_WRITE_ERROR);
724 724 } else {
725 725 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
726 726 }
727 727 return;
728 728 }
729 729 /*
730 730 * Start more xfers
731 731 */
732 732 sbd_do_sgl_write_xfer(task, scmd, 0);
733 733 return;
734 734 }
735 735 /*
736 736 * Sort out the failure
737 737 */
738 738 if (scmd->flags & SBD_SCSI_CMD_ACTIVE) {
739 739 if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
740 740 if (ATOMIC8_GET(scmd->nbufs) == 0) {
741 741 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
742 742 sbd_ats_remove_by_task(task);
743 743 stmf_scsilib_send_status(task, STATUS_CHECK,
744 744 STMF_SAA_WRITE_ERROR);
745 745 }
746 746 /*
747 747 * Leave the command active until last dbuf completes.
748 748 */
749 749 return;
750 750 }
751 751 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
752 752 sbd_ats_remove_by_task(task);
753 753 ASSERT(xfer_status != STMF_SUCCESS);
754 754 stmf_abort(STMF_QUEUE_TASK_ABORT, task, xfer_status, NULL);
755 755 }
756 756 }
757 757
758 758 /*
759 759 * Handle a copy operation using the zvol interface.
760 760 *
761 761 * Similar to the sbd_data_read/write path, except it goes directly through
762 762 * the zvol interfaces. It can pass a port provider sglist in the
763 763 * form of uio which is lost through the vn_rdwr path.
764 764 *
765 765 * Returns:
766 766 * STMF_SUCCESS - request handled
767 767 * STMF_FAILURE - request not handled, caller must deal with error
768 768 */
769 769 static stmf_status_t
770 770 sbd_copy_rdwr(scsi_task_t *task, uint64_t laddr, stmf_data_buf_t *dbuf,
771 771 int cmd, int commit)
772 772 {
773 773 sbd_lu_t *sl = task->task_lu->lu_provider_private;
774 774 struct uio uio;
775 775 struct iovec *iov, *tiov, iov1[8];
776 776 uint32_t len, resid;
777 777 int ret, i, iovcnt, flags;
778 778 hrtime_t xfer_start;
779 779 boolean_t is_read;
780 780
781 781 ASSERT(cmd == SBD_CMD_SCSI_READ || cmd == SBD_CMD_SCSI_WRITE);
782 782
783 783 is_read = (cmd == SBD_CMD_SCSI_READ) ? B_TRUE : B_FALSE;
784 784 iovcnt = dbuf->db_sglist_length;
785 785 /* use the stack for small iovecs */
786 786 if (iovcnt > 8) {
787 787 iov = kmem_alloc(iovcnt * sizeof (*iov), KM_SLEEP);
788 788 } else {
789 789 iov = &iov1[0];
790 790 }
791 791
792 792 /* Convert dbuf sglist to iovec format */
793 793 len = dbuf->db_data_size;
794 794 resid = len;
795 795 tiov = iov;
796 796 for (i = 0; i < iovcnt; i++) {
797 797 tiov->iov_base = (caddr_t)dbuf->db_sglist[i].seg_addr;
798 798 tiov->iov_len = MIN(resid, dbuf->db_sglist[i].seg_length);
799 799 resid -= tiov->iov_len;
800 800 tiov++;
801 801 }
802 802 if (resid != 0) {
803 803 cmn_err(CE_WARN, "inconsistant sglist rem %d", resid);
804 804 if (iov != &iov1[0])
805 805 kmem_free(iov, iovcnt * sizeof (*iov));
806 806 return (STMF_FAILURE);
807 807 }
808 808 /* Setup the uio struct */
809 809 uio.uio_iov = iov;
810 810 uio.uio_iovcnt = iovcnt;
811 811 uio.uio_loffset = laddr;
812 812 uio.uio_segflg = (short)UIO_SYSSPACE;
813 813 uio.uio_resid = (uint64_t)len;
814 814 uio.uio_llimit = RLIM64_INFINITY;
815 815
816 816 xfer_start = gethrtime();
817 817 if (is_read == B_TRUE) {
818 818 uio.uio_fmode = FREAD;
819 819 uio.uio_extflg = UIO_COPY_CACHED;
820 820 DTRACE_PROBE5(backing__store__read__start, sbd_lu_t *, sl,
821 821 uint8_t *, NULL, uint64_t, len, uint64_t, laddr,
822 822 scsi_task_t *, task);
823 823
824 824 /* Fetch the data */
825 825 ret = sbd_zvol_copy_read(sl, &uio);
826 826
827 827 DTRACE_PROBE6(backing__store__read__end, sbd_lu_t *, sl,
828 828 uint8_t *, NULL, uint64_t, len, uint64_t, laddr, int, ret,
829 829 scsi_task_t *, task);
830 830 } else {
831 831 uio.uio_fmode = FWRITE;
832 832 uio.uio_extflg = UIO_COPY_DEFAULT;
833 833 DTRACE_PROBE5(backing__store__write__start, sbd_lu_t *, sl,
834 834 uint8_t *, NULL, uint64_t, len, uint64_t, laddr,
835 835 scsi_task_t *, task);
836 836
837 837 flags = (commit) ? ZVIO_COMMIT : 0;
838 838 /* Write the data */
839 839 ret = sbd_zvol_copy_write(sl, &uio, flags);
840 840
841 841 DTRACE_PROBE6(backing__store__write__end, sbd_lu_t *, sl,
842 842 uint8_t *, NULL, uint64_t, len, uint64_t, laddr, int, ret,
843 843 scsi_task_t *, task);
844 844 }
845 845 /* finalize accounting */
846 846 stmf_lu_xfer_done(task, is_read, (gethrtime() - xfer_start));
847 847
848 848 if (iov != &iov1[0])
849 849 kmem_free(iov, iovcnt * sizeof (*iov));
850 850 if (ret != 0) {
851 851 /* Backend I/O error */
852 852 return (STMF_FAILURE);
853 853 }
854 854 return (STMF_SUCCESS);
855 855 }
856 856
857 857 void
858 858 sbd_handle_read(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
859 859 {
860 860 uint64_t lba, laddr;
861 861 uint64_t blkcount;
862 862 uint32_t len;
863 863 uint8_t op = task->task_cdb[0];
864 864 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
865 865 sbd_cmd_t *scmd;
866 866 stmf_data_buf_t *dbuf;
867 867 int fast_path;
868 868 boolean_t fua_bit = B_FALSE;
869 869
870 870 /*
871 871 * Check to see if the command is READ(10), READ(12), or READ(16).
872 872 * If it is then check for bit 3 being set to indicate if Forced
873 873 * Unit Access is being requested. If so, we'll bypass the use of
874 874 * DMA buffers to simplify support of this feature.
875 875 */
876 876 if (((op == SCMD_READ_G1) || (op == SCMD_READ_G4) ||
877 877 (op == SCMD_READ_G5)) &&
878 878 (task->task_cdb[1] & BIT_3)) {
879 879 fua_bit = B_TRUE;
880 880 }
881 881 if (op == SCMD_READ) {
882 882 lba = READ_SCSI21(&task->task_cdb[1], uint64_t);
883 883 len = (uint32_t)task->task_cdb[4];
884 884
885 885 if (len == 0) {
886 886 len = 256;
887 887 }
888 888 } else if (op == SCMD_READ_G1) {
889 889 lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
890 890 len = READ_SCSI16(&task->task_cdb[7], uint32_t);
891 891 } else if (op == SCMD_READ_G5) {
892 892 lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
893 893 len = READ_SCSI32(&task->task_cdb[6], uint32_t);
894 894 } else if (op == SCMD_READ_G4) {
895 895 lba = READ_SCSI64(&task->task_cdb[2], uint64_t);
896 896 len = READ_SCSI32(&task->task_cdb[10], uint32_t);
897 897 } else {
898 898 stmf_scsilib_send_status(task, STATUS_CHECK,
899 899 STMF_SAA_INVALID_OPCODE);
900 900 return;
901 901 }
902 902
903 903 laddr = lba << sl->sl_data_blocksize_shift;
904 904 blkcount = len;
905 905 len <<= sl->sl_data_blocksize_shift;
906 906
907 907 if ((laddr + (uint64_t)len) > sl->sl_lu_size) {
908 908 stmf_scsilib_send_status(task, STATUS_CHECK,
909 909 STMF_SAA_LBA_OUT_OF_RANGE);
910 910 return;
911 911 }
912 912
913 913 task->task_cmd_xfer_length = len;
914 914 if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
915 915 task->task_expected_xfer_length = len;
916 916 }
917 917
918 918 if (len != task->task_expected_xfer_length) {
919 919 fast_path = 0;
920 920 len = (len > task->task_expected_xfer_length) ?
921 921 task->task_expected_xfer_length : len;
922 922 } else {
923 923 fast_path = 1;
924 924 }
925 925
926 926 if (len == 0) {
927 927 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
928 928 return;
929 929 }
930 930
931 931 if (sbd_ats_handling_before_io(task, sl, lba, blkcount) !=
932 932 SBD_SUCCESS) {
933 933 if (stmf_task_poll_lu(task, 10) != STMF_SUCCESS) {
934 934 stmf_scsilib_send_status(task, STATUS_BUSY, 0);
935 935 }
936 936 return;
937 937 }
938 938 /*
939 939 * Determine if this read can directly use DMU buffers.
940 940 */
941 941 if (sbd_zcopy & (2|1) && /* Debug switch */
942 942 initial_dbuf == NULL && /* No PP buffer passed in */
943 943 sl->sl_flags & SL_CALL_ZVOL && /* zvol backing store */
944 944 (task->task_additional_flags &
945 945 TASK_AF_ACCEPT_LU_DBUF) && /* PP allows it */
946 946 !fua_bit) {
947 947 /*
948 948 * Reduced copy path
949 949 */
950 950 uint32_t copy_threshold, minsize;
951 951 int ret;
952 952
953 953 /*
954 954 * The sl_access_state_lock will be held shared
955 955 * for the entire request and released when all
956 956 * dbufs have completed.
957 957 */
958 958 rw_enter(&sl->sl_access_state_lock, RW_READER);
959 959 if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
960 960 rw_exit(&sl->sl_access_state_lock);
961 961 sbd_ats_remove_by_task(task);
962 962 stmf_scsilib_send_status(task, STATUS_CHECK,
963 963 STMF_SAA_READ_ERROR);
964 964 return;
965 965 }
966 966
967 967 /*
968 968 * Check if setup is more expensive than copying the data.
969 969 *
970 970 * Use the global over-ride sbd_zcopy_threshold if set.
971 971 */
972 972 copy_threshold = (sbd_copy_threshold > 0) ?
973 973 sbd_copy_threshold : task->task_copy_threshold;
974 974 minsize = len;
975 975 if (len < copy_threshold &&
976 976 (dbuf = stmf_alloc_dbuf(task, len, &minsize, 0)) != 0) {
977 977
978 978 ret = sbd_copy_rdwr(task, laddr, dbuf,
979 979 SBD_CMD_SCSI_READ, 0);
980 980 /* done with the backend */
981 981 rw_exit(&sl->sl_access_state_lock);
982 982 sbd_ats_remove_by_task(task);
983 983 if (ret != 0) {
984 984 /* backend error */
985 985 stmf_scsilib_send_status(task, STATUS_CHECK,
986 986 STMF_SAA_READ_ERROR);
987 987 } else {
988 988 /* send along good data */
989 989 dbuf->db_relative_offset = 0;
990 990 dbuf->db_data_size = len;
991 991 dbuf->db_flags = DB_SEND_STATUS_GOOD |
992 992 DB_DIRECTION_TO_RPORT;
993 993 /* XXX keep for FW? */
994 994 DTRACE_PROBE4(sbd__xfer,
995 995 struct scsi_task *, task,
996 996 struct stmf_data_buf *, dbuf,
997 997 uint64_t, laddr, uint32_t, len);
998 998 (void) stmf_xfer_data(task, dbuf,
999 999 STMF_IOF_LU_DONE);
1000 1000 }
1001 1001 return;
1002 1002 }
1003 1003
1004 1004 /* committed to reduced copy */
1005 1005 if (task->task_lu_private) {
1006 1006 scmd = (sbd_cmd_t *)task->task_lu_private;
1007 1007 } else {
1008 1008 scmd = (sbd_cmd_t *)kmem_alloc(sizeof (sbd_cmd_t),
1009 1009 KM_SLEEP);
1010 1010 task->task_lu_private = scmd;
1011 1011 }
1012 1012 /*
1013 1013 * Setup scmd to track read progress.
1014 1014 */
1015 1015 scmd->flags = SBD_SCSI_CMD_ACTIVE | SBD_SCSI_CMD_ATS_RELATED;
1016 1016 scmd->cmd_type = SBD_CMD_SCSI_READ;
1017 1017 scmd->nbufs = 0;
1018 1018 scmd->addr = laddr;
1019 1019 scmd->len = len;
1020 1020 scmd->current_ro = 0;
1021 1021 /*
1022 1022 * Kick-off the read.
1023 1023 */
1024 1024 sbd_do_sgl_read_xfer(task, scmd, 1);
1025 1025 return;
1026 1026 }
1027 1027
1028 1028 if (initial_dbuf == NULL) {
1029 1029 uint32_t maxsize, minsize, old_minsize;
1030 1030
1031 1031 maxsize = (len > (128*1024)) ? 128*1024 : len;
1032 1032 minsize = maxsize >> 2;
1033 1033 do {
1034 1034 old_minsize = minsize;
1035 1035 initial_dbuf = stmf_alloc_dbuf(task, maxsize,
1036 1036 &minsize, 0);
1037 1037 } while ((initial_dbuf == NULL) && (old_minsize > minsize) &&
1038 1038 (minsize >= 512));
1039 1039 if (initial_dbuf == NULL) {
1040 1040 sbd_ats_remove_by_task(task);
1041 1041 stmf_scsilib_send_status(task, STATUS_QFULL, 0);
1042 1042 return;
1043 1043 }
1044 1044 }
1045 1045 dbuf = initial_dbuf;
1046 1046
1047 1047 if ((dbuf->db_buf_size >= len) && fast_path &&
1048 1048 (dbuf->db_sglist_length == 1)) {
1049 1049 if (sbd_data_read(sl, task, laddr, (uint64_t)len,
1050 1050 dbuf->db_sglist[0].seg_addr) == STMF_SUCCESS) {
1051 1051 dbuf->db_relative_offset = 0;
1052 1052 dbuf->db_data_size = len;
1053 1053 dbuf->db_flags = DB_SEND_STATUS_GOOD |
1054 1054 DB_DIRECTION_TO_RPORT;
1055 1055 /* XXX keep for FW? */
1056 1056 DTRACE_PROBE4(sbd__xfer, struct scsi_task *, task,
1057 1057 struct stmf_data_buf *, dbuf,
1058 1058 uint64_t, laddr, uint32_t, len);
1059 1059 (void) stmf_xfer_data(task, dbuf, STMF_IOF_LU_DONE);
1060 1060 } else {
1061 1061 stmf_scsilib_send_status(task, STATUS_CHECK,
1062 1062 STMF_SAA_READ_ERROR);
1063 1063 }
1064 1064 sbd_ats_remove_by_task(task);
1065 1065 return;
1066 1066 }
1067 1067
1068 1068 if (task->task_lu_private) {
1069 1069 scmd = (sbd_cmd_t *)task->task_lu_private;
1070 1070 } else {
1071 1071 scmd = (sbd_cmd_t *)kmem_alloc(sizeof (sbd_cmd_t), KM_SLEEP);
1072 1072 task->task_lu_private = scmd;
1073 1073 }
1074 1074 scmd->flags = SBD_SCSI_CMD_ACTIVE | SBD_SCSI_CMD_ATS_RELATED;
1075 1075 scmd->cmd_type = SBD_CMD_SCSI_READ;
1076 1076 scmd->nbufs = 1;
1077 1077 scmd->addr = laddr;
1078 1078 scmd->len = len;
1079 1079 scmd->current_ro = 0;
1080 1080
1081 1081 sbd_do_read_xfer(task, scmd, dbuf);
1082 1082 }
1083 1083
1084 1084 void
1085 1085 sbd_do_write_xfer(struct scsi_task *task, sbd_cmd_t *scmd,
1086 1086 struct stmf_data_buf *dbuf, uint8_t dbuf_reusable)
1087 1087 {
1088 1088 uint32_t len;
1089 1089 int bufs_to_take;
1090 1090
1091 1091 if (ATOMIC32_GET(scmd->len) == 0) {
1092 1092 goto DO_WRITE_XFER_DONE;
1093 1093 }
1094 1094
1095 1095 /* Lets try not to hog all the buffers the port has. */
1096 1096 bufs_to_take = ((task->task_max_nbufs > 2) &&
1097 1097 (task->task_cmd_xfer_length < (32 * 1024))) ? 2 :
1098 1098 task->task_max_nbufs;
1099 1099
1100 1100 if ((dbuf != NULL) &&
1101 1101 ((dbuf->db_flags & DB_DONT_REUSE) || (dbuf_reusable == 0))) {
1102 1102 /* free current dbuf and allocate a new one */
1103 1103 stmf_free_dbuf(task, dbuf);
1104 1104 dbuf = NULL;
1105 1105 }
1106 1106 if (ATOMIC8_GET(scmd->nbufs) >= bufs_to_take) {
1107 1107 goto DO_WRITE_XFER_DONE;
1108 1108 }
1109 1109 if (dbuf == NULL) {
1110 1110 uint32_t maxsize, minsize, old_minsize;
1111 1111
1112 1112 maxsize = (ATOMIC32_GET(scmd->len) > (128*1024)) ? 128*1024 :
1113 1113 ATOMIC32_GET(scmd->len);
1114 1114 minsize = maxsize >> 2;
1115 1115 do {
1116 1116 old_minsize = minsize;
1117 1117 dbuf = stmf_alloc_dbuf(task, maxsize, &minsize, 0);
1118 1118 } while ((dbuf == NULL) && (old_minsize > minsize) &&
1119 1119 (minsize >= 512));
1120 1120 if (dbuf == NULL) {
1121 1121 if (ATOMIC8_GET(scmd->nbufs) == 0) {
1122 1122 stmf_abort(STMF_QUEUE_TASK_ABORT, task,
1123 1123 STMF_ALLOC_FAILURE, NULL);
1124 1124 }
1125 1125 return;
1126 1126 }
1127 1127 }
1128 1128
1129 1129 len = ATOMIC32_GET(scmd->len) > dbuf->db_buf_size ? dbuf->db_buf_size :
1130 1130 ATOMIC32_GET(scmd->len);
1131 1131
1132 1132 dbuf->db_relative_offset = scmd->current_ro;
1133 1133 dbuf->db_data_size = len;
1134 1134 dbuf->db_flags = DB_DIRECTION_FROM_RPORT;
1135 1135 (void) stmf_xfer_data(task, dbuf, 0);
1136 1136 /* outstanding port xfers and bufs used */
1137 1137 atomic_inc_8(&scmd->nbufs);
1138 1138 atomic_add_32(&scmd->len, -len);
1139 1139 scmd->current_ro += len;
1140 1140
1141 1141 if ((ATOMIC32_GET(scmd->len) != 0) &&
1142 1142 (ATOMIC8_GET(scmd->nbufs) < bufs_to_take)) {
1143 1143 sbd_do_write_xfer(task, scmd, NULL, 0);
1144 1144 }
1145 1145 return;
1146 1146
1147 1147 DO_WRITE_XFER_DONE:
1148 1148 if (dbuf != NULL) {
1149 1149 stmf_free_dbuf(task, dbuf);
1150 1150 }
1151 1151 }
1152 1152
1153 1153 void
1154 1154 sbd_do_sgl_write_xfer(struct scsi_task *task, sbd_cmd_t *scmd, int first_xfer)
1155 1155 {
1156 1156 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
1157 1157 sbd_zvol_io_t *zvio;
1158 1158 int ret;
1159 1159 uint32_t xfer_len, max_len, first_len;
1160 1160 stmf_status_t xstat;
1161 1161 stmf_data_buf_t *dbuf;
1162 1162 uint_t nblks;
1163 1163 uint64_t blksize = sl->sl_blksize;
1164 1164 uint64_t offset;
1165 1165 size_t db_private_sz;
1166 1166 uintptr_t pad;
1167 1167
1168 1168 ASSERT(rw_read_held(&sl->sl_access_state_lock));
1169 1169 ASSERT((sl->sl_flags & SL_MEDIA_LOADED) != 0);
1170 1170
1171 1171 /*
1172 1172 * Calculate the limits on xfer_len to the minimum of :
1173 1173 * - task limit
1174 1174 * - lun limit
1175 1175 * - sbd global limit if set
1176 1176 * - first xfer limit if set
1177 1177 *
1178 1178 * First, protect against silly over-ride value
1179 1179 */
1180 1180 if (sbd_max_xfer_len && ((sbd_max_xfer_len % DEV_BSIZE) != 0)) {
1181 1181 cmn_err(CE_WARN, "sbd_max_xfer_len invalid %d, resetting\n",
1182 1182 sbd_max_xfer_len);
1183 1183 sbd_max_xfer_len = 0;
1184 1184 }
1185 1185 if (sbd_1st_xfer_len && ((sbd_1st_xfer_len % DEV_BSIZE) != 0)) {
1186 1186 cmn_err(CE_WARN, "sbd_1st_xfer_len invalid %d, resetting\n",
1187 1187 sbd_1st_xfer_len);
1188 1188 sbd_1st_xfer_len = 0;
1189 1189 }
1190 1190
1191 1191 max_len = MIN(task->task_max_xfer_len, sl->sl_max_xfer_len);
1192 1192 if (sbd_max_xfer_len)
1193 1193 max_len = MIN(max_len, sbd_max_xfer_len);
1194 1194 /*
1195 1195 * Special case the first xfer if hints are set.
1196 1196 */
1197 1197 if (first_xfer && (sbd_1st_xfer_len || task->task_1st_xfer_len)) {
1198 1198 /* global over-ride has precedence */
1199 1199 if (sbd_1st_xfer_len)
1200 1200 first_len = sbd_1st_xfer_len;
1201 1201 else
1202 1202 first_len = task->task_1st_xfer_len;
1203 1203 } else {
1204 1204 first_len = 0;
1205 1205 }
1206 1206
1207 1207
1208 1208 while (ATOMIC32_GET(scmd->len) &&
1209 1209 ATOMIC8_GET(scmd->nbufs) < task->task_max_nbufs) {
1210 1210 xfer_len = MIN(max_len, ATOMIC32_GET(scmd->len));
1211 1211 if (first_len) {
1212 1212 xfer_len = MIN(xfer_len, first_len);
1213 1213 first_len = 0;
1214 1214 }
1215 1215 if (xfer_len < ATOMIC32_GET(scmd->len)) {
1216 1216 /*
1217 1217 * Attempt to end xfer on a block boundary.
1218 1218 * The only way this does not happen is if the
1219 1219 * xfer_len is small enough to stay contained
1220 1220 * within the same block.
1221 1221 */
1222 1222 uint64_t xfer_offset, xfer_aligned_end;
1223 1223
1224 1224 xfer_offset = scmd->addr + scmd->current_ro;
1225 1225 xfer_aligned_end =
1226 1226 P2ALIGN(xfer_offset+xfer_len, blksize);
1227 1227 if (xfer_aligned_end > xfer_offset)
1228 1228 xfer_len = xfer_aligned_end - xfer_offset;
1229 1229 }
1230 1230 /*
1231 1231 * Allocate object to track the write and reserve
1232 1232 * enough space for scatter/gather list.
1233 1233 */
1234 1234 offset = scmd->addr + scmd->current_ro;
1235 1235 nblks = sbd_zvol_numsegs(sl, offset, xfer_len);
1236 1236 db_private_sz = sizeof (*zvio) + sizeof (uintptr_t) /* PAD */ +
1237 1237 (nblks * sizeof (stmf_sglist_ent_t));
1238 1238 dbuf = stmf_alloc(STMF_STRUCT_DATA_BUF, db_private_sz,
1239 1239 AF_DONTZERO);
1240 1240
1241 1241 /*
1242 1242 * Setup the dbuf
1243 1243 *
1244 1244 * XXX Framework does not handle variable length sglists
1245 1245 * properly, so setup db_lu_private and db_port_private
1246 1246 * fields here. db_stmf_private is properly set for
1247 1247 * calls to stmf_free.
1248 1248 */
1249 1249 if (dbuf->db_port_private == NULL) {
1250 1250 /*
1251 1251 * XXX Framework assigns space to PP after db_sglist[0]
1252 1252 */
1253 1253 cmn_err(CE_PANIC, "db_port_private == NULL");
1254 1254 }
1255 1255 pad = (uintptr_t)&dbuf->db_sglist[nblks];
1256 1256 dbuf->db_lu_private = (void *)P2ROUNDUP(pad, sizeof (pad));
1257 1257 dbuf->db_port_private = NULL;
1258 1258 dbuf->db_buf_size = xfer_len;
1259 1259 dbuf->db_data_size = xfer_len;
1260 1260 dbuf->db_relative_offset = scmd->current_ro;
1261 1261 dbuf->db_sglist_length = (uint16_t)nblks;
1262 1262 dbuf->db_xfer_status = 0;
1263 1263 dbuf->db_handle = 0;
1264 1264 dbuf->db_flags = (DB_DONT_CACHE | DB_DONT_REUSE |
1265 1265 DB_DIRECTION_FROM_RPORT | DB_LU_DATA_BUF);
1266 1266
1267 1267 zvio = dbuf->db_lu_private;
1268 1268 zvio->zvio_offset = offset;
1269 1269
1270 1270 /* get the buffers */
1271 1271 ret = sbd_zvol_alloc_write_bufs(sl, dbuf);
1272 1272 if (ret != 0) {
1273 1273 /*
1274 1274 * Could not allocate buffers from the backend;
1275 1275 * treat it like an IO error.
1276 1276 */
1277 1277 stmf_free(dbuf);
1278 1278 scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
1279 1279 if (ATOMIC8_GET(scmd->nbufs) == 0) {
1280 1280 /*
1281 1281 * Nothing queued, so no completions coming
1282 1282 */
1283 1283 sbd_ats_remove_by_task(task);
1284 1284 stmf_scsilib_send_status(task, STATUS_CHECK,
1285 1285 STMF_SAA_WRITE_ERROR);
1286 1286 rw_exit(&sl->sl_access_state_lock);
1287 1287 }
1288 1288 /*
1289 1289 * Completions of previous buffers will cleanup.
1290 1290 */
1291 1291 return;
1292 1292 }
1293 1293
1294 1294 /*
1295 1295 * Allow PP to do setup
1296 1296 */
1297 1297 xstat = stmf_setup_dbuf(task, dbuf, 0);
1298 1298 if (xstat != STMF_SUCCESS) {
1299 1299 /*
1300 1300 * This could happen if the driver cannot get the
1301 1301 * DDI resources it needs for this request.
1302 1302 * If other dbufs are queued, try again when the next
1303 1303 * one completes, otherwise give up.
1304 1304 */
1305 1305 sbd_zvol_rele_write_bufs_abort(sl, dbuf);
1306 1306 stmf_free(dbuf);
1307 1307 if (ATOMIC8_GET(scmd->nbufs) > 0) {
1308 1308 /* completion of previous dbuf will retry */
1309 1309 return;
1310 1310 }
1311 1311 /*
1312 1312 * Done with this command.
1313 1313 */
1314 1314 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
1315 1315 sbd_ats_remove_by_task(task);
1316 1316 if (first_xfer)
1317 1317 stmf_scsilib_send_status(task, STATUS_QFULL, 0);
1318 1318 else
1319 1319 stmf_scsilib_send_status(task, STATUS_CHECK,
1320 1320 STMF_SAA_WRITE_ERROR);
1321 1321 rw_exit(&sl->sl_access_state_lock);
1322 1322 return;
1323 1323 }
1324 1324
1325 1325 /*
1326 1326 * dbuf is now queued on task
1327 1327 */
1328 1328 atomic_inc_8(&scmd->nbufs);
1329 1329
1330 1330 xstat = stmf_xfer_data(task, dbuf, 0);
1331 1331 switch (xstat) {
1332 1332 case STMF_SUCCESS:
1333 1333 break;
1334 1334 case STMF_BUSY:
1335 1335 /*
1336 1336 * The dbuf is queued on the task, but unknown
1337 1337 * to the PP, thus no completion will occur.
1338 1338 */
1339 1339 sbd_zvol_rele_write_bufs_abort(sl, dbuf);
1340 1340 stmf_teardown_dbuf(task, dbuf);
1341 1341 stmf_free(dbuf);
1342 1342 atomic_dec_8(&scmd->nbufs);
1343 1343 if (ATOMIC8_GET(scmd->nbufs) > 0) {
1344 1344 /* completion of previous dbuf will retry */
1345 1345 return;
1346 1346 }
1347 1347 /*
1348 1348 * Done with this command.
1349 1349 */
1350 1350 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
1351 1351 sbd_ats_remove_by_task(task);
1352 1352 if (first_xfer)
1353 1353 stmf_scsilib_send_status(task, STATUS_QFULL, 0);
1354 1354 else
1355 1355 stmf_scsilib_send_status(task, STATUS_CHECK,
1356 1356 STMF_SAA_WRITE_ERROR);
1357 1357 rw_exit(&sl->sl_access_state_lock);
1358 1358 return;
1359 1359 case STMF_ABORTED:
1360 1360 /*
1361 1361 * Completion code will cleanup.
1362 1362 */
1363 1363 scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
1364 1364 return;
1365 1365 }
1366 1366 /*
1367 1367 * Update the xfer progress.
1368 1368 */
1369 1369 atomic_add_32(&scmd->len, -xfer_len);
1370 1370 scmd->current_ro += xfer_len;
1371 1371 }
1372 1372 }
1373 1373
1374 1374 void
1375 1375 sbd_handle_write_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
1376 1376 struct stmf_data_buf *dbuf, uint8_t dbuf_reusable)
1377 1377 {
1378 1378 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
1379 1379 uint64_t laddr;
1380 1380 uint32_t buflen, iolen;
1381 1381 int ndx;
1382 1382 uint8_t op = task->task_cdb[0];
1383 1383 boolean_t fua_bit = B_FALSE;
1384 1384
1385 1385 if (ATOMIC8_GET(scmd->nbufs) > 0) {
1386 1386 /*
1387 1387 * Decrement the count to indicate the port xfer
1388 1388 * into the dbuf has completed even though the buf is
1389 1389 * still in use here in the LU provider.
1390 1390 */
1391 1391 atomic_dec_8(&scmd->nbufs);
1392 1392 }
1393 1393
1394 1394 if (dbuf->db_xfer_status != STMF_SUCCESS) {
1395 1395 sbd_ats_remove_by_task(task);
1396 1396 stmf_abort(STMF_QUEUE_TASK_ABORT, task,
1397 1397 dbuf->db_xfer_status, NULL);
1398 1398 return;
1399 1399 }
1400 1400
1401 1401 if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
1402 1402 goto WRITE_XFER_DONE;
1403 1403 }
1404 1404
1405 1405 if (ATOMIC32_GET(scmd->len) != 0) {
1406 1406 /*
1407 1407 * Initiate the next port xfer to occur in parallel
1408 1408 * with writing this buf.
1409 1409 */
1410 1410 sbd_do_write_xfer(task, scmd, NULL, 0);
1411 1411 }
1412 1412
1413 1413 /*
1414 1414 * Check to see if the command is WRITE(10), WRITE(12), or WRITE(16).
1415 1415 * If it is then check for bit 3 being set to indicate if Forced
1416 1416 * Unit Access is being requested. If so, we'll bypass the direct
1417 1417 * call and handle it in sbd_data_write().
1418 1418 */
1419 1419 if (((op == SCMD_WRITE_G1) || (op == SCMD_WRITE_G4) ||
1420 1420 (op == SCMD_WRITE_G5)) && (task->task_cdb[1] & BIT_3)) {
1421 1421 fua_bit = B_TRUE;
1422 1422 }
1423 1423 laddr = scmd->addr + dbuf->db_relative_offset;
1424 1424
1425 1425 /*
1426 1426 * If this is going to a zvol, use the direct call to
1427 1427 * sbd_zvol_copy_{read,write}. The direct call interface is
1428 1428 * restricted to PPs that accept sglists, but that is not required.
1429 1429 */
1430 1430 if (sl->sl_flags & SL_CALL_ZVOL &&
1431 1431 (task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF) &&
1432 1432 (sbd_zcopy & (4|1)) && !fua_bit) {
1433 1433 int commit;
1434 1434
1435 1435 commit = (ATOMIC32_GET(scmd->len) == 0 &&
1436 1436 ATOMIC8_GET(scmd->nbufs) == 0);
1437 1437 rw_enter(&sl->sl_access_state_lock, RW_READER);
1438 1438 if ((sl->sl_flags & SL_MEDIA_LOADED) == 0 ||
1439 1439 sbd_copy_rdwr(task, laddr, dbuf, SBD_CMD_SCSI_WRITE,
1440 1440 commit) != STMF_SUCCESS)
1441 1441 scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
1442 1442 rw_exit(&sl->sl_access_state_lock);
1443 1443 buflen = dbuf->db_data_size;
1444 1444 } else {
1445 1445 for (buflen = 0, ndx = 0; (buflen < dbuf->db_data_size) &&
1446 1446 (ndx < dbuf->db_sglist_length); ndx++) {
1447 1447 iolen = min(dbuf->db_data_size - buflen,
1448 1448 dbuf->db_sglist[ndx].seg_length);
1449 1449 if (iolen == 0)
1450 1450 break;
1451 1451 if (sbd_data_write(sl, task, laddr, (uint64_t)iolen,
1452 1452 dbuf->db_sglist[ndx].seg_addr) != STMF_SUCCESS) {
1453 1453 scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
1454 1454 break;
1455 1455 }
1456 1456 buflen += iolen;
1457 1457 laddr += (uint64_t)iolen;
1458 1458 }
1459 1459 }
1460 1460 task->task_nbytes_transferred += buflen;
1461 1461 WRITE_XFER_DONE:
1462 1462 if (ATOMIC32_GET(scmd->len) == 0 ||
1463 1463 scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
1464 1464 stmf_free_dbuf(task, dbuf);
1465 1465 if (ATOMIC8_GET(scmd->nbufs))
1466 1466 return; /* wait for all buffers to complete */
1467 1467 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
1468 1468 sbd_ats_remove_by_task(task);
1469 1469 if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
1470 1470 stmf_scsilib_send_status(task, STATUS_CHECK,
1471 1471 STMF_SAA_WRITE_ERROR);
1472 1472 } else {
1473 1473 /*
1474 1474 * If SYNC_WRITE flag is on then we need to flush
1475 1475 * cache before sending status.
1476 1476 * Note: this may be a no-op because of how
1477 1477 * SL_WRITEBACK_CACHE_DISABLE and
1478 1478 * SL_FLUSH_ON_DISABLED_WRITECACHE are set, but not
1479 1479 * worth code complexity of checking those in this code
1480 1480 * path, SBD_SCSI_CMD_SYNC_WRITE is rarely set.
1481 1481 */
1482 1482 if ((scmd->flags & SBD_SCSI_CMD_SYNC_WRITE) &&
1483 1483 (sbd_flush_data_cache(sl, 0) != SBD_SUCCESS)) {
1484 1484 stmf_scsilib_send_status(task, STATUS_CHECK,
1485 1485 STMF_SAA_WRITE_ERROR);
1486 1486 } else {
1487 1487 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1488 1488 }
1489 1489 }
1490 1490 return;
1491 1491 }
1492 1492 sbd_do_write_xfer(task, scmd, dbuf, dbuf_reusable);
1493 1493 }
1494 1494
1495 1495 /*
1496 1496 * Return true if copy avoidance is beneficial.
1497 1497 */
1498 1498 static int
1499 1499 sbd_zcopy_write_useful(scsi_task_t *task, uint64_t laddr, uint32_t len,
1500 1500 uint64_t blksize)
1501 1501 {
1502 1502 /*
1503 1503 * If there is a global copy threshold over-ride, use it.
1504 1504 * Otherwise use the PP value with the caveat that at least
1505 1505 * 1/2 the data must avoid being copied to be useful.
1506 1506 */
1507 1507 if (sbd_copy_threshold > 0) {
1508 1508 return (len >= sbd_copy_threshold);
1509 1509 } else {
1510 1510 uint64_t no_copy_span;
1511 1511
1512 1512 /* sub-blocksize writes always copy */
1513 1513 if (len < task->task_copy_threshold || len < blksize)
1514 1514 return (0);
1515 1515 /*
1516 1516 * Calculate amount of data that will avoid the copy path.
1517 1517 * The calculation is only valid if len >= blksize.
1518 1518 */
1519 1519 no_copy_span = P2ALIGN(laddr+len, blksize) -
1520 1520 P2ROUNDUP(laddr, blksize);
1521 1521 return (no_copy_span >= len/2);
1522 1522 }
1523 1523 }
1524 1524
1525 1525 void
1526 1526 sbd_handle_write(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
1527 1527 {
1528 1528 uint64_t lba, laddr;
1529 1529 uint32_t len;
1530 1530 uint8_t op = task->task_cdb[0], do_immediate_data = 0;
1531 1531 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
1532 1532 sbd_cmd_t *scmd;
1533 1533 stmf_data_buf_t *dbuf;
1534 1534 uint64_t blkcount;
1535 1535 uint8_t sync_wr_flag = 0;
1536 1536 boolean_t fua_bit = B_FALSE;
1537 1537
1538 1538 if (sl->sl_flags & SL_WRITE_PROTECTED) {
1539 1539 stmf_scsilib_send_status(task, STATUS_CHECK,
1540 1540 STMF_SAA_WRITE_PROTECTED);
1541 1541 return;
1542 1542 }
1543 1543 /*
1544 1544 * Check to see if the command is WRITE(10), WRITE(12), or WRITE(16).
1545 1545 * If it is then check for bit 3 being set to indicate if Forced
1546 1546 * Unit Access is being requested. If so, we'll bypass the fast path
1547 1547 * code to simplify support of this feature.
1548 1548 */
1549 1549 if (((op == SCMD_WRITE_G1) || (op == SCMD_WRITE_G4) ||
1550 1550 (op == SCMD_WRITE_G5)) && (task->task_cdb[1] & BIT_3)) {
1551 1551 fua_bit = B_TRUE;
1552 1552 }
1553 1553 if (op == SCMD_WRITE) {
1554 1554 lba = READ_SCSI21(&task->task_cdb[1], uint64_t);
1555 1555 len = (uint32_t)task->task_cdb[4];
1556 1556
1557 1557 if (len == 0) {
1558 1558 len = 256;
1559 1559 }
1560 1560 } else if (op == SCMD_WRITE_G1) {
1561 1561 lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
1562 1562 len = READ_SCSI16(&task->task_cdb[7], uint32_t);
1563 1563 } else if (op == SCMD_WRITE_G5) {
1564 1564 lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
1565 1565 len = READ_SCSI32(&task->task_cdb[6], uint32_t);
1566 1566 } else if (op == SCMD_WRITE_G4) {
1567 1567 lba = READ_SCSI64(&task->task_cdb[2], uint64_t);
1568 1568 len = READ_SCSI32(&task->task_cdb[10], uint32_t);
1569 1569 } else if (op == SCMD_WRITE_VERIFY) {
1570 1570 lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
1571 1571 len = READ_SCSI16(&task->task_cdb[7], uint32_t);
1572 1572 sync_wr_flag = SBD_SCSI_CMD_SYNC_WRITE;
1573 1573 } else if (op == SCMD_WRITE_VERIFY_G5) {
1574 1574 lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
1575 1575 len = READ_SCSI32(&task->task_cdb[6], uint32_t);
1576 1576 sync_wr_flag = SBD_SCSI_CMD_SYNC_WRITE;
1577 1577 } else if (op == SCMD_WRITE_VERIFY_G4) {
1578 1578 lba = READ_SCSI64(&task->task_cdb[2], uint64_t);
1579 1579 len = READ_SCSI32(&task->task_cdb[10], uint32_t);
1580 1580 sync_wr_flag = SBD_SCSI_CMD_SYNC_WRITE;
1581 1581 } else {
1582 1582 stmf_scsilib_send_status(task, STATUS_CHECK,
1583 1583 STMF_SAA_INVALID_OPCODE);
1584 1584 return;
1585 1585 }
1586 1586
1587 1587 laddr = lba << sl->sl_data_blocksize_shift;
1588 1588 blkcount = len;
1589 1589 len <<= sl->sl_data_blocksize_shift;
1590 1590
1591 1591 if ((laddr + (uint64_t)len) > sl->sl_lu_size) {
1592 1592 stmf_scsilib_send_status(task, STATUS_CHECK,
1593 1593 STMF_SAA_LBA_OUT_OF_RANGE);
1594 1594 return;
1595 1595 }
1596 1596
1597 1597 task->task_cmd_xfer_length = len;
1598 1598 if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
1599 1599 task->task_expected_xfer_length = len;
1600 1600 }
1601 1601
1602 1602 len = (len > task->task_expected_xfer_length) ?
1603 1603 task->task_expected_xfer_length : len;
1604 1604
1605 1605 if (len == 0) {
1606 1606 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1607 1607 return;
1608 1608 }
1609 1609
1610 1610 if (sbd_ats_handling_before_io(task, sl, lba, blkcount) !=
1611 1611 SBD_SUCCESS) {
1612 1612 if (stmf_task_poll_lu(task, 10) != STMF_SUCCESS) {
1613 1613 stmf_scsilib_send_status(task, STATUS_BUSY, 0);
1614 1614 }
1615 1615 return;
1616 1616 }
1617 1617
1618 1618 if (sbd_zcopy & (4|1) && /* Debug switch */
1619 1619 initial_dbuf == NULL && /* No PP buf passed in */
1620 1620 sl->sl_flags & SL_CALL_ZVOL && /* zvol backing store */
1621 1621 (task->task_additional_flags &
1622 1622 TASK_AF_ACCEPT_LU_DBUF) && /* PP allows it */
1623 1623 sbd_zcopy_write_useful(task, laddr, len, sl->sl_blksize) &&
1624 1624 !fua_bit) {
1625 1625
1626 1626 /*
1627 1627 * XXX Note that disallowing initial_dbuf will eliminate
1628 1628 * iSCSI from participating. For small writes, that is
1629 1629 * probably ok. For large writes, it may be best to just
1630 1630 * copy the data from the initial dbuf and use zcopy for
1631 1631 * the rest.
1632 1632 */
1633 1633 rw_enter(&sl->sl_access_state_lock, RW_READER);
1634 1634 if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
1635 1635 rw_exit(&sl->sl_access_state_lock);
1636 1636 sbd_ats_remove_by_task(task);
1637 1637 stmf_scsilib_send_status(task, STATUS_CHECK,
1638 1638 STMF_SAA_READ_ERROR);
1639 1639 return;
1640 1640 }
1641 1641 /*
1642 1642 * Setup scmd to track the write progress.
1643 1643 */
1644 1644 if (task->task_lu_private) {
1645 1645 scmd = (sbd_cmd_t *)task->task_lu_private;
1646 1646 } else {
1647 1647 scmd = (sbd_cmd_t *)kmem_alloc(sizeof (sbd_cmd_t),
1648 1648 KM_SLEEP);
1649 1649 task->task_lu_private = scmd;
1650 1650 }
1651 1651 scmd->flags = SBD_SCSI_CMD_ACTIVE | SBD_SCSI_CMD_ATS_RELATED |
1652 1652 sync_wr_flag;
1653 1653 scmd->cmd_type = SBD_CMD_SCSI_WRITE;
1654 1654 scmd->nbufs = 0;
1655 1655 scmd->addr = laddr;
1656 1656 scmd->len = len;
1657 1657 scmd->current_ro = 0;
1658 1658 sbd_do_sgl_write_xfer(task, scmd, 1);
1659 1659 return;
1660 1660 }
1661 1661
1662 1662 if ((initial_dbuf != NULL) && (task->task_flags & TF_INITIAL_BURST)) {
1663 1663 if (initial_dbuf->db_data_size > len) {
1664 1664 if (initial_dbuf->db_data_size >
1665 1665 task->task_expected_xfer_length) {
1666 1666 /* protocol error */
1667 1667 stmf_abort(STMF_QUEUE_TASK_ABORT, task,
1668 1668 STMF_INVALID_ARG, NULL);
1669 1669 return;
1670 1670 }
1671 1671 initial_dbuf->db_data_size = len;
1672 1672 }
1673 1673 do_immediate_data = 1;
1674 1674 }
1675 1675 dbuf = initial_dbuf;
1676 1676
1677 1677 if (task->task_lu_private) {
1678 1678 scmd = (sbd_cmd_t *)task->task_lu_private;
1679 1679 } else {
1680 1680 scmd = (sbd_cmd_t *)kmem_alloc(sizeof (sbd_cmd_t), KM_SLEEP);
1681 1681 task->task_lu_private = scmd;
1682 1682 }
1683 1683 scmd->flags = SBD_SCSI_CMD_ACTIVE | SBD_SCSI_CMD_ATS_RELATED |
1684 1684 sync_wr_flag;
1685 1685 scmd->cmd_type = SBD_CMD_SCSI_WRITE;
1686 1686 scmd->nbufs = 0;
1687 1687 scmd->addr = laddr;
1688 1688 scmd->len = len;
1689 1689 scmd->current_ro = 0;
1690 1690
1691 1691 if (do_immediate_data) {
1692 1692 /*
1693 1693 * Account for data passed in this write command
1694 1694 */
1695 1695 (void) stmf_xfer_data(task, dbuf, STMF_IOF_STATS_ONLY);
1696 1696 atomic_add_32(&scmd->len, -dbuf->db_data_size);
1697 1697 scmd->current_ro += dbuf->db_data_size;
1698 1698 dbuf->db_xfer_status = STMF_SUCCESS;
1699 1699 sbd_handle_write_xfer_completion(task, scmd, dbuf, 0);
1700 1700 } else {
1701 1701 sbd_do_write_xfer(task, scmd, dbuf, 0);
1702 1702 }
1703 1703 }
1704 1704
1705 1705 /*
1706 1706 * Utility routine to handle small non performance data transfers to the
1707 1707 * initiators. dbuf is an initial data buf (if any), 'p' points to a data
1708 1708 * buffer which is source of data for transfer, cdb_xfer_size is the
1709 1709 * transfer size based on CDB, cmd_xfer_size is the actual amount of data
1710 1710 * which this command would transfer (the size of data pointed to by 'p').
1711 1711 */
1712 1712 void
1713 1713 sbd_handle_short_read_transfers(scsi_task_t *task, stmf_data_buf_t *dbuf,
1714 1714 uint8_t *p, uint32_t cdb_xfer_size, uint32_t cmd_xfer_size)
1715 1715 {
1716 1716 uint32_t bufsize, ndx;
1717 1717 sbd_cmd_t *scmd;
1718 1718
1719 1719 cmd_xfer_size = min(cmd_xfer_size, cdb_xfer_size);
1720 1720
1721 1721 task->task_cmd_xfer_length = cmd_xfer_size;
1722 1722 if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
1723 1723 task->task_expected_xfer_length = cmd_xfer_size;
1724 1724 } else {
1725 1725 cmd_xfer_size = min(cmd_xfer_size,
1726 1726 task->task_expected_xfer_length);
1727 1727 }
1728 1728
1729 1729 if (cmd_xfer_size == 0) {
1730 1730 stmf_scsilib_send_status(task, STATUS_CHECK,
1731 1731 STMF_SAA_INVALID_FIELD_IN_CDB);
1732 1732 return;
1733 1733 }
1734 1734 if (dbuf == NULL) {
1735 1735 uint32_t minsize = cmd_xfer_size;
1736 1736
1737 1737 dbuf = stmf_alloc_dbuf(task, cmd_xfer_size, &minsize, 0);
1738 1738 }
1739 1739 if (dbuf == NULL) {
1740 1740 stmf_scsilib_send_status(task, STATUS_QFULL, 0);
1741 1741 return;
1742 1742 }
1743 1743
1744 1744 for (bufsize = 0, ndx = 0; bufsize < cmd_xfer_size; ndx++) {
1745 1745 uint8_t *d;
1746 1746 uint32_t s;
1747 1747
1748 1748 d = dbuf->db_sglist[ndx].seg_addr;
1749 1749 s = min((cmd_xfer_size - bufsize),
1750 1750 dbuf->db_sglist[ndx].seg_length);
1751 1751 bcopy(p+bufsize, d, s);
1752 1752 bufsize += s;
1753 1753 }
1754 1754 dbuf->db_relative_offset = 0;
1755 1755 dbuf->db_data_size = cmd_xfer_size;
1756 1756 dbuf->db_flags = DB_DIRECTION_TO_RPORT;
1757 1757
1758 1758 if (task->task_lu_private == NULL) {
1759 1759 task->task_lu_private =
1760 1760 kmem_alloc(sizeof (sbd_cmd_t), KM_SLEEP);
1761 1761 }
1762 1762 scmd = (sbd_cmd_t *)task->task_lu_private;
1763 1763
1764 1764 scmd->cmd_type = SBD_CMD_SMALL_READ;
1765 1765 scmd->flags = SBD_SCSI_CMD_ACTIVE;
1766 1766 (void) stmf_xfer_data(task, dbuf, 0);
1767 1767 }
1768 1768
1769 1769 void
1770 1770 sbd_handle_short_read_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
1771 1771 struct stmf_data_buf *dbuf)
1772 1772 {
1773 1773 if (dbuf->db_xfer_status != STMF_SUCCESS) {
1774 1774 stmf_abort(STMF_QUEUE_TASK_ABORT, task,
1775 1775 dbuf->db_xfer_status, NULL);
1776 1776 return;
1777 1777 }
1778 1778 task->task_nbytes_transferred = dbuf->db_data_size;
1779 1779 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
1780 1780 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1781 1781 }
1782 1782
1783 1783 void
1784 1784 sbd_handle_short_write_transfers(scsi_task_t *task,
1785 1785 stmf_data_buf_t *dbuf, uint32_t cdb_xfer_size)
1786 1786 {
1787 1787 sbd_cmd_t *scmd;
1788 1788
1789 1789 task->task_cmd_xfer_length = cdb_xfer_size;
1790 1790 if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
1791 1791 task->task_expected_xfer_length = cdb_xfer_size;
1792 1792 } else {
1793 1793 cdb_xfer_size = min(cdb_xfer_size,
1794 1794 task->task_expected_xfer_length);
1795 1795 }
1796 1796
1797 1797 if (cdb_xfer_size == 0) {
1798 1798 stmf_scsilib_send_status(task, STATUS_CHECK,
1799 1799 STMF_SAA_INVALID_FIELD_IN_CDB);
1800 1800 return;
1801 1801 }
1802 1802 if (task->task_lu_private == NULL) {
1803 1803 task->task_lu_private = kmem_zalloc(sizeof (sbd_cmd_t),
1804 1804 KM_SLEEP);
1805 1805 } else {
1806 1806 bzero(task->task_lu_private, sizeof (sbd_cmd_t));
1807 1807 }
1808 1808 scmd = (sbd_cmd_t *)task->task_lu_private;
1809 1809 scmd->cmd_type = SBD_CMD_SMALL_WRITE;
1810 1810 scmd->flags = SBD_SCSI_CMD_ACTIVE;
1811 1811 scmd->len = cdb_xfer_size;
1812 1812 if (dbuf == NULL) {
1813 1813 uint32_t minsize = cdb_xfer_size;
1814 1814
1815 1815 dbuf = stmf_alloc_dbuf(task, cdb_xfer_size, &minsize, 0);
1816 1816 if (dbuf == NULL) {
1817 1817 stmf_abort(STMF_QUEUE_TASK_ABORT, task,
1818 1818 STMF_ALLOC_FAILURE, NULL);
1819 1819 return;
1820 1820 }
1821 1821 dbuf->db_data_size = cdb_xfer_size;
1822 1822 dbuf->db_relative_offset = 0;
1823 1823 dbuf->db_flags = DB_DIRECTION_FROM_RPORT;
1824 1824 (void) stmf_xfer_data(task, dbuf, 0);
1825 1825 } else {
1826 1826 if (dbuf->db_data_size < cdb_xfer_size) {
1827 1827 stmf_abort(STMF_QUEUE_TASK_ABORT, task,
1828 1828 STMF_ABORTED, NULL);
1829 1829 return;
1830 1830 }
1831 1831 dbuf->db_data_size = cdb_xfer_size;
1832 1832 sbd_handle_short_write_xfer_completion(task, dbuf);
1833 1833 }
1834 1834 }
1835 1835
1836 1836 void
1837 1837 sbd_handle_short_write_xfer_completion(scsi_task_t *task,
1838 1838 stmf_data_buf_t *dbuf)
1839 1839 {
1840 1840 sbd_cmd_t *scmd;
1841 1841 stmf_status_t st_ret;
1842 1842 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
1843 1843
1844 1844 /*
1845 1845 * For now lets assume we will get only one sglist element
1846 1846 * for short writes. If that ever changes, we should allocate
1847 1847 * a local buffer and copy all the sg elements to one linear space.
1848 1848 */
1849 1849 if ((dbuf->db_xfer_status != STMF_SUCCESS) ||
1850 1850 (dbuf->db_sglist_length > 1)) {
1851 1851 stmf_abort(STMF_QUEUE_TASK_ABORT, task,
1852 1852 dbuf->db_xfer_status, NULL);
1853 1853 return;
1854 1854 }
1855 1855
1856 1856 task->task_nbytes_transferred = dbuf->db_data_size;
1857 1857 scmd = (sbd_cmd_t *)task->task_lu_private;
1858 1858 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
1859 1859
1860 1860 /* Lets find out who to call */
1861 1861 switch (task->task_cdb[0]) {
1862 1862 case SCMD_MODE_SELECT:
1863 1863 case SCMD_MODE_SELECT_G1:
1864 1864 if (sl->sl_access_state == SBD_LU_STANDBY) {
1865 1865 st_ret = stmf_proxy_scsi_cmd(task, dbuf);
1866 1866 if (st_ret != STMF_SUCCESS) {
1867 1867 stmf_scsilib_send_status(task, STATUS_CHECK,
1868 1868 STMF_SAA_LU_NO_ACCESS_UNAVAIL);
1869 1869 }
1870 1870 } else {
1871 1871 sbd_handle_mode_select_xfer(task,
1872 1872 dbuf->db_sglist[0].seg_addr, dbuf->db_data_size);
1873 1873 }
1874 1874 break;
1875 1875 case SCMD_UNMAP:
1876 1876 sbd_handle_unmap_xfer(task,
1877 1877 dbuf->db_sglist[0].seg_addr, dbuf->db_data_size);
1878 1878 break;
1879 1879 case SCMD_EXTENDED_COPY:
1880 1880 sbd_handle_xcopy_xfer(task, dbuf->db_sglist[0].seg_addr);
1881 1881 break;
1882 1882 case SCMD_PERSISTENT_RESERVE_OUT:
1883 1883 if (sl->sl_access_state == SBD_LU_STANDBY) {
1884 1884 st_ret = stmf_proxy_scsi_cmd(task, dbuf);
1885 1885 if (st_ret != STMF_SUCCESS) {
1886 1886 stmf_scsilib_send_status(task, STATUS_CHECK,
1887 1887 STMF_SAA_LU_NO_ACCESS_UNAVAIL);
1888 1888 }
1889 1889 } else {
1890 1890 sbd_handle_pgr_out_data(task, dbuf);
1891 1891 }
1892 1892 break;
1893 1893 default:
1894 1894 /* This should never happen */
1895 1895 stmf_abort(STMF_QUEUE_TASK_ABORT, task,
1896 1896 STMF_ABORTED, NULL);
1897 1897 }
1898 1898 }
1899 1899
1900 1900 void
1901 1901 sbd_handle_read_capacity(struct scsi_task *task,
1902 1902 struct stmf_data_buf *initial_dbuf)
1903 1903 {
1904 1904 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
1905 1905 uint32_t cdb_len;
1906 1906 uint8_t p[32];
1907 1907 uint64_t s;
1908 1908 uint16_t blksize;
1909 1909
1910 1910 s = sl->sl_lu_size >> sl->sl_data_blocksize_shift;
1911 1911 s--;
1912 1912 blksize = ((uint16_t)1) << sl->sl_data_blocksize_shift;
1913 1913
1914 1914 switch (task->task_cdb[0]) {
1915 1915 case SCMD_READ_CAPACITY:
1916 1916 if (s & 0xffffffff00000000ull) {
1917 1917 p[0] = p[1] = p[2] = p[3] = 0xFF;
1918 1918 } else {
1919 1919 p[0] = (s >> 24) & 0xff;
1920 1920 p[1] = (s >> 16) & 0xff;
1921 1921 p[2] = (s >> 8) & 0xff;
1922 1922 p[3] = s & 0xff;
1923 1923 }
1924 1924 p[4] = 0; p[5] = 0;
1925 1925 p[6] = (blksize >> 8) & 0xff;
1926 1926 p[7] = blksize & 0xff;
1927 1927 sbd_handle_short_read_transfers(task, initial_dbuf, p, 8, 8);
1928 1928 break;
1929 1929
1930 1930 case SCMD_SVC_ACTION_IN_G4:
1931 1931 cdb_len = READ_SCSI32(&task->task_cdb[10], uint32_t);
1932 1932 bzero(p, 32);
1933 1933 p[0] = (s >> 56) & 0xff;
1934 1934 p[1] = (s >> 48) & 0xff;
1935 1935 p[2] = (s >> 40) & 0xff;
1936 1936 p[3] = (s >> 32) & 0xff;
1937 1937 p[4] = (s >> 24) & 0xff;
1938 1938 p[5] = (s >> 16) & 0xff;
1939 1939 p[6] = (s >> 8) & 0xff;
1940 1940 p[7] = s & 0xff;
1941 1941 p[10] = (blksize >> 8) & 0xff;
1942 1942 p[11] = blksize & 0xff;
1943 1943 if (sl->sl_flags & SL_UNMAP_ENABLED) {
1944 1944 p[14] = 0x80;
1945 1945 }
1946 1946 sbd_handle_short_read_transfers(task, initial_dbuf, p,
1947 1947 cdb_len, 32);
1948 1948 break;
1949 1949 }
1950 1950 }
1951 1951
1952 1952 void
1953 1953 sbd_calc_geometry(uint64_t s, uint16_t blksize, uint8_t *nsectors,
1954 1954 uint8_t *nheads, uint32_t *ncyl)
1955 1955 {
1956 1956 if (s < (4ull * 1024ull * 1024ull * 1024ull)) {
1957 1957 *nsectors = 32;
1958 1958 *nheads = 8;
1959 1959 } else {
1960 1960 *nsectors = 254;
1961 1961 *nheads = 254;
1962 1962 }
1963 1963 *ncyl = s / ((uint64_t)blksize * (uint64_t)(*nsectors) *
1964 1964 (uint64_t)(*nheads));
1965 1965 }
1966 1966
1967 1967 void
1968 1968 sbd_handle_mode_sense(struct scsi_task *task,
1969 1969 struct stmf_data_buf *initial_dbuf, uint8_t *buf)
1970 1970 {
1971 1971 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
1972 1972 uint32_t cmd_size, n;
1973 1973 uint8_t *cdb;
1974 1974 uint32_t ncyl;
1975 1975 uint8_t nsectors, nheads;
1976 1976 uint8_t page, ctrl, header_size;
1977 1977 uint16_t nbytes;
1978 1978 uint8_t *p;
1979 1979 uint64_t s = sl->sl_lu_size;
1980 1980 uint32_t dev_spec_param_offset;
1981 1981
1982 1982 p = buf; /* buf is assumed to be zeroed out and large enough */
1983 1983 n = 0;
1984 1984 cdb = &task->task_cdb[0];
1985 1985 page = cdb[2] & 0x3F;
1986 1986 ctrl = (cdb[2] >> 6) & 3;
1987 1987
1988 1988 if (cdb[0] == SCMD_MODE_SENSE) {
1989 1989 cmd_size = cdb[4];
1990 1990 header_size = 4;
1991 1991 dev_spec_param_offset = 2;
1992 1992 } else {
1993 1993 cmd_size = READ_SCSI16(&cdb[7], uint32_t);
1994 1994 header_size = 8;
1995 1995 dev_spec_param_offset = 3;
1996 1996 }
1997 1997
1998 1998 /* Now validate the command */
1999 1999 if ((cdb[2] != 0) && (page != MODEPAGE_ALLPAGES) &&
2000 2000 (page != MODEPAGE_CACHING) && (page != MODEPAGE_CTRL_MODE) &&
2001 2001 (page != MODEPAGE_FORMAT) && (page != MODEPAGE_GEOMETRY)) {
2002 2002 stmf_scsilib_send_status(task, STATUS_CHECK,
2003 2003 STMF_SAA_INVALID_FIELD_IN_CDB);
2004 2004 return;
2005 2005 }
2006 2006
2007 2007 /* We will update the length in the mode header at the end */
2008 2008
2009 2009 /* Block dev device specific param in mode param header has wp bit */
2010 2010 if (sl->sl_flags & SL_WRITE_PROTECTED) {
2011 2011 p[n + dev_spec_param_offset] = BIT_7;
2012 2012 }
2013 2013 n += header_size;
2014 2014 /* We are not going to return any block descriptor */
2015 2015
2016 2016 nbytes = ((uint16_t)1) << sl->sl_data_blocksize_shift;
2017 2017 sbd_calc_geometry(s, nbytes, &nsectors, &nheads, &ncyl);
2018 2018
2019 2019 if ((page == MODEPAGE_FORMAT) || (page == MODEPAGE_ALLPAGES)) {
2020 2020 p[n] = 0x03;
2021 2021 p[n+1] = 0x16;
2022 2022 if (ctrl != 1) {
2023 2023 p[n + 11] = nsectors;
2024 2024 p[n + 12] = nbytes >> 8;
2025 2025 p[n + 13] = nbytes & 0xff;
2026 2026 p[n + 20] = 0x80;
2027 2027 }
2028 2028 n += 24;
2029 2029 }
2030 2030 if ((page == MODEPAGE_GEOMETRY) || (page == MODEPAGE_ALLPAGES)) {
2031 2031 p[n] = 0x04;
2032 2032 p[n + 1] = 0x16;
2033 2033 if (ctrl != 1) {
2034 2034 p[n + 2] = ncyl >> 16;
2035 2035 p[n + 3] = ncyl >> 8;
2036 2036 p[n + 4] = ncyl & 0xff;
2037 2037 p[n + 5] = nheads;
2038 2038 p[n + 20] = 0x15;
2039 2039 p[n + 21] = 0x18;
2040 2040 }
2041 2041 n += 24;
2042 2042 }
2043 2043 if ((page == MODEPAGE_CACHING) || (page == MODEPAGE_ALLPAGES)) {
2044 2044 struct mode_caching *mode_caching_page;
2045 2045
2046 2046 mode_caching_page = (struct mode_caching *)&p[n];
2047 2047
2048 2048 mode_caching_page->mode_page.code = MODEPAGE_CACHING;
2049 2049 mode_caching_page->mode_page.ps = 1; /* A saveable page */
2050 2050 mode_caching_page->mode_page.length = 0x12;
2051 2051
2052 2052 switch (ctrl) {
2053 2053 case (0):
2054 2054 /* Current */
2055 2055 if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) == 0) {
2056 2056 mode_caching_page->wce = 1;
2057 2057 }
2058 2058 break;
2059 2059
2060 2060 case (1):
2061 2061 /* Changeable */
2062 2062 if ((sl->sl_flags &
2063 2063 SL_WRITEBACK_CACHE_SET_UNSUPPORTED) == 0) {
2064 2064 mode_caching_page->wce = 1;
2065 2065 }
2066 2066 break;
2067 2067
2068 2068 default:
2069 2069 if ((sl->sl_flags &
2070 2070 SL_SAVED_WRITE_CACHE_DISABLE) == 0) {
2071 2071 mode_caching_page->wce = 1;
2072 2072 }
2073 2073 break;
2074 2074 }
2075 2075 n += (sizeof (struct mode_page) +
2076 2076 mode_caching_page->mode_page.length);
2077 2077 }
2078 2078 if ((page == MODEPAGE_CTRL_MODE) || (page == MODEPAGE_ALLPAGES)) {
2079 2079 struct mode_control_scsi3 *mode_control_page;
2080 2080
2081 2081 mode_control_page = (struct mode_control_scsi3 *)&p[n];
2082 2082
2083 2083 mode_control_page->mode_page.code = MODEPAGE_CTRL_MODE;
2084 2084 mode_control_page->mode_page.length =
2085 2085 PAGELENGTH_MODE_CONTROL_SCSI3;
2086 2086 if (ctrl != 1) {
2087 2087 /* If not looking for changeable values, report this. */
2088 2088 mode_control_page->que_mod = CTRL_QMOD_UNRESTRICT;
2089 2089 }
2090 2090 n += (sizeof (struct mode_page) +
2091 2091 mode_control_page->mode_page.length);
2092 2092 }
2093 2093
2094 2094 if (cdb[0] == SCMD_MODE_SENSE) {
2095 2095 if (n > 255) {
2096 2096 stmf_scsilib_send_status(task, STATUS_CHECK,
2097 2097 STMF_SAA_INVALID_FIELD_IN_CDB);
2098 2098 return;
2099 2099 }
2100 2100 /*
2101 2101 * Mode parameter header length doesn't include the number
2102 2102 * of bytes in the length field, so adjust the count.
2103 2103 * Byte count minus header length field size.
2104 2104 */
2105 2105 buf[0] = (n - header_size) & 0xff;
2106 2106 } else {
2107 2107 /* Byte count minus header length field size. */
2108 2108 buf[1] = (n - header_size) & 0xff;
2109 2109 buf[0] = ((n - header_size) >> 8) & 0xff;
2110 2110 }
2111 2111
2112 2112 sbd_handle_short_read_transfers(task, initial_dbuf, buf,
2113 2113 cmd_size, n);
2114 2114 }
2115 2115
2116 2116 void
2117 2117 sbd_handle_mode_select(scsi_task_t *task, stmf_data_buf_t *dbuf)
2118 2118 {
2119 2119 uint32_t cmd_xfer_len;
2120 2120
2121 2121 if (task->task_cdb[0] == SCMD_MODE_SELECT) {
2122 2122 cmd_xfer_len = (uint32_t)task->task_cdb[4];
2123 2123 } else {
2124 2124 cmd_xfer_len = READ_SCSI16(&task->task_cdb[7], uint32_t);
2125 2125 }
2126 2126
2127 2127 if ((task->task_cdb[1] & 0xFE) != 0x10) {
2128 2128 stmf_scsilib_send_status(task, STATUS_CHECK,
2129 2129 STMF_SAA_INVALID_FIELD_IN_CDB);
2130 2130 return;
2131 2131 }
2132 2132
2133 2133 if (cmd_xfer_len == 0) {
2134 2134 /* zero byte mode selects are allowed */
2135 2135 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
2136 2136 return;
2137 2137 }
2138 2138
2139 2139 sbd_handle_short_write_transfers(task, dbuf, cmd_xfer_len);
2140 2140 }
2141 2141
2142 2142 void
2143 2143 sbd_handle_mode_select_xfer(scsi_task_t *task, uint8_t *buf, uint32_t buflen)
2144 2144 {
2145 2145 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
2146 2146 sbd_it_data_t *it;
2147 2147 int hdr_len, bd_len;
2148 2148 sbd_status_t sret;
2149 2149 int i;
2150 2150
2151 2151 if (task->task_cdb[0] == SCMD_MODE_SELECT) {
2152 2152 hdr_len = 4;
2153 2153 } else {
2154 2154 hdr_len = 8;
2155 2155 }
2156 2156
2157 2157 if (buflen < hdr_len)
2158 2158 goto mode_sel_param_len_err;
2159 2159
2160 2160 bd_len = hdr_len == 4 ? buf[3] : READ_SCSI16(&buf[6], int);
2161 2161
2162 2162 if (buflen < (hdr_len + bd_len + 2))
2163 2163 goto mode_sel_param_len_err;
2164 2164
2165 2165 buf += hdr_len + bd_len;
2166 2166 buflen -= hdr_len + bd_len;
2167 2167
2168 2168 if ((buf[0] != 8) || (buflen != ((uint32_t)buf[1] + 2))) {
2169 2169 goto mode_sel_param_len_err;
2170 2170 }
2171 2171
2172 2172 if (buf[2] & 0xFB) {
2173 2173 goto mode_sel_param_field_err;
2174 2174 }
2175 2175
2176 2176 for (i = 3; i < (buf[1] + 2); i++) {
2177 2177 if (buf[i]) {
2178 2178 goto mode_sel_param_field_err;
2179 2179 }
2180 2180 }
2181 2181
2182 2182 sret = SBD_SUCCESS;
2183 2183
2184 2184 /* All good. Lets handle the write cache change, if any */
2185 2185 if (buf[2] & BIT_2) {
2186 2186 sret = sbd_wcd_set(0, sl);
2187 2187 } else {
2188 2188 sret = sbd_wcd_set(1, sl);
2189 2189 }
2190 2190
2191 2191 if (sret != SBD_SUCCESS) {
2192 2192 stmf_scsilib_send_status(task, STATUS_CHECK,
2193 2193 STMF_SAA_WRITE_ERROR);
2194 2194 return;
2195 2195 }
2196 2196
2197 2197 /* set on the device passed, now set the flags */
2198 2198 mutex_enter(&sl->sl_lock);
2199 2199 if (buf[2] & BIT_2) {
2200 2200 sl->sl_flags &= ~SL_WRITEBACK_CACHE_DISABLE;
2201 2201 } else {
2202 2202 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
2203 2203 }
2204 2204
2205 2205 for (it = sl->sl_it_list; it != NULL; it = it->sbd_it_next) {
2206 2206 if (it == task->task_lu_itl_handle)
2207 2207 continue;
2208 2208 it->sbd_it_ua_conditions |= SBD_UA_MODE_PARAMETERS_CHANGED;
2209 2209 }
2210 2210
2211 2211 if (task->task_cdb[1] & 1) {
2212 2212 if (buf[2] & BIT_2) {
2213 2213 sl->sl_flags &= ~SL_SAVED_WRITE_CACHE_DISABLE;
2214 2214 } else {
2215 2215 sl->sl_flags |= SL_SAVED_WRITE_CACHE_DISABLE;
2216 2216 }
2217 2217 mutex_exit(&sl->sl_lock);
2218 2218 sret = sbd_write_lu_info(sl);
2219 2219 } else {
2220 2220 mutex_exit(&sl->sl_lock);
2221 2221 }
2222 2222 if (sret == SBD_SUCCESS) {
2223 2223 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
2224 2224 } else {
2225 2225 stmf_scsilib_send_status(task, STATUS_CHECK,
2226 2226 STMF_SAA_WRITE_ERROR);
2227 2227 }
2228 2228 return;
2229 2229
2230 2230 mode_sel_param_len_err:
2231 2231 stmf_scsilib_send_status(task, STATUS_CHECK,
2232 2232 STMF_SAA_PARAM_LIST_LENGTH_ERROR);
2233 2233 return;
2234 2234 mode_sel_param_field_err:
2235 2235 stmf_scsilib_send_status(task, STATUS_CHECK,
2236 2236 STMF_SAA_INVALID_FIELD_IN_PARAM_LIST);
2237 2237 }
2238 2238
2239 2239 /*
2240 2240 * Command support added from SPC-4 r24
2241 2241 * Supports info type 0, 2, 127
2242 2242 */
2243 2243 void
2244 2244 sbd_handle_identifying_info(struct scsi_task *task,
2245 2245 stmf_data_buf_t *initial_dbuf)
2246 2246 {
2247 2247 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
2248 2248 uint8_t *cdb;
2249 2249 uint32_t cmd_size;
2250 2250 uint32_t param_len;
2251 2251 uint32_t xfer_size;
2252 2252 uint8_t info_type;
2253 2253 uint8_t *buf, *p;
2254 2254
2255 2255 cdb = &task->task_cdb[0];
2256 2256 cmd_size = READ_SCSI32(&cdb[6], uint32_t);
2257 2257 info_type = cdb[10]>>1;
2258 2258
2259 2259 /* Validate the command */
2260 2260 if (cmd_size < 4) {
2261 2261 stmf_scsilib_send_status(task, STATUS_CHECK,
2262 2262 STMF_SAA_INVALID_FIELD_IN_CDB);
2263 2263 return;
2264 2264 }
2265 2265
2266 2266 p = buf = kmem_zalloc(260, KM_SLEEP);
2267 2267
2268 2268 switch (info_type) {
2269 2269 case 0:
2270 2270 /*
2271 2271 * No value is supplied but this info type
2272 2272 * is mandatory.
2273 2273 */
2274 2274 xfer_size = 4;
2275 2275 break;
2276 2276 case 2:
2277 2277 mutex_enter(&sl->sl_lock);
2278 2278 param_len = strlcpy((char *)(p+4), sl->sl_alias, 256);
2279 2279 mutex_exit(&sl->sl_lock);
2280 2280 /* text info must be null terminated */
2281 2281 if (++param_len > 256)
2282 2282 param_len = 256;
2283 2283 SCSI_WRITE16(p+2, param_len);
2284 2284 xfer_size = param_len + 4;
2285 2285 break;
2286 2286 case 127:
2287 2287 /* 0 and 2 descriptor supported */
2288 2288 SCSI_WRITE16(p+2, 8); /* set param length */
2289 2289 p += 8;
2290 2290 *p = 4; /* set type to 2 (7 hi bits) */
2291 2291 p += 2;
2292 2292 SCSI_WRITE16(p, 256); /* 256 max length */
2293 2293 xfer_size = 12;
2294 2294 break;
2295 2295 default:
2296 2296 stmf_scsilib_send_status(task, STATUS_CHECK,
2297 2297 STMF_SAA_INVALID_FIELD_IN_CDB);
2298 2298 kmem_free(buf, 260);
2299 2299 return;
2300 2300 }
2301 2301 sbd_handle_short_read_transfers(task, initial_dbuf, buf,
2302 2302 cmd_size, xfer_size);
2303 2303 kmem_free(buf, 260);
2304 2304 }
2305 2305
2306 2306 /*
2307 2307 * This function parse through a string, passed to it as a pointer to a string,
2308 2308 * by adjusting the pointer to the first non-space character and returns
2309 2309 * the count/length of the first bunch of non-space characters. Multiple
2310 2310 * Management URLs are stored as a space delimited string in sl_mgmt_url
2311 2311 * field of sbd_lu_t. This function is used to retrieve one url at a time.
2312 2312 *
2313 2313 * i/p : pointer to pointer to a url string
2314 2314 * o/p : Adjust the pointer to the url to the first non white character
2315 2315 * and returns the length of the URL
2316 2316 */
2317 2317 uint16_t
2318 2318 sbd_parse_mgmt_url(char **url_addr)
2319 2319 {
2320 2320 uint16_t url_length = 0;
2321 2321 char *url;
2322 2322 url = *url_addr;
2323 2323
2324 2324 while (*url != '\0') {
2325 2325 if (*url == ' ' || *url == '\t' || *url == '\n') {
2326 2326 (*url_addr)++;
2327 2327 url = *url_addr;
2328 2328 } else {
2329 2329 break;
2330 2330 }
2331 2331 }
2332 2332
2333 2333 while (*url != '\0') {
2334 2334 if (*url == ' ' || *url == '\t' ||
2335 2335 *url == '\n' || *url == '\0') {
2336 2336 break;
2337 2337 }
2338 2338 url++;
2339 2339 url_length++;
2340 2340 }
2341 2341 return (url_length);
2342 2342 }
2343 2343
2344 2344 /* Try to make this the size of a kmem allocation cache. */
2345 2345 static uint_t sbd_write_same_optimal_chunk = 128 * 1024;
2346 2346
2347 2347 static sbd_status_t
2348 2348 sbd_write_same_data(struct scsi_task *task, sbd_cmd_t *scmd)
2349 2349 {
2350 2350 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
2351 2351 uint64_t addr, len, sz_done;
2352 2352 uint32_t big_buf_size, xfer_size, off;
2353 2353 uint8_t *big_buf;
2354 2354 sbd_status_t ret;
2355 2355
2356 2356 if (task->task_cdb[0] == SCMD_WRITE_SAME_G1) {
2357 2357 addr = READ_SCSI32(&task->task_cdb[2], uint64_t);
2358 2358 len = READ_SCSI16(&task->task_cdb[7], uint64_t);
2359 2359 } else {
2360 2360 addr = READ_SCSI64(&task->task_cdb[2], uint64_t);
2361 2361 len = READ_SCSI32(&task->task_cdb[10], uint64_t);
2362 2362 }
2363 2363 addr <<= sl->sl_data_blocksize_shift;
2364 2364 len <<= sl->sl_data_blocksize_shift;
2365 2365
2366 2366 /*
2367 2367 * Reminders:
2368 2368 * "len" is total size of what we wish to "write same".
2369 2369 *
2370 2370 * xfer_size will be scmd->trans_data_len, which is the length
2371 2371 * of the pattern we wish to replicate over "len". We replicate
2372 2372 * "xfer_size" of pattern over "len".
2373 2373 *
2374 2374 * big_buf_size is set to an ideal actual-write size for an output
2375 2375 * operation. It may be the same as "len". If it's not, it should
2376 2376 * be an exact multiple of "xfer_size" so we don't get pattern
2377 2377 * breakage until the very end of "len".
2378 2378 */
2379 2379 big_buf_size = len > sbd_write_same_optimal_chunk ?
2380 2380 sbd_write_same_optimal_chunk : (uint32_t)len;
2381 2381 xfer_size = scmd->trans_data_len;
|
↓ open down ↓ |
2381 lines elided |
↑ open up ↑ |
2382 2382
2383 2383 /*
2384 2384 * All transfers should be an integral multiple of the sector size.
2385 2385 */
2386 2386 ASSERT((big_buf_size % xfer_size) == 0);
2387 2387
2388 2388 /*
2389 2389 * Don't sleep for the allocation, and don't make the system
2390 2390 * reclaim memory. Trade higher I/Os if in a low-memory situation.
2391 2391 */
2392 - big_buf = kmem_alloc(big_buf_size, KM_NOSLEEP | KM_NORMALPRI);
2392 + big_buf = kmem_alloc(big_buf_size, KM_NOSLEEP_LAZY);
2393 2393
2394 2394 if (big_buf == NULL) {
2395 2395 /*
2396 2396 * Just send it in terms of of the transmitted data. This
2397 2397 * will be very slow.
2398 2398 */
2399 2399 DTRACE_PROBE1(write__same__low__memory, uint64_t, big_buf_size);
2400 2400 big_buf = scmd->trans_data;
2401 2401 big_buf_size = scmd->trans_data_len;
2402 2402 } else {
2403 2403 /*
2404 2404 * We already ASSERT()ed big_buf_size is an integral multiple
2405 2405 * of xfer_size.
2406 2406 */
2407 2407 for (off = 0; off < big_buf_size; off += xfer_size)
2408 2408 bcopy(scmd->trans_data, big_buf + off, xfer_size);
2409 2409 }
2410 2410
2411 2411 /* Do the actual I/O. Recycle xfer_size now to be write size. */
2412 2412 DTRACE_PROBE1(write__same__io__begin, uint64_t, len);
2413 2413 for (sz_done = 0; sz_done < len; sz_done += (uint64_t)xfer_size) {
2414 2414 xfer_size = ((big_buf_size + sz_done) <= len) ? big_buf_size :
2415 2415 len - sz_done;
2416 2416 ret = sbd_data_write(sl, task, addr + sz_done,
2417 2417 (uint64_t)xfer_size, big_buf);
2418 2418 if (ret != SBD_SUCCESS)
2419 2419 break;
2420 2420 }
2421 2421 DTRACE_PROBE2(write__same__io__end, uint64_t, len, uint64_t, sz_done);
2422 2422
2423 2423 if (big_buf != scmd->trans_data)
2424 2424 kmem_free(big_buf, big_buf_size);
2425 2425
2426 2426 return (ret);
2427 2427 }
2428 2428
2429 2429 static void
2430 2430 sbd_write_same_release_resources(struct scsi_task *task)
2431 2431 {
2432 2432 sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
2433 2433
2434 2434 if (scmd->nbufs == 0XFF)
2435 2435 cmn_err(CE_WARN, "%s invalid buffer count %x",
2436 2436 __func__, scmd->nbufs);
2437 2437 if ((scmd->trans_data_len != 0) && (scmd->trans_data != NULL))
2438 2438 kmem_free(scmd->trans_data, scmd->trans_data_len);
2439 2439 scmd->trans_data = NULL;
2440 2440 scmd->trans_data_len = 0;
2441 2441 scmd->flags &= ~SBD_SCSI_CMD_TRANS_DATA;
2442 2442 }
2443 2443
2444 2444 static void
2445 2445 sbd_handle_write_same_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
2446 2446 struct stmf_data_buf *dbuf, uint8_t dbuf_reusable)
2447 2447 {
2448 2448 uint64_t laddr;
2449 2449 uint32_t buflen, iolen;
2450 2450 int ndx, ret;
2451 2451
2452 2452 if (ATOMIC8_GET(scmd->nbufs) > 0) {
2453 2453 atomic_dec_8(&scmd->nbufs);
2454 2454 }
2455 2455
2456 2456 if (dbuf->db_xfer_status != STMF_SUCCESS) {
2457 2457 sbd_write_same_release_resources(task);
2458 2458 sbd_ats_remove_by_task(task);
2459 2459 stmf_abort(STMF_QUEUE_TASK_ABORT, task,
2460 2460 dbuf->db_xfer_status, NULL);
2461 2461 return;
2462 2462 }
2463 2463
2464 2464 if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
2465 2465 goto write_same_xfer_done;
2466 2466 }
2467 2467
2468 2468 /* if this is a unnessary callback just return */
2469 2469 if (((scmd->flags & SBD_SCSI_CMD_TRANS_DATA) == 0) ||
2470 2470 ((scmd->flags & SBD_SCSI_CMD_ACTIVE) == 0) ||
2471 2471 (scmd->trans_data == NULL)) {
2472 2472 sbd_ats_remove_by_task(task);
2473 2473 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
2474 2474 return;
2475 2475 }
2476 2476
2477 2477 if (ATOMIC32_GET(scmd->len) != 0) {
2478 2478 /*
2479 2479 * Initiate the next port xfer to occur in parallel
2480 2480 * with writing this buf.
2481 2481 */
2482 2482 sbd_do_write_same_xfer(task, scmd, NULL, 0);
2483 2483 }
2484 2484
2485 2485 laddr = dbuf->db_relative_offset;
2486 2486
2487 2487 for (buflen = 0, ndx = 0; (buflen < dbuf->db_data_size) &&
2488 2488 (ndx < dbuf->db_sglist_length); ndx++) {
2489 2489 iolen = min(dbuf->db_data_size - buflen,
2490 2490 dbuf->db_sglist[ndx].seg_length);
2491 2491 if (iolen == 0)
2492 2492 break;
2493 2493 bcopy(dbuf->db_sglist[ndx].seg_addr, &scmd->trans_data[laddr],
2494 2494 iolen);
2495 2495 buflen += iolen;
2496 2496 laddr += (uint64_t)iolen;
2497 2497 }
2498 2498 task->task_nbytes_transferred += buflen;
2499 2499
2500 2500 write_same_xfer_done:
2501 2501 if (ATOMIC32_GET(scmd->len) == 0 ||
2502 2502 scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
2503 2503 stmf_free_dbuf(task, dbuf);
2504 2504 if (ATOMIC8_GET(scmd->nbufs) > 0)
2505 2505 return;
2506 2506 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
2507 2507 if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
2508 2508 sbd_ats_remove_by_task(task);
2509 2509 sbd_write_same_release_resources(task);
2510 2510 stmf_scsilib_send_status(task, STATUS_CHECK,
2511 2511 STMF_SAA_WRITE_ERROR);
2512 2512 } else {
2513 2513 ret = sbd_write_same_data(task, scmd);
2514 2514 sbd_ats_remove_by_task(task);
2515 2515 sbd_write_same_release_resources(task);
2516 2516 if (ret != SBD_SUCCESS) {
2517 2517 stmf_scsilib_send_status(task, STATUS_CHECK,
2518 2518 STMF_SAA_WRITE_ERROR);
2519 2519 } else {
2520 2520 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
2521 2521 }
2522 2522 }
2523 2523 return;
2524 2524 }
2525 2525 sbd_do_write_same_xfer(task, scmd, dbuf, dbuf_reusable);
2526 2526 }
2527 2527
2528 2528 static void
2529 2529 sbd_do_write_same_xfer(struct scsi_task *task, sbd_cmd_t *scmd,
2530 2530 struct stmf_data_buf *dbuf, uint8_t dbuf_reusable)
2531 2531 {
2532 2532 uint32_t len;
2533 2533
2534 2534 if (ATOMIC32_GET(scmd->len) == 0) {
2535 2535 if (dbuf != NULL)
2536 2536 stmf_free_dbuf(task, dbuf);
2537 2537 return;
2538 2538 }
2539 2539
2540 2540 if ((dbuf != NULL) &&
2541 2541 ((dbuf->db_flags & DB_DONT_REUSE) || (dbuf_reusable == 0))) {
2542 2542 /* free current dbuf and allocate a new one */
2543 2543 stmf_free_dbuf(task, dbuf);
2544 2544 dbuf = NULL;
2545 2545 }
2546 2546 if (dbuf == NULL) {
2547 2547 uint32_t maxsize, minsize, old_minsize;
2548 2548
2549 2549 maxsize = (ATOMIC32_GET(scmd->len) > (128*1024)) ? 128*1024 :
2550 2550 ATOMIC32_GET(scmd->len);
2551 2551 minsize = maxsize >> 2;
2552 2552 do {
2553 2553 old_minsize = minsize;
2554 2554 dbuf = stmf_alloc_dbuf(task, maxsize, &minsize, 0);
2555 2555 } while ((dbuf == NULL) && (old_minsize > minsize) &&
2556 2556 (minsize >= 512));
2557 2557 if (dbuf == NULL) {
2558 2558 sbd_ats_remove_by_task(task);
2559 2559 sbd_write_same_release_resources(task);
2560 2560 if (ATOMIC8_GET(scmd->nbufs) == 0) {
2561 2561 stmf_abort(STMF_QUEUE_TASK_ABORT, task,
2562 2562 STMF_ALLOC_FAILURE, NULL);
2563 2563 }
2564 2564 return;
2565 2565 }
2566 2566 }
2567 2567
2568 2568 len = ATOMIC32_GET(scmd->len) > dbuf->db_buf_size ? dbuf->db_buf_size :
2569 2569 ATOMIC32_GET(scmd->len);
2570 2570
2571 2571 dbuf->db_relative_offset = scmd->current_ro;
2572 2572 dbuf->db_data_size = len;
2573 2573 dbuf->db_flags = DB_DIRECTION_FROM_RPORT;
2574 2574 (void) stmf_xfer_data(task, dbuf, 0);
2575 2575 /* outstanding port xfers and bufs used */
2576 2576 atomic_inc_8(&scmd->nbufs);
2577 2577 atomic_add_32(&scmd->len, -len);
2578 2578 scmd->current_ro += len;
2579 2579 }
2580 2580
2581 2581 static void
2582 2582 sbd_handle_write_same(scsi_task_t *task, struct stmf_data_buf *initial_dbuf)
2583 2583 {
2584 2584 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
2585 2585 uint64_t addr, len;
2586 2586 sbd_cmd_t *scmd;
2587 2587 stmf_data_buf_t *dbuf;
2588 2588 uint8_t unmap;
2589 2589 uint8_t do_immediate_data = 0;
2590 2590
2591 2591 if (HardwareAcceleratedInit == 0) {
2592 2592 stmf_scsilib_send_status(task, STATUS_CHECK,
2593 2593 STMF_SAA_INVALID_OPCODE);
2594 2594 return;
2595 2595 }
2596 2596
2597 2597 task->task_cmd_xfer_length = 0;
2598 2598 if (task->task_additional_flags &
2599 2599 TASK_AF_NO_EXPECTED_XFER_LENGTH) {
2600 2600 task->task_expected_xfer_length = 0;
2601 2601 }
2602 2602 if (sl->sl_flags & SL_WRITE_PROTECTED) {
2603 2603 stmf_scsilib_send_status(task, STATUS_CHECK,
2604 2604 STMF_SAA_WRITE_PROTECTED);
2605 2605 return;
2606 2606 }
2607 2607 if (task->task_cdb[1] & 0xF7) {
2608 2608 stmf_scsilib_send_status(task, STATUS_CHECK,
2609 2609 STMF_SAA_INVALID_FIELD_IN_CDB);
2610 2610 return;
2611 2611 }
2612 2612 unmap = task->task_cdb[1] & 0x08;
2613 2613
2614 2614 if (unmap && ((sl->sl_flags & SL_UNMAP_ENABLED) == 0)) {
2615 2615 stmf_scsilib_send_status(task, STATUS_CHECK,
2616 2616 STMF_SAA_INVALID_FIELD_IN_CDB);
2617 2617 return;
2618 2618 }
2619 2619
2620 2620 if (task->task_cdb[0] == SCMD_WRITE_SAME_G1) {
2621 2621 addr = READ_SCSI32(&task->task_cdb[2], uint64_t);
2622 2622 len = READ_SCSI16(&task->task_cdb[7], uint64_t);
2623 2623 } else {
2624 2624 addr = READ_SCSI64(&task->task_cdb[2], uint64_t);
2625 2625 len = READ_SCSI32(&task->task_cdb[10], uint64_t);
2626 2626 }
2627 2627
2628 2628 if (len == 0) {
2629 2629 stmf_scsilib_send_status(task, STATUS_CHECK,
2630 2630 STMF_SAA_INVALID_FIELD_IN_CDB);
2631 2631 return;
2632 2632 }
2633 2633
2634 2634 if (sbd_ats_handling_before_io(task, sl, addr, len) !=
2635 2635 SBD_SUCCESS) {
2636 2636 if (stmf_task_poll_lu(task, 10) != STMF_SUCCESS)
2637 2637 stmf_scsilib_send_status(task, STATUS_BUSY, 0);
2638 2638 return;
2639 2639 }
2640 2640
2641 2641 addr <<= sl->sl_data_blocksize_shift;
2642 2642 len <<= sl->sl_data_blocksize_shift;
2643 2643
2644 2644 /* Check if the command is for the unmap function */
2645 2645 if (unmap) {
2646 2646 dkioc_free_list_t *dfl = kmem_zalloc(DFL_SZ(1), KM_SLEEP);
2647 2647
2648 2648 dfl->dfl_num_exts = 1;
2649 2649 dfl->dfl_exts[0].dfle_start = addr;
2650 2650 dfl->dfl_exts[0].dfle_length = len;
2651 2651 if (sbd_unmap(sl, dfl) != 0) {
2652 2652 stmf_scsilib_send_status(task, STATUS_CHECK,
2653 2653 STMF_SAA_LBA_OUT_OF_RANGE);
2654 2654 } else {
2655 2655 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
2656 2656 }
2657 2657 dfl_free(dfl);
2658 2658 return;
2659 2659 }
2660 2660
2661 2661 /* Write same function */
2662 2662
2663 2663 task->task_cmd_xfer_length = 1 << sl->sl_data_blocksize_shift;
2664 2664 if (task->task_additional_flags &
2665 2665 TASK_AF_NO_EXPECTED_XFER_LENGTH) {
2666 2666 task->task_expected_xfer_length = task->task_cmd_xfer_length;
2667 2667 }
2668 2668 if ((addr + len) > sl->sl_lu_size) {
2669 2669 sbd_ats_remove_by_task(task);
2670 2670 stmf_scsilib_send_status(task, STATUS_CHECK,
2671 2671 STMF_SAA_LBA_OUT_OF_RANGE);
2672 2672 return;
2673 2673 }
2674 2674
2675 2675 /* For rest of this I/O the transfer length is 1 block */
2676 2676 len = ((uint64_t)1) << sl->sl_data_blocksize_shift;
2677 2677
2678 2678 /* Some basic checks */
2679 2679 if ((len == 0) || (len != task->task_expected_xfer_length)) {
2680 2680 sbd_ats_remove_by_task(task);
2681 2681 stmf_scsilib_send_status(task, STATUS_CHECK,
2682 2682 STMF_SAA_INVALID_FIELD_IN_CDB);
2683 2683 return;
2684 2684 }
2685 2685
2686 2686
2687 2687 if ((initial_dbuf != NULL) && (task->task_flags & TF_INITIAL_BURST)) {
2688 2688 if (initial_dbuf->db_data_size > len) {
2689 2689 if (initial_dbuf->db_data_size >
2690 2690 task->task_expected_xfer_length) {
2691 2691 /* protocol error */
2692 2692 sbd_ats_remove_by_task(task);
2693 2693 stmf_abort(STMF_QUEUE_TASK_ABORT, task,
2694 2694 STMF_INVALID_ARG, NULL);
2695 2695 return;
2696 2696 }
2697 2697 initial_dbuf->db_data_size = (uint32_t)len;
2698 2698 }
2699 2699 do_immediate_data = 1;
2700 2700 }
2701 2701 dbuf = initial_dbuf;
2702 2702
2703 2703 if (task->task_lu_private) {
2704 2704 scmd = (sbd_cmd_t *)task->task_lu_private;
2705 2705 } else {
2706 2706 scmd = (sbd_cmd_t *)kmem_alloc(sizeof (sbd_cmd_t), KM_SLEEP);
2707 2707 task->task_lu_private = scmd;
2708 2708 }
2709 2709 scmd->flags = SBD_SCSI_CMD_ACTIVE | SBD_SCSI_CMD_TRANS_DATA |
2710 2710 SBD_SCSI_CMD_ATS_RELATED;
2711 2711 scmd->cmd_type = SBD_CMD_SCSI_WRITE;
2712 2712 scmd->nbufs = 0;
2713 2713 scmd->len = (uint32_t)len;
2714 2714 scmd->trans_data_len = (uint32_t)len;
2715 2715 scmd->trans_data = kmem_alloc((size_t)len, KM_SLEEP);
2716 2716 scmd->current_ro = 0;
2717 2717
2718 2718 if (do_immediate_data) {
2719 2719 /*
2720 2720 * Account for data passed in this write command
2721 2721 */
2722 2722 (void) stmf_xfer_data(task, dbuf, STMF_IOF_STATS_ONLY);
2723 2723 atomic_add_32(&scmd->len, -dbuf->db_data_size);
2724 2724 scmd->current_ro += dbuf->db_data_size;
2725 2725 dbuf->db_xfer_status = STMF_SUCCESS;
2726 2726 sbd_handle_write_same_xfer_completion(task, scmd, dbuf, 0);
2727 2727 } else {
2728 2728 sbd_do_write_same_xfer(task, scmd, dbuf, 0);
2729 2729 }
2730 2730 }
2731 2731
2732 2732 static void
2733 2733 sbd_handle_unmap(scsi_task_t *task, stmf_data_buf_t *dbuf)
2734 2734 {
2735 2735 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
2736 2736 uint32_t cmd_xfer_len;
2737 2737
2738 2738 if (sbd_unmap_enable == 0) {
2739 2739 stmf_scsilib_send_status(task, STATUS_CHECK,
2740 2740 STMF_SAA_INVALID_OPCODE);
2741 2741 return;
2742 2742 }
2743 2743
2744 2744 if (sl->sl_flags & SL_WRITE_PROTECTED) {
2745 2745 stmf_scsilib_send_status(task, STATUS_CHECK,
2746 2746 STMF_SAA_WRITE_PROTECTED);
2747 2747 return;
2748 2748 }
2749 2749 cmd_xfer_len = READ_SCSI16(&task->task_cdb[7], uint32_t);
2750 2750
2751 2751 if (task->task_cdb[1] & 1) {
2752 2752 stmf_scsilib_send_status(task, STATUS_CHECK,
2753 2753 STMF_SAA_INVALID_FIELD_IN_CDB);
2754 2754 return;
2755 2755 }
2756 2756
2757 2757 if (cmd_xfer_len == 0) {
2758 2758 task->task_cmd_xfer_length = 0;
2759 2759 if (task->task_additional_flags &
2760 2760 TASK_AF_NO_EXPECTED_XFER_LENGTH) {
2761 2761 task->task_expected_xfer_length = 0;
2762 2762 }
2763 2763 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
2764 2764 return;
2765 2765 }
2766 2766
2767 2767 sbd_handle_short_write_transfers(task, dbuf, cmd_xfer_len);
2768 2768 }
2769 2769
2770 2770 static void
2771 2771 sbd_handle_unmap_xfer(scsi_task_t *task, uint8_t *buf, uint32_t buflen)
2772 2772 {
2773 2773 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
2774 2774 uint32_t ulen, dlen, num_desc;
2775 2775 uint64_t addr, len;
2776 2776 uint8_t *p;
2777 2777 dkioc_free_list_t *dfl;
2778 2778 int ret;
2779 2779 int i;
2780 2780
2781 2781 if (buflen < 24) {
2782 2782 stmf_scsilib_send_status(task, STATUS_CHECK,
2783 2783 STMF_SAA_INVALID_FIELD_IN_CDB);
2784 2784 return;
2785 2785 }
2786 2786 ulen = READ_SCSI16(buf, uint32_t);
2787 2787 dlen = READ_SCSI16(buf + 2, uint32_t);
2788 2788 num_desc = dlen >> 4;
2789 2789 if (((ulen + 2) != buflen) || ((dlen + 8) != buflen) || (dlen & 0xf) ||
2790 2790 (num_desc == 0)) {
2791 2791 stmf_scsilib_send_status(task, STATUS_CHECK,
2792 2792 STMF_SAA_INVALID_FIELD_IN_CDB);
2793 2793 return;
2794 2794 }
2795 2795
2796 2796 dfl = kmem_zalloc(DFL_SZ(num_desc), KM_SLEEP);
2797 2797 dfl->dfl_num_exts = num_desc;
2798 2798 /*
2799 2799 * This should use ATS locking but that was disabled by the
2800 2800 * changes to ZFS top take advantage of TRIM in SSDs.
2801 2801 *
2802 2802 * Since the entire list is passed to ZFS in one list ATS
2803 2803 * locking is not done. This may be detectable, and if it is
2804 2804 * then the entire list needs to be locked and then after the
2805 2805 * unmap completes the entire list must be unlocked
2806 2806 */
2807 2807 for (p = buf + 8, i = 0; num_desc; num_desc--, p += 16, i++) {
2808 2808 addr = READ_SCSI64(p, uint64_t);
2809 2809 len = READ_SCSI32(p+8, uint64_t);
2810 2810 addr <<= sl->sl_data_blocksize_shift;
2811 2811 len <<= sl->sl_data_blocksize_shift;
2812 2812
2813 2813 /* Prepare a list of extents to unmap */
2814 2814 dfl->dfl_exts[i].dfle_start = addr;
2815 2815 dfl->dfl_exts[i].dfle_length = len;
2816 2816
2817 2817 /* release the overlap */
2818 2818 }
2819 2819 ASSERT(i == dfl->dfl_num_exts);
2820 2820
2821 2821 /* Finally execute the unmap operations in a single step */
2822 2822 ret = sbd_unmap(sl, dfl);
2823 2823 dfl_free(dfl);
2824 2824 if (ret != 0) {
2825 2825 stmf_scsilib_send_status(task, STATUS_CHECK,
2826 2826 STMF_SAA_LBA_OUT_OF_RANGE);
2827 2827 return;
2828 2828 }
2829 2829
2830 2830 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
2831 2831 }
2832 2832
2833 2833 void
2834 2834 sbd_handle_inquiry(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
2835 2835 {
2836 2836 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
2837 2837 uint8_t *cdbp = (uint8_t *)&task->task_cdb[0];
2838 2838 uint8_t *p;
2839 2839 uint8_t byte0;
2840 2840 uint8_t page_length;
2841 2841 uint16_t bsize = 512;
2842 2842 uint16_t cmd_size;
2843 2843 uint32_t xfer_size = 4;
2844 2844 uint32_t mgmt_url_size = 0;
2845 2845 uint8_t exp;
2846 2846 uint64_t s;
2847 2847 char *mgmt_url = NULL;
2848 2848
2849 2849
2850 2850 byte0 = DTYPE_DIRECT;
2851 2851 /*
2852 2852 * Basic protocol checks.
2853 2853 */
2854 2854
2855 2855 if ((((cdbp[1] & 1) == 0) && cdbp[2]) || cdbp[5]) {
2856 2856 stmf_scsilib_send_status(task, STATUS_CHECK,
2857 2857 STMF_SAA_INVALID_FIELD_IN_CDB);
2858 2858 return;
2859 2859 }
2860 2860
2861 2861 /*
2862 2862 * Zero byte allocation length is not an error. Just
2863 2863 * return success.
2864 2864 */
2865 2865
2866 2866 cmd_size = (((uint16_t)cdbp[3]) << 8) | cdbp[4];
2867 2867
2868 2868 if (cmd_size == 0) {
2869 2869 task->task_cmd_xfer_length = 0;
2870 2870 if (task->task_additional_flags &
2871 2871 TASK_AF_NO_EXPECTED_XFER_LENGTH) {
2872 2872 task->task_expected_xfer_length = 0;
2873 2873 }
2874 2874 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
2875 2875 return;
2876 2876 }
2877 2877
2878 2878 /*
2879 2879 * Standard inquiry
2880 2880 */
2881 2881
2882 2882 if ((cdbp[1] & 1) == 0) {
2883 2883 int i;
2884 2884 struct scsi_inquiry *inq;
2885 2885
2886 2886 p = (uint8_t *)kmem_zalloc(bsize, KM_SLEEP);
2887 2887 inq = (struct scsi_inquiry *)p;
2888 2888
2889 2889 page_length = 69;
2890 2890 xfer_size = page_length + 5;
2891 2891
2892 2892 inq->inq_dtype = DTYPE_DIRECT;
2893 2893 inq->inq_ansi = 5; /* SPC-3 */
2894 2894 inq->inq_hisup = 1;
2895 2895 inq->inq_rdf = 2; /* Response data format for SPC-3 */
2896 2896 inq->inq_len = page_length;
2897 2897
2898 2898 inq->inq_tpgs = TPGS_FAILOVER_IMPLICIT;
2899 2899 inq->inq_cmdque = 1;
2900 2900 inq->inq_3pc = 1;
2901 2901
2902 2902 if (sl->sl_flags & SL_VID_VALID) {
2903 2903 bcopy(sl->sl_vendor_id, inq->inq_vid, 8);
2904 2904 } else {
2905 2905 bcopy(sbd_vendor_id, inq->inq_vid, 8);
2906 2906 }
2907 2907
2908 2908 if (sl->sl_flags & SL_PID_VALID) {
2909 2909 bcopy(sl->sl_product_id, inq->inq_pid, 16);
2910 2910 } else {
2911 2911 bcopy(sbd_product_id, inq->inq_pid, 16);
2912 2912 }
2913 2913
2914 2914 if (sl->sl_flags & SL_REV_VALID) {
2915 2915 bcopy(sl->sl_revision, inq->inq_revision, 4);
2916 2916 } else {
2917 2917 bcopy(sbd_revision, inq->inq_revision, 4);
2918 2918 }
2919 2919
2920 2920 /* Adding Version Descriptors */
2921 2921 i = 0;
2922 2922 /* SAM-3 no version */
2923 2923 inq->inq_vd[i].inq_vd_msb = 0x00;
2924 2924 inq->inq_vd[i].inq_vd_lsb = 0x60;
2925 2925 i++;
2926 2926
2927 2927 /* transport */
2928 2928 switch (task->task_lport->lport_id->protocol_id) {
2929 2929 case PROTOCOL_FIBRE_CHANNEL:
2930 2930 inq->inq_vd[i].inq_vd_msb = 0x09;
2931 2931 inq->inq_vd[i].inq_vd_lsb = 0x00;
2932 2932 i++;
2933 2933 break;
2934 2934
2935 2935 case PROTOCOL_PARALLEL_SCSI:
2936 2936 case PROTOCOL_SSA:
2937 2937 case PROTOCOL_IEEE_1394:
2938 2938 /* Currently no claims of conformance */
2939 2939 break;
2940 2940
2941 2941 case PROTOCOL_SRP:
2942 2942 inq->inq_vd[i].inq_vd_msb = 0x09;
2943 2943 inq->inq_vd[i].inq_vd_lsb = 0x40;
2944 2944 i++;
2945 2945 break;
2946 2946
2947 2947 case PROTOCOL_iSCSI:
2948 2948 inq->inq_vd[i].inq_vd_msb = 0x09;
2949 2949 inq->inq_vd[i].inq_vd_lsb = 0x60;
2950 2950 i++;
2951 2951 break;
2952 2952
2953 2953 case PROTOCOL_SAS:
2954 2954 case PROTOCOL_ADT:
2955 2955 case PROTOCOL_ATAPI:
2956 2956 default:
2957 2957 /* Currently no claims of conformance */
2958 2958 break;
2959 2959 }
2960 2960
2961 2961 /* SPC-3 no version */
2962 2962 inq->inq_vd[i].inq_vd_msb = 0x03;
2963 2963 inq->inq_vd[i].inq_vd_lsb = 0x00;
2964 2964 i++;
2965 2965
2966 2966 /* SBC-2 no version */
2967 2967 inq->inq_vd[i].inq_vd_msb = 0x03;
2968 2968 inq->inq_vd[i].inq_vd_lsb = 0x20;
2969 2969
2970 2970 sbd_handle_short_read_transfers(task, initial_dbuf, p, cmd_size,
2971 2971 min(cmd_size, xfer_size));
2972 2972 kmem_free(p, bsize);
2973 2973
2974 2974 return;
2975 2975 }
2976 2976
2977 2977 rw_enter(&sbd_global_prop_lock, RW_READER);
2978 2978 if (sl->sl_mgmt_url) {
2979 2979 mgmt_url_size = strlen(sl->sl_mgmt_url);
2980 2980 mgmt_url = sl->sl_mgmt_url;
2981 2981 } else if (sbd_mgmt_url) {
2982 2982 mgmt_url_size = strlen(sbd_mgmt_url);
2983 2983 mgmt_url = sbd_mgmt_url;
2984 2984 }
2985 2985
2986 2986 /*
2987 2987 * EVPD handling
2988 2988 */
2989 2989
2990 2990 /* Default 512 bytes may not be enough, increase bsize if necessary */
2991 2991 if (cdbp[2] == 0x83 || cdbp[2] == 0x85) {
2992 2992 if (bsize < cmd_size)
2993 2993 bsize = cmd_size;
2994 2994 }
2995 2995 p = (uint8_t *)kmem_zalloc(bsize, KM_SLEEP);
2996 2996
2997 2997 switch (cdbp[2]) {
2998 2998 case 0x00:
2999 2999 page_length = 5 + (mgmt_url_size ? 1 : 0);
3000 3000
3001 3001 if (sl->sl_flags & SL_UNMAP_ENABLED)
3002 3002 page_length += 1;
3003 3003
3004 3004 p[0] = byte0;
3005 3005 p[3] = page_length;
3006 3006 /* Supported VPD pages in ascending order */
3007 3007 /* CSTYLED */
3008 3008 {
3009 3009 uint8_t i = 5;
3010 3010
3011 3011 p[i++] = 0x80;
3012 3012 p[i++] = 0x83;
3013 3013 if (mgmt_url_size != 0)
3014 3014 p[i++] = 0x85;
3015 3015 p[i++] = 0x86;
3016 3016 p[i++] = 0xb0;
3017 3017 if (sl->sl_flags & SL_UNMAP_ENABLED) {
3018 3018 p[i++] = 0xb2;
3019 3019 }
3020 3020 }
3021 3021 xfer_size = page_length + 4;
3022 3022 break;
3023 3023
3024 3024 case 0x80:
3025 3025 if (sl->sl_serial_no_size) {
3026 3026 page_length = sl->sl_serial_no_size;
3027 3027 bcopy(sl->sl_serial_no, p + 4, sl->sl_serial_no_size);
3028 3028 } else {
3029 3029 /* if no serial num is specified set 4 spaces */
3030 3030 page_length = 4;
3031 3031 bcopy(" ", p + 4, 4);
3032 3032 }
3033 3033 p[0] = byte0;
3034 3034 p[1] = 0x80;
3035 3035 p[3] = page_length;
3036 3036 xfer_size = page_length + 4;
3037 3037 break;
3038 3038
3039 3039 case 0x83:
3040 3040 xfer_size = stmf_scsilib_prepare_vpd_page83(task, p,
3041 3041 bsize, byte0, STMF_VPD_LU_ID|STMF_VPD_TARGET_ID|
3042 3042 STMF_VPD_TP_GROUP|STMF_VPD_RELATIVE_TP_ID);
3043 3043 break;
3044 3044
3045 3045 case 0x85:
3046 3046 if (mgmt_url_size == 0) {
3047 3047 stmf_scsilib_send_status(task, STATUS_CHECK,
3048 3048 STMF_SAA_INVALID_FIELD_IN_CDB);
3049 3049 goto err_done;
3050 3050 } /* CSTYLED */
3051 3051 {
3052 3052 uint16_t idx, newidx, sz, url_size;
3053 3053 char *url;
3054 3054
3055 3055 p[0] = byte0;
3056 3056 p[1] = 0x85;
3057 3057
3058 3058 idx = 4;
3059 3059 url = mgmt_url;
3060 3060 url_size = sbd_parse_mgmt_url(&url);
3061 3061 /* Creating Network Service Descriptors */
3062 3062 while (url_size != 0) {
3063 3063 /* Null terminated and 4 Byte aligned */
3064 3064 sz = url_size + 1;
3065 3065 sz += (sz % 4) ? 4 - (sz % 4) : 0;
3066 3066 newidx = idx + sz + 4;
3067 3067
3068 3068 if (newidx < bsize) {
3069 3069 /*
3070 3070 * SPC-3r23 : Table 320 (Sec 7.6.5)
3071 3071 * (Network service descriptor format
3072 3072 *
3073 3073 * Note: Hard coding service type as
3074 3074 * "Storage Configuration Service".
3075 3075 */
3076 3076 p[idx] = 1;
3077 3077 SCSI_WRITE16(p + idx + 2, sz);
3078 3078 bcopy(url, p + idx + 4, url_size);
3079 3079 xfer_size = newidx + 4;
3080 3080 }
3081 3081 idx = newidx;
3082 3082
3083 3083 /* skip to next mgmt url if any */
3084 3084 url += url_size;
3085 3085 url_size = sbd_parse_mgmt_url(&url);
3086 3086 }
3087 3087
3088 3088 /* Total descriptor length */
3089 3089 SCSI_WRITE16(p + 2, idx - 4);
3090 3090 break;
3091 3091 }
3092 3092
3093 3093 case 0x86:
3094 3094 page_length = 0x3c;
3095 3095
3096 3096 p[0] = byte0;
3097 3097 p[1] = 0x86; /* Page 86 response */
3098 3098 p[3] = page_length;
3099 3099
3100 3100 /*
3101 3101 * Bits 0, 1, and 2 will need to be updated
3102 3102 * to reflect the queue tag handling if/when
3103 3103 * that is implemented. For now, we're going
3104 3104 * to claim support only for Simple TA.
3105 3105 */
3106 3106 p[5] = 1;
3107 3107 xfer_size = page_length + 4;
3108 3108 break;
3109 3109
3110 3110 case 0xb0:
3111 3111 page_length = 0x3c;
3112 3112 p[0] = byte0;
3113 3113 p[1] = 0xb0;
3114 3114 p[3] = page_length;
3115 3115 p[4] = 1;
3116 3116 p[5] = sbd_ats_max_nblks();
3117 3117 if (sl->sl_flags & SL_UNMAP_ENABLED && sbd_unmap_enable) {
3118 3118 p[20] = (stmf_sbd_unmap_max_nblks >> 24) & 0xff;
3119 3119 p[21] = (stmf_sbd_unmap_max_nblks >> 16) & 0xff;
3120 3120 p[22] = (stmf_sbd_unmap_max_nblks >> 8) & 0xff;
3121 3121 p[23] = stmf_sbd_unmap_max_nblks & 0xff;
3122 3122
3123 3123 p[24] = 0;
3124 3124 p[25] = 0;
3125 3125 p[26] = 0;
3126 3126 p[27] = 0xFF;
3127 3127 }
3128 3128 xfer_size = page_length + 4;
3129 3129 break;
3130 3130
3131 3131 case 0xb2:
3132 3132 if ((sl->sl_flags & SL_UNMAP_ENABLED) == 0) {
3133 3133 stmf_scsilib_send_status(task, STATUS_CHECK,
3134 3134 STMF_SAA_INVALID_FIELD_IN_CDB);
3135 3135 goto err_done;
3136 3136 }
3137 3137 page_length = 4;
3138 3138 p[0] = byte0;
3139 3139 p[1] = 0xb2;
3140 3140 p[3] = page_length;
3141 3141
3142 3142 exp = (uint8_t)sl->sl_data_blocksize_shift;
3143 3143 s = sl->sl_lu_size >> sl->sl_data_blocksize_shift;
3144 3144 while (s & ((uint64_t)0xFFFFFFFF80000000ull)) {
3145 3145 s >>= 1;
3146 3146 exp++;
3147 3147 }
3148 3148 p[4] = exp;
3149 3149 p[5] = 0xc0; /* Logical provisioning UNMAP and WRITE SAME */
3150 3150 xfer_size = page_length + 4;
3151 3151 break;
3152 3152
3153 3153 default:
3154 3154 stmf_scsilib_send_status(task, STATUS_CHECK,
3155 3155 STMF_SAA_INVALID_FIELD_IN_CDB);
3156 3156 goto err_done;
3157 3157 }
3158 3158
3159 3159 sbd_handle_short_read_transfers(task, initial_dbuf, p, cmd_size,
3160 3160 min(cmd_size, xfer_size));
3161 3161 err_done:
3162 3162 kmem_free(p, bsize);
3163 3163 rw_exit(&sbd_global_prop_lock);
3164 3164 }
3165 3165
3166 3166 stmf_status_t
3167 3167 sbd_task_alloc(struct scsi_task *task)
3168 3168 {
3169 3169 if ((task->task_lu_private =
3170 3170 kmem_zalloc(sizeof (sbd_cmd_t), KM_NOSLEEP)) != NULL) {
3171 3171 sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
3172 3172 scmd->flags = 0;
3173 3173 return (STMF_SUCCESS);
3174 3174 }
3175 3175 return (STMF_ALLOC_FAILURE);
3176 3176 }
3177 3177
3178 3178 void
3179 3179 sbd_remove_it_handle(sbd_lu_t *sl, sbd_it_data_t *it)
3180 3180 {
3181 3181 sbd_it_data_t **ppit;
3182 3182
3183 3183 sbd_pgr_remove_it_handle(sl, it);
3184 3184 mutex_enter(&sl->sl_lock);
3185 3185 for (ppit = &sl->sl_it_list; *ppit != NULL;
3186 3186 ppit = &((*ppit)->sbd_it_next)) {
3187 3187 if ((*ppit) == it) {
3188 3188 *ppit = it->sbd_it_next;
3189 3189 break;
3190 3190 }
3191 3191 }
3192 3192 mutex_exit(&sl->sl_lock);
3193 3193
3194 3194 DTRACE_PROBE2(itl__nexus__end, stmf_lu_t *, sl->sl_lu,
3195 3195 sbd_it_data_t *, it);
3196 3196
3197 3197 kmem_free(it, sizeof (*it));
3198 3198 }
3199 3199
3200 3200 void
3201 3201 sbd_check_and_clear_scsi2_reservation(sbd_lu_t *sl, sbd_it_data_t *it)
3202 3202 {
3203 3203 mutex_enter(&sl->sl_lock);
3204 3204 if ((sl->sl_flags & SL_LU_HAS_SCSI2_RESERVATION) == 0) {
3205 3205 /* If we dont have any reservations, just get out. */
3206 3206 mutex_exit(&sl->sl_lock);
3207 3207 return;
3208 3208 }
3209 3209
3210 3210 if (it == NULL) {
3211 3211 /* Find the I_T nexus which is holding the reservation. */
3212 3212 for (it = sl->sl_it_list; it != NULL; it = it->sbd_it_next) {
3213 3213 if (it->sbd_it_flags & SBD_IT_HAS_SCSI2_RESERVATION) {
3214 3214 ASSERT(it->sbd_it_session_id ==
3215 3215 sl->sl_rs_owner_session_id);
3216 3216 break;
3217 3217 }
3218 3218 }
3219 3219 ASSERT(it != NULL);
3220 3220 } else {
3221 3221 /*
3222 3222 * We were passed an I_T nexus. If this nexus does not hold
3223 3223 * the reservation, do nothing. This is why this function is
3224 3224 * called "check_and_clear".
3225 3225 */
3226 3226 if ((it->sbd_it_flags & SBD_IT_HAS_SCSI2_RESERVATION) == 0) {
3227 3227 mutex_exit(&sl->sl_lock);
3228 3228 return;
3229 3229 }
3230 3230 }
3231 3231 it->sbd_it_flags &= ~SBD_IT_HAS_SCSI2_RESERVATION;
3232 3232 sl->sl_flags &= ~SL_LU_HAS_SCSI2_RESERVATION;
3233 3233 mutex_exit(&sl->sl_lock);
3234 3234 }
3235 3235
3236 3236 /*
3237 3237 * Given a LU and a task, check if the task is causing reservation
3238 3238 * conflict. Returns 1 in case of conflict, 0 otherwise.
3239 3239 * Note that the LU might not be the same LU as in the task but the
3240 3240 * caller makes sure that the LU can be accessed.
3241 3241 */
3242 3242 int
3243 3243 sbd_check_reservation_conflict(struct sbd_lu *sl, struct scsi_task *task)
3244 3244 {
3245 3245 sbd_it_data_t *it;
3246 3246
3247 3247 it = task->task_lu_itl_handle;
3248 3248 ASSERT(it);
3249 3249 if (sl->sl_access_state == SBD_LU_ACTIVE) {
3250 3250 if (SBD_PGR_RSVD(sl->sl_pgr)) {
3251 3251 if (sbd_pgr_reservation_conflict(task, sl)) {
3252 3252 return (1);
3253 3253 }
3254 3254 } else if ((sl->sl_flags & SL_LU_HAS_SCSI2_RESERVATION) &&
3255 3255 ((it->sbd_it_flags & SBD_IT_HAS_SCSI2_RESERVATION) == 0)) {
3256 3256 if (!(SCSI2_CONFLICT_FREE_CMDS(task->task_cdb))) {
3257 3257 return (1);
3258 3258 }
3259 3259 }
3260 3260 }
3261 3261
3262 3262 return (0);
3263 3263 }
3264 3264
3265 3265 /*
3266 3266 * Keep in mind that sbd_new_task can be called multiple times for the same
3267 3267 * task because of us calling stmf_task_poll_lu resulting in a call to
3268 3268 * sbd_task_poll().
3269 3269 */
3270 3270 void
3271 3271 sbd_new_task(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
3272 3272 {
3273 3273 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
3274 3274 sbd_it_data_t *it;
3275 3275 uint8_t cdb0, cdb1;
3276 3276 stmf_status_t st_ret;
3277 3277
3278 3278 if ((it = task->task_lu_itl_handle) == NULL) {
3279 3279 mutex_enter(&sl->sl_lock);
3280 3280 for (it = sl->sl_it_list; it != NULL; it = it->sbd_it_next) {
3281 3281 if (it->sbd_it_session_id ==
3282 3282 task->task_session->ss_session_id) {
3283 3283 mutex_exit(&sl->sl_lock);
3284 3284 stmf_scsilib_send_status(task, STATUS_BUSY, 0);
3285 3285 return;
3286 3286 }
3287 3287 }
3288 3288 it = (sbd_it_data_t *)kmem_zalloc(sizeof (*it), KM_NOSLEEP);
3289 3289 if (it == NULL) {
3290 3290 mutex_exit(&sl->sl_lock);
3291 3291 stmf_scsilib_send_status(task, STATUS_BUSY, 0);
3292 3292 return;
3293 3293 }
3294 3294 it->sbd_it_session_id = task->task_session->ss_session_id;
3295 3295 bcopy(task->task_lun_no, it->sbd_it_lun, 8);
3296 3296 it->sbd_it_next = sl->sl_it_list;
3297 3297 sl->sl_it_list = it;
3298 3298 mutex_exit(&sl->sl_lock);
3299 3299
3300 3300 DTRACE_PROBE1(itl__nexus__start, scsi_task *, task);
3301 3301
3302 3302 sbd_pgr_initialize_it(task, it);
3303 3303 if (stmf_register_itl_handle(task->task_lu, task->task_lun_no,
3304 3304 task->task_session, it->sbd_it_session_id, it)
3305 3305 != STMF_SUCCESS) {
3306 3306 sbd_remove_it_handle(sl, it);
3307 3307 stmf_scsilib_send_status(task, STATUS_BUSY, 0);
3308 3308 return;
3309 3309 }
3310 3310 task->task_lu_itl_handle = it;
3311 3311 if (sl->sl_access_state != SBD_LU_STANDBY) {
3312 3312 it->sbd_it_ua_conditions = SBD_UA_POR;
3313 3313 }
3314 3314 } else if (it->sbd_it_flags & SBD_IT_PGR_CHECK_FLAG) {
3315 3315 mutex_enter(&sl->sl_lock);
3316 3316 it->sbd_it_flags &= ~SBD_IT_PGR_CHECK_FLAG;
3317 3317 mutex_exit(&sl->sl_lock);
3318 3318 sbd_pgr_initialize_it(task, it);
3319 3319 }
3320 3320
3321 3321 if (task->task_mgmt_function) {
3322 3322 stmf_scsilib_handle_task_mgmt(task);
3323 3323 return;
3324 3324 }
3325 3325
3326 3326 /*
3327 3327 * if we're transitioning between access
3328 3328 * states, return NOT READY
3329 3329 */
3330 3330 if (sl->sl_access_state == SBD_LU_TRANSITION_TO_STANDBY ||
3331 3331 sl->sl_access_state == SBD_LU_TRANSITION_TO_ACTIVE) {
3332 3332 stmf_scsilib_send_status(task, STATUS_CHECK,
3333 3333 STMF_SAA_LU_NO_ACCESS_TRANSITION);
3334 3334 return;
3335 3335 }
3336 3336
3337 3337 cdb0 = task->task_cdb[0];
3338 3338 cdb1 = task->task_cdb[1];
3339 3339 /*
3340 3340 * Special case for different versions of Windows.
3341 3341 * 1) Windows 2012 and VMWare will fail to discover LU's if a READ
3342 3342 * operation sent down the standby path returns an error. By default
3343 3343 * standby_fail_reads will be set to 0.
3344 3344 * 2) Windows 2008 R2 has a severe performace problem if READ ops
3345 3345 * aren't rejected on the standby path. 2008 sends commands
3346 3346 * down the standby path which then must be proxied over to the
3347 3347 * active node and back.
3348 3348 */
3349 3349 if ((sl->sl_access_state == SBD_LU_STANDBY) &&
3350 3350 stmf_standby_fail_reads &&
3351 3351 (cdb0 == SCMD_READ || cdb0 == SCMD_READ_G1 ||
3352 3352 cdb0 == SCMD_READ_G4 || cdb0 == SCMD_READ_G5)) {
3353 3353 stmf_scsilib_send_status(task, STATUS_CHECK,
3354 3354 STMF_SAA_LU_NO_ACCESS_STANDBY);
3355 3355 return;
3356 3356 }
3357 3357
3358 3358 /*
3359 3359 * Don't go further if cmd is unsupported in standby mode
3360 3360 */
3361 3361 if (sl->sl_access_state == SBD_LU_STANDBY) {
3362 3362 if (cdb0 != SCMD_INQUIRY &&
3363 3363 cdb0 != SCMD_MODE_SENSE &&
3364 3364 cdb0 != SCMD_MODE_SENSE_G1 &&
3365 3365 cdb0 != SCMD_MODE_SELECT &&
3366 3366 cdb0 != SCMD_MODE_SELECT_G1 &&
3367 3367 cdb0 != SCMD_RESERVE &&
3368 3368 cdb0 != SCMD_RELEASE &&
3369 3369 cdb0 != SCMD_PERSISTENT_RESERVE_OUT &&
3370 3370 cdb0 != SCMD_PERSISTENT_RESERVE_IN &&
3371 3371 cdb0 != SCMD_REQUEST_SENSE &&
3372 3372 cdb0 != SCMD_READ_CAPACITY &&
3373 3373 cdb0 != SCMD_TEST_UNIT_READY &&
3374 3374 cdb0 != SCMD_START_STOP &&
3375 3375 cdb0 != SCMD_READ &&
3376 3376 cdb0 != SCMD_READ_G1 &&
3377 3377 cdb0 != SCMD_READ_G4 &&
3378 3378 cdb0 != SCMD_READ_G5 &&
3379 3379 !(cdb0 == SCMD_SVC_ACTION_IN_G4 &&
3380 3380 cdb1 == SSVC_ACTION_READ_CAPACITY_G4) &&
3381 3381 !(cdb0 == SCMD_MAINTENANCE_IN &&
3382 3382 (cdb1 & 0x1F) == 0x05) &&
3383 3383 !(cdb0 == SCMD_MAINTENANCE_IN &&
3384 3384 (cdb1 & 0x1F) == 0x0A)) {
3385 3385 stmf_scsilib_send_status(task, STATUS_CHECK,
3386 3386 STMF_SAA_LU_NO_ACCESS_STANDBY);
3387 3387 return;
3388 3388 }
3389 3389 }
3390 3390
3391 3391 /*
3392 3392 * Checking ua conditions as per SAM3R14 5.3.2 specified order. During
3393 3393 * MPIO/ALUA failover, cmds come in through local ports and proxy port
3394 3394 * port provider (i.e. pppt), we want to report unit attention to
3395 3395 * only local cmds since initiators (Windows MPIO/DSM) would continue
3396 3396 * sending I/O to the target that reported unit attention.
3397 3397 */
3398 3398 if ((it->sbd_it_ua_conditions) &&
3399 3399 !(task->task_additional_flags & TASK_AF_PPPT_TASK) &&
3400 3400 (task->task_cdb[0] != SCMD_INQUIRY)) {
3401 3401 uint32_t saa = 0;
3402 3402
3403 3403 mutex_enter(&sl->sl_lock);
3404 3404 if (it->sbd_it_ua_conditions & SBD_UA_POR) {
3405 3405 it->sbd_it_ua_conditions &= ~SBD_UA_POR;
3406 3406 saa = STMF_SAA_POR;
3407 3407 } else if (it->sbd_it_ua_conditions &
3408 3408 SBD_UA_ASYMMETRIC_ACCESS_CHANGED) {
3409 3409 it->sbd_it_ua_conditions &=
3410 3410 ~SBD_UA_ASYMMETRIC_ACCESS_CHANGED;
3411 3411 saa = STMF_SAA_ASYMMETRIC_ACCESS_CHANGED;
3412 3412 }
3413 3413 mutex_exit(&sl->sl_lock);
3414 3414 if (saa) {
3415 3415 stmf_scsilib_send_status(task, STATUS_CHECK, saa);
3416 3416 return;
3417 3417 }
3418 3418 }
3419 3419
3420 3420 /* Reservation conflict checks */
3421 3421 if (sbd_check_reservation_conflict(sl, task)) {
3422 3422 stmf_scsilib_send_status(task,
3423 3423 STATUS_RESERVATION_CONFLICT, 0);
3424 3424 return;
3425 3425 }
3426 3426
3427 3427 /* Rest of the ua conndition checks */
3428 3428 if ((it->sbd_it_ua_conditions) && (task->task_cdb[0] != SCMD_INQUIRY)) {
3429 3429 uint32_t saa = 0;
3430 3430
3431 3431 mutex_enter(&sl->sl_lock);
3432 3432 if (it->sbd_it_ua_conditions & SBD_UA_CAPACITY_CHANGED) {
3433 3433 it->sbd_it_ua_conditions &= ~SBD_UA_CAPACITY_CHANGED;
3434 3434 if ((task->task_cdb[0] == SCMD_READ_CAPACITY) ||
3435 3435 ((task->task_cdb[0] == SCMD_SVC_ACTION_IN_G4) &&
3436 3436 (task->task_cdb[1] ==
3437 3437 SSVC_ACTION_READ_CAPACITY_G4))) {
3438 3438 saa = 0;
3439 3439 } else {
3440 3440 saa = STMF_SAA_CAPACITY_DATA_HAS_CHANGED;
3441 3441 }
3442 3442 } else if (it->sbd_it_ua_conditions &
3443 3443 SBD_UA_MODE_PARAMETERS_CHANGED) {
3444 3444 it->sbd_it_ua_conditions &=
3445 3445 ~SBD_UA_MODE_PARAMETERS_CHANGED;
3446 3446 saa = STMF_SAA_MODE_PARAMETERS_CHANGED;
3447 3447 } else if (it->sbd_it_ua_conditions &
3448 3448 SBD_UA_ASYMMETRIC_ACCESS_CHANGED) {
3449 3449 saa = 0;
3450 3450 } else if (it->sbd_it_ua_conditions & SBD_UA_POR) {
3451 3451 saa = 0;
3452 3452 } else if (it->sbd_it_ua_conditions &
3453 3453 SBD_UA_ACCESS_STATE_TRANSITION) {
3454 3454 it->sbd_it_ua_conditions &=
3455 3455 ~SBD_UA_ACCESS_STATE_TRANSITION;
3456 3456 saa = STMF_SAA_LU_NO_ACCESS_TRANSITION;
3457 3457 } else {
3458 3458 it->sbd_it_ua_conditions = 0;
3459 3459 saa = 0;
3460 3460 }
3461 3461 mutex_exit(&sl->sl_lock);
3462 3462 if (saa) {
3463 3463 stmf_scsilib_send_status(task, STATUS_CHECK, saa);
3464 3464 return;
3465 3465 }
3466 3466 }
3467 3467
3468 3468 if (sl->sl_access_state == SBD_LU_STANDBY) {
3469 3469 /*
3470 3470 * is this a short write?
3471 3471 * if so, we'll need to wait until we have the buffer
3472 3472 * before proxying the command
3473 3473 */
3474 3474 switch (cdb0) {
3475 3475 case SCMD_MODE_SELECT:
3476 3476 case SCMD_MODE_SELECT_G1:
3477 3477 case SCMD_PERSISTENT_RESERVE_OUT:
3478 3478 break;
3479 3479 default:
3480 3480 st_ret = stmf_proxy_scsi_cmd(task,
3481 3481 initial_dbuf);
3482 3482 if (st_ret != STMF_SUCCESS) {
3483 3483 stmf_scsilib_send_status(task,
3484 3484 STATUS_CHECK,
3485 3485 STMF_SAA_LU_NO_ACCESS_UNAVAIL);
3486 3486 }
3487 3487 return;
3488 3488 }
3489 3489 }
3490 3490
3491 3491 cdb0 = task->task_cdb[0] & 0x1F;
3492 3492
3493 3493 if ((cdb0 == SCMD_READ) || (cdb0 == SCMD_WRITE)) {
3494 3494 if (task->task_additional_flags & TASK_AF_PORT_LOAD_HIGH) {
3495 3495 stmf_scsilib_send_status(task, STATUS_QFULL, 0);
3496 3496 return;
3497 3497 }
3498 3498 if (cdb0 == SCMD_READ) {
3499 3499 sbd_handle_read(task, initial_dbuf);
3500 3500 return;
3501 3501 }
3502 3502 sbd_handle_write(task, initial_dbuf);
3503 3503 return;
3504 3504 }
3505 3505
3506 3506 cdb0 = task->task_cdb[0];
3507 3507 cdb1 = task->task_cdb[1];
3508 3508
3509 3509 if (cdb0 == SCMD_INQUIRY) { /* Inquiry */
3510 3510 sbd_handle_inquiry(task, initial_dbuf);
3511 3511 return;
3512 3512 }
3513 3513
3514 3514 if (cdb0 == SCMD_PERSISTENT_RESERVE_OUT) {
3515 3515 sbd_handle_pgr_out_cmd(task, initial_dbuf);
3516 3516 return;
3517 3517 }
3518 3518
3519 3519 if (cdb0 == SCMD_PERSISTENT_RESERVE_IN) {
3520 3520 sbd_handle_pgr_in_cmd(task, initial_dbuf);
3521 3521 return;
3522 3522 }
3523 3523
3524 3524 if (cdb0 == SCMD_RELEASE) {
3525 3525 if (cdb1) {
3526 3526 stmf_scsilib_send_status(task, STATUS_CHECK,
3527 3527 STMF_SAA_INVALID_FIELD_IN_CDB);
3528 3528 return;
3529 3529 }
3530 3530
3531 3531 mutex_enter(&sl->sl_lock);
3532 3532 if (sl->sl_flags & SL_LU_HAS_SCSI2_RESERVATION) {
3533 3533 /* If not owner don't release it, just return good */
3534 3534 if (it->sbd_it_session_id !=
3535 3535 sl->sl_rs_owner_session_id) {
3536 3536 mutex_exit(&sl->sl_lock);
3537 3537 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
3538 3538 return;
3539 3539 }
3540 3540 }
3541 3541 sl->sl_flags &= ~SL_LU_HAS_SCSI2_RESERVATION;
3542 3542 it->sbd_it_flags &= ~SBD_IT_HAS_SCSI2_RESERVATION;
3543 3543 mutex_exit(&sl->sl_lock);
3544 3544 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
3545 3545 return;
3546 3546 }
3547 3547
3548 3548 if (cdb0 == SCMD_RESERVE) {
3549 3549 if (cdb1) {
3550 3550 stmf_scsilib_send_status(task, STATUS_CHECK,
3551 3551 STMF_SAA_INVALID_FIELD_IN_CDB);
3552 3552 return;
3553 3553 }
3554 3554
3555 3555 mutex_enter(&sl->sl_lock);
3556 3556 if (sl->sl_flags & SL_LU_HAS_SCSI2_RESERVATION) {
3557 3557 /* If not owner, return conflict status */
3558 3558 if (it->sbd_it_session_id !=
3559 3559 sl->sl_rs_owner_session_id) {
3560 3560 mutex_exit(&sl->sl_lock);
3561 3561 stmf_scsilib_send_status(task,
3562 3562 STATUS_RESERVATION_CONFLICT, 0);
3563 3563 return;
3564 3564 }
3565 3565 }
3566 3566 sl->sl_flags |= SL_LU_HAS_SCSI2_RESERVATION;
3567 3567 it->sbd_it_flags |= SBD_IT_HAS_SCSI2_RESERVATION;
3568 3568 sl->sl_rs_owner_session_id = it->sbd_it_session_id;
3569 3569 mutex_exit(&sl->sl_lock);
3570 3570 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
3571 3571 return;
3572 3572 }
3573 3573
3574 3574 if (cdb0 == SCMD_REQUEST_SENSE) {
3575 3575 /*
3576 3576 * LU provider needs to store unretrieved sense data
3577 3577 * (e.g. after power-on/reset). For now, we'll just
3578 3578 * return good status with no sense.
3579 3579 */
3580 3580
3581 3581 if ((cdb1 & ~1) || task->task_cdb[2] || task->task_cdb[3] ||
3582 3582 task->task_cdb[5]) {
3583 3583 stmf_scsilib_send_status(task, STATUS_CHECK,
3584 3584 STMF_SAA_INVALID_FIELD_IN_CDB);
3585 3585 } else {
3586 3586 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
3587 3587 }
3588 3588
3589 3589 return;
3590 3590 }
3591 3591
3592 3592 /* Report Target Port Groups */
3593 3593 if ((cdb0 == SCMD_MAINTENANCE_IN) &&
3594 3594 ((cdb1 & 0x1F) == 0x0A)) {
3595 3595 stmf_scsilib_handle_report_tpgs(task, initial_dbuf);
3596 3596 return;
3597 3597 }
3598 3598
3599 3599 /* Report Identifying Information */
3600 3600 if ((cdb0 == SCMD_MAINTENANCE_IN) &&
3601 3601 ((cdb1 & 0x1F) == 0x05)) {
3602 3602 sbd_handle_identifying_info(task, initial_dbuf);
3603 3603 return;
3604 3604 }
3605 3605
3606 3606 if (cdb0 == SCMD_START_STOP) { /* Start stop */
3607 3607 task->task_cmd_xfer_length = 0;
3608 3608 if (task->task_cdb[4] & 0xFC) {
3609 3609 stmf_scsilib_send_status(task, STATUS_CHECK,
3610 3610 STMF_SAA_INVALID_FIELD_IN_CDB);
3611 3611 return;
3612 3612 }
3613 3613 if (task->task_cdb[4] & 2) {
3614 3614 stmf_scsilib_send_status(task, STATUS_CHECK,
3615 3615 STMF_SAA_INVALID_FIELD_IN_CDB);
3616 3616 } else {
3617 3617 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
3618 3618 }
3619 3619 return;
3620 3620
3621 3621 }
3622 3622
3623 3623 if ((cdb0 == SCMD_MODE_SENSE) || (cdb0 == SCMD_MODE_SENSE_G1)) {
3624 3624 uint8_t *p;
3625 3625 p = kmem_zalloc(512, KM_SLEEP);
3626 3626 sbd_handle_mode_sense(task, initial_dbuf, p);
3627 3627 kmem_free(p, 512);
3628 3628 return;
3629 3629 }
3630 3630
3631 3631 if ((cdb0 == SCMD_MODE_SELECT) || (cdb0 == SCMD_MODE_SELECT_G1)) {
3632 3632 sbd_handle_mode_select(task, initial_dbuf);
3633 3633 return;
3634 3634 }
3635 3635
3636 3636 if ((cdb0 == SCMD_UNMAP) && (sl->sl_flags & SL_UNMAP_ENABLED)) {
3637 3637 sbd_handle_unmap(task, initial_dbuf);
3638 3638 return;
3639 3639 }
3640 3640
3641 3641 if ((cdb0 == SCMD_WRITE_SAME_G4) || (cdb0 == SCMD_WRITE_SAME_G1)) {
3642 3642 sbd_handle_write_same(task, initial_dbuf);
3643 3643 return;
3644 3644 }
3645 3645
3646 3646 if (cdb0 == SCMD_COMPARE_AND_WRITE) {
3647 3647 sbd_handle_ats(task, initial_dbuf);
3648 3648 return;
3649 3649 }
3650 3650
3651 3651 if (cdb0 == SCMD_EXTENDED_COPY) {
3652 3652 sbd_handle_xcopy(task, initial_dbuf);
3653 3653 return;
3654 3654 }
3655 3655
3656 3656 if (cdb0 == SCMD_RECV_COPY_RESULTS) {
3657 3657 sbd_handle_recv_copy_results(task, initial_dbuf);
3658 3658 return;
3659 3659 }
3660 3660
3661 3661 if (cdb0 == SCMD_TEST_UNIT_READY) { /* Test unit ready */
3662 3662 task->task_cmd_xfer_length = 0;
3663 3663 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
3664 3664 return;
3665 3665 }
3666 3666
3667 3667 if (cdb0 == SCMD_READ_CAPACITY) { /* Read Capacity */
3668 3668 sbd_handle_read_capacity(task, initial_dbuf);
3669 3669 return;
3670 3670 }
3671 3671
3672 3672 if (cdb0 == SCMD_SVC_ACTION_IN_G4) { /* Read Capacity or read long */
3673 3673 if (cdb1 == SSVC_ACTION_READ_CAPACITY_G4) {
3674 3674 sbd_handle_read_capacity(task, initial_dbuf);
3675 3675 return;
3676 3676 /*
3677 3677 * } else if (cdb1 == SSVC_ACTION_READ_LONG_G4) {
3678 3678 * sbd_handle_read(task, initial_dbuf);
3679 3679 * return;
3680 3680 */
3681 3681 }
3682 3682 }
3683 3683
3684 3684 /*
3685 3685 * if (cdb0 == SCMD_SVC_ACTION_OUT_G4) {
3686 3686 * if (cdb1 == SSVC_ACTION_WRITE_LONG_G4) {
3687 3687 * sbd_handle_write(task, initial_dbuf);
3688 3688 * return;
3689 3689 * }
3690 3690 * }
3691 3691 */
3692 3692
3693 3693 if (cdb0 == SCMD_VERIFY) {
3694 3694 /*
3695 3695 * Something more likely needs to be done here.
3696 3696 */
3697 3697 task->task_cmd_xfer_length = 0;
3698 3698 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
3699 3699 return;
3700 3700 }
3701 3701
3702 3702 if (cdb0 == SCMD_SYNCHRONIZE_CACHE ||
3703 3703 cdb0 == SCMD_SYNCHRONIZE_CACHE_G4) {
3704 3704 sbd_handle_sync_cache(task, initial_dbuf);
3705 3705 return;
3706 3706 }
3707 3707
3708 3708 /*
3709 3709 * Write and Verify use the same path as write, but don't clutter the
3710 3710 * performance path above with checking for write_verify opcodes. We
3711 3711 * rely on zfs's integrity checks for the "Verify" part of Write &
3712 3712 * Verify. (Even if we did a read to "verify" we'd merely be reading
3713 3713 * cache, not actual media.)
3714 3714 * Therefore we
3715 3715 * a) only support this if sbd_is_zvol, and
3716 3716 * b) run the IO through the normal write path with a forced
3717 3717 * sbd_flush_data_cache at the end.
3718 3718 */
3719 3719
3720 3720 if ((sl->sl_flags & SL_ZFS_META) && (
3721 3721 cdb0 == SCMD_WRITE_VERIFY ||
3722 3722 cdb0 == SCMD_WRITE_VERIFY_G4 ||
3723 3723 cdb0 == SCMD_WRITE_VERIFY_G5)) {
3724 3724 sbd_handle_write(task, initial_dbuf);
3725 3725 return;
3726 3726 }
3727 3727 stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INVALID_OPCODE);
3728 3728 }
3729 3729
3730 3730 void
3731 3731 sbd_dbuf_xfer_done(struct scsi_task *task, struct stmf_data_buf *dbuf)
3732 3732 {
3733 3733 sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
3734 3734
3735 3735 if (dbuf->db_flags & DB_LU_DATA_BUF) {
3736 3736 /*
3737 3737 * Buffers passed in from the LU always complete
3738 3738 * even if the task is no longer active.
3739 3739 */
3740 3740 ASSERT(task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF);
3741 3741 ASSERT(scmd);
3742 3742 switch (scmd->cmd_type) {
3743 3743 case (SBD_CMD_SCSI_READ):
3744 3744 sbd_handle_sgl_read_xfer_completion(task, scmd, dbuf);
3745 3745 break;
3746 3746 case (SBD_CMD_SCSI_WRITE):
3747 3747 sbd_handle_sgl_write_xfer_completion(task, scmd, dbuf);
3748 3748 break;
3749 3749 default:
3750 3750 cmn_err(CE_PANIC, "Unknown cmd type, task = %p",
3751 3751 (void *)task);
3752 3752 break;
3753 3753 }
3754 3754 return;
3755 3755 }
3756 3756
3757 3757 if ((scmd == NULL) || ((scmd->flags & SBD_SCSI_CMD_ACTIVE) == 0))
3758 3758 return;
3759 3759
3760 3760 switch (scmd->cmd_type) {
3761 3761 case (SBD_CMD_SCSI_READ):
3762 3762 sbd_handle_read_xfer_completion(task, scmd, dbuf);
3763 3763 break;
3764 3764
3765 3765 case (SBD_CMD_SCSI_WRITE):
3766 3766 switch (task->task_cdb[0]) {
3767 3767 case SCMD_WRITE_SAME_G1:
3768 3768 case SCMD_WRITE_SAME_G4:
3769 3769 sbd_handle_write_same_xfer_completion(task, scmd, dbuf,
3770 3770 1);
3771 3771 break;
3772 3772 case SCMD_COMPARE_AND_WRITE:
3773 3773 sbd_handle_ats_xfer_completion(task, scmd, dbuf, 1);
3774 3774 break;
3775 3775 default:
3776 3776 sbd_handle_write_xfer_completion(task, scmd, dbuf, 1);
3777 3777 /* FALLTHRU */
3778 3778 }
3779 3779 break;
3780 3780
3781 3781 case (SBD_CMD_SMALL_READ):
3782 3782 sbd_handle_short_read_xfer_completion(task, scmd, dbuf);
3783 3783 break;
3784 3784
3785 3785 case (SBD_CMD_SMALL_WRITE):
3786 3786 sbd_handle_short_write_xfer_completion(task, dbuf);
3787 3787 break;
3788 3788
3789 3789 default:
3790 3790 cmn_err(CE_PANIC, "Unknown cmd type, task = %p", (void *)task);
3791 3791 break;
3792 3792 }
3793 3793 }
3794 3794
3795 3795 /* ARGSUSED */
3796 3796 void
3797 3797 sbd_send_status_done(struct scsi_task *task)
3798 3798 {
3799 3799 cmn_err(CE_PANIC,
3800 3800 "sbd_send_status_done: this should not have been called");
3801 3801 }
3802 3802
3803 3803 void
3804 3804 sbd_task_free(struct scsi_task *task)
3805 3805 {
3806 3806 if (task->task_lu_private) {
3807 3807 sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
3808 3808 if (scmd->flags & SBD_SCSI_CMD_ACTIVE) {
3809 3809 cmn_err(CE_PANIC, "cmd is active, task = %p",
3810 3810 (void *)task);
3811 3811 }
3812 3812 kmem_free(scmd, sizeof (sbd_cmd_t));
3813 3813 }
3814 3814 }
3815 3815
3816 3816 /*
3817 3817 * Aborts are synchronus w.r.t. I/O AND
3818 3818 * All the I/O which SBD does is synchronous AND
3819 3819 * Everything within a task is single threaded.
3820 3820 * IT MEANS
3821 3821 * If this function is called, we are doing nothing with this task
3822 3822 * inside of sbd module.
3823 3823 */
3824 3824 /* ARGSUSED */
3825 3825 stmf_status_t
3826 3826 sbd_abort(struct stmf_lu *lu, int abort_cmd, void *arg, uint32_t flags)
3827 3827 {
3828 3828 sbd_lu_t *sl = (sbd_lu_t *)lu->lu_provider_private;
3829 3829 scsi_task_t *task;
3830 3830
3831 3831 if (abort_cmd == STMF_LU_RESET_STATE) {
3832 3832 return (sbd_lu_reset_state(lu));
3833 3833 }
3834 3834
3835 3835 if (abort_cmd == STMF_LU_ITL_HANDLE_REMOVED) {
3836 3836 sbd_check_and_clear_scsi2_reservation(sl, (sbd_it_data_t *)arg);
3837 3837 sbd_remove_it_handle(sl, (sbd_it_data_t *)arg);
3838 3838 return (STMF_SUCCESS);
3839 3839 }
3840 3840
3841 3841 ASSERT(abort_cmd == STMF_LU_ABORT_TASK);
3842 3842 task = (scsi_task_t *)arg;
3843 3843 sbd_ats_remove_by_task(task);
3844 3844 if (task->task_lu_private) {
3845 3845 sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
3846 3846
3847 3847 if (scmd->flags & SBD_SCSI_CMD_ACTIVE) {
3848 3848 if (scmd->flags & SBD_SCSI_CMD_TRANS_DATA) {
3849 3849 kmem_free(scmd->trans_data,
3850 3850 scmd->trans_data_len);
3851 3851 scmd->flags &= ~SBD_SCSI_CMD_TRANS_DATA;
3852 3852 }
3853 3853 scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
3854 3854 return (STMF_ABORT_SUCCESS);
3855 3855 }
3856 3856 }
3857 3857
3858 3858 return (STMF_NOT_FOUND);
3859 3859 }
3860 3860
3861 3861 void
3862 3862 sbd_task_poll(struct scsi_task *task)
3863 3863 {
3864 3864 stmf_data_buf_t *initial_dbuf;
3865 3865
3866 3866 initial_dbuf = stmf_handle_to_buf(task, 0);
3867 3867 sbd_new_task(task, initial_dbuf);
3868 3868 }
3869 3869
3870 3870 /*
3871 3871 * This function is called during task clean-up if the
3872 3872 * DB_LU_FLAG is set on the dbuf. This should only be called for
3873 3873 * abort processing after sbd_abort has been called for the task.
3874 3874 */
3875 3875 void
3876 3876 sbd_dbuf_free(struct scsi_task *task, struct stmf_data_buf *dbuf)
3877 3877 {
3878 3878 sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
3879 3879 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
3880 3880
3881 3881 ASSERT(dbuf->db_lu_private);
3882 3882 ASSERT(scmd && ATOMIC8_GET(scmd->nbufs) > 0);
3883 3883 ASSERT((scmd->flags & SBD_SCSI_CMD_ACTIVE) == 0);
3884 3884 ASSERT(dbuf->db_flags & DB_LU_DATA_BUF);
3885 3885 ASSERT(task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF);
3886 3886 ASSERT((curthread->t_flag & T_INTR_THREAD) == 0);
3887 3887
3888 3888 if (scmd->cmd_type == SBD_CMD_SCSI_READ) {
3889 3889 sbd_zvol_rele_read_bufs(sl, dbuf);
3890 3890 } else if (scmd->cmd_type == SBD_CMD_SCSI_WRITE) {
3891 3891 sbd_zvol_rele_write_bufs_abort(sl, dbuf);
3892 3892 } else {
3893 3893 cmn_err(CE_PANIC, "Unknown cmd type %d, task = %p",
3894 3894 scmd->cmd_type, (void *)task);
3895 3895 }
3896 3896 if (atomic_dec_8_nv(&scmd->nbufs) == 0)
3897 3897 rw_exit(&sl->sl_access_state_lock);
3898 3898 stmf_teardown_dbuf(task, dbuf);
3899 3899 stmf_free(dbuf);
3900 3900 }
3901 3901
3902 3902 /* ARGSUSED */
3903 3903 void
3904 3904 sbd_ctl(struct stmf_lu *lu, int cmd, void *arg)
3905 3905 {
3906 3906 sbd_lu_t *sl = (sbd_lu_t *)lu->lu_provider_private;
3907 3907 stmf_change_status_t st;
3908 3908
3909 3909 ASSERT((cmd == STMF_CMD_LU_ONLINE) ||
3910 3910 (cmd == STMF_CMD_LU_OFFLINE) ||
3911 3911 (cmd == STMF_ACK_LU_ONLINE_COMPLETE) ||
3912 3912 (cmd == STMF_ACK_LU_OFFLINE_COMPLETE));
3913 3913
3914 3914 st.st_completion_status = STMF_SUCCESS;
3915 3915 st.st_additional_info = NULL;
3916 3916
3917 3917 switch (cmd) {
3918 3918 case STMF_CMD_LU_ONLINE:
3919 3919 if (sl->sl_state == STMF_STATE_ONLINE)
3920 3920 st.st_completion_status = STMF_ALREADY;
3921 3921 else if (sl->sl_state != STMF_STATE_OFFLINE)
3922 3922 st.st_completion_status = STMF_FAILURE;
3923 3923 if (st.st_completion_status == STMF_SUCCESS) {
3924 3924 sl->sl_state = STMF_STATE_ONLINE;
3925 3925 sl->sl_state_not_acked = 1;
3926 3926 }
3927 3927 (void) stmf_ctl(STMF_CMD_LU_ONLINE_COMPLETE, lu, &st);
3928 3928 break;
3929 3929
3930 3930 case STMF_CMD_LU_OFFLINE:
3931 3931 if (sl->sl_state == STMF_STATE_OFFLINE)
3932 3932 st.st_completion_status = STMF_ALREADY;
3933 3933 else if (sl->sl_state != STMF_STATE_ONLINE)
3934 3934 st.st_completion_status = STMF_FAILURE;
3935 3935 if (st.st_completion_status == STMF_SUCCESS) {
3936 3936 sl->sl_flags &= ~(SL_MEDIUM_REMOVAL_PREVENTED |
3937 3937 SL_LU_HAS_SCSI2_RESERVATION);
3938 3938 sl->sl_state = STMF_STATE_OFFLINE;
3939 3939 sl->sl_state_not_acked = 1;
3940 3940 sbd_pgr_reset(sl);
3941 3941 }
3942 3942 (void) stmf_ctl(STMF_CMD_LU_OFFLINE_COMPLETE, lu, &st);
3943 3943 break;
3944 3944
3945 3945 case STMF_ACK_LU_ONLINE_COMPLETE:
3946 3946 /* Fallthrough */
3947 3947 case STMF_ACK_LU_OFFLINE_COMPLETE:
3948 3948 sl->sl_state_not_acked = 0;
3949 3949 break;
3950 3950
3951 3951 }
3952 3952 }
3953 3953
3954 3954 /* ARGSUSED */
3955 3955 stmf_status_t
3956 3956 sbd_info(uint32_t cmd, stmf_lu_t *lu, void *arg, uint8_t *buf,
3957 3957 uint32_t *bufsizep)
3958 3958 {
3959 3959 return (STMF_NOT_SUPPORTED);
3960 3960 }
3961 3961
3962 3962 stmf_status_t
3963 3963 sbd_lu_reset_state(stmf_lu_t *lu)
3964 3964 {
3965 3965 sbd_lu_t *sl = (sbd_lu_t *)lu->lu_provider_private;
3966 3966
3967 3967 mutex_enter(&sl->sl_lock);
3968 3968 if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE) {
3969 3969 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
3970 3970 mutex_exit(&sl->sl_lock);
3971 3971 if (sl->sl_access_state == SBD_LU_ACTIVE) {
3972 3972 (void) sbd_wcd_set(1, sl);
3973 3973 }
3974 3974 } else {
3975 3975 sl->sl_flags &= ~SL_WRITEBACK_CACHE_DISABLE;
3976 3976 mutex_exit(&sl->sl_lock);
3977 3977 if (sl->sl_access_state == SBD_LU_ACTIVE) {
3978 3978 (void) sbd_wcd_set(0, sl);
3979 3979 }
3980 3980 }
3981 3981 sbd_pgr_reset(sl);
3982 3982 sbd_check_and_clear_scsi2_reservation(sl, NULL);
3983 3983 if (stmf_deregister_all_lu_itl_handles(lu) != STMF_SUCCESS) {
3984 3984 return (STMF_FAILURE);
3985 3985 }
3986 3986 return (STMF_SUCCESS);
3987 3987 }
3988 3988
3989 3989 sbd_status_t
3990 3990 sbd_flush_data_cache(sbd_lu_t *sl, int fsync_done)
3991 3991 {
3992 3992 sbd_status_t ret = SBD_SUCCESS;
3993 3993
3994 3994 rw_enter(&sl->sl_access_state_lock, RW_READER);
3995 3995 if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
3996 3996 ret = SBD_FILEIO_FAILURE;
3997 3997 goto flush_fail;
3998 3998 }
3999 3999 if (fsync_done)
4000 4000 goto over_fsync;
4001 4001 if ((sl->sl_data_vtype == VREG) || (sl->sl_data_vtype == VBLK)) {
4002 4002 if (VOP_FSYNC(sl->sl_data_vp, FSYNC, kcred, NULL)) {
4003 4003 ret = SBD_FAILURE;
4004 4004 goto flush_fail;
4005 4005 }
4006 4006 }
4007 4007 over_fsync:
4008 4008 if (((sl->sl_data_vtype == VCHR) || (sl->sl_data_vtype == VBLK)) &&
4009 4009 ((sl->sl_flags & SL_NO_DATA_DKIOFLUSH) == 0)) {
4010 4010 int r = 0;
4011 4011
4012 4012 ret = VOP_IOCTL(sl->sl_data_vp, DKIOCFLUSHWRITECACHE, 0,
4013 4013 FKIOCTL, kcred, &r, NULL);
4014 4014 if ((ret == ENOTTY) || (ret == ENOTSUP)) {
4015 4015 mutex_enter(&sl->sl_lock);
4016 4016 sl->sl_flags |= SL_NO_DATA_DKIOFLUSH;
4017 4017 mutex_exit(&sl->sl_lock);
4018 4018 } else {
4019 4019 ret = (ret != 0) ? SBD_FAILURE : SBD_SUCCESS;
4020 4020 }
4021 4021 }
4022 4022 flush_fail:
4023 4023 rw_exit(&sl->sl_access_state_lock);
4024 4024
4025 4025 return (ret);
4026 4026 }
4027 4027
4028 4028 /* ARGSUSED */
4029 4029 static void
4030 4030 sbd_handle_sync_cache(struct scsi_task *task,
4031 4031 struct stmf_data_buf *initial_dbuf)
4032 4032 {
4033 4033 sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
4034 4034 uint64_t lba, laddr;
4035 4035 sbd_status_t sret;
4036 4036 uint32_t len;
4037 4037 int is_g4 = 0;
4038 4038 int immed;
4039 4039
4040 4040 task->task_cmd_xfer_length = 0;
4041 4041 /*
4042 4042 * Determine if this is a 10 or 16 byte CDB
4043 4043 */
4044 4044
4045 4045 if (task->task_cdb[0] == SCMD_SYNCHRONIZE_CACHE_G4)
4046 4046 is_g4 = 1;
4047 4047
4048 4048 /*
4049 4049 * Determine other requested parameters
4050 4050 *
4051 4051 * We don't have a non-volatile cache, so don't care about SYNC_NV.
4052 4052 * Do not support the IMMED bit.
4053 4053 */
4054 4054
4055 4055 immed = (task->task_cdb[1] & 0x02);
4056 4056
4057 4057 if (immed) {
4058 4058 stmf_scsilib_send_status(task, STATUS_CHECK,
4059 4059 STMF_SAA_INVALID_FIELD_IN_CDB);
4060 4060 return;
4061 4061 }
4062 4062
4063 4063 /*
4064 4064 * Check to be sure we're not being asked to sync an LBA
4065 4065 * that is out of range. While checking, verify reserved fields.
4066 4066 */
4067 4067
4068 4068 if (is_g4) {
4069 4069 if ((task->task_cdb[1] & 0xf9) || task->task_cdb[14] ||
4070 4070 task->task_cdb[15]) {
4071 4071 stmf_scsilib_send_status(task, STATUS_CHECK,
4072 4072 STMF_SAA_INVALID_FIELD_IN_CDB);
4073 4073 return;
4074 4074 }
4075 4075
4076 4076 lba = READ_SCSI64(&task->task_cdb[2], uint64_t);
4077 4077 len = READ_SCSI32(&task->task_cdb[10], uint32_t);
4078 4078 } else {
4079 4079 if ((task->task_cdb[1] & 0xf9) || task->task_cdb[6] ||
4080 4080 task->task_cdb[9]) {
4081 4081 stmf_scsilib_send_status(task, STATUS_CHECK,
4082 4082 STMF_SAA_INVALID_FIELD_IN_CDB);
4083 4083 return;
4084 4084 }
4085 4085
4086 4086 lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
4087 4087 len = READ_SCSI16(&task->task_cdb[7], uint32_t);
4088 4088 }
4089 4089
4090 4090 laddr = lba << sl->sl_data_blocksize_shift;
4091 4091 len <<= sl->sl_data_blocksize_shift;
4092 4092
4093 4093 if ((laddr + (uint64_t)len) > sl->sl_lu_size) {
4094 4094 stmf_scsilib_send_status(task, STATUS_CHECK,
4095 4095 STMF_SAA_LBA_OUT_OF_RANGE);
4096 4096 return;
4097 4097 }
4098 4098
4099 4099 sret = sbd_flush_data_cache(sl, 0);
4100 4100 if (sret != SBD_SUCCESS) {
4101 4101 stmf_scsilib_send_status(task, STATUS_CHECK,
4102 4102 STMF_SAA_WRITE_ERROR);
4103 4103 return;
4104 4104 }
4105 4105
4106 4106 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
4107 4107 }
|
↓ open down ↓ |
1705 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX