18fe96085Stim szeto /*
28fe96085Stim szeto * CDDL HEADER START
38fe96085Stim szeto *
48fe96085Stim szeto * The contents of this file are subject to the terms of the
58fe96085Stim szeto * Common Development and Distribution License (the "License").
68fe96085Stim szeto * You may not use this file except in compliance with the License.
78fe96085Stim szeto *
88fe96085Stim szeto * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98fe96085Stim szeto * or http://www.opensolaris.org/os/licensing.
108fe96085Stim szeto * See the License for the specific language governing permissions
118fe96085Stim szeto * and limitations under the License.
128fe96085Stim szeto *
138fe96085Stim szeto * When distributing Covered Code, include this CDDL HEADER in each
148fe96085Stim szeto * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158fe96085Stim szeto * If applicable, add the following below this CDDL HEADER, with the
168fe96085Stim szeto * fields enclosed by brackets "[]" replaced with your own identifying
178fe96085Stim szeto * information: Portions Copyright [yyyy] [name of copyright owner]
188fe96085Stim szeto *
198fe96085Stim szeto * CDDL HEADER END
208fe96085Stim szeto */
218fe96085Stim szeto /*
22f4e76ddfSNattuvetty Bhavyan * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23*61dfa509SRick McNeal * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
248fe96085Stim szeto */
258fe96085Stim szeto
268fe96085Stim szeto #include <sys/atomic.h>
278fe96085Stim szeto #include <sys/conf.h>
288fe96085Stim szeto #include <sys/byteorder.h>
298fe96085Stim szeto #include <sys/scsi/scsi_types.h>
308fe96085Stim szeto #include <sys/scsi/generic/persist.h>
318fe96085Stim szeto
324558d122SViswanathan Kannappan #include <sys/lpif.h>
334558d122SViswanathan Kannappan #include <sys/stmf.h>
344558d122SViswanathan Kannappan #include <sys/stmf_ioctl.h>
354558d122SViswanathan Kannappan #include <sys/portif.h>
364558d122SViswanathan Kannappan #include <sys/stmf_sbd_ioctl.h>
374558d122SViswanathan Kannappan
384558d122SViswanathan Kannappan #include "stmf_sbd.h"
394558d122SViswanathan Kannappan #include "sbd_impl.h"
408fe96085Stim szeto
418fe96085Stim szeto #define MAX_PGR_PARAM_LIST_LENGTH (256 * 1024)
428fe96085Stim szeto
43*61dfa509SRick McNeal int sbd_pgr_reservation_conflict(scsi_task_t *, struct sbd_lu *sl);
4445039663SJohn Forte void sbd_pgr_reset(sbd_lu_t *);
45f4e76ddfSNattuvetty Bhavyan void sbd_pgr_initialize_it(scsi_task_t *, sbd_it_data_t *);
468fe96085Stim szeto void sbd_handle_pgr_in_cmd(scsi_task_t *, stmf_data_buf_t *);
478fe96085Stim szeto void sbd_handle_pgr_out_cmd(scsi_task_t *, stmf_data_buf_t *);
488fe96085Stim szeto void sbd_handle_pgr_out_data(scsi_task_t *, stmf_data_buf_t *);
498fe96085Stim szeto void sbd_pgr_keylist_dealloc(sbd_lu_t *);
508fe96085Stim szeto char *sbd_get_devid_string(sbd_lu_t *);
518fe96085Stim szeto
527145ae3eSNattuvetty Bhavyan sbd_status_t sbd_pgr_meta_init(sbd_lu_t *);
538fe96085Stim szeto sbd_status_t sbd_pgr_meta_load(sbd_lu_t *);
548fe96085Stim szeto sbd_status_t sbd_pgr_meta_write(sbd_lu_t *);
558fe96085Stim szeto static void sbd_swap_pgr_info(sbd_pgr_info_t *);
568fe96085Stim szeto static void sbd_swap_pgrkey_info(sbd_pgr_key_info_t *);
578fe96085Stim szeto static void sbd_pgr_key_free(sbd_pgr_key_t *);
588fe96085Stim szeto static void sbd_pgr_remove_key(sbd_lu_t *, sbd_pgr_key_t *);
598fe96085Stim szeto static uint32_t sbd_pgr_remove_keys(sbd_lu_t *, sbd_it_data_t *,
608fe96085Stim szeto sbd_pgr_key_t *, uint64_t, boolean_t);
618fe96085Stim szeto static boolean_t sbd_pgr_key_compare(sbd_pgr_key_t *, scsi_devid_desc_t *,
62716c1805SNattuvetty Bhavyan stmf_remote_port_t *);
638fe96085Stim szeto static sbd_pgr_key_t *sbd_pgr_key_alloc(scsi_devid_desc_t *,
64716c1805SNattuvetty Bhavyan scsi_transport_id_t *, int16_t, int16_t);
658fe96085Stim szeto
668fe96085Stim szeto static void sbd_pgr_set_pgr_check_flag(sbd_lu_t *, boolean_t);
678fe96085Stim szeto static void sbd_pgr_set_ua_conditions(sbd_lu_t *, sbd_it_data_t *, uint8_t);
688fe96085Stim szeto static void sbd_pgr_in_read_keys(scsi_task_t *, stmf_data_buf_t *);
698fe96085Stim szeto static void sbd_pgr_in_report_capabilities(scsi_task_t *, stmf_data_buf_t *);
708fe96085Stim szeto static void sbd_pgr_in_read_reservation(scsi_task_t *, stmf_data_buf_t *);
718fe96085Stim szeto static void sbd_pgr_in_read_full_status(scsi_task_t *, stmf_data_buf_t *);
728fe96085Stim szeto static void sbd_pgr_out_register(scsi_task_t *, stmf_data_buf_t *);
738fe96085Stim szeto static void sbd_pgr_out_reserve(scsi_task_t *);
748fe96085Stim szeto static void sbd_pgr_out_release(scsi_task_t *);
758fe96085Stim szeto static void sbd_pgr_out_clear(scsi_task_t *);
768fe96085Stim szeto static void sbd_pgr_out_preempt(scsi_task_t *, stmf_data_buf_t *);
778fe96085Stim szeto static void sbd_pgr_out_register_and_move(scsi_task_t *, stmf_data_buf_t *);
788fe96085Stim szeto
798fe96085Stim szeto static sbd_pgr_key_t *sbd_pgr_do_register(sbd_lu_t *, sbd_it_data_t *,
80716c1805SNattuvetty Bhavyan scsi_devid_desc_t *, stmf_remote_port_t *, uint8_t, uint64_t);
818fe96085Stim szeto static void sbd_pgr_do_unregister(sbd_lu_t *, sbd_it_data_t *, sbd_pgr_key_t *);
828fe96085Stim szeto static void sbd_pgr_do_release(sbd_lu_t *, sbd_it_data_t *, uint8_t);
838fe96085Stim szeto static void sbd_pgr_do_reserve(sbd_pgr_t *, sbd_pgr_key_t *, sbd_it_data_t *it,
848fe96085Stim szeto stmf_scsi_session_t *, scsi_cdb_prout_t *);
858fe96085Stim szeto
86*61dfa509SRick McNeal static boolean_t sbd_pgr_should_save(sbd_lu_t *);
878fe96085Stim szeto extern sbd_status_t sbd_write_meta_section(sbd_lu_t *, sm_section_hdr_t *);
888fe96085Stim szeto extern sbd_status_t sbd_read_meta_section(sbd_lu_t *, sm_section_hdr_t **,
898fe96085Stim szeto uint16_t);
908fe96085Stim szeto extern void sbd_swap_section_hdr(sm_section_hdr_t *);
918fe96085Stim szeto extern void sbd_handle_short_write_transfers(scsi_task_t *task,
928fe96085Stim szeto stmf_data_buf_t *dbuf, uint32_t cdb_xfer_size);
938fe96085Stim szeto extern void sbd_handle_short_read_transfers(scsi_task_t *task,
948fe96085Stim szeto stmf_data_buf_t *dbuf, uint8_t *p, uint32_t cdb_xfer_size,
958fe96085Stim szeto uint32_t cmd_xfer_size);
968fe96085Stim szeto extern uint16_t stmf_scsilib_get_lport_rtid(scsi_devid_desc_t *devid);
978fe96085Stim szeto extern scsi_devid_desc_t *stmf_scsilib_get_devid_desc(uint16_t rtpid);
9870c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States extern char sbd_ctoi(char c);
998fe96085Stim szeto
1008fe96085Stim szeto /*
1018fe96085Stim szeto *
1028fe96085Stim szeto *
1038fe96085Stim szeto * +-----------+
1048fe96085Stim szeto * | |sl_it_list
1058fe96085Stim szeto * | |---------------------------------------+
1068fe96085Stim szeto * | | |
1078fe96085Stim szeto * | sbd_lu_t | |
1088fe96085Stim szeto * | | |
1098fe96085Stim szeto * | | |
1108fe96085Stim szeto * | | |
1118fe96085Stim szeto * +-----+-----+ V
1128fe96085Stim szeto * | +-------+
1138fe96085Stim szeto * V | |
1148fe96085Stim szeto * +-----------+ pgr_key_list +------>| |
1158fe96085Stim szeto * | |------------+ +-->(NULL) | +- ---|sbd_it |
1168fe96085Stim szeto * | | | | | | | _data |
1178fe96085Stim szeto * | sbd_pgr_t | V | | | | |
1188fe96085Stim szeto * | | +-------+ | | +-------+
1198fe96085Stim szeto * | |---+ | | | | |
1208fe96085Stim szeto * | | | |sbd_pgr|---------+ | v
1218fe96085Stim szeto * +-----------+ | | _key_t|<----------+ +-------+
1228fe96085Stim szeto * | | | | |
1238fe96085Stim szeto * | | | | |
1248fe96085Stim szeto * | +-------+ +--------| |
1258fe96085Stim szeto * | |^ | | |
1268fe96085Stim szeto * | || | | |
1278fe96085Stim szeto * | v| | +-------+
1288fe96085Stim szeto * | +-------+ | |
1298fe96085Stim szeto * | | | | v
1308fe96085Stim szeto * | |ALL_TG_|<-------+ +-------+
1318fe96085Stim szeto * | |PT = 1 |<---------+ | |
1328fe96085Stim szeto * | | |---+ | | |
1338fe96085Stim szeto * | | | | +------| |
1348fe96085Stim szeto * (pgr_rsvholder +-------+ V | |
1358fe96085Stim szeto * pgr_flags& |^ (NUll) | |
1368fe96085Stim szeto * RSVD_ONE) || +-------+
1378fe96085Stim szeto * | v| |
1388fe96085Stim szeto * | +-------+ v
1398fe96085Stim szeto * | | | +-------+
1408fe96085Stim szeto * | | not | | |
1418fe96085Stim szeto * | |claimed|---+ | |
1428fe96085Stim szeto * | | | | +----| unreg |
1438fe96085Stim szeto * | | | V | | |
1448fe96085Stim szeto * | +-------+ (NUll) V | |
1458fe96085Stim szeto * | |^ (NUll) +-------+
1468fe96085Stim szeto * | || |
1478fe96085Stim szeto * | v| v
1488fe96085Stim szeto * | +-------+ +-------+
1498fe96085Stim szeto * | | | | |
1508fe96085Stim szeto * | |reserv-|<----------------| |
1518fe96085Stim szeto * +----->| ation|---------------->| |
1528fe96085Stim szeto * |holder | | |
1538fe96085Stim szeto * |key | | |
1548fe96085Stim szeto * +-------+ +-------+
1558fe96085Stim szeto * |^ |
1568fe96085Stim szeto * || v
1578fe96085Stim szeto * v| +-------+
1588fe96085Stim szeto * +-------+ | |
1598fe96085Stim szeto * | | | |
1608fe96085Stim szeto * | not |---+ +----| unreg |
1618fe96085Stim szeto * |claimed| | | | |
1628fe96085Stim szeto * | | V V | |
1638fe96085Stim szeto * | | (NUll) (NUll) +-------+
1648fe96085Stim szeto * +-------+ |
1658fe96085Stim szeto * | v
1668fe96085Stim szeto * v (NULL)
1678fe96085Stim szeto * (NULL)
1688fe96085Stim szeto *
1698fe96085Stim szeto *
1708fe96085Stim szeto */
1718fe96085Stim szeto
1728fe96085Stim szeto #define PGR_CONFLICT_FREE_CMDS(cdb) ( \
1738fe96085Stim szeto /* ----------------------- */ \
1748fe96085Stim szeto /* SPC-3 (rev 23) Table 31 */ \
1758fe96085Stim szeto /* ----------------------- */ \
1768fe96085Stim szeto ((cdb[0]) == SCMD_INQUIRY) || \
1778fe96085Stim szeto ((cdb[0]) == SCMD_LOG_SENSE_G1) || \
1788fe96085Stim szeto ((cdb[0]) == SCMD_PERSISTENT_RESERVE_IN) || \
1798fe96085Stim szeto ((cdb[0]) == SCMD_REPORT_LUNS) || \
1808fe96085Stim szeto ((cdb[0]) == SCMD_REQUEST_SENSE) || \
1818fe96085Stim szeto ((cdb[0]) == SCMD_TEST_UNIT_READY) || \
1828fe96085Stim szeto /* PREVENT ALLOW MEDIUM REMOVAL with prevent == 0 */ \
1838fe96085Stim szeto ((((cdb[0]) == SCMD_DOORLOCK) && (((cdb[4]) & 0x3) == 0))) || \
1848fe96085Stim szeto /* SERVICE ACTION IN with READ MEDIA SERIAL NUMBER (0x01) */ \
1858fe96085Stim szeto (((cdb[0]) == SCMD_SVC_ACTION_IN_G5) && ( \
1868fe96085Stim szeto ((cdb[1]) & 0x1F) == 0x01)) || \
1878fe96085Stim szeto /* MAINTENANCE IN with service actions REPORT ALIASES (0x0Bh) */ \
1888fe96085Stim szeto /* REPORT DEVICE IDENTIFIER (0x05) REPORT PRIORITY (0x0Eh) */ \
1898fe96085Stim szeto /* REPORT TARGET PORT GROUPS (0x0A) REPORT TIMESTAMP (0x0F) */ \
1908fe96085Stim szeto (((cdb[0]) == SCMD_MAINTENANCE_IN) && ( \
1918fe96085Stim szeto (((cdb[1]) & 0x1F) == 0x0B) || \
1928fe96085Stim szeto (((cdb[1]) & 0x1F) == 0x05) || \
1938fe96085Stim szeto (((cdb[1]) & 0x1F) == 0x0E) || \
1948fe96085Stim szeto (((cdb[1]) & 0x1F) == 0x0A) || \
1958fe96085Stim szeto (((cdb[1]) & 0x1F) == 0x0F))) || \
1968fe96085Stim szeto /* REGISTER and REGISTER_AND_IGNORE_EXISTING_KEY */ \
1978fe96085Stim szeto /* actions for PERSISTENT RESERVE OUT command */ \
1988fe96085Stim szeto (((cdb[0]) == SCMD_PERSISTENT_RESERVE_OUT) && ( \
1998fe96085Stim szeto (((cdb[1]) & 0x1F) == PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY) || \
200*61dfa509SRick McNeal (((cdb[1]) & 0x1F) == PR_OUT_REGISTER))) || \
2018fe96085Stim szeto /* ----------------------- */ \
2028fe96085Stim szeto /* SBC-3 (rev 17) Table 3 */ \
2038fe96085Stim szeto /* ----------------------- */ \
2048fe96085Stim szeto /* READ CAPACITY(10) */ \
2058fe96085Stim szeto ((cdb[0]) == SCMD_READ_CAPACITY) || \
2068fe96085Stim szeto /* READ CAPACITY(16) */ \
2078fe96085Stim szeto (((cdb[0]) == SCMD_SVC_ACTION_IN_G4) && ( \
2088fe96085Stim szeto ((cdb[1]) & 0x1F) == 0x10)) || \
2098fe96085Stim szeto /* START STOP UNIT with START bit 0 and POWER CONDITION 0 */ \
2108fe96085Stim szeto (((cdb[0]) == SCMD_START_STOP) && ( \
2118fe96085Stim szeto (((cdb[4]) & 0xF0) == 0) && (((cdb[4]) & 0x01) == 0))))
2128fe96085Stim szeto /* End of PGR_CONFLICT_FREE_CMDS */
2138fe96085Stim szeto
2148fe96085Stim szeto /* Commands allowed for registered IT nexues but not reservation holder */
2158fe96085Stim szeto #define PGR_REGISTERED_POSSIBLE_CMDS(cdb) ( \
2168fe96085Stim szeto (((cdb[0]) == SCMD_PERSISTENT_RESERVE_OUT) && ( \
2178fe96085Stim szeto (((cdb[1]) & 0x1F) == PR_OUT_RELEASE) || \
2188fe96085Stim szeto (((cdb[1]) & 0x1F) == PR_OUT_CLEAR) || \
2198fe96085Stim szeto (((cdb[1]) & 0x1F) == PR_OUT_PREEMPT) || \
2208fe96085Stim szeto (((cdb[1]) & 0x1F) == PR_OUT_PREEMPT_ABORT))))
2218fe96085Stim szeto
2228fe96085Stim szeto /* List of commands allowed when WR_EX type reservation held */
2238fe96085Stim szeto #define PGR_READ_POSSIBLE_CMDS(c) ( \
2248fe96085Stim szeto ((c) == SCMD_READ) || \
2258fe96085Stim szeto ((c) == SCMD_READ_G1) || \
2268fe96085Stim szeto ((c) == SCMD_READ_G4) || \
2278fe96085Stim szeto ((c) == SCMD_READ_G5) || \
2288fe96085Stim szeto /* READ FETCH (10) (16) */ \
2298fe96085Stim szeto ((c) == SCMD_READ_POSITION) || \
2308fe96085Stim szeto ((c) == 0x90) || \
2318fe96085Stim szeto /* READ DEFECT DATA */ \
2328fe96085Stim szeto ((c) == SCMD_READ_DEFECT_LIST) || \
2338fe96085Stim szeto ((c) == 0xB7) || \
2348fe96085Stim szeto /* VERIFY (10) (16) (12) */ \
2358fe96085Stim szeto ((c) == SCMD_VERIFY) || \
2368fe96085Stim szeto ((c) == SCMD_VERIFY_G4) || \
2378fe96085Stim szeto ((c) == SCMD_VERIFY_G5) || \
2388fe96085Stim szeto /* XDREAD (10) */ \
2398fe96085Stim szeto ((c) == 0x52))
2408fe96085Stim szeto
2418fe96085Stim szeto #define PGR_RESERVATION_HOLDER(pgr, key, it) ( \
2428fe96085Stim szeto ((pgr)->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS) || ( \
2438fe96085Stim szeto ((pgr)->pgr_rsvholder) && ((pgr)->pgr_rsvholder == (key)) && \
2448fe96085Stim szeto ((key)->pgr_key_it) && ((key)->pgr_key_it == (it))))
2458fe96085Stim szeto
2468fe96085Stim szeto #define PGR_SET_FLAG(flg, val) (atomic_or_8(&(flg), (val)))
2478fe96085Stim szeto #define PGR_CLEAR_FLAG(flg, val) (atomic_and_8(&(flg), ~(val)))
2488fe96085Stim szeto #define PGR_CLEAR_RSV_FLAG(flg) (atomic_and_8(&(flg), \
2498fe96085Stim szeto (~(SBD_PGR_RSVD_ALL_REGISTRANTS | SBD_PGR_RSVD_ONE))))
2508fe96085Stim szeto
2518fe96085Stim szeto #define PGR_VALID_SCOPE(scope) ((scope) == PR_LU_SCOPE)
2528fe96085Stim szeto #define PGR_VALID_TYPE(type) ( \
2538fe96085Stim szeto ((type) == PGR_TYPE_WR_EX) || \
2548fe96085Stim szeto ((type) == PGR_TYPE_EX_AC) || \
2558fe96085Stim szeto ((type) == PGR_TYPE_WR_EX_RO) || \
2568fe96085Stim szeto ((type) == PGR_TYPE_EX_AC_RO) || \
2578fe96085Stim szeto ((type) == PGR_TYPE_WR_EX_AR) || \
2588fe96085Stim szeto ((type) == PGR_TYPE_EX_AC_AR))
2598fe96085Stim szeto
260716c1805SNattuvetty Bhavyan #define ALIGNED_TO_8BYTE_BOUNDARY(i) (((i) + 7) & ~7)
2618fe96085Stim szeto
2628fe96085Stim szeto static void
sbd_swap_pgr_info(sbd_pgr_info_t * spi)2638fe96085Stim szeto sbd_swap_pgr_info(sbd_pgr_info_t *spi)
2648fe96085Stim szeto {
2658fe96085Stim szeto sbd_swap_section_hdr(&spi->pgr_sms_header);
2668fe96085Stim szeto if (spi->pgr_data_order == SMS_DATA_ORDER)
2678fe96085Stim szeto return;
2688fe96085Stim szeto spi->pgr_sms_header.sms_chksum += SMS_DATA_ORDER - spi->pgr_data_order;
2698fe96085Stim szeto spi->pgr_rsvholder_indx = BSWAP_32(spi->pgr_rsvholder_indx);
2708fe96085Stim szeto spi->pgr_numkeys = BSWAP_32(spi->pgr_numkeys);
2718fe96085Stim szeto }
2728fe96085Stim szeto
2738fe96085Stim szeto static void
sbd_swap_pgrkey_info(sbd_pgr_key_info_t * key)2748fe96085Stim szeto sbd_swap_pgrkey_info(sbd_pgr_key_info_t *key)
2758fe96085Stim szeto {
2768fe96085Stim szeto key->pgr_key = BSWAP_64(key->pgr_key);
2778fe96085Stim szeto key->pgr_key_lpt_len = BSWAP_16(key->pgr_key_lpt_len);
2788fe96085Stim szeto key->pgr_key_rpt_len = BSWAP_16(key->pgr_key_rpt_len);
2798fe96085Stim szeto }
2808fe96085Stim szeto
2817145ae3eSNattuvetty Bhavyan sbd_status_t
sbd_pgr_meta_init(sbd_lu_t * slu)2827145ae3eSNattuvetty Bhavyan sbd_pgr_meta_init(sbd_lu_t *slu)
2837145ae3eSNattuvetty Bhavyan {
2847145ae3eSNattuvetty Bhavyan sbd_pgr_info_t *spi = NULL;
285*61dfa509SRick McNeal uint32_t sz;
2867145ae3eSNattuvetty Bhavyan sbd_status_t ret;
2877145ae3eSNattuvetty Bhavyan
2887145ae3eSNattuvetty Bhavyan sz = sizeof (sbd_pgr_info_t);
2897145ae3eSNattuvetty Bhavyan spi = (sbd_pgr_info_t *)kmem_zalloc(sz, KM_SLEEP);
2907145ae3eSNattuvetty Bhavyan spi->pgr_data_order = SMS_DATA_ORDER;
2917145ae3eSNattuvetty Bhavyan spi->pgr_sms_header.sms_size = sz;
2927145ae3eSNattuvetty Bhavyan spi->pgr_sms_header.sms_id = SMS_ID_PGR_INFO;
2937145ae3eSNattuvetty Bhavyan spi->pgr_sms_header.sms_data_order = SMS_DATA_ORDER;
2947145ae3eSNattuvetty Bhavyan
2957145ae3eSNattuvetty Bhavyan ret = sbd_write_meta_section(slu, (sm_section_hdr_t *)spi);
2967145ae3eSNattuvetty Bhavyan kmem_free(spi, sz);
2977145ae3eSNattuvetty Bhavyan return (ret);
2987145ae3eSNattuvetty Bhavyan }
2997145ae3eSNattuvetty Bhavyan
300*61dfa509SRick McNeal /*
301*61dfa509SRick McNeal * Evaluate common cases where a PERSISTENT RESERVE OUT CDB handler should call
302*61dfa509SRick McNeal * sbd_pgr_meta_write().
303*61dfa509SRick McNeal */
304*61dfa509SRick McNeal static boolean_t
sbd_pgr_should_save(sbd_lu_t * slu)305*61dfa509SRick McNeal sbd_pgr_should_save(sbd_lu_t *slu)
306*61dfa509SRick McNeal {
307*61dfa509SRick McNeal sbd_pgr_t *pgr = slu->sl_pgr;
308*61dfa509SRick McNeal
309*61dfa509SRick McNeal if (stmf_is_pgr_aptpl_always() == B_TRUE ||
310*61dfa509SRick McNeal (pgr->pgr_flags & (SBD_PGR_APTPL)))
311*61dfa509SRick McNeal return (B_TRUE);
312*61dfa509SRick McNeal else
313*61dfa509SRick McNeal return (B_FALSE);
314*61dfa509SRick McNeal }
315*61dfa509SRick McNeal
3168fe96085Stim szeto sbd_status_t
sbd_pgr_meta_load(sbd_lu_t * slu)3178fe96085Stim szeto sbd_pgr_meta_load(sbd_lu_t *slu)
3188fe96085Stim szeto {
3198fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
3208fe96085Stim szeto sbd_pgr_info_t *spi = NULL;
3218fe96085Stim szeto sbd_pgr_key_t *key, *last_key = NULL;
3228fe96085Stim szeto sbd_pgr_key_info_t *spi_key;
3238fe96085Stim szeto sbd_status_t ret = SBD_SUCCESS;
324716c1805SNattuvetty Bhavyan scsi_devid_desc_t *lpt;
3258fe96085Stim szeto uint8_t *ptr, *keyoffset, *endoffset;
3268fe96085Stim szeto uint32_t i, sz;
3278fe96085Stim szeto
3288fe96085Stim szeto ret = sbd_read_meta_section(slu, (sm_section_hdr_t **)&spi,
3298fe96085Stim szeto SMS_ID_PGR_INFO);
3308fe96085Stim szeto if (ret != SBD_SUCCESS) {
3318fe96085Stim szeto /* No PGR section found, means volume made before PGR support */
3328fe96085Stim szeto if (ret == SBD_NOT_FOUND) {
3338fe96085Stim szeto /* So just create a default PGR section */
3347145ae3eSNattuvetty Bhavyan ret = sbd_pgr_meta_init(slu);
3358fe96085Stim szeto }
3368fe96085Stim szeto return (ret);
3378fe96085Stim szeto }
338716c1805SNattuvetty Bhavyan
3398fe96085Stim szeto if (spi->pgr_data_order != SMS_DATA_ORDER) {
3408fe96085Stim szeto sbd_swap_pgr_info(spi);
3418fe96085Stim szeto }
3428fe96085Stim szeto
3438fe96085Stim szeto pgr->pgr_flags = spi->pgr_flags;
344*61dfa509SRick McNeal /*
345*61dfa509SRick McNeal * We reload APTPL reservations when:
346*61dfa509SRick McNeal * 1. Global override is enabled
347*61dfa509SRick McNeal * 2. APTPL was explicitly asserted in the PERSISTENT RESERVE OUT CDB
348*61dfa509SRick McNeal */
349*61dfa509SRick McNeal if (stmf_is_pgr_aptpl_always() || (pgr->pgr_flags & SBD_PGR_APTPL)) {
3508fe96085Stim szeto pgr->pgr_rsv_type = spi->pgr_rsv_type;
3518fe96085Stim szeto pgr->pgr_rsv_scope = spi->pgr_rsv_scope;
3528fe96085Stim szeto } else {
3538fe96085Stim szeto PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
3548fe96085Stim szeto }
355716c1805SNattuvetty Bhavyan
3568fe96085Stim szeto PGR_CLEAR_FLAG(slu->sl_pgr->pgr_flags, SBD_PGR_ALL_KEYS_HAS_IT);
3578fe96085Stim szeto
3588fe96085Stim szeto endoffset = (uint8_t *)spi;
3598fe96085Stim szeto endoffset += spi->pgr_sms_header.sms_size;
3608fe96085Stim szeto keyoffset = (uint8_t *)(spi + 1);
3618fe96085Stim szeto for (i = 1; i <= spi->pgr_numkeys; i++) {
3628fe96085Stim szeto
3638fe96085Stim szeto spi_key = (sbd_pgr_key_info_t *)keyoffset;
3648fe96085Stim szeto if (spi->pgr_data_order != SMS_DATA_ORDER) {
3658fe96085Stim szeto sbd_swap_pgrkey_info(spi_key);
3668fe96085Stim szeto }
3678fe96085Stim szeto
3688fe96085Stim szeto /* Calculate the size and next offset */
369716c1805SNattuvetty Bhavyan sz = ALIGNED_TO_8BYTE_BOUNDARY(sizeof (sbd_pgr_key_info_t) - 1 +
3708fe96085Stim szeto spi_key->pgr_key_lpt_len + spi_key->pgr_key_rpt_len);
3718fe96085Stim szeto keyoffset += sz;
3728fe96085Stim szeto
3738fe96085Stim szeto /* Validate the key fields */
3748fe96085Stim szeto if (spi_key->pgr_key_rpt_len == 0 || endoffset < keyoffset ||
3758fe96085Stim szeto (spi_key->pgr_key_lpt_len == 0 &&
3768fe96085Stim szeto !(spi_key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT))) {
377716c1805SNattuvetty Bhavyan ret = SBD_META_CORRUPTED;
378716c1805SNattuvetty Bhavyan goto sbd_pgr_meta_load_failed;
3798fe96085Stim szeto }
3808fe96085Stim szeto
3818fe96085Stim szeto lpt = (scsi_devid_desc_t *)spi_key->pgr_key_it;
3828fe96085Stim szeto ptr = (uint8_t *)spi_key->pgr_key_it + spi_key->pgr_key_lpt_len;
383716c1805SNattuvetty Bhavyan
384716c1805SNattuvetty Bhavyan if (spi_key->pgr_key_flags & SBD_PGR_KEY_TPT_ID_FLAG) {
385716c1805SNattuvetty Bhavyan uint16_t tpd_len = 0;
386716c1805SNattuvetty Bhavyan
387716c1805SNattuvetty Bhavyan if (!stmf_scsilib_tptid_validate(
388716c1805SNattuvetty Bhavyan (scsi_transport_id_t *)ptr,
389716c1805SNattuvetty Bhavyan spi_key->pgr_key_rpt_len, &tpd_len)) {
390716c1805SNattuvetty Bhavyan ret = SBD_META_CORRUPTED;
391716c1805SNattuvetty Bhavyan goto sbd_pgr_meta_load_failed;
392716c1805SNattuvetty Bhavyan }
393716c1805SNattuvetty Bhavyan if (tpd_len != spi_key->pgr_key_rpt_len) {
394716c1805SNattuvetty Bhavyan ret = SBD_META_CORRUPTED;
395716c1805SNattuvetty Bhavyan goto sbd_pgr_meta_load_failed;
396716c1805SNattuvetty Bhavyan }
397716c1805SNattuvetty Bhavyan key = sbd_pgr_key_alloc(lpt, (scsi_transport_id_t *)ptr,
398716c1805SNattuvetty Bhavyan spi_key->pgr_key_lpt_len, spi_key->pgr_key_rpt_len);
399716c1805SNattuvetty Bhavyan } else {
400716c1805SNattuvetty Bhavyan stmf_remote_port_t *rpt = NULL;
401716c1805SNattuvetty Bhavyan
402716c1805SNattuvetty Bhavyan /*
403716c1805SNattuvetty Bhavyan * This block is executed only if the metadata was
404716c1805SNattuvetty Bhavyan * stored before the implementation of Transport ID
405716c1805SNattuvetty Bhavyan * support.
406716c1805SNattuvetty Bhavyan */
407716c1805SNattuvetty Bhavyan rpt = stmf_scsilib_devid_to_remote_port(
408716c1805SNattuvetty Bhavyan (scsi_devid_desc_t *)ptr);
409716c1805SNattuvetty Bhavyan if (rpt == NULL) {
410716c1805SNattuvetty Bhavyan ret = SBD_META_CORRUPTED;
411716c1805SNattuvetty Bhavyan goto sbd_pgr_meta_load_failed;
412716c1805SNattuvetty Bhavyan }
413716c1805SNattuvetty Bhavyan key = sbd_pgr_key_alloc(lpt, rpt->rport_tptid,
414716c1805SNattuvetty Bhavyan spi_key->pgr_key_lpt_len, rpt->rport_tptid_sz);
415716c1805SNattuvetty Bhavyan stmf_remote_port_free(rpt);
416716c1805SNattuvetty Bhavyan }
4178fe96085Stim szeto
4188fe96085Stim szeto key->pgr_key = spi_key->pgr_key;
4198fe96085Stim szeto key->pgr_key_flags = spi_key->pgr_key_flags;
4208fe96085Stim szeto key->pgr_key_prev = last_key;
4218fe96085Stim szeto
4228fe96085Stim szeto if (last_key) {
4238fe96085Stim szeto last_key->pgr_key_next = key;
4248fe96085Stim szeto } else {
4258fe96085Stim szeto pgr->pgr_keylist = key;
4268fe96085Stim szeto }
4278fe96085Stim szeto last_key = key;
4288fe96085Stim szeto
4298fe96085Stim szeto if ((pgr->pgr_flags & SBD_PGR_RSVD_ONE) &&
4308fe96085Stim szeto (i == spi->pgr_rsvholder_indx)) {
4318fe96085Stim szeto pgr->pgr_rsvholder = key;
4328fe96085Stim szeto }
4338fe96085Stim szeto }
4348fe96085Stim szeto
4358fe96085Stim szeto kmem_free(spi, spi->pgr_sms_header.sms_size);
4368fe96085Stim szeto return (ret);
437716c1805SNattuvetty Bhavyan
438716c1805SNattuvetty Bhavyan sbd_pgr_meta_load_failed:
439716c1805SNattuvetty Bhavyan {
440716c1805SNattuvetty Bhavyan char *lun_name = sbd_get_devid_string(slu);
441716c1805SNattuvetty Bhavyan sbd_pgr_keylist_dealloc(slu);
442716c1805SNattuvetty Bhavyan kmem_free(spi, spi->pgr_sms_header.sms_size);
443716c1805SNattuvetty Bhavyan cmn_err(CE_WARN, "sbd_pgr_meta_load: Failed to load PGR meta data "
444716c1805SNattuvetty Bhavyan "for lun %s.", lun_name);
445716c1805SNattuvetty Bhavyan kmem_free(lun_name, strlen(lun_name) + 1);
446716c1805SNattuvetty Bhavyan return (ret);
447716c1805SNattuvetty Bhavyan }
4488fe96085Stim szeto }
4498fe96085Stim szeto
4508fe96085Stim szeto sbd_status_t
sbd_pgr_meta_write(sbd_lu_t * slu)4518fe96085Stim szeto sbd_pgr_meta_write(sbd_lu_t *slu)
4528fe96085Stim szeto {
4538fe96085Stim szeto sbd_pgr_key_t *key;
4548fe96085Stim szeto sbd_pgr_info_t *spi;
4558fe96085Stim szeto sbd_pgr_key_info_t *spi_key;
4568fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
4578fe96085Stim szeto sbd_status_t ret = SBD_SUCCESS;
4588fe96085Stim szeto uint32_t sz, totalsz;
4598fe96085Stim szeto
4608fe96085Stim szeto /* Calculate total pgr meta section size needed */
4618fe96085Stim szeto sz = sizeof (sbd_pgr_info_t);
462*61dfa509SRick McNeal if ((pgr->pgr_flags & SBD_PGR_APTPL) || stmf_is_pgr_aptpl_always()) {
4638fe96085Stim szeto key = pgr->pgr_keylist;
4648fe96085Stim szeto while (key != NULL) {
465716c1805SNattuvetty Bhavyan sz = ALIGNED_TO_8BYTE_BOUNDARY(sz +
4668fe96085Stim szeto sizeof (sbd_pgr_key_info_t) - 1 +
4678fe96085Stim szeto key->pgr_key_lpt_len + key->pgr_key_rpt_len);
4688fe96085Stim szeto key = key->pgr_key_next;
4698fe96085Stim szeto }
4708fe96085Stim szeto }
4718fe96085Stim szeto totalsz = sz;
4728fe96085Stim szeto
4738fe96085Stim szeto spi = (sbd_pgr_info_t *)kmem_zalloc(totalsz, KM_SLEEP);
4748fe96085Stim szeto spi->pgr_flags = pgr->pgr_flags;
4758fe96085Stim szeto spi->pgr_rsv_type = pgr->pgr_rsv_type;
4768fe96085Stim szeto spi->pgr_rsv_scope = pgr->pgr_rsv_scope;
4778fe96085Stim szeto spi->pgr_data_order = SMS_DATA_ORDER;
4788fe96085Stim szeto spi->pgr_numkeys = 0;
4798fe96085Stim szeto
4808fe96085Stim szeto spi->pgr_sms_header.sms_size = totalsz;
4818fe96085Stim szeto spi->pgr_sms_header.sms_id = SMS_ID_PGR_INFO;
4828fe96085Stim szeto spi->pgr_sms_header.sms_data_order = SMS_DATA_ORDER;
4838fe96085Stim szeto
484*61dfa509SRick McNeal if ((pgr->pgr_flags & SBD_PGR_APTPL) || stmf_is_pgr_aptpl_always()) {
4858fe96085Stim szeto uint8_t *ptr;
4868fe96085Stim szeto key = pgr->pgr_keylist;
4878fe96085Stim szeto sz = sizeof (sbd_pgr_info_t);
4888fe96085Stim szeto while (key != NULL) {
4898fe96085Stim szeto spi_key = (sbd_pgr_key_info_t *)((uint8_t *)spi + sz);
4908fe96085Stim szeto spi_key->pgr_key = key->pgr_key;
491716c1805SNattuvetty Bhavyan spi_key->pgr_key_flags = key->pgr_key_flags;
4928fe96085Stim szeto spi_key->pgr_key_lpt_len = key->pgr_key_lpt_len;
4938fe96085Stim szeto spi_key->pgr_key_rpt_len = key->pgr_key_rpt_len;
4948fe96085Stim szeto ptr = spi_key->pgr_key_it;
4958fe96085Stim szeto bcopy(key->pgr_key_lpt_id, ptr, key->pgr_key_lpt_len);
4968fe96085Stim szeto ptr += key->pgr_key_lpt_len;
4978fe96085Stim szeto bcopy(key->pgr_key_rpt_id, ptr, key->pgr_key_rpt_len);
4988fe96085Stim szeto
4998fe96085Stim szeto spi->pgr_numkeys++;
5008fe96085Stim szeto if (key == pgr->pgr_rsvholder) {
5018fe96085Stim szeto spi->pgr_rsvholder_indx = spi->pgr_numkeys;
5028fe96085Stim szeto }
5038fe96085Stim szeto
504716c1805SNattuvetty Bhavyan sz = ALIGNED_TO_8BYTE_BOUNDARY(sz +
5058fe96085Stim szeto sizeof (sbd_pgr_key_info_t) - 1 +
5068fe96085Stim szeto key->pgr_key_lpt_len + key->pgr_key_rpt_len);
5078fe96085Stim szeto key = key->pgr_key_next;
5088fe96085Stim szeto }
5098fe96085Stim szeto }
510*61dfa509SRick McNeal rw_downgrade(&pgr->pgr_lock);
5118fe96085Stim szeto ret = sbd_write_meta_section(slu, (sm_section_hdr_t *)spi);
512*61dfa509SRick McNeal if (!rw_tryupgrade(&pgr->pgr_lock)) {
513*61dfa509SRick McNeal rw_exit(&pgr->pgr_lock);
514*61dfa509SRick McNeal rw_enter(&pgr->pgr_lock, RW_WRITER);
515*61dfa509SRick McNeal }
5168fe96085Stim szeto kmem_free(spi, totalsz);
5178fe96085Stim szeto if (ret != SBD_SUCCESS) {
5188fe96085Stim szeto sbd_pgr_key_t *tmp_list;
5198fe96085Stim szeto tmp_list = pgr->pgr_keylist;
5208fe96085Stim szeto pgr->pgr_keylist = NULL;
5218fe96085Stim szeto if (sbd_pgr_meta_load(slu) != SBD_SUCCESS) {
5228fe96085Stim szeto char *lun_name = sbd_get_devid_string(slu);
5238fe96085Stim szeto cmn_err(CE_WARN, "sbd_pgr_meta_write: Failed to revert "
5248fe96085Stim szeto "back to existing PGR state after meta write "
5258fe96085Stim szeto "failure, may cause PGR inconsistancy for lun %s.",
5268fe96085Stim szeto lun_name);
5278fe96085Stim szeto kmem_free(lun_name, strlen(lun_name) + 1);
5288fe96085Stim szeto pgr->pgr_keylist = tmp_list;
5298fe96085Stim szeto } else {
5308fe96085Stim szeto key = pgr->pgr_keylist;
5318fe96085Stim szeto pgr->pgr_keylist = tmp_list;
5328fe96085Stim szeto sbd_pgr_set_pgr_check_flag(slu, B_TRUE);
5338fe96085Stim szeto sbd_pgr_keylist_dealloc(slu);
5348fe96085Stim szeto pgr->pgr_keylist = key;
5358fe96085Stim szeto }
5368fe96085Stim szeto
5378fe96085Stim szeto }
5388fe96085Stim szeto return (ret);
5398fe96085Stim szeto }
5408fe96085Stim szeto
5418fe96085Stim szeto static sbd_pgr_key_t *
sbd_pgr_key_alloc(scsi_devid_desc_t * lptid,scsi_transport_id_t * rptid,int16_t lpt_len,int16_t rpt_len)542716c1805SNattuvetty Bhavyan sbd_pgr_key_alloc(scsi_devid_desc_t *lptid, scsi_transport_id_t *rptid,
543*61dfa509SRick McNeal int16_t lpt_len, int16_t rpt_len)
5448fe96085Stim szeto {
5458fe96085Stim szeto sbd_pgr_key_t *key;
5468fe96085Stim szeto
5478fe96085Stim szeto key = (sbd_pgr_key_t *)kmem_zalloc(sizeof (sbd_pgr_key_t), KM_SLEEP);
5488fe96085Stim szeto
549716c1805SNattuvetty Bhavyan if (lptid && lpt_len >= sizeof (scsi_devid_desc_t)) {
5508fe96085Stim szeto key->pgr_key_lpt_len = lpt_len;
5518fe96085Stim szeto key->pgr_key_lpt_id = (scsi_devid_desc_t *)kmem_zalloc(
5528fe96085Stim szeto lpt_len, KM_SLEEP);
5538fe96085Stim szeto bcopy(lptid, key->pgr_key_lpt_id, lpt_len);
5548fe96085Stim szeto }
5558fe96085Stim szeto
556716c1805SNattuvetty Bhavyan if (rptid && rpt_len >= sizeof (scsi_transport_id_t)) {
557716c1805SNattuvetty Bhavyan key->pgr_key_flags |= SBD_PGR_KEY_TPT_ID_FLAG;
5588fe96085Stim szeto key->pgr_key_rpt_len = rpt_len;
559716c1805SNattuvetty Bhavyan key->pgr_key_rpt_id = (scsi_transport_id_t *)kmem_zalloc(
5608fe96085Stim szeto rpt_len, KM_SLEEP);
5618fe96085Stim szeto bcopy(rptid, key->pgr_key_rpt_id, rpt_len);
5628fe96085Stim szeto }
5638fe96085Stim szeto
5648fe96085Stim szeto return (key);
5658fe96085Stim szeto }
5668fe96085Stim szeto
5678fe96085Stim szeto static void
sbd_pgr_key_free(sbd_pgr_key_t * key)5688fe96085Stim szeto sbd_pgr_key_free(sbd_pgr_key_t *key)
5698fe96085Stim szeto {
5708fe96085Stim szeto if (key->pgr_key_lpt_id) {
5718fe96085Stim szeto kmem_free(key->pgr_key_lpt_id, key->pgr_key_lpt_len);
5728fe96085Stim szeto }
5738fe96085Stim szeto if (key->pgr_key_rpt_id) {
5748fe96085Stim szeto kmem_free(key->pgr_key_rpt_id, key->pgr_key_rpt_len);
5758fe96085Stim szeto }
5768fe96085Stim szeto kmem_free(key, sizeof (sbd_pgr_key_t));
5778fe96085Stim szeto }
5788fe96085Stim szeto
5798fe96085Stim szeto void
sbd_pgr_keylist_dealloc(sbd_lu_t * slu)5808fe96085Stim szeto sbd_pgr_keylist_dealloc(sbd_lu_t *slu)
5818fe96085Stim szeto {
5828fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
5838fe96085Stim szeto sbd_it_data_t *it;
5848fe96085Stim szeto sbd_pgr_key_t *key;
5858fe96085Stim szeto
5868fe96085Stim szeto mutex_enter(&slu->sl_lock);
5878fe96085Stim szeto for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
5888fe96085Stim szeto it->pgr_key_ptr = NULL;
5898fe96085Stim szeto }
5908fe96085Stim szeto mutex_exit(&slu->sl_lock);
5918fe96085Stim szeto
5928fe96085Stim szeto while (pgr->pgr_keylist != NULL) {
5938fe96085Stim szeto key = pgr->pgr_keylist;
5948fe96085Stim szeto pgr->pgr_keylist = key->pgr_key_next;
5958fe96085Stim szeto sbd_pgr_key_free(key);
5968fe96085Stim szeto }
5978fe96085Stim szeto }
5988fe96085Stim szeto
59945039663SJohn Forte /*
60045039663SJohn Forte * Reset and clear the keys, Can be used in the case of Lun Reset
60145039663SJohn Forte */
60245039663SJohn Forte void
sbd_pgr_reset(sbd_lu_t * slu)60345039663SJohn Forte sbd_pgr_reset(sbd_lu_t *slu)
60445039663SJohn Forte {
60545039663SJohn Forte sbd_pgr_t *pgr = slu->sl_pgr;
60645039663SJohn Forte
60745039663SJohn Forte rw_enter(&pgr->pgr_lock, RW_WRITER);
608*61dfa509SRick McNeal if (!(pgr->pgr_flags & SBD_PGR_APTPL) &&
609*61dfa509SRick McNeal stmf_is_pgr_aptpl_always() == B_FALSE) {
61045039663SJohn Forte sbd_pgr_keylist_dealloc(slu);
61145039663SJohn Forte pgr->pgr_PRgeneration = 0;
61245039663SJohn Forte pgr->pgr_rsvholder = NULL;
61345039663SJohn Forte pgr->pgr_rsv_type = 0;
61445039663SJohn Forte pgr->pgr_flags = 0;
61545039663SJohn Forte }
61645039663SJohn Forte rw_exit(&pgr->pgr_lock);
61745039663SJohn Forte }
61845039663SJohn Forte
6198fe96085Stim szeto static void
sbd_pgr_remove_key(sbd_lu_t * slu,sbd_pgr_key_t * key)6208fe96085Stim szeto sbd_pgr_remove_key(sbd_lu_t *slu, sbd_pgr_key_t *key)
6218fe96085Stim szeto {
6228fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
6238fe96085Stim szeto sbd_it_data_t *it;
6248fe96085Stim szeto
6258fe96085Stim szeto ASSERT(key);
6268fe96085Stim szeto
6278fe96085Stim szeto mutex_enter(&slu->sl_lock);
6288fe96085Stim szeto if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
6298fe96085Stim szeto for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
6308fe96085Stim szeto if (it->pgr_key_ptr == key)
6318fe96085Stim szeto it->pgr_key_ptr = NULL;
6328fe96085Stim szeto }
6338fe96085Stim szeto } else {
6348fe96085Stim szeto if (key->pgr_key_it) {
6358fe96085Stim szeto key->pgr_key_it->pgr_key_ptr = NULL;
6368fe96085Stim szeto }
6378fe96085Stim szeto }
6388fe96085Stim szeto mutex_exit(&slu->sl_lock);
6398fe96085Stim szeto
6408fe96085Stim szeto if (key->pgr_key_next) {
6418fe96085Stim szeto key->pgr_key_next->pgr_key_prev = key->pgr_key_prev;
6428fe96085Stim szeto }
6438fe96085Stim szeto if (key->pgr_key_prev) {
6448fe96085Stim szeto key->pgr_key_prev->pgr_key_next = key->pgr_key_next;
6458fe96085Stim szeto } else {
6468fe96085Stim szeto pgr->pgr_keylist = key->pgr_key_next;
6478fe96085Stim szeto }
6488fe96085Stim szeto
6498fe96085Stim szeto sbd_pgr_key_free(key);
6508fe96085Stim szeto }
6518fe96085Stim szeto
6528fe96085Stim szeto /*
6538fe96085Stim szeto * Remove keys depends on boolean variable "match"
6548fe96085Stim szeto * match = B_TRUE ==> Remove all keys which matches the given svc_key,
6558fe96085Stim szeto * except for IT equal to given "my_it".
6568fe96085Stim szeto * match = B_FALSE ==> Remove all keys which does not matches the svc_key,
6578fe96085Stim szeto * except for IT equal to given "my_it"
6588fe96085Stim szeto */
6598fe96085Stim szeto static uint32_t
sbd_pgr_remove_keys(sbd_lu_t * slu,sbd_it_data_t * my_it,sbd_pgr_key_t * my_key,uint64_t svc_key,boolean_t match)6608fe96085Stim szeto sbd_pgr_remove_keys(sbd_lu_t *slu, sbd_it_data_t *my_it, sbd_pgr_key_t *my_key,
661*61dfa509SRick McNeal uint64_t svc_key, boolean_t match)
6628fe96085Stim szeto {
6638fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
6648fe96085Stim szeto sbd_it_data_t *it;
6658fe96085Stim szeto sbd_pgr_key_t *nextkey, *key = pgr->pgr_keylist;
6668fe96085Stim szeto uint32_t count = 0;
6678fe96085Stim szeto
6688fe96085Stim szeto while (key) {
6698fe96085Stim szeto
6708fe96085Stim szeto nextkey = key->pgr_key_next;
6718fe96085Stim szeto if (match == B_TRUE && key->pgr_key == svc_key ||
6728fe96085Stim szeto match == B_FALSE && key->pgr_key != svc_key) {
6738fe96085Stim szeto /*
6748fe96085Stim szeto * If the key is registered by current IT keep it,
6758fe96085Stim szeto * but just remove pgr pointers from other ITs
6768fe96085Stim szeto */
6778fe96085Stim szeto if (key == my_key) {
6788fe96085Stim szeto mutex_enter(&slu->sl_lock);
6798fe96085Stim szeto for (it = slu->sl_it_list; it != NULL;
6808fe96085Stim szeto it = it->sbd_it_next) {
6818fe96085Stim szeto if (it->pgr_key_ptr == key &&
6828fe96085Stim szeto it != my_it)
6838fe96085Stim szeto it->pgr_key_ptr = NULL;
6848fe96085Stim szeto }
6858fe96085Stim szeto mutex_exit(&slu->sl_lock);
6868fe96085Stim szeto } else {
6878fe96085Stim szeto sbd_pgr_remove_key(slu, key);
6888fe96085Stim szeto }
6898fe96085Stim szeto count++;
6908fe96085Stim szeto }
6918fe96085Stim szeto key = nextkey;
6928fe96085Stim szeto }
6938fe96085Stim szeto return (count);
6948fe96085Stim szeto }
6958fe96085Stim szeto
6968fe96085Stim szeto static void
sbd_pgr_set_ua_conditions(sbd_lu_t * slu,sbd_it_data_t * my_it,uint8_t ua)6978fe96085Stim szeto sbd_pgr_set_ua_conditions(sbd_lu_t *slu, sbd_it_data_t *my_it, uint8_t ua)
6988fe96085Stim szeto {
6998fe96085Stim szeto sbd_it_data_t *it;
7008fe96085Stim szeto
7018fe96085Stim szeto mutex_enter(&slu->sl_lock);
7028fe96085Stim szeto for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
7038fe96085Stim szeto if (it == my_it)
7048fe96085Stim szeto continue;
7058fe96085Stim szeto it->sbd_it_ua_conditions |= ua;
7068fe96085Stim szeto }
7078fe96085Stim szeto mutex_exit(&slu->sl_lock);
7088fe96085Stim szeto }
7098fe96085Stim szeto
7108fe96085Stim szeto /*
7118fe96085Stim szeto * Set the SBD_IT_PGR_CHECK_FLAG depends on variable "registered". See Below.
7128fe96085Stim szeto *
7138fe96085Stim szeto * If
7148fe96085Stim szeto * registered is B_TRUE => Set PGR_CHECK_FLAG on all registered IT nexus
7158fe96085Stim szeto * registered is B_FALSE => Set PGR_CHECK_FLAG on all unregistered IT nexus
7168fe96085Stim szeto */
7178fe96085Stim szeto static void
sbd_pgr_set_pgr_check_flag(sbd_lu_t * slu,boolean_t registered)7188fe96085Stim szeto sbd_pgr_set_pgr_check_flag(sbd_lu_t *slu, boolean_t registered)
7198fe96085Stim szeto {
7208fe96085Stim szeto sbd_it_data_t *it;
7218fe96085Stim szeto
7228fe96085Stim szeto PGR_CLEAR_FLAG(slu->sl_pgr->pgr_flags, SBD_PGR_ALL_KEYS_HAS_IT);
7238fe96085Stim szeto mutex_enter(&slu->sl_lock);
7248fe96085Stim szeto for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
7258fe96085Stim szeto if (it->pgr_key_ptr) {
7268fe96085Stim szeto if (registered == B_TRUE) {
7278fe96085Stim szeto it->sbd_it_flags |= SBD_IT_PGR_CHECK_FLAG;
7288fe96085Stim szeto }
7298fe96085Stim szeto } else {
7308fe96085Stim szeto if (registered == B_FALSE)
7318fe96085Stim szeto it->sbd_it_flags |= SBD_IT_PGR_CHECK_FLAG;
7328fe96085Stim szeto }
7338fe96085Stim szeto }
7348fe96085Stim szeto mutex_exit(&slu->sl_lock);
7358fe96085Stim szeto }
7368fe96085Stim szeto
7378fe96085Stim szeto static boolean_t
sbd_pgr_key_compare(sbd_pgr_key_t * key,scsi_devid_desc_t * lpt,stmf_remote_port_t * rpt)7388fe96085Stim szeto sbd_pgr_key_compare(sbd_pgr_key_t *key, scsi_devid_desc_t *lpt,
739*61dfa509SRick McNeal stmf_remote_port_t *rpt)
7408fe96085Stim szeto {
7418fe96085Stim szeto scsi_devid_desc_t *id;
7428fe96085Stim szeto
743716c1805SNattuvetty Bhavyan if (!stmf_scsilib_tptid_compare(rpt->rport_tptid, key->pgr_key_rpt_id))
7448fe96085Stim szeto return (B_FALSE);
7458fe96085Stim szeto
7468fe96085Stim szeto /*
7478fe96085Stim szeto * You can skip target port name comparison if ALL_TG_PT flag
7488fe96085Stim szeto * is set for this key;
7498fe96085Stim szeto */
7508fe96085Stim szeto if (!(key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) && lpt) {
7518fe96085Stim szeto id = key->pgr_key_lpt_id;
7528fe96085Stim szeto if ((lpt->ident_length != id->ident_length) ||
7538fe96085Stim szeto (memcmp(id->ident, lpt->ident, id->ident_length) != 0)) {
754716c1805SNattuvetty Bhavyan return (B_FALSE);
7558fe96085Stim szeto }
7568fe96085Stim szeto }
7578fe96085Stim szeto return (B_TRUE);
7588fe96085Stim szeto }
7598fe96085Stim szeto
7608fe96085Stim szeto
7618fe96085Stim szeto sbd_pgr_key_t *
sbd_pgr_key_registered(sbd_pgr_t * pgr,scsi_devid_desc_t * lpt,stmf_remote_port_t * rpt)7628fe96085Stim szeto sbd_pgr_key_registered(sbd_pgr_t *pgr, scsi_devid_desc_t *lpt,
763*61dfa509SRick McNeal stmf_remote_port_t *rpt)
7648fe96085Stim szeto {
7658fe96085Stim szeto sbd_pgr_key_t *key;
7668fe96085Stim szeto
7678fe96085Stim szeto for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next) {
7688fe96085Stim szeto if (sbd_pgr_key_compare(key, lpt, rpt) == B_TRUE) {
7698fe96085Stim szeto return (key);
7708fe96085Stim szeto }
7718fe96085Stim szeto }
7728fe96085Stim szeto return (NULL);
7738fe96085Stim szeto }
7748fe96085Stim szeto
7758fe96085Stim szeto void
sbd_pgr_initialize_it(scsi_task_t * task,sbd_it_data_t * it)776f4e76ddfSNattuvetty Bhavyan sbd_pgr_initialize_it(scsi_task_t *task, sbd_it_data_t *it)
7778fe96085Stim szeto {
7788fe96085Stim szeto sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
779f4e76ddfSNattuvetty Bhavyan stmf_scsi_session_t *ses = task->task_session;
7808fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
7818fe96085Stim szeto sbd_pgr_key_t *key;
782716c1805SNattuvetty Bhavyan scsi_devid_desc_t *lpt, *id;
783716c1805SNattuvetty Bhavyan stmf_remote_port_t *rpt;
7848fe96085Stim szeto
7858fe96085Stim szeto if (pgr->pgr_flags & SBD_PGR_ALL_KEYS_HAS_IT)
7868fe96085Stim szeto return;
787716c1805SNattuvetty Bhavyan
788716c1805SNattuvetty Bhavyan rpt = ses->ss_rport;
7898fe96085Stim szeto lpt = ses->ss_lport->lport_id;
7908fe96085Stim szeto
7918fe96085Stim szeto rw_enter(&pgr->pgr_lock, RW_WRITER);
7928fe96085Stim szeto PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_ALL_KEYS_HAS_IT);
7938fe96085Stim szeto for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next) {
7948fe96085Stim szeto
7958fe96085Stim szeto if ((!(key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT)) &&
7968fe96085Stim szeto key->pgr_key_it != NULL)
7978fe96085Stim szeto continue;
7988fe96085Stim szeto /*
7998fe96085Stim szeto * SBD_PGR_ALL_KEYS_HAS_IT is set only if no single key
8008fe96085Stim szeto * in the list has SBD_PGR_KEY_ALL_TG_PT flag set and
8018fe96085Stim szeto * pgr_key_it all keys points to some IT
8028fe96085Stim szeto */
8038fe96085Stim szeto PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_ALL_KEYS_HAS_IT);
8048fe96085Stim szeto
8058fe96085Stim szeto /* Check if key matches with given lpt rpt combination */
8068fe96085Stim szeto if (sbd_pgr_key_compare(key, lpt, rpt) == B_FALSE)
8078fe96085Stim szeto continue;
8088fe96085Stim szeto
8098fe96085Stim szeto /* IT nexus devid information matches with this key */
8108fe96085Stim szeto if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
8118fe96085Stim szeto /*
8128fe96085Stim szeto * If ALL_TG_PT is set, pgr_key_it will point to NULL,
8138fe96085Stim szeto * unless pgr->pgr_rsvholder pointing to this key.
8148fe96085Stim szeto * In that case, pgr_key_it should point to the IT
8158fe96085Stim szeto * which initiated that reservation.
8168fe96085Stim szeto */
8178fe96085Stim szeto if (pgr->pgr_rsvholder == key) {
8188fe96085Stim szeto id = key->pgr_key_lpt_id;
8198fe96085Stim szeto if (lpt->ident_length == id->ident_length) {
8208fe96085Stim szeto if (memcmp(id->ident, lpt->ident,
8218fe96085Stim szeto id->ident_length) == 0)
8228fe96085Stim szeto key->pgr_key_it = it;
8238fe96085Stim szeto }
8248fe96085Stim szeto }
8258fe96085Stim szeto
8268fe96085Stim szeto } else {
8278fe96085Stim szeto key->pgr_key_it = it;
8288fe96085Stim szeto }
8298fe96085Stim szeto
8308fe96085Stim szeto mutex_enter(&slu->sl_lock);
8318fe96085Stim szeto it->pgr_key_ptr = key;
8328fe96085Stim szeto mutex_exit(&slu->sl_lock);
8338fe96085Stim szeto rw_exit(&pgr->pgr_lock);
8348fe96085Stim szeto return;
8358fe96085Stim szeto }
8368fe96085Stim szeto rw_exit(&pgr->pgr_lock);
8378fe96085Stim szeto }
8388fe96085Stim szeto
8398fe96085Stim szeto /*
8408fe96085Stim szeto * Check for any PGR Reservation conflict. return 0 if access allowed
8418fe96085Stim szeto */
8428fe96085Stim szeto int
sbd_pgr_reservation_conflict(scsi_task_t * task,sbd_lu_t * slu)843*61dfa509SRick McNeal sbd_pgr_reservation_conflict(scsi_task_t *task, sbd_lu_t *slu)
8448fe96085Stim szeto {
8458fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
8468fe96085Stim szeto sbd_it_data_t *it = (sbd_it_data_t *)task->task_lu_itl_handle;
8478fe96085Stim szeto
8488fe96085Stim szeto /* If Registered */
8498fe96085Stim szeto if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS && it->pgr_key_ptr)
8508fe96085Stim szeto return (0);
8518fe96085Stim szeto
8528fe96085Stim szeto /* If you are registered */
8538fe96085Stim szeto if (pgr->pgr_flags & SBD_PGR_RSVD_ONE) {
8548fe96085Stim szeto rw_enter(&pgr->pgr_lock, RW_READER);
8558fe96085Stim szeto
8568fe96085Stim szeto /*
8578fe96085Stim szeto * Note: it->pgr_key_ptr is protected by sl_lock. Also,
8588fe96085Stim szeto * it is expected to change its value only with pgr_lock
8598fe96085Stim szeto * held. Hence we are safe to read its value without
8608fe96085Stim szeto * grabbing sl_lock. But make sure that the value used is
8618fe96085Stim szeto * not from registers by using "volatile" keyword.
8628fe96085Stim szeto * Since this funtion is in performance path, we may want
8638fe96085Stim szeto * to avoid grabbing sl_lock.
8648fe96085Stim szeto */
8658fe96085Stim szeto if ((volatile sbd_pgr_key_t *)it->pgr_key_ptr) {
8668fe96085Stim szeto /* If you are the reservation holder */
8678fe96085Stim szeto if (pgr->pgr_rsvholder == it->pgr_key_ptr &&
8688fe96085Stim szeto it->pgr_key_ptr->pgr_key_it == it) {
8698fe96085Stim szeto rw_exit(&pgr->pgr_lock);
8708fe96085Stim szeto return (0);
8718fe96085Stim szeto }
8728fe96085Stim szeto
8738fe96085Stim szeto /* If reserve type is not EX_AC */
8748fe96085Stim szeto if (pgr->pgr_rsv_type != PGR_TYPE_EX_AC) {
8758fe96085Stim szeto /* If reserve type is WR_EX allow read */
8768fe96085Stim szeto if (pgr->pgr_rsv_type == PGR_TYPE_WR_EX) {
8778fe96085Stim szeto if (PGR_READ_POSSIBLE_CMDS(
8788fe96085Stim szeto task->task_cdb[0])) {
8798fe96085Stim szeto rw_exit(&pgr->pgr_lock);
8808fe96085Stim szeto return (0);
8818fe96085Stim szeto }
8828fe96085Stim szeto /* For all other reserve types allow access */
8838fe96085Stim szeto } else {
8848fe96085Stim szeto rw_exit(&pgr->pgr_lock);
8858fe96085Stim szeto return (0);
8868fe96085Stim szeto }
8878fe96085Stim szeto }
8888fe96085Stim szeto
8898fe96085Stim szeto /* If registered, allow these commands */
8908fe96085Stim szeto if (PGR_REGISTERED_POSSIBLE_CMDS(task->task_cdb)) {
8918fe96085Stim szeto rw_exit(&pgr->pgr_lock);
8928fe96085Stim szeto return (0);
8938fe96085Stim szeto }
8948fe96085Stim szeto }
8958fe96085Stim szeto rw_exit(&pgr->pgr_lock);
8968fe96085Stim szeto }
8978fe96085Stim szeto
8988fe96085Stim szeto /* For any case, allow these commands */
8998fe96085Stim szeto if (PGR_CONFLICT_FREE_CMDS(task->task_cdb)) {
9008fe96085Stim szeto return (0);
9018fe96085Stim szeto }
9028fe96085Stim szeto
9038fe96085Stim szeto /* Give read access if reservation type WR_EX for registrants */
9048fe96085Stim szeto if (pgr->pgr_rsv_type == PGR_TYPE_WR_EX_RO ||
9058fe96085Stim szeto pgr->pgr_rsv_type == PGR_TYPE_WR_EX_AR) {
9068fe96085Stim szeto if (PGR_READ_POSSIBLE_CMDS(task->task_cdb[0]))
9078fe96085Stim szeto return (0);
9088fe96085Stim szeto }
9098fe96085Stim szeto
9108fe96085Stim szeto /* If you reached here, No access for you */
9118fe96085Stim szeto return (1);
9128fe96085Stim szeto }
9138fe96085Stim szeto
9148fe96085Stim szeto void
sbd_handle_pgr_in_cmd(scsi_task_t * task,stmf_data_buf_t * initial_dbuf)9158fe96085Stim szeto sbd_handle_pgr_in_cmd(scsi_task_t *task, stmf_data_buf_t *initial_dbuf)
9168fe96085Stim szeto {
9178fe96085Stim szeto
9188fe96085Stim szeto sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
9198fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
9208fe96085Stim szeto scsi_cdb_prin_t *pr_in;
9218fe96085Stim szeto
9228fe96085Stim szeto ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
9238fe96085Stim szeto
9248fe96085Stim szeto pr_in = (scsi_cdb_prin_t *)task->task_cdb;
9258fe96085Stim szeto
9268fe96085Stim szeto rw_enter(&pgr->pgr_lock, RW_READER);
9278fe96085Stim szeto switch (pr_in->action) {
9288fe96085Stim szeto case PR_IN_READ_KEYS:
9298fe96085Stim szeto sbd_pgr_in_read_keys(task, initial_dbuf);
9308fe96085Stim szeto break;
9318fe96085Stim szeto case PR_IN_READ_RESERVATION:
9328fe96085Stim szeto sbd_pgr_in_read_reservation(task, initial_dbuf);
9338fe96085Stim szeto break;
9348fe96085Stim szeto case PR_IN_REPORT_CAPABILITIES:
9358fe96085Stim szeto sbd_pgr_in_report_capabilities(task, initial_dbuf);
9368fe96085Stim szeto break;
9378fe96085Stim szeto case PR_IN_READ_FULL_STATUS:
9388fe96085Stim szeto sbd_pgr_in_read_full_status(task, initial_dbuf);
9398fe96085Stim szeto break;
9408fe96085Stim szeto default :
9418fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
9428fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
9438fe96085Stim szeto break;
9448fe96085Stim szeto }
9458fe96085Stim szeto rw_exit(&pgr->pgr_lock);
9468fe96085Stim szeto }
9478fe96085Stim szeto
9488fe96085Stim szeto void
sbd_handle_pgr_out_cmd(scsi_task_t * task,stmf_data_buf_t * initial_dbuf)9498fe96085Stim szeto sbd_handle_pgr_out_cmd(scsi_task_t *task, stmf_data_buf_t *initial_dbuf)
9508fe96085Stim szeto {
9518fe96085Stim szeto
9528fe96085Stim szeto scsi_cdb_prout_t *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
9538fe96085Stim szeto uint32_t param_len;
9548fe96085Stim szeto
9558fe96085Stim szeto ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_OUT);
9568fe96085Stim szeto
9578fe96085Stim szeto switch (pr_out->action) {
9588fe96085Stim szeto case PR_OUT_REGISTER:
9598fe96085Stim szeto case PR_OUT_RESERVE:
9608fe96085Stim szeto case PR_OUT_RELEASE:
9618fe96085Stim szeto case PR_OUT_CLEAR:
9628fe96085Stim szeto case PR_OUT_PREEMPT:
9638fe96085Stim szeto case PR_OUT_PREEMPT_ABORT:
9648fe96085Stim szeto case PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY:
9658fe96085Stim szeto case PR_OUT_REGISTER_MOVE:
9668fe96085Stim szeto param_len = READ_SCSI32(pr_out->param_len, uint32_t);
9678fe96085Stim szeto if (param_len < MAX_PGR_PARAM_LIST_LENGTH &&
9688fe96085Stim szeto param_len > 0) {
9698fe96085Stim szeto sbd_handle_short_write_transfers(task,
9708fe96085Stim szeto initial_dbuf, param_len);
9718fe96085Stim szeto } else {
9728fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
9738fe96085Stim szeto STMF_SAA_PARAM_LIST_LENGTH_ERROR);
9748fe96085Stim szeto }
9758fe96085Stim szeto break;
9768fe96085Stim szeto default :
9778fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
9788fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
9798fe96085Stim szeto break;
9808fe96085Stim szeto }
9818fe96085Stim szeto }
9828fe96085Stim szeto
9838fe96085Stim szeto void
sbd_handle_pgr_out_data(scsi_task_t * task,stmf_data_buf_t * dbuf)9848fe96085Stim szeto sbd_handle_pgr_out_data(scsi_task_t *task, stmf_data_buf_t *dbuf)
9858fe96085Stim szeto {
9868fe96085Stim szeto sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
9878fe96085Stim szeto scsi_cdb_prout_t *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
9888fe96085Stim szeto sbd_it_data_t *it = task->task_lu_itl_handle;
9898fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
9908fe96085Stim szeto sbd_pgr_key_t *key;
9918fe96085Stim szeto scsi_prout_plist_t *plist;
9928fe96085Stim szeto uint64_t rsv_key;
993716c1805SNattuvetty Bhavyan uint32_t buflen;
994716c1805SNattuvetty Bhavyan uint8_t *buf;
9958fe96085Stim szeto
9968fe96085Stim szeto ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_OUT);
9978fe96085Stim szeto
9988fe96085Stim szeto if (dbuf == NULL || dbuf->db_data_size < 24) {
9998fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
10008fe96085Stim szeto STMF_SAA_PARAM_LIST_LENGTH_ERROR);
10018fe96085Stim szeto return;
10028fe96085Stim szeto }
10038fe96085Stim szeto
10048fe96085Stim szeto buf = dbuf->db_sglist[0].seg_addr;
10058fe96085Stim szeto buflen = dbuf->db_data_size;
10068fe96085Stim szeto plist = (scsi_prout_plist_t *)buf;
10078fe96085Stim szeto
10088fe96085Stim szeto /* SPC3 - 6.12.1 */
10098fe96085Stim szeto if (pr_out->action != PR_OUT_REGISTER_MOVE && buflen != 24) {
10108fe96085Stim szeto if ((pr_out->action !=
10118fe96085Stim szeto PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY &&
10128fe96085Stim szeto pr_out->action != PR_OUT_REGISTER) ||
10138fe96085Stim szeto plist->spec_i_pt == 0) {
10148fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
10158fe96085Stim szeto STMF_SAA_PARAM_LIST_LENGTH_ERROR);
10168fe96085Stim szeto return;
10178fe96085Stim szeto }
10188fe96085Stim szeto }
10198fe96085Stim szeto
10208fe96085Stim szeto /*
10218fe96085Stim szeto * Common Reservation Conflict Checks
10228fe96085Stim szeto *
10238fe96085Stim szeto * It is okey to handle REGISTER_MOVE with same plist here,
10248fe96085Stim szeto * because we are only accessing reservation key feild.
10258fe96085Stim szeto */
10268fe96085Stim szeto rw_enter(&pgr->pgr_lock, RW_WRITER);
10278fe96085Stim szeto
10288fe96085Stim szeto /*
10298fe96085Stim szeto * Currently it is not mandatory to have volatile keyword here,
10308fe96085Stim szeto * because, it->pgr_key_ptr is not accessed yet. But still
10318fe96085Stim szeto * keeping it to safe gaurd against any possible future changes.
10328fe96085Stim szeto */
10338fe96085Stim szeto key = (sbd_pgr_key_t *)((volatile sbd_pgr_key_t *)it->pgr_key_ptr);
10348fe96085Stim szeto if (pr_out->action != PR_OUT_REGISTER &&
10358fe96085Stim szeto pr_out->action != PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY) {
10368fe96085Stim szeto /* if IT is not yet registered send conflict status */
10378fe96085Stim szeto if (key == NULL) {
10388fe96085Stim szeto if (pr_out->action == PR_OUT_REGISTER_MOVE &&
10398fe96085Stim szeto SBD_PGR_RSVD_NONE(pgr)) {
10408fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
10418fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
10428fe96085Stim szeto
10438fe96085Stim szeto } else {
10448fe96085Stim szeto stmf_scsilib_send_status(task,
10458fe96085Stim szeto STATUS_RESERVATION_CONFLICT, 0);
10468fe96085Stim szeto }
10478fe96085Stim szeto rw_exit(&pgr->pgr_lock);
10488fe96085Stim szeto return;
10498fe96085Stim szeto }
10508fe96085Stim szeto
10518fe96085Stim szeto /* Given reservation key should matches with registered key */
10528fe96085Stim szeto rsv_key = READ_SCSI64(plist->reservation_key, uint64_t);
10538fe96085Stim szeto if (key->pgr_key != rsv_key) {
10548fe96085Stim szeto stmf_scsilib_send_status(task,
10558fe96085Stim szeto STATUS_RESERVATION_CONFLICT, 0);
10568fe96085Stim szeto rw_exit(&pgr->pgr_lock);
10578fe96085Stim szeto return;
10588fe96085Stim szeto }
10598fe96085Stim szeto }
10608fe96085Stim szeto
10618fe96085Stim szeto switch (pr_out->action) {
10628fe96085Stim szeto case PR_OUT_REGISTER:
10638fe96085Stim szeto case PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY:
10648fe96085Stim szeto sbd_pgr_out_register(task, dbuf);
10658fe96085Stim szeto break;
10668fe96085Stim szeto case PR_OUT_REGISTER_MOVE:
10678fe96085Stim szeto sbd_pgr_out_register_and_move(task, dbuf);
10688fe96085Stim szeto break;
10698fe96085Stim szeto case PR_OUT_RESERVE:
10708fe96085Stim szeto sbd_pgr_out_reserve(task);
10718fe96085Stim szeto break;
10728fe96085Stim szeto case PR_OUT_RELEASE:
10738fe96085Stim szeto sbd_pgr_out_release(task);
10748fe96085Stim szeto break;
10758fe96085Stim szeto case PR_OUT_CLEAR:
10768fe96085Stim szeto sbd_pgr_out_clear(task);
10778fe96085Stim szeto break;
10788fe96085Stim szeto case PR_OUT_PREEMPT:
10798fe96085Stim szeto case PR_OUT_PREEMPT_ABORT:
10808fe96085Stim szeto sbd_pgr_out_preempt(task, dbuf);
10818fe96085Stim szeto break;
10828fe96085Stim szeto default :
10838fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
10848fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
10858fe96085Stim szeto break;
10868fe96085Stim szeto }
10878fe96085Stim szeto rw_exit(&pgr->pgr_lock);
10888fe96085Stim szeto }
10898fe96085Stim szeto
10908fe96085Stim szeto static void
sbd_pgr_in_read_keys(scsi_task_t * task,stmf_data_buf_t * initial_dbuf)10918fe96085Stim szeto sbd_pgr_in_read_keys(scsi_task_t *task, stmf_data_buf_t *initial_dbuf)
10928fe96085Stim szeto {
10938fe96085Stim szeto sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
10948fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
10958fe96085Stim szeto sbd_pgr_key_t *key;
10968fe96085Stim szeto scsi_prin_readrsrv_t *buf;
10978fe96085Stim szeto uint32_t buf_size, cdb_len, numkeys = 0;
10988fe96085Stim szeto uint64_t *reg_key;
10998fe96085Stim szeto
11008fe96085Stim szeto ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
11018fe96085Stim szeto
11028fe96085Stim szeto cdb_len = READ_SCSI16(&task->task_cdb[7], uint16_t);
11038fe96085Stim szeto for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next)
11048fe96085Stim szeto ++numkeys;
11058fe96085Stim szeto buf_size = 8 + numkeys * 8; /* minimum 8 bytes */
11068fe96085Stim szeto buf = kmem_zalloc(buf_size, KM_SLEEP);
11078fe96085Stim szeto SCSI_WRITE32(buf->PRgeneration, pgr->pgr_PRgeneration);
11088fe96085Stim szeto SCSI_WRITE32(buf->add_len, numkeys * 8);
11098fe96085Stim szeto
11108fe96085Stim szeto reg_key = (uint64_t *)&buf->key_list;
11118fe96085Stim szeto for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next) {
11128fe96085Stim szeto SCSI_WRITE64(reg_key, key->pgr_key);
11138fe96085Stim szeto reg_key++;
11148fe96085Stim szeto }
11158fe96085Stim szeto sbd_handle_short_read_transfers(task, initial_dbuf, (uint8_t *)buf,
11168fe96085Stim szeto cdb_len, buf_size);
11178fe96085Stim szeto kmem_free(buf, buf_size);
11188fe96085Stim szeto }
11198fe96085Stim szeto
11208fe96085Stim szeto static void
sbd_pgr_in_read_reservation(scsi_task_t * task,stmf_data_buf_t * initial_dbuf)11218fe96085Stim szeto sbd_pgr_in_read_reservation(scsi_task_t *task, stmf_data_buf_t *initial_dbuf)
11228fe96085Stim szeto {
11238fe96085Stim szeto sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
11248fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
11258fe96085Stim szeto scsi_prin_readrsrv_t *buf;
11268fe96085Stim szeto uint32_t cdb_len, buf_len, buf_size = 24;
11278fe96085Stim szeto
11288fe96085Stim szeto ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
11298fe96085Stim szeto
11308fe96085Stim szeto cdb_len = READ_SCSI16(&task->task_cdb[7], uint16_t);
11318fe96085Stim szeto buf = kmem_zalloc(buf_size, KM_SLEEP); /* fixed size cdb, 24 bytes */
11328fe96085Stim szeto SCSI_WRITE32(buf->PRgeneration, pgr->pgr_PRgeneration);
11338fe96085Stim szeto
11348fe96085Stim szeto if (SBD_PGR_RSVD_NONE(pgr)) {
11358fe96085Stim szeto SCSI_WRITE32(buf->add_len, 0);
11368fe96085Stim szeto buf_len = 8;
11378fe96085Stim szeto } else {
11388fe96085Stim szeto if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS) {
11398fe96085Stim szeto SCSI_WRITE64(
11408fe96085Stim szeto buf->key_list.res_key_list[0].reservation_key, 0);
11418fe96085Stim szeto } else {
11428fe96085Stim szeto SCSI_WRITE64(
11438fe96085Stim szeto buf->key_list.res_key_list[0].reservation_key,
11448fe96085Stim szeto pgr->pgr_rsvholder->pgr_key);
11458fe96085Stim szeto }
11468fe96085Stim szeto buf->key_list.res_key_list[0].type = pgr->pgr_rsv_type;
11478fe96085Stim szeto buf->key_list.res_key_list[0].scope = pgr->pgr_rsv_scope;
11488fe96085Stim szeto SCSI_WRITE32(buf->add_len, 16);
11498fe96085Stim szeto buf_len = 24;
11508fe96085Stim szeto }
11518fe96085Stim szeto
11528fe96085Stim szeto sbd_handle_short_read_transfers(task, initial_dbuf, (uint8_t *)buf,
11538fe96085Stim szeto cdb_len, buf_len);
11548fe96085Stim szeto kmem_free(buf, buf_size);
11558fe96085Stim szeto }
11568fe96085Stim szeto
11578fe96085Stim szeto static void
sbd_pgr_in_report_capabilities(scsi_task_t * task,stmf_data_buf_t * initial_dbuf)11588fe96085Stim szeto sbd_pgr_in_report_capabilities(scsi_task_t *task,
1159*61dfa509SRick McNeal stmf_data_buf_t *initial_dbuf)
11608fe96085Stim szeto {
11618fe96085Stim szeto sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
11628fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
11638fe96085Stim szeto scsi_prin_rpt_cap_t buf;
11648fe96085Stim szeto uint32_t cdb_len;
11658fe96085Stim szeto
11668fe96085Stim szeto ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
11678fe96085Stim szeto ASSERT(pgr != NULL);
11688fe96085Stim szeto
116970c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States bzero(&buf, sizeof (buf));
11708fe96085Stim szeto buf.ptpl_c = 1; /* Persist Through Power Loss C */
11718fe96085Stim szeto buf.atp_c = 1; /* All Target Ports Capable */
11728fe96085Stim szeto buf.sip_c = 1; /* Specify Initiator Ports Capable */
11738fe96085Stim szeto buf.crh = 0; /* Supports Reserve/Release exception */
11748fe96085Stim szeto buf.tmv = 1; /* Type Mask Valid */
11758fe96085Stim szeto buf.pr_type.wr_ex = 1; /* Write Exclusve */
11768fe96085Stim szeto buf.pr_type.ex_ac = 1; /* Exclusive Access */
11778fe96085Stim szeto buf.pr_type.wr_ex_ro = 1; /* Write Exclusive Registrants Only */
11788fe96085Stim szeto buf.pr_type.ex_ac_ro = 1; /* Exclusive Access Registrants Only */
11798fe96085Stim szeto buf.pr_type.wr_ex_ar = 1; /* Write Exclusive All Registrants */
11808fe96085Stim szeto buf.pr_type.ex_ac_ar = 1; /* Exclusive Access All Registrants */
11818fe96085Stim szeto
11828fe96085Stim szeto /* Persist Though Power Loss Active */
11838fe96085Stim szeto buf.ptpl_a = pgr->pgr_flags & SBD_PGR_APTPL;
11848fe96085Stim szeto SCSI_WRITE16(&buf.length, 8);
11858fe96085Stim szeto cdb_len = READ_SCSI16(&task->task_cdb[7], uint16_t);
11868fe96085Stim szeto sbd_handle_short_read_transfers(task, initial_dbuf, (uint8_t *)&buf,
11878fe96085Stim szeto cdb_len, 8);
11888fe96085Stim szeto }
11898fe96085Stim szeto
1190716c1805SNattuvetty Bhavyan /* Minimum required size, SPC3 rev23 Table 110 */
1191716c1805SNattuvetty Bhavyan #define PGR_IN_READ_FULL_STATUS_MINBUFSZ 8
1192716c1805SNattuvetty Bhavyan /* Full Satus Descriptor Fromat size, SPC3 rev23 Table 111 */
1193716c1805SNattuvetty Bhavyan #define PGR_IN_READ_FULL_STATUS_DESCFMTSZ 24
1194716c1805SNattuvetty Bhavyan
11958fe96085Stim szeto static void
sbd_pgr_in_read_full_status(scsi_task_t * task,stmf_data_buf_t * initial_dbuf)11968fe96085Stim szeto sbd_pgr_in_read_full_status(scsi_task_t *task,
1197*61dfa509SRick McNeal stmf_data_buf_t *initial_dbuf)
11988fe96085Stim szeto {
11998fe96085Stim szeto sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
12008fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
12018fe96085Stim szeto sbd_pgr_key_t *key;
1202*61dfa509SRick McNeal scsi_prin_status_t *sts;
12038fe96085Stim szeto scsi_prin_full_status_t *buf;
1204*61dfa509SRick McNeal uint32_t i, buf_size, cdb_len;
12058fe96085Stim szeto uint8_t *offset;
12068fe96085Stim szeto
12078fe96085Stim szeto ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
12088fe96085Stim szeto ASSERT(pgr != NULL);
12098fe96085Stim szeto
1210716c1805SNattuvetty Bhavyan /* 4 byte allocation length for CDB, SPC3 rev23, Table 101 */
12118fe96085Stim szeto cdb_len = READ_SCSI16(&task->task_cdb[7], uint16_t);
12128fe96085Stim szeto
1213716c1805SNattuvetty Bhavyan /* PRgeneration and additional length fields */
1214716c1805SNattuvetty Bhavyan buf_size = PGR_IN_READ_FULL_STATUS_MINBUFSZ;
12158fe96085Stim szeto for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next) {
1216716c1805SNattuvetty Bhavyan buf_size = buf_size + PGR_IN_READ_FULL_STATUS_DESCFMTSZ +
1217716c1805SNattuvetty Bhavyan key->pgr_key_rpt_len;
12188fe96085Stim szeto }
12198fe96085Stim szeto
12208fe96085Stim szeto buf = kmem_zalloc(buf_size, KM_SLEEP);
12218fe96085Stim szeto SCSI_WRITE32(buf->PRgeneration, pgr->pgr_PRgeneration);
1222716c1805SNattuvetty Bhavyan SCSI_WRITE32(buf->add_len, buf_size - PGR_IN_READ_FULL_STATUS_MINBUFSZ);
12238fe96085Stim szeto
12248fe96085Stim szeto offset = (uint8_t *)&buf->full_desc[0];
12258fe96085Stim szeto key = pgr->pgr_keylist;
12268fe96085Stim szeto i = 0;
12278fe96085Stim szeto while (key) {
12288fe96085Stim szeto sts = (scsi_prin_status_t *)offset;
12298fe96085Stim szeto SCSI_WRITE64(sts->reservation_key, key->pgr_key);
12308fe96085Stim szeto if ((pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS) ||
12318fe96085Stim szeto (pgr->pgr_rsvholder && pgr->pgr_rsvholder == key)) {
12328fe96085Stim szeto sts->r_holder = 1;
1233*61dfa509SRick McNeal sts->type = pgr->pgr_rsv_type;
12348fe96085Stim szeto sts->scope = pgr->pgr_rsv_scope;
12358fe96085Stim szeto }
12368fe96085Stim szeto
12378fe96085Stim szeto if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
12388fe96085Stim szeto sts->all_tg_pt = 1;
12398fe96085Stim szeto } else {
12408fe96085Stim szeto SCSI_WRITE16(sts->rel_tgt_port_id,
12418fe96085Stim szeto stmf_scsilib_get_lport_rtid(key->pgr_key_lpt_id));
12428fe96085Stim szeto }
1243716c1805SNattuvetty Bhavyan SCSI_WRITE32(sts->add_len, key->pgr_key_rpt_len);
1244716c1805SNattuvetty Bhavyan offset += PGR_IN_READ_FULL_STATUS_DESCFMTSZ;
1245716c1805SNattuvetty Bhavyan (void) memcpy(offset, key->pgr_key_rpt_id,
1246716c1805SNattuvetty Bhavyan key->pgr_key_rpt_len);
1247716c1805SNattuvetty Bhavyan offset += key->pgr_key_rpt_len;
12488fe96085Stim szeto key = key->pgr_key_next;
12498fe96085Stim szeto ++i;
12508fe96085Stim szeto }
125170c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(offset <= (uint8_t *)buf + buf_size);
12528fe96085Stim szeto
12538fe96085Stim szeto sbd_handle_short_read_transfers(task, initial_dbuf, (uint8_t *)buf,
12548fe96085Stim szeto cdb_len, buf_size);
12558fe96085Stim szeto kmem_free(buf, buf_size);
12568fe96085Stim szeto }
12578fe96085Stim szeto
12588fe96085Stim szeto static void
sbd_pgr_out_register(scsi_task_t * task,stmf_data_buf_t * dbuf)12598fe96085Stim szeto sbd_pgr_out_register(scsi_task_t *task, stmf_data_buf_t *dbuf)
12608fe96085Stim szeto {
12618fe96085Stim szeto sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
12628fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
12638fe96085Stim szeto stmf_scsi_session_t *ses = task->task_session;
12648fe96085Stim szeto sbd_it_data_t *it = task->task_lu_itl_handle;
12658fe96085Stim szeto sbd_pgr_key_t *key = it->pgr_key_ptr;
12668fe96085Stim szeto scsi_cdb_prout_t *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
1267716c1805SNattuvetty Bhavyan scsi_devid_desc_t *lpt = ses->ss_lport->lport_id;
12688fe96085Stim szeto scsi_prout_plist_t *plist;
1269716c1805SNattuvetty Bhavyan stmf_remote_port_t rport;
1270716c1805SNattuvetty Bhavyan uint8_t *buf, keyflag;
1271716c1805SNattuvetty Bhavyan uint32_t buflen;
12728fe96085Stim szeto uint64_t rsv_key, svc_key;
12738fe96085Stim szeto
12748fe96085Stim szeto buf = dbuf->db_sglist[0].seg_addr;
12758fe96085Stim szeto plist = (scsi_prout_plist_t *)buf;
12768fe96085Stim szeto buflen = dbuf->db_data_size;
12778fe96085Stim szeto rsv_key = READ_SCSI64(plist->reservation_key, uint64_t);
12788fe96085Stim szeto svc_key = READ_SCSI64(plist->service_key, uint64_t);
12798fe96085Stim szeto
12808fe96085Stim szeto /* Handling already registered IT session */
12818fe96085Stim szeto if (key) {
12828fe96085Stim szeto
12838fe96085Stim szeto if (pr_out->action == PR_OUT_REGISTER &&
12848fe96085Stim szeto key->pgr_key != rsv_key) {
12858fe96085Stim szeto stmf_scsilib_send_status(task,
12868fe96085Stim szeto STATUS_RESERVATION_CONFLICT, 0);
12878fe96085Stim szeto return;
12888fe96085Stim szeto }
12898fe96085Stim szeto if (plist->spec_i_pt) {
12908fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
12918fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
12928fe96085Stim szeto return;
12938fe96085Stim szeto }
12948fe96085Stim szeto
12958fe96085Stim szeto if (plist->all_tg_pt !=
12968fe96085Stim szeto (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT)) {
12978fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
12988fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
12998fe96085Stim szeto return;
13008fe96085Stim szeto }
13018fe96085Stim szeto
13028fe96085Stim szeto if (svc_key == 0) {
13038fe96085Stim szeto sbd_pgr_do_unregister(slu, it, key);
13048fe96085Stim szeto } else {
13058fe96085Stim szeto key->pgr_key = svc_key;
13068fe96085Stim szeto }
13078fe96085Stim szeto
13088fe96085Stim szeto goto sbd_pgr_reg_done;
13098fe96085Stim szeto }
13108fe96085Stim szeto
13118fe96085Stim szeto /* Handling unregistered IT session */
13128fe96085Stim szeto if (pr_out->action == PR_OUT_REGISTER && rsv_key != 0) {
13138fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_RESERVATION_CONFLICT, 0);
13148fe96085Stim szeto return;
13158fe96085Stim szeto }
13168fe96085Stim szeto
13178fe96085Stim szeto if (svc_key == 0) {
13188fe96085Stim szeto /* Do we need to consider aptpl here? I don't think so */
13198fe96085Stim szeto pgr->pgr_PRgeneration++;
13208fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_GOOD, 0);
13218fe96085Stim szeto return;
13228fe96085Stim szeto }
13238fe96085Stim szeto
1324716c1805SNattuvetty Bhavyan keyflag = SBD_PGR_KEY_TPT_ID_FLAG;
1325716c1805SNattuvetty Bhavyan if (plist->all_tg_pt) {
1326716c1805SNattuvetty Bhavyan keyflag |= SBD_PGR_KEY_ALL_TG_PT;
1327716c1805SNattuvetty Bhavyan lpt = NULL;
1328716c1805SNattuvetty Bhavyan }
1329716c1805SNattuvetty Bhavyan
13308fe96085Stim szeto if (plist->spec_i_pt) {
1331716c1805SNattuvetty Bhavyan uint32_t max_tpdnum, tpdnum, i, adn_len = 0;
1332716c1805SNattuvetty Bhavyan uint16_t tpd_sz = 0;
1333716c1805SNattuvetty Bhavyan uint8_t *adn_dat;
1334716c1805SNattuvetty Bhavyan scsi_transport_id_t *tpd;
1335716c1805SNattuvetty Bhavyan stmf_remote_port_t *rpt_ary;
13368fe96085Stim szeto
13378fe96085Stim szeto if (pr_out->action == PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY) {
13388fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
13398fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
13408fe96085Stim szeto return;
13418fe96085Stim szeto }
13428fe96085Stim szeto
1343716c1805SNattuvetty Bhavyan /* Length validation SPC3 rev23 Section 6.12.3 and Table 115 */
1344716c1805SNattuvetty Bhavyan if (buflen >= sizeof (scsi_prout_plist_t) - 1 +
1345716c1805SNattuvetty Bhavyan sizeof (uint32_t))
1346716c1805SNattuvetty Bhavyan adn_len = READ_SCSI32(plist->apd, uint32_t);
1347716c1805SNattuvetty Bhavyan /* SPC3 rev23, adn_len should be multiple of 4 */
1348716c1805SNattuvetty Bhavyan if (adn_len % 4 != 0 ||
1349716c1805SNattuvetty Bhavyan adn_len < sizeof (scsi_transport_id_t) +
1350716c1805SNattuvetty Bhavyan sizeof (uint32_t) ||
1351716c1805SNattuvetty Bhavyan buflen < sizeof (scsi_prout_plist_t) - 1 + adn_len) {
13528fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
13538fe96085Stim szeto STMF_SAA_PARAM_LIST_LENGTH_ERROR);
13548fe96085Stim szeto return;
13558fe96085Stim szeto }
1356716c1805SNattuvetty Bhavyan
13578fe96085Stim szeto tpdnum = 0;
1358716c1805SNattuvetty Bhavyan adn_dat = plist->apd + sizeof (uint32_t);
1359716c1805SNattuvetty Bhavyan max_tpdnum = adn_len / sizeof (scsi_transport_id_t);
1360716c1805SNattuvetty Bhavyan rpt_ary = (stmf_remote_port_t *)kmem_zalloc(
1361716c1805SNattuvetty Bhavyan sizeof (stmf_remote_port_t) * max_tpdnum, KM_SLEEP);
1362716c1805SNattuvetty Bhavyan
13638fe96085Stim szeto /* Check the validity of given TransportIDs */
1364716c1805SNattuvetty Bhavyan while (adn_len != 0) {
1365716c1805SNattuvetty Bhavyan if (!stmf_scsilib_tptid_validate(
1366716c1805SNattuvetty Bhavyan (scsi_transport_id_t *)adn_dat, adn_len, &tpd_sz))
13678fe96085Stim szeto break;
1368716c1805SNattuvetty Bhavyan /* SPC3 rev23, tpd_sz should be multiple of 4 */
1369716c1805SNattuvetty Bhavyan if (tpd_sz == 0 || tpd_sz % 4 != 0)
1370716c1805SNattuvetty Bhavyan break;
1371716c1805SNattuvetty Bhavyan tpd = (scsi_transport_id_t *)adn_dat;
1372716c1805SNattuvetty Bhavyan
13738fe96085Stim szeto /* make sure that there is no duplicates */
13748fe96085Stim szeto for (i = 0; i < tpdnum; i++) {
1375716c1805SNattuvetty Bhavyan if (stmf_scsilib_tptid_compare(
1376716c1805SNattuvetty Bhavyan rpt_ary[i].rport_tptid, tpd))
13778fe96085Stim szeto break;
13788fe96085Stim szeto }
1379716c1805SNattuvetty Bhavyan if (i < tpdnum)
13808fe96085Stim szeto break;
1381716c1805SNattuvetty Bhavyan
1382716c1805SNattuvetty Bhavyan rpt_ary[tpdnum].rport_tptid = tpd;
1383716c1805SNattuvetty Bhavyan rpt_ary[tpdnum].rport_tptid_sz = tpd_sz;
1384716c1805SNattuvetty Bhavyan
13858fe96085Stim szeto /* Check if the given IT nexus is already registered */
1386716c1805SNattuvetty Bhavyan if (sbd_pgr_key_registered(pgr, lpt, &rpt_ary[tpdnum]))
13878fe96085Stim szeto break;
13888fe96085Stim szeto
1389716c1805SNattuvetty Bhavyan adn_len -= tpd_sz;
1390716c1805SNattuvetty Bhavyan adn_dat += tpd_sz;
1391716c1805SNattuvetty Bhavyan tpdnum++;
13928fe96085Stim szeto }
1393716c1805SNattuvetty Bhavyan
1394716c1805SNattuvetty Bhavyan if (adn_len != 0) {
1395716c1805SNattuvetty Bhavyan kmem_free(rpt_ary,
1396716c1805SNattuvetty Bhavyan sizeof (stmf_remote_port_t) * max_tpdnum);
13978fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
13988fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
13998fe96085Stim szeto return;
14008fe96085Stim szeto }
1401716c1805SNattuvetty Bhavyan
1402716c1805SNattuvetty Bhavyan for (i = 0; i < tpdnum; i++) {
1403716c1805SNattuvetty Bhavyan (void) sbd_pgr_do_register(slu, NULL, lpt, &rpt_ary[i],
1404716c1805SNattuvetty Bhavyan keyflag, svc_key);
1405716c1805SNattuvetty Bhavyan }
1406716c1805SNattuvetty Bhavyan kmem_free(rpt_ary, sizeof (stmf_remote_port_t) * max_tpdnum);
14078fe96085Stim szeto }
14088fe96085Stim szeto
1409716c1805SNattuvetty Bhavyan rport.rport_tptid = ses->ss_rport->rport_tptid;
1410716c1805SNattuvetty Bhavyan rport.rport_tptid_sz = ses->ss_rport->rport_tptid_sz;
1411716c1805SNattuvetty Bhavyan
1412716c1805SNattuvetty Bhavyan (void) sbd_pgr_do_register(slu, it, lpt, &rport, keyflag, svc_key);
14138fe96085Stim szeto
14148fe96085Stim szeto sbd_pgr_reg_done:
14158fe96085Stim szeto
1416*61dfa509SRick McNeal if (plist->aptpl || (sbd_pgr_should_save(slu) == B_TRUE)) {
14178fe96085Stim szeto if (plist->aptpl)
14188fe96085Stim szeto PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
14198fe96085Stim szeto else
14208fe96085Stim szeto PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
14218fe96085Stim szeto
14228fe96085Stim szeto if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
14238fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
1424*61dfa509SRick McNeal STMF_SAA_INSUFFICIENT_REG_RESRCS);
14258fe96085Stim szeto return;
14268fe96085Stim szeto }
14278fe96085Stim szeto }
14288fe96085Stim szeto
14298fe96085Stim szeto pgr->pgr_PRgeneration++;
14308fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_GOOD, 0);
14318fe96085Stim szeto }
14328fe96085Stim szeto
14338fe96085Stim szeto static sbd_pgr_key_t *
sbd_pgr_do_register(sbd_lu_t * slu,sbd_it_data_t * it,scsi_devid_desc_t * lpt,stmf_remote_port_t * rpt,uint8_t keyflag,uint64_t svc_key)14348fe96085Stim szeto sbd_pgr_do_register(sbd_lu_t *slu, sbd_it_data_t *it, scsi_devid_desc_t *lpt,
1435*61dfa509SRick McNeal stmf_remote_port_t *rpt, uint8_t keyflag, uint64_t svc_key)
14368fe96085Stim szeto {
14378fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
14388fe96085Stim szeto sbd_pgr_key_t *key;
1439716c1805SNattuvetty Bhavyan uint16_t lpt_len = 0;
14408fe96085Stim szeto
1441716c1805SNattuvetty Bhavyan if (lpt)
1442716c1805SNattuvetty Bhavyan lpt_len = sizeof (scsi_devid_desc_t) + lpt->ident_length;
14438fe96085Stim szeto
1444716c1805SNattuvetty Bhavyan key = sbd_pgr_key_alloc(lpt, rpt->rport_tptid,
1445716c1805SNattuvetty Bhavyan lpt_len, rpt->rport_tptid_sz);
14468fe96085Stim szeto key->pgr_key = svc_key;
1447716c1805SNattuvetty Bhavyan key->pgr_key_flags |= keyflag;
14488fe96085Stim szeto
1449716c1805SNattuvetty Bhavyan if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
14508fe96085Stim szeto /* set PGR_CHECK flag for all unregistered IT nexus */
14518fe96085Stim szeto sbd_pgr_set_pgr_check_flag(slu, B_FALSE);
14528fe96085Stim szeto } else {
14538fe96085Stim szeto key->pgr_key_it = it;
14548fe96085Stim szeto }
14558fe96085Stim szeto
14568fe96085Stim szeto if (it) {
14578fe96085Stim szeto mutex_enter(&slu->sl_lock);
14588fe96085Stim szeto it->pgr_key_ptr = key;
14598fe96085Stim szeto mutex_exit(&slu->sl_lock);
1460716c1805SNattuvetty Bhavyan } else {
1461716c1805SNattuvetty Bhavyan sbd_pgr_set_pgr_check_flag(slu, B_FALSE);
14628fe96085Stim szeto }
14638fe96085Stim szeto
14648fe96085Stim szeto key->pgr_key_next = pgr->pgr_keylist;
14658fe96085Stim szeto if (pgr->pgr_keylist) {
14668fe96085Stim szeto pgr->pgr_keylist->pgr_key_prev = key;
14678fe96085Stim szeto }
14688fe96085Stim szeto pgr->pgr_keylist = key;
14698fe96085Stim szeto
14708fe96085Stim szeto return (key);
14718fe96085Stim szeto }
14728fe96085Stim szeto
14738fe96085Stim szeto static void
sbd_pgr_do_unregister(sbd_lu_t * slu,sbd_it_data_t * it,sbd_pgr_key_t * key)14748fe96085Stim szeto sbd_pgr_do_unregister(sbd_lu_t *slu, sbd_it_data_t *it, sbd_pgr_key_t *key)
14758fe96085Stim szeto {
14768fe96085Stim szeto if (slu->sl_pgr->pgr_rsvholder == key) {
14778fe96085Stim szeto sbd_pgr_do_release(slu, it, SBD_UA_RESERVATIONS_RELEASED);
14788fe96085Stim szeto }
14798fe96085Stim szeto
14808fe96085Stim szeto sbd_pgr_remove_key(slu, key);
14818fe96085Stim szeto if (slu->sl_pgr->pgr_keylist == NULL) {
14828fe96085Stim szeto PGR_CLEAR_RSV_FLAG(slu->sl_pgr->pgr_flags);
14838fe96085Stim szeto }
14848fe96085Stim szeto }
14858fe96085Stim szeto
14868fe96085Stim szeto static void
sbd_pgr_out_reserve(scsi_task_t * task)14878fe96085Stim szeto sbd_pgr_out_reserve(scsi_task_t *task)
14888fe96085Stim szeto {
14898fe96085Stim szeto sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
14908fe96085Stim szeto stmf_scsi_session_t *ses = task->task_session;
14918fe96085Stim szeto scsi_cdb_prout_t *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
14928fe96085Stim szeto sbd_it_data_t *it = task->task_lu_itl_handle;
14938fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
14948fe96085Stim szeto sbd_pgr_key_t *key = it->pgr_key_ptr;
14958fe96085Stim szeto
14968fe96085Stim szeto ASSERT(key);
14978fe96085Stim szeto
14988fe96085Stim szeto if (!(PGR_VALID_SCOPE(pr_out->scope) && PGR_VALID_TYPE(pr_out->type))) {
14998fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
15008fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
15018fe96085Stim szeto return;
15028fe96085Stim szeto }
15038fe96085Stim szeto
15048fe96085Stim szeto if (SBD_PGR_RSVD(pgr)) {
15058fe96085Stim szeto if (PGR_RESERVATION_HOLDER(pgr, key, it)) {
15068fe96085Stim szeto if (pgr->pgr_rsv_type != pr_out->type ||
15078fe96085Stim szeto pgr->pgr_rsv_scope != pr_out->scope) {
15088fe96085Stim szeto stmf_scsilib_send_status(task,
15098fe96085Stim szeto STATUS_RESERVATION_CONFLICT, 0);
15108fe96085Stim szeto return;
15118fe96085Stim szeto }
15128fe96085Stim szeto } else {
15138fe96085Stim szeto stmf_scsilib_send_status(task,
15148fe96085Stim szeto STATUS_RESERVATION_CONFLICT, 0);
15158fe96085Stim szeto return;
15168fe96085Stim szeto
15178fe96085Stim szeto }
15188fe96085Stim szeto /* In case there is no reservation exist */
15198fe96085Stim szeto } else {
15208fe96085Stim szeto sbd_pgr_do_reserve(pgr, key, it, ses, pr_out);
1521*61dfa509SRick McNeal if (sbd_pgr_should_save(slu) == B_TRUE) {
15228fe96085Stim szeto if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
15238fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
1524*61dfa509SRick McNeal STMF_SAA_INSUFFICIENT_REG_RESRCS);
15258fe96085Stim szeto return;
15268fe96085Stim szeto }
15278fe96085Stim szeto }
15288fe96085Stim szeto }
15298fe96085Stim szeto
15308fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_GOOD, 0);
15318fe96085Stim szeto }
15328fe96085Stim szeto
15338fe96085Stim szeto static void
sbd_pgr_do_reserve(sbd_pgr_t * pgr,sbd_pgr_key_t * key,sbd_it_data_t * it,stmf_scsi_session_t * ses,scsi_cdb_prout_t * pr_out)15348fe96085Stim szeto sbd_pgr_do_reserve(sbd_pgr_t *pgr, sbd_pgr_key_t *key, sbd_it_data_t *it,
1535*61dfa509SRick McNeal stmf_scsi_session_t *ses, scsi_cdb_prout_t *pr_out)
15368fe96085Stim szeto {
15378fe96085Stim szeto scsi_devid_desc_t *lpt;
15388fe96085Stim szeto uint16_t lpt_len;
15398fe96085Stim szeto
15408fe96085Stim szeto pgr->pgr_rsv_type = pr_out->type;
15418fe96085Stim szeto pgr->pgr_rsv_scope = pr_out->scope;
15428fe96085Stim szeto if (pr_out->type == PGR_TYPE_WR_EX_AR ||
15438fe96085Stim szeto pr_out->type == PGR_TYPE_EX_AC_AR) {
15448fe96085Stim szeto PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_RSVD_ALL_REGISTRANTS);
15458fe96085Stim szeto } else {
15468fe96085Stim szeto if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
15478fe96085Stim szeto lpt = key->pgr_key_lpt_id;
15488fe96085Stim szeto lpt_len = key->pgr_key_lpt_len;
15498fe96085Stim szeto if (lpt_len > 0 && lpt != NULL) {
15508fe96085Stim szeto kmem_free(lpt, lpt_len);
15518fe96085Stim szeto }
15528fe96085Stim szeto lpt = ses->ss_lport->lport_id;
1553716c1805SNattuvetty Bhavyan lpt_len = sizeof (scsi_devid_desc_t) +
15548fe96085Stim szeto lpt->ident_length;
15558fe96085Stim szeto key->pgr_key_lpt_len = lpt_len;
15568fe96085Stim szeto key->pgr_key_lpt_id = (scsi_devid_desc_t *)
15578fe96085Stim szeto kmem_zalloc(lpt_len, KM_SLEEP);
15588fe96085Stim szeto bcopy(lpt, key->pgr_key_lpt_id, lpt_len);
15598fe96085Stim szeto key->pgr_key_it = it;
15608fe96085Stim szeto }
15618fe96085Stim szeto
15628fe96085Stim szeto PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_RSVD_ONE);
15638fe96085Stim szeto pgr->pgr_rsvholder = key;
15648fe96085Stim szeto }
15658fe96085Stim szeto }
15668fe96085Stim szeto
15678fe96085Stim szeto static void
sbd_pgr_out_release(scsi_task_t * task)15688fe96085Stim szeto sbd_pgr_out_release(scsi_task_t *task)
15698fe96085Stim szeto {
15708fe96085Stim szeto sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
15718fe96085Stim szeto scsi_cdb_prout_t *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
15728fe96085Stim szeto sbd_it_data_t *it = task->task_lu_itl_handle;
15738fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
15748fe96085Stim szeto sbd_pgr_key_t *key = it->pgr_key_ptr;
15758fe96085Stim szeto
15768fe96085Stim szeto ASSERT(key);
15778fe96085Stim szeto
1578*61dfa509SRick McNeal /*
1579*61dfa509SRick McNeal * XXX this does not honor APTPL
1580*61dfa509SRick McNeal * (i.e., changes made to a formerly-persistent reservation are not
1581*61dfa509SRick McNeal * updated here!!!)
1582*61dfa509SRick McNeal */
15838fe96085Stim szeto if (SBD_PGR_RSVD(pgr)) {
15848fe96085Stim szeto if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS ||
15858fe96085Stim szeto pgr->pgr_rsvholder == key) {
15868fe96085Stim szeto if (pgr->pgr_rsv_type != pr_out->type ||
15878fe96085Stim szeto pgr->pgr_rsv_scope != pr_out->scope) {
15888fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
15898fe96085Stim szeto STMF_SAA_INVALID_RELEASE_OF_PR);
15908fe96085Stim szeto return;
15918fe96085Stim szeto }
15928fe96085Stim szeto sbd_pgr_do_release(slu, it,
15938fe96085Stim szeto SBD_UA_RESERVATIONS_RELEASED);
1594*61dfa509SRick McNeal
1595*61dfa509SRick McNeal /*
1596*61dfa509SRick McNeal * XXX T10 SPC-3 5.6.10.2 says nothing about what to
1597*61dfa509SRick McNeal * do in the event of a failure updating the
1598*61dfa509SRick McNeal * PGR nvram store for a reservation associated with
1599*61dfa509SRick McNeal * an APTPL-enabled (see SPC-3 5.6.4.1) I_T
1600*61dfa509SRick McNeal * registration during a RELEASE service action.
1601*61dfa509SRick McNeal *
1602*61dfa509SRick McNeal * Technically, the CDB completed successfully, as per
1603*61dfa509SRick McNeal * the spec, but at some point we may need to enter
1604*61dfa509SRick McNeal * a recovery mode on the initiator(s) if we power cycle
1605*61dfa509SRick McNeal * the target at the wrong instant...
1606*61dfa509SRick McNeal */
1607*61dfa509SRick McNeal if (sbd_pgr_should_save(slu) == B_TRUE) {
1608*61dfa509SRick McNeal if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1609*61dfa509SRick McNeal stmf_scsilib_send_status(task,
1610*61dfa509SRick McNeal STATUS_CHECK,
1611*61dfa509SRick McNeal STMF_SAA_INSUFFICIENT_REG_RESRCS);
1612*61dfa509SRick McNeal return;
1613*61dfa509SRick McNeal }
1614*61dfa509SRick McNeal }
16158fe96085Stim szeto }
16168fe96085Stim szeto }
16178fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_GOOD, 0);
16188fe96085Stim szeto }
16198fe96085Stim szeto
16208fe96085Stim szeto static void
sbd_pgr_do_release(sbd_lu_t * slu,sbd_it_data_t * it,uint8_t ua_condition)16218fe96085Stim szeto sbd_pgr_do_release(sbd_lu_t *slu, sbd_it_data_t *it, uint8_t ua_condition)
16228fe96085Stim szeto {
16238fe96085Stim szeto
16248fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
16258fe96085Stim szeto
16268fe96085Stim szeto /* Reset pgr_flags */
16278fe96085Stim szeto PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
16288fe96085Stim szeto pgr->pgr_rsvholder = NULL;
16298fe96085Stim szeto
16308fe96085Stim szeto /* set unit attention condition if necessary */
16318fe96085Stim szeto if (pgr->pgr_rsv_type != PGR_TYPE_WR_EX &&
16328fe96085Stim szeto pgr->pgr_rsv_type != PGR_TYPE_EX_AC) {
16338fe96085Stim szeto sbd_pgr_set_ua_conditions(slu, it, ua_condition);
16348fe96085Stim szeto }
16358fe96085Stim szeto pgr->pgr_rsv_type = 0;
16368fe96085Stim szeto }
16378fe96085Stim szeto
16388fe96085Stim szeto static void
sbd_pgr_out_clear(scsi_task_t * task)16398fe96085Stim szeto sbd_pgr_out_clear(scsi_task_t *task)
16408fe96085Stim szeto {
16418fe96085Stim szeto sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
16428fe96085Stim szeto sbd_it_data_t *it = task->task_lu_itl_handle;
16438fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
16448fe96085Stim szeto
16458fe96085Stim szeto ASSERT(it->pgr_key_ptr);
16468fe96085Stim szeto
16478fe96085Stim szeto PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
16488fe96085Stim szeto pgr->pgr_rsvholder = NULL;
16498fe96085Stim szeto pgr->pgr_rsv_type = 0;
16508fe96085Stim szeto mutex_enter(&slu->sl_lock);
16518fe96085Stim szeto /* Remove all pointers from IT to pgr keys */
16528fe96085Stim szeto for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
16538fe96085Stim szeto it->pgr_key_ptr = NULL;
16548fe96085Stim szeto }
16558fe96085Stim szeto mutex_exit(&slu->sl_lock);
16568fe96085Stim szeto sbd_pgr_keylist_dealloc(slu);
16578fe96085Stim szeto sbd_pgr_set_ua_conditions(slu, it, SBD_UA_RESERVATIONS_PREEMPTED);
1658*61dfa509SRick McNeal if (sbd_pgr_should_save(slu) == B_TRUE) {
16598fe96085Stim szeto if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
16608fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
1661*61dfa509SRick McNeal STMF_SAA_INSUFFICIENT_REG_RESRCS);
16628fe96085Stim szeto return;
16638fe96085Stim szeto }
16648fe96085Stim szeto }
16658fe96085Stim szeto pgr->pgr_PRgeneration++;
16668fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_GOOD, 0);
16678fe96085Stim szeto }
16688fe96085Stim szeto
16698fe96085Stim szeto static void
sbd_pgr_out_preempt(scsi_task_t * task,stmf_data_buf_t * dbuf)16708fe96085Stim szeto sbd_pgr_out_preempt(scsi_task_t *task, stmf_data_buf_t *dbuf)
16718fe96085Stim szeto {
16728fe96085Stim szeto sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
16738fe96085Stim szeto stmf_scsi_session_t *ses = task->task_session;
16748fe96085Stim szeto scsi_cdb_prout_t *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
16758fe96085Stim szeto sbd_it_data_t *it = task->task_lu_itl_handle;
16768fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
16778fe96085Stim szeto sbd_pgr_key_t *key = it->pgr_key_ptr;
16788fe96085Stim szeto scsi_prout_plist_t *plist;
16798fe96085Stim szeto uint8_t *buf, change_rsv = 0;
16808fe96085Stim szeto uint64_t svc_key;
16818fe96085Stim szeto
16828fe96085Stim szeto ASSERT(key);
16838fe96085Stim szeto
16848fe96085Stim szeto buf = dbuf->db_sglist[0].seg_addr;
16858fe96085Stim szeto plist = (scsi_prout_plist_t *)buf;
16868fe96085Stim szeto svc_key = READ_SCSI64(plist->service_key, uint64_t);
16878fe96085Stim szeto
16888fe96085Stim szeto if (SBD_PGR_RSVD_NONE(pgr)) {
16898fe96085Stim szeto if (svc_key == 0 ||
16908fe96085Stim szeto sbd_pgr_remove_keys(slu, it, key, svc_key, B_TRUE) == 0) {
16918fe96085Stim szeto stmf_scsilib_send_status(task,
16928fe96085Stim szeto STATUS_RESERVATION_CONFLICT, 0);
16938fe96085Stim szeto return;
16948fe96085Stim szeto }
16958fe96085Stim szeto
16968fe96085Stim szeto } else if (pgr->pgr_flags & SBD_PGR_RSVD_ONE) {
16978fe96085Stim szeto if (svc_key == 0) {
16988fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
16998fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
17008fe96085Stim szeto return;
17018fe96085Stim szeto }
17028fe96085Stim szeto
17038fe96085Stim szeto /* Validity check of scope and type */
17048fe96085Stim szeto if (pgr->pgr_rsvholder->pgr_key == svc_key) {
17058fe96085Stim szeto if (!(PGR_VALID_SCOPE(pr_out->scope) &&
17068fe96085Stim szeto PGR_VALID_TYPE(pr_out->type))) {
17078fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
17088fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
17098fe96085Stim szeto return;
17108fe96085Stim szeto }
17118fe96085Stim szeto }
17128fe96085Stim szeto
17138fe96085Stim szeto if (pgr->pgr_rsvholder != key &&
17148fe96085Stim szeto pgr->pgr_rsvholder->pgr_key == svc_key) {
17158fe96085Stim szeto sbd_pgr_do_release(slu, it,
17168fe96085Stim szeto SBD_UA_REGISTRATIONS_PREEMPTED);
17178fe96085Stim szeto change_rsv = 1;
17188fe96085Stim szeto }
17198fe96085Stim szeto
17208fe96085Stim szeto if (pgr->pgr_rsvholder == key &&
17218fe96085Stim szeto pgr->pgr_rsvholder->pgr_key == svc_key) {
17228fe96085Stim szeto if (pr_out->scope != pgr->pgr_rsv_scope ||
17238fe96085Stim szeto pr_out->type != pgr->pgr_rsv_type) {
17248fe96085Stim szeto sbd_pgr_do_release(slu, it,
17258fe96085Stim szeto SBD_UA_REGISTRATIONS_PREEMPTED);
17268fe96085Stim szeto change_rsv = 1;
17278fe96085Stim szeto }
17288fe96085Stim szeto } else {
17298fe96085Stim szeto /*
17308fe96085Stim szeto * Remove matched keys in all cases, except when the
17318fe96085Stim szeto * current IT nexus holds the reservation and the given
17328fe96085Stim szeto * svc_key matches with registered key.
17338fe96085Stim szeto * Note that, if the reservation is held by another
17348fe96085Stim szeto * IT nexus, and svc_key matches registered key for
17358fe96085Stim szeto * that IT nexus, sbd_pgr_remove_key() is not expected
17368fe96085Stim szeto * return 0. Hence, returning check condition after
17378fe96085Stim szeto * releasing the reservation does not arise.
17388fe96085Stim szeto */
17398fe96085Stim szeto if (sbd_pgr_remove_keys(slu, it, key, svc_key, B_TRUE)
17408fe96085Stim szeto == 0) {
17418fe96085Stim szeto stmf_scsilib_send_status(task,
17428fe96085Stim szeto STATUS_RESERVATION_CONFLICT, 0);
17438fe96085Stim szeto return;
17448fe96085Stim szeto }
17458fe96085Stim szeto }
17468fe96085Stim szeto
17478fe96085Stim szeto if (change_rsv) {
17488fe96085Stim szeto sbd_pgr_do_reserve(pgr, key, it, ses, pr_out);
17498fe96085Stim szeto }
17508fe96085Stim szeto
17518fe96085Stim szeto } else if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS) {
17528fe96085Stim szeto if (svc_key == 0) {
17538fe96085Stim szeto if (!(PGR_VALID_SCOPE(pr_out->scope) &&
17548fe96085Stim szeto PGR_VALID_TYPE(pr_out->type))) {
17558fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
17568fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
17578fe96085Stim szeto return;
17588fe96085Stim szeto }
17598fe96085Stim szeto sbd_pgr_do_release(slu, it,
17608fe96085Stim szeto SBD_UA_REGISTRATIONS_PREEMPTED);
17618fe96085Stim szeto (void) sbd_pgr_remove_keys(slu, it, key, 0, B_FALSE);
17628fe96085Stim szeto sbd_pgr_do_reserve(pgr, key, it, ses, pr_out);
17638fe96085Stim szeto } else {
17648fe96085Stim szeto if (sbd_pgr_remove_keys(slu, it, key, svc_key, B_TRUE)
17658fe96085Stim szeto == 0) {
17668fe96085Stim szeto stmf_scsilib_send_status(task,
17678fe96085Stim szeto STATUS_RESERVATION_CONFLICT, 0);
17688fe96085Stim szeto return;
17698fe96085Stim szeto }
17708fe96085Stim szeto }
17718fe96085Stim szeto }
17728fe96085Stim szeto
1773*61dfa509SRick McNeal if (sbd_pgr_should_save(slu) == B_TRUE) {
17748fe96085Stim szeto if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
17758fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
1776*61dfa509SRick McNeal STMF_SAA_INSUFFICIENT_REG_RESRCS);
17778fe96085Stim szeto return;
17788fe96085Stim szeto }
17798fe96085Stim szeto }
17808fe96085Stim szeto
17818fe96085Stim szeto pgr->pgr_PRgeneration++;
17828fe96085Stim szeto
17838fe96085Stim szeto if (pr_out->action == PR_OUT_PREEMPT_ABORT) {
178444b678cfSNattuvetty Bhavyan stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED,
178544b678cfSNattuvetty Bhavyan (void *)slu->sl_lu);
17868fe96085Stim szeto }
178744b678cfSNattuvetty Bhavyan stmf_scsilib_send_status(task, STATUS_GOOD, 0);
17888fe96085Stim szeto }
17898fe96085Stim szeto
17908fe96085Stim szeto static void
sbd_pgr_out_register_and_move(scsi_task_t * task,stmf_data_buf_t * dbuf)17918fe96085Stim szeto sbd_pgr_out_register_and_move(scsi_task_t *task, stmf_data_buf_t *dbuf)
17928fe96085Stim szeto {
17938fe96085Stim szeto sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
17948fe96085Stim szeto sbd_it_data_t *it = task->task_lu_itl_handle;
17958fe96085Stim szeto sbd_pgr_t *pgr = slu->sl_pgr;
17968fe96085Stim szeto sbd_pgr_key_t *key = it->pgr_key_ptr;
1797716c1805SNattuvetty Bhavyan scsi_devid_desc_t *lpt;
1798716c1805SNattuvetty Bhavyan stmf_remote_port_t rport;
17998fe96085Stim szeto sbd_pgr_key_t *newkey;
18008fe96085Stim szeto scsi_prout_reg_move_plist_t *plist;
18018fe96085Stim szeto uint8_t *buf, lpt_len;
1802716c1805SNattuvetty Bhavyan uint16_t tpd_len;
1803716c1805SNattuvetty Bhavyan uint32_t adn_len;
18048fe96085Stim szeto uint64_t svc_key;
18058fe96085Stim szeto
18068fe96085Stim szeto /*
18078fe96085Stim szeto * Check whether the key holds the reservation or current reservation
18088fe96085Stim szeto * is of type all registrants.
18098fe96085Stim szeto */
18108fe96085Stim szeto if (pgr->pgr_rsvholder != key) {
18118fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_RESERVATION_CONFLICT, 0);
18128fe96085Stim szeto return;
18138fe96085Stim szeto }
18148fe96085Stim szeto
18158fe96085Stim szeto buf = dbuf->db_sglist[0].seg_addr;
18168fe96085Stim szeto plist = (scsi_prout_reg_move_plist_t *)buf;
18178fe96085Stim szeto svc_key = READ_SCSI64(plist->service_key, uint64_t);
18188fe96085Stim szeto if (svc_key == 0) {
18198fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
18208fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
18218fe96085Stim szeto return;
18228fe96085Stim szeto }
18238fe96085Stim szeto
18248fe96085Stim szeto lpt = stmf_scsilib_get_devid_desc(READ_SCSI16(plist->rel_tgt_port_id,
18258fe96085Stim szeto uint16_t));
18268fe96085Stim szeto if (lpt == NULL) {
18278fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
18288fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
18298fe96085Stim szeto return;
18308fe96085Stim szeto }
18318fe96085Stim szeto
1832716c1805SNattuvetty Bhavyan adn_len = READ_SCSI32(plist->tptid_len, uint32_t);
1833716c1805SNattuvetty Bhavyan if (!stmf_scsilib_tptid_validate(
1834716c1805SNattuvetty Bhavyan (scsi_transport_id_t *)plist->tptid, adn_len, &tpd_len)) {
1835716c1805SNattuvetty Bhavyan kmem_free(lpt, sizeof (scsi_devid_desc_t) + lpt->ident_length);
18368fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
18378fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_PARAM_LIST);
18388fe96085Stim szeto return;
1839716c1805SNattuvetty Bhavyan }
1840716c1805SNattuvetty Bhavyan
1841716c1805SNattuvetty Bhavyan rport.rport_tptid = (scsi_transport_id_t *)plist->tptid;
1842716c1805SNattuvetty Bhavyan rport.rport_tptid_sz = tpd_len;
1843716c1805SNattuvetty Bhavyan
1844716c1805SNattuvetty Bhavyan if (sbd_pgr_key_compare(key, lpt, &rport)) {
1845716c1805SNattuvetty Bhavyan kmem_free(lpt, sizeof (scsi_devid_desc_t) + lpt->ident_length);
18468fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
18478fe96085Stim szeto STMF_SAA_INVALID_FIELD_IN_PARAM_LIST);
18488fe96085Stim szeto return;
18498fe96085Stim szeto }
18508fe96085Stim szeto
1851716c1805SNattuvetty Bhavyan newkey = sbd_pgr_key_registered(pgr, lpt, &rport);
18528fe96085Stim szeto if (newkey) {
18538fe96085Stim szeto /* Set the pgr_key, irrespective of what it currently holds */
18548fe96085Stim szeto newkey->pgr_key = svc_key;
18558fe96085Stim szeto
18568fe96085Stim szeto /* all_tg_pt is set for found key, copy lpt info to the key */
18578fe96085Stim szeto if (newkey->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
18588fe96085Stim szeto if (newkey->pgr_key_lpt_id &&
18598fe96085Stim szeto newkey->pgr_key_lpt_len > 0) {
18608fe96085Stim szeto kmem_free(newkey->pgr_key_lpt_id,
18618fe96085Stim szeto newkey->pgr_key_lpt_len);
18628fe96085Stim szeto }
1863716c1805SNattuvetty Bhavyan lpt_len = sizeof (scsi_devid_desc_t) +
18648fe96085Stim szeto lpt->ident_length;
18658fe96085Stim szeto newkey->pgr_key_lpt_len = lpt_len;
18668fe96085Stim szeto newkey->pgr_key_lpt_id = (scsi_devid_desc_t *)
18678fe96085Stim szeto kmem_zalloc(lpt_len, KM_SLEEP);
18688fe96085Stim szeto bcopy(lpt, newkey->pgr_key_lpt_id, lpt_len);
18698fe96085Stim szeto }
1870716c1805SNattuvetty Bhavyan /* No IT nexus information, hence set PGR_CHEK flag */
1871716c1805SNattuvetty Bhavyan sbd_pgr_set_pgr_check_flag(slu, B_TRUE);
18728fe96085Stim szeto } else {
1873716c1805SNattuvetty Bhavyan newkey = sbd_pgr_do_register(slu, NULL, lpt, &rport,
1874716c1805SNattuvetty Bhavyan SBD_PGR_KEY_TPT_ID_FLAG, svc_key);
18758fe96085Stim szeto }
18768fe96085Stim szeto
1877716c1805SNattuvetty Bhavyan kmem_free(lpt, sizeof (scsi_devid_desc_t) + lpt->ident_length);
18788fe96085Stim szeto
18798fe96085Stim szeto /* Now reserve the key corresponding to the specified IT nexus */
18808fe96085Stim szeto pgr->pgr_rsvholder = newkey;
18818fe96085Stim szeto
18828fe96085Stim szeto if (plist->unreg) {
18838fe96085Stim szeto sbd_pgr_do_unregister(slu, it, key);
18848fe96085Stim szeto }
18858fe96085Stim szeto
18868fe96085Stim szeto
1887*61dfa509SRick McNeal /* Write to disk if aptpl is currently set or this task is setting it */
1888*61dfa509SRick McNeal if (plist->aptpl || (sbd_pgr_should_save(slu) == B_TRUE)) {
18898fe96085Stim szeto if (plist->aptpl)
18908fe96085Stim szeto PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
18918fe96085Stim szeto else
18928fe96085Stim szeto PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
18938fe96085Stim szeto
18948fe96085Stim szeto if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
18958fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
1896*61dfa509SRick McNeal STMF_SAA_INSUFFICIENT_REG_RESRCS);
18978fe96085Stim szeto return;
18988fe96085Stim szeto }
18998fe96085Stim szeto }
19008fe96085Stim szeto
19018fe96085Stim szeto pgr->pgr_PRgeneration++;
19028fe96085Stim szeto stmf_scsilib_send_status(task, STATUS_GOOD, 0);
19038fe96085Stim szeto }
19048fe96085Stim szeto
19058fe96085Stim szeto void
sbd_pgr_remove_it_handle(sbd_lu_t * sl,sbd_it_data_t * my_it)1906*61dfa509SRick McNeal sbd_pgr_remove_it_handle(sbd_lu_t *sl, sbd_it_data_t *my_it)
1907*61dfa509SRick McNeal {
19088fe96085Stim szeto sbd_it_data_t *it;
19098fe96085Stim szeto
19108fe96085Stim szeto rw_enter(&sl->sl_pgr->pgr_lock, RW_WRITER);
19118fe96085Stim szeto mutex_enter(&sl->sl_lock);
19128fe96085Stim szeto for (it = sl->sl_it_list; it != NULL; it = it->sbd_it_next) {
19138fe96085Stim szeto if (it == my_it) {
19148fe96085Stim szeto if (it->pgr_key_ptr) {
19158fe96085Stim szeto sbd_pgr_key_t *key = it->pgr_key_ptr;
19168fe96085Stim szeto if (key->pgr_key_it == it) {
19178fe96085Stim szeto key->pgr_key_it = NULL;
19188fe96085Stim szeto sl->sl_pgr->pgr_flags &=
19198fe96085Stim szeto ~SBD_PGR_ALL_KEYS_HAS_IT;
19208fe96085Stim szeto }
19218fe96085Stim szeto }
19228fe96085Stim szeto break;
19238fe96085Stim szeto }
19248fe96085Stim szeto }
19258fe96085Stim szeto mutex_exit(&sl->sl_lock);
19268fe96085Stim szeto rw_exit(&sl->sl_pgr->pgr_lock);
19278fe96085Stim szeto
19288fe96085Stim szeto }
19298fe96085Stim szeto
19308fe96085Stim szeto char *
sbd_get_devid_string(sbd_lu_t * sl)19318fe96085Stim szeto sbd_get_devid_string(sbd_lu_t *sl)
19328fe96085Stim szeto {
19338fe96085Stim szeto char *str = (char *)kmem_zalloc(33, KM_SLEEP);
19348fe96085Stim szeto (void) snprintf(str, 33,
19358fe96085Stim szeto "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
19368fe96085Stim szeto sl->sl_device_id[4], sl->sl_device_id[5], sl->sl_device_id[6],
19378fe96085Stim szeto sl->sl_device_id[7], sl->sl_device_id[8], sl->sl_device_id[9],
19388fe96085Stim szeto sl->sl_device_id[10], sl->sl_device_id[11], sl->sl_device_id[12],
19398fe96085Stim szeto sl->sl_device_id[13], sl->sl_device_id[14], sl->sl_device_id[15],
19408fe96085Stim szeto sl->sl_device_id[16], sl->sl_device_id[17], sl->sl_device_id[18],
19418fe96085Stim szeto sl->sl_device_id[19]);
19428fe96085Stim szeto return (str);
19438fe96085Stim szeto }
1944