Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 7 Jul 2014 11:05:05 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r268363 - in head: sys/cam/ctl usr.sbin/ctladm
Message-ID:  <201407071105.s67B55Hx013313@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Mon Jul  7 11:05:04 2014
New Revision: 268363
URL: http://svnweb.freebsd.org/changeset/base/268363

Log:
  Add support for READ FULL STATUS action of PERSISTENT RESERVE IN command.

Modified:
  head/sys/cam/ctl/ctl.c
  head/sys/cam/ctl/ctl.h
  head/sys/cam/ctl/ctl_cmd_table.c
  head/sys/cam/ctl/scsi_ctl.c
  head/usr.sbin/ctladm/ctladm.c

Modified: head/sys/cam/ctl/ctl.c
==============================================================================
--- head/sys/cam/ctl/ctl.c	Mon Jul  7 09:37:22 2014	(r268362)
+++ head/sys/cam/ctl/ctl.c	Mon Jul  7 11:05:04 2014	(r268363)
@@ -1499,6 +1499,61 @@ take:
 }
 
 static int
+ctl_create_iid(struct ctl_port *port, int iid, uint8_t *buf)
+{
+	int len;
+
+	switch (port->port_type) {
+	case CTL_PORT_FC:
+	{
+		struct scsi_transportid_fcp *id =
+		    (struct scsi_transportid_fcp *)buf;
+		if (port->wwpn_iid[iid].wwpn == 0)
+			return (0);
+		memset(id, 0, sizeof(*id));
+		id->format_protocol = SCSI_PROTO_FC;
+		scsi_u64to8b(port->wwpn_iid[iid].wwpn, id->n_port_name);
+		return (sizeof(*id));
+	}
+	case CTL_PORT_ISCSI:
+	{
+		struct scsi_transportid_iscsi_port *id =
+		    (struct scsi_transportid_iscsi_port *)buf;
+		if (port->wwpn_iid[iid].name == NULL)
+			return (0);
+		memset(id, 0, 256);
+		id->format_protocol = SCSI_TRN_ISCSI_FORMAT_PORT |
+		    SCSI_PROTO_ISCSI;
+		len = strlcpy(id->iscsi_name, port->wwpn_iid[iid].name, 252) + 1;
+		len = roundup2(min(len, 252), 4);
+		scsi_ulto2b(len, id->additional_length);
+		return (sizeof(*id) + len);
+	}
+	case CTL_PORT_SAS:
+	{
+		struct scsi_transportid_sas *id =
+		    (struct scsi_transportid_sas *)buf;
+		if (port->wwpn_iid[iid].wwpn == 0)
+			return (0);
+		memset(id, 0, sizeof(*id));
+		id->format_protocol = SCSI_PROTO_SAS;
+		scsi_u64to8b(port->wwpn_iid[iid].wwpn, id->sas_address);
+		return (sizeof(*id));
+	}
+	default:
+	{
+		struct scsi_transportid_spi *id =
+		    (struct scsi_transportid_spi *)buf;
+		memset(id, 0, sizeof(*id));
+		id->format_protocol = SCSI_PROTO_SPI;
+		scsi_ulto2b(iid, id->scsi_addr);
+		scsi_ulto2b(port->targ_port, id->rel_trgt_port_id);
+		return (sizeof(*id));
+	}
+	}
+}
+
+static int
 ctl_ioctl_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
 {
 	return (0);
@@ -7619,6 +7674,11 @@ retry:
 	case SPRI_RC: /* report capabilities */
 		total_len = sizeof(struct scsi_per_res_cap);
 		break;
+	case SPRI_RS: /* read full status */
+		total_len = sizeof(struct scsi_per_res_in_header) +
+		    (sizeof(struct scsi_per_res_in_full_desc) + 256) *
+		    lun->pr_key_count;
+		break;
 	default:
 		panic("Invalid PR type %x", cdb->action);
 	}
@@ -7775,7 +7835,62 @@ retry:
 		scsi_ulto2b(type_mask, res_cap->type_mask);
 		break;
 	}
