svn commit: r268308 - head/sys/cam/ctl

Alexander Motin mav at FreeBSD.org
Sun Jul 6 07:02:37 UTC 2014


Author: mav
Date: Sun Jul  6 07:02:36 2014
New Revision: 268308
URL: http://svnweb.freebsd.org/changeset/base/268308

Log:
  Make REPORT TARGET PORT GROUPS command report realistic data instead of
  hardcoded garbage.

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

Modified: head/sys/cam/ctl/ctl.c
==============================================================================
--- head/sys/cam/ctl/ctl.c	Sun Jul  6 06:21:34 2014	(r268307)
+++ head/sys/cam/ctl/ctl.c	Sun Jul  6 07:02:36 2014	(r268308)
@@ -347,6 +347,7 @@ static int ctl_ioctl(struct cdev *dev, u
 uint32_t ctl_get_resindex(struct ctl_nexus *nexus);
 uint32_t ctl_port_idx(int port_num);
 static uint32_t ctl_map_lun(int port_num, uint32_t lun);
+static uint32_t ctl_map_lun_back(int port_num, uint32_t lun);
 #ifdef unused
 static union ctl_io *ctl_malloc_io(ctl_io_type io_type, uint32_t targ_port,
 				   uint32_t targ_target, uint32_t targ_lun,
@@ -3359,6 +3360,22 @@ ctl_map_lun(int port_num, uint32_t lun_i
 	return (port->lun_map(port->targ_lun_arg, lun_id));
 }
 
+static uint32_t
+ctl_map_lun_back(int port_num, uint32_t lun_id)
+{
+	struct ctl_port *port;
+	uint32_t i;
+
+	port = control_softc->ctl_ports[ctl_port_idx(port_num)];
+	if (port->lun_map == NULL)
+		return (lun_id);
+	for (i = 0; i < CTL_MAX_LUNS; i++) {
+		if (port->lun_map(port->targ_lun_arg, i) == lun_id)
+			return (i);
+	}
+	return (UINT32_MAX);
+}
+
 /*
  * Note:  This only works for bitmask sizes that are at least 32 bits, and
  * that are a power of 2.
@@ -7118,14 +7135,14 @@ ctl_report_tagret_port_groups(struct ctl
 {
 	struct scsi_maintenance_in *cdb;
 	int retval;
-	int alloc_len, total_len = 0;
-	int num_target_port_groups, single;
+	int alloc_len, ext, total_len = 0, g, p, pc, pg;
+	int num_target_port_groups, num_target_ports, single;
 	struct ctl_lun *lun;
 	struct ctl_softc *softc;
+	struct ctl_port *port;
 	struct scsi_target_group_data *rtg_ptr;
-	struct scsi_target_port_group_descriptor *tpg_desc_ptr1, *tpg_desc_ptr2;
-	struct scsi_target_port_descriptor  *tp_desc_ptr1_1, *tp_desc_ptr1_2,
-	                                    *tp_desc_ptr2_1, *tp_desc_ptr2_2;
+	struct scsi_target_group_data_extended *rtg_ext_ptr;
+	struct scsi_target_port_group_descriptor *tpg_desc;
 
 	CTL_DEBUG_PRINT(("ctl_report_tagret_port_groups\n"));
 
@@ -7135,17 +7152,48 @@ ctl_report_tagret_port_groups(struct ctl
 
 	retval = CTL_RETVAL_COMPLETE;
 
+	switch (cdb->byte2 & STG_PDF_MASK) {
+	case STG_PDF_LENGTH:
+		ext = 0;
+		break;
+	case STG_PDF_EXTENDED:
+		ext = 1;
+		break;
+	default:
+		ctl_set_invalid_field(/*ctsio*/ ctsio,
+				      /*sks_valid*/ 1,
+				      /*command*/ 1,
+				      /*field*/ 2,
+				      /*bit_valid*/ 1,
+				      /*bit*/ 5);
+		ctl_done((union ctl_io *)ctsio);
+		return(retval);
+	}
+
 	single = ctl_is_single;
 	if (single)
