diff options
author | jdunham <none@none> | 2007-09-13 15:17:59 -0700 |
---|---|---|
committer | jdunham <none@none> | 2007-09-13 15:17:59 -0700 |
commit | 68941780f0da57f6844d5666a8528421c53133bc (patch) | |
tree | 6480da8f31da1d410bfb4e42ffb2707792b31e08 /deleted_files | |
parent | dd5829d1456ba00e6f704e6a88e7eaae608e3c1b (diff) | |
download | illumos-gate-68941780f0da57f6844d5666a8528421c53133bc.tar.gz |
6415440 iSCSI target needs persistent reserve support
--HG--
rename : deleted_files/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.c => usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.c
rename : deleted_files/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.h => usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.h
rename : deleted_files/usr/src/uts/common/sys/scsi/generic/persist.h => usr/src/uts/common/sys/scsi/generic/persist.h
Diffstat (limited to 'deleted_files')
-rw-r--r-- | deleted_files/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.c | 1913 | ||||
-rw-r--r-- | deleted_files/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.h | 165 | ||||
-rw-r--r-- | deleted_files/usr/src/uts/common/sys/scsi/generic/persist.h | 398 |
3 files changed, 0 insertions, 2476 deletions
diff --git a/deleted_files/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.c b/deleted_files/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.c deleted file mode 100644 index 99da20d627..0000000000 --- a/deleted_files/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.c +++ /dev/null @@ -1,1913 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * []------------------------------------------------------------------[] - * | Implementation of SPC-3 Persistent Reserve emulation | - * []------------------------------------------------------------------[] - */ -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/asynch.h> -#include <sys/param.h> -#include <sys/sysmacros.h> -#include <strings.h> -#include <unistd.h> -#include <pthread.h> -#include <assert.h> - -#include <sys/scsi/generic/sense.h> -#include <sys/scsi/generic/status.h> -#include <sys/scsi/generic/inquiry.h> -#include <sys/scsi/generic/mode.h> -#include <sys/scsi/generic/commands.h> -#include <sys/scsi/generic/persist.h> - -#include "t10.h" -#include "t10_spc.h" -#include "t10_spc_pr.h" -#include "t10_sbc.h" -#include "target.h" - -/* - * External declarations - */ -void spc_free(emul_handle_t id); -void sbc_cmd(t10_cmd_t *, uint8_t *, size_t); -void sbc_cmd_reserved(t10_cmd_t *, uint8_t *, size_t); - -extern target_queue_t *mgmtq; - -/* - * Forward declarations - */ -static - spc_pr_rsrv_t *spc_pr_rsrv_find(scsi3_pgr_t *, uint64_t, uint64_t, char *); -static - spc_pr_rsrv_t *spc_pr_rsrv_alloc(scsi3_pgr_t *, uint64_t, uint64_t, char *, - uint8_t, uint8_t); -static - spc_pr_key_t *spc_pr_key_find(scsi3_pgr_t *, uint64_t, uint64_t, char *); -static - spc_pr_key_t *spc_pr_key_alloc(scsi3_pgr_t *, uint64_t, uint64_t, char *); - -static void spc_pr_rsrv_release(t10_cmd_t *, scsi3_pgr_t *, spc_pr_rsrv_t *); -static void spc_pr_key_free(scsi3_pgr_t *, spc_pr_key_t *); -static void spc_pr_rsrv_free(scsi3_pgr_t *, spc_pr_rsrv_t *); -static void spc_pr_erase(scsi3_pgr_t *); -static void spc_pr_key_rsrv_init(scsi3_pgr_t *); - -static int spc_pr_register(t10_cmd_t *, void *, size_t); -static int spc_pr_reserve(t10_cmd_t *, void *, size_t); -static int spc_pr_release(t10_cmd_t *, void *, size_t); -static int spc_pr_clear(t10_cmd_t *, void *, size_t); -static int spc_pr_preempt(t10_cmd_t *, void *, size_t); -static int spc_pr_register_and_move(t10_cmd_t *, void *, size_t); - -static int spc_pr_in_readkeys(char *, scsi3_pgr_t *, void *, uint16_t); -static int spc_pr_in_readrsrv(char *, scsi3_pgr_t *, void *, uint16_t); -static int spc_pr_in_repcap(char *, scsi3_pgr_t *, void *, uint16_t); -static int spc_pr_in_fullstat(char *, scsi3_pgr_t *, void *, uint16_t); - -static int spc_pgr_isconflict(uint8_t *, uint_t); -Boolean_t spc_pr_write(t10_cmd_t *); - -/* - * []---- - * | spc_pgr_check -- PERSISTENT_RESERVE {IN|OUT} check of I_T_L - * | Refer to SPC-3, Section ?.?, Tables ?? and ?? - * []---- - */ -Boolean_t -spc_pgr_check(t10_cmd_t *cmd, uint8_t *cdb) -{ - disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd); - sbc_reserve_t *res = &p->d_sbc_reserve; - scsi3_pgr_t *pgr = &res->res_scsi_3_pgr; - spc_pr_rsrv_t *rsrv; - Boolean_t conflict = False; - - /* - * Check reservation commands. - */ - switch (cdb[0]) { - /* - * Always dis-allow these commands. - */ - case SCMD_RESERVE: - case SCMD_RESERVE_G1: - case SCMD_RELEASE: - case SCMD_RELEASE_G1: - conflict = True; - goto done; - - /* - * Always allow these commands. - */ - case SCMD_PERSISTENT_RESERVE_IN: - case SCMD_PERSISTENT_RESERVE_OUT: - conflict = False; - goto done; - } - - /* - * If no reservations exist, allow all remaining command types. - */ - assert(res->res_type == RT_PGR); - if (pgr->pgr_numrsrv == 0) { - conflict = False; - goto done; - } - - /* - * At this point we know there is at least one reservation. - * If there is no reservation set on this service delivery - * port then conflict all remaining command types. - */ - if (!(rsrv = spc_pr_rsrv_find(pgr, 0, 0, T10_PGR_TID(cmd)))) { - queue_prt(mgmtq, Q_PR_IO, "PGR Reserved on other port\n", - "\t%016x:%s\n", T10_PGR_ISID(cmd), T10_PGR_TID(cmd)); - conflict = True; - goto done; - } - - /* - * Check the command against the reservation type for this port. - */ - switch (rsrv->r_type) { - case PGR_TYPE_WR_EX: - case PGR_TYPE_EX_AC: - if (T10_PGR_ISID(cmd) == rsrv->r_isid) - conflict = False; - else - conflict = spc_pgr_isconflict(cdb, - rsrv->r_type); - break; - case PGR_TYPE_WR_EX_RO: - case PGR_TYPE_EX_AC_RO: - if (spc_pr_key_find( - pgr, 0, T10_PGR_ISID(cmd), T10_PGR_TID(cmd))) - conflict = False; - else - conflict = spc_pgr_isconflict(cdb, - rsrv->r_type); - break; - case PGR_TYPE_WR_EX_AR: - case PGR_TYPE_EX_AC_AR: - if (spc_pr_key_find(pgr, 0, 0, T10_PGR_TID(cmd))) - conflict = False; - else - conflict = spc_pgr_isconflict(cdb, - rsrv->r_type); - break; - default: - conflict = True; - break; - } - -done: - queue_prt(mgmtq, Q_PR_IO, "PGR%d LUN%d CDB:%s - spc_pgr_check(%s)\n", - cmd->c_lu->l_targ->s_targ_num, - cmd->c_lu->l_common->l_num, - cmd->c_lu->l_cmd_table[cmd->c_cdb[0]].cmd_name == NULL - ? "(no name)" - : cmd->c_lu->l_cmd_table[cmd->c_cdb[0]].cmd_name, - (conflict) ? "Conflict" : "Allowed"); - - return (conflict); -} - -/* - * []---- - * | spc_pgr_isconflict - * | PGR reservation conflict checking. - * | SPC-3, Revision 23, Table 31 - * []---- - */ -static int -spc_pgr_isconflict(uint8_t *cdb, uint_t type) -{ - Boolean_t conflict = False; - - switch (cdb[0]) { - case SCMD_FORMAT: - case SCMD_EXTENDED_COPY: - case SCMD_LOG_SELECT_G1: - case SCMD_MODE_SELECT: - case SCMD_MODE_SELECT_G1: - case SCMD_MODE_SENSE: - case SCMD_MODE_SENSE_G1: - case SCMD_READ_ATTRIBUTE: - case SCMD_READ_BUFFER: - case SCMD_GDIAG: /* SCMD_RECEIVE_DIAGNOSTIC_RESULTS */ - case SCMD_SDIAG: /* SCMD_SEND_DIAGNOSTIC_RESULTS */ - case SCMD_WRITE_ATTRIBUTE: - case SCMD_WRITE_BUFFER: - conflict = True; - break; - - case SCMD_DOORLOCK: /* SCMD_PREVENT_ALLOW_MEDIA_REMOVAL */ - /* - * As per SPC-3, Revision 23, Table 31 - * (prevent <> 0) - */ - conflict = (cdb[4] & 0x1) ? True: False; - break; - - case SCMD_REPORT_TARGET_PORT_GROUPS: /* SCMD_REPORT_ */ - /* - * As pee SPC-3, Revision 23, Section 6.23 - */ - switch ((cdb[1] & 0x03)) { - /* SCMD_REPORT_SUPPORTED_OPERATION_CODES */ - case 0x0c: - /* SCMD_REPORT_SUPPORTED_MANAGEMENT_FUNCTIONS */ - case 0x0d: - - conflict = True; - break; - } - break; - - case SCMD_SET_DEVICE: - /* - * SPC-3, Revision 23, Section 6.29 - */ - switch ((cdb[1] & 0x1F)) { - case SCMD_SET_DEVICE_IDENTIFIER: - case SCMD_SET_PRIORITY: - case SCMD_SET_TARGET_PORT_GROUPS: - case SCMD_SET_TIMESTAMP: - conflict = True; - break; - } - break; - - case SCMD_READ: - case SCMD_READ_G1: - case SCMD_READ_G4: - if (type == PGR_TYPE_EX_AC || type == PGR_TYPE_EX_AC_RO) - conflict = True; - break; - } - - return (conflict); -} - - -/* - * []---- - * | spc_cmd_pr_in -- PERSISTENT_RESERVE IN - * | Refer to SPC-3, Section 6.1, Tables ?? and ?? - * []---- - */ -/*ARGSUSED*/ -void -spc_cmd_pr_in(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len) -{ - scsi_cdb_prin_t *p_prin = (scsi_cdb_prin_t *)cdb; - disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd); - sbc_reserve_t *res = &p->d_sbc_reserve; - scsi3_pgr_t *pgr = &res->res_scsi_3_pgr; - uint16_t alen; - size_t len; - void *buf; - Boolean_t status; - - /* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.11 PERSISTENCE RESERVE IN - * Need to generate a CHECK CONDITION with ILLEGAL REQUEST - * and INVALID FIELD IN CDB (0x24/0x00) if any of the following is - * true. - * (1) The SERVICE ACTION field is 004h - 01fh, - * (2) The reserved area in byte 1 is set, - * (3) The reserved area in bytes 2 thru 6 are set, - * (4) If any of the reserved bits in the CONTROL byte are set. - */ - if ((p_prin->action >= 0x4) || p_prin->resbits || p_prin->resbytes[0] || - p_prin->resbytes[1] || p_prin->resbytes[2] || p_prin->resbytes[3] || - p_prin->resbytes[4] || p_prin->control) { - spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0); - spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00); - trans_send_complete(cmd, STATUS_CHECK); - return; - } - - /* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.11 PERSISTENCE RESERVE IN - * Acquire ALLOCATION LENGTH from bytes 7, 8 - * A zero(0) length allocation is not an error and we should just - * acknowledge the operation. - */ - if ((alen = SCSI_READ16(p_prin->alloc_len)) == 0) { - queue_prt(mgmtq, Q_PR_IO, - "PGR:%d LUN:%d CDB:%s - spc_cmd_pr_in, len = 0\n", - cmd->c_lu->l_targ->s_targ_num, - cmd->c_lu->l_common->l_num, - cmd->c_lu->l_cmd_table[cmd->c_cdb[0]].cmd_name == NULL - ? "(no name)" - : cmd->c_lu->l_cmd_table[cmd->c_cdb[0]].cmd_name); - - trans_send_complete(cmd, STATUS_GOOD); - return; - } - - /* - * Allocate space with an alignment that will work for any casting. - */ - if ((buf = memalign(sizeof (void *), alen)) == NULL) { - /* - * Lack of memory is not fatal, just too busy - */ - trans_send_complete(cmd, STATUS_BUSY); - return; - } else { - bzero(buf, alen); - } - - /* - * Start processing, lock reservation - */ - pthread_rwlock_rdlock(&res->res_rwlock); - - /* - * Per SPC-3, Revision 23, Table 102, validate ranget of service actions - */ - switch (p_prin->action) { - case PR_IN_READ_KEYS: - len = spc_pr_in_readkeys( - T10_PGR_TID(cmd), pgr, buf, alen); - break; - case PR_IN_READ_RESERVATION: - len = spc_pr_in_readrsrv( - T10_PGR_TID(cmd), pgr, buf, alen); - break; - case PR_IN_REPORT_CAPABILITIES: - len = spc_pr_in_repcap( - T10_PGR_TID(cmd), pgr, buf, alen); - break; - case PR_IN_READ_FULL_STATUS: - len = spc_pr_in_fullstat( - T10_PGR_TID(cmd), pgr, buf, alen); - break; - default: - pthread_rwlock_unlock(&res->res_rwlock); - spc_free(buf); - - /* - * Fail command - */ - spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0); - spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00); - trans_send_complete(cmd, STATUS_CHECK); - return; - } - - /* - * Complete processing, unlock reservation - */ - pthread_rwlock_unlock(&res->res_rwlock); - - /* - * Now send the selected Persistent Reservation response back - */ - if (trans_send_datain(cmd, buf, alen, 0, spc_free, True, buf) == False) - trans_send_complete(cmd, STATUS_BUSY); -} - -/* - * []---- - * | spc_pr_in_readkey - - * | Refer to SPC-3, Section 6.1, Tables ?? and ?? - * []---- - */ -static int -spc_pr_in_readkeys(char *transportID, scsi3_pgr_t *pgr, void *bp, - uint16_t alloc_len) -{ - int i = 0, max_buf_keys, hsize; - scsi_prin_readrsrv_t *buf = (scsi_prin_readrsrv_t *)bp; - spc_pr_key_t *key; - - hsize = sizeof (buf->PRgeneration) + sizeof (buf->add_len); - max_buf_keys = ((int)alloc_len - hsize) / sizeof (key->k_key); - - queue_prt(mgmtq, Q_PR_IO, - "PGRIN readkeys - transportID=%s\n", transportID); - - if (pgr->pgr_numkeys) - for (key = (spc_pr_key_t *)pgr->pgr_keylist.lnk_fwd; - key != (spc_pr_key_t *)&pgr->pgr_keylist; - key = (spc_pr_key_t *)key->k_link.lnk_fwd) { - - if (strcmp(key->k_transportID, transportID)) - continue; - - if (i < max_buf_keys) - SCSI_WRITE64(buf->res_key_list[i].reservation_key, - key->k_key); - - queue_prt(mgmtq, Q_PR_IO, - "PGRIN readkeys - key:%016x, isid:%016x\n", - key->k_key, key->k_isid); - - i++; - } - - SCSI_WRITE32(buf->add_len, i * sizeof (key->k_key)); - SCSI_WRITE32(buf->PRgeneration, pgr->pgr_generation); - - return (hsize + min(SCSI_READ32(buf->add_len), - (int)(max_buf_keys * sizeof (key->k_key)))); -} - -/* - * []---- - * | spc_pr_in_readresv - - * | Refer to SPC-3, Section 6.1, Tables ?? and ?? - * []---- - */ -static int -spc_pr_in_readrsrv( - char *transportID, scsi3_pgr_t *pgr, void *bp, uint16_t alloc_len) -{ - int i = 0, max_buf_rsrv, hsize; - spc_pr_rsrv_t *rsrv; - scsi_prin_readrsrv_t *buf = (scsi_prin_readrsrv_t *)bp; - - hsize = sizeof (buf->PRgeneration) + sizeof (buf->add_len); - max_buf_rsrv = ((int)alloc_len - hsize) / sizeof (scsi_prin_rsrvdesc_t); - - queue_prt(mgmtq, Q_PR_IO, - "PGRIN readrsrv - transportID=%s\n", transportID); - - if (pgr->pgr_numrsrv) - for (rsrv = (spc_pr_rsrv_t *)pgr->pgr_rsrvlist.lnk_fwd; - rsrv != (spc_pr_rsrv_t *)&pgr->pgr_rsrvlist; - rsrv = (spc_pr_rsrv_t *)rsrv->r_link.lnk_fwd) { - - if (strcmp(rsrv->r_transportID, transportID)) - continue; - - if (i < max_buf_rsrv) { - SCSI_WRITE64(buf->res_key_list[i].reservation_key, - rsrv->r_key); - buf->res_key_list[i].scope = rsrv->r_scope; - buf->res_key_list[i].type = rsrv->r_type; - } - - queue_prt(mgmtq, Q_PR_IO, - "PGRIN readrsrv - " - "key:%016x isid:%016x scope:%d type:%d \n", - rsrv->r_key, rsrv->r_isid, rsrv->r_scope, rsrv->r_type); - - i++; - } - - SCSI_WRITE32(buf->add_len, i * sizeof (scsi_prin_rsrvdesc_t)); - SCSI_WRITE32(buf->PRgeneration, pgr->pgr_generation); - - return (hsize + min(SCSI_READ32(buf->add_len), - (int)(max_buf_rsrv * sizeof (scsi_prin_rsrvdesc_t)))); -} - -/* - * []---- - * | spc_pr_in_repcap - - * | Refer to SPC-3, Section 6.1, Tables ?? and ?? - * []---- - */ -/* - */ -static int -spc_pr_in_repcap( - char *transportID, scsi3_pgr_t *pgr, void *bp, uint16_t alloc_len) -{ - scsi_prin_rpt_cap_t *buf = (scsi_prin_rpt_cap_t *)bp; - - buf->crh = 0; /* Supports Reserve / Release */ - buf->sip_c = 1; /* Specify Initiator Ports Capable */ - buf->atp_c = 1; /* All Target Ports Capable */ - buf->ptpl_c = 1; /* Persist Through Power Loss C */ - buf->tmv = 1; /* Type Mask Valid */ - buf->ptpl_a = pgr_persist; /* Persist Though Power Loss Active */ - buf->pr_type.wr_ex = 1; /* Write Exclusve */ - buf->pr_type.ex_ac = 1; /* Exclusive Access */ - buf->pr_type.wr_ex_ro = 1; /* Write Exclusive Registrants Only */ - buf->pr_type.ex_ac_ro = 1; /* Exclusive Access Registrants Only */ - buf->pr_type.wr_ex_ar = 1; /* Write Exclusive All Registrants */ - buf->pr_type.ex_ac_ar = 1; /* Exclusive Access All Registrants */ - - SCSI_WRITE16(buf->length, sizeof (scsi_prin_rpt_cap_t)); - - return (sizeof (scsi_prin_rpt_cap_t)); -} - -/* - * []---- - * | spc_pr_in_fullstat - - * | Refer to SPC-3, Section 6.1, Tables ?? and ?? - * []---- - */ -/* - */ -static int -spc_pr_in_fullstat( - char *transportID, scsi3_pgr_t *pgr, void *bp, uint16_t alloc_len) -{ - int i = 0, max_buf_rsrv, hsize; - spc_pr_rsrv_t *rsrv; - scsi_prin_full_status_t *buf = (scsi_prin_full_status_t *)bp; - - hsize = sizeof (buf->PRgeneration) + sizeof (buf->add_len); - max_buf_rsrv = ((int)alloc_len - hsize) / - sizeof (scsi_prin_full_status_t); - - if (pgr->pgr_numrsrv) - for (i = 0, rsrv = (spc_pr_rsrv_t *)pgr->pgr_rsrvlist.lnk_fwd; - rsrv != (spc_pr_rsrv_t *)&pgr->pgr_rsrvlist; - rsrv = (spc_pr_rsrv_t *)rsrv->r_link.lnk_fwd) { - - if (i < max_buf_rsrv) { - SCSI_WRITE64(buf->full_desc[i].reservation_key, - rsrv->r_key); - buf->full_desc[i].all_tg_pt = 1; - buf->full_desc[i].r_holder = - strcmp(rsrv->r_transportID, transportID) ? 0 : 1; - buf->full_desc[i].scope = rsrv->r_scope; - buf->full_desc[i].type = rsrv->r_type; - SCSI_WRITE16(buf->full_desc[i].rel_tgt_port_id, 0); - SCSI_WRITE32(buf->full_desc[i].add_len, - sizeof (scsi_transport_id_t)); - buf->full_desc[i].trans_id.protocol_id = - iSCSI_PROTOCOL_ID; - buf->full_desc[i].trans_id.format_code = - WW_UID_DEVICE_NAME; - SCSI_WRITE16(buf->full_desc[i].trans_id.add_len, 0); - sprintf(buf->full_desc[i].trans_id.iscsi_name, ""); - } - - i++; - } - - SCSI_WRITE32(buf->add_len, i * sizeof (scsi_prin_rsrvdesc_t)); - SCSI_WRITE32(buf->PRgeneration, pgr->pgr_generation); - - return (hsize + min(SCSI_READ32(buf->add_len), - (int)(max_buf_rsrv * sizeof (scsi_prin_rsrvdesc_t)))); - -} - -/* - * []---- - * | spc_cmd_pr_out -- PERSISTENT_RESERVE OUT - * | Refer to SPC-3, Section 6.1, Tables ?? and ?? - * []---- - */ -/*ARGSUSED*/ -void -spc_cmd_pr_out(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len) -{ - scsi_cdb_prout_t *p_prout = (scsi_cdb_prout_t *)cdb; - disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd); - sbc_reserve_t *res = &p->d_sbc_reserve; - size_t len; - void *buf; - - /* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.12 PERSISTENCE RESERVE OUT - * Need to generate a CHECK CONDITION with ILLEGAL REQUEST - * and INVALID FIELD IN CDB (0x24/0x00) if any of the following is - * true. - * (1) The SERVICE ACTION field is 008h - 01fh, - * (2) The reserved area in byte 1 is set, - * (3) The TYPE and SCOPE fields are invalid, - * (4) The reserved area in bytes 3 and 4 are set, - * (5) If any of the reserved bits in the CONTROL byte are set. - */ - if ((p_prout->action >= 0x8) || p_prout->resbits || - (p_prout->type >= 0x9) || - (p_prout->scope >= 0x3) || p_prout->control) { - spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0); - spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00); - trans_send_complete(cmd, STATUS_CHECK); - return; - } - - /* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.12 PERSISTENCE RESERVE OUT - * Acquire ALLOCATION LENGTH from bytes 5 thru 8 - */ - len = SCSI_READ32(p_prout->param_len); - - /* - * Parameter list length shall contain 24 (0x18), - * the SPEC_I_PIT is zero (it is because we don't support SIP_C)) - * the service action is not REGISTER AND MOVE - */ - if ((p_prout->action != PR_OUT_REGISTER_MOVE) && (len != 24)) { - spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0); - spc_sense_ascq(cmd, SPC_ASC_PARAM_LIST_LEN, 0x00); - trans_send_complete(cmd, STATUS_CHECK); - return; - } - - /* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.11.3.3 Persistent Reservation Scope - * SCOPE field shall be set to LU_SCOPE - */ - if (p_prout->scope != PR_LU_SCOPE) { - pthread_rwlock_unlock(&res->res_rwlock); - spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0); - spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00); - trans_send_complete(cmd, STATUS_CHECK); - return; - } - - /* - * Allocate space with an alignment that will work for any casting. - */ - if ((buf = memalign(sizeof (void *), len)) == NULL) { - /* - * Lack of memory is not fatal, just too busy - */ - trans_send_complete(cmd, STATUS_BUSY); - return; - } - - /* - * Now request the Persistent Reserve OUT parameter list - */ - if (trans_rqst_dataout(cmd, buf, len, 0, buf, spc_free) == False) - trans_send_complete(cmd, STATUS_BUSY); -} - -/* - * []---- - * | spc_cmd_pr_out_data -- DataIn phase of PERSISTENT_RESERVE OUT command - * []---- - */ -/*ARGSUSED*/ -void -spc_cmd_pr_out_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data, - size_t data_len) -{ - scsi_cdb_prout_t *p_prout = (scsi_cdb_prout_t *)cmd->c_cdb; - disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd); - scsi_prout_plist_t *plist = (scsi_prout_plist_t *)data; - sbc_reserve_t *res = &p->d_sbc_reserve; - scsi3_pgr_t *pgr = &res->res_scsi_3_pgr; - t10_lu_impl_t *lu; - int status; - - /* - * If this is the first time using the persistance data, - * initialize the reservation and resource key queues - */ - pthread_rwlock_wrlock(&res->res_rwlock); - if (pgr->pgr_rsrvlist.lnk_fwd == NULL) { - spc_pr_key_rsrv_init(pgr); - } - - /* - * Now process the action. - */ - switch (p_prout->action) { - case PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY: - case PR_OUT_REGISTER: - /* - * PR_OUT_REGISTER_IGNORE differs from PR_OUT_REGISTER - * in that the reservation_key is ignored. - */ - status = spc_pr_register(cmd, data, data_len); - break; - - case PR_OUT_RESERVE: - status = spc_pr_reserve(cmd, data, data_len); - break; - - case PR_OUT_RELEASE: - status = spc_pr_release(cmd, data, data_len); - break; - - case PR_OUT_CLEAR: - status = spc_pr_clear(cmd, data, data_len); - break; - - case PR_OUT_PREEMPT_ABORT: - case PR_OUT_PREEMPT: - /* - * PR_OUT_PREEMPT_ABORT differs from PR_OUT_PREEMPT - * in that all current acitivy for the preempted - * Initiators will be terminated. - */ - status = spc_pr_preempt(cmd, data, data_len); - break; - - case PR_OUT_REGISTER_MOVE: - /* - * PR_OUT_REGISTER_MOVE registers a key for another I_T - */ - status = spc_pr_register_and_move(cmd, data, data_len); - break; - } - - /* - * Check status of action performed. - */ - if (status == STATUS_CHECK) { - /* - * Check condition required. - */ - pthread_rwlock_unlock(&res->res_rwlock); - spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0); - spc_sense_ascq(cmd, cmd->c_lu->l_asc, cmd->c_lu->l_ascq); - trans_send_complete(cmd, STATUS_CHECK); - return; - } - - /* - * Handle Failed processing status - */ - if (status != STATUS_GOOD) { - pthread_rwlock_unlock(&res->res_rwlock); - trans_send_complete(cmd, status); - return; - } - - /* - * Successful, bump the PRgeneration value - */ - if (p_prout->action != PR_OUT_RESERVE && - p_prout->action != PR_OUT_RELEASE) - pgr->pgr_generation++; - - /* - * If Activate Persist Through Power Loss (APTPL) is set, persist - * this PGR data on disk - */ - if (plist->aptpl || pgr->pgr_aptpl) - spc_pr_write(cmd); - - /* - * When the last registration is removed, PGR is no longer - * active and we must reset the reservation type. - */ - if (pgr->pgr_numkeys == 0 && pgr->pgr_numrsrv == 0) { - res->res_type = RT_NONE; - pgr->pgr_aptpl = 0; - } else { - res->res_type = RT_PGR; - } - - /* - * Set the command dispatcher according to the reservation type - */ - lu = avl_first(&cmd->c_lu->l_common->l_all_open); - do { - lu->l_cmd = (res->res_type == RT_NONE) - ? sbc_cmd - : sbc_cmd_reserved; - lu = AVL_NEXT(&cmd->c_lu->l_common->l_all_open, lu); - } while (lu != NULL); - - queue_prt(mgmtq, Q_PR_IO, "PGROUT:%d LUN:%d action:%s\n", - cmd->c_lu->l_targ->s_targ_num, - cmd->c_lu->l_common->l_num, - (p_prout->action == PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY) - ? "Register & ignore existing key" - : (p_prout->action == PR_OUT_REGISTER) - ? "Register" - : (p_prout->action == PR_OUT_RESERVE) - ? "Reserve" - : (p_prout->action == PR_OUT_RELEASE) - ? "Release" - : (p_prout->action == PR_OUT_CLEAR) - ? "Clear" - : (p_prout->action == PR_OUT_PREEMPT_ABORT) - ? "Preempt & abort" - : (p_prout->action == PR_OUT_PREEMPT) - ? "Preempt" - : (p_prout->action == PR_OUT_REGISTER_MOVE) - ? "Register & move" - : "Uknown"); - - /* - * Processing is complete, release mutex - */ - pthread_rwlock_unlock(&res->res_rwlock); - - /* - * Send back a succesful response - */ - trans_send_complete(cmd, STATUS_GOOD); -} - -/* - * []---- - * | spc_pr_register - * | Refer to SPC-3, Section 6.1, Tables ?? and ?? - * []---- - */ -static int -spc_pr_register(t10_cmd_t *cmd, void *data, size_t data_len) -{ - scsi_cdb_prout_t *p_prout = (scsi_cdb_prout_t *)cmd->c_cdb; - scsi_prout_plist_t *plist = (scsi_prout_plist_t *)data; - disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd); - sbc_reserve_t *res = &p->d_sbc_reserve; - scsi3_pgr_t *pgr = &res->res_scsi_3_pgr; - spc_pr_rsrv_t *rsrv; - spc_pr_key_t *key; - uint64_t reservation_key; - uint64_t service_key; - t10_lu_impl_t *lu; - t10_targ_impl_t *ti; - - /* - * Validate Persistent Reserver Out parameter list - */ - if (plist->obsolete1[0] || plist->obsolete1[1] || - plist->obsolete1[2] || plist->obsolete1[3] || - plist->resbits1 || plist->resbits2 || plist->resbytes1 || - plist->obsolete2[0] || plist->obsolete2[1]) { - cmd->c_lu->l_status = KEY_ILLEGAL_REQUEST; - cmd->c_lu->l_asc = SPC_ASC_INVALID_CDB; - cmd->c_lu->l_ascq = 0; - return (STATUS_CHECK); - } - - /* - * Determine if Activate Persist Trhough Power Loss (APTPL) - * is valid for this device server. - */ - if (plist->aptpl && (pgr_persist == 0)) { - /* pgr - define SCSI-3 error codes */ - cmd->c_lu->l_status = KEY_ILLEGAL_REQUEST; - cmd->c_lu->l_asc = SPC_ASC_INVALID_FIELD_IN_PARAMETER_LIST; - cmd->c_lu->l_ascq = 0; - return (STATUS_CHECK); - } - - /* - * Get reservation values - */ - reservation_key = SCSI_READ64(plist->reservation_key); - service_key = SCSI_READ64(plist->service_key); - - queue_prt(mgmtq, Q_PR_IO, - "PGROUT: register reservation:%016x, key:%016x\n", - reservation_key, service_key); - - /* - * We may need register all initiators, depending on ALL_TG_TP - */ - lu = avl_first(&cmd->c_lu->l_common->l_all_open); - do { - /* - * Find specified key - */ - ti = lu->l_targ; - key = spc_pr_key_find(pgr, 0, ti->s_isid, ti->s_transportID); - if (key) { - /* - * What about ALL_TG_TP? - */ - if (plist->all_tg_pt || - (key->k_isid == T10_PGR_ISID(cmd))) { - - if (p_prout->action == PR_OUT_REGISTER && - key->k_key != reservation_key) { - /* - * The Initiator did not specify the - * existing key. Reservation conflict. - */ - return (STATUS_RESERVATION_CONFLICT); - } - /* - * Change existing key ? - */ - if (service_key) { - queue_prt(mgmtq, Q_PR_IO, - "PGROUT: change " - "old:%016x = new:%016x\n", - key->k_key, service_key); - - /* - * Overwrite (change) key - */ - key->k_key = service_key; - - } else { - /* - * Remove existing key - * NOTE: If we own the reservation then - * we must release it. - */ - queue_prt(mgmtq, Q_PR_IO, - "PGROUT: delete " - "old:%016x = new:%016x\n", - key->k_key, service_key); - - rsrv = spc_pr_rsrv_find(pgr, 0, - ti->s_isid, ti->s_transportID); - if (rsrv) { - spc_pr_rsrv_release( - cmd, pgr, rsrv); - spc_pr_key_free(pgr, key); - } - } - } - } else { - /* - * What about ALL_TG_TP? - */ - if (plist->all_tg_pt || - (ti->s_isid == T10_PGR_ISID(cmd))) { - /* - * Process request from un-registered Initiator. - */ - if ((p_prout->action == PR_OUT_REGISTER) && - (reservation_key || service_key == 0)) { - /* - * Unregistered initiator is attempting - * to modify a key. - */ - return (STATUS_RESERVATION_CONFLICT); - } - - /* - * Allocate new key. - */ - queue_prt(mgmtq, Q_PR_IO, - "PGROUT: new:%016x\n", service_key); - - key = spc_pr_key_alloc(pgr, service_key, - ti->s_isid, ti->s_transportID); - if (key == NULL) { - /* pgr - define SCSI-3 error codes */ - cmd->c_lu->l_status = - KEY_ABORTED_COMMAND; - cmd->c_lu->l_asc = - SPC_ASC_MEMORY_OUT_OF; - cmd->c_lu->l_ascq = - SPC_ASCQ_RESERVATION_FAIL; - return (STATUS_CHECK); - } - } - } - lu = AVL_NEXT(&cmd->c_lu->l_common->l_all_open, lu); - } while (lu != NULL); - - /* - * Apply the last valid APTPL bit - * SPC-3, Revision 23 - * Section 5.6.4.1 Preserving persistent reservervations and - * registrations through power loss - */ - pgr->pgr_aptpl = plist->aptpl; - - return (STATUS_GOOD); -} - -/* - * []---- - * | spc_pr_reserve - * | Refer to SPC-3, Section 6.1, Tables ?? and ?? - * []---- - */ -/* ARGSUSED */ -static int -spc_pr_reserve(t10_cmd_t *cmd, void *data, size_t data_len) -{ - scsi_cdb_prout_t *p_prout = (scsi_cdb_prout_t *)cmd->c_cdb; - disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd); - sbc_reserve_t *res = &p->d_sbc_reserve; - scsi3_pgr_t *pgr = &res->res_scsi_3_pgr; - spc_pr_rsrv_t *rsrv; - scsi_prout_plist_t *plist = (scsi_prout_plist_t *)data; - uint64_t reservation_key; - int status; - - /* - * Do not allow an unregistered initiator to - * make a reservation. - */ - reservation_key = SCSI_READ64(plist->reservation_key); - if (!spc_pr_key_find( - pgr, reservation_key, T10_PGR_ISID(cmd), T10_PGR_TID(cmd))) { - - queue_prt(mgmtq, Q_PR_IO, - "PGROUT: reserve reservation:%016x not found\n", - reservation_key); - - return (STATUS_RESERVATION_CONFLICT); - } else { - - queue_prt(mgmtq, Q_PR_IO, - "PGROUT: reserve reservation:%016x\n", reservation_key); - - } - - /* - * See if there is a reservation on this port by - * another Initiator. There can be only one LU_SCOPE - * reservation per ITL. We do not support extents. - */ - if (rsrv = spc_pr_rsrv_find(pgr, 0, 0, T10_PGR_TID(cmd))) { - if (rsrv->r_isid != T10_PGR_ISID(cmd)) { - - queue_prt(mgmtq, Q_PR_IO, - "PGROUT: reserve %016x != %016x:%s\n", - rsrv->r_isid, T10_PGR_ISID(cmd), - T10_PGR_TID(cmd)); - - return (STATUS_RESERVATION_CONFLICT); - } - } - - /* - * At this point there is either no reservation or the - * reservation is held by this Initiator. - */ - if (rsrv != NULL) { - - queue_prt(mgmtq, Q_PR_IO, - "PGROUT reserve(+) - transportID=%s\n" - "\tkey:%016x isid:%016x scope:%d type:%d \n", - rsrv->r_transportID, rsrv->r_key, rsrv->r_isid, - rsrv->r_scope, rsrv->r_type); - - /* - * An Initiator cannot re-reserve. It must first - * release. But if its' type and scope match then - * return STATUS_GOOD. - */ - if (rsrv->r_type == p_prout->type && - rsrv->r_scope == p_prout->scope) { - status = STATUS_GOOD; - } else { - status = STATUS_RESERVATION_CONFLICT; - } - } else { - /* - * No reservation exists. Establish a new one. - */ - queue_prt(mgmtq, Q_PR_IO, - "PGROUT reserve - transportID=%s\n" - "\tkey:%016x isid:%016x scope:%d type:%d \n", - T10_PGR_TID(cmd), reservation_key, T10_PGR_ISID(cmd), - p_prout->scope, p_prout->type); - - rsrv = spc_pr_rsrv_alloc(pgr, reservation_key, - T10_PGR_ISID(cmd), T10_PGR_TID(cmd), - p_prout->scope, p_prout->type); - if (rsrv == NULL) { - cmd->c_lu->l_status = KEY_ABORTED_COMMAND; - cmd->c_lu->l_asc = SPC_ASC_MEMORY_OUT_OF; - cmd->c_lu->l_ascq = SPC_ASCQ_RESERVATION_FAIL; - status = STATUS_CHECK; - } else { - status = STATUS_GOOD; - } - } - - return (status); -} - -/* - * []---- - * | spc_pr_release - * | Refer to SPC-3, Section 6.1, Tables ?? and ?? - * []---- - */ -static int -spc_pr_release(t10_cmd_t *cmd, void *data, size_t data_len) -{ - scsi_cdb_prout_t *p_prout = (scsi_cdb_prout_t *)cmd->c_cdb; - disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd); - sbc_reserve_t *res = &p->d_sbc_reserve; - scsi3_pgr_t *pgr = &res->res_scsi_3_pgr; - spc_pr_rsrv_t *rsrv; - scsi_prout_plist_t *plist = (scsi_prout_plist_t *)data; - uint64_t reservation_key; - int status; - - /* - * Do not allow an unregistered initiator to attempting to - * release a reservation. - */ - reservation_key = SCSI_READ64(plist->reservation_key); - if (!spc_pr_key_find( - pgr, reservation_key, T10_PGR_ISID(cmd), T10_PGR_TID(cmd))) { - - queue_prt(mgmtq, Q_PR_IO, - "PGROUT: release reservation:%016x not found\n", - reservation_key); - - return (STATUS_RESERVATION_CONFLICT); - } else { - - queue_prt(mgmtq, Q_PR_IO, - "PGROUT: release reservation:%016x\n", reservation_key); - } - - if (!(rsrv = spc_pr_rsrv_find( - pgr, 0, T10_PGR_ISID(cmd), T10_PGR_TID(cmd)))) { - /* - * Releasing a non-existent reservation is allowed. - */ - status = STATUS_GOOD; - - } else if (p_prout->scope != rsrv->r_scope || - p_prout->type != rsrv->r_type || - reservation_key != rsrv->r_key) { - queue_prt(mgmtq, Q_PR_IO, - "PGROUT release failed - transportID=%s\n" - "\tkey:%016x isid:%016x scope:%d type:%d \n", - T10_PGR_TID(cmd), reservation_key, T10_PGR_ISID(cmd), - p_prout->scope, p_prout->type); - - /* - * Scope and key must match to release. - */ - cmd->c_lu->l_status = KEY_ILLEGAL_REQUEST; - cmd->c_lu->l_asc = SPC_ASC_PARAMETERS_CHANGED; - cmd->c_lu->l_ascq = SPC_ASCQ_RES_RELEASED; - status = STATUS_CHECK; - } else { - /* - * Now release the reservation. - */ - queue_prt(mgmtq, Q_PR_IO, - "PGROUT release - transportID=%s\n" - "\tkey:%016x isid:%016x scope:%d type:%d \n", - rsrv->r_transportID, rsrv->r_key, rsrv->r_isid, - rsrv->r_scope, rsrv->r_type); - - spc_pr_rsrv_release(cmd, pgr, rsrv); - status = STATUS_GOOD; - } - - return (status); -} - -/* - * []---- - * | spc_pr_preempt - * | Refer to SPC-3, Section 6.1, Tables ?? and ?? - * []---- - */ -/* ARGSUSED */ -static int -spc_pr_preempt(t10_cmd_t *cmd, void *data, size_t data_len) -{ - scsi_cdb_prout_t *p_prout = (scsi_cdb_prout_t *)cmd->c_cdb; - t10_lu_impl_t *lu; - disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd); - sbc_reserve_t *res = &p->d_sbc_reserve; - scsi3_pgr_t *pgr = &res->res_scsi_3_pgr; - scsi_prout_plist_t *plist = (scsi_prout_plist_t *)data; - uint64_t reservation_key; - uint64_t service_key; - spc_pr_key_t *key; - spc_pr_rsrv_t *rsrv; - int status = STATUS_GOOD; - - /* - * Get reservation values - */ - reservation_key = SCSI_READ64(plist->reservation_key); - service_key = SCSI_READ64(plist->service_key); - - - /* - * Initiator must be registered and service key (preempt key) - * must exist. - */ - if ((!(key = spc_pr_key_find(pgr, service_key, 0, ""))) || - (!(rsrv = spc_pr_rsrv_find(pgr, reservation_key, - T10_PGR_ISID(cmd), "")))) { - - queue_prt(mgmtq, Q_PR_IO, - "PGROUT: preempt failed reservation:%016x, key:%016x\n", - reservation_key, service_key); - - return (STATUS_RESERVATION_CONFLICT); - } else { - - queue_prt(mgmtq, Q_PR_IO, - "PGROUT: preempt reservation:%016x, key:%016x\n", - reservation_key, service_key); - } - - /* - * Preempt all keys matching service action key and free - * the associated structures. Do not set UNIT_ATTN for - * the Initiator which requested the action. - * - * Unlike the other Persistent Reservation commands, the preempt, - * preempt_and_abort and clear actions are service delivery port - * independent. So we remove matching keys across ports. - */ - for (key = (spc_pr_key_t *)pgr->pgr_keylist.lnk_fwd; - key != (spc_pr_key_t *)&pgr->pgr_keylist; - key = (spc_pr_key_t *)key->k_link.lnk_fwd) { - - /* Skip non-matching keys */ - if (key->k_key != service_key) - continue; - - /* Remove the registration key. */ - spc_pr_key_free(pgr, key); - - /* Do not set UNIT ATTN for calling Initiator */ - if (key->k_isid == T10_PGR_ISID(cmd)) - continue; - - /* - * Find associated I_T Nexuses - */ - lu = avl_first(&cmd->c_lu->l_common->l_all_open); - do { - lu->l_cmd = sbc_cmd; - lu->l_status = KEY_UNIT_ATTENTION; - lu->l_asc = SPC_ASC_PARAMETERS_CHANGED; - lu->l_ascq = SPC_ASCQ_RES_PREEMPTED; - lu = AVL_NEXT(&cmd->c_lu->l_common->l_all_open, lu); - } while (lu != NULL); - - /* - * Is this the preempt and abort? - */ - if (p_prout->action == PR_OUT_PREEMPT_ABORT) { - queue_message_set( - cmd->c_lu->l_common->l_from_transports, - Q_HIGH, msg_reset_lu, (void *)cmd->c_lu); - } - } - - /* - * Re-establish our registration key if we preempted it. - */ - if (!(key = spc_pr_key_find( - pgr, reservation_key, T10_PGR_ISID(cmd), T10_PGR_TID(cmd)))) { - - queue_prt(mgmtq, Q_PR_IO, - "PGROUT: preempt - register:%016x, isid:%016x:%s\n", - reservation_key, T10_PGR_ISID(cmd), T10_PGR_TID(cmd)); - - key = spc_pr_key_alloc(pgr, reservation_key, - T10_PGR_ISID(cmd), T10_PGR_TID(cmd)); - } - - /* - * Now look for a matching reservation to preempt. - */ - for (rsrv = (spc_pr_rsrv_t *)pgr->pgr_rsrvlist.lnk_fwd; - rsrv != (spc_pr_rsrv_t *)&pgr->pgr_rsrvlist; - rsrv = (spc_pr_rsrv_t *)rsrv->r_link.lnk_fwd) { - - /* Skip non-matching keys */ - if (rsrv->r_key != service_key) - continue; - - /* - * Remove matching reservations on other ports - * and establish a new reservation on this port only. - * To change the fuctionality to preempt rather than - * delete the reservations on other ports just remove - * the following block of code. - */ - if (strcmp(rsrv->r_transportID, T10_PGR_TID(cmd))) { - spc_pr_rsrv_free(pgr, rsrv); - continue; - } - - rsrv->r_key = reservation_key; - rsrv->r_isid = T10_PGR_ISID(cmd); - rsrv->r_scope = p_prout->scope; - rsrv->r_type = p_prout->type; - - queue_prt(mgmtq, Q_PR_IO, - "PGROUT preempt - transportID=%s\n" - "\tkey:%016x isid:%016x scope:%d type:%d \n", - rsrv->r_transportID, rsrv->r_key, rsrv->r_isid, - rsrv->r_scope, rsrv->r_type); - } - - return (status); -} - -/* - * []---- - * | spc_pr_clear - * | Refer to SPC-3, Section 6.1, Tables ?? and ?? - * []---- - */ -/* ARGSUSED */ -static int -spc_pr_clear(t10_cmd_t *cmd, void *data, size_t data_len) -{ - scsi_cdb_prout_t *p_prout = (scsi_cdb_prout_t *)cmd->c_cdb; - disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd); - sbc_reserve_t *res = &p->d_sbc_reserve; - scsi3_pgr_t *pgr = &res->res_scsi_3_pgr; - scsi_prout_plist_t *plist = (scsi_prout_plist_t *)data; - uint64_t reservation_key; - spc_pr_key_t *key; - t10_targ_impl_t *tp; - t10_lu_impl_t *lu; - - /* - * Do not allow an unregistered initiator to attempting to - * clear the PGR. - */ - reservation_key = SCSI_READ64(plist->reservation_key); - if (!spc_pr_key_find(pgr, reservation_key, T10_PGR_ISID(cmd), "")) { - - queue_prt(mgmtq, Q_PR_IO, - "PGROUT: clear pgr:%016x not found\n", reservation_key); - - return (STATUS_RESERVATION_CONFLICT); - } else { - queue_prt(mgmtq, Q_PR_IO, - "PGROUT: clear pgr:%016x\n", reservation_key); - } - - /* - * We need to set UNIT ATTENTION for all registered initiators. - */ - for (key = (spc_pr_key_t *)pgr->pgr_keylist.lnk_fwd; - key != (spc_pr_key_t *)&pgr->pgr_keylist; - key = (spc_pr_key_t *)key->k_link.lnk_fwd) { - - /* Do not set UNIT ATTN for calling Initiator */ - if (key->k_isid == T10_PGR_ISID(cmd)) - continue; - /* - * At this point the only way to get in here is to be the owner - * of the reservation. - */ - lu = avl_first(&cmd->c_lu->l_common->l_all_open); - do { - lu->l_status = KEY_UNIT_ATTENTION; - lu->l_asc = SPC_ASC_PARAMETERS_CHANGED; - lu->l_ascq = SPC_ASCQ_RES_PREEMPTED; - lu = AVL_NEXT(&cmd->c_lu->l_common->l_all_open, lu); - } while (lu != NULL); - } - - /* - * Now erase the reservation and registration info. - */ - spc_pr_erase(pgr); - - return (STATUS_GOOD); -} - -/* - * []---- - * | spc_pr_register_and_move - * | Refer to SPC-3, Section 6.1, Tables ?? and ?? - * []---- - */ -static int -spc_pr_register_and_move(t10_cmd_t *cmd, void *data, size_t data_len) -{ - return (STATUS_RESERVATION_CONFLICT); -} - -/* - * []---- - * | spc_pr_key_alloc - - * | Allocate a new registration key and add it to the key list. - * | Refer to SPC-3, Section 6.1, Tables ?? and ?? - * []---- - */ -static spc_pr_key_t * -spc_pr_key_alloc(scsi3_pgr_t *pgr, uint64_t service_key, uint64_t isid, - char *transportID) -{ - spc_pr_key_t *key = (spc_pr_key_t *) - memalign(sizeof (void *), sizeof (spc_pr_key_t)); - - if (key != NULL) { - key->k_key = service_key; - key->k_isid = isid; - key->k_transportID = strdup(transportID); - - insque(&key->k_link, pgr->pgr_keylist.lnk_bwd); - - pgr->pgr_numkeys++; - assert(pgr->pgr_numkeys > 0); - } - - return (key); -} - -/* - * []---- - * | spc_pr_key_rsrv_init - - * | Initialize registration & reservervation queues - * []---- - */ -static void -spc_pr_key_rsrv_init(scsi3_pgr_t *pgr) -{ - assert(pgr->pgr_numrsrv == 0); - assert(pgr->pgr_numkeys == 0); - pgr->pgr_rsrvlist.lnk_fwd = (key_link_t *)&pgr->pgr_rsrvlist.lnk_fwd; - - assert(pgr->pgr_rsrvlist.lnk_bwd == NULL); - pgr->pgr_rsrvlist.lnk_bwd = (key_link_t *)&pgr->pgr_rsrvlist.lnk_fwd; - - assert(pgr->pgr_keylist.lnk_fwd == NULL); - pgr->pgr_keylist.lnk_fwd = (key_link_t *)&pgr->pgr_keylist.lnk_fwd; - - assert(pgr->pgr_keylist.lnk_bwd == NULL); - pgr->pgr_keylist.lnk_bwd = (key_link_t *)&pgr->pgr_keylist.lnk_fwd; -} - -/* - * []---- - * | spc_pr_key_free - - * | Free a registration key - * []---- - */ -static void -spc_pr_key_free(scsi3_pgr_t *pgr, spc_pr_key_t *key) -{ - remque(&key->k_link); - free(key->k_transportID); - free(key); - - pgr->pgr_numkeys--; - assert(pgr->pgr_numkeys >= 0); -} - -/* - * []---- - * | spc_pr_key_find - - * | Find a registration key based on the key, owner id and port id. - * []---- - */ -static spc_pr_key_t * -spc_pr_key_find(scsi3_pgr_t *pgr, uint64_t key, uint64_t isid, - char *transportID) -{ - spc_pr_key_t *kp; - spc_pr_key_t *rval = NULL; - - - for (kp = (spc_pr_key_t *)pgr->pgr_keylist.lnk_fwd; - kp != (spc_pr_key_t *)&pgr->pgr_keylist; - kp = (spc_pr_key_t *)kp->k_link.lnk_fwd) { - if ((key == 0 || kp->k_key == key) && - (isid == 0 || kp->k_isid == isid) && - (strlen(transportID) == 0 || - (strcmp(kp->k_transportID, transportID) == 0))) { - rval = kp; - break; - } - } - - return (rval); -} - - -/* - * []---- - * | spc_pr_rsrv_alloc - - * | Allocate a new reservation and add it to the rsrv list. - * []---- - */ -static spc_pr_rsrv_t * -spc_pr_rsrv_alloc(scsi3_pgr_t *pgr, uint64_t service_key, uint64_t isid, - char *transportID, uint8_t scope, uint8_t type) -{ - spc_pr_rsrv_t *rsrv = (spc_pr_rsrv_t *) - memalign(sizeof (void *), sizeof (spc_pr_rsrv_t)); - - if (rsrv != NULL) { - rsrv->r_key = service_key; - rsrv->r_isid = isid; - rsrv->r_transportID = strdup(transportID); - rsrv->r_scope = scope; - rsrv->r_type = type; - - insque(&rsrv->r_link, pgr->pgr_rsrvlist.lnk_bwd); - - pgr->pgr_numrsrv++; - assert(pgr->pgr_numrsrv > 0); - } - - return (rsrv); -} - - -/* - * []---- - * | spc_pr_rsrv_free - - * | Free a reservation. - * []---- - */ -static void -spc_pr_rsrv_free(scsi3_pgr_t *pgr, spc_pr_rsrv_t *rsrv) -{ - remque(&rsrv->r_link); - free(rsrv->r_transportID); - free(rsrv); - - pgr->pgr_numrsrv--; - assert(pgr->pgr_numrsrv >= 0); -} - -/* - * []---- - * | spc_pr_rsrv_find - - * | Find a reservation based on the key, owner id and port id. - * []---- - */ -static spc_pr_rsrv_t * -spc_pr_rsrv_find(scsi3_pgr_t *pgr, uint64_t key, uint64_t isid, - char *transportID) -{ - spc_pr_rsrv_t *rp, *rval = NULL; - - for (rp = (spc_pr_rsrv_t *)pgr->pgr_rsrvlist.lnk_fwd; - rp != (spc_pr_rsrv_t *)&pgr->pgr_rsrvlist; - rp = (spc_pr_rsrv_t *)rp->r_link.lnk_fwd) { - if ((key == 0 || rp->r_key == key) && - (isid == 0 || rp->r_isid == isid) && - (strlen(transportID) == 0 || - (strcmp(rp->r_transportID, transportID) == 0))) { - rval = rp; - break; - } - } - - return (rval); -} - -/* - * []---- - * | spc_pr_erase - - * | Find specified key / reservation and erease it - * []---- - */ -/* - */ -static void -spc_pr_erase(scsi3_pgr_t *pgr) -{ - spc_pr_key_t *key; - spc_pr_rsrv_t *rsrv; - - while ((key = (spc_pr_key_t *)pgr->pgr_keylist.lnk_fwd) != - (spc_pr_key_t *)&pgr->pgr_keylist) { - spc_pr_key_free(pgr, key); - } - - assert(pgr->pgr_numkeys == 0); - - while ((rsrv = (spc_pr_rsrv_t *)pgr->pgr_rsrvlist.lnk_fwd) != - (spc_pr_rsrv_t *)&pgr->pgr_rsrvlist) { - spc_pr_rsrv_free(pgr, rsrv); - } - - assert(pgr->pgr_numrsrv == 0); - - pgr->pgr_generation = 0; - pgr->pgr_aptpl = 0; -} - -/* - * []---- - * | spc_pr_rsrv_release - - * | Release the reservation the perform any other required clearing actions. - * | Refer to SPC-3, Section 6.1, Tables ?? and ?? - * []---- - */ -static void -spc_pr_rsrv_release(t10_cmd_t *cmd, scsi3_pgr_t *pgr, spc_pr_rsrv_t *rsrv) -{ - disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd); - t10_lu_impl_t *lu; - spc_pr_key_t *key; - - /* - * For Registrants-Only mode set UNIT ATTN. - */ - if (rsrv->r_type == PGR_TYPE_WR_EX_RO || - rsrv->r_type == PGR_TYPE_EX_AC_RO) { - - for (key = (spc_pr_key_t *)pgr->pgr_keylist.lnk_fwd; - key != (spc_pr_key_t *)&pgr->pgr_keylist; - key = (spc_pr_key_t *)key->k_link.lnk_fwd) { - - /* - * No UNIT ATTN for the requesting Initiator. - */ - if (key->k_isid == T10_PGR_ISID(cmd)) - continue; - - /* - * Find associated I_T Nexuses - */ - lu = avl_first(&cmd->c_lu->l_common->l_all_open); - do { - lu->l_cmd = sbc_cmd; - lu->l_status = KEY_UNIT_ATTENTION; - lu->l_asc = SPC_ASC_PARAMETERS_CHANGED; - lu->l_ascq = SPC_ASCQ_RES_RELEASED; - lu = AVL_NEXT(&cmd->c_lu->l_common->l_all_open, - lu); - } while (lu != NULL); - } - } - - /* - * Remove the reservation. - */ - spc_pr_rsrv_free(pgr, rsrv); -} - -/* - * []---- - * | spc_pr_read - - * | Read in pgr keys and reservations for this device from backend storage. - * | At least the local pgr write lock must be held. - * []---- - */ -Boolean_t -spc_pr_read(t10_cmd_t *cmd) -{ - disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd); - sbc_reserve_t *res = &p->d_sbc_reserve; - scsi3_pgr_t *pgr = &res->res_scsi_3_pgr; - spc_pr_key_t *key; - spc_pr_rsrv_t *rsrv; - spc_pr_diskkey_t *klist; - spc_pr_diskrsrv_t *rlist; - spc_pr_persist_disk_t *buf = NULL; - t10_lu_impl_t *lu; - int i, pfd; - Boolean_t status = False; - char path[MAXPATHLEN]; - - /* - * If the pre-processor supported "#if .. sizeof", these would - * not be required here - */ - assert(sizeof (spc_pr_diskkey_t) == 256); - assert(sizeof (spc_pr_diskrsrv_t) == 256); - assert(sizeof (spc_pr_persist_disk_t) == 512); - - /* - * Open/create the PERSISTANCE file specification - */ - (void) snprintf(path, MAXPATHLEN, "%s/%s/%s%d", - target_basedir, cmd->c_lu->l_targ->s_targ_base, - PERSISTANCEBASE, cmd->c_lu->l_common->l_num); - if ((pfd = open(path, O_RDONLY)) >= 0) { - struct stat pstat; - if ((fstat(pfd, &pstat)) == 0) - if (pstat.st_size > 0) - if (buf = malloc(pstat.st_size)) - if (read(pfd, buf, pstat.st_size) == - pstat.st_size) - status = True; - } - - /* - * Clean up on no persistence file found - */ - if (status == False) { - if (pfd >= 0) - close(pfd); - if (buf) - free(buf); - return (status); - } - - /* - * If this is the first time using the persistance data, - * initialize the reservation and resource key queues - */ - if (pgr->pgr_rsrvlist.lnk_fwd == NULL) { - spc_pr_key_rsrv_init(pgr); - } - - /* - * Perform some vailidation - */ - if ((buf->magic != PGRMAGIC) || - (buf->revision != SPC_PGR_PERSIST_DATA_REVISION)) { - status = False; - goto done; - } - - /* - * Get the registration keys. - */ - klist = buf->keylist; - for (i = 0; i < buf->numkeys; i++) { - if (klist[i].rectype != PGRDISKKEY) { - status = False; - goto done; - } - key = spc_pr_key_alloc(pgr, klist[i].key, klist[i].isid, - klist[i].transportID); - if (key == NULL) { - status = False; - goto done; - } - } - - /* - * Get the reservations. - */ - rlist = (spc_pr_diskrsrv_t *)&buf->keylist[buf->numkeys]; - for (i = 0; i < buf->numrsrv; i++) { - if (rlist[i].rectype != PGRDISKRSRV) { - status = False; - goto done; - } - rsrv = spc_pr_rsrv_alloc(pgr, rlist[i].key, rlist[i].isid, - rlist[i].transportID, rlist[i].scope, rlist[i].type); - if (rsrv == NULL) { - status = False; - goto done; - } - } - - /* - * If there was data then set the reservation type. - */ - if (pgr->pgr_numkeys > 0 || pgr->pgr_numrsrv > 0) { - res->res_type = RT_PGR; - pgr->pgr_generation = buf->generation; - - /* - * Set the command dispatcher according to the reservation type - */ - lu = avl_first(&cmd->c_lu->l_common->l_all_open); - do { - lu->l_cmd = sbc_cmd_reserved; - lu = AVL_NEXT(&cmd->c_lu->l_common->l_all_open, lu); - } while (lu != NULL); - } - -done: pthread_rwlock_unlock(&res->res_rwlock); - free(buf); - return (status); -} - -/* - * []---- - * | spc_pr_write - - * | Write PGR keys and reservations for this device to backend storage. - * | At least the local pgr write lock must be held. - * []---- - */ -Boolean_t -spc_pr_write(t10_cmd_t *cmd) -{ - disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd); - sbc_reserve_t *res = &p->d_sbc_reserve; - scsi3_pgr_t *pgr = &res->res_scsi_3_pgr; - spc_pr_key_t *key; - spc_pr_rsrv_t *rsrv; - spc_pr_diskkey_t *klist; - spc_pr_diskrsrv_t *rlist; - spc_pr_persist_disk_t *buf; - ssize_t length, bufsize; - int i, pfd = -1; - char path[MAXPATHLEN]; - Boolean_t status = True; - - /* - * If the pre-processor supported "#if .. sizeof", these would - * not be required here - */ - assert(sizeof (spc_pr_diskkey_t) == 256); - assert(sizeof (spc_pr_diskrsrv_t) == 256); - assert(sizeof (spc_pr_persist_disk_t) == 512); - - /* - * Verify space requirements and allocate buffer memory. - * Space needed is header + keylist + rsrvlist. - * Subtract 1 from numkeys since header already defines - * the first element of the keylist. - * Round up the bufsize to the next FBA boundary. - */ - bufsize = sizeof (spc_pr_persist_disk_t) + - (pgr->pgr_numkeys - 1) * sizeof (spc_pr_diskkey_t) + - pgr->pgr_numrsrv * sizeof (spc_pr_diskrsrv_t); - bufsize = roundup(bufsize, 512); - if ((buf = memalign(sizeof (void *), bufsize)) == NULL) - return (False); - else - bzero(buf, bufsize); - - /* - * Build header. - */ - buf->magic = PGRMAGIC; - buf->revision = SPC_PGR_PERSIST_DATA_REVISION; - buf->generation = pgr->pgr_generation; - buf->numkeys = pgr->pgr_numkeys; - buf->numrsrv = pgr->pgr_numrsrv; - - /* - * Copy the keys. - */ - klist = buf->keylist; - for (i = 0, key = (spc_pr_key_t *)pgr->pgr_keylist.lnk_fwd; - key != (spc_pr_key_t *)&pgr->pgr_keylist && i < pgr->pgr_numkeys; - key = (spc_pr_key_t *)key->k_link.lnk_fwd, i++) { - - klist[i].rectype = PGRDISKKEY; - klist[i].reserved = 0; - klist[i].key = key->k_key; - klist[i].isid = key->k_isid; - strncpy(klist[i].transportID, key->k_transportID, - sizeof (klist[i].transportID)); - } - - /* - * Copy the reservations. - */ - rlist = (spc_pr_diskrsrv_t *)&buf->keylist[pgr->pgr_numkeys]; - for (i = 0, rsrv = (spc_pr_rsrv_t *)pgr->pgr_rsrvlist.lnk_fwd; - rsrv != (spc_pr_rsrv_t *)&pgr->pgr_rsrvlist && - i < pgr->pgr_numrsrv; - rsrv = (spc_pr_rsrv_t *)rsrv->r_link.lnk_fwd, i++) { - - rlist[i].rectype = PGRDISKRSRV; - rlist[i].reserved = 0; - rlist[i].scope = rsrv->r_scope; - rlist[i].type = rsrv->r_type; - rlist[i].key = rsrv->r_key; - rlist[i].isid = rsrv->r_isid; - strncpy(rlist[i].transportID, rsrv->r_transportID, - sizeof (rlist[i].transportID)); - } - - /* - * Open/create the PERSISTANCE file specification - */ - (void) snprintf(path, MAXPATHLEN, "%s/%s/%s%d", - target_basedir, cmd->c_lu->l_targ->s_targ_base, - PERSISTANCEBASE, cmd->c_lu->l_common->l_num); - if ((pfd = open(path, O_WRONLY|O_CREAT)) >= 0) { - length = write(pfd, buf, bufsize); - close(pfd); - } else { - if ((pfd < 0) || (length != bufsize)) - status = False; - } - - /* - * Free allocated buffer - */ - free(buf); - return (status); -} diff --git a/deleted_files/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.h b/deleted_files/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.h deleted file mode 100644 index 7ebc085a1b..0000000000 --- a/deleted_files/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _T10_SPC_PR_H -#define _T10_SPC_PR_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * SPC-3 Persistent Reservation specific structures and defines - */ - -/* - * Key Linked Lists - */ -typedef struct key_link { - union { - uint64_t align; - struct { - struct key_link *_lnk_fwd; /* Forward element */ - struct key_link *_lnk_bwd; /* Backward element */ - } key_ptr; - } key_link; -} key_link_t; -#define lnk_fwd key_link.key_ptr._lnk_fwd -#define lnk_bwd key_link.key_ptr._lnk_bwd -#define insque(a, b) do { \ - ((key_link_t *)(a))->lnk_fwd = (key_link_t *)(b); \ - ((key_link_t *)(a))->lnk_bwd = ((key_link_t *)(b))->lnk_bwd; \ - ((key_link_t *)(b))->lnk_bwd = (key_link_t *)(a); \ - ((key_link_t *)(a))->lnk_bwd->lnk_fwd = (key_link_t *)(a); \ - } while (0) - -#define remque(A) do { \ - ((key_link_t *)(A))->lnk_bwd->lnk_fwd = ((key_link_t *)(A))->lnk_fwd; \ - ((key_link_t *)(A))->lnk_fwd->lnk_bwd = ((key_link_t *)(A))->lnk_bwd; \ - } while (0) - -/* - * Reservation Types (res_type). - */ -typedef enum { - RT_NONE = 0, /* None */ - RT_PGR /* SCSI-3 Persistent Reservation */ -} spc_reserve_types; - -/* - * Persistent reservation data. - */ -typedef struct spc_pr_key { - key_link_t k_link; /* Key linked list */ - uint64_t k_key; /* registration key */ - uint64_t k_isid; /* Owner ISID */ - char *k_transportID; /* transport ID */ -} spc_pr_key_t; - -typedef struct spc_pr_rsrv { - key_link_t r_link; /* Key linked list */ - uint64_t r_key; /* reservation key */ - uint64_t r_isid; /* Owner ISID */ - char *r_transportID; /* transport ID */ - uint8_t r_scope; /* reservation scope */ - uint8_t r_type; /* reservation type */ -} spc_pr_rsrv_t; - -/* - * Persistent Reservation data - */ -typedef struct scsi3_pgr { - uint32_t pgr_generation; /* PGR PRgeneration value */ - uint16_t pgr_unused; - uint16_t pgr_bits : 15, - pgr_aptpl : 1; /* persistence data exists */ - int32_t pgr_numkeys; /* # entries in key list */ - int32_t pgr_numrsrv; /* # entries in rsrv list */ - key_link_t pgr_keylist; /* Registration key list */ - key_link_t pgr_rsrvlist; /* reservation list */ -} scsi3_pgr_t; - -typedef struct sbc_reserve { - spc_reserve_types res_type; /* standard or pr active */ - pthread_rwlock_t res_rwlock; /* Lock for coordination */ - scsi3_pgr_t res_scsi_3_pgr; /* SCSI-3 PGR */ -} sbc_reserve_t; - -/* - * On-disk PGR data. - * - * NOTE: The following three structures should be rounded up to 256 bytes each - * to prevent potential problems with on-disk data. - */ -typedef struct spc_pr_diskkey { - uint32_t rectype; /* record type */ - uint32_t reserved; - uint64_t key; /* registration key */ - uint64_t isid; /* Owner ISID */ - char transportID[228]; /* transport ID */ - char filler[4]; /* Unsed, round to 256 bytes */ -} spc_pr_diskkey_t; - -typedef struct spc_pr_diskrsrv { - uint32_t rectype; /* record type */ - uint16_t reserved; - uint8_t scope; /* reservation scope */ - uint8_t type; /* reservation type */ - uint64_t key; /* reservation key */ - uint64_t isid; /* Owner ISID */ - char transportID[228]; /* Transport ID */ - char filler[4]; /* Unsed, round to 256 bytes */ -} spc_pr_diskrsrv_t; - -typedef struct spc_pr_persist_disk { - uint64_t magic; /* magic number */ - uint32_t revision; /* header format revision */ - uint32_t generation; /* pgr generation count */ - int32_t numkeys; /* # items in key list */ - int32_t numrsrv; /* # items in rsrv list */ - char filler[232]; /* Unused, round to 256 bytes */ - -/* - * After the header the data is laid out as follows: - * spc_pr_diskkey_t keylist[]; - * spc_pr_diskrsrv_t rsrvlist[]; - */ - spc_pr_diskkey_t keylist[1]; -} spc_pr_persist_disk_t; - - -#define SPC_PGR_PERSIST_DATA_REVISION 0x01 /* REVISON = 1 */ -#define PGRMAGIC 0x5047524D41474943LL /* "PGRMAGIC" */ -#define PGRDISKKEY 0x5047526B /* "PGRk" */ -#define PGRDISKRSRV 0x50475272 /* "PGRr" */ - -#ifdef __cplusplus -} -#endif - -#endif /* _T10_SPC_PR_H */ diff --git a/deleted_files/usr/src/uts/common/sys/scsi/generic/persist.h b/deleted_files/usr/src/uts/common/sys/scsi/generic/persist.h deleted file mode 100644 index 613c91cf12..0000000000 --- a/deleted_files/usr/src/uts/common/sys/scsi/generic/persist.h +++ /dev/null @@ -1,398 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_SCSI_GENERIC_PERSIST_H -#define _SYS_SCSI_GENERIC_PERSIST_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * SCSI Persistence Data - * - * Format of data returned as a result of PERSISTENCE RESERVER { IN | OUT } - */ - -/* - * SPC-3 revision 23, Section 6.11.1, Table 102 - * Persistent Reservations - * Persistent Reserve In service actions - */ -#define PR_IN_READ_KEYS 0x0 /* Read all registered reservation keys */ -#define PR_IN_READ_RESERVATION 0x1 /* Reads th persistent reservations */ -#define PR_IN_REPORT_CAPABILITIES 0x2 /* Returns capability information */ -#define PR_IN_READ_FULL_STATUS 0x3 /* Reads complete information about all */ - /* registrations and the persistent */ - /* reservations, if any */ -/* - * SPC-3 revision 23, Section 6.11.3.3, Table 106 - * Persistent reservation scope codes - */ -#define PR_LU_SCOPE 0x0 /* Persistent reservation applies to */ - /* full logical unit */ -/* - * SPC-3 revision 23, Section 6.11.3.4, Table 107 - * Persistent Reservations - * Persistent reservation type codes - */ -#define PGR_TYPE_WR_EX 0x1 /* Write Exclusive */ -#define PGR_TYPE_EX_AC 0x3 /* Exclusive Access */ -#define PGR_TYPE_WR_EX_RO 0x5 /* Write Exclusive, Registrants Only */ -#define PGR_TYPE_EX_AC_RO 0x6 /* Exclusive Access, Registrants Only */ -#define PGR_TYPE_WR_EX_AR 0x7 /* Write Exclusive, All Registrants */ -#define PGR_TYPE_EX_AC_AR 0x8 /* Exclusive Access, All Registrants */ - -/* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.11.5 PERSISTENCE RESERVE IN - * Table 111 - full status descriptor format - */ -/* Table 289 - iSCSI Initiator Device TransportID format */ - -#define iSCSI_PROTOCOL_ID 0x5 /* Table 262 - iSCSI Protocol ID */ -#define WW_UID_DEVICE_NAME 0x0 /* Table 288 - iSCSI Transport IDs */ - - -#if defined(_BIT_FIELDS_LTOH) -/* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.11.1 PERSISTENCE RESERVE IN - * Table 101 - PERSISTENCE RESERVE IN command - */ -typedef struct scsi_cdb_prin { - uint8_t cmd; - uint8_t action : 5, - resbits : 3; - uint8_t resbytes[5]; - uint8_t alloc_len[2]; - uint8_t control; -} scsi_cdb_prin_t; - -/* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.11.2 PERSISTENCE RESERVE IN - * Table 103/104/105 - parameter data for READS KEYS - */ -typedef struct scsi_prin_rsrvdesc { - uint8_t reservation_key[8]; - uint8_t obsolete1[4]; - uint8_t resbytes; - uint8_t type : 4, - scope : 4; - uint8_t obsolete2[2]; -} scsi_prin_rsrvdesc_t; -typedef struct scsi_prin_readrsrv { - uint8_t PRgeneration[4]; - uint8_t add_len[4]; - scsi_prin_rsrvdesc_t res_key_list[1]; -} scsi_prin_readrsrv_t; - -/* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.11.4 PERSISTENCE RESERVE IN - * Table 108 - parameter data for REPORT CAPABILTIES - */ -typedef struct scsi_per_res_type { - uint8_t resbits1 : 1, - wr_ex : 1, - resbits2 : 1, - ex_ac : 1, - resbits3 : 1, - wr_ex_ro : 1, - ex_ac_ro : 1, - wr_ex_ar : 1; - uint8_t ex_ac_ar : 1, - resbits4 : 7; -} scsi_per_res_type_t; -typedef struct scsi_prin_rpt_cap { - uint8_t length[2]; - uint8_t ptpl_c : 1, - resbits1 : 1, - atp_c : 1, - sip_c : 1, - crh : 1, - resbits2 : 3; - uint8_t ptpl_a : 1, - resbits3 : 6, - tmv : 1; - scsi_per_res_type_t pr_type; - uint8_t resbytes[2]; -} scsi_prin_rpt_cap_t; - -/* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.11.5 PERSISTENCE RESERVE IN - * Table 110/111 - parameter data for READ FULL STATUS - * Table 281 - TransportId format - */ -typedef struct scsi_transport_id { - uint8_t protocol_id : 4, - resbits : 2, - format_code : 2; - uint8_t add_len[2]; - char iscsi_name[1]; -} scsi_transport_id_t; -typedef struct scsi_prin_status_t { - uint8_t reservation_key[8]; - uint8_t resbytes1[4]; - uint8_t r_holder : 1, - all_tg_pt : 1, - resbits : 6; - uint8_t type : 4, - scope : 4; - uint8_t resbytes2[4]; - uint8_t rel_tgt_port_id[2]; - uint8_t add_len[4]; - scsi_transport_id_t trans_id; -} scsi_prin_status_t; -typedef struct scsi_prin_full_status { - uint8_t PRgeneration[4]; - uint8_t add_len[4]; - scsi_prin_status_t full_desc[1]; -} scsi_prin_full_status_t; - -/* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.12.1 PERSISTENCE RESERVE OUT - * Table 112 - PERSISTENCE RESERVE OUT command - */ -typedef struct scsi_cdb_prout { - uint8_t cmd; - uint8_t action : 5, - resbits : 3; - uint8_t type : 4, - scope : 4; - uint8_t resbytes[2]; - uint8_t param_len[4]; - uint8_t control; -} scsi_cdb_prout_t; - -/* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.12.3 PERSISTENCE RESERVE OUT - * Table 114 - PERSISTENCE RESERVE OUT parameter list - */ -typedef struct scsi_prout_plist { - uint8_t reservation_key[8]; - uint8_t service_key[8]; - uint8_t obsolete1[4]; - uint8_t aptpl : 1, - resbits1 : 1, - all_tg_pt : 1, - spec_i_pt : 1, - resbits2 : 4; - uint8_t resbytes1; - uint8_t obsolete2[2]; - uint8_t apd[1]; -} scsi_prout_plist_t; - -#elif defined(_BIT_FIELDS_HTOL) -/* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.11.1 PERSISTENCE RESERVE IN - * Table 101 - PERSISTENCE RESERVE IN command - */ -typedef struct scsi_cdb_prin { - uint8_t cmd; - uint8_t resbits : 3, - action : 5; - uint8_t resbytes[5]; - uint8_t alloc_len[2]; - uint8_t control; -} scsi_cdb_prin_t; - -/* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.11.2 PERSISTENCE RESERVE IN - * Table 103/104/105 - parameter data for READS KEYS - */ -typedef struct scsi_prin_rsrvdesc { - uint8_t reservation_key[8]; - uint8_t obsolete1[4]; - uint8_t resbytes; - uint8_t scope : 4, - type : 4; - uint8_t obsolete2[8]; -} scsi_prin_rsrvdesc_t; -typedef struct scsi_prin_readrsrv { - uint8_t PRgeneration[4]; - uint8_t add_len[4]; - scsi_prin_rsrvdesc_t res_key_list[1]; -} scsi_prin_readrsrv_t; - -/* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.11.4 PERSISTENCE RESERVE IN - * Table 108 - parameter data for REPORT CAPABILTIES - */ -typedef struct scsi_per_res_type { - uint8_t wr_ex_ar : 1, - ex_ac_ro : 1, - wr_ex_ro : 1, - resbits3 : 1, - ex_ac : 1, - resbits2 : 1, - wr_ex : 1, - resbits1 : 1; - uint8_t resbits4 : 7, - ex_ac_ar : 1; -} scsi_per_res_type_t; -typedef struct scsi_prin_rpt_cap { - uint8_t length[2]; - uint8_t resbits2 : 3, - crh : 1, - sip_c : 1, - atp_c : 1, - resbits1 : 1, - ptpl_c : 1; - uint8_t tmv : 1, - resbits3 : 6, - ptpl_a : 1; - scsi_per_res_type_t pr_type; - uint8_t resbytes[2]; -} scsi_prin_rpt_cap_t; - -/* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.11.5 PERSISTENCE RESERVE IN - * Table 110/111 - parameter data for READ FULL STATUS - * Table 281 - TransportId format - */ -typedef struct scsi_transport_id { - uint8_t format_code : 2, - resbits : 2, - protocol_id : 4; - uint8_t add_len[2]; - char iscsi_name[1]; -} scsi_transport_id_t; -typedef struct scsi_prin_status_t { - uint8_t reservation_key[8]; - uint8_t resbytes1[4]; - uint8_t resbits : 6, - all_tg_pt : 1, - r_holder : 1; - uint8_t scope : 4, - type : 4; - uint8_t resbytes2[4]; - uint8_t rel_tgt_port_id[2]; - uint8_t add_len[4]; - scsi_transport_id_t trans_id; -} scsi_prin_status_t; -typedef struct scsi_prin_full_status { - uint8_t PRgeneration[4]; - uint8_t add_len[4]; - scsi_prin_status_t full_desc[1]; -} scsi_prin_full_status_t; - -/* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.12.1 PERSISTENCE RESERVE OUT - * Table 112 - PERSISTENCE RESERVE OUT command - */ -typedef struct scsi_cdb_prout { - uint8_t cmd; - uint8_t resbits : 3, - action : 5; - uint8_t scope : 4, - type : 4; - uint8_t resbytes[2]; - uint8_t param_len[4]; - uint8_t control; -} scsi_cdb_prout_t; - -/* - * Information obtained from: - * SPC-3, Revision 23 - * Section 6.12.3 PERSISTENCE RESERVE OUT - * Table 114 - PERSISTENCE RESERVE OUT parameter list - */ -typedef struct scsi_prout_plist { - uint8_t reservation_key[8]; - uint8_t service_key[8]; - uint8_t obsolete1[4]; - uint8_t resbits1 : 4, - spec_i_pt : 1, - all_tg_pt : 1, - resbits2 : 1, - aptpl : 1; - uint8_t resbytes1; - uint8_t obsolete2[2]; - uint8_t apd[1]; -} scsi_prout_plist_t; - -#else -#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined -#endif /* _BIT_FIELDS_LTOH */ - - -/* - * SPC-3 revision 23, Section 6.12.2, Table 113 - * Persistent Reservations - * Persistent Reserve Out service action codes - */ -#define PR_OUT_REGISTER 0x0 /* Register/unregister a reservation */ - /* key with the device server */ -#define PR_OUT_RESERVE 0x1 /* Create a persistent reservation */ - /* having a specified SCOPE & TYPE */ -#define PR_OUT_RELEASE 0x2 /* Release the selected persistent */ - /* reservation */ -#define PR_OUT_CLEAR 0x3 /* Clears all reservation keys and */ - /* all persistent reservations */ -#define PR_OUT_PREEMPT 0x4 /* Preempts persistent reservations */ - /* and/or removes reservations */ -#define PR_OUT_PREEMPT_ABORT 0x5 /* Preempts persistent reservations */ - /* and/or removes reservations, and */ - /* aborts all tasks for all preempted */ - /* I_T nexuses */ -#define PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY 0x06 - /* Register a reservation key with */ - /* the device server, or unregister a */ - /* reservation key */ -#define PR_OUT_REGISTER_MOVE 0x7 /* Register a reservation key for */ - /* another I_T nexus with the device */ - /* server and move a persistent */ - /* reservation to the I_T nexus */ - - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_SCSI_GENERIC_PERSIST_H */ |