-	case SPRI_RS: //read full status
+	case SPRI_RS: { // read full status
+		struct scsi_per_res_in_full *res_status;
+		struct scsi_per_res_in_full_desc *res_desc;
+		struct ctl_port *port;
+		int i, len;
+
+		res_status = (struct scsi_per_res_in_full*)ctsio->kern_data_ptr;
+
+		/*
+		 * We had to drop the lock to allocate our buffer, which
+		 * leaves time for someone to come in with another
+		 * persistent reservation.  (That is unlikely, though,
+		 * since this should be the only persistent reservation
+		 * command active right now.)
+		 */
+		if (total_len < (sizeof(struct scsi_per_res_in_header) +
+		    (sizeof(struct scsi_per_res_in_full_desc) + 256) *
+		     lun->pr_key_count)){
+			mtx_unlock(&lun->lun_lock);
+			free(ctsio->kern_data_ptr, M_CTL);
+			printf("%s: reservation length changed, retrying\n",
+			       __func__);
+			goto retry;
+		}
+
+		scsi_ulto4b(lun->PRGeneration, res_status->header.generation);
+
+		res_desc = &res_status->desc[0];
+		for (i = 0; i < 2*CTL_MAX_INITIATORS; i++) {
+			if (!lun->per_res[i].registered)
+				continue;
+
+			memcpy(&res_desc->res_key, &lun->per_res[i].res_key.key,
+			    sizeof(res_desc->res_key));
+			if ((lun->flags & CTL_LUN_PR_RESERVED) &&
+			    (lun->pr_res_idx == i ||
+			     lun->pr_res_idx == CTL_PR_ALL_REGISTRANTS)) {
+				res_desc->flags = SPRI_FULL_R_HOLDER;
+				res_desc->scopetype = lun->res_type;
+			}
+			scsi_ulto2b(i / CTL_MAX_INIT_PER_PORT,
+			    res_desc->rel_trgt_port_id);
+			len = 0;
+			port = softc->ctl_ports[i / CTL_MAX_INIT_PER_PORT];
+			if (port != NULL)
+				len = ctl_create_iid(port,
+				    i % CTL_MAX_INIT_PER_PORT,
+				    res_desc->transport_id);
+			scsi_ulto4b(len, res_desc->additional_length);
+			res_desc = (struct scsi_per_res_in_full_desc *)
+			    &res_desc->transport_id[len];
+		}
+		scsi_ulto4b((uint8_t *)res_desc - (uint8_t *)&res_status->desc[0],
+		    res_status->header.length);
+		break;
+	}
 	default:
 		/*
 		 * This is a bug, because we just checked for this above,

Modified: head/sys/cam/ctl/ctl.h
==============================================================================
--- head/sys/cam/ctl/ctl.h	Mon Jul  7 09:37:22 2014	(r268362)
+++ head/sys/cam/ctl/ctl.h	Mon Jul  7 11:05:04 2014	(r268363)
@@ -53,6 +53,7 @@ typedef enum {
 	CTL_PORT_IOCTL		= 0x04,
 	CTL_PORT_INTERNAL	= 0x08,
 	CTL_PORT_ISCSI		= 0x10,
+	CTL_PORT_SAS		= 0x20,
 	CTL_PORT_ALL		= 0xff,
 	CTL_PORT_ISC		= 0x100 // FC port for inter-shelf communication
 } ctl_port_type;

Modified: head/sys/cam/ctl/ctl_cmd_table.c
==============================================================================
--- head/sys/cam/ctl/ctl_cmd_table.c	Mon Jul  7 09:37:22 2014	(r268362)
+++ head/sys/cam/ctl/ctl_cmd_table.c	Mon Jul  7 11:05:04 2014	(r268363)
@@ -99,7 +99,15 @@ const struct ctl_cmd_entry ctl_cmd_table
  10, { 0x02, 0, 0, 0, 0, 0, 0xff, 0xff, 0x07}},
 
 /* 03 READ FULL STATUS */
-{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
+{ctl_persistent_reserve_in, CTL_SERIDX_INQ, CTL_CMD_FLAG_ALLOW_ON_RESV |
+					    CTL_CMD_FLAG_OK_ON_BOTH |
+					    CTL_CMD_FLAG_OK_ON_STOPPED |
+					    CTL_CMD_FLAG_OK_ON_INOPERABLE |
+					    CTL_CMD_FLAG_OK_ON_SECONDARY |
+					    CTL_FLAG_DATA_IN |
+					    CTL_CMD_FLAG_ALLOW_ON_PR_RESV,
+ CTL_LUN_PAT_NONE,
+ 10, { 0x03, 0, 0, 0, 0, 0, 0xff, 0xff, 0x07}},
 
 /* 04-1f */
 };

Modified: head/sys/cam/ctl/scsi_ctl.c
==============================================================================
--- head/sys/cam/ctl/scsi_ctl.c	Mon Jul  7 09:37:22 2014	(r268362)
+++ head/sys/cam/ctl/scsi_ctl.c	Mon Jul  7 11:05:04 2014	(r268363)
@@ -372,6 +372,8 @@ ctlfeasync(void *callback_arg, uint32_t 
 		 */
 		if (cpi->transport == XPORT_FC)
 			port->port_type = CTL_PORT_FC;
+		else if (cpi->transport == XPORT_SAS)
+			port->port_type = CTL_PORT_SAS;
 		else
 			port->port_type = CTL_PORT_SCSI;
 

Modified: head/usr.sbin/ctladm/ctladm.c
==============================================================================
--- head/usr.sbin/ctladm/ctladm.c	Mon Jul  7 09:37:22 2014	(r268362)
+++ head/usr.sbin/ctladm/ctladm.c	Mon Jul  7 11:05:04 2014	(r268363)
@@ -500,6 +500,9 @@ retry:
 		case CTL_PORT_ISCSI:
 			type = "ISCSI";
 			break;
+		case CTL_PORT_SAS:
+			type = "SAS";
+			break;
 		default:
 			type = "UNKNOWN";
 			break;
@@ -590,6 +593,7 @@ static struct ctladm_opts cctl_fe_table[
 	{"scsi", CTL_PORT_SCSI, CTLADM_ARG_NONE, NULL},
 	{"internal", CTL_PORT_INTERNAL, CTLADM_ARG_NONE, NULL},
 	{"iscsi", CTL_PORT_ISCSI, CTLADM_ARG_NONE, NULL},
+	{"sas", CTL_PORT_SAS, CTLADM_ARG_NONE, NULL},
 	{"all", CTL_PORT_ALL, CTLADM_ARG_NONE, NULL},
 	{NULL, 0, 0, NULL}
 };



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407071105.s67B55Hx013313>