-        	num_target_port_groups = NUM_TARGET_PORT_GROUPS - 1;
+		num_target_port_groups = 1;
 	else
-        	num_target_port_groups = NUM_TARGET_PORT_GROUPS;
+		num_target_port_groups = NUM_TARGET_PORT_GROUPS;
+	num_target_ports = 0;
+	mtx_lock(&softc->ctl_lock);
+	STAILQ_FOREACH(port, &softc->port_list, links) {
+		if ((port->status & CTL_PORT_STATUS_ONLINE) == 0)
+			continue;
+		if (ctl_map_lun_back(port->targ_port, lun->lun) >= CTL_MAX_LUNS)
+			continue;
+		num_target_ports++;
+	}
+	mtx_unlock(&softc->ctl_lock);
 
-	total_len = sizeof(struct scsi_target_group_data) +
-		sizeof(struct scsi_target_port_group_descriptor) *
+	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 +
-		sizeof(struct scsi_target_port_descriptor) *
-		NUM_PORTS_PER_GRP * num_target_port_groups;
+	    sizeof(struct scsi_target_port_descriptor) *
+		num_target_ports * num_target_port_groups;
 
 	alloc_len = scsi_4btoul(cdb->length);
 
@@ -7165,76 +7213,51 @@ ctl_report_tagret_port_groups(struct ctl
 	ctsio->kern_data_resid = 0;
 	ctsio->kern_rel_offset = 0;
 
-	rtg_ptr = (struct scsi_target_group_data *)ctsio->kern_data_ptr;
-
-	tpg_desc_ptr1 = &rtg_ptr->groups[0];
-	tp_desc_ptr1_1 = &tpg_desc_ptr1->descriptors[0];
-	tp_desc_ptr1_2 = (struct scsi_target_port_descriptor *)
-	        &tp_desc_ptr1_1->desc_list[0];
-
-	if (single == 0) {
-		tpg_desc_ptr2 = (struct scsi_target_port_group_descriptor *)
-	                &tp_desc_ptr1_2->desc_list[0];
-		tp_desc_ptr2_1 = &tpg_desc_ptr2->descriptors[0];
-		tp_desc_ptr2_2 = (struct scsi_target_port_descriptor *)
-	        	&tp_desc_ptr2_1->desc_list[0];
-        } else {
-		tpg_desc_ptr2 = NULL;
-		tp_desc_ptr2_1 = NULL;
-		tp_desc_ptr2_2 = NULL;
-	}
-
-	scsi_ulto4b(total_len - 4, rtg_ptr->length);
-	if (single == 0) {
-        	if (ctsio->io_hdr.nexus.targ_port < CTL_MAX_PORTS) {
-			if (lun->flags & CTL_LUN_PRIMARY_SC) {
-				tpg_desc_ptr1->pref_state = TPG_PRIMARY;
-				tpg_desc_ptr2->pref_state =
-					TPG_ASYMMETRIC_ACCESS_NONOPTIMIZED;
-			} else {
-				tpg_desc_ptr1->pref_state =
-					TPG_ASYMMETRIC_ACCESS_NONOPTIMIZED;
-				tpg_desc_ptr2->pref_state = TPG_PRIMARY;
-			}
-		} else {
-			if (lun->flags & CTL_LUN_PRIMARY_SC) {
-				tpg_desc_ptr1->pref_state =
-					TPG_ASYMMETRIC_ACCESS_NONOPTIMIZED;
-				tpg_desc_ptr2->pref_state = TPG_PRIMARY;
-			} else {
-				tpg_desc_ptr1->pref_state = TPG_PRIMARY;
-				tpg_desc_ptr2->pref_state =
-					TPG_ASYMMETRIC_ACCESS_NONOPTIMIZED;
-			}
-		}
+	if (ext) {
+		rtg_ext_ptr = (struct scsi_target_group_data_extended *)
+		    ctsio->kern_data_ptr;
+		scsi_ulto4b(total_len - 4, rtg_ext_ptr->length);
+		rtg_ext_ptr->format_type = 0x10;
+		rtg_ext_ptr->implicit_transition_time = 0;
+		tpg_desc = &rtg_ext_ptr->groups[0];
 	} else {
-		tpg_desc_ptr1->pref_state = TPG_PRIMARY;
+		rtg_ptr = (struct scsi_target_group_data *)
+		    ctsio->kern_data_ptr;
+		scsi_ulto4b(total_len - 4, rtg_ptr->length);
+		tpg_desc = &rtg_ptr->groups[0];
 	}
-	tpg_desc_ptr1->support = 0;
-	tpg_desc_ptr1->target_port_group[1] = 1;
-	tpg_desc_ptr1->status = TPG_IMPLICIT;
-	tpg_desc_ptr1->target_port_count= NUM_PORTS_PER_GRP;
-
-	if (single == 0) {
-		tpg_desc_ptr2->support = 0;
-		tpg_desc_ptr2->target_port_group[1] = 2;
-		tpg_desc_ptr2->status = TPG_IMPLICIT;
-		tpg_desc_ptr2->target_port_count = NUM_PORTS_PER_GRP;
 
-		tp_desc_ptr1_1->relative_target_port_identifier[1] = 1;
-		tp_desc_ptr1_2->relative_target_port_identifier[1] = 2;
-
-		tp_desc_ptr2_1->relative_target_port_identifier[1] = 9;
-		tp_desc_ptr2_2->relative_target_port_identifier[1] = 10;
-	} else {
-        	if (ctsio->io_hdr.nexus.targ_port < CTL_MAX_PORTS) {
-			tp_desc_ptr1_1->relative_target_port_identifier[1] = 1;
-			tp_desc_ptr1_2->relative_target_port_identifier[1] = 2;
-		} else {
-			tp_desc_ptr1_1->relative_target_port_identifier[1] = 9;
-			tp_desc_ptr1_2->relative_target_port_identifier[1] = 10;
-		}
+	pg = ctsio->io_hdr.nexus.targ_port / CTL_MAX_PORTS;
+	mtx_lock(&softc->ctl_lock);
+	for (g = 0; g < num_target_port_groups; g++) {
+		if (g == pg)
+			tpg_desc->pref_state = TPG_PRIMARY |
+			    TPG_ASYMMETRIC_ACCESS_OPTIMIZED;
+		else
+			tpg_desc->pref_state =
+			    TPG_ASYMMETRIC_ACCESS_NONOPTIMIZED;
+		tpg_desc->support = TPG_AO_SUP;
+		if (!single)
+			tpg_desc->support = TPG_AN_SUP;
+		scsi_ulto2b(g + 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 (ctl_map_lun_back(port->targ_port, lun->lun) >=
+			    CTL_MAX_LUNS)
+				continue;
+			p = port->targ_port % CTL_MAX_PORTS + g * CTL_MAX_PORTS;
+			scsi_ulto2b(p, 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];
 	}
+	mtx_unlock(&softc->ctl_lock);
 
 	ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
 	ctsio->be_move_done = ctl_config_move_done;
@@ -9776,10 +9799,8 @@ ctl_inquiry_evpd_devid(struct ctl_scsiio
 	desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT |
 	    SVPD_ID_TYPE_TPORTGRP;
 	desc->length = 4;
-	if (ctsio->io_hdr.nexus.targ_port < CTL_MAX_PORTS || ctl_is_single)
-		scsi_ulto2b(1, &desc->identifier[2]);
-	else
-		scsi_ulto2b(2, &desc->identifier[2]);
+	scsi_ulto2b(ctsio->io_hdr.nexus.targ_port / CTL_MAX_PORTS + 1,
+	    &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_private.h
==============================================================================
--- head/sys/cam/ctl/ctl_private.h	Sun Jul  6 06:21:34 2014	(r268307)
+++ head/sys/cam/ctl/ctl_private.h	Sun Jul  6 07:02:36 2014	(r268308)
@@ -376,7 +376,6 @@ struct ctl_devid {
  * For report target port groups.
  */
 #define NUM_TARGET_PORT_GROUPS	2
-#define NUM_PORTS_PER_GRP	2
 
 struct ctl_lun {
 	struct mtx			lun_lock;


More information about the svn-src-head mailing list