Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Nov 2015 13:18:38 +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: r290670 - head/sys/cam/ctl
Message-ID:  <201511111318.tABDIcHd004070@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Wed Nov 11 13:18:38 2015
New Revision: 290670
URL: https://svnweb.freebsd.org/changeset/base/290670

Log:
  Modify target port groups logic in CTL.
  
   - Introduce "ha_shared" port option, which being set to "on" moves the
  port into separate port group, shared between HA nodes.  This allows to
  better handle cases when iSCSI portals are bound to CARP address that can
  dynamically move between nodes.  Some initiators (at least VMware) don't
  detect that after iSCSI reconnect they've attached to different SCSI port
  from different port group, that totally breakes ALUA status parsing.
  In theory, I believe, it should be enough to have different iSCSI portal
  group tags on different nodes to make initiators detect this condition,
  but it seems like VMware ignores those values, and even full LUN retaste
  forced by UA does not help.
   - Make CTL report up to three port groups: 1 -- non-HA mode or ports
  with "ha_shared" option set, 2 -- HA node 1, 3 -- HA node 2.
   - Report Transitioning state for all port groups when HA interlink is
  connected, but neither of nodes is primary for the LUN.
  
  MFC after:	2 weeks

Modified:
  head/sys/cam/ctl/ctl.c
  head/sys/cam/ctl/ctl_frontend.c
  head/sys/cam/ctl/ctl_frontend.h
  head/sys/cam/ctl/ctl_private.h

Modified: head/sys/cam/ctl/ctl.c
==============================================================================
--- head/sys/cam/ctl/ctl.c	Wed Nov 11 12:36:42 2015	(r290669)
+++ head/sys/cam/ctl/ctl.c	Wed Nov 11 13:18:38 2015	(r290670)
@@ -1819,13 +1819,13 @@ ctl_init(void)
 	SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
 	    OID_AUTO, "ha_id", CTLFLAG_RDTUN, &softc->ha_id, 0,
 	    "HA head ID (0 - no HA)");
