Print this page
NEX-4433 Deadlock among txg_wait_synced(), sbd_pgr_remove_it_handle(), and ppt_sess_lookup_create() after HA failover
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
NEX-3111 Comstar does not pass cstyle and hdrchk
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Tony Nguyen <tony.nguyen@nexenta.com>
SUP-765 When a Windows Clustered Shared Volume is placed on a pool under Nexenta HA Cluster control the clustered shared disk looses its PGR3 reservation to the presented zvol.
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Tony Nguyen <tony.nguyen@nexenta.com>
Reviewed by: Josef Sipek <josef.sipek@nexenta.com>
Re #6790 backspace should perform delete on console
VAAI (XXX ATS support for COMSTAR, YYY Block-copy support for COMSTAR)
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_pgr.c
+++ new/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_pgr.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 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
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 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23 + *
24 + * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
23 25 */
24 26
25 27 #include <sys/atomic.h>
26 28 #include <sys/conf.h>
27 29 #include <sys/byteorder.h>
28 30 #include <sys/scsi/scsi_types.h>
29 31 #include <sys/scsi/generic/persist.h>
30 32
31 33 #include <sys/lpif.h>
32 34 #include <sys/stmf.h>
33 35 #include <sys/stmf_ioctl.h>
34 36 #include <sys/portif.h>
35 37 #include <sys/stmf_sbd_ioctl.h>
36 38
37 39 #include "stmf_sbd.h"
38 40 #include "sbd_impl.h"
39 41
40 42 #define MAX_PGR_PARAM_LIST_LENGTH (256 * 1024)
41 43
42 -int sbd_pgr_reservation_conflict(scsi_task_t *);
44 +int sbd_pgr_reservation_conflict(scsi_task_t *, struct sbd_lu *sl);
43 45 void sbd_pgr_reset(sbd_lu_t *);
44 46 void sbd_pgr_initialize_it(scsi_task_t *, sbd_it_data_t *);
45 47 void sbd_handle_pgr_in_cmd(scsi_task_t *, stmf_data_buf_t *);
46 48 void sbd_handle_pgr_out_cmd(scsi_task_t *, stmf_data_buf_t *);
47 49 void sbd_handle_pgr_out_data(scsi_task_t *, stmf_data_buf_t *);
48 50 void sbd_pgr_keylist_dealloc(sbd_lu_t *);
49 51 char *sbd_get_devid_string(sbd_lu_t *);
50 52
51 53 sbd_status_t sbd_pgr_meta_init(sbd_lu_t *);
52 54 sbd_status_t sbd_pgr_meta_load(sbd_lu_t *);
53 55 sbd_status_t sbd_pgr_meta_write(sbd_lu_t *);
54 56 static void sbd_swap_pgr_info(sbd_pgr_info_t *);
55 57 static void sbd_swap_pgrkey_info(sbd_pgr_key_info_t *);
56 58 static void sbd_pgr_key_free(sbd_pgr_key_t *);
57 59 static void sbd_pgr_remove_key(sbd_lu_t *, sbd_pgr_key_t *);
58 60 static uint32_t sbd_pgr_remove_keys(sbd_lu_t *, sbd_it_data_t *,
59 61 sbd_pgr_key_t *, uint64_t, boolean_t);
60 62 static boolean_t sbd_pgr_key_compare(sbd_pgr_key_t *, scsi_devid_desc_t *,
61 63 stmf_remote_port_t *);
62 64 static sbd_pgr_key_t *sbd_pgr_key_alloc(scsi_devid_desc_t *,
63 65 scsi_transport_id_t *, int16_t, int16_t);
64 66
65 67 static void sbd_pgr_set_pgr_check_flag(sbd_lu_t *, boolean_t);
66 68 static void sbd_pgr_set_ua_conditions(sbd_lu_t *, sbd_it_data_t *, uint8_t);
67 69 static void sbd_pgr_in_read_keys(scsi_task_t *, stmf_data_buf_t *);
68 70 static void sbd_pgr_in_report_capabilities(scsi_task_t *, stmf_data_buf_t *);
69 71 static void sbd_pgr_in_read_reservation(scsi_task_t *, stmf_data_buf_t *);
70 72 static void sbd_pgr_in_read_full_status(scsi_task_t *, stmf_data_buf_t *);
71 73 static void sbd_pgr_out_register(scsi_task_t *, stmf_data_buf_t *);
72 74 static void sbd_pgr_out_reserve(scsi_task_t *);
73 75 static void sbd_pgr_out_release(scsi_task_t *);
74 76 static void sbd_pgr_out_clear(scsi_task_t *);
|
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
75 77 static void sbd_pgr_out_preempt(scsi_task_t *, stmf_data_buf_t *);
76 78 static void sbd_pgr_out_register_and_move(scsi_task_t *, stmf_data_buf_t *);
77 79
78 80 static sbd_pgr_key_t *sbd_pgr_do_register(sbd_lu_t *, sbd_it_data_t *,
79 81 scsi_devid_desc_t *, stmf_remote_port_t *, uint8_t, uint64_t);
80 82 static void sbd_pgr_do_unregister(sbd_lu_t *, sbd_it_data_t *, sbd_pgr_key_t *);
81 83 static void sbd_pgr_do_release(sbd_lu_t *, sbd_it_data_t *, uint8_t);
82 84 static void sbd_pgr_do_reserve(sbd_pgr_t *, sbd_pgr_key_t *, sbd_it_data_t *it,
83 85 stmf_scsi_session_t *, scsi_cdb_prout_t *);
84 86
87 +static boolean_t sbd_pgr_should_save(sbd_lu_t *);
85 88 extern sbd_status_t sbd_write_meta_section(sbd_lu_t *, sm_section_hdr_t *);
86 89 extern sbd_status_t sbd_read_meta_section(sbd_lu_t *, sm_section_hdr_t **,
87 90 uint16_t);
88 91 extern void sbd_swap_section_hdr(sm_section_hdr_t *);
89 92 extern void sbd_handle_short_write_transfers(scsi_task_t *task,
90 93 stmf_data_buf_t *dbuf, uint32_t cdb_xfer_size);
91 94 extern void sbd_handle_short_read_transfers(scsi_task_t *task,
92 95 stmf_data_buf_t *dbuf, uint8_t *p, uint32_t cdb_xfer_size,
93 96 uint32_t cmd_xfer_size);
94 97 extern uint16_t stmf_scsilib_get_lport_rtid(scsi_devid_desc_t *devid);
95 98 extern scsi_devid_desc_t *stmf_scsilib_get_devid_desc(uint16_t rtpid);
96 99 extern char sbd_ctoi(char c);
97 100
98 101 /*
99 102 *
100 103 *
101 104 * +-----------+
102 105 * | |sl_it_list
103 106 * | |---------------------------------------+
104 107 * | | |
105 108 * | sbd_lu_t | |
106 109 * | | |
107 110 * | | |
108 111 * | | |
109 112 * +-----+-----+ V
110 113 * | +-------+
111 114 * V | |
112 115 * +-----------+ pgr_key_list +------>| |
113 116 * | |------------+ +-->(NULL) | +- ---|sbd_it |
114 117 * | | | | | | | _data |
115 118 * | sbd_pgr_t | V | | | | |
116 119 * | | +-------+ | | +-------+
117 120 * | |---+ | | | | |
118 121 * | | | |sbd_pgr|---------+ | v
119 122 * +-----------+ | | _key_t|<----------+ +-------+
120 123 * | | | | |
121 124 * | | | | |
122 125 * | +-------+ +--------| |
123 126 * | |^ | | |
124 127 * | || | | |
125 128 * | v| | +-------+
126 129 * | +-------+ | |
127 130 * | | | | v
128 131 * | |ALL_TG_|<-------+ +-------+
129 132 * | |PT = 1 |<---------+ | |
130 133 * | | |---+ | | |
131 134 * | | | | +------| |
132 135 * (pgr_rsvholder +-------+ V | |
133 136 * pgr_flags& |^ (NUll) | |
134 137 * RSVD_ONE) || +-------+
135 138 * | v| |
136 139 * | +-------+ v
137 140 * | | | +-------+
138 141 * | | not | | |
139 142 * | |claimed|---+ | |
140 143 * | | | | +----| unreg |
141 144 * | | | V | | |
142 145 * | +-------+ (NUll) V | |
143 146 * | |^ (NUll) +-------+
144 147 * | || |
145 148 * | v| v
146 149 * | +-------+ +-------+
147 150 * | | | | |
148 151 * | |reserv-|<----------------| |
149 152 * +----->| ation|---------------->| |
150 153 * |holder | | |
151 154 * |key | | |
152 155 * +-------+ +-------+
153 156 * |^ |
154 157 * || v
155 158 * v| +-------+
156 159 * +-------+ | |
157 160 * | | | |
158 161 * | not |---+ +----| unreg |
159 162 * |claimed| | | | |
160 163 * | | V V | |
161 164 * | | (NUll) (NUll) +-------+
162 165 * +-------+ |
163 166 * | v
164 167 * v (NULL)
165 168 * (NULL)
166 169 *
167 170 *
168 171 */
169 172
170 173 #define PGR_CONFLICT_FREE_CMDS(cdb) ( \
171 174 /* ----------------------- */ \
172 175 /* SPC-3 (rev 23) Table 31 */ \
173 176 /* ----------------------- */ \
174 177 ((cdb[0]) == SCMD_INQUIRY) || \
175 178 ((cdb[0]) == SCMD_LOG_SENSE_G1) || \
176 179 ((cdb[0]) == SCMD_PERSISTENT_RESERVE_IN) || \
177 180 ((cdb[0]) == SCMD_REPORT_LUNS) || \
178 181 ((cdb[0]) == SCMD_REQUEST_SENSE) || \
179 182 ((cdb[0]) == SCMD_TEST_UNIT_READY) || \
180 183 /* PREVENT ALLOW MEDIUM REMOVAL with prevent == 0 */ \
181 184 ((((cdb[0]) == SCMD_DOORLOCK) && (((cdb[4]) & 0x3) == 0))) || \
182 185 /* SERVICE ACTION IN with READ MEDIA SERIAL NUMBER (0x01) */ \
183 186 (((cdb[0]) == SCMD_SVC_ACTION_IN_G5) && ( \
184 187 ((cdb[1]) & 0x1F) == 0x01)) || \
185 188 /* MAINTENANCE IN with service actions REPORT ALIASES (0x0Bh) */ \
186 189 /* REPORT DEVICE IDENTIFIER (0x05) REPORT PRIORITY (0x0Eh) */ \
187 190 /* REPORT TARGET PORT GROUPS (0x0A) REPORT TIMESTAMP (0x0F) */ \
188 191 (((cdb[0]) == SCMD_MAINTENANCE_IN) && ( \
189 192 (((cdb[1]) & 0x1F) == 0x0B) || \
190 193 (((cdb[1]) & 0x1F) == 0x05) || \
191 194 (((cdb[1]) & 0x1F) == 0x0E) || \
192 195 (((cdb[1]) & 0x1F) == 0x0A) || \
193 196 (((cdb[1]) & 0x1F) == 0x0F))) || \
194 197 /* REGISTER and REGISTER_AND_IGNORE_EXISTING_KEY */ \
195 198 /* actions for PERSISTENT RESERVE OUT command */ \
196 199 (((cdb[0]) == SCMD_PERSISTENT_RESERVE_OUT) && ( \
197 200 (((cdb[1]) & 0x1F) == PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY) || \
198 201 (((cdb[1]) & 0x1F) == PR_OUT_REGISTER))) || \
199 202 /* ----------------------- */ \
200 203 /* SBC-3 (rev 17) Table 3 */ \
201 204 /* ----------------------- */ \
202 205 /* READ CAPACITY(10) */ \
203 206 ((cdb[0]) == SCMD_READ_CAPACITY) || \
204 207 /* READ CAPACITY(16) */ \
205 208 (((cdb[0]) == SCMD_SVC_ACTION_IN_G4) && ( \
206 209 ((cdb[1]) & 0x1F) == 0x10)) || \
207 210 /* START STOP UNIT with START bit 0 and POWER CONDITION 0 */ \
208 211 (((cdb[0]) == SCMD_START_STOP) && ( \
209 212 (((cdb[4]) & 0xF0) == 0) && (((cdb[4]) & 0x01) == 0))))
210 213 /* End of PGR_CONFLICT_FREE_CMDS */
211 214
212 215 /* Commands allowed for registered IT nexues but not reservation holder */
213 216 #define PGR_REGISTERED_POSSIBLE_CMDS(cdb) ( \
214 217 (((cdb[0]) == SCMD_PERSISTENT_RESERVE_OUT) && ( \
215 218 (((cdb[1]) & 0x1F) == PR_OUT_RELEASE) || \
216 219 (((cdb[1]) & 0x1F) == PR_OUT_CLEAR) || \
217 220 (((cdb[1]) & 0x1F) == PR_OUT_PREEMPT) || \
218 221 (((cdb[1]) & 0x1F) == PR_OUT_PREEMPT_ABORT))))
219 222
220 223 /* List of commands allowed when WR_EX type reservation held */
221 224 #define PGR_READ_POSSIBLE_CMDS(c) ( \
222 225 ((c) == SCMD_READ) || \
223 226 ((c) == SCMD_READ_G1) || \
224 227 ((c) == SCMD_READ_G4) || \
225 228 ((c) == SCMD_READ_G5) || \
226 229 /* READ FETCH (10) (16) */ \
227 230 ((c) == SCMD_READ_POSITION) || \
228 231 ((c) == 0x90) || \
229 232 /* READ DEFECT DATA */ \
230 233 ((c) == SCMD_READ_DEFECT_LIST) || \
231 234 ((c) == 0xB7) || \
232 235 /* VERIFY (10) (16) (12) */ \
233 236 ((c) == SCMD_VERIFY) || \
234 237 ((c) == SCMD_VERIFY_G4) || \
235 238 ((c) == SCMD_VERIFY_G5) || \
236 239 /* XDREAD (10) */ \
237 240 ((c) == 0x52))
238 241
239 242 #define PGR_RESERVATION_HOLDER(pgr, key, it) ( \
240 243 ((pgr)->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS) || ( \
241 244 ((pgr)->pgr_rsvholder) && ((pgr)->pgr_rsvholder == (key)) && \
242 245 ((key)->pgr_key_it) && ((key)->pgr_key_it == (it))))
243 246
244 247 #define PGR_SET_FLAG(flg, val) (atomic_or_8(&(flg), (val)))
245 248 #define PGR_CLEAR_FLAG(flg, val) (atomic_and_8(&(flg), ~(val)))
246 249 #define PGR_CLEAR_RSV_FLAG(flg) (atomic_and_8(&(flg), \
247 250 (~(SBD_PGR_RSVD_ALL_REGISTRANTS | SBD_PGR_RSVD_ONE))))
248 251
249 252 #define PGR_VALID_SCOPE(scope) ((scope) == PR_LU_SCOPE)
250 253 #define PGR_VALID_TYPE(type) ( \
251 254 ((type) == PGR_TYPE_WR_EX) || \
252 255 ((type) == PGR_TYPE_EX_AC) || \
253 256 ((type) == PGR_TYPE_WR_EX_RO) || \
254 257 ((type) == PGR_TYPE_EX_AC_RO) || \
255 258 ((type) == PGR_TYPE_WR_EX_AR) || \
256 259 ((type) == PGR_TYPE_EX_AC_AR))
257 260
258 261 #define ALIGNED_TO_8BYTE_BOUNDARY(i) (((i) + 7) & ~7)
259 262
260 263 static void
261 264 sbd_swap_pgr_info(sbd_pgr_info_t *spi)
262 265 {
263 266 sbd_swap_section_hdr(&spi->pgr_sms_header);
264 267 if (spi->pgr_data_order == SMS_DATA_ORDER)
265 268 return;
266 269 spi->pgr_sms_header.sms_chksum += SMS_DATA_ORDER - spi->pgr_data_order;
267 270 spi->pgr_rsvholder_indx = BSWAP_32(spi->pgr_rsvholder_indx);
268 271 spi->pgr_numkeys = BSWAP_32(spi->pgr_numkeys);
269 272 }
270 273
271 274 static void
272 275 sbd_swap_pgrkey_info(sbd_pgr_key_info_t *key)
273 276 {
274 277 key->pgr_key = BSWAP_64(key->pgr_key);
275 278 key->pgr_key_lpt_len = BSWAP_16(key->pgr_key_lpt_len);
276 279 key->pgr_key_rpt_len = BSWAP_16(key->pgr_key_rpt_len);
277 280 }
278 281
279 282 sbd_status_t
280 283 sbd_pgr_meta_init(sbd_lu_t *slu)
281 284 {
282 285 sbd_pgr_info_t *spi = NULL;
283 286 uint32_t sz;
284 287 sbd_status_t ret;
285 288
286 289 sz = sizeof (sbd_pgr_info_t);
287 290 spi = (sbd_pgr_info_t *)kmem_zalloc(sz, KM_SLEEP);
|
↓ open down ↓ |
193 lines elided |
↑ open up ↑ |
288 291 spi->pgr_data_order = SMS_DATA_ORDER;
289 292 spi->pgr_sms_header.sms_size = sz;
290 293 spi->pgr_sms_header.sms_id = SMS_ID_PGR_INFO;
291 294 spi->pgr_sms_header.sms_data_order = SMS_DATA_ORDER;
292 295
293 296 ret = sbd_write_meta_section(slu, (sm_section_hdr_t *)spi);
294 297 kmem_free(spi, sz);
295 298 return (ret);
296 299 }
297 300
301 +/*
302 + * Evaluate common cases where a PERSISTENT RESERVE OUT CDB handler should call
303 + * sbd_pgr_meta_write().
304 + */
305 +static boolean_t
306 +sbd_pgr_should_save(sbd_lu_t *slu)
307 +{
308 + sbd_pgr_t *pgr = slu->sl_pgr;
309 +
310 + if (stmf_is_pgr_aptpl_always() == B_TRUE ||
311 + (pgr->pgr_flags & (SBD_PGR_APTPL)))
312 + return (B_TRUE);
313 + else
314 + return (B_FALSE);
315 +}
316 +
298 317 sbd_status_t
299 318 sbd_pgr_meta_load(sbd_lu_t *slu)
300 319 {
301 320 sbd_pgr_t *pgr = slu->sl_pgr;
302 321 sbd_pgr_info_t *spi = NULL;
303 322 sbd_pgr_key_t *key, *last_key = NULL;
304 323 sbd_pgr_key_info_t *spi_key;
305 324 sbd_status_t ret = SBD_SUCCESS;
306 325 scsi_devid_desc_t *lpt;
307 326 uint8_t *ptr, *keyoffset, *endoffset;
308 327 uint32_t i, sz;
309 328
310 329 ret = sbd_read_meta_section(slu, (sm_section_hdr_t **)&spi,
311 330 SMS_ID_PGR_INFO);
312 331 if (ret != SBD_SUCCESS) {
313 332 /* No PGR section found, means volume made before PGR support */
314 333 if (ret == SBD_NOT_FOUND) {
315 334 /* So just create a default PGR section */
|
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
316 335 ret = sbd_pgr_meta_init(slu);
317 336 }
318 337 return (ret);
319 338 }
320 339
321 340 if (spi->pgr_data_order != SMS_DATA_ORDER) {
322 341 sbd_swap_pgr_info(spi);
323 342 }
324 343
325 344 pgr->pgr_flags = spi->pgr_flags;
326 - if (pgr->pgr_flags & SBD_PGR_APTPL) {
345 + /*
346 + * We reload APTPL reservations when:
347 + * 1. Global override is enabled
348 + * 2. APTPL was explicitly asserted in the PERSISTENT RESERVE OUT CDB
349 + */
350 + if (stmf_is_pgr_aptpl_always() || (pgr->pgr_flags & SBD_PGR_APTPL)) {
327 351 pgr->pgr_rsv_type = spi->pgr_rsv_type;
328 352 pgr->pgr_rsv_scope = spi->pgr_rsv_scope;
329 353 } else {
330 354 PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
331 355 }
332 356
333 357 PGR_CLEAR_FLAG(slu->sl_pgr->pgr_flags, SBD_PGR_ALL_KEYS_HAS_IT);
334 358
335 359 endoffset = (uint8_t *)spi;
336 360 endoffset += spi->pgr_sms_header.sms_size;
337 361 keyoffset = (uint8_t *)(spi + 1);
338 362 for (i = 1; i <= spi->pgr_numkeys; i++) {
339 363
340 364 spi_key = (sbd_pgr_key_info_t *)keyoffset;
341 365 if (spi->pgr_data_order != SMS_DATA_ORDER) {
342 366 sbd_swap_pgrkey_info(spi_key);
343 367 }
344 368
345 369 /* Calculate the size and next offset */
346 370 sz = ALIGNED_TO_8BYTE_BOUNDARY(sizeof (sbd_pgr_key_info_t) - 1 +
347 371 spi_key->pgr_key_lpt_len + spi_key->pgr_key_rpt_len);
348 372 keyoffset += sz;
349 373
350 374 /* Validate the key fields */
351 375 if (spi_key->pgr_key_rpt_len == 0 || endoffset < keyoffset ||
352 376 (spi_key->pgr_key_lpt_len == 0 &&
353 377 !(spi_key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT))) {
354 378 ret = SBD_META_CORRUPTED;
355 379 goto sbd_pgr_meta_load_failed;
356 380 }
357 381
358 382 lpt = (scsi_devid_desc_t *)spi_key->pgr_key_it;
359 383 ptr = (uint8_t *)spi_key->pgr_key_it + spi_key->pgr_key_lpt_len;
360 384
361 385 if (spi_key->pgr_key_flags & SBD_PGR_KEY_TPT_ID_FLAG) {
362 386 uint16_t tpd_len = 0;
363 387
364 388 if (!stmf_scsilib_tptid_validate(
365 389 (scsi_transport_id_t *)ptr,
366 390 spi_key->pgr_key_rpt_len, &tpd_len)) {
367 391 ret = SBD_META_CORRUPTED;
368 392 goto sbd_pgr_meta_load_failed;
369 393 }
370 394 if (tpd_len != spi_key->pgr_key_rpt_len) {
371 395 ret = SBD_META_CORRUPTED;
372 396 goto sbd_pgr_meta_load_failed;
373 397 }
374 398 key = sbd_pgr_key_alloc(lpt, (scsi_transport_id_t *)ptr,
375 399 spi_key->pgr_key_lpt_len, spi_key->pgr_key_rpt_len);
376 400 } else {
377 401 stmf_remote_port_t *rpt = NULL;
378 402
379 403 /*
380 404 * This block is executed only if the metadata was
381 405 * stored before the implementation of Transport ID
382 406 * support.
383 407 */
384 408 rpt = stmf_scsilib_devid_to_remote_port(
385 409 (scsi_devid_desc_t *)ptr);
386 410 if (rpt == NULL) {
387 411 ret = SBD_META_CORRUPTED;
388 412 goto sbd_pgr_meta_load_failed;
389 413 }
390 414 key = sbd_pgr_key_alloc(lpt, rpt->rport_tptid,
391 415 spi_key->pgr_key_lpt_len, rpt->rport_tptid_sz);
392 416 stmf_remote_port_free(rpt);
393 417 }
394 418
395 419 key->pgr_key = spi_key->pgr_key;
396 420 key->pgr_key_flags = spi_key->pgr_key_flags;
397 421 key->pgr_key_prev = last_key;
398 422
399 423 if (last_key) {
400 424 last_key->pgr_key_next = key;
401 425 } else {
402 426 pgr->pgr_keylist = key;
403 427 }
404 428 last_key = key;
405 429
|
↓ open down ↓ |
69 lines elided |
↑ open up ↑ |
406 430 if ((pgr->pgr_flags & SBD_PGR_RSVD_ONE) &&
407 431 (i == spi->pgr_rsvholder_indx)) {
408 432 pgr->pgr_rsvholder = key;
409 433 }
410 434 }
411 435
412 436 kmem_free(spi, spi->pgr_sms_header.sms_size);
413 437 return (ret);
414 438
415 439 sbd_pgr_meta_load_failed:
440 + /* CSTYLED */
416 441 {
417 442 char *lun_name = sbd_get_devid_string(slu);
418 443 sbd_pgr_keylist_dealloc(slu);
419 444 kmem_free(spi, spi->pgr_sms_header.sms_size);
420 445 cmn_err(CE_WARN, "sbd_pgr_meta_load: Failed to load PGR meta data "
421 446 "for lun %s.", lun_name);
422 447 kmem_free(lun_name, strlen(lun_name) + 1);
423 448 return (ret);
424 449 }
425 450 }
426 451
427 452 sbd_status_t
428 453 sbd_pgr_meta_write(sbd_lu_t *slu)
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
429 454 {
430 455 sbd_pgr_key_t *key;
431 456 sbd_pgr_info_t *spi;
432 457 sbd_pgr_key_info_t *spi_key;
433 458 sbd_pgr_t *pgr = slu->sl_pgr;
434 459 sbd_status_t ret = SBD_SUCCESS;
435 460 uint32_t sz, totalsz;
436 461
437 462 /* Calculate total pgr meta section size needed */
438 463 sz = sizeof (sbd_pgr_info_t);
439 - if (pgr->pgr_flags & SBD_PGR_APTPL) {
464 + if ((pgr->pgr_flags & SBD_PGR_APTPL) || stmf_is_pgr_aptpl_always()) {
440 465 key = pgr->pgr_keylist;
441 466 while (key != NULL) {
442 467 sz = ALIGNED_TO_8BYTE_BOUNDARY(sz +
443 468 sizeof (sbd_pgr_key_info_t) - 1 +
444 469 key->pgr_key_lpt_len + key->pgr_key_rpt_len);
445 470 key = key->pgr_key_next;
446 471 }
447 472 }
448 473 totalsz = sz;
449 474
450 475 spi = (sbd_pgr_info_t *)kmem_zalloc(totalsz, KM_SLEEP);
|
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
451 476 spi->pgr_flags = pgr->pgr_flags;
452 477 spi->pgr_rsv_type = pgr->pgr_rsv_type;
453 478 spi->pgr_rsv_scope = pgr->pgr_rsv_scope;
454 479 spi->pgr_data_order = SMS_DATA_ORDER;
455 480 spi->pgr_numkeys = 0;
456 481
457 482 spi->pgr_sms_header.sms_size = totalsz;
458 483 spi->pgr_sms_header.sms_id = SMS_ID_PGR_INFO;
459 484 spi->pgr_sms_header.sms_data_order = SMS_DATA_ORDER;
460 485
461 - if (pgr->pgr_flags & SBD_PGR_APTPL) {
486 + if ((pgr->pgr_flags & SBD_PGR_APTPL) || stmf_is_pgr_aptpl_always()) {
462 487 uint8_t *ptr;
463 488 key = pgr->pgr_keylist;
464 489 sz = sizeof (sbd_pgr_info_t);
465 490 while (key != NULL) {
466 491 spi_key = (sbd_pgr_key_info_t *)((uint8_t *)spi + sz);
467 492 spi_key->pgr_key = key->pgr_key;
468 493 spi_key->pgr_key_flags = key->pgr_key_flags;
469 494 spi_key->pgr_key_lpt_len = key->pgr_key_lpt_len;
470 495 spi_key->pgr_key_rpt_len = key->pgr_key_rpt_len;
471 496 ptr = spi_key->pgr_key_it;
472 497 bcopy(key->pgr_key_lpt_id, ptr, key->pgr_key_lpt_len);
473 498 ptr += key->pgr_key_lpt_len;
474 499 bcopy(key->pgr_key_rpt_id, ptr, key->pgr_key_rpt_len);
475 500
476 501 spi->pgr_numkeys++;
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
477 502 if (key == pgr->pgr_rsvholder) {
478 503 spi->pgr_rsvholder_indx = spi->pgr_numkeys;
479 504 }
480 505
481 506 sz = ALIGNED_TO_8BYTE_BOUNDARY(sz +
482 507 sizeof (sbd_pgr_key_info_t) - 1 +
483 508 key->pgr_key_lpt_len + key->pgr_key_rpt_len);
484 509 key = key->pgr_key_next;
485 510 }
486 511 }
487 -
512 + rw_downgrade(&pgr->pgr_lock);
488 513 ret = sbd_write_meta_section(slu, (sm_section_hdr_t *)spi);
514 + if (!rw_tryupgrade(&pgr->pgr_lock)) {
515 + rw_exit(&pgr->pgr_lock);
516 + rw_enter(&pgr->pgr_lock, RW_WRITER);
517 + }
489 518 kmem_free(spi, totalsz);
490 519 if (ret != SBD_SUCCESS) {
491 520 sbd_pgr_key_t *tmp_list;
492 521 tmp_list = pgr->pgr_keylist;
493 522 pgr->pgr_keylist = NULL;
494 523 if (sbd_pgr_meta_load(slu) != SBD_SUCCESS) {
495 524 char *lun_name = sbd_get_devid_string(slu);
496 525 cmn_err(CE_WARN, "sbd_pgr_meta_write: Failed to revert "
497 526 "back to existing PGR state after meta write "
498 527 "failure, may cause PGR inconsistancy for lun %s.",
499 528 lun_name);
500 529 kmem_free(lun_name, strlen(lun_name) + 1);
501 530 pgr->pgr_keylist = tmp_list;
502 531 } else {
503 532 key = pgr->pgr_keylist;
504 533 pgr->pgr_keylist = tmp_list;
505 534 sbd_pgr_set_pgr_check_flag(slu, B_TRUE);
506 535 sbd_pgr_keylist_dealloc(slu);
507 536 pgr->pgr_keylist = key;
508 537 }
509 538
510 539 }
511 540 return (ret);
512 541 }
513 542
514 543 static sbd_pgr_key_t *
515 544 sbd_pgr_key_alloc(scsi_devid_desc_t *lptid, scsi_transport_id_t *rptid,
516 545 int16_t lpt_len, int16_t rpt_len)
517 546 {
518 547 sbd_pgr_key_t *key;
519 548
520 549 key = (sbd_pgr_key_t *)kmem_zalloc(sizeof (sbd_pgr_key_t), KM_SLEEP);
521 550
522 551 if (lptid && lpt_len >= sizeof (scsi_devid_desc_t)) {
523 552 key->pgr_key_lpt_len = lpt_len;
524 553 key->pgr_key_lpt_id = (scsi_devid_desc_t *)kmem_zalloc(
525 554 lpt_len, KM_SLEEP);
526 555 bcopy(lptid, key->pgr_key_lpt_id, lpt_len);
527 556 }
528 557
529 558 if (rptid && rpt_len >= sizeof (scsi_transport_id_t)) {
530 559 key->pgr_key_flags |= SBD_PGR_KEY_TPT_ID_FLAG;
531 560 key->pgr_key_rpt_len = rpt_len;
532 561 key->pgr_key_rpt_id = (scsi_transport_id_t *)kmem_zalloc(
533 562 rpt_len, KM_SLEEP);
534 563 bcopy(rptid, key->pgr_key_rpt_id, rpt_len);
535 564 }
536 565
537 566 return (key);
538 567 }
539 568
540 569 static void
541 570 sbd_pgr_key_free(sbd_pgr_key_t *key)
542 571 {
543 572 if (key->pgr_key_lpt_id) {
544 573 kmem_free(key->pgr_key_lpt_id, key->pgr_key_lpt_len);
545 574 }
546 575 if (key->pgr_key_rpt_id) {
547 576 kmem_free(key->pgr_key_rpt_id, key->pgr_key_rpt_len);
548 577 }
549 578 kmem_free(key, sizeof (sbd_pgr_key_t));
550 579 }
551 580
552 581 void
553 582 sbd_pgr_keylist_dealloc(sbd_lu_t *slu)
554 583 {
555 584 sbd_pgr_t *pgr = slu->sl_pgr;
556 585 sbd_it_data_t *it;
557 586 sbd_pgr_key_t *key;
558 587
559 588 mutex_enter(&slu->sl_lock);
560 589 for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
561 590 it->pgr_key_ptr = NULL;
562 591 }
563 592 mutex_exit(&slu->sl_lock);
564 593
565 594 while (pgr->pgr_keylist != NULL) {
566 595 key = pgr->pgr_keylist;
567 596 pgr->pgr_keylist = key->pgr_key_next;
568 597 sbd_pgr_key_free(key);
569 598 }
570 599 }
|
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
571 600
572 601 /*
573 602 * Reset and clear the keys, Can be used in the case of Lun Reset
574 603 */
575 604 void
576 605 sbd_pgr_reset(sbd_lu_t *slu)
577 606 {
578 607 sbd_pgr_t *pgr = slu->sl_pgr;
579 608
580 609 rw_enter(&pgr->pgr_lock, RW_WRITER);
581 - if (!(pgr->pgr_flags & SBD_PGR_APTPL)) {
610 + if (!(pgr->pgr_flags & SBD_PGR_APTPL) &&
611 + stmf_is_pgr_aptpl_always() == B_FALSE) {
582 612 sbd_pgr_keylist_dealloc(slu);
583 613 pgr->pgr_PRgeneration = 0;
584 614 pgr->pgr_rsvholder = NULL;
585 615 pgr->pgr_rsv_type = 0;
586 616 pgr->pgr_flags = 0;
587 617 }
588 618 rw_exit(&pgr->pgr_lock);
589 619 }
590 620
591 621 static void
592 622 sbd_pgr_remove_key(sbd_lu_t *slu, sbd_pgr_key_t *key)
593 623 {
594 624 sbd_pgr_t *pgr = slu->sl_pgr;
595 625 sbd_it_data_t *it;
596 626
597 627 ASSERT(key);
598 628
599 629 mutex_enter(&slu->sl_lock);
600 630 if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
601 631 for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
602 632 if (it->pgr_key_ptr == key)
603 633 it->pgr_key_ptr = NULL;
604 634 }
605 635 } else {
606 636 if (key->pgr_key_it) {
607 637 key->pgr_key_it->pgr_key_ptr = NULL;
608 638 }
609 639 }
610 640 mutex_exit(&slu->sl_lock);
611 641
612 642 if (key->pgr_key_next) {
613 643 key->pgr_key_next->pgr_key_prev = key->pgr_key_prev;
614 644 }
615 645 if (key->pgr_key_prev) {
616 646 key->pgr_key_prev->pgr_key_next = key->pgr_key_next;
617 647 } else {
618 648 pgr->pgr_keylist = key->pgr_key_next;
619 649 }
620 650
621 651 sbd_pgr_key_free(key);
622 652 }
623 653
624 654 /*
625 655 * Remove keys depends on boolean variable "match"
626 656 * match = B_TRUE ==> Remove all keys which matches the given svc_key,
627 657 * except for IT equal to given "my_it".
628 658 * match = B_FALSE ==> Remove all keys which does not matches the svc_key,
629 659 * except for IT equal to given "my_it"
630 660 */
631 661 static uint32_t
632 662 sbd_pgr_remove_keys(sbd_lu_t *slu, sbd_it_data_t *my_it, sbd_pgr_key_t *my_key,
633 663 uint64_t svc_key, boolean_t match)
634 664 {
635 665 sbd_pgr_t *pgr = slu->sl_pgr;
636 666 sbd_it_data_t *it;
637 667 sbd_pgr_key_t *nextkey, *key = pgr->pgr_keylist;
638 668 uint32_t count = 0;
639 669
640 670 while (key) {
641 671
642 672 nextkey = key->pgr_key_next;
643 673 if (match == B_TRUE && key->pgr_key == svc_key ||
644 674 match == B_FALSE && key->pgr_key != svc_key) {
645 675 /*
646 676 * If the key is registered by current IT keep it,
647 677 * but just remove pgr pointers from other ITs
648 678 */
649 679 if (key == my_key) {
650 680 mutex_enter(&slu->sl_lock);
651 681 for (it = slu->sl_it_list; it != NULL;
652 682 it = it->sbd_it_next) {
653 683 if (it->pgr_key_ptr == key &&
654 684 it != my_it)
655 685 it->pgr_key_ptr = NULL;
656 686 }
657 687 mutex_exit(&slu->sl_lock);
658 688 } else {
659 689 sbd_pgr_remove_key(slu, key);
660 690 }
661 691 count++;
662 692 }
663 693 key = nextkey;
664 694 }
665 695 return (count);
666 696 }
667 697
668 698 static void
669 699 sbd_pgr_set_ua_conditions(sbd_lu_t *slu, sbd_it_data_t *my_it, uint8_t ua)
670 700 {
671 701 sbd_it_data_t *it;
672 702
673 703 mutex_enter(&slu->sl_lock);
674 704 for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
675 705 if (it == my_it)
676 706 continue;
677 707 it->sbd_it_ua_conditions |= ua;
678 708 }
679 709 mutex_exit(&slu->sl_lock);
680 710 }
681 711
682 712 /*
683 713 * Set the SBD_IT_PGR_CHECK_FLAG depends on variable "registered". See Below.
684 714 *
685 715 * If
686 716 * registered is B_TRUE => Set PGR_CHECK_FLAG on all registered IT nexus
687 717 * registered is B_FALSE => Set PGR_CHECK_FLAG on all unregistered IT nexus
688 718 */
689 719 static void
690 720 sbd_pgr_set_pgr_check_flag(sbd_lu_t *slu, boolean_t registered)
691 721 {
692 722 sbd_it_data_t *it;
693 723
694 724 PGR_CLEAR_FLAG(slu->sl_pgr->pgr_flags, SBD_PGR_ALL_KEYS_HAS_IT);
695 725 mutex_enter(&slu->sl_lock);
696 726 for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
697 727 if (it->pgr_key_ptr) {
698 728 if (registered == B_TRUE) {
699 729 it->sbd_it_flags |= SBD_IT_PGR_CHECK_FLAG;
700 730 }
701 731 } else {
702 732 if (registered == B_FALSE)
703 733 it->sbd_it_flags |= SBD_IT_PGR_CHECK_FLAG;
704 734 }
705 735 }
706 736 mutex_exit(&slu->sl_lock);
707 737 }
708 738
709 739 static boolean_t
710 740 sbd_pgr_key_compare(sbd_pgr_key_t *key, scsi_devid_desc_t *lpt,
711 741 stmf_remote_port_t *rpt)
712 742 {
713 743 scsi_devid_desc_t *id;
714 744
715 745 if (!stmf_scsilib_tptid_compare(rpt->rport_tptid, key->pgr_key_rpt_id))
716 746 return (B_FALSE);
717 747
718 748 /*
719 749 * You can skip target port name comparison if ALL_TG_PT flag
720 750 * is set for this key;
721 751 */
722 752 if (!(key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) && lpt) {
723 753 id = key->pgr_key_lpt_id;
724 754 if ((lpt->ident_length != id->ident_length) ||
725 755 (memcmp(id->ident, lpt->ident, id->ident_length) != 0)) {
726 756 return (B_FALSE);
727 757 }
728 758 }
729 759 return (B_TRUE);
730 760 }
731 761
732 762
733 763 sbd_pgr_key_t *
734 764 sbd_pgr_key_registered(sbd_pgr_t *pgr, scsi_devid_desc_t *lpt,
735 765 stmf_remote_port_t *rpt)
736 766 {
737 767 sbd_pgr_key_t *key;
738 768
739 769 for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next) {
740 770 if (sbd_pgr_key_compare(key, lpt, rpt) == B_TRUE) {
741 771 return (key);
742 772 }
743 773 }
744 774 return (NULL);
745 775 }
746 776
747 777 void
748 778 sbd_pgr_initialize_it(scsi_task_t *task, sbd_it_data_t *it)
749 779 {
750 780 sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
751 781 stmf_scsi_session_t *ses = task->task_session;
752 782 sbd_pgr_t *pgr = slu->sl_pgr;
753 783 sbd_pgr_key_t *key;
754 784 scsi_devid_desc_t *lpt, *id;
755 785 stmf_remote_port_t *rpt;
756 786
757 787 if (pgr->pgr_flags & SBD_PGR_ALL_KEYS_HAS_IT)
758 788 return;
759 789
760 790 rpt = ses->ss_rport;
761 791 lpt = ses->ss_lport->lport_id;
762 792
763 793 rw_enter(&pgr->pgr_lock, RW_WRITER);
764 794 PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_ALL_KEYS_HAS_IT);
765 795 for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next) {
766 796
767 797 if ((!(key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT)) &&
768 798 key->pgr_key_it != NULL)
769 799 continue;
770 800 /*
771 801 * SBD_PGR_ALL_KEYS_HAS_IT is set only if no single key
772 802 * in the list has SBD_PGR_KEY_ALL_TG_PT flag set and
773 803 * pgr_key_it all keys points to some IT
774 804 */
775 805 PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_ALL_KEYS_HAS_IT);
776 806
777 807 /* Check if key matches with given lpt rpt combination */
778 808 if (sbd_pgr_key_compare(key, lpt, rpt) == B_FALSE)
779 809 continue;
780 810
781 811 /* IT nexus devid information matches with this key */
782 812 if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
783 813 /*
784 814 * If ALL_TG_PT is set, pgr_key_it will point to NULL,
785 815 * unless pgr->pgr_rsvholder pointing to this key.
786 816 * In that case, pgr_key_it should point to the IT
787 817 * which initiated that reservation.
788 818 */
789 819 if (pgr->pgr_rsvholder == key) {
790 820 id = key->pgr_key_lpt_id;
791 821 if (lpt->ident_length == id->ident_length) {
792 822 if (memcmp(id->ident, lpt->ident,
793 823 id->ident_length) == 0)
794 824 key->pgr_key_it = it;
795 825 }
796 826 }
797 827
798 828 } else {
799 829 key->pgr_key_it = it;
800 830 }
801 831
802 832 mutex_enter(&slu->sl_lock);
803 833 it->pgr_key_ptr = key;
804 834 mutex_exit(&slu->sl_lock);
|
↓ open down ↓ |
213 lines elided |
↑ open up ↑ |
805 835 rw_exit(&pgr->pgr_lock);
806 836 return;
807 837 }
808 838 rw_exit(&pgr->pgr_lock);
809 839 }
810 840
811 841 /*
812 842 * Check for any PGR Reservation conflict. return 0 if access allowed
813 843 */
814 844 int
815 -sbd_pgr_reservation_conflict(scsi_task_t *task)
845 +sbd_pgr_reservation_conflict(scsi_task_t *task, sbd_lu_t *slu)
816 846 {
817 - sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
818 847 sbd_pgr_t *pgr = slu->sl_pgr;
819 848 sbd_it_data_t *it = (sbd_it_data_t *)task->task_lu_itl_handle;
820 849
821 850 /* If Registered */
822 851 if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS && it->pgr_key_ptr)
823 852 return (0);
824 853
825 854 /* If you are registered */
826 855 if (pgr->pgr_flags & SBD_PGR_RSVD_ONE) {
827 856 rw_enter(&pgr->pgr_lock, RW_READER);
828 857
829 858 /*
830 859 * Note: it->pgr_key_ptr is protected by sl_lock. Also,
831 860 * it is expected to change its value only with pgr_lock
832 861 * held. Hence we are safe to read its value without
833 862 * grabbing sl_lock. But make sure that the value used is
834 863 * not from registers by using "volatile" keyword.
835 864 * Since this funtion is in performance path, we may want
836 865 * to avoid grabbing sl_lock.
837 866 */
838 867 if ((volatile sbd_pgr_key_t *)it->pgr_key_ptr) {
839 868 /* If you are the reservation holder */
840 869 if (pgr->pgr_rsvholder == it->pgr_key_ptr &&
841 870 it->pgr_key_ptr->pgr_key_it == it) {
842 871 rw_exit(&pgr->pgr_lock);
843 872 return (0);
844 873 }
845 874
846 875 /* If reserve type is not EX_AC */
847 876 if (pgr->pgr_rsv_type != PGR_TYPE_EX_AC) {
848 877 /* If reserve type is WR_EX allow read */
849 878 if (pgr->pgr_rsv_type == PGR_TYPE_WR_EX) {
850 879 if (PGR_READ_POSSIBLE_CMDS(
851 880 task->task_cdb[0])) {
852 881 rw_exit(&pgr->pgr_lock);
853 882 return (0);
854 883 }
855 884 /* For all other reserve types allow access */
856 885 } else {
857 886 rw_exit(&pgr->pgr_lock);
858 887 return (0);
859 888 }
860 889 }
861 890
862 891 /* If registered, allow these commands */
863 892 if (PGR_REGISTERED_POSSIBLE_CMDS(task->task_cdb)) {
864 893 rw_exit(&pgr->pgr_lock);
865 894 return (0);
866 895 }
867 896 }
868 897 rw_exit(&pgr->pgr_lock);
869 898 }
870 899
871 900 /* For any case, allow these commands */
872 901 if (PGR_CONFLICT_FREE_CMDS(task->task_cdb)) {
873 902 return (0);
874 903 }
875 904
876 905 /* Give read access if reservation type WR_EX for registrants */
877 906 if (pgr->pgr_rsv_type == PGR_TYPE_WR_EX_RO ||
878 907 pgr->pgr_rsv_type == PGR_TYPE_WR_EX_AR) {
879 908 if (PGR_READ_POSSIBLE_CMDS(task->task_cdb[0]))
880 909 return (0);
881 910 }
882 911
883 912 /* If you reached here, No access for you */
884 913 return (1);
885 914 }
886 915
887 916 void
888 917 sbd_handle_pgr_in_cmd(scsi_task_t *task, stmf_data_buf_t *initial_dbuf)
889 918 {
890 919
891 920 sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
892 921 sbd_pgr_t *pgr = slu->sl_pgr;
893 922 scsi_cdb_prin_t *pr_in;
894 923
895 924 ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
896 925
897 926 pr_in = (scsi_cdb_prin_t *)task->task_cdb;
898 927
899 928 rw_enter(&pgr->pgr_lock, RW_READER);
900 929 switch (pr_in->action) {
901 930 case PR_IN_READ_KEYS:
902 931 sbd_pgr_in_read_keys(task, initial_dbuf);
903 932 break;
904 933 case PR_IN_READ_RESERVATION:
905 934 sbd_pgr_in_read_reservation(task, initial_dbuf);
906 935 break;
907 936 case PR_IN_REPORT_CAPABILITIES:
908 937 sbd_pgr_in_report_capabilities(task, initial_dbuf);
909 938 break;
910 939 case PR_IN_READ_FULL_STATUS:
911 940 sbd_pgr_in_read_full_status(task, initial_dbuf);
912 941 break;
913 942 default :
914 943 stmf_scsilib_send_status(task, STATUS_CHECK,
915 944 STMF_SAA_INVALID_FIELD_IN_CDB);
916 945 break;
917 946 }
918 947 rw_exit(&pgr->pgr_lock);
919 948 }
920 949
921 950 void
922 951 sbd_handle_pgr_out_cmd(scsi_task_t *task, stmf_data_buf_t *initial_dbuf)
923 952 {
924 953
925 954 scsi_cdb_prout_t *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
926 955 uint32_t param_len;
927 956
928 957 ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_OUT);
929 958
930 959 switch (pr_out->action) {
931 960 case PR_OUT_REGISTER:
932 961 case PR_OUT_RESERVE:
933 962 case PR_OUT_RELEASE:
934 963 case PR_OUT_CLEAR:
935 964 case PR_OUT_PREEMPT:
936 965 case PR_OUT_PREEMPT_ABORT:
937 966 case PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY:
938 967 case PR_OUT_REGISTER_MOVE:
939 968 param_len = READ_SCSI32(pr_out->param_len, uint32_t);
940 969 if (param_len < MAX_PGR_PARAM_LIST_LENGTH &&
941 970 param_len > 0) {
942 971 sbd_handle_short_write_transfers(task,
943 972 initial_dbuf, param_len);
944 973 } else {
945 974 stmf_scsilib_send_status(task, STATUS_CHECK,
946 975 STMF_SAA_PARAM_LIST_LENGTH_ERROR);
947 976 }
948 977 break;
949 978 default :
950 979 stmf_scsilib_send_status(task, STATUS_CHECK,
951 980 STMF_SAA_INVALID_FIELD_IN_CDB);
952 981 break;
953 982 }
954 983 }
955 984
956 985 void
957 986 sbd_handle_pgr_out_data(scsi_task_t *task, stmf_data_buf_t *dbuf)
958 987 {
959 988 sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
960 989 scsi_cdb_prout_t *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
961 990 sbd_it_data_t *it = task->task_lu_itl_handle;
962 991 sbd_pgr_t *pgr = slu->sl_pgr;
963 992 sbd_pgr_key_t *key;
964 993 scsi_prout_plist_t *plist;
965 994 uint64_t rsv_key;
966 995 uint32_t buflen;
967 996 uint8_t *buf;
968 997
969 998 ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_OUT);
970 999
971 1000 if (dbuf == NULL || dbuf->db_data_size < 24) {
972 1001 stmf_scsilib_send_status(task, STATUS_CHECK,
973 1002 STMF_SAA_PARAM_LIST_LENGTH_ERROR);
974 1003 return;
975 1004 }
976 1005
977 1006 buf = dbuf->db_sglist[0].seg_addr;
978 1007 buflen = dbuf->db_data_size;
979 1008 plist = (scsi_prout_plist_t *)buf;
980 1009
981 1010 /* SPC3 - 6.12.1 */
982 1011 if (pr_out->action != PR_OUT_REGISTER_MOVE && buflen != 24) {
983 1012 if ((pr_out->action !=
984 1013 PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY &&
985 1014 pr_out->action != PR_OUT_REGISTER) ||
986 1015 plist->spec_i_pt == 0) {
987 1016 stmf_scsilib_send_status(task, STATUS_CHECK,
988 1017 STMF_SAA_PARAM_LIST_LENGTH_ERROR);
989 1018 return;
990 1019 }
991 1020 }
992 1021
993 1022 /*
994 1023 * Common Reservation Conflict Checks
995 1024 *
996 1025 * It is okey to handle REGISTER_MOVE with same plist here,
997 1026 * because we are only accessing reservation key feild.
998 1027 */
999 1028 rw_enter(&pgr->pgr_lock, RW_WRITER);
1000 1029
1001 1030 /*
1002 1031 * Currently it is not mandatory to have volatile keyword here,
1003 1032 * because, it->pgr_key_ptr is not accessed yet. But still
1004 1033 * keeping it to safe gaurd against any possible future changes.
1005 1034 */
1006 1035 key = (sbd_pgr_key_t *)((volatile sbd_pgr_key_t *)it->pgr_key_ptr);
1007 1036 if (pr_out->action != PR_OUT_REGISTER &&
1008 1037 pr_out->action != PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY) {
1009 1038 /* if IT is not yet registered send conflict status */
1010 1039 if (key == NULL) {
1011 1040 if (pr_out->action == PR_OUT_REGISTER_MOVE &&
1012 1041 SBD_PGR_RSVD_NONE(pgr)) {
1013 1042 stmf_scsilib_send_status(task, STATUS_CHECK,
1014 1043 STMF_SAA_INVALID_FIELD_IN_CDB);
1015 1044
1016 1045 } else {
1017 1046 stmf_scsilib_send_status(task,
1018 1047 STATUS_RESERVATION_CONFLICT, 0);
1019 1048 }
1020 1049 rw_exit(&pgr->pgr_lock);
1021 1050 return;
1022 1051 }
1023 1052
1024 1053 /* Given reservation key should matches with registered key */
1025 1054 rsv_key = READ_SCSI64(plist->reservation_key, uint64_t);
1026 1055 if (key->pgr_key != rsv_key) {
1027 1056 stmf_scsilib_send_status(task,
1028 1057 STATUS_RESERVATION_CONFLICT, 0);
1029 1058 rw_exit(&pgr->pgr_lock);
1030 1059 return;
1031 1060 }
1032 1061 }
1033 1062
1034 1063 switch (pr_out->action) {
1035 1064 case PR_OUT_REGISTER:
1036 1065 case PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY:
1037 1066 sbd_pgr_out_register(task, dbuf);
1038 1067 break;
1039 1068 case PR_OUT_REGISTER_MOVE:
1040 1069 sbd_pgr_out_register_and_move(task, dbuf);
1041 1070 break;
1042 1071 case PR_OUT_RESERVE:
1043 1072 sbd_pgr_out_reserve(task);
1044 1073 break;
1045 1074 case PR_OUT_RELEASE:
1046 1075 sbd_pgr_out_release(task);
1047 1076 break;
1048 1077 case PR_OUT_CLEAR:
1049 1078 sbd_pgr_out_clear(task);
1050 1079 break;
1051 1080 case PR_OUT_PREEMPT:
1052 1081 case PR_OUT_PREEMPT_ABORT:
1053 1082 sbd_pgr_out_preempt(task, dbuf);
1054 1083 break;
1055 1084 default :
1056 1085 stmf_scsilib_send_status(task, STATUS_CHECK,
1057 1086 STMF_SAA_INVALID_FIELD_IN_CDB);
1058 1087 break;
1059 1088 }
1060 1089 rw_exit(&pgr->pgr_lock);
1061 1090 }
1062 1091
1063 1092 static void
1064 1093 sbd_pgr_in_read_keys(scsi_task_t *task, stmf_data_buf_t *initial_dbuf)
1065 1094 {
1066 1095 sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
1067 1096 sbd_pgr_t *pgr = slu->sl_pgr;
1068 1097 sbd_pgr_key_t *key;
1069 1098 scsi_prin_readrsrv_t *buf;
1070 1099 uint32_t buf_size, cdb_len, numkeys = 0;
1071 1100 uint64_t *reg_key;
1072 1101
1073 1102 ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
1074 1103
1075 1104 cdb_len = READ_SCSI16(&task->task_cdb[7], uint16_t);
1076 1105 for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next)
1077 1106 ++numkeys;
1078 1107 buf_size = 8 + numkeys * 8; /* minimum 8 bytes */
1079 1108 buf = kmem_zalloc(buf_size, KM_SLEEP);
1080 1109 SCSI_WRITE32(buf->PRgeneration, pgr->pgr_PRgeneration);
1081 1110 SCSI_WRITE32(buf->add_len, numkeys * 8);
1082 1111
1083 1112 reg_key = (uint64_t *)&buf->key_list;
1084 1113 for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next) {
1085 1114 SCSI_WRITE64(reg_key, key->pgr_key);
1086 1115 reg_key++;
1087 1116 }
1088 1117 sbd_handle_short_read_transfers(task, initial_dbuf, (uint8_t *)buf,
1089 1118 cdb_len, buf_size);
1090 1119 kmem_free(buf, buf_size);
1091 1120 }
1092 1121
1093 1122 static void
1094 1123 sbd_pgr_in_read_reservation(scsi_task_t *task, stmf_data_buf_t *initial_dbuf)
1095 1124 {
1096 1125 sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
1097 1126 sbd_pgr_t *pgr = slu->sl_pgr;
1098 1127 scsi_prin_readrsrv_t *buf;
1099 1128 uint32_t cdb_len, buf_len, buf_size = 24;
1100 1129
1101 1130 ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
1102 1131
1103 1132 cdb_len = READ_SCSI16(&task->task_cdb[7], uint16_t);
1104 1133 buf = kmem_zalloc(buf_size, KM_SLEEP); /* fixed size cdb, 24 bytes */
1105 1134 SCSI_WRITE32(buf->PRgeneration, pgr->pgr_PRgeneration);
1106 1135
1107 1136 if (SBD_PGR_RSVD_NONE(pgr)) {
1108 1137 SCSI_WRITE32(buf->add_len, 0);
1109 1138 buf_len = 8;
1110 1139 } else {
1111 1140 if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS) {
1112 1141 SCSI_WRITE64(
1113 1142 buf->key_list.res_key_list[0].reservation_key, 0);
1114 1143 } else {
1115 1144 SCSI_WRITE64(
1116 1145 buf->key_list.res_key_list[0].reservation_key,
1117 1146 pgr->pgr_rsvholder->pgr_key);
1118 1147 }
1119 1148 buf->key_list.res_key_list[0].type = pgr->pgr_rsv_type;
1120 1149 buf->key_list.res_key_list[0].scope = pgr->pgr_rsv_scope;
1121 1150 SCSI_WRITE32(buf->add_len, 16);
1122 1151 buf_len = 24;
1123 1152 }
1124 1153
1125 1154 sbd_handle_short_read_transfers(task, initial_dbuf, (uint8_t *)buf,
1126 1155 cdb_len, buf_len);
1127 1156 kmem_free(buf, buf_size);
1128 1157 }
1129 1158
1130 1159 static void
1131 1160 sbd_pgr_in_report_capabilities(scsi_task_t *task,
1132 1161 stmf_data_buf_t *initial_dbuf)
1133 1162 {
1134 1163 sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
1135 1164 sbd_pgr_t *pgr = slu->sl_pgr;
1136 1165 scsi_prin_rpt_cap_t buf;
1137 1166 uint32_t cdb_len;
1138 1167
1139 1168 ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
1140 1169 ASSERT(pgr != NULL);
1141 1170
1142 1171 bzero(&buf, sizeof (buf));
1143 1172 buf.ptpl_c = 1; /* Persist Through Power Loss C */
1144 1173 buf.atp_c = 1; /* All Target Ports Capable */
1145 1174 buf.sip_c = 1; /* Specify Initiator Ports Capable */
1146 1175 buf.crh = 0; /* Supports Reserve/Release exception */
1147 1176 buf.tmv = 1; /* Type Mask Valid */
1148 1177 buf.pr_type.wr_ex = 1; /* Write Exclusve */
1149 1178 buf.pr_type.ex_ac = 1; /* Exclusive Access */
1150 1179 buf.pr_type.wr_ex_ro = 1; /* Write Exclusive Registrants Only */
1151 1180 buf.pr_type.ex_ac_ro = 1; /* Exclusive Access Registrants Only */
1152 1181 buf.pr_type.wr_ex_ar = 1; /* Write Exclusive All Registrants */
1153 1182 buf.pr_type.ex_ac_ar = 1; /* Exclusive Access All Registrants */
1154 1183
1155 1184 /* Persist Though Power Loss Active */
1156 1185 buf.ptpl_a = pgr->pgr_flags & SBD_PGR_APTPL;
1157 1186 SCSI_WRITE16(&buf.length, 8);
1158 1187 cdb_len = READ_SCSI16(&task->task_cdb[7], uint16_t);
1159 1188 sbd_handle_short_read_transfers(task, initial_dbuf, (uint8_t *)&buf,
1160 1189 cdb_len, 8);
1161 1190 }
1162 1191
1163 1192 /* Minimum required size, SPC3 rev23 Table 110 */
1164 1193 #define PGR_IN_READ_FULL_STATUS_MINBUFSZ 8
1165 1194 /* Full Satus Descriptor Fromat size, SPC3 rev23 Table 111 */
1166 1195 #define PGR_IN_READ_FULL_STATUS_DESCFMTSZ 24
1167 1196
1168 1197 static void
1169 1198 sbd_pgr_in_read_full_status(scsi_task_t *task,
1170 1199 stmf_data_buf_t *initial_dbuf)
1171 1200 {
1172 1201 sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
1173 1202 sbd_pgr_t *pgr = slu->sl_pgr;
1174 1203 sbd_pgr_key_t *key;
1175 1204 scsi_prin_status_t *sts;
1176 1205 scsi_prin_full_status_t *buf;
1177 1206 uint32_t i, buf_size, cdb_len;
1178 1207 uint8_t *offset;
1179 1208
1180 1209 ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
1181 1210 ASSERT(pgr != NULL);
1182 1211
1183 1212 /* 4 byte allocation length for CDB, SPC3 rev23, Table 101 */
1184 1213 cdb_len = READ_SCSI16(&task->task_cdb[7], uint16_t);
1185 1214
1186 1215 /* PRgeneration and additional length fields */
1187 1216 buf_size = PGR_IN_READ_FULL_STATUS_MINBUFSZ;
1188 1217 for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next) {
1189 1218 buf_size = buf_size + PGR_IN_READ_FULL_STATUS_DESCFMTSZ +
1190 1219 key->pgr_key_rpt_len;
1191 1220 }
1192 1221
1193 1222 buf = kmem_zalloc(buf_size, KM_SLEEP);
1194 1223 SCSI_WRITE32(buf->PRgeneration, pgr->pgr_PRgeneration);
1195 1224 SCSI_WRITE32(buf->add_len, buf_size - PGR_IN_READ_FULL_STATUS_MINBUFSZ);
1196 1225
1197 1226 offset = (uint8_t *)&buf->full_desc[0];
1198 1227 key = pgr->pgr_keylist;
1199 1228 i = 0;
1200 1229 while (key) {
1201 1230 sts = (scsi_prin_status_t *)offset;
1202 1231 SCSI_WRITE64(sts->reservation_key, key->pgr_key);
1203 1232 if ((pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS) ||
1204 1233 (pgr->pgr_rsvholder && pgr->pgr_rsvholder == key)) {
1205 1234 sts->r_holder = 1;
1206 1235 sts->type = pgr->pgr_rsv_type;
1207 1236 sts->scope = pgr->pgr_rsv_scope;
1208 1237 }
1209 1238
1210 1239 if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
1211 1240 sts->all_tg_pt = 1;
1212 1241 } else {
1213 1242 SCSI_WRITE16(sts->rel_tgt_port_id,
1214 1243 stmf_scsilib_get_lport_rtid(key->pgr_key_lpt_id));
1215 1244 }
1216 1245 SCSI_WRITE32(sts->add_len, key->pgr_key_rpt_len);
1217 1246 offset += PGR_IN_READ_FULL_STATUS_DESCFMTSZ;
1218 1247 (void) memcpy(offset, key->pgr_key_rpt_id,
1219 1248 key->pgr_key_rpt_len);
1220 1249 offset += key->pgr_key_rpt_len;
1221 1250 key = key->pgr_key_next;
1222 1251 ++i;
1223 1252 }
1224 1253 ASSERT(offset <= (uint8_t *)buf + buf_size);
1225 1254
1226 1255 sbd_handle_short_read_transfers(task, initial_dbuf, (uint8_t *)buf,
1227 1256 cdb_len, buf_size);
1228 1257 kmem_free(buf, buf_size);
1229 1258 }
1230 1259
1231 1260 static void
1232 1261 sbd_pgr_out_register(scsi_task_t *task, stmf_data_buf_t *dbuf)
1233 1262 {
1234 1263 sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
1235 1264 sbd_pgr_t *pgr = slu->sl_pgr;
1236 1265 stmf_scsi_session_t *ses = task->task_session;
1237 1266 sbd_it_data_t *it = task->task_lu_itl_handle;
1238 1267 sbd_pgr_key_t *key = it->pgr_key_ptr;
1239 1268 scsi_cdb_prout_t *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
1240 1269 scsi_devid_desc_t *lpt = ses->ss_lport->lport_id;
1241 1270 scsi_prout_plist_t *plist;
1242 1271 stmf_remote_port_t rport;
1243 1272 uint8_t *buf, keyflag;
1244 1273 uint32_t buflen;
1245 1274 uint64_t rsv_key, svc_key;
1246 1275
1247 1276 buf = dbuf->db_sglist[0].seg_addr;
1248 1277 plist = (scsi_prout_plist_t *)buf;
1249 1278 buflen = dbuf->db_data_size;
1250 1279 rsv_key = READ_SCSI64(plist->reservation_key, uint64_t);
1251 1280 svc_key = READ_SCSI64(plist->service_key, uint64_t);
1252 1281
1253 1282 /* Handling already registered IT session */
1254 1283 if (key) {
1255 1284
1256 1285 if (pr_out->action == PR_OUT_REGISTER &&
1257 1286 key->pgr_key != rsv_key) {
1258 1287 stmf_scsilib_send_status(task,
1259 1288 STATUS_RESERVATION_CONFLICT, 0);
1260 1289 return;
1261 1290 }
1262 1291 if (plist->spec_i_pt) {
1263 1292 stmf_scsilib_send_status(task, STATUS_CHECK,
1264 1293 STMF_SAA_INVALID_FIELD_IN_CDB);
1265 1294 return;
1266 1295 }
1267 1296
1268 1297 if (plist->all_tg_pt !=
1269 1298 (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT)) {
1270 1299 stmf_scsilib_send_status(task, STATUS_CHECK,
1271 1300 STMF_SAA_INVALID_FIELD_IN_CDB);
1272 1301 return;
1273 1302 }
1274 1303
1275 1304 if (svc_key == 0) {
1276 1305 sbd_pgr_do_unregister(slu, it, key);
1277 1306 } else {
1278 1307 key->pgr_key = svc_key;
1279 1308 }
1280 1309
1281 1310 goto sbd_pgr_reg_done;
1282 1311 }
1283 1312
1284 1313 /* Handling unregistered IT session */
1285 1314 if (pr_out->action == PR_OUT_REGISTER && rsv_key != 0) {
1286 1315 stmf_scsilib_send_status(task, STATUS_RESERVATION_CONFLICT, 0);
1287 1316 return;
1288 1317 }
1289 1318
1290 1319 if (svc_key == 0) {
1291 1320 /* Do we need to consider aptpl here? I don't think so */
1292 1321 pgr->pgr_PRgeneration++;
1293 1322 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1294 1323 return;
1295 1324 }
1296 1325
1297 1326 keyflag = SBD_PGR_KEY_TPT_ID_FLAG;
1298 1327 if (plist->all_tg_pt) {
1299 1328 keyflag |= SBD_PGR_KEY_ALL_TG_PT;
1300 1329 lpt = NULL;
1301 1330 }
1302 1331
1303 1332 if (plist->spec_i_pt) {
1304 1333 uint32_t max_tpdnum, tpdnum, i, adn_len = 0;
1305 1334 uint16_t tpd_sz = 0;
1306 1335 uint8_t *adn_dat;
1307 1336 scsi_transport_id_t *tpd;
1308 1337 stmf_remote_port_t *rpt_ary;
1309 1338
1310 1339 if (pr_out->action == PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY) {
1311 1340 stmf_scsilib_send_status(task, STATUS_CHECK,
1312 1341 STMF_SAA_INVALID_FIELD_IN_CDB);
1313 1342 return;
1314 1343 }
1315 1344
1316 1345 /* Length validation SPC3 rev23 Section 6.12.3 and Table 115 */
1317 1346 if (buflen >= sizeof (scsi_prout_plist_t) - 1 +
1318 1347 sizeof (uint32_t))
1319 1348 adn_len = READ_SCSI32(plist->apd, uint32_t);
1320 1349 /* SPC3 rev23, adn_len should be multiple of 4 */
1321 1350 if (adn_len % 4 != 0 ||
1322 1351 adn_len < sizeof (scsi_transport_id_t) +
1323 1352 sizeof (uint32_t) ||
1324 1353 buflen < sizeof (scsi_prout_plist_t) - 1 + adn_len) {
1325 1354 stmf_scsilib_send_status(task, STATUS_CHECK,
1326 1355 STMF_SAA_PARAM_LIST_LENGTH_ERROR);
1327 1356 return;
1328 1357 }
1329 1358
1330 1359 tpdnum = 0;
1331 1360 adn_dat = plist->apd + sizeof (uint32_t);
1332 1361 max_tpdnum = adn_len / sizeof (scsi_transport_id_t);
1333 1362 rpt_ary = (stmf_remote_port_t *)kmem_zalloc(
1334 1363 sizeof (stmf_remote_port_t) * max_tpdnum, KM_SLEEP);
1335 1364
1336 1365 /* Check the validity of given TransportIDs */
1337 1366 while (adn_len != 0) {
1338 1367 if (!stmf_scsilib_tptid_validate(
1339 1368 (scsi_transport_id_t *)adn_dat, adn_len, &tpd_sz))
1340 1369 break;
1341 1370 /* SPC3 rev23, tpd_sz should be multiple of 4 */
1342 1371 if (tpd_sz == 0 || tpd_sz % 4 != 0)
1343 1372 break;
1344 1373 tpd = (scsi_transport_id_t *)adn_dat;
1345 1374
1346 1375 /* make sure that there is no duplicates */
1347 1376 for (i = 0; i < tpdnum; i++) {
1348 1377 if (stmf_scsilib_tptid_compare(
1349 1378 rpt_ary[i].rport_tptid, tpd))
1350 1379 break;
1351 1380 }
1352 1381 if (i < tpdnum)
1353 1382 break;
1354 1383
1355 1384 rpt_ary[tpdnum].rport_tptid = tpd;
1356 1385 rpt_ary[tpdnum].rport_tptid_sz = tpd_sz;
1357 1386
1358 1387 /* Check if the given IT nexus is already registered */
1359 1388 if (sbd_pgr_key_registered(pgr, lpt, &rpt_ary[tpdnum]))
1360 1389 break;
1361 1390
1362 1391 adn_len -= tpd_sz;
1363 1392 adn_dat += tpd_sz;
1364 1393 tpdnum++;
1365 1394 }
1366 1395
1367 1396 if (adn_len != 0) {
1368 1397 kmem_free(rpt_ary,
1369 1398 sizeof (stmf_remote_port_t) * max_tpdnum);
1370 1399 stmf_scsilib_send_status(task, STATUS_CHECK,
1371 1400 STMF_SAA_INVALID_FIELD_IN_CDB);
1372 1401 return;
1373 1402 }
1374 1403
1375 1404 for (i = 0; i < tpdnum; i++) {
1376 1405 (void) sbd_pgr_do_register(slu, NULL, lpt, &rpt_ary[i],
1377 1406 keyflag, svc_key);
1378 1407 }
|
↓ open down ↓ |
551 lines elided |
↑ open up ↑ |
1379 1408 kmem_free(rpt_ary, sizeof (stmf_remote_port_t) * max_tpdnum);
1380 1409 }
1381 1410
1382 1411 rport.rport_tptid = ses->ss_rport->rport_tptid;
1383 1412 rport.rport_tptid_sz = ses->ss_rport->rport_tptid_sz;
1384 1413
1385 1414 (void) sbd_pgr_do_register(slu, it, lpt, &rport, keyflag, svc_key);
1386 1415
1387 1416 sbd_pgr_reg_done:
1388 1417
1389 - if (pgr->pgr_flags & SBD_PGR_APTPL || plist->aptpl) {
1418 + if (plist->aptpl || (sbd_pgr_should_save(slu) == B_TRUE)) {
1390 1419 if (plist->aptpl)
1391 1420 PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
1392 1421 else
1393 1422 PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
1394 1423
1395 1424 if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1396 1425 stmf_scsilib_send_status(task, STATUS_CHECK,
1397 1426 STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1398 1427 return;
1399 1428 }
1400 1429 }
1401 1430
1402 1431 pgr->pgr_PRgeneration++;
1403 1432 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1404 1433 }
1405 1434
1406 1435 static sbd_pgr_key_t *
1407 1436 sbd_pgr_do_register(sbd_lu_t *slu, sbd_it_data_t *it, scsi_devid_desc_t *lpt,
1408 1437 stmf_remote_port_t *rpt, uint8_t keyflag, uint64_t svc_key)
1409 1438 {
1410 1439 sbd_pgr_t *pgr = slu->sl_pgr;
1411 1440 sbd_pgr_key_t *key;
1412 1441 uint16_t lpt_len = 0;
1413 1442
1414 1443 if (lpt)
1415 1444 lpt_len = sizeof (scsi_devid_desc_t) + lpt->ident_length;
1416 1445
1417 1446 key = sbd_pgr_key_alloc(lpt, rpt->rport_tptid,
1418 1447 lpt_len, rpt->rport_tptid_sz);
1419 1448 key->pgr_key = svc_key;
1420 1449 key->pgr_key_flags |= keyflag;
1421 1450
1422 1451 if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
1423 1452 /* set PGR_CHECK flag for all unregistered IT nexus */
1424 1453 sbd_pgr_set_pgr_check_flag(slu, B_FALSE);
1425 1454 } else {
1426 1455 key->pgr_key_it = it;
1427 1456 }
1428 1457
1429 1458 if (it) {
1430 1459 mutex_enter(&slu->sl_lock);
1431 1460 it->pgr_key_ptr = key;
1432 1461 mutex_exit(&slu->sl_lock);
1433 1462 } else {
1434 1463 sbd_pgr_set_pgr_check_flag(slu, B_FALSE);
1435 1464 }
1436 1465
1437 1466 key->pgr_key_next = pgr->pgr_keylist;
1438 1467 if (pgr->pgr_keylist) {
1439 1468 pgr->pgr_keylist->pgr_key_prev = key;
1440 1469 }
1441 1470 pgr->pgr_keylist = key;
1442 1471
1443 1472 return (key);
1444 1473 }
1445 1474
1446 1475 static void
1447 1476 sbd_pgr_do_unregister(sbd_lu_t *slu, sbd_it_data_t *it, sbd_pgr_key_t *key)
1448 1477 {
1449 1478 if (slu->sl_pgr->pgr_rsvholder == key) {
1450 1479 sbd_pgr_do_release(slu, it, SBD_UA_RESERVATIONS_RELEASED);
1451 1480 }
1452 1481
1453 1482 sbd_pgr_remove_key(slu, key);
1454 1483 if (slu->sl_pgr->pgr_keylist == NULL) {
1455 1484 PGR_CLEAR_RSV_FLAG(slu->sl_pgr->pgr_flags);
1456 1485 }
1457 1486 }
1458 1487
1459 1488 static void
1460 1489 sbd_pgr_out_reserve(scsi_task_t *task)
1461 1490 {
1462 1491 sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
1463 1492 stmf_scsi_session_t *ses = task->task_session;
1464 1493 scsi_cdb_prout_t *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
1465 1494 sbd_it_data_t *it = task->task_lu_itl_handle;
1466 1495 sbd_pgr_t *pgr = slu->sl_pgr;
1467 1496 sbd_pgr_key_t *key = it->pgr_key_ptr;
1468 1497
1469 1498 ASSERT(key);
1470 1499
1471 1500 if (!(PGR_VALID_SCOPE(pr_out->scope) && PGR_VALID_TYPE(pr_out->type))) {
1472 1501 stmf_scsilib_send_status(task, STATUS_CHECK,
1473 1502 STMF_SAA_INVALID_FIELD_IN_CDB);
1474 1503 return;
1475 1504 }
1476 1505
1477 1506 if (SBD_PGR_RSVD(pgr)) {
1478 1507 if (PGR_RESERVATION_HOLDER(pgr, key, it)) {
1479 1508 if (pgr->pgr_rsv_type != pr_out->type ||
1480 1509 pgr->pgr_rsv_scope != pr_out->scope) {
1481 1510 stmf_scsilib_send_status(task,
1482 1511 STATUS_RESERVATION_CONFLICT, 0);
1483 1512 return;
|
↓ open down ↓ |
84 lines elided |
↑ open up ↑ |
1484 1513 }
1485 1514 } else {
1486 1515 stmf_scsilib_send_status(task,
1487 1516 STATUS_RESERVATION_CONFLICT, 0);
1488 1517 return;
1489 1518
1490 1519 }
1491 1520 /* In case there is no reservation exist */
1492 1521 } else {
1493 1522 sbd_pgr_do_reserve(pgr, key, it, ses, pr_out);
1494 - if (pgr->pgr_flags & SBD_PGR_APTPL) {
1523 + if (sbd_pgr_should_save(slu) == B_TRUE) {
1495 1524 if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1496 1525 stmf_scsilib_send_status(task, STATUS_CHECK,
1497 1526 STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1498 1527 return;
1499 1528 }
1500 1529 }
1501 1530 }
1502 1531
1503 1532 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1504 1533 }
1505 1534
1506 1535 static void
1507 1536 sbd_pgr_do_reserve(sbd_pgr_t *pgr, sbd_pgr_key_t *key, sbd_it_data_t *it,
1508 1537 stmf_scsi_session_t *ses, scsi_cdb_prout_t *pr_out)
1509 1538 {
1510 1539 scsi_devid_desc_t *lpt;
1511 1540 uint16_t lpt_len;
1512 1541
1513 1542 pgr->pgr_rsv_type = pr_out->type;
1514 1543 pgr->pgr_rsv_scope = pr_out->scope;
1515 1544 if (pr_out->type == PGR_TYPE_WR_EX_AR ||
1516 1545 pr_out->type == PGR_TYPE_EX_AC_AR) {
1517 1546 PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_RSVD_ALL_REGISTRANTS);
1518 1547 } else {
1519 1548 if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
1520 1549 lpt = key->pgr_key_lpt_id;
1521 1550 lpt_len = key->pgr_key_lpt_len;
1522 1551 if (lpt_len > 0 && lpt != NULL) {
1523 1552 kmem_free(lpt, lpt_len);
1524 1553 }
1525 1554 lpt = ses->ss_lport->lport_id;
1526 1555 lpt_len = sizeof (scsi_devid_desc_t) +
1527 1556 lpt->ident_length;
1528 1557 key->pgr_key_lpt_len = lpt_len;
1529 1558 key->pgr_key_lpt_id = (scsi_devid_desc_t *)
1530 1559 kmem_zalloc(lpt_len, KM_SLEEP);
1531 1560 bcopy(lpt, key->pgr_key_lpt_id, lpt_len);
1532 1561 key->pgr_key_it = it;
1533 1562 }
1534 1563
1535 1564 PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_RSVD_ONE);
1536 1565 pgr->pgr_rsvholder = key;
1537 1566 }
1538 1567 }
1539 1568
1540 1569 static void
|
↓ open down ↓ |
36 lines elided |
↑ open up ↑ |
1541 1570 sbd_pgr_out_release(scsi_task_t *task)
1542 1571 {
1543 1572 sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
1544 1573 scsi_cdb_prout_t *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
1545 1574 sbd_it_data_t *it = task->task_lu_itl_handle;
1546 1575 sbd_pgr_t *pgr = slu->sl_pgr;
1547 1576 sbd_pgr_key_t *key = it->pgr_key_ptr;
1548 1577
1549 1578 ASSERT(key);
1550 1579
1580 + /*
1581 + * XXX this does not honor APTPL
1582 + * (i.e., changes made to a formerly-persistent reservation are not
1583 + * updated here!!!)
1584 + */
1551 1585 if (SBD_PGR_RSVD(pgr)) {
1552 1586 if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS ||
1553 1587 pgr->pgr_rsvholder == key) {
1554 1588 if (pgr->pgr_rsv_type != pr_out->type ||
1555 1589 pgr->pgr_rsv_scope != pr_out->scope) {
1556 1590 stmf_scsilib_send_status(task, STATUS_CHECK,
1557 1591 STMF_SAA_INVALID_RELEASE_OF_PR);
1558 1592 return;
1559 1593 }
1560 1594 sbd_pgr_do_release(slu, it,
1561 1595 SBD_UA_RESERVATIONS_RELEASED);
1596 +
1597 + /*
1598 + * XXX T10 SPC-3 5.6.10.2 says nothing about what to
1599 + * do in the event of a failure updating the
1600 + * PGR nvram store for a reservation associated with
1601 + * an APTPL-enabled (see SPC-3 5.6.4.1) I_T
1602 + * registration during a RELEASE service action.
1603 + *
1604 + * Technically, the CDB completed successfully, as per
1605 + * the spec, but at some point we may need to enter
1606 + * a recovery mode on the initiator(s) if we power cycle
1607 + * the target at the wrong instant...
1608 + */
1609 + if (sbd_pgr_should_save(slu) == B_TRUE) {
1610 + if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1611 + stmf_scsilib_send_status(task,
1612 + STATUS_CHECK, /* CSTYLED */
1613 + STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1614 + return;
1615 + }
1616 + }
1562 1617 }
1563 1618 }
1564 1619 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1565 1620 }
1566 1621
1567 1622 static void
1568 1623 sbd_pgr_do_release(sbd_lu_t *slu, sbd_it_data_t *it, uint8_t ua_condition)
1569 1624 {
1570 1625
1571 1626 sbd_pgr_t *pgr = slu->sl_pgr;
1572 1627
1573 1628 /* Reset pgr_flags */
1574 1629 PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
1575 1630 pgr->pgr_rsvholder = NULL;
1576 1631
1577 1632 /* set unit attention condition if necessary */
1578 1633 if (pgr->pgr_rsv_type != PGR_TYPE_WR_EX &&
1579 1634 pgr->pgr_rsv_type != PGR_TYPE_EX_AC) {
1580 1635 sbd_pgr_set_ua_conditions(slu, it, ua_condition);
1581 1636 }
1582 1637 pgr->pgr_rsv_type = 0;
1583 1638 }
1584 1639
1585 1640 static void
1586 1641 sbd_pgr_out_clear(scsi_task_t *task)
1587 1642 {
1588 1643 sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
1589 1644 sbd_it_data_t *it = task->task_lu_itl_handle;
1590 1645 sbd_pgr_t *pgr = slu->sl_pgr;
1591 1646
1592 1647 ASSERT(it->pgr_key_ptr);
1593 1648
1594 1649 PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
|
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
1595 1650 pgr->pgr_rsvholder = NULL;
1596 1651 pgr->pgr_rsv_type = 0;
1597 1652 mutex_enter(&slu->sl_lock);
1598 1653 /* Remove all pointers from IT to pgr keys */
1599 1654 for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
1600 1655 it->pgr_key_ptr = NULL;
1601 1656 }
1602 1657 mutex_exit(&slu->sl_lock);
1603 1658 sbd_pgr_keylist_dealloc(slu);
1604 1659 sbd_pgr_set_ua_conditions(slu, it, SBD_UA_RESERVATIONS_PREEMPTED);
1605 - if (pgr->pgr_flags & SBD_PGR_APTPL) {
1660 + if (sbd_pgr_should_save(slu) == B_TRUE) {
1606 1661 if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1607 1662 stmf_scsilib_send_status(task, STATUS_CHECK,
1608 1663 STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1609 1664 return;
1610 1665 }
1611 1666 }
1612 1667 pgr->pgr_PRgeneration++;
1613 1668 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1614 1669 }
1615 1670
1616 1671 static void
1617 1672 sbd_pgr_out_preempt(scsi_task_t *task, stmf_data_buf_t *dbuf)
1618 1673 {
1619 1674 sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
1620 1675 stmf_scsi_session_t *ses = task->task_session;
1621 1676 scsi_cdb_prout_t *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
1622 1677 sbd_it_data_t *it = task->task_lu_itl_handle;
1623 1678 sbd_pgr_t *pgr = slu->sl_pgr;
1624 1679 sbd_pgr_key_t *key = it->pgr_key_ptr;
1625 1680 scsi_prout_plist_t *plist;
1626 1681 uint8_t *buf, change_rsv = 0;
1627 1682 uint64_t svc_key;
1628 1683
1629 1684 ASSERT(key);
1630 1685
1631 1686 buf = dbuf->db_sglist[0].seg_addr;
1632 1687 plist = (scsi_prout_plist_t *)buf;
1633 1688 svc_key = READ_SCSI64(plist->service_key, uint64_t);
1634 1689
1635 1690 if (SBD_PGR_RSVD_NONE(pgr)) {
1636 1691 if (svc_key == 0 ||
1637 1692 sbd_pgr_remove_keys(slu, it, key, svc_key, B_TRUE) == 0) {
1638 1693 stmf_scsilib_send_status(task,
1639 1694 STATUS_RESERVATION_CONFLICT, 0);
1640 1695 return;
1641 1696 }
1642 1697
1643 1698 } else if (pgr->pgr_flags & SBD_PGR_RSVD_ONE) {
1644 1699 if (svc_key == 0) {
1645 1700 stmf_scsilib_send_status(task, STATUS_CHECK,
1646 1701 STMF_SAA_INVALID_FIELD_IN_CDB);
1647 1702 return;
1648 1703 }
1649 1704
1650 1705 /* Validity check of scope and type */
1651 1706 if (pgr->pgr_rsvholder->pgr_key == svc_key) {
1652 1707 if (!(PGR_VALID_SCOPE(pr_out->scope) &&
1653 1708 PGR_VALID_TYPE(pr_out->type))) {
1654 1709 stmf_scsilib_send_status(task, STATUS_CHECK,
1655 1710 STMF_SAA_INVALID_FIELD_IN_CDB);
1656 1711 return;
1657 1712 }
1658 1713 }
1659 1714
1660 1715 if (pgr->pgr_rsvholder != key &&
1661 1716 pgr->pgr_rsvholder->pgr_key == svc_key) {
1662 1717 sbd_pgr_do_release(slu, it,
1663 1718 SBD_UA_REGISTRATIONS_PREEMPTED);
1664 1719 change_rsv = 1;
1665 1720 }
1666 1721
1667 1722 if (pgr->pgr_rsvholder == key &&
1668 1723 pgr->pgr_rsvholder->pgr_key == svc_key) {
1669 1724 if (pr_out->scope != pgr->pgr_rsv_scope ||
1670 1725 pr_out->type != pgr->pgr_rsv_type) {
1671 1726 sbd_pgr_do_release(slu, it,
1672 1727 SBD_UA_REGISTRATIONS_PREEMPTED);
1673 1728 change_rsv = 1;
1674 1729 }
1675 1730 } else {
1676 1731 /*
1677 1732 * Remove matched keys in all cases, except when the
1678 1733 * current IT nexus holds the reservation and the given
1679 1734 * svc_key matches with registered key.
1680 1735 * Note that, if the reservation is held by another
1681 1736 * IT nexus, and svc_key matches registered key for
1682 1737 * that IT nexus, sbd_pgr_remove_key() is not expected
1683 1738 * return 0. Hence, returning check condition after
1684 1739 * releasing the reservation does not arise.
1685 1740 */
1686 1741 if (sbd_pgr_remove_keys(slu, it, key, svc_key, B_TRUE)
1687 1742 == 0) {
1688 1743 stmf_scsilib_send_status(task,
1689 1744 STATUS_RESERVATION_CONFLICT, 0);
1690 1745 return;
1691 1746 }
1692 1747 }
1693 1748
1694 1749 if (change_rsv) {
1695 1750 sbd_pgr_do_reserve(pgr, key, it, ses, pr_out);
1696 1751 }
1697 1752
1698 1753 } else if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS) {
1699 1754 if (svc_key == 0) {
1700 1755 if (!(PGR_VALID_SCOPE(pr_out->scope) &&
1701 1756 PGR_VALID_TYPE(pr_out->type))) {
1702 1757 stmf_scsilib_send_status(task, STATUS_CHECK,
1703 1758 STMF_SAA_INVALID_FIELD_IN_CDB);
1704 1759 return;
1705 1760 }
1706 1761 sbd_pgr_do_release(slu, it,
1707 1762 SBD_UA_REGISTRATIONS_PREEMPTED);
1708 1763 (void) sbd_pgr_remove_keys(slu, it, key, 0, B_FALSE);
1709 1764 sbd_pgr_do_reserve(pgr, key, it, ses, pr_out);
|
↓ open down ↓ |
94 lines elided |
↑ open up ↑ |
1710 1765 } else {
1711 1766 if (sbd_pgr_remove_keys(slu, it, key, svc_key, B_TRUE)
1712 1767 == 0) {
1713 1768 stmf_scsilib_send_status(task,
1714 1769 STATUS_RESERVATION_CONFLICT, 0);
1715 1770 return;
1716 1771 }
1717 1772 }
1718 1773 }
1719 1774
1720 - if (pgr->pgr_flags & SBD_PGR_APTPL) {
1775 + if (sbd_pgr_should_save(slu) == B_TRUE) {
1721 1776 if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1722 1777 stmf_scsilib_send_status(task, STATUS_CHECK,
1723 1778 STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1724 1779 return;
1725 1780 }
1726 1781 }
1727 1782
1728 1783 pgr->pgr_PRgeneration++;
1729 1784
1730 1785 if (pr_out->action == PR_OUT_PREEMPT_ABORT) {
1731 1786 stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED,
1732 1787 (void *)slu->sl_lu);
1733 1788 }
1734 1789 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1735 1790 }
1736 1791
1737 1792 static void
1738 1793 sbd_pgr_out_register_and_move(scsi_task_t *task, stmf_data_buf_t *dbuf)
1739 1794 {
1740 1795 sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
1741 1796 sbd_it_data_t *it = task->task_lu_itl_handle;
1742 1797 sbd_pgr_t *pgr = slu->sl_pgr;
1743 1798 sbd_pgr_key_t *key = it->pgr_key_ptr;
1744 1799 scsi_devid_desc_t *lpt;
1745 1800 stmf_remote_port_t rport;
1746 1801 sbd_pgr_key_t *newkey;
1747 1802 scsi_prout_reg_move_plist_t *plist;
1748 1803 uint8_t *buf, lpt_len;
1749 1804 uint16_t tpd_len;
1750 1805 uint32_t adn_len;
1751 1806 uint64_t svc_key;
1752 1807
1753 1808 /*
1754 1809 * Check whether the key holds the reservation or current reservation
1755 1810 * is of type all registrants.
1756 1811 */
1757 1812 if (pgr->pgr_rsvholder != key) {
1758 1813 stmf_scsilib_send_status(task, STATUS_RESERVATION_CONFLICT, 0);
1759 1814 return;
1760 1815 }
1761 1816
1762 1817 buf = dbuf->db_sglist[0].seg_addr;
1763 1818 plist = (scsi_prout_reg_move_plist_t *)buf;
1764 1819 svc_key = READ_SCSI64(plist->service_key, uint64_t);
1765 1820 if (svc_key == 0) {
1766 1821 stmf_scsilib_send_status(task, STATUS_CHECK,
1767 1822 STMF_SAA_INVALID_FIELD_IN_CDB);
1768 1823 return;
1769 1824 }
1770 1825
1771 1826 lpt = stmf_scsilib_get_devid_desc(READ_SCSI16(plist->rel_tgt_port_id,
1772 1827 uint16_t));
1773 1828 if (lpt == NULL) {
1774 1829 stmf_scsilib_send_status(task, STATUS_CHECK,
1775 1830 STMF_SAA_INVALID_FIELD_IN_CDB);
1776 1831 return;
1777 1832 }
1778 1833
1779 1834 adn_len = READ_SCSI32(plist->tptid_len, uint32_t);
1780 1835 if (!stmf_scsilib_tptid_validate(
1781 1836 (scsi_transport_id_t *)plist->tptid, adn_len, &tpd_len)) {
1782 1837 kmem_free(lpt, sizeof (scsi_devid_desc_t) + lpt->ident_length);
1783 1838 stmf_scsilib_send_status(task, STATUS_CHECK,
1784 1839 STMF_SAA_INVALID_FIELD_IN_PARAM_LIST);
1785 1840 return;
1786 1841 }
1787 1842
1788 1843 rport.rport_tptid = (scsi_transport_id_t *)plist->tptid;
1789 1844 rport.rport_tptid_sz = tpd_len;
1790 1845
1791 1846 if (sbd_pgr_key_compare(key, lpt, &rport)) {
1792 1847 kmem_free(lpt, sizeof (scsi_devid_desc_t) + lpt->ident_length);
1793 1848 stmf_scsilib_send_status(task, STATUS_CHECK,
1794 1849 STMF_SAA_INVALID_FIELD_IN_PARAM_LIST);
1795 1850 return;
1796 1851 }
1797 1852
1798 1853 newkey = sbd_pgr_key_registered(pgr, lpt, &rport);
1799 1854 if (newkey) {
1800 1855 /* Set the pgr_key, irrespective of what it currently holds */
1801 1856 newkey->pgr_key = svc_key;
1802 1857
1803 1858 /* all_tg_pt is set for found key, copy lpt info to the key */
1804 1859 if (newkey->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
1805 1860 if (newkey->pgr_key_lpt_id &&
1806 1861 newkey->pgr_key_lpt_len > 0) {
1807 1862 kmem_free(newkey->pgr_key_lpt_id,
1808 1863 newkey->pgr_key_lpt_len);
1809 1864 }
1810 1865 lpt_len = sizeof (scsi_devid_desc_t) +
1811 1866 lpt->ident_length;
1812 1867 newkey->pgr_key_lpt_len = lpt_len;
1813 1868 newkey->pgr_key_lpt_id = (scsi_devid_desc_t *)
1814 1869 kmem_zalloc(lpt_len, KM_SLEEP);
1815 1870 bcopy(lpt, newkey->pgr_key_lpt_id, lpt_len);
1816 1871 }
1817 1872 /* No IT nexus information, hence set PGR_CHEK flag */
1818 1873 sbd_pgr_set_pgr_check_flag(slu, B_TRUE);
1819 1874 } else {
1820 1875 newkey = sbd_pgr_do_register(slu, NULL, lpt, &rport,
1821 1876 SBD_PGR_KEY_TPT_ID_FLAG, svc_key);
1822 1877 }
1823 1878
|
↓ open down ↓ |
93 lines elided |
↑ open up ↑ |
1824 1879 kmem_free(lpt, sizeof (scsi_devid_desc_t) + lpt->ident_length);
1825 1880
1826 1881 /* Now reserve the key corresponding to the specified IT nexus */
1827 1882 pgr->pgr_rsvholder = newkey;
1828 1883
1829 1884 if (plist->unreg) {
1830 1885 sbd_pgr_do_unregister(slu, it, key);
1831 1886 }
1832 1887
1833 1888
1834 - /* Write to disk if currenty aptpl is set or given task is setting it */
1835 - if (pgr->pgr_flags & SBD_PGR_APTPL || plist->aptpl) {
1889 + /* Write to disk if aptpl is currently set or this task is setting it */
1890 + if (plist->aptpl || (sbd_pgr_should_save(slu) == B_TRUE)) {
1836 1891 if (plist->aptpl)
1837 1892 PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
1838 1893 else
1839 1894 PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
1840 1895
1841 1896 if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1842 1897 stmf_scsilib_send_status(task, STATUS_CHECK,
1843 1898 STMF_SAA_INSUFFICIENT_REG_RESOURCES);
1844 1899 return;
1845 1900 }
1846 1901 }
1847 1902
1848 1903 pgr->pgr_PRgeneration++;
1849 1904 stmf_scsilib_send_status(task, STATUS_GOOD, 0);
1850 1905 }
1851 1906
1852 1907 void
1853 1908 sbd_pgr_remove_it_handle(sbd_lu_t *sl, sbd_it_data_t *my_it) {
1854 1909 sbd_it_data_t *it;
1855 1910
1856 1911 rw_enter(&sl->sl_pgr->pgr_lock, RW_WRITER);
1857 1912 mutex_enter(&sl->sl_lock);
1858 1913 for (it = sl->sl_it_list; it != NULL; it = it->sbd_it_next) {
1859 1914 if (it == my_it) {
1860 1915 if (it->pgr_key_ptr) {
1861 1916 sbd_pgr_key_t *key = it->pgr_key_ptr;
1862 1917 if (key->pgr_key_it == it) {
1863 1918 key->pgr_key_it = NULL;
1864 1919 sl->sl_pgr->pgr_flags &=
1865 1920 ~SBD_PGR_ALL_KEYS_HAS_IT;
1866 1921 }
1867 1922 }
1868 1923 break;
1869 1924 }
1870 1925 }
1871 1926 mutex_exit(&sl->sl_lock);
1872 1927 rw_exit(&sl->sl_pgr->pgr_lock);
1873 1928
1874 1929 }
1875 1930
1876 1931 char *
1877 1932 sbd_get_devid_string(sbd_lu_t *sl)
1878 1933 {
1879 1934 char *str = (char *)kmem_zalloc(33, KM_SLEEP);
1880 1935 (void) snprintf(str, 33,
1881 1936 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
1882 1937 sl->sl_device_id[4], sl->sl_device_id[5], sl->sl_device_id[6],
1883 1938 sl->sl_device_id[7], sl->sl_device_id[8], sl->sl_device_id[9],
1884 1939 sl->sl_device_id[10], sl->sl_device_id[11], sl->sl_device_id[12],
1885 1940 sl->sl_device_id[13], sl->sl_device_id[14], sl->sl_device_id[15],
1886 1941 sl->sl_device_id[16], sl->sl_device_id[17], sl->sl_device_id[18],
1887 1942 sl->sl_device_id[19]);
1888 1943 return (str);
1889 1944 }
|
↓ open down ↓ |
44 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX