xref: /onnv-gate/usr/src/uts/common/io/comstar/stmf/lun_map.c (revision 12571:05943d9c379f)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
22*12571SViswanathan.Kannappan@Sun.COM  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
237836SJohn.Forte@Sun.COM  */
247836SJohn.Forte@Sun.COM 
257836SJohn.Forte@Sun.COM #include <sys/conf.h>
267836SJohn.Forte@Sun.COM #include <sys/file.h>
277836SJohn.Forte@Sun.COM #include <sys/ddi.h>
287836SJohn.Forte@Sun.COM #include <sys/sunddi.h>
297836SJohn.Forte@Sun.COM #include <sys/modctl.h>
307836SJohn.Forte@Sun.COM #include <sys/scsi/scsi.h>
317836SJohn.Forte@Sun.COM #include <sys/scsi/impl/scsi_reset_notify.h>
327836SJohn.Forte@Sun.COM #include <sys/disp.h>
337836SJohn.Forte@Sun.COM #include <sys/byteorder.h>
347836SJohn.Forte@Sun.COM #include <sys/atomic.h>
357836SJohn.Forte@Sun.COM 
36*12571SViswanathan.Kannappan@Sun.COM #include <sys/stmf.h>
37*12571SViswanathan.Kannappan@Sun.COM #include <sys/lpif.h>
38*12571SViswanathan.Kannappan@Sun.COM #include <sys/portif.h>
39*12571SViswanathan.Kannappan@Sun.COM #include <sys/stmf_ioctl.h>
40*12571SViswanathan.Kannappan@Sun.COM 
417836SJohn.Forte@Sun.COM #include "stmf_impl.h"
427836SJohn.Forte@Sun.COM #include "lun_map.h"
437836SJohn.Forte@Sun.COM #include "stmf_state.h"
447836SJohn.Forte@Sun.COM 
457836SJohn.Forte@Sun.COM void stmf_update_sessions_per_ve(stmf_view_entry_t *ve,
467836SJohn.Forte@Sun.COM 		stmf_lu_t *lu, int action);
477836SJohn.Forte@Sun.COM void stmf_add_lus_to_session_per_vemap(stmf_i_local_port_t *ilport,
487836SJohn.Forte@Sun.COM 		stmf_i_scsi_session_t *iss, stmf_lun_map_t *vemap);
497836SJohn.Forte@Sun.COM stmf_id_data_t *stmf_lookup_group_for_host(uint8_t *ident, uint16_t ident_size);
507836SJohn.Forte@Sun.COM stmf_status_t stmf_add_ent_to_map(stmf_lun_map_t *sm, void *ent, uint8_t *lun);
517836SJohn.Forte@Sun.COM stmf_status_t stmf_remove_ent_from_map(stmf_lun_map_t *sm, uint8_t *lun);
527836SJohn.Forte@Sun.COM uint16_t stmf_get_next_free_lun(stmf_lun_map_t *sm, uint8_t *lun);
537836SJohn.Forte@Sun.COM stmf_status_t stmf_add_tg(uint8_t *tg_name, uint16_t tg_name_size,
547836SJohn.Forte@Sun.COM 		int allow_special, uint32_t *err_detail);
557836SJohn.Forte@Sun.COM stmf_status_t stmf_add_hg(uint8_t *hg_name, uint16_t hg_name_size,
567836SJohn.Forte@Sun.COM 		int allow_special, uint32_t *err_detail);
577836SJohn.Forte@Sun.COM stmf_i_local_port_t *stmf_targetident_to_ilport(uint8_t *target_ident,
587836SJohn.Forte@Sun.COM 		uint16_t ident_size);
597836SJohn.Forte@Sun.COM stmf_i_scsi_session_t *stmf_lookup_session_for_hostident(
607836SJohn.Forte@Sun.COM 		stmf_i_local_port_t *ilport, uint8_t *host_ident,
617836SJohn.Forte@Sun.COM 		uint16_t ident_size);
627836SJohn.Forte@Sun.COM stmf_i_lu_t *stmf_luident_to_ilu(uint8_t *lu_ident);
637836SJohn.Forte@Sun.COM stmf_lun_map_t *stmf_get_ve_map_per_ids(stmf_id_data_t *tgid,
647836SJohn.Forte@Sun.COM 		stmf_id_data_t *hgid);
657836SJohn.Forte@Sun.COM stmf_lun_map_t *stmf_duplicate_ve_map(stmf_lun_map_t *src);
667836SJohn.Forte@Sun.COM int stmf_merge_ve_map(stmf_lun_map_t *src, stmf_lun_map_t *dst,
677836SJohn.Forte@Sun.COM 		stmf_lun_map_t **pp_ret_map, stmf_merge_flags_t mf);
687836SJohn.Forte@Sun.COM void stmf_destroy_ve_map(stmf_lun_map_t *dst);
697836SJohn.Forte@Sun.COM void stmf_free_id(stmf_id_data_t *id);
707836SJohn.Forte@Sun.COM 
717836SJohn.Forte@Sun.COM 
727836SJohn.Forte@Sun.COM /*
737836SJohn.Forte@Sun.COM  * Init the view
747836SJohn.Forte@Sun.COM  */
757836SJohn.Forte@Sun.COM void
stmf_view_init()767836SJohn.Forte@Sun.COM stmf_view_init()
777836SJohn.Forte@Sun.COM {
787836SJohn.Forte@Sun.COM 	uint8_t grpname_forall = '*';
797836SJohn.Forte@Sun.COM 	(void) stmf_add_hg(&grpname_forall, 1, 1, NULL);
807836SJohn.Forte@Sun.COM 	(void) stmf_add_tg(&grpname_forall, 1, 1, NULL);
817836SJohn.Forte@Sun.COM }
827836SJohn.Forte@Sun.COM 
837836SJohn.Forte@Sun.COM /*
847836SJohn.Forte@Sun.COM  * Clear config database here
857836SJohn.Forte@Sun.COM  */
867836SJohn.Forte@Sun.COM void
stmf_view_clear_config()877836SJohn.Forte@Sun.COM stmf_view_clear_config()
887836SJohn.Forte@Sun.COM {
897836SJohn.Forte@Sun.COM 	stmf_id_data_t *idgrp, *idgrp_next, *idmemb, *idmemb_next;
907836SJohn.Forte@Sun.COM 	stmf_ver_tg_t *vtg, *vtg_next;
917836SJohn.Forte@Sun.COM 	stmf_ver_hg_t *vhg, *vhg_next;
927836SJohn.Forte@Sun.COM 	stmf_view_entry_t *ve, *ve_next;
937836SJohn.Forte@Sun.COM 	stmf_i_lu_t	*ilu;
947836SJohn.Forte@Sun.COM 	stmf_id_list_t	*idlist;
957836SJohn.Forte@Sun.COM 	stmf_i_local_port_t *ilport;
967836SJohn.Forte@Sun.COM 
977836SJohn.Forte@Sun.COM 	for (vtg = stmf_state.stmf_ver_tg_head; vtg; vtg = vtg_next) {
987836SJohn.Forte@Sun.COM 		for (vhg = vtg->vert_verh_list; vhg; vhg = vhg_next) {
997836SJohn.Forte@Sun.COM 			if (vhg->verh_ve_map.lm_nentries) {
1007836SJohn.Forte@Sun.COM 				kmem_free(vhg->verh_ve_map.lm_plus,
1017836SJohn.Forte@Sun.COM 				    vhg->verh_ve_map.lm_nentries *
1027836SJohn.Forte@Sun.COM 				    sizeof (void *));
1037836SJohn.Forte@Sun.COM 			}
1047836SJohn.Forte@Sun.COM 			vhg_next = vhg->verh_next;
1057836SJohn.Forte@Sun.COM 			kmem_free(vhg, sizeof (stmf_ver_hg_t));
1067836SJohn.Forte@Sun.COM 		}
1077836SJohn.Forte@Sun.COM 		vtg_next = vtg->vert_next;
1087836SJohn.Forte@Sun.COM 		kmem_free(vtg, sizeof (stmf_ver_tg_t));
1097836SJohn.Forte@Sun.COM 	}
1107836SJohn.Forte@Sun.COM 	stmf_state.stmf_ver_tg_head = NULL;
1117836SJohn.Forte@Sun.COM 
1127836SJohn.Forte@Sun.COM 	if (stmf_state.stmf_luid_list.id_count) {
1137836SJohn.Forte@Sun.COM 		/* clear the views for lus */
1147836SJohn.Forte@Sun.COM 		for (idmemb = stmf_state.stmf_luid_list.idl_head;
1157836SJohn.Forte@Sun.COM 		    idmemb; idmemb = idmemb_next) {
1167836SJohn.Forte@Sun.COM 			for (ve = (stmf_view_entry_t *)idmemb->id_impl_specific;
1177836SJohn.Forte@Sun.COM 			    ve; ve = ve_next) {
1187836SJohn.Forte@Sun.COM 				ve_next = ve->ve_next;
1197836SJohn.Forte@Sun.COM 				ve->ve_hg->id_refcnt--;
1207836SJohn.Forte@Sun.COM 				ve->ve_tg->id_refcnt--;
1217836SJohn.Forte@Sun.COM 				kmem_free(ve, sizeof (stmf_view_entry_t));
1227836SJohn.Forte@Sun.COM 			}
1237836SJohn.Forte@Sun.COM 			if (idmemb->id_pt_to_object) {
1247836SJohn.Forte@Sun.COM 				ilu = (stmf_i_lu_t *)(idmemb->id_pt_to_object);
1257836SJohn.Forte@Sun.COM 				ilu->ilu_luid = NULL;
1267836SJohn.Forte@Sun.COM 			}
1277836SJohn.Forte@Sun.COM 			idmemb_next = idmemb->id_next;
1287836SJohn.Forte@Sun.COM 			stmf_free_id(idmemb);
1297836SJohn.Forte@Sun.COM 		}
1307836SJohn.Forte@Sun.COM 		stmf_state.stmf_luid_list.id_count = 0;
1317836SJohn.Forte@Sun.COM 		stmf_state.stmf_luid_list.idl_head =
1327836SJohn.Forte@Sun.COM 		    stmf_state.stmf_luid_list.idl_tail = NULL;
1337836SJohn.Forte@Sun.COM 	}
1347836SJohn.Forte@Sun.COM 
1357836SJohn.Forte@Sun.COM 	if (stmf_state.stmf_hg_list.id_count) {
1367836SJohn.Forte@Sun.COM 		/* free all the host group */
1377836SJohn.Forte@Sun.COM 		for (idgrp = stmf_state.stmf_hg_list.idl_head;
1387836SJohn.Forte@Sun.COM 		    idgrp; idgrp = idgrp_next) {
1397836SJohn.Forte@Sun.COM 			idlist = (stmf_id_list_t *)(idgrp->id_impl_specific);
1407836SJohn.Forte@Sun.COM 			if (idlist->id_count) {
1417836SJohn.Forte@Sun.COM 				for (idmemb = idlist->idl_head; idmemb;
1427836SJohn.Forte@Sun.COM 				    idmemb = idmemb_next) {
1437836SJohn.Forte@Sun.COM 					idmemb_next = idmemb->id_next;
1447836SJohn.Forte@Sun.COM 					stmf_free_id(idmemb);
1457836SJohn.Forte@Sun.COM 				}
1467836SJohn.Forte@Sun.COM 			}
1477836SJohn.Forte@Sun.COM 			idgrp_next = idgrp->id_next;
1487836SJohn.Forte@Sun.COM 			stmf_free_id(idgrp);
1497836SJohn.Forte@Sun.COM 		}
1507836SJohn.Forte@Sun.COM 		stmf_state.stmf_hg_list.id_count = 0;
1517836SJohn.Forte@Sun.COM 		stmf_state.stmf_hg_list.idl_head =
1527836SJohn.Forte@Sun.COM 		    stmf_state.stmf_hg_list.idl_tail = NULL;
1537836SJohn.Forte@Sun.COM 	}
1547836SJohn.Forte@Sun.COM 	if (stmf_state.stmf_tg_list.id_count) {
1557836SJohn.Forte@Sun.COM 		/* free all the target group */
1567836SJohn.Forte@Sun.COM 		for (idgrp = stmf_state.stmf_tg_list.idl_head;
1577836SJohn.Forte@Sun.COM 		    idgrp; idgrp = idgrp_next) {
1587836SJohn.Forte@Sun.COM 			idlist = (stmf_id_list_t *)(idgrp->id_impl_specific);
1597836SJohn.Forte@Sun.COM 			if (idlist->id_count) {
1607836SJohn.Forte@Sun.COM 				for (idmemb = idlist->idl_head; idmemb;
1617836SJohn.Forte@Sun.COM 				    idmemb = idmemb_next) {
1627836SJohn.Forte@Sun.COM 					idmemb_next = idmemb->id_next;
1637836SJohn.Forte@Sun.COM 					stmf_free_id(idmemb);
1647836SJohn.Forte@Sun.COM 				}
1657836SJohn.Forte@Sun.COM 			}
1667836SJohn.Forte@Sun.COM 			idgrp_next = idgrp->id_next;
1677836SJohn.Forte@Sun.COM 			stmf_free_id(idgrp);
1687836SJohn.Forte@Sun.COM 		}
1697836SJohn.Forte@Sun.COM 		stmf_state.stmf_tg_list.id_count = 0;
1707836SJohn.Forte@Sun.COM 		stmf_state.stmf_tg_list.idl_head =
1717836SJohn.Forte@Sun.COM 		    stmf_state.stmf_tg_list.idl_tail = NULL;
1727836SJohn.Forte@Sun.COM 	}
1737836SJohn.Forte@Sun.COM 
1747836SJohn.Forte@Sun.COM 	for (ilport = stmf_state.stmf_ilportlist; ilport;
1757836SJohn.Forte@Sun.COM 	    ilport = ilport->ilport_next) {
1767836SJohn.Forte@Sun.COM 		ilport->ilport_tg = NULL;
1777836SJohn.Forte@Sun.COM 	}
1787836SJohn.Forte@Sun.COM }
1797836SJohn.Forte@Sun.COM 
1807836SJohn.Forte@Sun.COM /*
1817836SJohn.Forte@Sun.COM  * Create luns map for session based on the view
1827836SJohn.Forte@Sun.COM  */
1837836SJohn.Forte@Sun.COM stmf_status_t
stmf_session_create_lun_map(stmf_i_local_port_t * ilport,stmf_i_scsi_session_t * iss)1847836SJohn.Forte@Sun.COM stmf_session_create_lun_map(stmf_i_local_port_t *ilport,
1857836SJohn.Forte@Sun.COM 		stmf_i_scsi_session_t *iss)
1867836SJohn.Forte@Sun.COM {
1877836SJohn.Forte@Sun.COM 	stmf_id_data_t *tg;
1887836SJohn.Forte@Sun.COM 	stmf_id_data_t *hg;
1897836SJohn.Forte@Sun.COM 	stmf_ver_tg_t	*vertg;
1907836SJohn.Forte@Sun.COM 	char *phg_data, *ptg_data;
1917836SJohn.Forte@Sun.COM 	stmf_ver_hg_t	*verhg;
1927836SJohn.Forte@Sun.COM 	stmf_lun_map_t	*ve_map;
1937836SJohn.Forte@Sun.COM 
19411978STim.Szeto@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
19511978STim.Szeto@Sun.COM 
1967836SJohn.Forte@Sun.COM 	tg = ilport->ilport_tg;
1977836SJohn.Forte@Sun.COM 	hg = stmf_lookup_group_for_host(iss->iss_ss->ss_rport_id->ident,
1987836SJohn.Forte@Sun.COM 	    iss->iss_ss->ss_rport_id->ident_length);
1997836SJohn.Forte@Sun.COM 	iss->iss_hg = hg;
2007836SJohn.Forte@Sun.COM 
2017836SJohn.Forte@Sun.COM 	/*
2027836SJohn.Forte@Sun.COM 	 * get the view entry map,
2037836SJohn.Forte@Sun.COM 	 * take all host/target group into consideration
2047836SJohn.Forte@Sun.COM 	 */
2057836SJohn.Forte@Sun.COM 	ve_map = stmf_duplicate_ve_map(0);
2067836SJohn.Forte@Sun.COM 	for (vertg = stmf_state.stmf_ver_tg_head; vertg != NULL;
2077836SJohn.Forte@Sun.COM 	    vertg = vertg->vert_next) {
2087836SJohn.Forte@Sun.COM 		ptg_data = (char *)vertg->vert_tg_ref->id_data;
2097836SJohn.Forte@Sun.COM 		if ((ptg_data[0] != '*') && (!tg ||
2107836SJohn.Forte@Sun.COM 		    ((tg->id_data[0] != '*') &&
2117836SJohn.Forte@Sun.COM 		    (vertg->vert_tg_ref != tg)))) {
2127836SJohn.Forte@Sun.COM 			continue;
2137836SJohn.Forte@Sun.COM 		}
2147836SJohn.Forte@Sun.COM 		for (verhg = vertg->vert_verh_list; verhg != NULL;
2157836SJohn.Forte@Sun.COM 		    verhg = verhg->verh_next) {
2167836SJohn.Forte@Sun.COM 			phg_data = (char *)verhg->verh_hg_ref->id_data;
2177836SJohn.Forte@Sun.COM 			if ((phg_data[0] != '*') && (!hg ||
2187836SJohn.Forte@Sun.COM 			    ((hg->id_data[0] != '*') &&
2197836SJohn.Forte@Sun.COM 			    (verhg->verh_hg_ref != hg)))) {
2207836SJohn.Forte@Sun.COM 				continue;
2217836SJohn.Forte@Sun.COM 			}
2227836SJohn.Forte@Sun.COM 			(void) stmf_merge_ve_map(&verhg->verh_ve_map, ve_map,
2237836SJohn.Forte@Sun.COM 			    &ve_map, 0);
2247836SJohn.Forte@Sun.COM 		}
2257836SJohn.Forte@Sun.COM 	}
2267836SJohn.Forte@Sun.COM 
2277836SJohn.Forte@Sun.COM 
2287836SJohn.Forte@Sun.COM 	if (ve_map->lm_nluns) {
2297836SJohn.Forte@Sun.COM 		stmf_add_lus_to_session_per_vemap(ilport, iss, ve_map);
2307836SJohn.Forte@Sun.COM 	}
2317836SJohn.Forte@Sun.COM 	/* not configured, cannot access any luns for now */
2327836SJohn.Forte@Sun.COM 
2337836SJohn.Forte@Sun.COM 	stmf_destroy_ve_map(ve_map);
2347836SJohn.Forte@Sun.COM 
2357836SJohn.Forte@Sun.COM 	return (STMF_SUCCESS);
2367836SJohn.Forte@Sun.COM }
2377836SJohn.Forte@Sun.COM 
2387836SJohn.Forte@Sun.COM /*
2397836SJohn.Forte@Sun.COM  * destroy lun map for session
2407836SJohn.Forte@Sun.COM  */
2417836SJohn.Forte@Sun.COM /* ARGSUSED */
2427836SJohn.Forte@Sun.COM stmf_status_t
stmf_session_destroy_lun_map(stmf_i_local_port_t * ilport,stmf_i_scsi_session_t * iss)2437836SJohn.Forte@Sun.COM stmf_session_destroy_lun_map(stmf_i_local_port_t *ilport,
2447836SJohn.Forte@Sun.COM 		stmf_i_scsi_session_t *iss)
2457836SJohn.Forte@Sun.COM {
2467836SJohn.Forte@Sun.COM 	stmf_lun_map_t *sm;
2477836SJohn.Forte@Sun.COM 	stmf_i_lu_t *ilu;
2487836SJohn.Forte@Sun.COM 	uint16_t n;
2497836SJohn.Forte@Sun.COM 	stmf_lun_map_ent_t *ent;
2507836SJohn.Forte@Sun.COM 
25111978STim.Szeto@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
2527836SJohn.Forte@Sun.COM 	/*
2537836SJohn.Forte@Sun.COM 	 * to avoid conflict with updating session's map,
2547836SJohn.Forte@Sun.COM 	 * which only grab stmf_lock
2557836SJohn.Forte@Sun.COM 	 */
2567836SJohn.Forte@Sun.COM 	sm = iss->iss_sm;
2577836SJohn.Forte@Sun.COM 	iss->iss_sm = NULL;
2587836SJohn.Forte@Sun.COM 	iss->iss_hg = NULL;
2597836SJohn.Forte@Sun.COM 	if (sm->lm_nentries) {
2607836SJohn.Forte@Sun.COM 		for (n = 0; n < sm->lm_nentries; n++) {
2617836SJohn.Forte@Sun.COM 			if ((ent = (stmf_lun_map_ent_t *)sm->lm_plus[n])
2627836SJohn.Forte@Sun.COM 			    != NULL) {
2637836SJohn.Forte@Sun.COM 				if (ent->ent_itl_datap) {
2647836SJohn.Forte@Sun.COM 					stmf_do_itl_dereg(ent->ent_lu,
2657836SJohn.Forte@Sun.COM 					    ent->ent_itl_datap,
2667836SJohn.Forte@Sun.COM 					    STMF_ITL_REASON_IT_NEXUS_LOSS);
2677836SJohn.Forte@Sun.COM 				}
2687836SJohn.Forte@Sun.COM 				ilu = (stmf_i_lu_t *)
2697836SJohn.Forte@Sun.COM 				    ent->ent_lu->lu_stmf_private;
2707836SJohn.Forte@Sun.COM 				atomic_add_32(&ilu->ilu_ref_cnt, -1);
2717836SJohn.Forte@Sun.COM 				kmem_free(sm->lm_plus[n],
2727836SJohn.Forte@Sun.COM 				    sizeof (stmf_lun_map_ent_t));
2737836SJohn.Forte@Sun.COM 			}
2747836SJohn.Forte@Sun.COM 		}
2757836SJohn.Forte@Sun.COM 		kmem_free(sm->lm_plus,
2767836SJohn.Forte@Sun.COM 		    sizeof (stmf_lun_map_ent_t *) * sm->lm_nentries);
2777836SJohn.Forte@Sun.COM 	}
2787836SJohn.Forte@Sun.COM 
2797836SJohn.Forte@Sun.COM 	kmem_free(sm, sizeof (*sm));
2807836SJohn.Forte@Sun.COM 	return (STMF_SUCCESS);
2817836SJohn.Forte@Sun.COM }
2827836SJohn.Forte@Sun.COM 
2837836SJohn.Forte@Sun.COM /*
2847836SJohn.Forte@Sun.COM  * Expects the session lock to be held.
2857836SJohn.Forte@Sun.COM  */
2867836SJohn.Forte@Sun.COM stmf_xfer_data_t *
stmf_session_prepare_report_lun_data(stmf_lun_map_t * sm)2877836SJohn.Forte@Sun.COM stmf_session_prepare_report_lun_data(stmf_lun_map_t *sm)
2887836SJohn.Forte@Sun.COM {
2897836SJohn.Forte@Sun.COM 	stmf_xfer_data_t *xd;
2907836SJohn.Forte@Sun.COM 	uint16_t nluns, ent;
2917836SJohn.Forte@Sun.COM 	uint32_t alloc_size, data_size;
2927836SJohn.Forte@Sun.COM 	int i;
2937836SJohn.Forte@Sun.COM 
2947836SJohn.Forte@Sun.COM 	nluns = sm->lm_nluns;
2957836SJohn.Forte@Sun.COM 
2967836SJohn.Forte@Sun.COM 	data_size = 8 + (((uint32_t)nluns) << 3);
2977836SJohn.Forte@Sun.COM 	if (nluns == 0) {
2987836SJohn.Forte@Sun.COM 		data_size += 8;
2997836SJohn.Forte@Sun.COM 	}
3007836SJohn.Forte@Sun.COM 	alloc_size = data_size + sizeof (stmf_xfer_data_t) - 4;
3017836SJohn.Forte@Sun.COM 
3027836SJohn.Forte@Sun.COM 	xd = (stmf_xfer_data_t *)kmem_zalloc(alloc_size, KM_NOSLEEP);
3037836SJohn.Forte@Sun.COM 
3047836SJohn.Forte@Sun.COM 	if (xd == NULL)
3057836SJohn.Forte@Sun.COM 		return (NULL);
3067836SJohn.Forte@Sun.COM 
3077836SJohn.Forte@Sun.COM 	xd->alloc_size = alloc_size;
3087836SJohn.Forte@Sun.COM 	xd->size_left = data_size;
3097836SJohn.Forte@Sun.COM 
3107836SJohn.Forte@Sun.COM 	*((uint32_t *)xd->buf) = BE_32(data_size - 8);
3117836SJohn.Forte@Sun.COM 	if (nluns == 0) {
3127836SJohn.Forte@Sun.COM 		return (xd);
3137836SJohn.Forte@Sun.COM 	}
3147836SJohn.Forte@Sun.COM 
3157836SJohn.Forte@Sun.COM 	ent = 0;
3167836SJohn.Forte@Sun.COM 
3177836SJohn.Forte@Sun.COM 	for (i = 0; ((i < sm->lm_nentries) && (ent < nluns)); i++) {
3187836SJohn.Forte@Sun.COM 		if (sm->lm_plus[i] == NULL)
3197836SJohn.Forte@Sun.COM 			continue;
3207836SJohn.Forte@Sun.COM 		/* Fill in the entry */
3217836SJohn.Forte@Sun.COM 		xd->buf[8 + (ent << 3) + 1] = (uchar_t)i;
3227836SJohn.Forte@Sun.COM 		xd->buf[8 + (ent << 3) + 0] = ((uchar_t)(i >> 8));
3237836SJohn.Forte@Sun.COM 		ent++;
3247836SJohn.Forte@Sun.COM 	}
3257836SJohn.Forte@Sun.COM 
3267836SJohn.Forte@Sun.COM 	ASSERT(ent == nluns);
3277836SJohn.Forte@Sun.COM 
3287836SJohn.Forte@Sun.COM 	return (xd);
3297836SJohn.Forte@Sun.COM }
3307836SJohn.Forte@Sun.COM 
3317836SJohn.Forte@Sun.COM /*
3327836SJohn.Forte@Sun.COM  * Add a lu to active sessions based on LUN inventory.
3337836SJohn.Forte@Sun.COM  * Only invoked when the lu is onlined
3347836SJohn.Forte@Sun.COM  */
3357836SJohn.Forte@Sun.COM void
stmf_add_lu_to_active_sessions(stmf_lu_t * lu)3367836SJohn.Forte@Sun.COM stmf_add_lu_to_active_sessions(stmf_lu_t *lu)
3377836SJohn.Forte@Sun.COM {
3387836SJohn.Forte@Sun.COM 	stmf_id_data_t *luid;
3397836SJohn.Forte@Sun.COM 	stmf_view_entry_t	*ve;
3407836SJohn.Forte@Sun.COM 	stmf_i_lu_t *ilu;
3417836SJohn.Forte@Sun.COM 
3427836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
3437836SJohn.Forte@Sun.COM 	ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
3447836SJohn.Forte@Sun.COM 	ASSERT(ilu->ilu_state == STMF_STATE_ONLINE);
3457836SJohn.Forte@Sun.COM 
3467836SJohn.Forte@Sun.COM 	luid = ((stmf_i_lu_t *)lu->lu_stmf_private)->ilu_luid;
3477836SJohn.Forte@Sun.COM 
3487836SJohn.Forte@Sun.COM 	if (!luid) {
3497836SJohn.Forte@Sun.COM 		/* we did not configure view for this lun, so just return */
3507836SJohn.Forte@Sun.COM 		return;
3517836SJohn.Forte@Sun.COM 	}
3527836SJohn.Forte@Sun.COM 
3537836SJohn.Forte@Sun.COM 	for (ve = (stmf_view_entry_t *)luid->id_impl_specific;
3547836SJohn.Forte@Sun.COM 	    ve; ve = ve->ve_next) {
3557836SJohn.Forte@Sun.COM 		stmf_update_sessions_per_ve(ve, lu, 1);
3567836SJohn.Forte@Sun.COM 	}
3577836SJohn.Forte@Sun.COM }
3587836SJohn.Forte@Sun.COM /*
3597836SJohn.Forte@Sun.COM  * Unmap a lun from all sessions
3607836SJohn.Forte@Sun.COM  */
3617836SJohn.Forte@Sun.COM void
stmf_session_lu_unmapall(stmf_lu_t * lu)3627836SJohn.Forte@Sun.COM stmf_session_lu_unmapall(stmf_lu_t *lu)
3637836SJohn.Forte@Sun.COM {
3647836SJohn.Forte@Sun.COM 	stmf_i_lu_t *ilu;
3657836SJohn.Forte@Sun.COM 	stmf_id_data_t *luid;
3667836SJohn.Forte@Sun.COM 	stmf_view_entry_t *ve;
3677836SJohn.Forte@Sun.COM 
3687836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
3697836SJohn.Forte@Sun.COM 
3707836SJohn.Forte@Sun.COM 	ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
3717836SJohn.Forte@Sun.COM 
3727836SJohn.Forte@Sun.COM 	if (ilu->ilu_ref_cnt == 0)
3737836SJohn.Forte@Sun.COM 		return;
3747836SJohn.Forte@Sun.COM 
3757836SJohn.Forte@Sun.COM 	luid = ((stmf_i_lu_t *)lu->lu_stmf_private)->ilu_luid;
3767836SJohn.Forte@Sun.COM 	if (!luid) {
3777836SJohn.Forte@Sun.COM 		/*
3787836SJohn.Forte@Sun.COM 		 * we did not configure view for this lun, this should be
3797836SJohn.Forte@Sun.COM 		 * an error
3807836SJohn.Forte@Sun.COM 		 */
3817836SJohn.Forte@Sun.COM 		return;
3827836SJohn.Forte@Sun.COM 	}
3837836SJohn.Forte@Sun.COM 
3847836SJohn.Forte@Sun.COM 	for (ve = (stmf_view_entry_t *)luid->id_impl_specific;
3857836SJohn.Forte@Sun.COM 	    ve; ve = ve->ve_next) {
3867836SJohn.Forte@Sun.COM 		stmf_update_sessions_per_ve(ve, lu, 0);
3877836SJohn.Forte@Sun.COM 		if (ilu->ilu_ref_cnt == 0)
3887836SJohn.Forte@Sun.COM 			break;
3897836SJohn.Forte@Sun.COM 	}
3907836SJohn.Forte@Sun.COM }
3917836SJohn.Forte@Sun.COM /*
3927836SJohn.Forte@Sun.COM  * add lu to a session, stmf_lock is already held
3937836SJohn.Forte@Sun.COM  */
3947836SJohn.Forte@Sun.COM stmf_status_t
stmf_add_lu_to_session(stmf_i_local_port_t * ilport,stmf_i_scsi_session_t * iss,stmf_lu_t * lu,uint8_t * lu_nbr)3957836SJohn.Forte@Sun.COM stmf_add_lu_to_session(stmf_i_local_port_t *ilport,
3967836SJohn.Forte@Sun.COM 		stmf_i_scsi_session_t	*iss,
3977836SJohn.Forte@Sun.COM 		stmf_lu_t *lu,
3987836SJohn.Forte@Sun.COM 		uint8_t *lu_nbr)
3997836SJohn.Forte@Sun.COM {
4007836SJohn.Forte@Sun.COM 	stmf_lun_map_t *sm = iss->iss_sm;
4017836SJohn.Forte@Sun.COM 	stmf_status_t ret;
4027836SJohn.Forte@Sun.COM 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
4037836SJohn.Forte@Sun.COM 	stmf_lun_map_ent_t *lun_map_ent;
4047836SJohn.Forte@Sun.COM 	uint32_t new_flags = 0;
4057836SJohn.Forte@Sun.COM 	uint16_t luNbr =
4067836SJohn.Forte@Sun.COM 	    ((uint16_t)lu_nbr[1] | (((uint16_t)(lu_nbr[0] & 0x3F)) << 8));
4077836SJohn.Forte@Sun.COM 
4087836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
4097836SJohn.Forte@Sun.COM 	ASSERT(!stmf_get_ent_from_map(sm, luNbr));
4107836SJohn.Forte@Sun.COM 
4117836SJohn.Forte@Sun.COM 	if ((sm->lm_nluns == 0) &&
4127836SJohn.Forte@Sun.COM 	    ((iss->iss_flags & ISS_BEING_CREATED) == 0)) {
4137836SJohn.Forte@Sun.COM 		new_flags = ISS_GOT_INITIAL_LUNS;
4147836SJohn.Forte@Sun.COM 		atomic_or_32(&ilport->ilport_flags, ILPORT_SS_GOT_INITIAL_LUNS);
4157836SJohn.Forte@Sun.COM 		stmf_state.stmf_process_initial_luns = 1;
4167836SJohn.Forte@Sun.COM 	}
4177836SJohn.Forte@Sun.COM 
4187836SJohn.Forte@Sun.COM 	lun_map_ent = (stmf_lun_map_ent_t *)
4197836SJohn.Forte@Sun.COM 	    kmem_zalloc(sizeof (stmf_lun_map_ent_t), KM_SLEEP);
4207836SJohn.Forte@Sun.COM 	lun_map_ent->ent_lu = lu;
4217836SJohn.Forte@Sun.COM 	ret = stmf_add_ent_to_map(sm, (void *)lun_map_ent, lu_nbr);
4227836SJohn.Forte@Sun.COM 	ASSERT(ret == STMF_SUCCESS);
4237836SJohn.Forte@Sun.COM 	atomic_add_32(&ilu->ilu_ref_cnt, 1);
42410725SJohn.Forte@Sun.COM 	/*
42510725SJohn.Forte@Sun.COM 	 * do not set lun inventory flag for standby port
42610725SJohn.Forte@Sun.COM 	 * as this would be handled from peer
42710725SJohn.Forte@Sun.COM 	 */
42810725SJohn.Forte@Sun.COM 	if (ilport->ilport_standby == 0) {
42910725SJohn.Forte@Sun.COM 		new_flags |= ISS_LUN_INVENTORY_CHANGED;
43010725SJohn.Forte@Sun.COM 	}
4317836SJohn.Forte@Sun.COM 	atomic_or_32(&iss->iss_flags, new_flags);
4327836SJohn.Forte@Sun.COM 	return (STMF_SUCCESS);
4337836SJohn.Forte@Sun.COM }
4347836SJohn.Forte@Sun.COM 
4357836SJohn.Forte@Sun.COM /*
4367836SJohn.Forte@Sun.COM  * remvoe lu from a session, stmf_lock is already held
4377836SJohn.Forte@Sun.COM  */
4387836SJohn.Forte@Sun.COM /* ARGSUSED */
4397836SJohn.Forte@Sun.COM stmf_status_t
stmf_remove_lu_from_session(stmf_i_local_port_t * ilport,stmf_i_scsi_session_t * iss,stmf_lu_t * lu,uint8_t * lu_nbr)4407836SJohn.Forte@Sun.COM stmf_remove_lu_from_session(stmf_i_local_port_t *ilport,
4417836SJohn.Forte@Sun.COM 		stmf_i_scsi_session_t *iss,
4427836SJohn.Forte@Sun.COM 		stmf_lu_t *lu,
4437836SJohn.Forte@Sun.COM 		uint8_t *lu_nbr)
4447836SJohn.Forte@Sun.COM {
4457836SJohn.Forte@Sun.COM 	stmf_status_t ret;
4467836SJohn.Forte@Sun.COM 	stmf_i_lu_t *ilu;
4477836SJohn.Forte@Sun.COM 	stmf_lun_map_t *sm = iss->iss_sm;
4487836SJohn.Forte@Sun.COM 	stmf_lun_map_ent_t *lun_map_ent;
4497836SJohn.Forte@Sun.COM 	uint16_t luNbr =
4507836SJohn.Forte@Sun.COM 	    ((uint16_t)lu_nbr[1] | (((uint16_t)(lu_nbr[0] & 0x3F)) << 8));
4517836SJohn.Forte@Sun.COM 
4527836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
4537836SJohn.Forte@Sun.COM 	lun_map_ent = stmf_get_ent_from_map(sm, luNbr);
4547836SJohn.Forte@Sun.COM 	ASSERT(lun_map_ent && lun_map_ent->ent_lu == lu);
4557836SJohn.Forte@Sun.COM 
4567836SJohn.Forte@Sun.COM 	ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
4577836SJohn.Forte@Sun.COM 
4587836SJohn.Forte@Sun.COM 	ret = stmf_remove_ent_from_map(sm, lu_nbr);
4597836SJohn.Forte@Sun.COM 	ASSERT(ret == STMF_SUCCESS);
4607836SJohn.Forte@Sun.COM 	atomic_add_32(&ilu->ilu_ref_cnt, -1);
4617836SJohn.Forte@Sun.COM 	iss->iss_flags |= ISS_LUN_INVENTORY_CHANGED;
4627836SJohn.Forte@Sun.COM 	if (lun_map_ent->ent_itl_datap) {
4637836SJohn.Forte@Sun.COM 		stmf_do_itl_dereg(lu, lun_map_ent->ent_itl_datap,
4649884STim.Szeto@Sun.COM 		    STMF_ITL_REASON_USER_REQUEST);
4657836SJohn.Forte@Sun.COM 	}
4667836SJohn.Forte@Sun.COM 	kmem_free((void *)lun_map_ent, sizeof (stmf_lun_map_ent_t));
4677836SJohn.Forte@Sun.COM 	return (STMF_SUCCESS);
4687836SJohn.Forte@Sun.COM }
4697836SJohn.Forte@Sun.COM 
4707836SJohn.Forte@Sun.COM /*
4717836SJohn.Forte@Sun.COM  * add or remove lu from all related sessions based on view entry,
4727836SJohn.Forte@Sun.COM  * action is 0 for delete, 1 for add
4737836SJohn.Forte@Sun.COM  */
4747836SJohn.Forte@Sun.COM void
stmf_update_sessions_per_ve(stmf_view_entry_t * ve,stmf_lu_t * lu,int action)4757836SJohn.Forte@Sun.COM stmf_update_sessions_per_ve(stmf_view_entry_t *ve,
4767836SJohn.Forte@Sun.COM 		stmf_lu_t *lu, int action)
4777836SJohn.Forte@Sun.COM {
4787836SJohn.Forte@Sun.COM 	stmf_i_lu_t *ilu_tmp;
4797836SJohn.Forte@Sun.COM 	stmf_lu_t *lu_to_add;
4807836SJohn.Forte@Sun.COM 	stmf_i_local_port_t *ilport;
4817836SJohn.Forte@Sun.COM 	stmf_i_scsi_session_t *iss;
4827836SJohn.Forte@Sun.COM 	stmf_id_list_t	*hostlist;
4837836SJohn.Forte@Sun.COM 	stmf_id_list_t	*targetlist;
4847836SJohn.Forte@Sun.COM 	int all_hg = 0, all_tg = 0;
4857836SJohn.Forte@Sun.COM 
4867836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
4877836SJohn.Forte@Sun.COM 
4887836SJohn.Forte@Sun.COM 	if (!lu) {
4897836SJohn.Forte@Sun.COM 		ilu_tmp = (stmf_i_lu_t *)ve->ve_luid->id_pt_to_object;
4907836SJohn.Forte@Sun.COM 		if (!ilu_tmp)
4917836SJohn.Forte@Sun.COM 			return;
4927836SJohn.Forte@Sun.COM 		lu_to_add = ilu_tmp->ilu_lu;
4937836SJohn.Forte@Sun.COM 	} else {
4947836SJohn.Forte@Sun.COM 		lu_to_add = lu;
4957836SJohn.Forte@Sun.COM 		ilu_tmp = (stmf_i_lu_t *)lu->lu_stmf_private;
4967836SJohn.Forte@Sun.COM 	}
4977836SJohn.Forte@Sun.COM 
4987836SJohn.Forte@Sun.COM 	if (ve->ve_hg->id_data[0] == '*')
4997836SJohn.Forte@Sun.COM 		all_hg = 1;
5007836SJohn.Forte@Sun.COM 	if (ve->ve_tg->id_data[0] == '*')
5017836SJohn.Forte@Sun.COM 		all_tg = 1;
5027836SJohn.Forte@Sun.COM 	hostlist = (stmf_id_list_t *)ve->ve_hg->id_impl_specific;
5037836SJohn.Forte@Sun.COM 	targetlist = (stmf_id_list_t *)ve->ve_tg->id_impl_specific;
5047836SJohn.Forte@Sun.COM 
5057836SJohn.Forte@Sun.COM 	if ((!all_hg && !hostlist->idl_head) ||
5067836SJohn.Forte@Sun.COM 	    (!all_tg && !targetlist->idl_head))
5077836SJohn.Forte@Sun.COM 		/* No sessions to be updated */
5087836SJohn.Forte@Sun.COM 		return;
5097836SJohn.Forte@Sun.COM 
5107836SJohn.Forte@Sun.COM 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
5117836SJohn.Forte@Sun.COM 	    ilport = ilport->ilport_next) {
5127836SJohn.Forte@Sun.COM 		if (!all_tg && ilport->ilport_tg != ve->ve_tg)
5137836SJohn.Forte@Sun.COM 			continue;
5147836SJohn.Forte@Sun.COM 		/* This ilport belongs to the target group */
5157836SJohn.Forte@Sun.COM 		rw_enter(&ilport->ilport_lock, RW_WRITER);
5167836SJohn.Forte@Sun.COM 		for (iss = ilport->ilport_ss_list; iss != NULL;
5177836SJohn.Forte@Sun.COM 		    iss = iss->iss_next) {
5187836SJohn.Forte@Sun.COM 			if (!all_hg && iss->iss_hg != ve->ve_hg)
5197836SJohn.Forte@Sun.COM 				continue;
5207836SJohn.Forte@Sun.COM 			/* This host belongs to the host group */
5217836SJohn.Forte@Sun.COM 			if (action == 0) { /* to remove */
5227836SJohn.Forte@Sun.COM 				(void) stmf_remove_lu_from_session(ilport, iss,
5237836SJohn.Forte@Sun.COM 				    lu_to_add, ve->ve_lun);
5247836SJohn.Forte@Sun.COM 				if (ilu_tmp->ilu_ref_cnt == 0) {
5257836SJohn.Forte@Sun.COM 					rw_exit(&ilport->ilport_lock);
5267836SJohn.Forte@Sun.COM 					return;
5277836SJohn.Forte@Sun.COM 				}
5287836SJohn.Forte@Sun.COM 			} else {
5297836SJohn.Forte@Sun.COM 				(void) stmf_add_lu_to_session(ilport, iss,
5307836SJohn.Forte@Sun.COM 				    lu_to_add, ve->ve_lun);
5317836SJohn.Forte@Sun.COM 			}
5327836SJohn.Forte@Sun.COM 		}
5337836SJohn.Forte@Sun.COM 		rw_exit(&ilport->ilport_lock);
5347836SJohn.Forte@Sun.COM 	}
5357836SJohn.Forte@Sun.COM }
5367836SJohn.Forte@Sun.COM 
5377836SJohn.Forte@Sun.COM /*
5387836SJohn.Forte@Sun.COM  * add luns in view entry map to a session,
5397836SJohn.Forte@Sun.COM  * and stmf_lock is already held
5407836SJohn.Forte@Sun.COM  */
5417836SJohn.Forte@Sun.COM void
stmf_add_lus_to_session_per_vemap(stmf_i_local_port_t * ilport,stmf_i_scsi_session_t * iss,stmf_lun_map_t * vemap)5427836SJohn.Forte@Sun.COM stmf_add_lus_to_session_per_vemap(stmf_i_local_port_t *ilport,
5437836SJohn.Forte@Sun.COM 		stmf_i_scsi_session_t *iss,
5447836SJohn.Forte@Sun.COM 		stmf_lun_map_t *vemap)
5457836SJohn.Forte@Sun.COM {
5467836SJohn.Forte@Sun.COM 	stmf_lu_t *lu;
5477836SJohn.Forte@Sun.COM 	stmf_i_lu_t *ilu;
5487836SJohn.Forte@Sun.COM 	stmf_view_entry_t *ve;
5497836SJohn.Forte@Sun.COM 	uint32_t	i;
5507836SJohn.Forte@Sun.COM 
5517836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
5527836SJohn.Forte@Sun.COM 
5537836SJohn.Forte@Sun.COM 	for (i = 0; i < vemap->lm_nentries; i++) {
5547836SJohn.Forte@Sun.COM 		ve = (stmf_view_entry_t *)vemap->lm_plus[i];
5557836SJohn.Forte@Sun.COM 		if (!ve)
5567836SJohn.Forte@Sun.COM 			continue;
5577836SJohn.Forte@Sun.COM 		ilu = (stmf_i_lu_t *)ve->ve_luid->id_pt_to_object;
5587836SJohn.Forte@Sun.COM 		if (ilu && ilu->ilu_state == STMF_STATE_ONLINE) {
5597836SJohn.Forte@Sun.COM 			lu = ilu->ilu_lu;
5607836SJohn.Forte@Sun.COM 			(void) stmf_add_lu_to_session(ilport, iss, lu,
5617836SJohn.Forte@Sun.COM 			    ve->ve_lun);
5627836SJohn.Forte@Sun.COM 		}
5637836SJohn.Forte@Sun.COM 	}
5647836SJohn.Forte@Sun.COM }
5657836SJohn.Forte@Sun.COM /* remove luns in view entry map from a session */
5667836SJohn.Forte@Sun.COM void
stmf_remove_lus_from_session_per_vemap(stmf_i_local_port_t * ilport,stmf_i_scsi_session_t * iss,stmf_lun_map_t * vemap)5677836SJohn.Forte@Sun.COM stmf_remove_lus_from_session_per_vemap(stmf_i_local_port_t *ilport,
5687836SJohn.Forte@Sun.COM 		stmf_i_scsi_session_t *iss,
5697836SJohn.Forte@Sun.COM 		stmf_lun_map_t *vemap)
5707836SJohn.Forte@Sun.COM {
5717836SJohn.Forte@Sun.COM 	stmf_lu_t *lu;
5727836SJohn.Forte@Sun.COM 	stmf_i_lu_t *ilu;
5737836SJohn.Forte@Sun.COM 	stmf_view_entry_t *ve;
5747836SJohn.Forte@Sun.COM 	uint32_t i;
5757836SJohn.Forte@Sun.COM 
5767836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
5777836SJohn.Forte@Sun.COM 
5787836SJohn.Forte@Sun.COM 	for (i = 0; i < vemap->lm_nentries; i++) {
5797836SJohn.Forte@Sun.COM 		ve = (stmf_view_entry_t *)vemap->lm_plus[i];
5807836SJohn.Forte@Sun.COM 		if (!ve)
5817836SJohn.Forte@Sun.COM 			continue;
5827836SJohn.Forte@Sun.COM 		ilu = (stmf_i_lu_t *)ve->ve_luid->id_pt_to_object;
5837836SJohn.Forte@Sun.COM 		if (ilu && ilu->ilu_state == STMF_STATE_ONLINE) {
5847836SJohn.Forte@Sun.COM 			lu = ilu->ilu_lu;
5857836SJohn.Forte@Sun.COM 			(void) stmf_remove_lu_from_session(ilport, iss, lu,
5867836SJohn.Forte@Sun.COM 			    ve->ve_lun);
5877836SJohn.Forte@Sun.COM 		}
5887836SJohn.Forte@Sun.COM 	}
5897836SJohn.Forte@Sun.COM }
5907836SJohn.Forte@Sun.COM 
5917836SJohn.Forte@Sun.COM stmf_id_data_t *
stmf_alloc_id(uint16_t id_size,uint16_t type,uint8_t * id_data,uint32_t additional_size)5927836SJohn.Forte@Sun.COM stmf_alloc_id(uint16_t id_size, uint16_t type, uint8_t *id_data,
5937836SJohn.Forte@Sun.COM 			uint32_t additional_size)
5947836SJohn.Forte@Sun.COM {
5957836SJohn.Forte@Sun.COM 	stmf_id_data_t *id;
5967836SJohn.Forte@Sun.COM 	int struct_size, total_size, real_id_size;
5977836SJohn.Forte@Sun.COM 
5987836SJohn.Forte@Sun.COM 	real_id_size = ((uint32_t)id_size + 7) & (~7);
5997836SJohn.Forte@Sun.COM 	struct_size = (sizeof (*id) + 7) & (~7);
6007836SJohn.Forte@Sun.COM 	total_size = ((additional_size + 7) & (~7)) + struct_size +
6017836SJohn.Forte@Sun.COM 	    real_id_size;
6027836SJohn.Forte@Sun.COM 	id = (stmf_id_data_t *)kmem_zalloc(total_size, KM_SLEEP);
6037836SJohn.Forte@Sun.COM 	id->id_type = type;
6047836SJohn.Forte@Sun.COM 	id->id_data_size = id_size;
6057836SJohn.Forte@Sun.COM 	id->id_data = ((uint8_t *)id) + struct_size;
6067836SJohn.Forte@Sun.COM 	id->id_total_alloc_size = total_size;
6077836SJohn.Forte@Sun.COM 	if (additional_size) {
6087836SJohn.Forte@Sun.COM 		id->id_impl_specific = ((uint8_t *)id) + struct_size +
6097836SJohn.Forte@Sun.COM 		    real_id_size;
6107836SJohn.Forte@Sun.COM 	}
6117836SJohn.Forte@Sun.COM 	bcopy(id_data, id->id_data, id_size);
6127836SJohn.Forte@Sun.COM 
6137836SJohn.Forte@Sun.COM 	return (id);
6147836SJohn.Forte@Sun.COM }
6157836SJohn.Forte@Sun.COM 
6167836SJohn.Forte@Sun.COM void
stmf_free_id(stmf_id_data_t * id)6177836SJohn.Forte@Sun.COM stmf_free_id(stmf_id_data_t *id)
6187836SJohn.Forte@Sun.COM {
6197836SJohn.Forte@Sun.COM 	kmem_free(id, id->id_total_alloc_size);
6207836SJohn.Forte@Sun.COM }
6217836SJohn.Forte@Sun.COM 
6227836SJohn.Forte@Sun.COM 
6237836SJohn.Forte@Sun.COM stmf_id_data_t *
stmf_lookup_id(stmf_id_list_t * idlist,uint16_t id_size,uint8_t * data)6247836SJohn.Forte@Sun.COM stmf_lookup_id(stmf_id_list_t *idlist, uint16_t id_size, uint8_t *data)
6257836SJohn.Forte@Sun.COM {
6267836SJohn.Forte@Sun.COM 	stmf_id_data_t *id;
6277836SJohn.Forte@Sun.COM 
6287836SJohn.Forte@Sun.COM 	for (id = idlist->idl_head; id != NULL; id = id->id_next) {
6297836SJohn.Forte@Sun.COM 		if ((id->id_data_size == id_size) &&
6307836SJohn.Forte@Sun.COM 		    (bcmp(id->id_data, data, id_size) == 0)) {
6317836SJohn.Forte@Sun.COM 			return (id);
6327836SJohn.Forte@Sun.COM 		}
6337836SJohn.Forte@Sun.COM 	}
6347836SJohn.Forte@Sun.COM 
6357836SJohn.Forte@Sun.COM 	return (NULL);
6367836SJohn.Forte@Sun.COM }
6377836SJohn.Forte@Sun.COM /* Return the target group which a target belong to */
6387836SJohn.Forte@Sun.COM stmf_id_data_t *
stmf_lookup_group_for_target(uint8_t * ident,uint16_t ident_size)6397836SJohn.Forte@Sun.COM stmf_lookup_group_for_target(uint8_t *ident, uint16_t ident_size)
6407836SJohn.Forte@Sun.COM {
6417836SJohn.Forte@Sun.COM 	stmf_id_data_t *tgid;
6427836SJohn.Forte@Sun.COM 	stmf_id_data_t *target;
6437836SJohn.Forte@Sun.COM 
6447836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
6457836SJohn.Forte@Sun.COM 
6467836SJohn.Forte@Sun.COM 	for (tgid = stmf_state.stmf_tg_list.idl_head; tgid;
6477836SJohn.Forte@Sun.COM 	    tgid = tgid->id_next) {
6487836SJohn.Forte@Sun.COM 		target = stmf_lookup_id(
6497836SJohn.Forte@Sun.COM 		    (stmf_id_list_t *)tgid->id_impl_specific,
6507836SJohn.Forte@Sun.COM 		    ident_size, ident);
6517836SJohn.Forte@Sun.COM 		if (target)
6527836SJohn.Forte@Sun.COM 			return (tgid);
6537836SJohn.Forte@Sun.COM 	}
6547836SJohn.Forte@Sun.COM 	return (NULL);
6557836SJohn.Forte@Sun.COM }
6567836SJohn.Forte@Sun.COM /* Return the host group which a host belong to */
6577836SJohn.Forte@Sun.COM stmf_id_data_t *
stmf_lookup_group_for_host(uint8_t * ident,uint16_t ident_size)6587836SJohn.Forte@Sun.COM stmf_lookup_group_for_host(uint8_t *ident, uint16_t ident_size)
6597836SJohn.Forte@Sun.COM {
6607836SJohn.Forte@Sun.COM 	stmf_id_data_t *hgid;
6617836SJohn.Forte@Sun.COM 	stmf_id_data_t *host;
6627836SJohn.Forte@Sun.COM 
6637836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
6647836SJohn.Forte@Sun.COM 
6657836SJohn.Forte@Sun.COM 	for (hgid = stmf_state.stmf_hg_list.idl_head; hgid;
6667836SJohn.Forte@Sun.COM 	    hgid = hgid->id_next) {
6677836SJohn.Forte@Sun.COM 		host = stmf_lookup_id(
6687836SJohn.Forte@Sun.COM 		    (stmf_id_list_t *)hgid->id_impl_specific,
6697836SJohn.Forte@Sun.COM 		    ident_size, ident);
6707836SJohn.Forte@Sun.COM 		if (host)
6717836SJohn.Forte@Sun.COM 			return (hgid);
6727836SJohn.Forte@Sun.COM 	}
6737836SJohn.Forte@Sun.COM 	return (NULL);
6747836SJohn.Forte@Sun.COM }
6757836SJohn.Forte@Sun.COM 
6767836SJohn.Forte@Sun.COM void
stmf_append_id(stmf_id_list_t * idlist,stmf_id_data_t * id)6777836SJohn.Forte@Sun.COM stmf_append_id(stmf_id_list_t *idlist, stmf_id_data_t *id)
6787836SJohn.Forte@Sun.COM {
6797836SJohn.Forte@Sun.COM 	id->id_next = NULL;
6807836SJohn.Forte@Sun.COM 
6817836SJohn.Forte@Sun.COM 	if ((id->id_prev = idlist->idl_tail) == NULL) {
6827836SJohn.Forte@Sun.COM 		idlist->idl_head = idlist->idl_tail = id;
6837836SJohn.Forte@Sun.COM 	} else {
6847836SJohn.Forte@Sun.COM 		idlist->idl_tail->id_next = id;
6857836SJohn.Forte@Sun.COM 		idlist->idl_tail = id;
6867836SJohn.Forte@Sun.COM 	}
6877836SJohn.Forte@Sun.COM 	atomic_add_32(&idlist->id_count, 1);
6887836SJohn.Forte@Sun.COM }
6897836SJohn.Forte@Sun.COM 
6907836SJohn.Forte@Sun.COM void
stmf_remove_id(stmf_id_list_t * idlist,stmf_id_data_t * id)6917836SJohn.Forte@Sun.COM stmf_remove_id(stmf_id_list_t *idlist, stmf_id_data_t *id)
6927836SJohn.Forte@Sun.COM {
6937836SJohn.Forte@Sun.COM 	if (id->id_next) {
6947836SJohn.Forte@Sun.COM 		id->id_next->id_prev = id->id_prev;
6957836SJohn.Forte@Sun.COM 	} else {
6967836SJohn.Forte@Sun.COM 		idlist->idl_tail = id->id_prev;
6977836SJohn.Forte@Sun.COM 	}
6987836SJohn.Forte@Sun.COM 
6997836SJohn.Forte@Sun.COM 	if (id->id_prev) {
7007836SJohn.Forte@Sun.COM 		id->id_prev->id_next = id->id_next;
7017836SJohn.Forte@Sun.COM 	} else {
7027836SJohn.Forte@Sun.COM 		idlist->idl_head = id->id_next;
7037836SJohn.Forte@Sun.COM 	}
7047836SJohn.Forte@Sun.COM 	atomic_add_32(&idlist->id_count, -1);
7057836SJohn.Forte@Sun.COM }
7067836SJohn.Forte@Sun.COM 
7077836SJohn.Forte@Sun.COM 
7087836SJohn.Forte@Sun.COM /*
7097836SJohn.Forte@Sun.COM  * The refcnts of objects in a view entry are updated when then entry
7107836SJohn.Forte@Sun.COM  * is successfully added. ve_map is just another representation of the
7117836SJohn.Forte@Sun.COM  * view enrtries in a LU. Duplicating or merging a ve map does not
7127836SJohn.Forte@Sun.COM  * affect any refcnts.
7137836SJohn.Forte@Sun.COM  */
7147836SJohn.Forte@Sun.COM stmf_lun_map_t *
stmf_duplicate_ve_map(stmf_lun_map_t * src)7157836SJohn.Forte@Sun.COM stmf_duplicate_ve_map(stmf_lun_map_t *src)
7167836SJohn.Forte@Sun.COM {
7177836SJohn.Forte@Sun.COM 	stmf_lun_map_t *dst;
7187836SJohn.Forte@Sun.COM 	int i;
7197836SJohn.Forte@Sun.COM 
7207836SJohn.Forte@Sun.COM 	dst = (stmf_lun_map_t *)kmem_zalloc(sizeof (*dst), KM_SLEEP);
7217836SJohn.Forte@Sun.COM 
7227836SJohn.Forte@Sun.COM 	if (src == NULL)
7237836SJohn.Forte@Sun.COM 		return (dst);
7247836SJohn.Forte@Sun.COM 
7257836SJohn.Forte@Sun.COM 	if (src->lm_nentries) {
7267836SJohn.Forte@Sun.COM 		dst->lm_plus = kmem_zalloc(dst->lm_nentries *
7277836SJohn.Forte@Sun.COM 		    sizeof (void *), KM_SLEEP);
7287836SJohn.Forte@Sun.COM 		for (i = 0; i < dst->lm_nentries; i++) {
7297836SJohn.Forte@Sun.COM 			dst->lm_plus[i] = src->lm_plus[i];
7307836SJohn.Forte@Sun.COM 		}
7317836SJohn.Forte@Sun.COM 	}
7327836SJohn.Forte@Sun.COM 
7337836SJohn.Forte@Sun.COM 	return (dst);
7347836SJohn.Forte@Sun.COM }
7357836SJohn.Forte@Sun.COM 
7367836SJohn.Forte@Sun.COM void
stmf_destroy_ve_map(stmf_lun_map_t * dst)7377836SJohn.Forte@Sun.COM stmf_destroy_ve_map(stmf_lun_map_t *dst)
7387836SJohn.Forte@Sun.COM {
7397836SJohn.Forte@Sun.COM 	if (dst->lm_nentries) {
7407836SJohn.Forte@Sun.COM 		kmem_free(dst->lm_plus, dst->lm_nentries * sizeof (void *));
7417836SJohn.Forte@Sun.COM 	}
7427836SJohn.Forte@Sun.COM 	kmem_free(dst, sizeof (*dst));
7437836SJohn.Forte@Sun.COM }
7447836SJohn.Forte@Sun.COM 
7457836SJohn.Forte@Sun.COM int
stmf_merge_ve_map(stmf_lun_map_t * src,stmf_lun_map_t * dst,stmf_lun_map_t ** pp_ret_map,stmf_merge_flags_t mf)7467836SJohn.Forte@Sun.COM stmf_merge_ve_map(stmf_lun_map_t *src, stmf_lun_map_t *dst,
7477836SJohn.Forte@Sun.COM 		stmf_lun_map_t **pp_ret_map, stmf_merge_flags_t mf)
7487836SJohn.Forte@Sun.COM {
7497836SJohn.Forte@Sun.COM 	int i;
7507836SJohn.Forte@Sun.COM 	int nentries;
7517836SJohn.Forte@Sun.COM 	int to_create_space = 0;
7527836SJohn.Forte@Sun.COM 
7537836SJohn.Forte@Sun.COM 	if (dst == NULL) {
7547836SJohn.Forte@Sun.COM 		*pp_ret_map = stmf_duplicate_ve_map(src);
7557836SJohn.Forte@Sun.COM 		return (1);
7567836SJohn.Forte@Sun.COM 	}
7577836SJohn.Forte@Sun.COM 
7587836SJohn.Forte@Sun.COM 	if (src == NULL || src->lm_nluns == 0) {
7597836SJohn.Forte@Sun.COM 		if (mf & MERGE_FLAG_RETURN_NEW_MAP)
7607836SJohn.Forte@Sun.COM 			*pp_ret_map = stmf_duplicate_ve_map(dst);
7617836SJohn.Forte@Sun.COM 		else
7627836SJohn.Forte@Sun.COM 			*pp_ret_map = dst;
7637836SJohn.Forte@Sun.COM 		return (1);
7647836SJohn.Forte@Sun.COM 	}
7657836SJohn.Forte@Sun.COM 
7667836SJohn.Forte@Sun.COM 	if (mf & MERGE_FLAG_RETURN_NEW_MAP) {
7677836SJohn.Forte@Sun.COM 		*pp_ret_map = stmf_duplicate_ve_map(NULL);
7687836SJohn.Forte@Sun.COM 		nentries = max(dst->lm_nentries, src->lm_nentries);
7697836SJohn.Forte@Sun.COM 		to_create_space = 1;
7707836SJohn.Forte@Sun.COM 	} else {
7717836SJohn.Forte@Sun.COM 		*pp_ret_map = dst;
7727836SJohn.Forte@Sun.COM 		/* If there is not enough space in dst map */
7737836SJohn.Forte@Sun.COM 		if (dst->lm_nentries < src->lm_nentries) {
7747836SJohn.Forte@Sun.COM 			nentries = src->lm_nentries;
7757836SJohn.Forte@Sun.COM 			to_create_space = 1;
7767836SJohn.Forte@Sun.COM 		}
7777836SJohn.Forte@Sun.COM 	}
7787836SJohn.Forte@Sun.COM 	if (to_create_space) {
7797836SJohn.Forte@Sun.COM 		void **p;
7807836SJohn.Forte@Sun.COM 		p = (void **)kmem_zalloc(nentries * sizeof (void *), KM_SLEEP);
7817836SJohn.Forte@Sun.COM 		if (dst->lm_nentries) {
7827836SJohn.Forte@Sun.COM 			bcopy(dst->lm_plus, p,
7837836SJohn.Forte@Sun.COM 			    dst->lm_nentries * sizeof (void *));
7847836SJohn.Forte@Sun.COM 		}
7857836SJohn.Forte@Sun.COM 		if (mf & (MERGE_FLAG_RETURN_NEW_MAP == 0))
7867836SJohn.Forte@Sun.COM 			kmem_free(dst->lm_plus,
7877836SJohn.Forte@Sun.COM 			    dst->lm_nentries * sizeof (void *));
7887836SJohn.Forte@Sun.COM 		(*pp_ret_map)->lm_plus = p;
7897836SJohn.Forte@Sun.COM 		(*pp_ret_map)->lm_nentries = nentries;
7907836SJohn.Forte@Sun.COM 	}
7917836SJohn.Forte@Sun.COM 
7927836SJohn.Forte@Sun.COM 	for (i = 0; i < src->lm_nentries; i++) {
7937836SJohn.Forte@Sun.COM 		if (src->lm_plus[i] == NULL)
7947836SJohn.Forte@Sun.COM 			continue;
7957836SJohn.Forte@Sun.COM 		if (dst->lm_plus[i] != NULL) {
7967836SJohn.Forte@Sun.COM 			if (mf & MERGE_FLAG_NO_DUPLICATE) {
7977836SJohn.Forte@Sun.COM 				if (mf & MERGE_FLAG_RETURN_NEW_MAP) {
7987836SJohn.Forte@Sun.COM 					stmf_destroy_ve_map(*pp_ret_map);
7997836SJohn.Forte@Sun.COM 					*pp_ret_map = NULL;
8007836SJohn.Forte@Sun.COM 				}
8017836SJohn.Forte@Sun.COM 				return (0);
8027836SJohn.Forte@Sun.COM 			}
8037836SJohn.Forte@Sun.COM 		} else {
8047836SJohn.Forte@Sun.COM 			dst->lm_plus[i] = src->lm_plus[i];
8057836SJohn.Forte@Sun.COM 			dst->lm_nluns++;
8067836SJohn.Forte@Sun.COM 		}
8077836SJohn.Forte@Sun.COM 	}
8087836SJohn.Forte@Sun.COM 
8097836SJohn.Forte@Sun.COM 	return (1);
8107836SJohn.Forte@Sun.COM }
8117836SJohn.Forte@Sun.COM 
8127836SJohn.Forte@Sun.COM /*
8137836SJohn.Forte@Sun.COM  * add host group, id_impl_specific point to a list of hosts,
8147836SJohn.Forte@Sun.COM  * on return, if error happened, err_detail may be assigned if
8157836SJohn.Forte@Sun.COM  * the pointer is not NULL
8167836SJohn.Forte@Sun.COM  */
8177836SJohn.Forte@Sun.COM stmf_status_t
stmf_add_hg(uint8_t * hg_name,uint16_t hg_name_size,int allow_special,uint32_t * err_detail)8187836SJohn.Forte@Sun.COM stmf_add_hg(uint8_t *hg_name, uint16_t hg_name_size,
8197836SJohn.Forte@Sun.COM 		int allow_special, uint32_t *err_detail)
8207836SJohn.Forte@Sun.COM {
8217836SJohn.Forte@Sun.COM 	stmf_id_data_t *id;
8227836SJohn.Forte@Sun.COM 
8237836SJohn.Forte@Sun.COM 	if (!allow_special) {
8247836SJohn.Forte@Sun.COM 		if (hg_name[0] == '*')
8257836SJohn.Forte@Sun.COM 			return (STMF_INVALID_ARG);
8267836SJohn.Forte@Sun.COM 	}
8277836SJohn.Forte@Sun.COM 
8287836SJohn.Forte@Sun.COM 	if (stmf_lookup_id(&stmf_state.stmf_hg_list,
8297836SJohn.Forte@Sun.COM 	    hg_name_size, (uint8_t *)hg_name)) {
8307836SJohn.Forte@Sun.COM 		if (err_detail)
8317836SJohn.Forte@Sun.COM 			*err_detail = STMF_IOCERR_HG_EXISTS;
8327836SJohn.Forte@Sun.COM 		return (STMF_ALREADY);
8337836SJohn.Forte@Sun.COM 	}
8347836SJohn.Forte@Sun.COM 	id = stmf_alloc_id(hg_name_size, STMF_ID_TYPE_HOST_GROUP,
8357836SJohn.Forte@Sun.COM 	    (uint8_t *)hg_name, sizeof (stmf_id_list_t));
8367836SJohn.Forte@Sun.COM 	stmf_append_id(&stmf_state.stmf_hg_list, id);
8377836SJohn.Forte@Sun.COM 
8387836SJohn.Forte@Sun.COM 	return (STMF_SUCCESS);
8397836SJohn.Forte@Sun.COM }
8407836SJohn.Forte@Sun.COM 
8417836SJohn.Forte@Sun.COM /* add target group */
8427836SJohn.Forte@Sun.COM stmf_status_t
stmf_add_tg(uint8_t * tg_name,uint16_t tg_name_size,int allow_special,uint32_t * err_detail)8437836SJohn.Forte@Sun.COM stmf_add_tg(uint8_t *tg_name, uint16_t tg_name_size,
8447836SJohn.Forte@Sun.COM 		int allow_special, uint32_t *err_detail)
8457836SJohn.Forte@Sun.COM {
8467836SJohn.Forte@Sun.COM 	stmf_id_data_t *id;
8477836SJohn.Forte@Sun.COM 
8487836SJohn.Forte@Sun.COM 	if (!allow_special) {
8497836SJohn.Forte@Sun.COM 		if (tg_name[0] == '*')
8507836SJohn.Forte@Sun.COM 			return (STMF_INVALID_ARG);
8517836SJohn.Forte@Sun.COM 	}
8527836SJohn.Forte@Sun.COM 
8537836SJohn.Forte@Sun.COM 
8547836SJohn.Forte@Sun.COM 	if (stmf_lookup_id(&stmf_state.stmf_tg_list, tg_name_size,
8557836SJohn.Forte@Sun.COM 	    (uint8_t *)tg_name)) {
8567836SJohn.Forte@Sun.COM 		if (err_detail)
8577836SJohn.Forte@Sun.COM 			*err_detail = STMF_IOCERR_TG_EXISTS;
8587836SJohn.Forte@Sun.COM 		return (STMF_ALREADY);
8597836SJohn.Forte@Sun.COM 	}
8607836SJohn.Forte@Sun.COM 	id = stmf_alloc_id(tg_name_size, STMF_ID_TYPE_TARGET_GROUP,
8617836SJohn.Forte@Sun.COM 	    (uint8_t *)tg_name, sizeof (stmf_id_list_t));
8627836SJohn.Forte@Sun.COM 	stmf_append_id(&stmf_state.stmf_tg_list, id);
8637836SJohn.Forte@Sun.COM 
8647836SJohn.Forte@Sun.COM 	return (STMF_SUCCESS);
8657836SJohn.Forte@Sun.COM }
8667836SJohn.Forte@Sun.COM 
8677836SJohn.Forte@Sun.COM /*
8687836SJohn.Forte@Sun.COM  * insert view entry into list for a luid, if ve->ve_id is 0xffffffff,
8697836SJohn.Forte@Sun.COM  * pick up a smallest available veid for it, and return the veid in ve->ve_id.
8707836SJohn.Forte@Sun.COM  * The view entries list is sorted based on veid.
8717836SJohn.Forte@Sun.COM  */
8727836SJohn.Forte@Sun.COM stmf_status_t
stmf_add_ve_to_luid(stmf_id_data_t * luid,stmf_view_entry_t * ve)8737836SJohn.Forte@Sun.COM stmf_add_ve_to_luid(stmf_id_data_t *luid, stmf_view_entry_t *ve)
8747836SJohn.Forte@Sun.COM {
8757836SJohn.Forte@Sun.COM 	stmf_view_entry_t *ve_tmp = NULL;
8767836SJohn.Forte@Sun.COM 	stmf_view_entry_t *ve_prev = NULL;
8777836SJohn.Forte@Sun.COM 
8787836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
8797836SJohn.Forte@Sun.COM 
8807836SJohn.Forte@Sun.COM 	ve_tmp = (stmf_view_entry_t *)luid->id_impl_specific;
8817836SJohn.Forte@Sun.COM 
8827836SJohn.Forte@Sun.COM 	if (ve->ve_id != 0xffffffff) {
8837836SJohn.Forte@Sun.COM 		for (; ve_tmp; ve_tmp = ve_tmp->ve_next) {
8847836SJohn.Forte@Sun.COM 			if (ve_tmp->ve_id > ve->ve_id) {
8857836SJohn.Forte@Sun.COM 				break;
8867836SJohn.Forte@Sun.COM 			} else if (ve_tmp->ve_id == ve->ve_id) {
8877836SJohn.Forte@Sun.COM 				return (STMF_ALREADY);
8887836SJohn.Forte@Sun.COM 			}
8897836SJohn.Forte@Sun.COM 			ve_prev = ve_tmp;
8907836SJohn.Forte@Sun.COM 		}
8917836SJohn.Forte@Sun.COM 	} else {
8927836SJohn.Forte@Sun.COM 		uint32_t veid = 0;
8937836SJohn.Forte@Sun.COM 		/* search the smallest available veid */
8947836SJohn.Forte@Sun.COM 		for (; ve_tmp; ve_tmp = ve_tmp->ve_next) {
8957836SJohn.Forte@Sun.COM 			ASSERT(ve_tmp->ve_id >= veid);
8967836SJohn.Forte@Sun.COM 			if (ve_tmp->ve_id != veid)
8977836SJohn.Forte@Sun.COM 				break;
8987836SJohn.Forte@Sun.COM 			veid++;
8997836SJohn.Forte@Sun.COM 			if (veid == 0xffffffff)
9007836SJohn.Forte@Sun.COM 				return (STMF_NOT_SUPPORTED);
9017836SJohn.Forte@Sun.COM 			ve_prev = ve_tmp;
9027836SJohn.Forte@Sun.COM 		}
9037836SJohn.Forte@Sun.COM 		ve->ve_id = veid;
9047836SJohn.Forte@Sun.COM 	}
9057836SJohn.Forte@Sun.COM 
9067836SJohn.Forte@Sun.COM 	/* insert before ve_tmp if it exist */
9077836SJohn.Forte@Sun.COM 	ve->ve_next = ve_tmp;
9087836SJohn.Forte@Sun.COM 	ve->ve_prev = ve_prev;
9097836SJohn.Forte@Sun.COM 	if (ve_tmp) {
9107836SJohn.Forte@Sun.COM 		ve_tmp->ve_prev = ve;
9117836SJohn.Forte@Sun.COM 	}
9127836SJohn.Forte@Sun.COM 	if (ve_prev) {
9137836SJohn.Forte@Sun.COM 		ve_prev->ve_next = ve;
9147836SJohn.Forte@Sun.COM 	} else {
9157836SJohn.Forte@Sun.COM 		luid->id_impl_specific = (void *)ve;
9167836SJohn.Forte@Sun.COM 	}
9177836SJohn.Forte@Sun.COM 	return (STMF_SUCCESS);
9187836SJohn.Forte@Sun.COM }
9197836SJohn.Forte@Sun.COM 
9207836SJohn.Forte@Sun.COM /* stmf_lock is already held, err_detail may be assigned if error happens */
9217836SJohn.Forte@Sun.COM stmf_status_t
stmf_add_view_entry(stmf_id_data_t * hg,stmf_id_data_t * tg,uint8_t * lu_guid,uint32_t * ve_id,uint8_t * lun,stmf_view_entry_t ** conflicting,uint32_t * err_detail)9227836SJohn.Forte@Sun.COM stmf_add_view_entry(stmf_id_data_t *hg, stmf_id_data_t *tg,
9237836SJohn.Forte@Sun.COM 		uint8_t *lu_guid, uint32_t *ve_id, uint8_t *lun,
9247836SJohn.Forte@Sun.COM 		stmf_view_entry_t **conflicting, uint32_t *err_detail)
9257836SJohn.Forte@Sun.COM {
9267836SJohn.Forte@Sun.COM 	stmf_id_data_t *luid;
9277836SJohn.Forte@Sun.COM 	stmf_view_entry_t *ve;
9287836SJohn.Forte@Sun.COM 	char *phg, *ptg;
9297836SJohn.Forte@Sun.COM 	stmf_lun_map_t *ve_map = NULL;
9307836SJohn.Forte@Sun.COM 	stmf_ver_hg_t *verhg = NULL, *verhg_ex = NULL;
9317836SJohn.Forte@Sun.COM 	stmf_ver_tg_t *vertg = NULL, *vertg_ex = NULL;
9327836SJohn.Forte@Sun.COM 	char luid_new;
9337836SJohn.Forte@Sun.COM 	uint16_t lun_num;
9347836SJohn.Forte@Sun.COM 	stmf_i_lu_t *ilu;
9357836SJohn.Forte@Sun.COM 	stmf_status_t ret;
9367836SJohn.Forte@Sun.COM 
9377836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
9387836SJohn.Forte@Sun.COM 
9397836SJohn.Forte@Sun.COM 	lun_num = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
9407836SJohn.Forte@Sun.COM 
9417836SJohn.Forte@Sun.COM 	luid = stmf_lookup_id(&stmf_state.stmf_luid_list, 16, lu_guid);
9427836SJohn.Forte@Sun.COM 	if (luid == NULL) {
9437836SJohn.Forte@Sun.COM 		luid = stmf_alloc_id(16, STMF_ID_TYPE_LU_GUID, lu_guid, 0);
9447836SJohn.Forte@Sun.COM 		ilu = stmf_luident_to_ilu(lu_guid);
9457836SJohn.Forte@Sun.COM 		if (ilu) {
9467836SJohn.Forte@Sun.COM 			ilu->ilu_luid = luid;
9477836SJohn.Forte@Sun.COM 			luid->id_pt_to_object = (void *)ilu;
9487836SJohn.Forte@Sun.COM 		}
9497836SJohn.Forte@Sun.COM 		luid_new = 1;
9507836SJohn.Forte@Sun.COM 	} else {
9517836SJohn.Forte@Sun.COM 		luid_new = 0;
9527836SJohn.Forte@Sun.COM 		ilu = (stmf_i_lu_t *)luid->id_pt_to_object;
9537836SJohn.Forte@Sun.COM 	}
9547836SJohn.Forte@Sun.COM 
9557836SJohn.Forte@Sun.COM 	/* The view entry won't be added if there is any confilict */
9567836SJohn.Forte@Sun.COM 	phg = (char *)hg->id_data; ptg = (char *)tg->id_data;
9577836SJohn.Forte@Sun.COM 	for (ve = (stmf_view_entry_t *)luid->id_impl_specific; ve != NULL;
9587836SJohn.Forte@Sun.COM 	    ve = ve->ve_next) {
9597836SJohn.Forte@Sun.COM 		if (((phg[0] == '*') || (ve->ve_hg->id_data[0] == '*') ||
9607836SJohn.Forte@Sun.COM 		    (hg == ve->ve_hg)) && ((ptg[0] == '*') ||
9617836SJohn.Forte@Sun.COM 		    (ve->ve_tg->id_data[0] == '*') || (tg == ve->ve_tg))) {
9627836SJohn.Forte@Sun.COM 			*conflicting = ve;
9637836SJohn.Forte@Sun.COM 			*err_detail = STMF_IOCERR_VIEW_ENTRY_CONFLICT;
9647836SJohn.Forte@Sun.COM 			ret = STMF_ALREADY;
9657836SJohn.Forte@Sun.COM 			goto add_ve_err_ret;
9667836SJohn.Forte@Sun.COM 		}
9677836SJohn.Forte@Sun.COM 	}
9687836SJohn.Forte@Sun.COM 
9697836SJohn.Forte@Sun.COM 	ve_map = stmf_duplicate_ve_map(0);
9707836SJohn.Forte@Sun.COM 	for (vertg = stmf_state.stmf_ver_tg_head; vertg != NULL;
9717836SJohn.Forte@Sun.COM 	    vertg = vertg->vert_next) {
9727836SJohn.Forte@Sun.COM 		ptg = (char *)vertg->vert_tg_ref->id_data;
9737836SJohn.Forte@Sun.COM 		if ((ptg[0] != '*') && (tg->id_data[0] != '*') &&
9747836SJohn.Forte@Sun.COM 		    (vertg->vert_tg_ref != tg)) {
9757836SJohn.Forte@Sun.COM 			continue;
9767836SJohn.Forte@Sun.COM 		}
9777836SJohn.Forte@Sun.COM 		if (vertg->vert_tg_ref == tg)
9787836SJohn.Forte@Sun.COM 			vertg_ex = vertg;
9797836SJohn.Forte@Sun.COM 		for (verhg = vertg->vert_verh_list; verhg != NULL;
9807836SJohn.Forte@Sun.COM 		    verhg = verhg->verh_next) {
9817836SJohn.Forte@Sun.COM 			phg = (char *)verhg->verh_hg_ref->id_data;
9827836SJohn.Forte@Sun.COM 			if ((phg[0] != '*') && (hg->id_data[0] != '*') &&
9837836SJohn.Forte@Sun.COM 			    (verhg->verh_hg_ref != hg)) {
9847836SJohn.Forte@Sun.COM 				continue;
9857836SJohn.Forte@Sun.COM 			}
9867836SJohn.Forte@Sun.COM 			if ((vertg_ex == vertg) && (verhg->verh_hg_ref == hg))
9877836SJohn.Forte@Sun.COM 				verhg_ex = verhg;
9887836SJohn.Forte@Sun.COM 			(void) stmf_merge_ve_map(&verhg->verh_ve_map, ve_map,
9897836SJohn.Forte@Sun.COM 			    &ve_map, 0);
9907836SJohn.Forte@Sun.COM 		}
9917836SJohn.Forte@Sun.COM 	}
9927836SJohn.Forte@Sun.COM 
9937836SJohn.Forte@Sun.COM 	if (lun[2] == 0xFF) {
9947836SJohn.Forte@Sun.COM 		/* Pick a LUN number */
9957836SJohn.Forte@Sun.COM 		lun_num = stmf_get_next_free_lun(ve_map, lun);
9967836SJohn.Forte@Sun.COM 		if (lun_num > 0x3FFF) {
9977836SJohn.Forte@Sun.COM 			stmf_destroy_ve_map(ve_map);
9987836SJohn.Forte@Sun.COM 			ret = STMF_NOT_SUPPORTED;
9997836SJohn.Forte@Sun.COM 			goto add_ve_err_ret;
10007836SJohn.Forte@Sun.COM 		}
10017836SJohn.Forte@Sun.COM 	} else {
10027836SJohn.Forte@Sun.COM 		if ((*conflicting = stmf_get_ent_from_map(ve_map, lun_num))
10037836SJohn.Forte@Sun.COM 		    != NULL) {
10047836SJohn.Forte@Sun.COM 			stmf_destroy_ve_map(ve_map);
10057836SJohn.Forte@Sun.COM 			*err_detail = STMF_IOCERR_LU_NUMBER_IN_USE;
10067836SJohn.Forte@Sun.COM 			ret = STMF_LUN_TAKEN;
10077836SJohn.Forte@Sun.COM 			goto add_ve_err_ret;
10087836SJohn.Forte@Sun.COM 		}
10097836SJohn.Forte@Sun.COM 	}
10107836SJohn.Forte@Sun.COM 	stmf_destroy_ve_map(ve_map);
10117836SJohn.Forte@Sun.COM 
10127836SJohn.Forte@Sun.COM 	/* All is well, do the actual addition now */
10137836SJohn.Forte@Sun.COM 	ve = (stmf_view_entry_t *)kmem_zalloc(sizeof (*ve), KM_SLEEP);
10147836SJohn.Forte@Sun.COM 	ve->ve_id = *ve_id;
10157836SJohn.Forte@Sun.COM 	ve->ve_lun[0] = lun[0];
10167836SJohn.Forte@Sun.COM 	ve->ve_lun[1] = lun[1];
10177836SJohn.Forte@Sun.COM 
10187836SJohn.Forte@Sun.COM 	if ((ret = stmf_add_ve_to_luid(luid, ve)) != STMF_SUCCESS) {
10197836SJohn.Forte@Sun.COM 		kmem_free(ve, sizeof (stmf_view_entry_t));
10207836SJohn.Forte@Sun.COM 		goto add_ve_err_ret;
10217836SJohn.Forte@Sun.COM 	}
10227836SJohn.Forte@Sun.COM 	ve->ve_hg = hg; hg->id_refcnt++;
10237836SJohn.Forte@Sun.COM 	ve->ve_tg = tg; tg->id_refcnt++;
10247836SJohn.Forte@Sun.COM 	ve->ve_luid = luid; luid->id_refcnt++;
10257836SJohn.Forte@Sun.COM 
10267836SJohn.Forte@Sun.COM 	*ve_id = ve->ve_id;
10277836SJohn.Forte@Sun.COM 
10287836SJohn.Forte@Sun.COM 	if (luid_new) {
10297836SJohn.Forte@Sun.COM 		stmf_append_id(&stmf_state.stmf_luid_list, luid);
10307836SJohn.Forte@Sun.COM 	}
10317836SJohn.Forte@Sun.COM 
10327836SJohn.Forte@Sun.COM 	if (vertg_ex == NULL) {
10337836SJohn.Forte@Sun.COM 		vertg_ex = (stmf_ver_tg_t *)kmem_zalloc(sizeof (stmf_ver_tg_t),
10347836SJohn.Forte@Sun.COM 		    KM_SLEEP);
10357836SJohn.Forte@Sun.COM 		vertg_ex->vert_next = stmf_state.stmf_ver_tg_head;
10367836SJohn.Forte@Sun.COM 		stmf_state.stmf_ver_tg_head = vertg_ex;
10377836SJohn.Forte@Sun.COM 		vertg_ex->vert_tg_ref = tg;
10387836SJohn.Forte@Sun.COM 		verhg_ex = vertg_ex->vert_verh_list =
10397836SJohn.Forte@Sun.COM 		    (stmf_ver_hg_t *)kmem_zalloc(sizeof (stmf_ver_hg_t),
10407836SJohn.Forte@Sun.COM 		    KM_SLEEP);
10417836SJohn.Forte@Sun.COM 		verhg_ex->verh_hg_ref = hg;
10427836SJohn.Forte@Sun.COM 	}
10437836SJohn.Forte@Sun.COM 	if (verhg_ex == NULL) {
10447836SJohn.Forte@Sun.COM 		verhg_ex = (stmf_ver_hg_t *)kmem_zalloc(sizeof (stmf_ver_hg_t),
10457836SJohn.Forte@Sun.COM 		    KM_SLEEP);
10467836SJohn.Forte@Sun.COM 		verhg_ex->verh_next = vertg_ex->vert_verh_list;
10477836SJohn.Forte@Sun.COM 		vertg_ex->vert_verh_list = verhg_ex;
10487836SJohn.Forte@Sun.COM 		verhg_ex->verh_hg_ref = hg;
10497836SJohn.Forte@Sun.COM 	}
10507836SJohn.Forte@Sun.COM 	ret = stmf_add_ent_to_map(&verhg_ex->verh_ve_map, ve, ve->ve_lun);
10517836SJohn.Forte@Sun.COM 	ASSERT(ret == STMF_SUCCESS);
10527836SJohn.Forte@Sun.COM 
10537836SJohn.Forte@Sun.COM 	/* we need to update the affected session */
10547836SJohn.Forte@Sun.COM 	if (stmf_state.stmf_service_running) {
10557836SJohn.Forte@Sun.COM 		if (ilu && ilu->ilu_state == STMF_STATE_ONLINE)
10567836SJohn.Forte@Sun.COM 			stmf_update_sessions_per_ve(ve, ilu->ilu_lu, 1);
10577836SJohn.Forte@Sun.COM 	}
10587836SJohn.Forte@Sun.COM 
10597836SJohn.Forte@Sun.COM 	return (STMF_SUCCESS);
10607836SJohn.Forte@Sun.COM add_ve_err_ret:
10617836SJohn.Forte@Sun.COM 	if (luid_new) {
10627836SJohn.Forte@Sun.COM 		if (ilu)
10637836SJohn.Forte@Sun.COM 			ilu->ilu_luid = NULL;
10647836SJohn.Forte@Sun.COM 		stmf_free_id(luid);
10657836SJohn.Forte@Sun.COM 	}
10667836SJohn.Forte@Sun.COM 	return (ret);
10677836SJohn.Forte@Sun.COM }
10687836SJohn.Forte@Sun.COM 
10697836SJohn.Forte@Sun.COM stmf_status_t
stmf_add_ent_to_map(stmf_lun_map_t * lm,void * ent,uint8_t * lun)10707836SJohn.Forte@Sun.COM stmf_add_ent_to_map(stmf_lun_map_t *lm, void *ent, uint8_t *lun)
10717836SJohn.Forte@Sun.COM {
10727836SJohn.Forte@Sun.COM 	uint16_t n;
10737836SJohn.Forte@Sun.COM 	if (((lun[0] & 0xc0) >> 6) != 0)
10747836SJohn.Forte@Sun.COM 		return (STMF_FAILURE);
10757836SJohn.Forte@Sun.COM 
10767836SJohn.Forte@Sun.COM 	n = (uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8);
10777836SJohn.Forte@Sun.COM try_again_to_add:
10787836SJohn.Forte@Sun.COM 	if (lm->lm_nentries && (n < lm->lm_nentries)) {
10797836SJohn.Forte@Sun.COM 		if (lm->lm_plus[n] == NULL) {
10807836SJohn.Forte@Sun.COM 			lm->lm_plus[n] = ent;
10817836SJohn.Forte@Sun.COM 			lm->lm_nluns++;
10827836SJohn.Forte@Sun.COM 			return (STMF_SUCCESS);
10837836SJohn.Forte@Sun.COM 		} else {
10847836SJohn.Forte@Sun.COM 			return (STMF_LUN_TAKEN);
10857836SJohn.Forte@Sun.COM 		}
10867836SJohn.Forte@Sun.COM 	} else {
10877836SJohn.Forte@Sun.COM 		void **pplu;
10887836SJohn.Forte@Sun.COM 		uint16_t m = n + 1;
10897836SJohn.Forte@Sun.COM 		m = ((m + 7) & ~7) & 0x7FFF;
10907836SJohn.Forte@Sun.COM 		pplu = (void **)kmem_zalloc(m * sizeof (void *), KM_SLEEP);
10917836SJohn.Forte@Sun.COM 		bcopy(lm->lm_plus, pplu,
10927836SJohn.Forte@Sun.COM 		    lm->lm_nentries * sizeof (void *));
10937836SJohn.Forte@Sun.COM 		kmem_free(lm->lm_plus, lm->lm_nentries * sizeof (void *));
10947836SJohn.Forte@Sun.COM 		lm->lm_plus = pplu;
10957836SJohn.Forte@Sun.COM 		lm->lm_nentries = m;
10967836SJohn.Forte@Sun.COM 		goto try_again_to_add;
10977836SJohn.Forte@Sun.COM 	}
10987836SJohn.Forte@Sun.COM }
10997836SJohn.Forte@Sun.COM 
11007836SJohn.Forte@Sun.COM 
11017836SJohn.Forte@Sun.COM stmf_status_t
stmf_remove_ent_from_map(stmf_lun_map_t * lm,uint8_t * lun)11027836SJohn.Forte@Sun.COM stmf_remove_ent_from_map(stmf_lun_map_t *lm, uint8_t *lun)
11037836SJohn.Forte@Sun.COM {
11047836SJohn.Forte@Sun.COM 	uint16_t n, i;
11057836SJohn.Forte@Sun.COM 	uint8_t lutype = (lun[0] & 0xc0) >> 6;
11067836SJohn.Forte@Sun.COM 	if (lutype != 0)
11077836SJohn.Forte@Sun.COM 		return (STMF_FAILURE);
11087836SJohn.Forte@Sun.COM 
11097836SJohn.Forte@Sun.COM 	n = (uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8);
11107836SJohn.Forte@Sun.COM 
11117836SJohn.Forte@Sun.COM 	if (n >= lm->lm_nentries)
11127836SJohn.Forte@Sun.COM 		return (STMF_NOT_FOUND);
11137836SJohn.Forte@Sun.COM 	if (lm->lm_plus[n] == NULL)
11147836SJohn.Forte@Sun.COM 		return (STMF_NOT_FOUND);
11157836SJohn.Forte@Sun.COM 
11167836SJohn.Forte@Sun.COM 	lm->lm_plus[n] = NULL;
11177836SJohn.Forte@Sun.COM 	lm->lm_nluns--;
11187836SJohn.Forte@Sun.COM 
11197836SJohn.Forte@Sun.COM 	for (i = 0; i < lm->lm_nentries; i++) {
11207836SJohn.Forte@Sun.COM 		if (lm->lm_plus[lm->lm_nentries - 1 - i] != NULL)
11217836SJohn.Forte@Sun.COM 			break;
11227836SJohn.Forte@Sun.COM 	}
11237836SJohn.Forte@Sun.COM 	i &= ~15;
11247836SJohn.Forte@Sun.COM 	if (i >= 16) {
11257836SJohn.Forte@Sun.COM 		void **pplu;
11267836SJohn.Forte@Sun.COM 		uint16_t m;
11277836SJohn.Forte@Sun.COM 		m = lm->lm_nentries - i;
11287836SJohn.Forte@Sun.COM 		pplu = (void **)kmem_zalloc(m * sizeof (void *), KM_SLEEP);
11297836SJohn.Forte@Sun.COM 		bcopy(lm->lm_plus, pplu, m * sizeof (void *));
11307836SJohn.Forte@Sun.COM 		kmem_free(lm->lm_plus, lm->lm_nentries * sizeof (void *));
11317836SJohn.Forte@Sun.COM 		lm->lm_plus = pplu;
11327836SJohn.Forte@Sun.COM 		lm->lm_nentries = m;
11337836SJohn.Forte@Sun.COM 	}
11347836SJohn.Forte@Sun.COM 
11357836SJohn.Forte@Sun.COM 	return (STMF_SUCCESS);
11367836SJohn.Forte@Sun.COM }
11377836SJohn.Forte@Sun.COM 
11387836SJohn.Forte@Sun.COM uint16_t
stmf_get_next_free_lun(stmf_lun_map_t * sm,uint8_t * lun)11397836SJohn.Forte@Sun.COM stmf_get_next_free_lun(stmf_lun_map_t *sm, uint8_t *lun)
11407836SJohn.Forte@Sun.COM {
11417836SJohn.Forte@Sun.COM 	uint16_t luNbr;
11427836SJohn.Forte@Sun.COM 
11437836SJohn.Forte@Sun.COM 
11447836SJohn.Forte@Sun.COM 	if (sm->lm_nluns < 0x4000) {
11457836SJohn.Forte@Sun.COM 		for (luNbr = 0; luNbr < sm->lm_nentries; luNbr++) {
11467836SJohn.Forte@Sun.COM 			if (sm->lm_plus[luNbr] == NULL)
11477836SJohn.Forte@Sun.COM 				break;
11487836SJohn.Forte@Sun.COM 		}
11497836SJohn.Forte@Sun.COM 	} else {
11507836SJohn.Forte@Sun.COM 		return (0xFFFF);
11517836SJohn.Forte@Sun.COM 	}
11527836SJohn.Forte@Sun.COM 	if (lun) {
11537836SJohn.Forte@Sun.COM 		bzero(lun, 8);
11547836SJohn.Forte@Sun.COM 		lun[1] = luNbr & 0xff;
11557836SJohn.Forte@Sun.COM 		lun[0] = (luNbr >> 8) & 0xff;
11567836SJohn.Forte@Sun.COM 	}
11577836SJohn.Forte@Sun.COM 
11587836SJohn.Forte@Sun.COM 	return (luNbr);
11597836SJohn.Forte@Sun.COM }
11607836SJohn.Forte@Sun.COM 
11617836SJohn.Forte@Sun.COM void *
stmf_get_ent_from_map(stmf_lun_map_t * sm,uint16_t lun_num)11627836SJohn.Forte@Sun.COM stmf_get_ent_from_map(stmf_lun_map_t *sm, uint16_t lun_num)
11637836SJohn.Forte@Sun.COM {
11647836SJohn.Forte@Sun.COM 	if ((lun_num & 0xC000) == 0) {
11657836SJohn.Forte@Sun.COM 		if (sm->lm_nentries > lun_num)
11667836SJohn.Forte@Sun.COM 			return (sm->lm_plus[lun_num & 0x3FFF]);
11677836SJohn.Forte@Sun.COM 		else
11687836SJohn.Forte@Sun.COM 			return (NULL);
11697836SJohn.Forte@Sun.COM 	}
11707836SJohn.Forte@Sun.COM 
11717836SJohn.Forte@Sun.COM 	return (NULL);
11727836SJohn.Forte@Sun.COM }
11737836SJohn.Forte@Sun.COM 
11747836SJohn.Forte@Sun.COM int
stmf_add_ve(uint8_t * hgname,uint16_t hgname_size,uint8_t * tgname,uint16_t tgname_size,uint8_t * lu_guid,uint32_t * ve_id,uint8_t * luNbr,uint32_t * err_detail)11757836SJohn.Forte@Sun.COM stmf_add_ve(uint8_t *hgname, uint16_t hgname_size,
11767836SJohn.Forte@Sun.COM 		uint8_t *tgname, uint16_t tgname_size,
11777836SJohn.Forte@Sun.COM 		uint8_t *lu_guid, uint32_t *ve_id,
11787836SJohn.Forte@Sun.COM 		uint8_t *luNbr, uint32_t *err_detail)
11797836SJohn.Forte@Sun.COM {
11807836SJohn.Forte@Sun.COM 	stmf_id_data_t *hg;
11817836SJohn.Forte@Sun.COM 	stmf_id_data_t *tg;
11827836SJohn.Forte@Sun.COM 	stmf_view_entry_t *conflictve;
11837836SJohn.Forte@Sun.COM 	stmf_status_t ret;
11847836SJohn.Forte@Sun.COM 
11857836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
11867836SJohn.Forte@Sun.COM 
11877836SJohn.Forte@Sun.COM 	hg = stmf_lookup_id(&stmf_state.stmf_hg_list, hgname_size,
11887836SJohn.Forte@Sun.COM 	    (uint8_t *)hgname);
11897836SJohn.Forte@Sun.COM 	if (!hg) {
11907836SJohn.Forte@Sun.COM 		*err_detail = STMF_IOCERR_INVALID_HG;
11917836SJohn.Forte@Sun.COM 		return (ENOENT); /* could not find group */
11927836SJohn.Forte@Sun.COM 	}
11937836SJohn.Forte@Sun.COM 	tg = stmf_lookup_id(&stmf_state.stmf_tg_list, tgname_size,
11947836SJohn.Forte@Sun.COM 	    (uint8_t *)tgname);
11957836SJohn.Forte@Sun.COM 	if (!tg) {
11967836SJohn.Forte@Sun.COM 		*err_detail = STMF_IOCERR_INVALID_TG;
11977836SJohn.Forte@Sun.COM 		return (ENOENT); /* could not find group */
11987836SJohn.Forte@Sun.COM 	}
11997836SJohn.Forte@Sun.COM 	ret = stmf_add_view_entry(hg, tg, lu_guid, ve_id, luNbr,
12007836SJohn.Forte@Sun.COM 	    &conflictve, err_detail);
12017836SJohn.Forte@Sun.COM 
12027836SJohn.Forte@Sun.COM 	if (ret == STMF_ALREADY) {
12037836SJohn.Forte@Sun.COM 		return (EALREADY);
12047836SJohn.Forte@Sun.COM 	} else if (ret == STMF_LUN_TAKEN) {
12057836SJohn.Forte@Sun.COM 		return (EEXIST);
12067836SJohn.Forte@Sun.COM 	} else if (ret == STMF_NOT_SUPPORTED) {
12077836SJohn.Forte@Sun.COM 		return (E2BIG);
12087836SJohn.Forte@Sun.COM 	} else if (ret != STMF_SUCCESS) {
12097836SJohn.Forte@Sun.COM 		return (EINVAL);
12107836SJohn.Forte@Sun.COM 	}
12117836SJohn.Forte@Sun.COM 	return (0);
12127836SJohn.Forte@Sun.COM }
12137836SJohn.Forte@Sun.COM 
12147836SJohn.Forte@Sun.COM int
stmf_remove_ve_by_id(uint8_t * guid,uint32_t veid,uint32_t * err_detail)12157836SJohn.Forte@Sun.COM stmf_remove_ve_by_id(uint8_t *guid, uint32_t veid, uint32_t *err_detail)
12167836SJohn.Forte@Sun.COM {
12177836SJohn.Forte@Sun.COM 	stmf_id_data_t *luid;
12187836SJohn.Forte@Sun.COM 	stmf_view_entry_t	*ve;
12197836SJohn.Forte@Sun.COM 	stmf_ver_tg_t *vtg;
12207836SJohn.Forte@Sun.COM 	stmf_ver_hg_t *vhg;
12217836SJohn.Forte@Sun.COM 	stmf_ver_tg_t *prev_vtg = NULL;
12227836SJohn.Forte@Sun.COM 	stmf_ver_hg_t *prev_vhg = NULL;
12237836SJohn.Forte@Sun.COM 	int found = 0;
12247836SJohn.Forte@Sun.COM 	stmf_i_lu_t *ilu;
12257836SJohn.Forte@Sun.COM 
12267836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
12277836SJohn.Forte@Sun.COM 	luid = stmf_lookup_id(&stmf_state.stmf_luid_list, 16, guid);
12287836SJohn.Forte@Sun.COM 	if (luid == NULL) {
12297836SJohn.Forte@Sun.COM 		*err_detail = STMF_IOCERR_INVALID_LU_ID;
12307836SJohn.Forte@Sun.COM 		return (ENODEV);
12317836SJohn.Forte@Sun.COM 	}
12327836SJohn.Forte@Sun.COM 	ilu = (stmf_i_lu_t *)luid->id_pt_to_object;
12337836SJohn.Forte@Sun.COM 
12347836SJohn.Forte@Sun.COM 	for (ve = (stmf_view_entry_t *)luid->id_impl_specific;
12357836SJohn.Forte@Sun.COM 	    ve; ve = ve->ve_next) {
12367836SJohn.Forte@Sun.COM 		if (ve->ve_id == veid) {
12377836SJohn.Forte@Sun.COM 			break;
12387836SJohn.Forte@Sun.COM 		}
12397836SJohn.Forte@Sun.COM 	}
12407836SJohn.Forte@Sun.COM 	if (!ve) {
12417836SJohn.Forte@Sun.COM 		*err_detail = STMF_IOCERR_INVALID_VE_ID;
12427836SJohn.Forte@Sun.COM 		return (ENODEV);
12437836SJohn.Forte@Sun.COM 	}
12447836SJohn.Forte@Sun.COM 	/* remove the ve */
12457836SJohn.Forte@Sun.COM 	if (ve->ve_next)
12467836SJohn.Forte@Sun.COM 		ve->ve_next->ve_prev = ve->ve_prev;
12477836SJohn.Forte@Sun.COM 	if (ve->ve_prev)
12487836SJohn.Forte@Sun.COM 		ve->ve_prev->ve_next = ve->ve_next;
12497836SJohn.Forte@Sun.COM 	else {
12507836SJohn.Forte@Sun.COM 		luid->id_impl_specific = (void *)ve->ve_next;
12517836SJohn.Forte@Sun.COM 		if (!luid->id_impl_specific) {
12527836SJohn.Forte@Sun.COM 			/* don't have any view entries related to this lu */
12537836SJohn.Forte@Sun.COM 			stmf_remove_id(&stmf_state.stmf_luid_list, luid);
12547836SJohn.Forte@Sun.COM 			if (ilu)
12557836SJohn.Forte@Sun.COM 				ilu->ilu_luid = NULL;
12567836SJohn.Forte@Sun.COM 			stmf_free_id(luid);
12577836SJohn.Forte@Sun.COM 		}
12587836SJohn.Forte@Sun.COM 	}
12597836SJohn.Forte@Sun.COM 
12607836SJohn.Forte@Sun.COM 	/* we need to update ver_hg->verh_ve_map */
12617836SJohn.Forte@Sun.COM 	for (vtg = stmf_state.stmf_ver_tg_head; vtg; vtg = vtg->vert_next) {
12627836SJohn.Forte@Sun.COM 		if (vtg->vert_tg_ref == ve->ve_tg) {
12637836SJohn.Forte@Sun.COM 			found = 1;
12647836SJohn.Forte@Sun.COM 			break;
12657836SJohn.Forte@Sun.COM 		}
12667836SJohn.Forte@Sun.COM 		prev_vtg = vtg;
12677836SJohn.Forte@Sun.COM 	}
12687836SJohn.Forte@Sun.COM 	ASSERT(found);
12697836SJohn.Forte@Sun.COM 	found = 0;
12707836SJohn.Forte@Sun.COM 	for (vhg = vtg->vert_verh_list; vhg; vhg = vhg->verh_next) {
12717836SJohn.Forte@Sun.COM 		if (vhg->verh_hg_ref == ve->ve_hg) {
12727836SJohn.Forte@Sun.COM 			found = 1;
12737836SJohn.Forte@Sun.COM 			break;
12747836SJohn.Forte@Sun.COM 		}
12757836SJohn.Forte@Sun.COM 		prev_vhg = vhg;
12767836SJohn.Forte@Sun.COM 	}
12777836SJohn.Forte@Sun.COM 	ASSERT(found);
12787836SJohn.Forte@Sun.COM 
12797836SJohn.Forte@Sun.COM 	(void) stmf_remove_ent_from_map(&vhg->verh_ve_map, ve->ve_lun);
12807836SJohn.Forte@Sun.COM 
12817836SJohn.Forte@Sun.COM 	/* free verhg if it don't have any ve entries related */
12827836SJohn.Forte@Sun.COM 	if (!vhg->verh_ve_map.lm_nluns) {
12837836SJohn.Forte@Sun.COM 		/* we don't have any view entry related */
12847836SJohn.Forte@Sun.COM 		if (prev_vhg)
12857836SJohn.Forte@Sun.COM 			prev_vhg->verh_next = vhg->verh_next;
12867836SJohn.Forte@Sun.COM 		else
12877836SJohn.Forte@Sun.COM 			vtg->vert_verh_list = vhg->verh_next;
12887836SJohn.Forte@Sun.COM 
12897836SJohn.Forte@Sun.COM 		/* Free entries in case the map still has memory */
12907836SJohn.Forte@Sun.COM 		if (vhg->verh_ve_map.lm_nentries) {
12917836SJohn.Forte@Sun.COM 			kmem_free(vhg->verh_ve_map.lm_plus,
12927836SJohn.Forte@Sun.COM 			    vhg->verh_ve_map.lm_nentries *
12937836SJohn.Forte@Sun.COM 			    sizeof (void *));
12947836SJohn.Forte@Sun.COM 		}
12957836SJohn.Forte@Sun.COM 		kmem_free(vhg, sizeof (stmf_ver_hg_t));
12967836SJohn.Forte@Sun.COM 		if (!vtg->vert_verh_list) {
12977836SJohn.Forte@Sun.COM 			/* we don't have any ve related */
12987836SJohn.Forte@Sun.COM 			if (prev_vtg)
12997836SJohn.Forte@Sun.COM 				prev_vtg->vert_next = vtg->vert_next;
13007836SJohn.Forte@Sun.COM 			else
13017836SJohn.Forte@Sun.COM 				stmf_state.stmf_ver_tg_head = vtg->vert_next;
13027836SJohn.Forte@Sun.COM 			kmem_free(vtg, sizeof (stmf_ver_tg_t));
13037836SJohn.Forte@Sun.COM 		}
13047836SJohn.Forte@Sun.COM 	}
13057836SJohn.Forte@Sun.COM 
13067836SJohn.Forte@Sun.COM 	if (stmf_state.stmf_service_running && ilu &&
13077836SJohn.Forte@Sun.COM 	    ilu->ilu_state == STMF_STATE_ONLINE) {
13087836SJohn.Forte@Sun.COM 		stmf_update_sessions_per_ve(ve, ilu->ilu_lu, 0);
13097836SJohn.Forte@Sun.COM 	}
13107836SJohn.Forte@Sun.COM 
13117836SJohn.Forte@Sun.COM 	ve->ve_hg->id_refcnt--;
13127836SJohn.Forte@Sun.COM 	ve->ve_tg->id_refcnt--;
13137836SJohn.Forte@Sun.COM 
13147836SJohn.Forte@Sun.COM 	kmem_free(ve, sizeof (stmf_view_entry_t));
13157836SJohn.Forte@Sun.COM 	return (0);
13167836SJohn.Forte@Sun.COM }
13177836SJohn.Forte@Sun.COM 
13187836SJohn.Forte@Sun.COM int
stmf_add_group(uint8_t * grpname,uint16_t grpname_size,stmf_id_type_t group_type,uint32_t * err_detail)13197836SJohn.Forte@Sun.COM stmf_add_group(uint8_t *grpname, uint16_t grpname_size,
13207836SJohn.Forte@Sun.COM 		stmf_id_type_t group_type, uint32_t *err_detail)
13217836SJohn.Forte@Sun.COM {
13227836SJohn.Forte@Sun.COM 	stmf_status_t status;
13237836SJohn.Forte@Sun.COM 
13247836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
13257836SJohn.Forte@Sun.COM 
13267836SJohn.Forte@Sun.COM 	if (group_type == STMF_ID_TYPE_HOST_GROUP)
13277836SJohn.Forte@Sun.COM 		status = stmf_add_hg(grpname, grpname_size, 0, err_detail);
13287836SJohn.Forte@Sun.COM 	else if (group_type == STMF_ID_TYPE_TARGET_GROUP)
13297836SJohn.Forte@Sun.COM 		status = stmf_add_tg(grpname, grpname_size, 0, err_detail);
13307836SJohn.Forte@Sun.COM 	else {
13317836SJohn.Forte@Sun.COM 		return (EINVAL);
13327836SJohn.Forte@Sun.COM 	}
13337836SJohn.Forte@Sun.COM 	switch (status) {
13347836SJohn.Forte@Sun.COM 	case STMF_SUCCESS:
13357836SJohn.Forte@Sun.COM 		return (0);
13367836SJohn.Forte@Sun.COM 	case STMF_INVALID_ARG:
13377836SJohn.Forte@Sun.COM 		return (EINVAL);
13387836SJohn.Forte@Sun.COM 	case STMF_ALREADY:
13397836SJohn.Forte@Sun.COM 		return (EEXIST);
13407836SJohn.Forte@Sun.COM 	default:
13417836SJohn.Forte@Sun.COM 		return (EIO);
13427836SJohn.Forte@Sun.COM 	}
13437836SJohn.Forte@Sun.COM }
13447836SJohn.Forte@Sun.COM 
13457836SJohn.Forte@Sun.COM /*
13467836SJohn.Forte@Sun.COM  * Group can only be removed only when it does not have
13477836SJohn.Forte@Sun.COM  * any view entry related
13487836SJohn.Forte@Sun.COM  */
13497836SJohn.Forte@Sun.COM int
stmf_remove_group(uint8_t * grpname,uint16_t grpname_size,stmf_id_type_t group_type,uint32_t * err_detail)13507836SJohn.Forte@Sun.COM stmf_remove_group(uint8_t *grpname, uint16_t grpname_size,
13517836SJohn.Forte@Sun.COM 		stmf_id_type_t group_type, uint32_t *err_detail)
13527836SJohn.Forte@Sun.COM {
13537836SJohn.Forte@Sun.COM 	stmf_id_data_t *id;
13547836SJohn.Forte@Sun.COM 	stmf_id_data_t *idmemb;
13557836SJohn.Forte@Sun.COM 	stmf_id_list_t *grp_memblist;
13567836SJohn.Forte@Sun.COM 	stmf_i_scsi_session_t *iss;
13577836SJohn.Forte@Sun.COM 	stmf_i_local_port_t *ilport;
13587836SJohn.Forte@Sun.COM 
13597836SJohn.Forte@Sun.COM 	if (grpname[0] == '*')
13607836SJohn.Forte@Sun.COM 		return (EINVAL);
13617836SJohn.Forte@Sun.COM 
13627836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
13637836SJohn.Forte@Sun.COM 
13647836SJohn.Forte@Sun.COM 	if (group_type == STMF_ID_TYPE_HOST_GROUP)
13657836SJohn.Forte@Sun.COM 		id = stmf_lookup_id(&stmf_state.stmf_hg_list,
13667836SJohn.Forte@Sun.COM 		    grpname_size, grpname);
13677836SJohn.Forte@Sun.COM 	else if (group_type == STMF_ID_TYPE_TARGET_GROUP)
13687836SJohn.Forte@Sun.COM 		id = stmf_lookup_id(&stmf_state.stmf_tg_list,
13697836SJohn.Forte@Sun.COM 		    grpname_size, grpname);
13707836SJohn.Forte@Sun.COM 	if (!id) {
13717836SJohn.Forte@Sun.COM 		*err_detail = (group_type == STMF_ID_TYPE_HOST_GROUP)?
13727836SJohn.Forte@Sun.COM 		    STMF_IOCERR_INVALID_HG:STMF_IOCERR_INVALID_TG;
13737836SJohn.Forte@Sun.COM 		return (ENODEV); /* no such grp */
13747836SJohn.Forte@Sun.COM 	}
13757836SJohn.Forte@Sun.COM 	if (id->id_refcnt) {
13767836SJohn.Forte@Sun.COM 		/* fail, still have viewentry related to it */
13777836SJohn.Forte@Sun.COM 		*err_detail = (group_type == STMF_ID_TYPE_HOST_GROUP)?
13787836SJohn.Forte@Sun.COM 		    STMF_IOCERR_HG_IN_USE:STMF_IOCERR_TG_IN_USE;
13797836SJohn.Forte@Sun.COM 		return (EBUSY);
13807836SJohn.Forte@Sun.COM 	}
13817836SJohn.Forte@Sun.COM 	grp_memblist = (stmf_id_list_t *)id->id_impl_specific;
13827836SJohn.Forte@Sun.COM 	while ((idmemb = grp_memblist->idl_head) != NULL) {
13837836SJohn.Forte@Sun.COM 		stmf_remove_id(grp_memblist, idmemb);
13847836SJohn.Forte@Sun.COM 		stmf_free_id(idmemb);
13857836SJohn.Forte@Sun.COM 	}
13867836SJohn.Forte@Sun.COM 
13877836SJohn.Forte@Sun.COM 	ASSERT(!grp_memblist->id_count);
13887836SJohn.Forte@Sun.COM 	if (id->id_type == STMF_ID_TYPE_TARGET_GROUP) {
13897836SJohn.Forte@Sun.COM 		for (ilport = stmf_state.stmf_ilportlist; ilport;
13907836SJohn.Forte@Sun.COM 		    ilport = ilport->ilport_next) {
13917836SJohn.Forte@Sun.COM 			if (ilport->ilport_tg == (void *)id) {
13927836SJohn.Forte@Sun.COM 				ilport->ilport_tg = NULL;
13937836SJohn.Forte@Sun.COM 			}
13947836SJohn.Forte@Sun.COM 		}
13957836SJohn.Forte@Sun.COM 		stmf_remove_id(&stmf_state.stmf_tg_list, id);
13967836SJohn.Forte@Sun.COM 	} else {
13977836SJohn.Forte@Sun.COM 		for (ilport = stmf_state.stmf_ilportlist; ilport;
13987836SJohn.Forte@Sun.COM 		    ilport = ilport->ilport_next) {
13997836SJohn.Forte@Sun.COM 			for (iss = ilport->ilport_ss_list; iss;
14007836SJohn.Forte@Sun.COM 			    iss = iss->iss_next) {
14017836SJohn.Forte@Sun.COM 				if (iss->iss_hg == (void *)id)
14027836SJohn.Forte@Sun.COM 					iss->iss_hg = NULL;
14037836SJohn.Forte@Sun.COM 			}
14047836SJohn.Forte@Sun.COM 		}
14057836SJohn.Forte@Sun.COM 		stmf_remove_id(&stmf_state.stmf_hg_list, id);
14067836SJohn.Forte@Sun.COM 	}
14077836SJohn.Forte@Sun.COM 	stmf_free_id(id);
14087836SJohn.Forte@Sun.COM 	return (0);
14097836SJohn.Forte@Sun.COM 
14107836SJohn.Forte@Sun.COM }
14117836SJohn.Forte@Sun.COM 
14127836SJohn.Forte@Sun.COM int
stmf_add_group_member(uint8_t * grpname,uint16_t grpname_size,uint8_t * entry_ident,uint16_t entry_size,stmf_id_type_t entry_type,uint32_t * err_detail)14137836SJohn.Forte@Sun.COM stmf_add_group_member(uint8_t *grpname, uint16_t grpname_size,
14147836SJohn.Forte@Sun.COM 		uint8_t	*entry_ident, uint16_t entry_size,
14157836SJohn.Forte@Sun.COM 		stmf_id_type_t entry_type, uint32_t *err_detail)
14167836SJohn.Forte@Sun.COM {
14177836SJohn.Forte@Sun.COM 	stmf_id_data_t	*id_grp, *id_alltgt;
14187836SJohn.Forte@Sun.COM 	stmf_id_data_t	*id_member;
14197836SJohn.Forte@Sun.COM 	stmf_id_data_t	*id_grp_tmp;
14207836SJohn.Forte@Sun.COM 	stmf_i_scsi_session_t *iss;
14217836SJohn.Forte@Sun.COM 	stmf_i_local_port_t *ilport;
14227836SJohn.Forte@Sun.COM 	stmf_lun_map_t *vemap, *vemap_alltgt;
14237836SJohn.Forte@Sun.COM 	uint8_t grpname_forall = '*';
14247836SJohn.Forte@Sun.COM 
14257836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
14267836SJohn.Forte@Sun.COM 	ASSERT(grpname[0] != '*');
14277836SJohn.Forte@Sun.COM 
14287836SJohn.Forte@Sun.COM 	if (entry_type == STMF_ID_TYPE_HOST) {
14297836SJohn.Forte@Sun.COM 		id_grp = stmf_lookup_id(&stmf_state.stmf_hg_list,
14307836SJohn.Forte@Sun.COM 		    grpname_size, grpname);
14317836SJohn.Forte@Sun.COM 		id_grp_tmp = stmf_lookup_group_for_host(entry_ident,
14327836SJohn.Forte@Sun.COM 		    entry_size);
14337836SJohn.Forte@Sun.COM 	} else {
14347836SJohn.Forte@Sun.COM 		id_grp = stmf_lookup_id(&stmf_state.stmf_tg_list,
14357836SJohn.Forte@Sun.COM 		    grpname_size, grpname);
14367836SJohn.Forte@Sun.COM 		id_grp_tmp = stmf_lookup_group_for_target(entry_ident,
14377836SJohn.Forte@Sun.COM 		    entry_size);
14387836SJohn.Forte@Sun.COM 	}
14397836SJohn.Forte@Sun.COM 	if (id_grp == NULL) {
14407836SJohn.Forte@Sun.COM 		*err_detail = (entry_type == STMF_ID_TYPE_HOST)?
14417836SJohn.Forte@Sun.COM 		    STMF_IOCERR_INVALID_HG:STMF_IOCERR_INVALID_TG;
14427836SJohn.Forte@Sun.COM 		return (ENODEV); /* not found */
14437836SJohn.Forte@Sun.COM 	}
14447836SJohn.Forte@Sun.COM 
14457836SJohn.Forte@Sun.COM 	/* Check whether this member already bound to a group */
14467836SJohn.Forte@Sun.COM 	if (id_grp_tmp) {
14477836SJohn.Forte@Sun.COM 		if (id_grp_tmp != id_grp) {
14487836SJohn.Forte@Sun.COM 			*err_detail = (entry_type == STMF_ID_TYPE_HOST)?
14497836SJohn.Forte@Sun.COM 			    STMF_IOCERR_HG_ENTRY_EXISTS:
14507836SJohn.Forte@Sun.COM 			    STMF_IOCERR_TG_ENTRY_EXISTS;
14517836SJohn.Forte@Sun.COM 			return (EEXIST); /* already added into another grp */
14527836SJohn.Forte@Sun.COM 		}
14537836SJohn.Forte@Sun.COM 		else
14547836SJohn.Forte@Sun.COM 			return (0);
14557836SJohn.Forte@Sun.COM 	}
145611108STim.Szeto@Sun.COM 
145711108STim.Szeto@Sun.COM 	/* verify target is offline */
145811108STim.Szeto@Sun.COM 	if (entry_type == STMF_ID_TYPE_TARGET) {
145911108STim.Szeto@Sun.COM 		ilport = stmf_targetident_to_ilport(entry_ident, entry_size);
146011108STim.Szeto@Sun.COM 		if (ilport && ilport->ilport_state != STMF_STATE_OFFLINE) {
146111108STim.Szeto@Sun.COM 			*err_detail = STMF_IOCERR_TG_NEED_TG_OFFLINE;
146211108STim.Szeto@Sun.COM 			return (EBUSY);
146311108STim.Szeto@Sun.COM 		}
146411108STim.Szeto@Sun.COM 	}
146511108STim.Szeto@Sun.COM 
14667836SJohn.Forte@Sun.COM 	id_member = stmf_alloc_id(entry_size, entry_type,
14677836SJohn.Forte@Sun.COM 	    entry_ident, 0);
14687836SJohn.Forte@Sun.COM 	stmf_append_id((stmf_id_list_t *)id_grp->id_impl_specific, id_member);
14697836SJohn.Forte@Sun.COM 
14707836SJohn.Forte@Sun.COM 	if (entry_type == STMF_ID_TYPE_TARGET) {
14717836SJohn.Forte@Sun.COM 		ilport = stmf_targetident_to_ilport(entry_ident, entry_size);
14727836SJohn.Forte@Sun.COM 		if (ilport)
14737836SJohn.Forte@Sun.COM 			ilport->ilport_tg = (void *)id_grp;
14747836SJohn.Forte@Sun.COM 		return (0);
14757836SJohn.Forte@Sun.COM 	}
14767836SJohn.Forte@Sun.COM 	/* For host group member, update the session if needed */
14777836SJohn.Forte@Sun.COM 	if (!stmf_state.stmf_service_running)
14787836SJohn.Forte@Sun.COM 		return (0);
14797836SJohn.Forte@Sun.COM 	/* Need to consider all target group + this host group */
14807836SJohn.Forte@Sun.COM 	id_alltgt = stmf_lookup_id(&stmf_state.stmf_tg_list,
14817836SJohn.Forte@Sun.COM 	    1, &grpname_forall);
14827836SJohn.Forte@Sun.COM 	vemap_alltgt = stmf_get_ve_map_per_ids(id_alltgt, id_grp);
14837836SJohn.Forte@Sun.COM 
14847836SJohn.Forte@Sun.COM 	/* check whether there are sessions may be affected */
14857836SJohn.Forte@Sun.COM 	for (ilport = stmf_state.stmf_ilportlist; ilport;
14867836SJohn.Forte@Sun.COM 	    ilport = ilport->ilport_next) {
14877836SJohn.Forte@Sun.COM 		if (ilport->ilport_state != STMF_STATE_ONLINE)
14887836SJohn.Forte@Sun.COM 			continue;
14897836SJohn.Forte@Sun.COM 		iss = stmf_lookup_session_for_hostident(ilport,
14907836SJohn.Forte@Sun.COM 		    entry_ident, entry_size);
14917836SJohn.Forte@Sun.COM 		if (iss) {
14927836SJohn.Forte@Sun.COM 			stmf_id_data_t *tgid;
14937836SJohn.Forte@Sun.COM 			iss->iss_hg = (void *)id_grp;
14947836SJohn.Forte@Sun.COM 			tgid = ilport->ilport_tg;
14957836SJohn.Forte@Sun.COM 			if (tgid) {
14967836SJohn.Forte@Sun.COM 				vemap = stmf_get_ve_map_per_ids(tgid, id_grp);
14977836SJohn.Forte@Sun.COM 				if (vemap)
14987836SJohn.Forte@Sun.COM 					stmf_add_lus_to_session_per_vemap(
14997836SJohn.Forte@Sun.COM 					    ilport, iss, vemap);
15007836SJohn.Forte@Sun.COM 			}
15017836SJohn.Forte@Sun.COM 			if (vemap_alltgt)
15027836SJohn.Forte@Sun.COM 				stmf_add_lus_to_session_per_vemap(ilport,
15037836SJohn.Forte@Sun.COM 				    iss, vemap_alltgt);
15047836SJohn.Forte@Sun.COM 		}
15057836SJohn.Forte@Sun.COM 	}
15067836SJohn.Forte@Sun.COM 
15077836SJohn.Forte@Sun.COM 	return (0);
15087836SJohn.Forte@Sun.COM }
15097836SJohn.Forte@Sun.COM 
15107836SJohn.Forte@Sun.COM int
stmf_remove_group_member(uint8_t * grpname,uint16_t grpname_size,uint8_t * entry_ident,uint16_t entry_size,stmf_id_type_t entry_type,uint32_t * err_detail)15117836SJohn.Forte@Sun.COM stmf_remove_group_member(uint8_t *grpname, uint16_t grpname_size,
15127836SJohn.Forte@Sun.COM 		uint8_t *entry_ident, uint16_t entry_size,
15137836SJohn.Forte@Sun.COM 		stmf_id_type_t entry_type, uint32_t *err_detail)
15147836SJohn.Forte@Sun.COM {
15157836SJohn.Forte@Sun.COM 	stmf_id_data_t	*id_grp, *id_alltgt;
15167836SJohn.Forte@Sun.COM 	stmf_id_data_t	*id_member;
15177836SJohn.Forte@Sun.COM 	stmf_lun_map_t *vemap,  *vemap_alltgt;
15187836SJohn.Forte@Sun.COM 	uint8_t grpname_forall = '*';
15197836SJohn.Forte@Sun.COM 	stmf_i_local_port_t *ilport;
15207836SJohn.Forte@Sun.COM 	stmf_i_scsi_session_t *iss;
15217836SJohn.Forte@Sun.COM 
15227836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
15237836SJohn.Forte@Sun.COM 	ASSERT(grpname[0] != '*');
15247836SJohn.Forte@Sun.COM 
15257836SJohn.Forte@Sun.COM 	if (entry_type == STMF_ID_TYPE_HOST) {
15267836SJohn.Forte@Sun.COM 		id_grp = stmf_lookup_id(&stmf_state.stmf_hg_list,
15277836SJohn.Forte@Sun.COM 		    grpname_size, grpname);
15287836SJohn.Forte@Sun.COM 	} else {
15297836SJohn.Forte@Sun.COM 		id_grp = stmf_lookup_id(&stmf_state.stmf_tg_list,
15307836SJohn.Forte@Sun.COM 		    grpname_size, grpname);
15317836SJohn.Forte@Sun.COM 	}
15327836SJohn.Forte@Sun.COM 	if (id_grp == NULL) {
15337836SJohn.Forte@Sun.COM 		*err_detail = (entry_type == STMF_ID_TYPE_HOST)?
15347836SJohn.Forte@Sun.COM 		    STMF_IOCERR_INVALID_HG:STMF_IOCERR_INVALID_TG;
15357836SJohn.Forte@Sun.COM 		return (ENODEV); /* no such group */
15367836SJohn.Forte@Sun.COM 	}
15377836SJohn.Forte@Sun.COM 	id_member = stmf_lookup_id((stmf_id_list_t *)id_grp->id_impl_specific,
15387836SJohn.Forte@Sun.COM 	    entry_size, entry_ident);
15397836SJohn.Forte@Sun.COM 	if (!id_member) {
15407836SJohn.Forte@Sun.COM 		*err_detail = (entry_type == STMF_ID_TYPE_HOST)?
15417836SJohn.Forte@Sun.COM 		    STMF_IOCERR_INVALID_HG_ENTRY:STMF_IOCERR_INVALID_TG_ENTRY;
15427836SJohn.Forte@Sun.COM 		return (ENODEV); /* no such member */
15437836SJohn.Forte@Sun.COM 	}
15449884STim.Szeto@Sun.COM 	/* verify target is offline */
15459884STim.Szeto@Sun.COM 	if (entry_type == STMF_ID_TYPE_TARGET) {
15469884STim.Szeto@Sun.COM 		ilport = stmf_targetident_to_ilport(entry_ident, entry_size);
15479884STim.Szeto@Sun.COM 		if (ilport && ilport->ilport_state != STMF_STATE_OFFLINE) {
15489884STim.Szeto@Sun.COM 			*err_detail = STMF_IOCERR_TG_NEED_TG_OFFLINE;
15499884STim.Szeto@Sun.COM 			return (EBUSY);
15509884STim.Szeto@Sun.COM 		}
15519884STim.Szeto@Sun.COM 	}
15529884STim.Szeto@Sun.COM 
15537836SJohn.Forte@Sun.COM 	stmf_remove_id((stmf_id_list_t *)id_grp->id_impl_specific, id_member);
15547836SJohn.Forte@Sun.COM 	stmf_free_id(id_member);
15557836SJohn.Forte@Sun.COM 
15567836SJohn.Forte@Sun.COM 	if (entry_type == STMF_ID_TYPE_TARGET) {
15577836SJohn.Forte@Sun.COM 		ilport = stmf_targetident_to_ilport(entry_ident, entry_size);
15587836SJohn.Forte@Sun.COM 		if (ilport)
15597836SJohn.Forte@Sun.COM 			ilport->ilport_tg = NULL;
15607836SJohn.Forte@Sun.COM 		return (0);
15617836SJohn.Forte@Sun.COM 	}
15627836SJohn.Forte@Sun.COM 	/* For host group member, update the session */
15637836SJohn.Forte@Sun.COM 	if (!stmf_state.stmf_service_running)
15647836SJohn.Forte@Sun.COM 		return (0);
15657836SJohn.Forte@Sun.COM 
15667836SJohn.Forte@Sun.COM 	/* Need to consider all target group + this host group */
15677836SJohn.Forte@Sun.COM 	id_alltgt = stmf_lookup_id(&stmf_state.stmf_tg_list,
15687836SJohn.Forte@Sun.COM 	    1, &grpname_forall);
15697836SJohn.Forte@Sun.COM 	vemap_alltgt = stmf_get_ve_map_per_ids(id_alltgt, id_grp);
15707836SJohn.Forte@Sun.COM 
15717836SJohn.Forte@Sun.COM 	/* check if there are session related, if so, update it */
15727836SJohn.Forte@Sun.COM 	for (ilport = stmf_state.stmf_ilportlist; ilport;
15737836SJohn.Forte@Sun.COM 	    ilport = ilport->ilport_next) {
15747836SJohn.Forte@Sun.COM 		if (ilport->ilport_state != STMF_STATE_ONLINE)
15757836SJohn.Forte@Sun.COM 			continue;
15767836SJohn.Forte@Sun.COM 		iss = stmf_lookup_session_for_hostident(ilport,
15777836SJohn.Forte@Sun.COM 		    entry_ident, entry_size);
15787836SJohn.Forte@Sun.COM 		if (iss) {
15797836SJohn.Forte@Sun.COM 			stmf_id_data_t *tgid;
15807836SJohn.Forte@Sun.COM 			iss->iss_hg = NULL;
15817836SJohn.Forte@Sun.COM 			tgid = ilport->ilport_tg;
15827836SJohn.Forte@Sun.COM 			if (tgid) {
15837836SJohn.Forte@Sun.COM 				vemap = stmf_get_ve_map_per_ids(tgid, id_grp);
15847836SJohn.Forte@Sun.COM 				if (vemap)
15857836SJohn.Forte@Sun.COM 					stmf_remove_lus_from_session_per_vemap(
15867836SJohn.Forte@Sun.COM 					    ilport, iss, vemap);
15877836SJohn.Forte@Sun.COM 			}
15887836SJohn.Forte@Sun.COM 			if (vemap_alltgt)
15897836SJohn.Forte@Sun.COM 				stmf_remove_lus_from_session_per_vemap(ilport,
15907836SJohn.Forte@Sun.COM 				    iss, vemap_alltgt);
15917836SJohn.Forte@Sun.COM 		}
15927836SJohn.Forte@Sun.COM 	}
15937836SJohn.Forte@Sun.COM 
15947836SJohn.Forte@Sun.COM 	return (0);
15957836SJohn.Forte@Sun.COM }
15967836SJohn.Forte@Sun.COM 
15977836SJohn.Forte@Sun.COM /* Assert stmf_lock is already held */
15987836SJohn.Forte@Sun.COM stmf_i_local_port_t *
stmf_targetident_to_ilport(uint8_t * target_ident,uint16_t ident_size)15997836SJohn.Forte@Sun.COM stmf_targetident_to_ilport(uint8_t *target_ident, uint16_t ident_size)
16007836SJohn.Forte@Sun.COM {
16017836SJohn.Forte@Sun.COM 	stmf_i_local_port_t *ilport;
16027836SJohn.Forte@Sun.COM 	uint8_t *id;
16037836SJohn.Forte@Sun.COM 
16047836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
16057836SJohn.Forte@Sun.COM 
16067836SJohn.Forte@Sun.COM 	for (ilport = stmf_state.stmf_ilportlist; ilport;
16077836SJohn.Forte@Sun.COM 	    ilport = ilport->ilport_next) {
16087836SJohn.Forte@Sun.COM 		id = (uint8_t *)ilport->ilport_lport->lport_id;
16097836SJohn.Forte@Sun.COM 		if ((id[3] == ident_size) &&
16107836SJohn.Forte@Sun.COM 		    bcmp(id + 4, target_ident, ident_size) == 0) {
16117836SJohn.Forte@Sun.COM 			return (ilport);
16127836SJohn.Forte@Sun.COM 		}
16137836SJohn.Forte@Sun.COM 	}
16147836SJohn.Forte@Sun.COM 	return (NULL);
16157836SJohn.Forte@Sun.COM }
16167836SJohn.Forte@Sun.COM 
16177836SJohn.Forte@Sun.COM stmf_i_scsi_session_t *
stmf_lookup_session_for_hostident(stmf_i_local_port_t * ilport,uint8_t * host_ident,uint16_t ident_size)16187836SJohn.Forte@Sun.COM stmf_lookup_session_for_hostident(stmf_i_local_port_t *ilport,
16197836SJohn.Forte@Sun.COM 		uint8_t *host_ident, uint16_t ident_size)
16207836SJohn.Forte@Sun.COM {
16217836SJohn.Forte@Sun.COM 	stmf_i_scsi_session_t *iss;
16227836SJohn.Forte@Sun.COM 	uint8_t *id;
16237836SJohn.Forte@Sun.COM 
16247836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
16257836SJohn.Forte@Sun.COM 
16267836SJohn.Forte@Sun.COM 	for (iss = ilport->ilport_ss_list; iss; iss = iss->iss_next) {
16277836SJohn.Forte@Sun.COM 		id = (uint8_t *)iss->iss_ss->ss_rport_id;
16287836SJohn.Forte@Sun.COM 		if ((id[3] == ident_size) &&
16297836SJohn.Forte@Sun.COM 		    bcmp(id + 4, host_ident, ident_size) == 0) {
16307836SJohn.Forte@Sun.COM 			return (iss);
16317836SJohn.Forte@Sun.COM 		}
16327836SJohn.Forte@Sun.COM 	}
16337836SJohn.Forte@Sun.COM 	return (NULL);
16347836SJohn.Forte@Sun.COM }
16357836SJohn.Forte@Sun.COM 
16367836SJohn.Forte@Sun.COM stmf_i_lu_t *
stmf_luident_to_ilu(uint8_t * lu_ident)16377836SJohn.Forte@Sun.COM stmf_luident_to_ilu(uint8_t *lu_ident)
16387836SJohn.Forte@Sun.COM {
16397836SJohn.Forte@Sun.COM 	stmf_i_lu_t *ilu;
16407836SJohn.Forte@Sun.COM 
16417836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
16427836SJohn.Forte@Sun.COM 
16437836SJohn.Forte@Sun.COM 	for (ilu = stmf_state.stmf_ilulist; ilu; ilu = ilu->ilu_next) {
16447836SJohn.Forte@Sun.COM 		if (bcmp(&ilu->ilu_lu->lu_id->ident[0], lu_ident, 16) == 0)
16457836SJohn.Forte@Sun.COM 			return (ilu);
16467836SJohn.Forte@Sun.COM 	}
16477836SJohn.Forte@Sun.COM 
16487836SJohn.Forte@Sun.COM 	return (NULL);
16497836SJohn.Forte@Sun.COM }
16507836SJohn.Forte@Sun.COM 
16517836SJohn.Forte@Sun.COM /*
16527836SJohn.Forte@Sun.COM  * Assert stmf_lock is already held,
16537836SJohn.Forte@Sun.COM  * Just get the view map for the specific target group and host group
16547836SJohn.Forte@Sun.COM  * tgid and hgid can not be NULL
16557836SJohn.Forte@Sun.COM  */
16567836SJohn.Forte@Sun.COM stmf_lun_map_t *
stmf_get_ve_map_per_ids(stmf_id_data_t * tgid,stmf_id_data_t * hgid)16577836SJohn.Forte@Sun.COM stmf_get_ve_map_per_ids(stmf_id_data_t *tgid, stmf_id_data_t *hgid)
16587836SJohn.Forte@Sun.COM {
16597836SJohn.Forte@Sun.COM 	int found = 0;
16607836SJohn.Forte@Sun.COM 	stmf_ver_tg_t *vertg;
16617836SJohn.Forte@Sun.COM 	stmf_ver_hg_t *verhg;
16627836SJohn.Forte@Sun.COM 
16637836SJohn.Forte@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
16647836SJohn.Forte@Sun.COM 
16657836SJohn.Forte@Sun.COM 	for (vertg = stmf_state.stmf_ver_tg_head;
16667836SJohn.Forte@Sun.COM 	    vertg; vertg = vertg->vert_next) {
16677836SJohn.Forte@Sun.COM 		if (vertg->vert_tg_ref == tgid) {
16687836SJohn.Forte@Sun.COM 			found = 1;
16697836SJohn.Forte@Sun.COM 			break;
16707836SJohn.Forte@Sun.COM 		}
16717836SJohn.Forte@Sun.COM 	}
16727836SJohn.Forte@Sun.COM 	if (!found)
16737836SJohn.Forte@Sun.COM 		return (NULL);
16747836SJohn.Forte@Sun.COM 
16757836SJohn.Forte@Sun.COM 	for (verhg = vertg->vert_verh_list; verhg; verhg = verhg->verh_next) {
16767836SJohn.Forte@Sun.COM 		if (verhg->verh_hg_ref == hgid) {
16777836SJohn.Forte@Sun.COM 			return (&verhg->verh_ve_map);
16787836SJohn.Forte@Sun.COM 		}
16797836SJohn.Forte@Sun.COM 	}
16807836SJohn.Forte@Sun.COM 	return (NULL);
16817836SJohn.Forte@Sun.COM }
168210691STim.Szeto@Sun.COM 
168310691STim.Szeto@Sun.COM stmf_status_t
stmf_validate_lun_view_entry(stmf_id_data_t * hg,stmf_id_data_t * tg,uint8_t * lun,uint32_t * err_detail)168410691STim.Szeto@Sun.COM stmf_validate_lun_view_entry(stmf_id_data_t *hg, stmf_id_data_t *tg,
168510691STim.Szeto@Sun.COM     uint8_t *lun, uint32_t *err_detail)
168610691STim.Szeto@Sun.COM {
168710691STim.Szeto@Sun.COM 	char			*phg, *ptg;
168810691STim.Szeto@Sun.COM 	stmf_lun_map_t		*ve_map = NULL;
168910691STim.Szeto@Sun.COM 	stmf_ver_hg_t		*verhg = NULL;
169010691STim.Szeto@Sun.COM 	stmf_ver_tg_t		*vertg = NULL;
169110691STim.Szeto@Sun.COM 	uint16_t		lun_num;
169210691STim.Szeto@Sun.COM 	stmf_status_t		ret = STMF_SUCCESS;
169310691STim.Szeto@Sun.COM 
169410691STim.Szeto@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
169510691STim.Szeto@Sun.COM 
169610691STim.Szeto@Sun.COM 	ve_map = stmf_duplicate_ve_map(0);
169710691STim.Szeto@Sun.COM 	for (vertg = stmf_state.stmf_ver_tg_head; vertg != NULL;
169810691STim.Szeto@Sun.COM 	    vertg = vertg->vert_next) {
169910691STim.Szeto@Sun.COM 		ptg = (char *)vertg->vert_tg_ref->id_data;
170010691STim.Szeto@Sun.COM 		if ((ptg[0] != '*') && (tg->id_data[0] != '*') &&
170110691STim.Szeto@Sun.COM 		    (vertg->vert_tg_ref != tg)) {
170210691STim.Szeto@Sun.COM 			continue;
170310691STim.Szeto@Sun.COM 		}
170410691STim.Szeto@Sun.COM 		for (verhg = vertg->vert_verh_list; verhg != NULL;
170510691STim.Szeto@Sun.COM 		    verhg = verhg->verh_next) {
170610691STim.Szeto@Sun.COM 			phg = (char *)verhg->verh_hg_ref->id_data;
170710691STim.Szeto@Sun.COM 			if ((phg[0] != '*') && (hg->id_data[0] != '*') &&
170810691STim.Szeto@Sun.COM 			    (verhg->verh_hg_ref != hg)) {
170910691STim.Szeto@Sun.COM 				continue;
171010691STim.Szeto@Sun.COM 			}
171110691STim.Szeto@Sun.COM 			(void) stmf_merge_ve_map(&verhg->verh_ve_map, ve_map,
171210691STim.Szeto@Sun.COM 			    &ve_map, 0);
171310691STim.Szeto@Sun.COM 		}
171410691STim.Szeto@Sun.COM 	}
171510691STim.Szeto@Sun.COM 
171610691STim.Szeto@Sun.COM 	ret = STMF_SUCCESS;
171710691STim.Szeto@Sun.COM 	/* Return an available lun number */
171810691STim.Szeto@Sun.COM 	if (lun[2] == 0xFF) {
171910691STim.Szeto@Sun.COM 		/* Pick a LUN number */
172010691STim.Szeto@Sun.COM 		lun_num = stmf_get_next_free_lun(ve_map, lun);
172110691STim.Szeto@Sun.COM 		if (lun_num > 0x3FFF)
172210691STim.Szeto@Sun.COM 			ret = STMF_NOT_SUPPORTED;
172310691STim.Szeto@Sun.COM 	} else {
172410691STim.Szeto@Sun.COM 		lun_num = (uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8);
172510691STim.Szeto@Sun.COM 		if (stmf_get_ent_from_map(ve_map, lun_num) != NULL) {
172610691STim.Szeto@Sun.COM 			*err_detail = STMF_IOCERR_LU_NUMBER_IN_USE;
172710691STim.Szeto@Sun.COM 			ret = STMF_LUN_TAKEN;
172810691STim.Szeto@Sun.COM 		}
172910691STim.Szeto@Sun.COM 	}
173010691STim.Szeto@Sun.COM 	stmf_destroy_ve_map(ve_map);
173110691STim.Szeto@Sun.COM 
173210691STim.Szeto@Sun.COM 	return (ret);
173310691STim.Szeto@Sun.COM }
173410691STim.Szeto@Sun.COM 
173510691STim.Szeto@Sun.COM int
stmf_validate_lun_ve(uint8_t * hgname,uint16_t hgname_size,uint8_t * tgname,uint16_t tgname_size,uint8_t * luNbr,uint32_t * err_detail)173610691STim.Szeto@Sun.COM stmf_validate_lun_ve(uint8_t *hgname, uint16_t hgname_size,
173710691STim.Szeto@Sun.COM 		uint8_t *tgname, uint16_t tgname_size,
173810691STim.Szeto@Sun.COM 		uint8_t *luNbr, uint32_t *err_detail)
173910691STim.Szeto@Sun.COM {
174010691STim.Szeto@Sun.COM 	stmf_id_data_t		*hg;
174110691STim.Szeto@Sun.COM 	stmf_id_data_t		*tg;
174210691STim.Szeto@Sun.COM 	stmf_status_t		ret;
174310691STim.Szeto@Sun.COM 
174410691STim.Szeto@Sun.COM 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
174510691STim.Szeto@Sun.COM 
174610691STim.Szeto@Sun.COM 	hg = stmf_lookup_id(&stmf_state.stmf_hg_list, hgname_size,
174710691STim.Szeto@Sun.COM 	    (uint8_t *)hgname);
174810691STim.Szeto@Sun.COM 	if (!hg) {
174910691STim.Szeto@Sun.COM 		*err_detail = STMF_IOCERR_INVALID_HG;
175010691STim.Szeto@Sun.COM 		return (ENOENT); /* could not find group */
175110691STim.Szeto@Sun.COM 	}
175210691STim.Szeto@Sun.COM 	tg = stmf_lookup_id(&stmf_state.stmf_tg_list, tgname_size,
175310691STim.Szeto@Sun.COM 	    (uint8_t *)tgname);
175410691STim.Szeto@Sun.COM 	if (!tg) {
175510691STim.Szeto@Sun.COM 		*err_detail = STMF_IOCERR_INVALID_TG;
175610691STim.Szeto@Sun.COM 		return (ENOENT); /* could not find group */
175710691STim.Szeto@Sun.COM 	}
175810691STim.Szeto@Sun.COM 	ret = stmf_validate_lun_view_entry(hg, tg, luNbr, err_detail);
175910691STim.Szeto@Sun.COM 
176010691STim.Szeto@Sun.COM 	if (ret == STMF_LUN_TAKEN) {
176110691STim.Szeto@Sun.COM 		return (EEXIST);
176210691STim.Szeto@Sun.COM 	} else if (ret == STMF_NOT_SUPPORTED) {
176310691STim.Szeto@Sun.COM 		return (E2BIG);
176410691STim.Szeto@Sun.COM 	} else if (ret != STMF_SUCCESS) {
176510691STim.Szeto@Sun.COM 		return (EINVAL);
176610691STim.Szeto@Sun.COM 	}
176710691STim.Szeto@Sun.COM 	return (0);
176810691STim.Szeto@Sun.COM }
1769