-	if (softc->ha_id == 0 || softc->ha_id > NUM_TARGET_PORT_GROUPS) {
+	if (softc->ha_id == 0 || softc->ha_id > NUM_HA_SHELVES) {
 		softc->flags |= CTL_FLAG_ACTIVE_SHELF;
 		softc->is_single = 1;
 		softc->port_cnt = CTL_MAX_PORTS;
 		softc->port_min = 0;
 	} else {
-		softc->port_cnt = CTL_MAX_PORTS / NUM_TARGET_PORT_GROUPS;
+		softc->port_cnt = CTL_MAX_PORTS / NUM_HA_SHELVES;
 		softc->port_min = (softc->ha_id - 1) * softc->port_cnt;
 	}
 	softc->port_max = softc->port_min + softc->port_cnt;
@@ -7137,8 +7137,8 @@ ctl_report_tagret_port_groups(struct ctl
 {
 	struct scsi_maintenance_in *cdb;
 	int retval;
-	int alloc_len, ext, total_len = 0, g, pc, pg, gs, os;
-	int num_target_port_groups, num_target_ports;
+	int alloc_len, ext, total_len = 0, g, pc, pg, ts, os;
+	int num_ha_groups, num_target_ports, shared_group;
 	struct ctl_lun *lun;
 	struct ctl_softc *softc;
 	struct ctl_port *port;
@@ -7172,11 +7172,8 @@ ctl_report_tagret_port_groups(struct ctl
 		return(retval);
 	}
 
-	if (softc->is_single)
-		num_target_port_groups = 1;
-	else
-		num_target_port_groups = NUM_TARGET_PORT_GROUPS;
 	num_target_ports = 0;
+	shared_group = (softc->is_single != 0);
 	mtx_lock(&softc->ctl_lock);
 	STAILQ_FOREACH(port, &softc->port_list, links) {
 		if ((port->status & CTL_PORT_STATUS_ONLINE) == 0)
@@ -7184,15 +7181,18 @@ ctl_report_tagret_port_groups(struct ctl
 		if (ctl_lun_map_to_port(port, lun->lun) >= CTL_MAX_LUNS)
 			continue;
 		num_target_ports++;
+		if (port->status & CTL_PORT_STATUS_HA_SHARED)
+			shared_group = 1;
 	}
 	mtx_unlock(&softc->ctl_lock);
+	num_ha_groups = (softc->is_single) ? 0 : NUM_HA_SHELVES;
 
 	if (ext)
 		total_len = sizeof(struct scsi_target_group_data_extended);
 	else
 		total_len = sizeof(struct scsi_target_group_data);
 	total_len += sizeof(struct scsi_target_port_group_descriptor) *
-		num_target_port_groups +
+		(shared_group + num_ha_groups) +
 	    sizeof(struct scsi_target_port_descriptor) * num_target_ports;
 
 	alloc_len = scsi_4btoul(cdb->length);
@@ -7229,24 +7229,62 @@ ctl_report_tagret_port_groups(struct ctl
 
 	mtx_lock(&softc->ctl_lock);
 	pg = softc->port_min / softc->port_cnt;
-	if (softc->ha_link == CTL_HA_LINK_OFFLINE)
-		gs = TPG_ASYMMETRIC_ACCESS_UNAVAILABLE;
-	else if (softc->ha_link == CTL_HA_LINK_UNKNOWN)
-		gs = TPG_ASYMMETRIC_ACCESS_TRANSITIONING;
-	else if (softc->ha_mode == CTL_HA_MODE_ACT_STBY)
-		gs = TPG_ASYMMETRIC_ACCESS_STANDBY;
-	else
-		gs = TPG_ASYMMETRIC_ACCESS_NONOPTIMIZED;
-	if (lun->flags & CTL_LUN_PRIMARY_SC) {
-		os = gs;
-		gs = TPG_ASYMMETRIC_ACCESS_OPTIMIZED;
-	} else
-		os = TPG_ASYMMETRIC_ACCESS_OPTIMIZED;
-	for (g = 0; g < num_target_port_groups; g++) {
-		tpg_desc->pref_state = (g == pg) ? gs : os;
+	if (lun->flags & (CTL_LUN_PRIMARY_SC | CTL_LUN_PEER_SC_PRIMARY)) {
+		/* Some shelf is known to be primary. */
+		if (softc->ha_link == CTL_HA_LINK_OFFLINE)
+			os = TPG_ASYMMETRIC_ACCESS_UNAVAILABLE;
+		else if (softc->ha_link == CTL_HA_LINK_UNKNOWN)
+			os = TPG_ASYMMETRIC_ACCESS_TRANSITIONING;
+		else if (softc->ha_mode == CTL_HA_MODE_ACT_STBY)
+			os = TPG_ASYMMETRIC_ACCESS_STANDBY;
+		else
+			os = TPG_ASYMMETRIC_ACCESS_NONOPTIMIZED;
+		if (lun->flags & CTL_LUN_PRIMARY_SC) {
+			ts = TPG_ASYMMETRIC_ACCESS_OPTIMIZED;
+		} else {
+			ts = os;
+			os = TPG_ASYMMETRIC_ACCESS_OPTIMIZED;
+		}
+	} else {
+		/* No known primary shelf. */
+		if (softc->ha_link == CTL_HA_LINK_OFFLINE) {
+			ts = TPG_ASYMMETRIC_ACCESS_UNAVAILABLE;
+			os = TPG_ASYMMETRIC_ACCESS_OPTIMIZED;
+		} else if (softc->ha_link == CTL_HA_LINK_UNKNOWN) {
+			ts = TPG_ASYMMETRIC_ACCESS_TRANSITIONING;
+			os = TPG_ASYMMETRIC_ACCESS_OPTIMIZED;
+		} else {
+			ts = os = TPG_ASYMMETRIC_ACCESS_TRANSITIONING;
+		}
+	}
+	if (shared_group) {
+		tpg_desc->pref_state = ts;
 		tpg_desc->support = TPG_AO_SUP | TPG_AN_SUP | TPG_S_SUP |
 		    TPG_U_SUP | TPG_T_SUP;
-		scsi_ulto2b(g + 1, tpg_desc->target_port_group);
+		scsi_ulto2b(1, tpg_desc->target_port_group);
+		tpg_desc->status = TPG_IMPLICIT;
+		pc = 0;
+		STAILQ_FOREACH(port, &softc->port_list, links) {
+			if ((port->status & CTL_PORT_STATUS_ONLINE) == 0)
+				continue;
+			if (!softc->is_single &&
+			    (port->status & CTL_PORT_STATUS_HA_SHARED) == 0)
+				continue;
+			if (ctl_lun_map_to_port(port, lun->lun) >= CTL_MAX_LUNS)
+				continue;
+			scsi_ulto2b(port->targ_port, tpg_desc->descriptors[pc].
+			    relative_target_port_identifier);
+			pc++;
+		}
+		tpg_desc->target_port_count = pc;
+		tpg_desc = (struct scsi_target_port_group_descriptor *)
+		    &tpg_desc->descriptors[pc];
+	}
+	for (g = 0; g < num_ha_groups; g++) {
+		tpg_desc->pref_state = (g == pg) ? ts : os;
+		tpg_desc->support = TPG_AO_SUP | TPG_AN_SUP | TPG_S_SUP |
+		    TPG_U_SUP | TPG_T_SUP;
+		scsi_ulto2b(2 + g, tpg_desc->target_port_group);
 		tpg_desc->status = TPG_IMPLICIT;
 		pc = 0;
 		STAILQ_FOREACH(port, &softc->port_list, links) {
@@ -7255,6 +7293,8 @@ ctl_report_tagret_port_groups(struct ctl
 				continue;
 			if ((port->status & CTL_PORT_STATUS_ONLINE) == 0)
 				continue;
+			if (port->status & CTL_PORT_STATUS_HA_SHARED)
+				continue;
 			if (ctl_lun_map_to_port(port, lun->lun) >= CTL_MAX_LUNS)
 				continue;
 			scsi_ulto2b(port->targ_port, tpg_desc->descriptors[pc].
@@ -9626,7 +9666,7 @@ ctl_inquiry_evpd_devid(struct ctl_scsiio
 	struct ctl_softc *softc;
 	struct ctl_lun *lun;
 	struct ctl_port *port;
-	int data_len;
+	int data_len, g;
 	uint8_t proto;
 
 	softc = control_softc;
@@ -9720,8 +9760,11 @@ ctl_inquiry_evpd_devid(struct ctl_scsiio
 	desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT |
 	    SVPD_ID_TYPE_TPORTGRP;
 	desc->length = 4;
-	scsi_ulto2b(ctsio->io_hdr.nexus.targ_port / softc->port_cnt + 1,
-	    &desc->identifier[2]);
+	if (softc->is_single || port->status & CTL_PORT_STATUS_HA_SHARED)
+		g = 1;
+	else
+		g = 2 + ctsio->io_hdr.nexus.targ_port / softc->port_cnt;
+	scsi_ulto2b(g, &desc->identifier[2]);
 	desc = (struct scsi_vpd_id_descriptor *)(&desc->identifier[0] +
 	    sizeof(struct scsi_vpd_id_trgt_port_grp_id));
 

Modified: head/sys/cam/ctl/ctl_frontend.c
==============================================================================
--- head/sys/cam/ctl/ctl_frontend.c	Wed Nov 11 12:36:42 2015	(r290669)
+++ head/sys/cam/ctl/ctl_frontend.c	Wed Nov 11 13:18:38 2015	(r290670)
@@ -310,6 +310,7 @@ ctl_port_online(struct ctl_port *port)
 {
 	struct ctl_softc *softc = port->ctl_softc;
 	struct ctl_lun *lun;
+	const char *value;
 	uint32_t l;
 
 	if (port->lun_enable != NULL) {
@@ -328,6 +329,13 @@ ctl_port_online(struct ctl_port *port)
 	if (port->port_online != NULL)
 		port->port_online(port->onoff_arg);
 	mtx_lock(&softc->ctl_lock);
+	if (softc->is_single == 0) {
+		value = ctl_get_opt(&port->options, "ha_shared");
+		if (value != NULL && strcmp(value, "on") == 0)
+			port->status |= CTL_PORT_STATUS_HA_SHARED;
+		else
+			port->status &= ~CTL_PORT_STATUS_HA_SHARED;
+	}
 	port->status |= CTL_PORT_STATUS_ONLINE;
 	STAILQ_FOREACH(lun, &softc->lun_list, links) {
 		if (ctl_lun_map_to_port(port, lun->lun) >= CTL_MAX_LUNS)

Modified: head/sys/cam/ctl/ctl_frontend.h
==============================================================================
--- head/sys/cam/ctl/ctl_frontend.h	Wed Nov 11 12:36:42 2015	(r290669)
+++ head/sys/cam/ctl/ctl_frontend.h	Wed Nov 11 13:18:38 2015	(r290670)
@@ -41,7 +41,8 @@
 
 typedef enum {
 	CTL_PORT_STATUS_NONE		= 0x00,
-	CTL_PORT_STATUS_ONLINE		= 0x01
+	CTL_PORT_STATUS_ONLINE		= 0x01,
+	CTL_PORT_STATUS_HA_SHARED	= 0x02
 } ctl_port_status;
 
 typedef int (*fe_init_t)(void);

Modified: head/sys/cam/ctl/ctl_private.h
==============================================================================
--- head/sys/cam/ctl/ctl_private.h	Wed Nov 11 12:36:42 2015	(r290669)
+++ head/sys/cam/ctl/ctl_private.h	Wed Nov 11 13:18:38 2015	(r290670)
@@ -356,10 +356,7 @@ struct ctl_devid {
 	uint8_t		data[];
 };
 
-/*
- * For report target port groups.
- */
-#define NUM_TARGET_PORT_GROUPS	2
+#define NUM_HA_SHELVES		2
 
 #define CTL_WRITE_BUFFER_SIZE	262144
 



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