xref: /illumos-gate/usr/src/uts/common/io/comstar/stmf/lun_map.c (revision 8ad466288742ffe497149f668ec1c028def2c686)
1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte /*
224558d122SViswanathan Kannappan  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23fcf3ce44SJohn Forte  */
24fcf3ce44SJohn Forte 
25fcf3ce44SJohn Forte #include <sys/conf.h>
26fcf3ce44SJohn Forte #include <sys/file.h>
27fcf3ce44SJohn Forte #include <sys/ddi.h>
28fcf3ce44SJohn Forte #include <sys/sunddi.h>
29fcf3ce44SJohn Forte #include <sys/modctl.h>
30fcf3ce44SJohn Forte #include <sys/scsi/scsi.h>
31fcf3ce44SJohn Forte #include <sys/scsi/impl/scsi_reset_notify.h>
32fcf3ce44SJohn Forte #include <sys/disp.h>
33fcf3ce44SJohn Forte #include <sys/byteorder.h>
34fcf3ce44SJohn Forte #include <sys/atomic.h>
35fcf3ce44SJohn Forte 
364558d122SViswanathan Kannappan #include <sys/stmf.h>
374558d122SViswanathan Kannappan #include <sys/lpif.h>
384558d122SViswanathan Kannappan #include <sys/portif.h>
394558d122SViswanathan Kannappan #include <sys/stmf_ioctl.h>
404558d122SViswanathan Kannappan 
41fcf3ce44SJohn Forte #include "stmf_impl.h"
42fcf3ce44SJohn Forte #include "lun_map.h"
43fcf3ce44SJohn Forte #include "stmf_state.h"
44fcf3ce44SJohn Forte 
45fcf3ce44SJohn Forte void stmf_update_sessions_per_ve(stmf_view_entry_t *ve,
46fcf3ce44SJohn Forte 		stmf_lu_t *lu, int action);
47fcf3ce44SJohn Forte void stmf_add_lus_to_session_per_vemap(stmf_i_local_port_t *ilport,
48fcf3ce44SJohn Forte 		stmf_i_scsi_session_t *iss, stmf_lun_map_t *vemap);
49fcf3ce44SJohn Forte stmf_id_data_t *stmf_lookup_group_for_host(uint8_t *ident, uint16_t ident_size);
5061dfa509SRick McNeal static stmf_status_t stmf_add_ent_to_map(stmf_lun_map_t *sm, void *ent,
5161dfa509SRick McNeal     uint8_t *lun);
5261dfa509SRick McNeal static stmf_status_t stmf_remove_ent_from_map(stmf_lun_map_t *sm, uint8_t *lun);
53fcf3ce44SJohn Forte uint16_t stmf_get_next_free_lun(stmf_lun_map_t *sm, uint8_t *lun);
54fcf3ce44SJohn Forte stmf_status_t stmf_add_tg(uint8_t *tg_name, uint16_t tg_name_size,
55fcf3ce44SJohn Forte 		int allow_special, uint32_t *err_detail);
56fcf3ce44SJohn Forte stmf_status_t stmf_add_hg(uint8_t *hg_name, uint16_t hg_name_size,
57fcf3ce44SJohn Forte 		int allow_special, uint32_t *err_detail);
58fcf3ce44SJohn Forte stmf_i_local_port_t *stmf_targetident_to_ilport(uint8_t *target_ident,
59fcf3ce44SJohn Forte 		uint16_t ident_size);
60fcf3ce44SJohn Forte stmf_i_scsi_session_t *stmf_lookup_session_for_hostident(
61fcf3ce44SJohn Forte 		stmf_i_local_port_t *ilport, uint8_t *host_ident,
62fcf3ce44SJohn Forte 		uint16_t ident_size);
63fcf3ce44SJohn Forte stmf_i_lu_t *stmf_luident_to_ilu(uint8_t *lu_ident);
64fcf3ce44SJohn Forte stmf_lun_map_t *stmf_get_ve_map_per_ids(stmf_id_data_t *tgid,
65fcf3ce44SJohn Forte 		stmf_id_data_t *hgid);
66fcf3ce44SJohn Forte stmf_lun_map_t *stmf_duplicate_ve_map(stmf_lun_map_t *src);
67fcf3ce44SJohn Forte int stmf_merge_ve_map(stmf_lun_map_t *src, stmf_lun_map_t *dst,
68fcf3ce44SJohn Forte 		stmf_lun_map_t **pp_ret_map, stmf_merge_flags_t mf);
69fcf3ce44SJohn Forte void stmf_destroy_ve_map(stmf_lun_map_t *dst);
70fcf3ce44SJohn Forte void stmf_free_id(stmf_id_data_t *id);
71fcf3ce44SJohn Forte 
72fcf3ce44SJohn Forte 
73fcf3ce44SJohn Forte /*
74fcf3ce44SJohn Forte  * Init the view
75fcf3ce44SJohn Forte  */
76fcf3ce44SJohn Forte void
stmf_view_init()77fcf3ce44SJohn Forte stmf_view_init()
78fcf3ce44SJohn Forte {
79fcf3ce44SJohn Forte 	uint8_t grpname_forall = '*';
80fcf3ce44SJohn Forte 	(void) stmf_add_hg(&grpname_forall, 1, 1, NULL);
81fcf3ce44SJohn Forte 	(void) stmf_add_tg(&grpname_forall, 1, 1, NULL);
82fcf3ce44SJohn Forte }
83fcf3ce44SJohn Forte 
84fcf3ce44SJohn Forte /*
85fcf3ce44SJohn Forte  * Clear config database here
86fcf3ce44SJohn Forte  */
87fcf3ce44SJohn Forte void
stmf_view_clear_config()88fcf3ce44SJohn Forte stmf_view_clear_config()
89fcf3ce44SJohn Forte {
90fcf3ce44SJohn Forte 	stmf_id_data_t *idgrp, *idgrp_next, *idmemb, *idmemb_next;
91fcf3ce44SJohn Forte 	stmf_ver_tg_t *vtg, *vtg_next;
92fcf3ce44SJohn Forte 	stmf_ver_hg_t *vhg, *vhg_next;
93fcf3ce44SJohn Forte 	stmf_view_entry_t *ve, *ve_next;
94fcf3ce44SJohn Forte 	stmf_i_lu_t	*ilu;
95fcf3ce44SJohn Forte 	stmf_id_list_t	*idlist;
96fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
97fcf3ce44SJohn Forte 
98fcf3ce44SJohn Forte 	for (vtg = stmf_state.stmf_ver_tg_head; vtg; vtg = vtg_next) {
99fcf3ce44SJohn Forte 		for (vhg = vtg->vert_verh_list; vhg; vhg = vhg_next) {
100fcf3ce44SJohn Forte 			if (vhg->verh_ve_map.lm_nentries) {
101fcf3ce44SJohn Forte 				kmem_free(vhg->verh_ve_map.lm_plus,
102fcf3ce44SJohn Forte 				    vhg->verh_ve_map.lm_nentries *
103fcf3ce44SJohn Forte 				    sizeof (void *));
104fcf3ce44SJohn Forte 			}
105fcf3ce44SJohn Forte 			vhg_next = vhg->verh_next;
106fcf3ce44SJohn Forte 			kmem_free(vhg, sizeof (stmf_ver_hg_t));
107fcf3ce44SJohn Forte 		}
108fcf3ce44SJohn Forte 		vtg_next = vtg->vert_next;
109fcf3ce44SJohn Forte 		kmem_free(vtg, sizeof (stmf_ver_tg_t));
110fcf3ce44SJohn Forte 	}
111fcf3ce44SJohn Forte 	stmf_state.stmf_ver_tg_head = NULL;
112fcf3ce44SJohn Forte 
113fcf3ce44SJohn Forte 	if (stmf_state.stmf_luid_list.id_count) {
114fcf3ce44SJohn Forte 		/* clear the views for lus */
115fcf3ce44SJohn Forte 		for (idmemb = stmf_state.stmf_luid_list.idl_head;
116fcf3ce44SJohn Forte 		    idmemb; idmemb = idmemb_next) {
117fcf3ce44SJohn Forte 			for (ve = (stmf_view_entry_t *)idmemb->id_impl_specific;
118fcf3ce44SJohn Forte 			    ve; ve = ve_next) {
119fcf3ce44SJohn Forte 				ve_next = ve->ve_next;
120fcf3ce44SJohn Forte 				ve->ve_hg->id_refcnt--;
121fcf3ce44SJohn Forte 				ve->ve_tg->id_refcnt--;
122fcf3ce44SJohn Forte 				kmem_free(ve, sizeof (stmf_view_entry_t));
123fcf3ce44SJohn Forte 			}
124fcf3ce44SJohn Forte 			if (idmemb->id_pt_to_object) {
125fcf3ce44SJohn Forte 				ilu = (stmf_i_lu_t *)(idmemb->id_pt_to_object);
126fcf3ce44SJohn Forte 				ilu->ilu_luid = NULL;
127fcf3ce44SJohn Forte 			}
128fcf3ce44SJohn Forte 			idmemb_next = idmemb->id_next;
129fcf3ce44SJohn Forte 			stmf_free_id(idmemb);
130fcf3ce44SJohn Forte 		}
131fcf3ce44SJohn Forte 		stmf_state.stmf_luid_list.id_count = 0;
132fcf3ce44SJohn Forte 		stmf_state.stmf_luid_list.idl_head =
133fcf3ce44SJohn Forte 		    stmf_state.stmf_luid_list.idl_tail = NULL;
134fcf3ce44SJohn Forte 	}
135fcf3ce44SJohn Forte 
136fcf3ce44SJohn Forte 	if (stmf_state.stmf_hg_list.id_count) {
137fcf3ce44SJohn Forte 		/* free all the host group */
138fcf3ce44SJohn Forte 		for (idgrp = stmf_state.stmf_hg_list.idl_head;
139fcf3ce44SJohn Forte 		    idgrp; idgrp = idgrp_next) {
140fcf3ce44SJohn Forte 			idlist = (stmf_id_list_t *)(idgrp->id_impl_specific);
141fcf3ce44SJohn Forte 			if (idlist->id_count) {
142fcf3ce44SJohn Forte 				for (idmemb = idlist->idl_head; idmemb;
143fcf3ce44SJohn Forte 				    idmemb = idmemb_next) {
144fcf3ce44SJohn Forte 					idmemb_next = idmemb->id_next;
145fcf3ce44SJohn Forte 					stmf_free_id(idmemb);
146fcf3ce44SJohn Forte 				}
147fcf3ce44SJohn Forte 			}
148fcf3ce44SJohn Forte 			idgrp_next = idgrp->id_next;
149fcf3ce44SJohn Forte 			stmf_free_id(idgrp);
150fcf3ce44SJohn Forte 		}
151fcf3ce44SJohn Forte 		stmf_state.stmf_hg_list.id_count = 0;
152fcf3ce44SJohn Forte 		stmf_state.stmf_hg_list.idl_head =
153fcf3ce44SJohn Forte 		    stmf_state.stmf_hg_list.idl_tail = NULL;
154fcf3ce44SJohn Forte 	}
155fcf3ce44SJohn Forte 	if (stmf_state.stmf_tg_list.id_count) {
156fcf3ce44SJohn Forte 		/* free all the target group */
157fcf3ce44SJohn Forte 		for (idgrp = stmf_state.stmf_tg_list.idl_head;
158fcf3ce44SJohn Forte 		    idgrp; idgrp = idgrp_next) {
159fcf3ce44SJohn Forte 			idlist = (stmf_id_list_t *)(idgrp->id_impl_specific);
160fcf3ce44SJohn Forte 			if (idlist->id_count) {
161fcf3ce44SJohn Forte 				for (idmemb = idlist->idl_head; idmemb;
162fcf3ce44SJohn Forte 				    idmemb = idmemb_next) {
163fcf3ce44SJohn Forte 					idmemb_next = idmemb->id_next;
164fcf3ce44SJohn Forte 					stmf_free_id(idmemb);
165fcf3ce44SJohn Forte 				}
166fcf3ce44SJohn Forte 			}
167fcf3ce44SJohn Forte 			idgrp_next = idgrp->id_next;
168fcf3ce44SJohn Forte 			stmf_free_id(idgrp);
169fcf3ce44SJohn Forte 		}
170fcf3ce44SJohn Forte 		stmf_state.stmf_tg_list.id_count = 0;
171fcf3ce44SJohn Forte 		stmf_state.stmf_tg_list.idl_head =
172fcf3ce44SJohn Forte 		    stmf_state.stmf_tg_list.idl_tail = NULL;
173fcf3ce44SJohn Forte 	}
174fcf3ce44SJohn Forte 
175fcf3ce44SJohn Forte 	for (ilport = stmf_state.stmf_ilportlist; ilport;
176fcf3ce44SJohn Forte 	    ilport = ilport->ilport_next) {
177fcf3ce44SJohn Forte 		ilport->ilport_tg = NULL;
178fcf3ce44SJohn Forte 	}
179fcf3ce44SJohn Forte }
180fcf3ce44SJohn Forte 
181fcf3ce44SJohn Forte /*
182fcf3ce44SJohn Forte  * Create luns map for session based on the view
18361dfa509SRick McNeal  * iss_lockp is held
184fcf3ce44SJohn Forte  */
185fcf3ce44SJohn Forte stmf_status_t
stmf_session_create_lun_map(stmf_i_local_port_t * ilport,stmf_i_scsi_session_t * iss)186fcf3ce44SJohn Forte stmf_session_create_lun_map(stmf_i_local_port_t *ilport,
187fcf3ce44SJohn Forte     stmf_i_scsi_session_t *iss)
188fcf3ce44SJohn Forte {
189fcf3ce44SJohn Forte 	stmf_id_data_t *tg;
190fcf3ce44SJohn Forte 	stmf_id_data_t *hg;
191fcf3ce44SJohn Forte 	stmf_ver_tg_t	*vertg;
192fcf3ce44SJohn Forte 	char *phg_data, *ptg_data;
193fcf3ce44SJohn Forte 	stmf_ver_hg_t	*verhg;
194fcf3ce44SJohn Forte 	stmf_lun_map_t	*ve_map;
195fcf3ce44SJohn Forte 
196780c822cStim szeto 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
197780c822cStim szeto 
198fcf3ce44SJohn Forte 	tg = ilport->ilport_tg;
199fcf3ce44SJohn Forte 	hg = stmf_lookup_group_for_host(iss->iss_ss->ss_rport_id->ident,
200fcf3ce44SJohn Forte 	    iss->iss_ss->ss_rport_id->ident_length);
201fcf3ce44SJohn Forte 	iss->iss_hg = hg;
202fcf3ce44SJohn Forte 
203fcf3ce44SJohn Forte 	/*
204fcf3ce44SJohn Forte 	 * get the view entry map,
205fcf3ce44SJohn Forte 	 * take all host/target group into consideration
206fcf3ce44SJohn Forte 	 */
207fcf3ce44SJohn Forte 	ve_map = stmf_duplicate_ve_map(0);
208fcf3ce44SJohn Forte 	for (vertg = stmf_state.stmf_ver_tg_head; vertg != NULL;
209fcf3ce44SJohn Forte 	    vertg = vertg->vert_next) {
210fcf3ce44SJohn Forte 		ptg_data = (char *)vertg->vert_tg_ref->id_data;
211fcf3ce44SJohn Forte 		if ((ptg_data[0] != '*') && (!tg ||
212fcf3ce44SJohn Forte 		    ((tg->id_data[0] != '*') &&
213fcf3ce44SJohn Forte 		    (vertg->vert_tg_ref != tg)))) {
214fcf3ce44SJohn Forte 			continue;
215fcf3ce44SJohn Forte 		}
216fcf3ce44SJohn Forte 		for (verhg = vertg->vert_verh_list; verhg != NULL;
217fcf3ce44SJohn Forte 		    verhg = verhg->verh_next) {
218fcf3ce44SJohn Forte 			phg_data = (char *)verhg->verh_hg_ref->id_data;
219fcf3ce44SJohn Forte 			if ((phg_data[0] != '*') && (!hg ||
220fcf3ce44SJohn Forte 			    ((hg->id_data[0] != '*') &&
221fcf3ce44SJohn Forte 			    (verhg->verh_hg_ref != hg)))) {
222fcf3ce44SJohn Forte 				continue;
223fcf3ce44SJohn Forte 			}
224fcf3ce44SJohn Forte 			(void) stmf_merge_ve_map(&verhg->verh_ve_map, ve_map,
225fcf3ce44SJohn Forte 			    &ve_map, 0);
226fcf3ce44SJohn Forte 		}
227fcf3ce44SJohn Forte 	}
228fcf3ce44SJohn Forte 
229fcf3ce44SJohn Forte 
230fcf3ce44SJohn Forte 	if (ve_map->lm_nluns) {
231fcf3ce44SJohn Forte 		stmf_add_lus_to_session_per_vemap(ilport, iss, ve_map);
232fcf3ce44SJohn Forte 	}
233fcf3ce44SJohn Forte 	/* not configured, cannot access any luns for now */
234fcf3ce44SJohn Forte 
235fcf3ce44SJohn Forte 	stmf_destroy_ve_map(ve_map);
236fcf3ce44SJohn Forte 
237fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
238fcf3ce44SJohn Forte }
239fcf3ce44SJohn Forte 
240fcf3ce44SJohn Forte /*
241fcf3ce44SJohn Forte  * Expects the session lock to be held.
24261dfa509SRick McNeal  * iss_lockp is held
243fcf3ce44SJohn Forte  */
244fcf3ce44SJohn Forte stmf_xfer_data_t *
stmf_session_prepare_report_lun_data(stmf_lun_map_t * sm)245fcf3ce44SJohn Forte stmf_session_prepare_report_lun_data(stmf_lun_map_t *sm)
246fcf3ce44SJohn Forte {
247fcf3ce44SJohn Forte 	stmf_xfer_data_t *xd;
248fcf3ce44SJohn Forte 	uint16_t nluns, ent;
249fcf3ce44SJohn Forte 	uint32_t alloc_size, data_size;
250*8ad46628SToomas Soome 	uchar_t *buf;
251fcf3ce44SJohn Forte 	int i;
252fcf3ce44SJohn Forte 
253fcf3ce44SJohn Forte 	nluns = sm->lm_nluns;
254fcf3ce44SJohn Forte 
255fcf3ce44SJohn Forte 	data_size = 8 + (((uint32_t)nluns) << 3);
256fcf3ce44SJohn Forte 	if (nluns == 0) {
257fcf3ce44SJohn Forte 		data_size += 8;
258fcf3ce44SJohn Forte 	}
259fcf3ce44SJohn Forte 	alloc_size = data_size + sizeof (stmf_xfer_data_t) - 4;
260fcf3ce44SJohn Forte 
261fcf3ce44SJohn Forte 	xd = (stmf_xfer_data_t *)kmem_zalloc(alloc_size, KM_NOSLEEP);
262fcf3ce44SJohn Forte 
263fcf3ce44SJohn Forte 	if (xd == NULL)
264fcf3ce44SJohn Forte 		return (NULL);
265fcf3ce44SJohn Forte 
266fcf3ce44SJohn Forte 	xd->alloc_size = alloc_size;
267fcf3ce44SJohn Forte 	xd->size_left = data_size;
268fcf3ce44SJohn Forte 
269fcf3ce44SJohn Forte 	*((uint32_t *)xd->buf) = BE_32(data_size - 8);
270fcf3ce44SJohn Forte 	if (nluns == 0) {
271fcf3ce44SJohn Forte 		return (xd);
272fcf3ce44SJohn Forte 	}
273fcf3ce44SJohn Forte 
274fcf3ce44SJohn Forte 	ent = 0;
275fcf3ce44SJohn Forte 
276*8ad46628SToomas Soome 	buf = &(xd->buf[0]);
277fcf3ce44SJohn Forte 	for (i = 0; ((i < sm->lm_nentries) && (ent < nluns)); i++) {
278fcf3ce44SJohn Forte 		if (sm->lm_plus[i] == NULL)
279fcf3ce44SJohn Forte 			continue;
280fcf3ce44SJohn Forte 		/* Fill in the entry */
281*8ad46628SToomas Soome 		buf[8 + (ent << 3) + 1] = (uchar_t)i;
282*8ad46628SToomas Soome 		buf[8 + (ent << 3) + 0] = ((uchar_t)(i >> 8));
283fcf3ce44SJohn Forte 		ent++;
284fcf3ce44SJohn Forte 	}
285fcf3ce44SJohn Forte 
286fcf3ce44SJohn Forte 	ASSERT(ent == nluns);
287fcf3ce44SJohn Forte 
288fcf3ce44SJohn Forte 	return (xd);
289fcf3ce44SJohn Forte }
290fcf3ce44SJohn Forte 
291fcf3ce44SJohn Forte /*
292fcf3ce44SJohn Forte  * Add a lu to active sessions based on LUN inventory.
293fcf3ce44SJohn Forte  * Only invoked when the lu is onlined
294fcf3ce44SJohn Forte  */
295fcf3ce44SJohn Forte void
stmf_add_lu_to_active_sessions(stmf_lu_t * lu)296fcf3ce44SJohn Forte stmf_add_lu_to_active_sessions(stmf_lu_t *lu)
297fcf3ce44SJohn Forte {
298fcf3ce44SJohn Forte 	stmf_id_data_t *luid;
299fcf3ce44SJohn Forte 	stmf_view_entry_t	*ve;
300fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
301fcf3ce44SJohn Forte 
302fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
303fcf3ce44SJohn Forte 	ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
304fcf3ce44SJohn Forte 	ASSERT(ilu->ilu_state == STMF_STATE_ONLINE);
305fcf3ce44SJohn Forte 
306fcf3ce44SJohn Forte 	luid = ((stmf_i_lu_t *)lu->lu_stmf_private)->ilu_luid;
307fcf3ce44SJohn Forte 
308fcf3ce44SJohn Forte 	if (!luid) {
309fcf3ce44SJohn Forte 		/* we did not configure view for this lun, so just return */
310fcf3ce44SJohn Forte 		return;
311fcf3ce44SJohn Forte 	}
312fcf3ce44SJohn Forte 
313fcf3ce44SJohn Forte 	for (ve = (stmf_view_entry_t *)luid->id_impl_specific;
314fcf3ce44SJohn Forte 	    ve; ve = ve->ve_next) {
315fcf3ce44SJohn Forte 		stmf_update_sessions_per_ve(ve, lu, 1);
316fcf3ce44SJohn Forte 	}
317fcf3ce44SJohn Forte }
318fcf3ce44SJohn Forte /*
319fcf3ce44SJohn Forte  * Unmap a lun from all sessions
320fcf3ce44SJohn Forte  */
321fcf3ce44SJohn Forte void
stmf_session_lu_unmapall(stmf_lu_t * lu)322fcf3ce44SJohn Forte stmf_session_lu_unmapall(stmf_lu_t *lu)
323fcf3ce44SJohn Forte {
324fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
325fcf3ce44SJohn Forte 	stmf_id_data_t *luid;
326fcf3ce44SJohn Forte 	stmf_view_entry_t *ve;
327fcf3ce44SJohn Forte 
328fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
329fcf3ce44SJohn Forte 
330fcf3ce44SJohn Forte 	ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
331fcf3ce44SJohn Forte 
332fcf3ce44SJohn Forte 	if (ilu->ilu_ref_cnt == 0)
333fcf3ce44SJohn Forte 		return;
334fcf3ce44SJohn Forte 
335fcf3ce44SJohn Forte 	luid = ((stmf_i_lu_t *)lu->lu_stmf_private)->ilu_luid;
336fcf3ce44SJohn Forte 	if (!luid) {
337fcf3ce44SJohn Forte 		/*
338fcf3ce44SJohn Forte 		 * we did not configure view for this lun, this should be
339fcf3ce44SJohn Forte 		 * an error
340fcf3ce44SJohn Forte 		 */
341fcf3ce44SJohn Forte 		return;
342fcf3ce44SJohn Forte 	}
343fcf3ce44SJohn Forte 
344fcf3ce44SJohn Forte 	for (ve = (stmf_view_entry_t *)luid->id_impl_specific;
345fcf3ce44SJohn Forte 	    ve; ve = ve->ve_next) {
346fcf3ce44SJohn Forte 		stmf_update_sessions_per_ve(ve, lu, 0);
347fcf3ce44SJohn Forte 		if (ilu->ilu_ref_cnt == 0)
348fcf3ce44SJohn Forte 			break;
349fcf3ce44SJohn Forte 	}
350fcf3ce44SJohn Forte }
351fcf3ce44SJohn Forte /*
352fcf3ce44SJohn Forte  * add lu to a session, stmf_lock is already held
35361dfa509SRick McNeal  * iss_lockp/ilport_lock already held
354fcf3ce44SJohn Forte  */
35561dfa509SRick McNeal static 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)356fcf3ce44SJohn Forte stmf_add_lu_to_session(stmf_i_local_port_t *ilport,
357fcf3ce44SJohn Forte     stmf_i_scsi_session_t *iss,
358fcf3ce44SJohn Forte     stmf_lu_t *lu,
359fcf3ce44SJohn Forte     uint8_t *lu_nbr)
360fcf3ce44SJohn Forte {
361fcf3ce44SJohn Forte 	stmf_lun_map_t *sm = iss->iss_sm;
362fcf3ce44SJohn Forte 	stmf_status_t ret;
363fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
364fcf3ce44SJohn Forte 	stmf_lun_map_ent_t *lun_map_ent;
365fcf3ce44SJohn Forte 	uint32_t new_flags = 0;
366fcf3ce44SJohn Forte 	uint16_t luNbr =
367fcf3ce44SJohn Forte 	    ((uint16_t)lu_nbr[1] | (((uint16_t)(lu_nbr[0] & 0x3F)) << 8));
368fcf3ce44SJohn Forte 
369fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
370fcf3ce44SJohn Forte 	ASSERT(!stmf_get_ent_from_map(sm, luNbr));
371fcf3ce44SJohn Forte 
372fcf3ce44SJohn Forte 	if ((sm->lm_nluns == 0) &&
373fcf3ce44SJohn Forte 	    ((iss->iss_flags & ISS_BEING_CREATED) == 0)) {
374fcf3ce44SJohn Forte 		new_flags = ISS_GOT_INITIAL_LUNS;
375fcf3ce44SJohn Forte 		atomic_or_32(&ilport->ilport_flags, ILPORT_SS_GOT_INITIAL_LUNS);
376fcf3ce44SJohn Forte 		stmf_state.stmf_process_initial_luns = 1;
377fcf3ce44SJohn Forte 	}
378fcf3ce44SJohn Forte 
379fcf3ce44SJohn Forte 	lun_map_ent = (stmf_lun_map_ent_t *)
380fcf3ce44SJohn Forte 	    kmem_zalloc(sizeof (stmf_lun_map_ent_t), KM_SLEEP);
381fcf3ce44SJohn Forte 	lun_map_ent->ent_lu = lu;
382fcf3ce44SJohn Forte 	ret = stmf_add_ent_to_map(sm, (void *)lun_map_ent, lu_nbr);
383fcf3ce44SJohn Forte 	ASSERT(ret == STMF_SUCCESS);
3841a5e258fSJosef 'Jeff' Sipek 	atomic_inc_32(&ilu->ilu_ref_cnt);
38545039663SJohn Forte 	/*
38645039663SJohn Forte 	 * do not set lun inventory flag for standby port
38745039663SJohn Forte 	 * as this would be handled from peer
38845039663SJohn Forte 	 */
38945039663SJohn Forte 	if (ilport->ilport_standby == 0) {
390fcf3ce44SJohn Forte 		new_flags |= ISS_LUN_INVENTORY_CHANGED;
39145039663SJohn Forte 	}
392fcf3ce44SJohn Forte 	atomic_or_32(&iss->iss_flags, new_flags);
393fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
394fcf3ce44SJohn Forte }
395fcf3ce44SJohn Forte 
396fcf3ce44SJohn Forte /*
397fcf3ce44SJohn Forte  * remvoe lu from a session, stmf_lock is already held
39861dfa509SRick McNeal  * iss_lockp held
399fcf3ce44SJohn Forte  */
40061dfa509SRick McNeal static void
stmf_remove_lu_from_session(stmf_i_scsi_session_t * iss,stmf_lu_t * lu,uint8_t * lu_nbr)40161dfa509SRick McNeal stmf_remove_lu_from_session(stmf_i_scsi_session_t *iss,
40261dfa509SRick McNeal     stmf_lu_t *lu, uint8_t *lu_nbr)
403fcf3ce44SJohn Forte {
404fcf3ce44SJohn Forte 	stmf_status_t ret;
405fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
406fcf3ce44SJohn Forte 	stmf_lun_map_t *sm = iss->iss_sm;
407fcf3ce44SJohn Forte 	stmf_lun_map_ent_t *lun_map_ent;
408fcf3ce44SJohn Forte 	uint16_t luNbr =
409fcf3ce44SJohn Forte 	    ((uint16_t)lu_nbr[1] | (((uint16_t)(lu_nbr[0] & 0x3F)) << 8));
410fcf3ce44SJohn Forte 
411fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
412fcf3ce44SJohn Forte 	lun_map_ent = stmf_get_ent_from_map(sm, luNbr);
41361dfa509SRick McNeal 	ASSERT(lun_map_ent->ent_lu == lu);
41461dfa509SRick McNeal 	if (lun_map_ent == NULL) {
41561dfa509SRick McNeal 		return;
41661dfa509SRick McNeal 	}
417fcf3ce44SJohn Forte 
418fcf3ce44SJohn Forte 	ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
419fcf3ce44SJohn Forte 
420fcf3ce44SJohn Forte 	ret = stmf_remove_ent_from_map(sm, lu_nbr);
421fcf3ce44SJohn Forte 	ASSERT(ret == STMF_SUCCESS);
4221a5e258fSJosef 'Jeff' Sipek 	atomic_dec_32(&ilu->ilu_ref_cnt);
423fcf3ce44SJohn Forte 	iss->iss_flags |= ISS_LUN_INVENTORY_CHANGED;
424fcf3ce44SJohn Forte 	if (lun_map_ent->ent_itl_datap) {
425fcf3ce44SJohn Forte 		stmf_do_itl_dereg(lu, lun_map_ent->ent_itl_datap,
426fcf3ce44SJohn Forte 		    STMF_ITL_REASON_USER_REQUEST);
427fcf3ce44SJohn Forte 	}
428fcf3ce44SJohn Forte 	kmem_free((void *)lun_map_ent, sizeof (stmf_lun_map_ent_t));
429fcf3ce44SJohn Forte }
430fcf3ce44SJohn Forte 
431fcf3ce44SJohn Forte /*
432fcf3ce44SJohn Forte  * add or remove lu from all related sessions based on view entry,
433fcf3ce44SJohn Forte  * action is 0 for delete, 1 for add
434fcf3ce44SJohn Forte  */
435fcf3ce44SJohn Forte void
stmf_update_sessions_per_ve(stmf_view_entry_t * ve,stmf_lu_t * lu,int action)436fcf3ce44SJohn Forte stmf_update_sessions_per_ve(stmf_view_entry_t *ve,
437fcf3ce44SJohn Forte     stmf_lu_t *lu, int action)
438fcf3ce44SJohn Forte {
439fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu_tmp;
440fcf3ce44SJohn Forte 	stmf_lu_t *lu_to_add;
441fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
442fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss;
443fcf3ce44SJohn Forte 	stmf_id_list_t	*hostlist;
444fcf3ce44SJohn Forte 	stmf_id_list_t	*targetlist;
445fcf3ce44SJohn Forte 	int all_hg = 0, all_tg = 0;
446fcf3ce44SJohn Forte 
447fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
448fcf3ce44SJohn Forte 
449fcf3ce44SJohn Forte 	if (!lu) {
450fcf3ce44SJohn Forte 		ilu_tmp = (stmf_i_lu_t *)ve->ve_luid->id_pt_to_object;
451fcf3ce44SJohn Forte 		if (!ilu_tmp)
452fcf3ce44SJohn Forte 			return;
453fcf3ce44SJohn Forte 		lu_to_add = ilu_tmp->ilu_lu;
454fcf3ce44SJohn Forte 	} else {
455fcf3ce44SJohn Forte 		lu_to_add = lu;
456fcf3ce44SJohn Forte 		ilu_tmp = (stmf_i_lu_t *)lu->lu_stmf_private;
457fcf3ce44SJohn Forte 	}
458fcf3ce44SJohn Forte 
459fcf3ce44SJohn Forte 	if (ve->ve_hg->id_data[0] == '*')
460fcf3ce44SJohn Forte 		all_hg = 1;
461fcf3ce44SJohn Forte 	if (ve->ve_tg->id_data[0] == '*')
462fcf3ce44SJohn Forte 		all_tg = 1;
463fcf3ce44SJohn Forte 	hostlist = (stmf_id_list_t *)ve->ve_hg->id_impl_specific;
464fcf3ce44SJohn Forte 	targetlist = (stmf_id_list_t *)ve->ve_tg->id_impl_specific;
465fcf3ce44SJohn Forte 
466fcf3ce44SJohn Forte 	if ((!all_hg && !hostlist->idl_head) ||
467fcf3ce44SJohn Forte 	    (!all_tg && !targetlist->idl_head))
468fcf3ce44SJohn Forte 		/* No sessions to be updated */
469fcf3ce44SJohn Forte 		return;
470fcf3ce44SJohn Forte 
471fcf3ce44SJohn Forte 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
472fcf3ce44SJohn Forte 	    ilport = ilport->ilport_next) {
473fcf3ce44SJohn Forte 		if (!all_tg && ilport->ilport_tg != ve->ve_tg)
474fcf3ce44SJohn Forte 			continue;
475fcf3ce44SJohn Forte 		/* This ilport belongs to the target group */
476fcf3ce44SJohn Forte 		rw_enter(&ilport->ilport_lock, RW_WRITER);
477fcf3ce44SJohn Forte 		for (iss = ilport->ilport_ss_list; iss != NULL;
478fcf3ce44SJohn Forte 		    iss = iss->iss_next) {
479fcf3ce44SJohn Forte 			if (!all_hg && iss->iss_hg != ve->ve_hg)
480fcf3ce44SJohn Forte 				continue;
481fcf3ce44SJohn Forte 			/* This host belongs to the host group */
482fcf3ce44SJohn Forte 			if (action == 0) { /* to remove */
48361dfa509SRick McNeal 				stmf_remove_lu_from_session(iss, lu_to_add,
48461dfa509SRick McNeal 				    ve->ve_lun);
485fcf3ce44SJohn Forte 				if (ilu_tmp->ilu_ref_cnt == 0) {
486fcf3ce44SJohn Forte 					rw_exit(&ilport->ilport_lock);
487fcf3ce44SJohn Forte 					return;
488fcf3ce44SJohn Forte 				}
489fcf3ce44SJohn Forte 			} else {
490fcf3ce44SJohn Forte 				(void) stmf_add_lu_to_session(ilport, iss,
491fcf3ce44SJohn Forte 				    lu_to_add, ve->ve_lun);
492fcf3ce44SJohn Forte 			}
493fcf3ce44SJohn Forte 		}
494fcf3ce44SJohn Forte 		rw_exit(&ilport->ilport_lock);
495fcf3ce44SJohn Forte 	}
496fcf3ce44SJohn Forte }
497fcf3ce44SJohn Forte 
498fcf3ce44SJohn Forte /*
499fcf3ce44SJohn Forte  * add luns in view entry map to a session,
500fcf3ce44SJohn Forte  * and stmf_lock is already held
501fcf3ce44SJohn Forte  */
502fcf3ce44SJohn Forte 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)503fcf3ce44SJohn Forte stmf_add_lus_to_session_per_vemap(stmf_i_local_port_t *ilport,
504fcf3ce44SJohn Forte     stmf_i_scsi_session_t *iss,
505fcf3ce44SJohn Forte     stmf_lun_map_t *vemap)
506fcf3ce44SJohn Forte {
507fcf3ce44SJohn Forte 	stmf_lu_t *lu;
508fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
509fcf3ce44SJohn Forte 	stmf_view_entry_t *ve;
510fcf3ce44SJohn Forte 	uint32_t	i;
511fcf3ce44SJohn Forte 
512fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
513fcf3ce44SJohn Forte 	for (i = 0; i < vemap->lm_nentries; i++) {
514fcf3ce44SJohn Forte 		ve = (stmf_view_entry_t *)vemap->lm_plus[i];
515fcf3ce44SJohn Forte 		if (!ve)
516fcf3ce44SJohn Forte 			continue;
517fcf3ce44SJohn Forte 		ilu = (stmf_i_lu_t *)ve->ve_luid->id_pt_to_object;
518fcf3ce44SJohn Forte 		if (ilu && ilu->ilu_state == STMF_STATE_ONLINE) {
519fcf3ce44SJohn Forte 			lu = ilu->ilu_lu;
520fcf3ce44SJohn Forte 			(void) stmf_add_lu_to_session(ilport, iss, lu,
521fcf3ce44SJohn Forte 			    ve->ve_lun);
522fcf3ce44SJohn Forte 		}
523fcf3ce44SJohn Forte 	}
524fcf3ce44SJohn Forte }
52561dfa509SRick McNeal /*
52661dfa509SRick McNeal  * remove luns in view entry map from a session
52761dfa509SRick McNeal  * iss_lockp held
52861dfa509SRick McNeal  */
529fcf3ce44SJohn Forte void
stmf_remove_lus_from_session_per_vemap(stmf_i_scsi_session_t * iss,stmf_lun_map_t * vemap)53061dfa509SRick McNeal stmf_remove_lus_from_session_per_vemap(stmf_i_scsi_session_t *iss,
531fcf3ce44SJohn Forte     stmf_lun_map_t *vemap)
532fcf3ce44SJohn Forte {
533fcf3ce44SJohn Forte 	stmf_lu_t *lu;
534fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
535fcf3ce44SJohn Forte 	stmf_view_entry_t *ve;
536fcf3ce44SJohn Forte 	uint32_t i;
537fcf3ce44SJohn Forte 
538fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
539fcf3ce44SJohn Forte 
540fcf3ce44SJohn Forte 	for (i = 0; i < vemap->lm_nentries; i++) {
541fcf3ce44SJohn Forte 		ve = (stmf_view_entry_t *)vemap->lm_plus[i];
542fcf3ce44SJohn Forte 		if (!ve)
543fcf3ce44SJohn Forte 			continue;
544fcf3ce44SJohn Forte 		ilu = (stmf_i_lu_t *)ve->ve_luid->id_pt_to_object;
545fcf3ce44SJohn Forte 		if (ilu && ilu->ilu_state == STMF_STATE_ONLINE) {
546fcf3ce44SJohn Forte 			lu = ilu->ilu_lu;
54761dfa509SRick McNeal 			stmf_remove_lu_from_session(iss, lu, ve->ve_lun);
548fcf3ce44SJohn Forte 		}
549fcf3ce44SJohn Forte 	}
550fcf3ce44SJohn Forte }
551fcf3ce44SJohn Forte 
552fcf3ce44SJohn Forte stmf_id_data_t *
stmf_alloc_id(uint16_t id_size,uint16_t type,uint8_t * id_data,uint32_t additional_size)553fcf3ce44SJohn Forte stmf_alloc_id(uint16_t id_size, uint16_t type, uint8_t *id_data,
554fcf3ce44SJohn Forte     uint32_t additional_size)
555fcf3ce44SJohn Forte {
556fcf3ce44SJohn Forte 	stmf_id_data_t *id;
557fcf3ce44SJohn Forte 	int struct_size, total_size, real_id_size;
558fcf3ce44SJohn Forte 
559fcf3ce44SJohn Forte 	real_id_size = ((uint32_t)id_size + 7) & (~7);
560fcf3ce44SJohn Forte 	struct_size = (sizeof (*id) + 7) & (~7);
561fcf3ce44SJohn Forte 	total_size = ((additional_size + 7) & (~7)) + struct_size +
562fcf3ce44SJohn Forte 	    real_id_size;
563fcf3ce44SJohn Forte 	id = (stmf_id_data_t *)kmem_zalloc(total_size, KM_SLEEP);
564fcf3ce44SJohn Forte 	id->id_type = type;
565fcf3ce44SJohn Forte 	id->id_data_size = id_size;
566fcf3ce44SJohn Forte 	id->id_data = ((uint8_t *)id) + struct_size;
567fcf3ce44SJohn Forte 	id->id_total_alloc_size = total_size;
568fcf3ce44SJohn Forte 	if (additional_size) {
569fcf3ce44SJohn Forte 		id->id_impl_specific = ((uint8_t *)id) + struct_size +
570fcf3ce44SJohn Forte 		    real_id_size;
571fcf3ce44SJohn Forte 	}
572fcf3ce44SJohn Forte 	bcopy(id_data, id->id_data, id_size);
573fcf3ce44SJohn Forte 
574fcf3ce44SJohn Forte 	return (id);
575fcf3ce44SJohn Forte }
576fcf3ce44SJohn Forte 
577fcf3ce44SJohn Forte void
stmf_free_id(stmf_id_data_t * id)578fcf3ce44SJohn Forte stmf_free_id(stmf_id_data_t *id)
579fcf3ce44SJohn Forte {
580fcf3ce44SJohn Forte 	kmem_free(id, id->id_total_alloc_size);
581fcf3ce44SJohn Forte }
582fcf3ce44SJohn Forte 
583fcf3ce44SJohn Forte 
584fcf3ce44SJohn Forte stmf_id_data_t *
stmf_lookup_id(stmf_id_list_t * idlist,uint16_t id_size,uint8_t * data)585fcf3ce44SJohn Forte stmf_lookup_id(stmf_id_list_t *idlist, uint16_t id_size, uint8_t *data)
586fcf3ce44SJohn Forte {
587fcf3ce44SJohn Forte 	stmf_id_data_t *id;
588fcf3ce44SJohn Forte 
589fcf3ce44SJohn Forte 	for (id = idlist->idl_head; id != NULL; id = id->id_next) {
590fcf3ce44SJohn Forte 		if ((id->id_data_size == id_size) &&
591fcf3ce44SJohn Forte 		    (bcmp(id->id_data, data, id_size) == 0)) {
592fcf3ce44SJohn Forte 			return (id);
593fcf3ce44SJohn Forte 		}
594fcf3ce44SJohn Forte 	}
595fcf3ce44SJohn Forte 
596fcf3ce44SJohn Forte 	return (NULL);
597fcf3ce44SJohn Forte }
598fcf3ce44SJohn Forte /* Return the target group which a target belong to */
599fcf3ce44SJohn Forte stmf_id_data_t *
stmf_lookup_group_for_target(uint8_t * ident,uint16_t ident_size)600fcf3ce44SJohn Forte stmf_lookup_group_for_target(uint8_t *ident, uint16_t ident_size)
601fcf3ce44SJohn Forte {
602fcf3ce44SJohn Forte 	stmf_id_data_t *tgid;
603fcf3ce44SJohn Forte 	stmf_id_data_t *target;
604fcf3ce44SJohn Forte 
605fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
606fcf3ce44SJohn Forte 
607fcf3ce44SJohn Forte 	for (tgid = stmf_state.stmf_tg_list.idl_head; tgid;
608fcf3ce44SJohn Forte 	    tgid = tgid->id_next) {
609fcf3ce44SJohn Forte 		target = stmf_lookup_id(
610fcf3ce44SJohn Forte 		    (stmf_id_list_t *)tgid->id_impl_specific,
611fcf3ce44SJohn Forte 		    ident_size, ident);
612fcf3ce44SJohn Forte 		if (target)
613fcf3ce44SJohn Forte 			return (tgid);
614fcf3ce44SJohn Forte 	}
615fcf3ce44SJohn Forte 	return (NULL);
616fcf3ce44SJohn Forte }
617fcf3ce44SJohn Forte /* Return the host group which a host belong to */
618fcf3ce44SJohn Forte stmf_id_data_t *
stmf_lookup_group_for_host(uint8_t * ident,uint16_t ident_size)619fcf3ce44SJohn Forte stmf_lookup_group_for_host(uint8_t *ident, uint16_t ident_size)
620fcf3ce44SJohn Forte {
621fcf3ce44SJohn Forte 	stmf_id_data_t *hgid;
622fcf3ce44SJohn Forte 	stmf_id_data_t *host;
623fcf3ce44SJohn Forte 
624fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
625fcf3ce44SJohn Forte 
626fcf3ce44SJohn Forte 	for (hgid = stmf_state.stmf_hg_list.idl_head; hgid;
627fcf3ce44SJohn Forte 	    hgid = hgid->id_next) {
628fcf3ce44SJohn Forte 		host = stmf_lookup_id(
629fcf3ce44SJohn Forte 		    (stmf_id_list_t *)hgid->id_impl_specific,
630fcf3ce44SJohn Forte 		    ident_size, ident);
631fcf3ce44SJohn Forte 		if (host)
632fcf3ce44SJohn Forte 			return (hgid);
633fcf3ce44SJohn Forte 	}
634fcf3ce44SJohn Forte 	return (NULL);
635fcf3ce44SJohn Forte }
636fcf3ce44SJohn Forte 
637fcf3ce44SJohn Forte void
stmf_append_id(stmf_id_list_t * idlist,stmf_id_data_t * id)638fcf3ce44SJohn Forte stmf_append_id(stmf_id_list_t *idlist, stmf_id_data_t *id)
639fcf3ce44SJohn Forte {
640fcf3ce44SJohn Forte 	id->id_next = NULL;
641fcf3ce44SJohn Forte 
642fcf3ce44SJohn Forte 	if ((id->id_prev = idlist->idl_tail) == NULL) {
643fcf3ce44SJohn Forte 		idlist->idl_head = idlist->idl_tail = id;
644fcf3ce44SJohn Forte 	} else {
645fcf3ce44SJohn Forte 		idlist->idl_tail->id_next = id;
646fcf3ce44SJohn Forte 		idlist->idl_tail = id;
647fcf3ce44SJohn Forte 	}
6481a5e258fSJosef 'Jeff' Sipek 	atomic_inc_32(&idlist->id_count);
649fcf3ce44SJohn Forte }
650fcf3ce44SJohn Forte 
651fcf3ce44SJohn Forte void
stmf_remove_id(stmf_id_list_t * idlist,stmf_id_data_t * id)652fcf3ce44SJohn Forte stmf_remove_id(stmf_id_list_t *idlist, stmf_id_data_t *id)
653fcf3ce44SJohn Forte {
654fcf3ce44SJohn Forte 	if (id->id_next) {
655fcf3ce44SJohn Forte 		id->id_next->id_prev = id->id_prev;
656fcf3ce44SJohn Forte 	} else {
657fcf3ce44SJohn Forte 		idlist->idl_tail = id->id_prev;
658fcf3ce44SJohn Forte 	}
659fcf3ce44SJohn Forte 
660fcf3ce44SJohn Forte 	if (id->id_prev) {
661fcf3ce44SJohn Forte 		id->id_prev->id_next = id->id_next;
662fcf3ce44SJohn Forte 	} else {
663fcf3ce44SJohn Forte 		idlist->idl_head = id->id_next;
664fcf3ce44SJohn Forte 	}
6651a5e258fSJosef 'Jeff' Sipek 	atomic_dec_32(&idlist->id_count);
666fcf3ce44SJohn Forte }
667fcf3ce44SJohn Forte 
668fcf3ce44SJohn Forte 
669fcf3ce44SJohn Forte /*
670fcf3ce44SJohn Forte  * The refcnts of objects in a view entry are updated when then entry
671fcf3ce44SJohn Forte  * is successfully added. ve_map is just another representation of the
672fcf3ce44SJohn Forte  * view enrtries in a LU. Duplicating or merging a ve map does not
673fcf3ce44SJohn Forte  * affect any refcnts.
67461dfa509SRick McNeal  * stmf_state.stmf_lock held
675fcf3ce44SJohn Forte  */
676fcf3ce44SJohn Forte stmf_lun_map_t *
stmf_duplicate_ve_map(stmf_lun_map_t * src)677fcf3ce44SJohn Forte stmf_duplicate_ve_map(stmf_lun_map_t *src)
678fcf3ce44SJohn Forte {
679fcf3ce44SJohn Forte 	stmf_lun_map_t *dst;
680fcf3ce44SJohn Forte 	int i;
681fcf3ce44SJohn Forte 
682fcf3ce44SJohn Forte 	dst = (stmf_lun_map_t *)kmem_zalloc(sizeof (*dst), KM_SLEEP);
683fcf3ce44SJohn Forte 
684fcf3ce44SJohn Forte 	if (src == NULL)
685fcf3ce44SJohn Forte 		return (dst);
686fcf3ce44SJohn Forte 
687fcf3ce44SJohn Forte 	if (src->lm_nentries) {
688fcf3ce44SJohn Forte 		dst->lm_plus = kmem_zalloc(dst->lm_nentries *
689fcf3ce44SJohn Forte 		    sizeof (void *), KM_SLEEP);
690fcf3ce44SJohn Forte 		for (i = 0; i < dst->lm_nentries; i++) {
691fcf3ce44SJohn Forte 			dst->lm_plus[i] = src->lm_plus[i];
692fcf3ce44SJohn Forte 		}
693fcf3ce44SJohn Forte 	}
694fcf3ce44SJohn Forte 
695fcf3ce44SJohn Forte 	return (dst);
696fcf3ce44SJohn Forte }
697fcf3ce44SJohn Forte 
698fcf3ce44SJohn Forte void
stmf_destroy_ve_map(stmf_lun_map_t * dst)699fcf3ce44SJohn Forte stmf_destroy_ve_map(stmf_lun_map_t *dst)
700fcf3ce44SJohn Forte {
701fcf3ce44SJohn Forte 	if (dst->lm_nentries) {
702fcf3ce44SJohn Forte 		kmem_free(dst->lm_plus, dst->lm_nentries * sizeof (void *));
703fcf3ce44SJohn Forte 	}
704fcf3ce44SJohn Forte 	kmem_free(dst, sizeof (*dst));
705fcf3ce44SJohn Forte }
706fcf3ce44SJohn Forte 
70761dfa509SRick McNeal /*
70861dfa509SRick McNeal  * stmf_state.stmf_lock held. Operations are stmf global in nature and
70961dfa509SRick McNeal  * not session level.
71061dfa509SRick McNeal  */
711fcf3ce44SJohn Forte 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)712fcf3ce44SJohn Forte stmf_merge_ve_map(stmf_lun_map_t *src, stmf_lun_map_t *dst,
713fcf3ce44SJohn Forte     stmf_lun_map_t **pp_ret_map, stmf_merge_flags_t mf)
714fcf3ce44SJohn Forte {
715fcf3ce44SJohn Forte 	int i;
716fcf3ce44SJohn Forte 	int nentries;
717fcf3ce44SJohn Forte 	int to_create_space = 0;
718fcf3ce44SJohn Forte 
719fcf3ce44SJohn Forte 	if (dst == NULL) {
720fcf3ce44SJohn Forte 		*pp_ret_map = stmf_duplicate_ve_map(src);
721fcf3ce44SJohn Forte 		return (1);
722fcf3ce44SJohn Forte 	}
723fcf3ce44SJohn Forte 
724fcf3ce44SJohn Forte 	if (src == NULL || src->lm_nluns == 0) {
725fcf3ce44SJohn Forte 		if (mf & MERGE_FLAG_RETURN_NEW_MAP)
726fcf3ce44SJohn Forte 			*pp_ret_map = stmf_duplicate_ve_map(dst);
727fcf3ce44SJohn Forte 		else
728fcf3ce44SJohn Forte 			*pp_ret_map = dst;
729fcf3ce44SJohn Forte 		return (1);
730fcf3ce44SJohn Forte 	}
731fcf3ce44SJohn Forte 
732fcf3ce44SJohn Forte 	if (mf & MERGE_FLAG_RETURN_NEW_MAP) {
733fcf3ce44SJohn Forte 		*pp_ret_map = stmf_duplicate_ve_map(NULL);
734fcf3ce44SJohn Forte 		nentries = max(dst->lm_nentries, src->lm_nentries);
735fcf3ce44SJohn Forte 		to_create_space = 1;
736fcf3ce44SJohn Forte 	} else {
737fcf3ce44SJohn Forte 		*pp_ret_map = dst;
738fcf3ce44SJohn Forte 		/* If there is not enough space in dst map */
739fcf3ce44SJohn Forte 		if (dst->lm_nentries < src->lm_nentries) {
740fcf3ce44SJohn Forte 			nentries = src->lm_nentries;
741fcf3ce44SJohn Forte 			to_create_space = 1;
742fcf3ce44SJohn Forte 		}
743fcf3ce44SJohn Forte 	}
744fcf3ce44SJohn Forte 	if (to_create_space) {
745fcf3ce44SJohn Forte 		void **p;
746fcf3ce44SJohn Forte 		p = (void **)kmem_zalloc(nentries * sizeof (void *), KM_SLEEP);
747fcf3ce44SJohn Forte 		if (dst->lm_nentries) {
748fcf3ce44SJohn Forte 			bcopy(dst->lm_plus, p,
749fcf3ce44SJohn Forte 			    dst->lm_nentries * sizeof (void *));
750fcf3ce44SJohn Forte 		}
751fcf3ce44SJohn Forte 		if (mf & (MERGE_FLAG_RETURN_NEW_MAP == 0))
752fcf3ce44SJohn Forte 			kmem_free(dst->lm_plus,
753fcf3ce44SJohn Forte 			    dst->lm_nentries * sizeof (void *));
754fcf3ce44SJohn Forte 		(*pp_ret_map)->lm_plus = p;
755fcf3ce44SJohn Forte 		(*pp_ret_map)->lm_nentries = nentries;
756fcf3ce44SJohn Forte 	}
757fcf3ce44SJohn Forte 
758fcf3ce44SJohn Forte 	for (i = 0; i < src->lm_nentries; i++) {
759fcf3ce44SJohn Forte 		if (src->lm_plus[i] == NULL)
760fcf3ce44SJohn Forte 			continue;
761fcf3ce44SJohn Forte 		if (dst->lm_plus[i] != NULL) {
762fcf3ce44SJohn Forte 			if (mf & MERGE_FLAG_NO_DUPLICATE) {
763fcf3ce44SJohn Forte 				if (mf & MERGE_FLAG_RETURN_NEW_MAP) {
764fcf3ce44SJohn Forte 					stmf_destroy_ve_map(*pp_ret_map);
765fcf3ce44SJohn Forte 					*pp_ret_map = NULL;
766fcf3ce44SJohn Forte 				}
767fcf3ce44SJohn Forte 				return (0);
768fcf3ce44SJohn Forte 			}
769fcf3ce44SJohn Forte 		} else {
770fcf3ce44SJohn Forte 			dst->lm_plus[i] = src->lm_plus[i];
771fcf3ce44SJohn Forte 			dst->lm_nluns++;
772fcf3ce44SJohn Forte 		}
773fcf3ce44SJohn Forte 	}
774fcf3ce44SJohn Forte 
775fcf3ce44SJohn Forte 	return (1);
776fcf3ce44SJohn Forte }
777fcf3ce44SJohn Forte 
778fcf3ce44SJohn Forte /*
779fcf3ce44SJohn Forte  * add host group, id_impl_specific point to a list of hosts,
780fcf3ce44SJohn Forte  * on return, if error happened, err_detail may be assigned if
781fcf3ce44SJohn Forte  * the pointer is not NULL
782fcf3ce44SJohn Forte  */
783fcf3ce44SJohn Forte stmf_status_t
stmf_add_hg(uint8_t * hg_name,uint16_t hg_name_size,int allow_special,uint32_t * err_detail)784fcf3ce44SJohn Forte stmf_add_hg(uint8_t *hg_name, uint16_t hg_name_size,
785fcf3ce44SJohn Forte     int allow_special, uint32_t *err_detail)
786fcf3ce44SJohn Forte {
787fcf3ce44SJohn Forte 	stmf_id_data_t *id;
788fcf3ce44SJohn Forte 
789fcf3ce44SJohn Forte 	if (!allow_special) {
790fcf3ce44SJohn Forte 		if (hg_name[0] == '*')
791fcf3ce44SJohn Forte 			return (STMF_INVALID_ARG);
792fcf3ce44SJohn Forte 	}
793fcf3ce44SJohn Forte 
794fcf3ce44SJohn Forte 	if (stmf_lookup_id(&stmf_state.stmf_hg_list,
795fcf3ce44SJohn Forte 	    hg_name_size, (uint8_t *)hg_name)) {
796fcf3ce44SJohn Forte 		if (err_detail)
797fcf3ce44SJohn Forte 			*err_detail = STMF_IOCERR_HG_EXISTS;
798fcf3ce44SJohn Forte 		return (STMF_ALREADY);
799fcf3ce44SJohn Forte 	}
800fcf3ce44SJohn Forte 	id = stmf_alloc_id(hg_name_size, STMF_ID_TYPE_HOST_GROUP,
801fcf3ce44SJohn Forte 	    (uint8_t *)hg_name, sizeof (stmf_id_list_t));
802fcf3ce44SJohn Forte 	stmf_append_id(&stmf_state.stmf_hg_list, id);
803fcf3ce44SJohn Forte 
804fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
805fcf3ce44SJohn Forte }
806fcf3ce44SJohn Forte 
807fcf3ce44SJohn Forte /* add target group */
808fcf3ce44SJohn Forte stmf_status_t
stmf_add_tg(uint8_t * tg_name,uint16_t tg_name_size,int allow_special,uint32_t * err_detail)809fcf3ce44SJohn Forte stmf_add_tg(uint8_t *tg_name, uint16_t tg_name_size,
810fcf3ce44SJohn Forte     int allow_special, uint32_t *err_detail)
811fcf3ce44SJohn Forte {
812fcf3ce44SJohn Forte 	stmf_id_data_t *id;
813fcf3ce44SJohn Forte 
814fcf3ce44SJohn Forte 	if (!allow_special) {
815fcf3ce44SJohn Forte 		if (tg_name[0] == '*')
816fcf3ce44SJohn Forte 			return (STMF_INVALID_ARG);
817fcf3ce44SJohn Forte 	}
818fcf3ce44SJohn Forte 
819fcf3ce44SJohn Forte 
820fcf3ce44SJohn Forte 	if (stmf_lookup_id(&stmf_state.stmf_tg_list, tg_name_size,
821fcf3ce44SJohn Forte 	    (uint8_t *)tg_name)) {
822fcf3ce44SJohn Forte 		if (err_detail)
823fcf3ce44SJohn Forte 			*err_detail = STMF_IOCERR_TG_EXISTS;
824fcf3ce44SJohn Forte 		return (STMF_ALREADY);
825fcf3ce44SJohn Forte 	}
826fcf3ce44SJohn Forte 	id = stmf_alloc_id(tg_name_size, STMF_ID_TYPE_TARGET_GROUP,
827fcf3ce44SJohn Forte 	    (uint8_t *)tg_name, sizeof (stmf_id_list_t));
828fcf3ce44SJohn Forte 	stmf_append_id(&stmf_state.stmf_tg_list, id);
829fcf3ce44SJohn Forte 
830fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
831fcf3ce44SJohn Forte }
832fcf3ce44SJohn Forte 
833fcf3ce44SJohn Forte /*
834fcf3ce44SJohn Forte  * insert view entry into list for a luid, if ve->ve_id is 0xffffffff,
835fcf3ce44SJohn Forte  * pick up a smallest available veid for it, and return the veid in ve->ve_id.
836fcf3ce44SJohn Forte  * The view entries list is sorted based on veid.
837fcf3ce44SJohn Forte  */
838fcf3ce44SJohn Forte stmf_status_t
stmf_add_ve_to_luid(stmf_id_data_t * luid,stmf_view_entry_t * ve)839fcf3ce44SJohn Forte stmf_add_ve_to_luid(stmf_id_data_t *luid, stmf_view_entry_t *ve)
840fcf3ce44SJohn Forte {
841fcf3ce44SJohn Forte 	stmf_view_entry_t *ve_tmp = NULL;
842fcf3ce44SJohn Forte 	stmf_view_entry_t *ve_prev = NULL;
843fcf3ce44SJohn Forte 
844fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
845fcf3ce44SJohn Forte 
846fcf3ce44SJohn Forte 	ve_tmp = (stmf_view_entry_t *)luid->id_impl_specific;
847fcf3ce44SJohn Forte 
848fcf3ce44SJohn Forte 	if (ve->ve_id != 0xffffffff) {
849fcf3ce44SJohn Forte 		for (; ve_tmp; ve_tmp = ve_tmp->ve_next) {
850fcf3ce44SJohn Forte 			if (ve_tmp->ve_id > ve->ve_id) {
851fcf3ce44SJohn Forte 				break;
852fcf3ce44SJohn Forte 			} else if (ve_tmp->ve_id == ve->ve_id) {
853fcf3ce44SJohn Forte 				return (STMF_ALREADY);
854fcf3ce44SJohn Forte 			}
855fcf3ce44SJohn Forte 			ve_prev = ve_tmp;
856fcf3ce44SJohn Forte 		}
857fcf3ce44SJohn Forte 	} else {
858fcf3ce44SJohn Forte 		uint32_t veid = 0;
859fcf3ce44SJohn Forte 		/* search the smallest available veid */
860fcf3ce44SJohn Forte 		for (; ve_tmp; ve_tmp = ve_tmp->ve_next) {
861fcf3ce44SJohn Forte 			ASSERT(ve_tmp->ve_id >= veid);
862fcf3ce44SJohn Forte 			if (ve_tmp->ve_id != veid)
863fcf3ce44SJohn Forte 				break;
864fcf3ce44SJohn Forte 			veid++;
865fcf3ce44SJohn Forte 			if (veid == 0xffffffff)
866fcf3ce44SJohn Forte 				return (STMF_NOT_SUPPORTED);
867fcf3ce44SJohn Forte 			ve_prev = ve_tmp;
868fcf3ce44SJohn Forte 		}
869fcf3ce44SJohn Forte 		ve->ve_id = veid;
870fcf3ce44SJohn Forte 	}
871fcf3ce44SJohn Forte 
872fcf3ce44SJohn Forte 	/* insert before ve_tmp if it exist */
873fcf3ce44SJohn Forte 	ve->ve_next = ve_tmp;
874fcf3ce44SJohn Forte 	ve->ve_prev = ve_prev;
875fcf3ce44SJohn Forte 	if (ve_tmp) {
876fcf3ce44SJohn Forte 		ve_tmp->ve_prev = ve;
877fcf3ce44SJohn Forte 	}
878fcf3ce44SJohn Forte 	if (ve_prev) {
879fcf3ce44SJohn Forte 		ve_prev->ve_next = ve;
880fcf3ce44SJohn Forte 	} else {
881fcf3ce44SJohn Forte 		luid->id_impl_specific = (void *)ve;
882fcf3ce44SJohn Forte 	}
883fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
884fcf3ce44SJohn Forte }
885fcf3ce44SJohn Forte 
886fcf3ce44SJohn Forte /* stmf_lock is already held, err_detail may be assigned if error happens */
887fcf3ce44SJohn Forte 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)888fcf3ce44SJohn Forte stmf_add_view_entry(stmf_id_data_t *hg, stmf_id_data_t *tg,
889fcf3ce44SJohn Forte     uint8_t *lu_guid, uint32_t *ve_id, uint8_t *lun,
890fcf3ce44SJohn Forte     stmf_view_entry_t **conflicting, uint32_t *err_detail)
891fcf3ce44SJohn Forte {
892fcf3ce44SJohn Forte 	stmf_id_data_t *luid;
893fcf3ce44SJohn Forte 	stmf_view_entry_t *ve;
894fcf3ce44SJohn Forte 	char *phg, *ptg;
895fcf3ce44SJohn Forte 	stmf_lun_map_t *ve_map = NULL;
896fcf3ce44SJohn Forte 	stmf_ver_hg_t *verhg = NULL, *verhg_ex = NULL;
897fcf3ce44SJohn Forte 	stmf_ver_tg_t *vertg = NULL, *vertg_ex = NULL;
898fcf3ce44SJohn Forte 	char luid_new;
899fcf3ce44SJohn Forte 	uint16_t lun_num;
900fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
901fcf3ce44SJohn Forte 	stmf_status_t ret;
902fcf3ce44SJohn Forte 
903fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
904fcf3ce44SJohn Forte 
905fcf3ce44SJohn Forte 	lun_num = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
906fcf3ce44SJohn Forte 
907fcf3ce44SJohn Forte 	luid = stmf_lookup_id(&stmf_state.stmf_luid_list, 16, lu_guid);
908fcf3ce44SJohn Forte 	if (luid == NULL) {
909fcf3ce44SJohn Forte 		luid = stmf_alloc_id(16, STMF_ID_TYPE_LU_GUID, lu_guid, 0);
910fcf3ce44SJohn Forte 		ilu = stmf_luident_to_ilu(lu_guid);
911fcf3ce44SJohn Forte 		if (ilu) {
912fcf3ce44SJohn Forte 			ilu->ilu_luid = luid;
913fcf3ce44SJohn Forte 			luid->id_pt_to_object = (void *)ilu;
914fcf3ce44SJohn Forte 		}
915fcf3ce44SJohn Forte 		luid_new = 1;
916fcf3ce44SJohn Forte 	} else {
917fcf3ce44SJohn Forte 		luid_new = 0;
918fcf3ce44SJohn Forte 		ilu = (stmf_i_lu_t *)luid->id_pt_to_object;
919fcf3ce44SJohn Forte 	}
920fcf3ce44SJohn Forte 
921fcf3ce44SJohn Forte 	/* The view entry won't be added if there is any confilict */
922fcf3ce44SJohn Forte 	phg = (char *)hg->id_data; ptg = (char *)tg->id_data;
923fcf3ce44SJohn Forte 	for (ve = (stmf_view_entry_t *)luid->id_impl_specific; ve != NULL;
924fcf3ce44SJohn Forte 	    ve = ve->ve_next) {
925fcf3ce44SJohn Forte 		if (((phg[0] == '*') || (ve->ve_hg->id_data[0] == '*') ||
926fcf3ce44SJohn Forte 		    (hg == ve->ve_hg)) && ((ptg[0] == '*') ||
927fcf3ce44SJohn Forte 		    (ve->ve_tg->id_data[0] == '*') || (tg == ve->ve_tg))) {
928fcf3ce44SJohn Forte 			*conflicting = ve;
929fcf3ce44SJohn Forte 			*err_detail = STMF_IOCERR_VIEW_ENTRY_CONFLICT;
930fcf3ce44SJohn Forte 			ret = STMF_ALREADY;
931fcf3ce44SJohn Forte 			goto add_ve_err_ret;
932fcf3ce44SJohn Forte 		}
933fcf3ce44SJohn Forte 	}
934fcf3ce44SJohn Forte 
935fcf3ce44SJohn Forte 	ve_map = stmf_duplicate_ve_map(0);
936fcf3ce44SJohn Forte 	for (vertg = stmf_state.stmf_ver_tg_head; vertg != NULL;
937fcf3ce44SJohn Forte 	    vertg = vertg->vert_next) {
938fcf3ce44SJohn Forte 		ptg = (char *)vertg->vert_tg_ref->id_data;
939fcf3ce44SJohn Forte 		if ((ptg[0] != '*') && (tg->id_data[0] != '*') &&
940fcf3ce44SJohn Forte 		    (vertg->vert_tg_ref != tg)) {
941fcf3ce44SJohn Forte 			continue;
942fcf3ce44SJohn Forte 		}
943fcf3ce44SJohn Forte 		if (vertg->vert_tg_ref == tg)
944fcf3ce44SJohn Forte 			vertg_ex = vertg;
945fcf3ce44SJohn Forte 		for (verhg = vertg->vert_verh_list; verhg != NULL;
946fcf3ce44SJohn Forte 		    verhg = verhg->verh_next) {
947fcf3ce44SJohn Forte 			phg = (char *)verhg->verh_hg_ref->id_data;
948fcf3ce44SJohn Forte 			if ((phg[0] != '*') && (hg->id_data[0] != '*') &&
949fcf3ce44SJohn Forte 			    (verhg->verh_hg_ref != hg)) {
950fcf3ce44SJohn Forte 				continue;
951fcf3ce44SJohn Forte 			}
952fcf3ce44SJohn Forte 			if ((vertg_ex == vertg) && (verhg->verh_hg_ref == hg))
953fcf3ce44SJohn Forte 				verhg_ex = verhg;
954fcf3ce44SJohn Forte 			(void) stmf_merge_ve_map(&verhg->verh_ve_map, ve_map,
955fcf3ce44SJohn Forte 			    &ve_map, 0);
956fcf3ce44SJohn Forte 		}
957fcf3ce44SJohn Forte 	}
958fcf3ce44SJohn Forte 
959fcf3ce44SJohn Forte 	if (lun[2] == 0xFF) {
960fcf3ce44SJohn Forte 		/* Pick a LUN number */
961fcf3ce44SJohn Forte 		lun_num = stmf_get_next_free_lun(ve_map, lun);
962fcf3ce44SJohn Forte 		if (lun_num > 0x3FFF) {
963fcf3ce44SJohn Forte 			stmf_destroy_ve_map(ve_map);
964fcf3ce44SJohn Forte 			ret = STMF_NOT_SUPPORTED;
965fcf3ce44SJohn Forte 			goto add_ve_err_ret;
966fcf3ce44SJohn Forte 		}
967fcf3ce44SJohn Forte 	} else {
968fcf3ce44SJohn Forte 		if ((*conflicting = stmf_get_ent_from_map(ve_map, lun_num))
969fcf3ce44SJohn Forte 		    != NULL) {
970fcf3ce44SJohn Forte 			stmf_destroy_ve_map(ve_map);
971fcf3ce44SJohn Forte 			*err_detail = STMF_IOCERR_LU_NUMBER_IN_USE;
972fcf3ce44SJohn Forte 			ret = STMF_LUN_TAKEN;
973fcf3ce44SJohn Forte 			goto add_ve_err_ret;
974fcf3ce44SJohn Forte 		}
975fcf3ce44SJohn Forte 	}
976fcf3ce44SJohn Forte 	stmf_destroy_ve_map(ve_map);
977fcf3ce44SJohn Forte 
978fcf3ce44SJohn Forte 	/* All is well, do the actual addition now */
979fcf3ce44SJohn Forte 	ve = (stmf_view_entry_t *)kmem_zalloc(sizeof (*ve), KM_SLEEP);
980fcf3ce44SJohn Forte 	ve->ve_id = *ve_id;
981fcf3ce44SJohn Forte 	ve->ve_lun[0] = lun[0];
982fcf3ce44SJohn Forte 	ve->ve_lun[1] = lun[1];
983fcf3ce44SJohn Forte 
984fcf3ce44SJohn Forte 	if ((ret = stmf_add_ve_to_luid(luid, ve)) != STMF_SUCCESS) {
985fcf3ce44SJohn Forte 		kmem_free(ve, sizeof (stmf_view_entry_t));
986fcf3ce44SJohn Forte 		goto add_ve_err_ret;
987fcf3ce44SJohn Forte 	}
988fcf3ce44SJohn Forte 	ve->ve_hg = hg; hg->id_refcnt++;
989fcf3ce44SJohn Forte 	ve->ve_tg = tg; tg->id_refcnt++;
990fcf3ce44SJohn Forte 	ve->ve_luid = luid; luid->id_refcnt++;
991fcf3ce44SJohn Forte 
992fcf3ce44SJohn Forte 	*ve_id = ve->ve_id;
993fcf3ce44SJohn Forte 
994fcf3ce44SJohn Forte 	if (luid_new) {
995fcf3ce44SJohn Forte 		stmf_append_id(&stmf_state.stmf_luid_list, luid);
996fcf3ce44SJohn Forte 	}
997fcf3ce44SJohn Forte 
998fcf3ce44SJohn Forte 	if (vertg_ex == NULL) {
999fcf3ce44SJohn Forte 		vertg_ex = (stmf_ver_tg_t *)kmem_zalloc(sizeof (stmf_ver_tg_t),
1000fcf3ce44SJohn Forte 		    KM_SLEEP);
1001fcf3ce44SJohn Forte 		vertg_ex->vert_next = stmf_state.stmf_ver_tg_head;
1002fcf3ce44SJohn Forte 		stmf_state.stmf_ver_tg_head = vertg_ex;
1003fcf3ce44SJohn Forte 		vertg_ex->vert_tg_ref = tg;
1004fcf3ce44SJohn Forte 		verhg_ex = vertg_ex->vert_verh_list =
1005fcf3ce44SJohn Forte 		    (stmf_ver_hg_t *)kmem_zalloc(sizeof (stmf_ver_hg_t),
1006fcf3ce44SJohn Forte 		    KM_SLEEP);
1007fcf3ce44SJohn Forte 		verhg_ex->verh_hg_ref = hg;
1008fcf3ce44SJohn Forte 	}
1009fcf3ce44SJohn Forte 	if (verhg_ex == NULL) {
1010fcf3ce44SJohn Forte 		verhg_ex = (stmf_ver_hg_t *)kmem_zalloc(sizeof (stmf_ver_hg_t),
1011fcf3ce44SJohn Forte 		    KM_SLEEP);
1012fcf3ce44SJohn Forte 		verhg_ex->verh_next = vertg_ex->vert_verh_list;
1013fcf3ce44SJohn Forte 		vertg_ex->vert_verh_list = verhg_ex;
1014fcf3ce44SJohn Forte 		verhg_ex->verh_hg_ref = hg;
1015fcf3ce44SJohn Forte 	}
1016fcf3ce44SJohn Forte 	ret = stmf_add_ent_to_map(&verhg_ex->verh_ve_map, ve, ve->ve_lun);
1017fcf3ce44SJohn Forte 	ASSERT(ret == STMF_SUCCESS);
1018fcf3ce44SJohn Forte 
1019fcf3ce44SJohn Forte 	/* we need to update the affected session */
1020fcf3ce44SJohn Forte 	if (stmf_state.stmf_service_running) {
1021fcf3ce44SJohn Forte 		if (ilu && ilu->ilu_state == STMF_STATE_ONLINE)
1022fcf3ce44SJohn Forte 			stmf_update_sessions_per_ve(ve, ilu->ilu_lu, 1);
1023fcf3ce44SJohn Forte 	}
1024fcf3ce44SJohn Forte 
1025fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
1026fcf3ce44SJohn Forte add_ve_err_ret:
1027fcf3ce44SJohn Forte 	if (luid_new) {
1028fcf3ce44SJohn Forte 		if (ilu)
1029fcf3ce44SJohn Forte 			ilu->ilu_luid = NULL;
1030fcf3ce44SJohn Forte 		stmf_free_id(luid);
1031fcf3ce44SJohn Forte 	}
1032fcf3ce44SJohn Forte 	return (ret);
1033fcf3ce44SJohn Forte }
1034fcf3ce44SJohn Forte 
103561dfa509SRick McNeal /*
103661dfa509SRick McNeal  * protected by stmf_state.stmf_lock when working on global lun map.
103761dfa509SRick McNeal  * iss_lockp when working at the session level.
103861dfa509SRick McNeal  */
103961dfa509SRick McNeal static stmf_status_t
stmf_add_ent_to_map(stmf_lun_map_t * lm,void * ent,uint8_t * lun)1040fcf3ce44SJohn Forte stmf_add_ent_to_map(stmf_lun_map_t *lm, void *ent, uint8_t *lun)
1041fcf3ce44SJohn Forte {
1042fcf3ce44SJohn Forte 	uint16_t n;
1043fcf3ce44SJohn Forte 	if (((lun[0] & 0xc0) >> 6) != 0)
1044fcf3ce44SJohn Forte 		return (STMF_FAILURE);
1045fcf3ce44SJohn Forte 
1046fcf3ce44SJohn Forte 	n = (uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8);
1047fcf3ce44SJohn Forte try_again_to_add:
1048fcf3ce44SJohn Forte 	if (lm->lm_nentries && (n < lm->lm_nentries)) {
1049fcf3ce44SJohn Forte 		if (lm->lm_plus[n] == NULL) {
1050fcf3ce44SJohn Forte 			lm->lm_plus[n] = ent;
1051fcf3ce44SJohn Forte 			lm->lm_nluns++;
1052fcf3ce44SJohn Forte 			return (STMF_SUCCESS);
1053fcf3ce44SJohn Forte 		} else {
1054fcf3ce44SJohn Forte 			return (STMF_LUN_TAKEN);
1055fcf3ce44SJohn Forte 		}
1056fcf3ce44SJohn Forte 	} else {
1057fcf3ce44SJohn Forte 		void **pplu;
1058fcf3ce44SJohn Forte 		uint16_t m = n + 1;
1059fcf3ce44SJohn Forte 		m = ((m + 7) & ~7) & 0x7FFF;
1060fcf3ce44SJohn Forte 		pplu = (void **)kmem_zalloc(m * sizeof (void *), KM_SLEEP);
1061fcf3ce44SJohn Forte 		bcopy(lm->lm_plus, pplu,
1062fcf3ce44SJohn Forte 		    lm->lm_nentries * sizeof (void *));
1063fcf3ce44SJohn Forte 		kmem_free(lm->lm_plus, lm->lm_nentries * sizeof (void *));
1064fcf3ce44SJohn Forte 		lm->lm_plus = pplu;
1065fcf3ce44SJohn Forte 		lm->lm_nentries = m;
1066fcf3ce44SJohn Forte 		goto try_again_to_add;
1067fcf3ce44SJohn Forte 	}
1068fcf3ce44SJohn Forte }
1069fcf3ce44SJohn Forte 
1070fcf3ce44SJohn Forte 
107161dfa509SRick McNeal /*
107261dfa509SRick McNeal  * iss_lockp held when working on a session.
107361dfa509SRick McNeal  * stmf_state.stmf_lock is held when working on the global views.
107461dfa509SRick McNeal  */
107561dfa509SRick McNeal static stmf_status_t
stmf_remove_ent_from_map(stmf_lun_map_t * lm,uint8_t * lun)1076fcf3ce44SJohn Forte stmf_remove_ent_from_map(stmf_lun_map_t *lm, uint8_t *lun)
1077fcf3ce44SJohn Forte {
1078fcf3ce44SJohn Forte 	uint16_t n, i;
1079fcf3ce44SJohn Forte 	uint8_t lutype = (lun[0] & 0xc0) >> 6;
1080fcf3ce44SJohn Forte 	if (lutype != 0)
1081fcf3ce44SJohn Forte 		return (STMF_FAILURE);
1082fcf3ce44SJohn Forte 
1083fcf3ce44SJohn Forte 	n = (uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8);
1084fcf3ce44SJohn Forte 
1085fcf3ce44SJohn Forte 	if (n >= lm->lm_nentries)
1086fcf3ce44SJohn Forte 		return (STMF_NOT_FOUND);
1087fcf3ce44SJohn Forte 	if (lm->lm_plus[n] == NULL)
1088fcf3ce44SJohn Forte 		return (STMF_NOT_FOUND);
1089fcf3ce44SJohn Forte 
1090fcf3ce44SJohn Forte 	lm->lm_plus[n] = NULL;
1091fcf3ce44SJohn Forte 	lm->lm_nluns--;
1092fcf3ce44SJohn Forte 
1093fcf3ce44SJohn Forte 	for (i = 0; i < lm->lm_nentries; i++) {
1094fcf3ce44SJohn Forte 		if (lm->lm_plus[lm->lm_nentries - 1 - i] != NULL)
1095fcf3ce44SJohn Forte 			break;
1096fcf3ce44SJohn Forte 	}
1097fcf3ce44SJohn Forte 	i &= ~15;
1098fcf3ce44SJohn Forte 	if (i >= 16) {
1099fcf3ce44SJohn Forte 		void **pplu;
1100fcf3ce44SJohn Forte 		uint16_t m;
1101fcf3ce44SJohn Forte 		m = lm->lm_nentries - i;
1102fcf3ce44SJohn Forte 		pplu = (void **)kmem_zalloc(m * sizeof (void *), KM_SLEEP);
1103fcf3ce44SJohn Forte 		bcopy(lm->lm_plus, pplu, m * sizeof (void *));
1104fcf3ce44SJohn Forte 		kmem_free(lm->lm_plus, lm->lm_nentries * sizeof (void *));
1105fcf3ce44SJohn Forte 		lm->lm_plus = pplu;
1106fcf3ce44SJohn Forte 		lm->lm_nentries = m;
1107fcf3ce44SJohn Forte 	}
1108fcf3ce44SJohn Forte 
1109fcf3ce44SJohn Forte 	return (STMF_SUCCESS);
1110fcf3ce44SJohn Forte }
1111fcf3ce44SJohn Forte 
111261dfa509SRick McNeal /*
111361dfa509SRick McNeal  * stmf_state.stmf_lock held
111461dfa509SRick McNeal  */
1115fcf3ce44SJohn Forte uint16_t
stmf_get_next_free_lun(stmf_lun_map_t * sm,uint8_t * lun)1116fcf3ce44SJohn Forte stmf_get_next_free_lun(stmf_lun_map_t *sm, uint8_t *lun)
1117fcf3ce44SJohn Forte {
1118fcf3ce44SJohn Forte 	uint16_t luNbr;
1119fcf3ce44SJohn Forte 
1120fcf3ce44SJohn Forte 
1121fcf3ce44SJohn Forte 	if (sm->lm_nluns < 0x4000) {
1122fcf3ce44SJohn Forte 		for (luNbr = 0; luNbr < sm->lm_nentries; luNbr++) {
1123fcf3ce44SJohn Forte 			if (sm->lm_plus[luNbr] == NULL)
1124fcf3ce44SJohn Forte 				break;
1125fcf3ce44SJohn Forte 		}
1126fcf3ce44SJohn Forte 	} else {
1127fcf3ce44SJohn Forte 		return (0xFFFF);
1128fcf3ce44SJohn Forte 	}
1129fcf3ce44SJohn Forte 	if (lun) {
1130fcf3ce44SJohn Forte 		bzero(lun, 8);
1131fcf3ce44SJohn Forte 		lun[1] = luNbr & 0xff;
1132fcf3ce44SJohn Forte 		lun[0] = (luNbr >> 8) & 0xff;
1133fcf3ce44SJohn Forte 	}
1134fcf3ce44SJohn Forte 
1135fcf3ce44SJohn Forte 	return (luNbr);
1136fcf3ce44SJohn Forte }
1137fcf3ce44SJohn Forte 
113861dfa509SRick McNeal /*
113961dfa509SRick McNeal  * stmf_state.stmf_lock is held when working on global view map
114061dfa509SRick McNeal  * iss_lockp (RW_WRITER) is held when working on session map.
114161dfa509SRick McNeal  */
1142fcf3ce44SJohn Forte void *
stmf_get_ent_from_map(stmf_lun_map_t * sm,uint16_t lun_num)1143fcf3ce44SJohn Forte stmf_get_ent_from_map(stmf_lun_map_t *sm, uint16_t lun_num)
1144fcf3ce44SJohn Forte {
1145fcf3ce44SJohn Forte 	if ((lun_num & 0xC000) == 0) {
1146fcf3ce44SJohn Forte 		if (sm->lm_nentries > lun_num)
1147fcf3ce44SJohn Forte 			return (sm->lm_plus[lun_num & 0x3FFF]);
1148fcf3ce44SJohn Forte 		else
1149fcf3ce44SJohn Forte 			return (NULL);
1150fcf3ce44SJohn Forte 	}
1151fcf3ce44SJohn Forte 
1152fcf3ce44SJohn Forte 	return (NULL);
1153fcf3ce44SJohn Forte }
1154fcf3ce44SJohn Forte 
1155fcf3ce44SJohn Forte 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)1156fcf3ce44SJohn Forte stmf_add_ve(uint8_t *hgname, uint16_t hgname_size,
1157fcf3ce44SJohn Forte     uint8_t *tgname, uint16_t tgname_size,
1158fcf3ce44SJohn Forte     uint8_t *lu_guid, uint32_t *ve_id,
1159fcf3ce44SJohn Forte     uint8_t *luNbr, uint32_t *err_detail)
1160fcf3ce44SJohn Forte {
1161fcf3ce44SJohn Forte 	stmf_id_data_t *hg;
1162fcf3ce44SJohn Forte 	stmf_id_data_t *tg;
1163fcf3ce44SJohn Forte 	stmf_view_entry_t *conflictve;
1164fcf3ce44SJohn Forte 	stmf_status_t ret;
1165fcf3ce44SJohn Forte 
1166fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
1167fcf3ce44SJohn Forte 
1168fcf3ce44SJohn Forte 	hg = stmf_lookup_id(&stmf_state.stmf_hg_list, hgname_size,
1169fcf3ce44SJohn Forte 	    (uint8_t *)hgname);
1170fcf3ce44SJohn Forte 	if (!hg) {
1171fcf3ce44SJohn Forte 		*err_detail = STMF_IOCERR_INVALID_HG;
1172fcf3ce44SJohn Forte 		return (ENOENT); /* could not find group */
1173fcf3ce44SJohn Forte 	}
1174fcf3ce44SJohn Forte 	tg = stmf_lookup_id(&stmf_state.stmf_tg_list, tgname_size,
1175fcf3ce44SJohn Forte 	    (uint8_t *)tgname);
1176fcf3ce44SJohn Forte 	if (!tg) {
1177fcf3ce44SJohn Forte 		*err_detail = STMF_IOCERR_INVALID_TG;
1178fcf3ce44SJohn Forte 		return (ENOENT); /* could not find group */
1179fcf3ce44SJohn Forte 	}
1180fcf3ce44SJohn Forte 	ret = stmf_add_view_entry(hg, tg, lu_guid, ve_id, luNbr,
1181fcf3ce44SJohn Forte 	    &conflictve, err_detail);
1182fcf3ce44SJohn Forte 
1183fcf3ce44SJohn Forte 	if (ret == STMF_ALREADY) {
1184fcf3ce44SJohn Forte 		return (EALREADY);
1185fcf3ce44SJohn Forte 	} else if (ret == STMF_LUN_TAKEN) {
1186fcf3ce44SJohn Forte 		return (EEXIST);
1187fcf3ce44SJohn Forte 	} else if (ret == STMF_NOT_SUPPORTED) {
1188fcf3ce44SJohn Forte 		return (E2BIG);
1189fcf3ce44SJohn Forte 	} else if (ret != STMF_SUCCESS) {
1190fcf3ce44SJohn Forte 		return (EINVAL);
1191fcf3ce44SJohn Forte 	}
1192fcf3ce44SJohn Forte 	return (0);
1193fcf3ce44SJohn Forte }
1194fcf3ce44SJohn Forte 
1195fcf3ce44SJohn Forte int
stmf_remove_ve_by_id(uint8_t * guid,uint32_t veid,uint32_t * err_detail)1196fcf3ce44SJohn Forte stmf_remove_ve_by_id(uint8_t *guid, uint32_t veid, uint32_t *err_detail)
1197fcf3ce44SJohn Forte {
1198fcf3ce44SJohn Forte 	stmf_id_data_t *luid;
1199fcf3ce44SJohn Forte 	stmf_view_entry_t	*ve;
1200fcf3ce44SJohn Forte 	stmf_ver_tg_t *vtg;
1201fcf3ce44SJohn Forte 	stmf_ver_hg_t *vhg;
1202fcf3ce44SJohn Forte 	stmf_ver_tg_t *prev_vtg = NULL;
1203fcf3ce44SJohn Forte 	stmf_ver_hg_t *prev_vhg = NULL;
1204fcf3ce44SJohn Forte 	int found = 0;
1205fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
1206fcf3ce44SJohn Forte 
1207fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
1208fcf3ce44SJohn Forte 	luid = stmf_lookup_id(&stmf_state.stmf_luid_list, 16, guid);
1209fcf3ce44SJohn Forte 	if (luid == NULL) {
1210fcf3ce44SJohn Forte 		*err_detail = STMF_IOCERR_INVALID_LU_ID;
1211fcf3ce44SJohn Forte 		return (ENODEV);
1212fcf3ce44SJohn Forte 	}
1213fcf3ce44SJohn Forte 	ilu = (stmf_i_lu_t *)luid->id_pt_to_object;
1214fcf3ce44SJohn Forte 
1215fcf3ce44SJohn Forte 	for (ve = (stmf_view_entry_t *)luid->id_impl_specific;
1216fcf3ce44SJohn Forte 	    ve; ve = ve->ve_next) {
1217fcf3ce44SJohn Forte 		if (ve->ve_id == veid) {
1218fcf3ce44SJohn Forte 			break;
1219fcf3ce44SJohn Forte 		}
1220fcf3ce44SJohn Forte 	}
1221fcf3ce44SJohn Forte 	if (!ve) {
1222fcf3ce44SJohn Forte 		*err_detail = STMF_IOCERR_INVALID_VE_ID;
1223fcf3ce44SJohn Forte 		return (ENODEV);
1224fcf3ce44SJohn Forte 	}
1225fcf3ce44SJohn Forte 	/* remove the ve */
1226fcf3ce44SJohn Forte 	if (ve->ve_next)
1227fcf3ce44SJohn Forte 		ve->ve_next->ve_prev = ve->ve_prev;
1228fcf3ce44SJohn Forte 	if (ve->ve_prev)
1229fcf3ce44SJohn Forte 		ve->ve_prev->ve_next = ve->ve_next;
1230fcf3ce44SJohn Forte 	else {
1231fcf3ce44SJohn Forte 		luid->id_impl_specific = (void *)ve->ve_next;
1232fcf3ce44SJohn Forte 		if (!luid->id_impl_specific) {
1233fcf3ce44SJohn Forte 			/* don't have any view entries related to this lu */
1234fcf3ce44SJohn Forte 			stmf_remove_id(&stmf_state.stmf_luid_list, luid);
1235fcf3ce44SJohn Forte 			if (ilu)
1236fcf3ce44SJohn Forte 				ilu->ilu_luid = NULL;
1237fcf3ce44SJohn Forte 			stmf_free_id(luid);
1238fcf3ce44SJohn Forte 		}
1239fcf3ce44SJohn Forte 	}
1240fcf3ce44SJohn Forte 
1241fcf3ce44SJohn Forte 	/* we need to update ver_hg->verh_ve_map */
1242fcf3ce44SJohn Forte 	for (vtg = stmf_state.stmf_ver_tg_head; vtg; vtg = vtg->vert_next) {
1243fcf3ce44SJohn Forte 		if (vtg->vert_tg_ref == ve->ve_tg) {
1244fcf3ce44SJohn Forte 			found = 1;
1245fcf3ce44SJohn Forte 			break;
1246fcf3ce44SJohn Forte 		}
1247fcf3ce44SJohn Forte 		prev_vtg = vtg;
1248fcf3ce44SJohn Forte 	}
1249fcf3ce44SJohn Forte 	ASSERT(found);
1250fcf3ce44SJohn Forte 	found = 0;
1251fcf3ce44SJohn Forte 	for (vhg = vtg->vert_verh_list; vhg; vhg = vhg->verh_next) {
1252fcf3ce44SJohn Forte 		if (vhg->verh_hg_ref == ve->ve_hg) {
1253fcf3ce44SJohn Forte 			found = 1;
1254fcf3ce44SJohn Forte 			break;
1255fcf3ce44SJohn Forte 		}
1256fcf3ce44SJohn Forte 		prev_vhg = vhg;
1257fcf3ce44SJohn Forte 	}
1258fcf3ce44SJohn Forte 	ASSERT(found);
1259fcf3ce44SJohn Forte 
1260fcf3ce44SJohn Forte 	(void) stmf_remove_ent_from_map(&vhg->verh_ve_map, ve->ve_lun);
1261fcf3ce44SJohn Forte 
1262fcf3ce44SJohn Forte 	/* free verhg if it don't have any ve entries related */
1263fcf3ce44SJohn Forte 	if (!vhg->verh_ve_map.lm_nluns) {
1264fcf3ce44SJohn Forte 		/* we don't have any view entry related */
1265fcf3ce44SJohn Forte 		if (prev_vhg)
1266fcf3ce44SJohn Forte 			prev_vhg->verh_next = vhg->verh_next;
1267fcf3ce44SJohn Forte 		else
1268fcf3ce44SJohn Forte 			vtg->vert_verh_list = vhg->verh_next;
1269fcf3ce44SJohn Forte 
1270fcf3ce44SJohn Forte 		/* Free entries in case the map still has memory */
1271fcf3ce44SJohn Forte 		if (vhg->verh_ve_map.lm_nentries) {
1272fcf3ce44SJohn Forte 			kmem_free(vhg->verh_ve_map.lm_plus,
1273fcf3ce44SJohn Forte 			    vhg->verh_ve_map.lm_nentries *
1274fcf3ce44SJohn Forte 			    sizeof (void *));
1275fcf3ce44SJohn Forte 		}
1276fcf3ce44SJohn Forte 		kmem_free(vhg, sizeof (stmf_ver_hg_t));
1277fcf3ce44SJohn Forte 		if (!vtg->vert_verh_list) {
1278fcf3ce44SJohn Forte 			/* we don't have any ve related */
1279fcf3ce44SJohn Forte 			if (prev_vtg)
1280fcf3ce44SJohn Forte 				prev_vtg->vert_next = vtg->vert_next;
1281fcf3ce44SJohn Forte 			else
1282fcf3ce44SJohn Forte 				stmf_state.stmf_ver_tg_head = vtg->vert_next;
1283fcf3ce44SJohn Forte 			kmem_free(vtg, sizeof (stmf_ver_tg_t));
1284fcf3ce44SJohn Forte 		}
1285fcf3ce44SJohn Forte 	}
1286fcf3ce44SJohn Forte 
1287fcf3ce44SJohn Forte 	if (stmf_state.stmf_service_running && ilu &&
1288fcf3ce44SJohn Forte 	    ilu->ilu_state == STMF_STATE_ONLINE) {
1289fcf3ce44SJohn Forte 		stmf_update_sessions_per_ve(ve, ilu->ilu_lu, 0);
1290fcf3ce44SJohn Forte 	}
1291fcf3ce44SJohn Forte 
1292fcf3ce44SJohn Forte 	ve->ve_hg->id_refcnt--;
1293fcf3ce44SJohn Forte 	ve->ve_tg->id_refcnt--;
1294fcf3ce44SJohn Forte 
1295fcf3ce44SJohn Forte 	kmem_free(ve, sizeof (stmf_view_entry_t));
1296fcf3ce44SJohn Forte 	return (0);
1297fcf3ce44SJohn Forte }
1298fcf3ce44SJohn Forte 
1299fcf3ce44SJohn Forte int
stmf_add_group(uint8_t * grpname,uint16_t grpname_size,stmf_id_type_t group_type,uint32_t * err_detail)1300fcf3ce44SJohn Forte stmf_add_group(uint8_t *grpname, uint16_t grpname_size,
1301fcf3ce44SJohn Forte     stmf_id_type_t group_type, uint32_t *err_detail)
1302fcf3ce44SJohn Forte {
1303fcf3ce44SJohn Forte 	stmf_status_t status;
1304fcf3ce44SJohn Forte 
1305fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
1306fcf3ce44SJohn Forte 
1307fcf3ce44SJohn Forte 	if (group_type == STMF_ID_TYPE_HOST_GROUP)
1308fcf3ce44SJohn Forte 		status = stmf_add_hg(grpname, grpname_size, 0, err_detail);
1309fcf3ce44SJohn Forte 	else if (group_type == STMF_ID_TYPE_TARGET_GROUP)
1310fcf3ce44SJohn Forte 		status = stmf_add_tg(grpname, grpname_size, 0, err_detail);
1311fcf3ce44SJohn Forte 	else {
1312fcf3ce44SJohn Forte 		return (EINVAL);
1313fcf3ce44SJohn Forte 	}
1314fcf3ce44SJohn Forte 	switch (status) {
1315fcf3ce44SJohn Forte 	case STMF_SUCCESS:
1316fcf3ce44SJohn Forte 		return (0);
1317fcf3ce44SJohn Forte 	case STMF_INVALID_ARG:
1318fcf3ce44SJohn Forte 		return (EINVAL);
1319fcf3ce44SJohn Forte 	case STMF_ALREADY:
1320fcf3ce44SJohn Forte 		return (EEXIST);
1321fcf3ce44SJohn Forte 	default:
1322fcf3ce44SJohn Forte 		return (EIO);
1323fcf3ce44SJohn Forte 	}
1324fcf3ce44SJohn Forte }
1325fcf3ce44SJohn Forte 
1326fcf3ce44SJohn Forte /*
1327fcf3ce44SJohn Forte  * Group can only be removed only when it does not have
1328fcf3ce44SJohn Forte  * any view entry related
1329fcf3ce44SJohn Forte  */
1330fcf3ce44SJohn Forte int
stmf_remove_group(uint8_t * grpname,uint16_t grpname_size,stmf_id_type_t group_type,uint32_t * err_detail)1331fcf3ce44SJohn Forte stmf_remove_group(uint8_t *grpname, uint16_t grpname_size,
1332fcf3ce44SJohn Forte     stmf_id_type_t group_type, uint32_t *err_detail)
1333fcf3ce44SJohn Forte {
1334fcf3ce44SJohn Forte 	stmf_id_data_t *id;
1335fcf3ce44SJohn Forte 	stmf_id_data_t *idmemb;
1336fcf3ce44SJohn Forte 	stmf_id_list_t *grp_memblist;
1337fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss;
1338fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
1339fcf3ce44SJohn Forte 
1340fcf3ce44SJohn Forte 	if (grpname[0] == '*')
1341fcf3ce44SJohn Forte 		return (EINVAL);
1342fcf3ce44SJohn Forte 
1343fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
1344fcf3ce44SJohn Forte 
1345fcf3ce44SJohn Forte 	if (group_type == STMF_ID_TYPE_HOST_GROUP)
1346fcf3ce44SJohn Forte 		id = stmf_lookup_id(&stmf_state.stmf_hg_list,
1347fcf3ce44SJohn Forte 		    grpname_size, grpname);
1348fcf3ce44SJohn Forte 	else if (group_type == STMF_ID_TYPE_TARGET_GROUP)
1349fcf3ce44SJohn Forte 		id = stmf_lookup_id(&stmf_state.stmf_tg_list,
1350fcf3ce44SJohn Forte 		    grpname_size, grpname);
1351fcf3ce44SJohn Forte 	if (!id) {
1352fcf3ce44SJohn Forte 		*err_detail = (group_type == STMF_ID_TYPE_HOST_GROUP)?
1353fcf3ce44SJohn Forte 		    STMF_IOCERR_INVALID_HG:STMF_IOCERR_INVALID_TG;
1354fcf3ce44SJohn Forte 		return (ENODEV); /* no such grp */
1355fcf3ce44SJohn Forte 	}
1356fcf3ce44SJohn Forte 	if (id->id_refcnt) {
1357fcf3ce44SJohn Forte 		/* fail, still have viewentry related to it */
1358fcf3ce44SJohn Forte 		*err_detail = (group_type == STMF_ID_TYPE_HOST_GROUP)?
1359fcf3ce44SJohn Forte 		    STMF_IOCERR_HG_IN_USE:STMF_IOCERR_TG_IN_USE;
1360fcf3ce44SJohn Forte 		return (EBUSY);
1361fcf3ce44SJohn Forte 	}
1362fcf3ce44SJohn Forte 	grp_memblist = (stmf_id_list_t *)id->id_impl_specific;
1363fcf3ce44SJohn Forte 	while ((idmemb = grp_memblist->idl_head) != NULL) {
1364fcf3ce44SJohn Forte 		stmf_remove_id(grp_memblist, idmemb);
1365fcf3ce44SJohn Forte 		stmf_free_id(idmemb);
1366fcf3ce44SJohn Forte 	}
1367fcf3ce44SJohn Forte 
1368fcf3ce44SJohn Forte 	ASSERT(!grp_memblist->id_count);
1369fcf3ce44SJohn Forte 	if (id->id_type == STMF_ID_TYPE_TARGET_GROUP) {
1370fcf3ce44SJohn Forte 		for (ilport = stmf_state.stmf_ilportlist; ilport;
1371fcf3ce44SJohn Forte 		    ilport = ilport->ilport_next) {
1372fcf3ce44SJohn Forte 			if (ilport->ilport_tg == (void *)id) {
1373fcf3ce44SJohn Forte 				ilport->ilport_tg = NULL;
1374fcf3ce44SJohn Forte 			}
1375fcf3ce44SJohn Forte 		}
1376fcf3ce44SJohn Forte 		stmf_remove_id(&stmf_state.stmf_tg_list, id);
1377fcf3ce44SJohn Forte 	} else {
1378fcf3ce44SJohn Forte 		for (ilport = stmf_state.stmf_ilportlist; ilport;
1379fcf3ce44SJohn Forte 		    ilport = ilport->ilport_next) {
1380fcf3ce44SJohn Forte 			for (iss = ilport->ilport_ss_list; iss;
1381fcf3ce44SJohn Forte 			    iss = iss->iss_next) {
1382fcf3ce44SJohn Forte 				if (iss->iss_hg == (void *)id)
1383fcf3ce44SJohn Forte 					iss->iss_hg = NULL;
1384fcf3ce44SJohn Forte 			}
1385fcf3ce44SJohn Forte 		}
1386fcf3ce44SJohn Forte 		stmf_remove_id(&stmf_state.stmf_hg_list, id);
1387fcf3ce44SJohn Forte 	}
1388fcf3ce44SJohn Forte 	stmf_free_id(id);
1389fcf3ce44SJohn Forte 	return (0);
1390fcf3ce44SJohn Forte 
1391fcf3ce44SJohn Forte }
1392fcf3ce44SJohn Forte 
1393fcf3ce44SJohn Forte 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)1394fcf3ce44SJohn Forte stmf_add_group_member(uint8_t *grpname, uint16_t grpname_size,
1395fcf3ce44SJohn Forte     uint8_t *entry_ident, uint16_t entry_size,
1396fcf3ce44SJohn Forte     stmf_id_type_t entry_type, uint32_t *err_detail)
1397fcf3ce44SJohn Forte {
1398fcf3ce44SJohn Forte 	stmf_id_data_t	*id_grp, *id_alltgt;
1399fcf3ce44SJohn Forte 	stmf_id_data_t	*id_member;
1400fcf3ce44SJohn Forte 	stmf_id_data_t	*id_grp_tmp;
1401fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss;
1402fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
1403fcf3ce44SJohn Forte 	stmf_lun_map_t *vemap, *vemap_alltgt;
1404fcf3ce44SJohn Forte 	uint8_t grpname_forall = '*';
1405fcf3ce44SJohn Forte 
1406fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
1407fcf3ce44SJohn Forte 	ASSERT(grpname[0] != '*');
1408fcf3ce44SJohn Forte 
1409fcf3ce44SJohn Forte 	if (entry_type == STMF_ID_TYPE_HOST) {
1410fcf3ce44SJohn Forte 		id_grp = stmf_lookup_id(&stmf_state.stmf_hg_list,
1411fcf3ce44SJohn Forte 		    grpname_size, grpname);
1412fcf3ce44SJohn Forte 		id_grp_tmp = stmf_lookup_group_for_host(entry_ident,
1413fcf3ce44SJohn Forte 		    entry_size);
1414fcf3ce44SJohn Forte 	} else {
1415fcf3ce44SJohn Forte 		id_grp = stmf_lookup_id(&stmf_state.stmf_tg_list,
1416fcf3ce44SJohn Forte 		    grpname_size, grpname);
1417fcf3ce44SJohn Forte 		id_grp_tmp = stmf_lookup_group_for_target(entry_ident,
1418fcf3ce44SJohn Forte 		    entry_size);
1419fcf3ce44SJohn Forte 	}
1420fcf3ce44SJohn Forte 	if (id_grp == NULL) {
1421fcf3ce44SJohn Forte 		*err_detail = (entry_type == STMF_ID_TYPE_HOST)?
1422fcf3ce44SJohn Forte 		    STMF_IOCERR_INVALID_HG:STMF_IOCERR_INVALID_TG;
1423fcf3ce44SJohn Forte 		return (ENODEV); /* not found */
1424fcf3ce44SJohn Forte 	}
1425fcf3ce44SJohn Forte 
1426fcf3ce44SJohn Forte 	/* Check whether this member already bound to a group */
1427fcf3ce44SJohn Forte 	if (id_grp_tmp) {
1428fcf3ce44SJohn Forte 		if (id_grp_tmp != id_grp) {
1429fcf3ce44SJohn Forte 			*err_detail = (entry_type == STMF_ID_TYPE_HOST)?
1430fcf3ce44SJohn Forte 			    STMF_IOCERR_HG_ENTRY_EXISTS:
1431fcf3ce44SJohn Forte 			    STMF_IOCERR_TG_ENTRY_EXISTS;
1432fcf3ce44SJohn Forte 			return (EEXIST); /* already added into another grp */
1433fcf3ce44SJohn Forte 		}
1434fcf3ce44SJohn Forte 		else
1435fcf3ce44SJohn Forte 			return (0);
1436fcf3ce44SJohn Forte 	}
1437f80ea9bbStim szeto 
1438f80ea9bbStim szeto 	/* verify target is offline */
1439f80ea9bbStim szeto 	if (entry_type == STMF_ID_TYPE_TARGET) {
1440f80ea9bbStim szeto 		ilport = stmf_targetident_to_ilport(entry_ident, entry_size);
1441f80ea9bbStim szeto 		if (ilport && ilport->ilport_state != STMF_STATE_OFFLINE) {
1442f80ea9bbStim szeto 			*err_detail = STMF_IOCERR_TG_NEED_TG_OFFLINE;
1443f80ea9bbStim szeto 			return (EBUSY);
1444f80ea9bbStim szeto 		}
1445f80ea9bbStim szeto 	}
1446f80ea9bbStim szeto 
1447fcf3ce44SJohn Forte 	id_member = stmf_alloc_id(entry_size, entry_type,
1448fcf3ce44SJohn Forte 	    entry_ident, 0);
1449fcf3ce44SJohn Forte 	stmf_append_id((stmf_id_list_t *)id_grp->id_impl_specific, id_member);
1450fcf3ce44SJohn Forte 
1451fcf3ce44SJohn Forte 	if (entry_type == STMF_ID_TYPE_TARGET) {
1452fcf3ce44SJohn Forte 		ilport = stmf_targetident_to_ilport(entry_ident, entry_size);
1453fcf3ce44SJohn Forte 		if (ilport)
1454fcf3ce44SJohn Forte 			ilport->ilport_tg = (void *)id_grp;
1455fcf3ce44SJohn Forte 		return (0);
1456fcf3ce44SJohn Forte 	}
1457fcf3ce44SJohn Forte 	/* For host group member, update the session if needed */
1458fcf3ce44SJohn Forte 	if (!stmf_state.stmf_service_running)
1459fcf3ce44SJohn Forte 		return (0);
1460fcf3ce44SJohn Forte 	/* Need to consider all target group + this host group */
1461fcf3ce44SJohn Forte 	id_alltgt = stmf_lookup_id(&stmf_state.stmf_tg_list,
1462fcf3ce44SJohn Forte 	    1, &grpname_forall);
1463fcf3ce44SJohn Forte 	vemap_alltgt = stmf_get_ve_map_per_ids(id_alltgt, id_grp);
1464fcf3ce44SJohn Forte 
1465fcf3ce44SJohn Forte 	/* check whether there are sessions may be affected */
1466fcf3ce44SJohn Forte 	for (ilport = stmf_state.stmf_ilportlist; ilport;
1467fcf3ce44SJohn Forte 	    ilport = ilport->ilport_next) {
1468fcf3ce44SJohn Forte 		if (ilport->ilport_state != STMF_STATE_ONLINE)
1469fcf3ce44SJohn Forte 			continue;
1470fcf3ce44SJohn Forte 		iss = stmf_lookup_session_for_hostident(ilport,
1471fcf3ce44SJohn Forte 		    entry_ident, entry_size);
1472fcf3ce44SJohn Forte 		if (iss) {
1473fcf3ce44SJohn Forte 			stmf_id_data_t *tgid;
1474fcf3ce44SJohn Forte 			iss->iss_hg = (void *)id_grp;
1475fcf3ce44SJohn Forte 			tgid = ilport->ilport_tg;
147661dfa509SRick McNeal 			rw_enter(iss->iss_lockp, RW_WRITER);
1477fcf3ce44SJohn Forte 			if (tgid) {
1478fcf3ce44SJohn Forte 				vemap = stmf_get_ve_map_per_ids(tgid, id_grp);
1479fcf3ce44SJohn Forte 				if (vemap)
1480fcf3ce44SJohn Forte 					stmf_add_lus_to_session_per_vemap(
1481fcf3ce44SJohn Forte 					    ilport, iss, vemap);
1482fcf3ce44SJohn Forte 			}
1483fcf3ce44SJohn Forte 			if (vemap_alltgt)
1484fcf3ce44SJohn Forte 				stmf_add_lus_to_session_per_vemap(ilport,
1485fcf3ce44SJohn Forte 				    iss, vemap_alltgt);
148661dfa509SRick McNeal 			rw_exit(iss->iss_lockp);
1487fcf3ce44SJohn Forte 		}
1488fcf3ce44SJohn Forte 	}
1489fcf3ce44SJohn Forte 
1490fcf3ce44SJohn Forte 	return (0);
1491fcf3ce44SJohn Forte }
1492fcf3ce44SJohn Forte 
1493fcf3ce44SJohn Forte 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)1494fcf3ce44SJohn Forte stmf_remove_group_member(uint8_t *grpname, uint16_t grpname_size,
1495fcf3ce44SJohn Forte     uint8_t *entry_ident, uint16_t entry_size,
1496fcf3ce44SJohn Forte     stmf_id_type_t entry_type, uint32_t *err_detail)
1497fcf3ce44SJohn Forte {
1498fcf3ce44SJohn Forte 	stmf_id_data_t	*id_grp, *id_alltgt;
1499fcf3ce44SJohn Forte 	stmf_id_data_t	*id_member;
1500fcf3ce44SJohn Forte 	stmf_lun_map_t *vemap,  *vemap_alltgt;
1501fcf3ce44SJohn Forte 	uint8_t grpname_forall = '*';
1502fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
1503fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss;
1504fcf3ce44SJohn Forte 
1505fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
1506fcf3ce44SJohn Forte 	ASSERT(grpname[0] != '*');
1507fcf3ce44SJohn Forte 
1508fcf3ce44SJohn Forte 	if (entry_type == STMF_ID_TYPE_HOST) {
1509fcf3ce44SJohn Forte 		id_grp = stmf_lookup_id(&stmf_state.stmf_hg_list,
1510fcf3ce44SJohn Forte 		    grpname_size, grpname);
1511fcf3ce44SJohn Forte 	} else {
1512fcf3ce44SJohn Forte 		id_grp = stmf_lookup_id(&stmf_state.stmf_tg_list,
1513fcf3ce44SJohn Forte 		    grpname_size, grpname);
1514fcf3ce44SJohn Forte 	}
1515fcf3ce44SJohn Forte 	if (id_grp == NULL) {
1516fcf3ce44SJohn Forte 		*err_detail = (entry_type == STMF_ID_TYPE_HOST)?
1517fcf3ce44SJohn Forte 		    STMF_IOCERR_INVALID_HG:STMF_IOCERR_INVALID_TG;
1518fcf3ce44SJohn Forte 		return (ENODEV); /* no such group */
1519fcf3ce44SJohn Forte 	}
1520fcf3ce44SJohn Forte 	id_member = stmf_lookup_id((stmf_id_list_t *)id_grp->id_impl_specific,
1521fcf3ce44SJohn Forte 	    entry_size, entry_ident);
1522fcf3ce44SJohn Forte 	if (!id_member) {
1523fcf3ce44SJohn Forte 		*err_detail = (entry_type == STMF_ID_TYPE_HOST)?
1524fcf3ce44SJohn Forte 		    STMF_IOCERR_INVALID_HG_ENTRY:STMF_IOCERR_INVALID_TG_ENTRY;
1525fcf3ce44SJohn Forte 		return (ENODEV); /* no such member */
1526fcf3ce44SJohn Forte 	}
15275c8cac22Stim szeto 	/* verify target is offline */
15285c8cac22Stim szeto 	if (entry_type == STMF_ID_TYPE_TARGET) {
15295c8cac22Stim szeto 		ilport = stmf_targetident_to_ilport(entry_ident, entry_size);
15305c8cac22Stim szeto 		if (ilport && ilport->ilport_state != STMF_STATE_OFFLINE) {
15315c8cac22Stim szeto 			*err_detail = STMF_IOCERR_TG_NEED_TG_OFFLINE;
15325c8cac22Stim szeto 			return (EBUSY);
15335c8cac22Stim szeto 		}
15345c8cac22Stim szeto 	}
15355c8cac22Stim szeto 
1536fcf3ce44SJohn Forte 	stmf_remove_id((stmf_id_list_t *)id_grp->id_impl_specific, id_member);
1537fcf3ce44SJohn Forte 	stmf_free_id(id_member);
1538fcf3ce44SJohn Forte 
1539fcf3ce44SJohn Forte 	if (entry_type == STMF_ID_TYPE_TARGET) {
1540fcf3ce44SJohn Forte 		ilport = stmf_targetident_to_ilport(entry_ident, entry_size);
1541fcf3ce44SJohn Forte 		if (ilport)
1542fcf3ce44SJohn Forte 			ilport->ilport_tg = NULL;
1543fcf3ce44SJohn Forte 		return (0);
1544fcf3ce44SJohn Forte 	}
1545fcf3ce44SJohn Forte 	/* For host group member, update the session */
1546fcf3ce44SJohn Forte 	if (!stmf_state.stmf_service_running)
1547fcf3ce44SJohn Forte 		return (0);
1548fcf3ce44SJohn Forte 
1549fcf3ce44SJohn Forte 	/* Need to consider all target group + this host group */
1550fcf3ce44SJohn Forte 	id_alltgt = stmf_lookup_id(&stmf_state.stmf_tg_list,
1551fcf3ce44SJohn Forte 	    1, &grpname_forall);
1552fcf3ce44SJohn Forte 	vemap_alltgt = stmf_get_ve_map_per_ids(id_alltgt, id_grp);
1553fcf3ce44SJohn Forte 
1554fcf3ce44SJohn Forte 	/* check if there are session related, if so, update it */
1555fcf3ce44SJohn Forte 	for (ilport = stmf_state.stmf_ilportlist; ilport;
1556fcf3ce44SJohn Forte 	    ilport = ilport->ilport_next) {
1557fcf3ce44SJohn Forte 		if (ilport->ilport_state != STMF_STATE_ONLINE)
1558fcf3ce44SJohn Forte 			continue;
1559fcf3ce44SJohn Forte 		iss = stmf_lookup_session_for_hostident(ilport,
1560fcf3ce44SJohn Forte 		    entry_ident, entry_size);
1561fcf3ce44SJohn Forte 		if (iss) {
1562fcf3ce44SJohn Forte 			stmf_id_data_t *tgid;
156361dfa509SRick McNeal 			rw_enter(iss->iss_lockp, RW_WRITER);
1564fcf3ce44SJohn Forte 			iss->iss_hg = NULL;
1565fcf3ce44SJohn Forte 			tgid = ilport->ilport_tg;
1566fcf3ce44SJohn Forte 			if (tgid) {
1567fcf3ce44SJohn Forte 				vemap = stmf_get_ve_map_per_ids(tgid, id_grp);
1568fcf3ce44SJohn Forte 				if (vemap)
1569fcf3ce44SJohn Forte 					stmf_remove_lus_from_session_per_vemap(
157061dfa509SRick McNeal 					    iss, vemap);
1571fcf3ce44SJohn Forte 			}
1572fcf3ce44SJohn Forte 			if (vemap_alltgt)
157361dfa509SRick McNeal 				stmf_remove_lus_from_session_per_vemap(iss,
157461dfa509SRick McNeal 				    vemap_alltgt);
157561dfa509SRick McNeal 			rw_exit(iss->iss_lockp);
1576fcf3ce44SJohn Forte 		}
1577fcf3ce44SJohn Forte 	}
1578fcf3ce44SJohn Forte 
1579fcf3ce44SJohn Forte 	return (0);
1580fcf3ce44SJohn Forte }
1581fcf3ce44SJohn Forte 
1582fcf3ce44SJohn Forte /* Assert stmf_lock is already held */
1583fcf3ce44SJohn Forte stmf_i_local_port_t *
stmf_targetident_to_ilport(uint8_t * target_ident,uint16_t ident_size)1584fcf3ce44SJohn Forte stmf_targetident_to_ilport(uint8_t *target_ident, uint16_t ident_size)
1585fcf3ce44SJohn Forte {
1586fcf3ce44SJohn Forte 	stmf_i_local_port_t *ilport;
1587fcf3ce44SJohn Forte 	uint8_t *id;
1588fcf3ce44SJohn Forte 
1589fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
1590fcf3ce44SJohn Forte 
1591fcf3ce44SJohn Forte 	for (ilport = stmf_state.stmf_ilportlist; ilport;
1592fcf3ce44SJohn Forte 	    ilport = ilport->ilport_next) {
1593fcf3ce44SJohn Forte 		id = (uint8_t *)ilport->ilport_lport->lport_id;
1594fcf3ce44SJohn Forte 		if ((id[3] == ident_size) &&
1595fcf3ce44SJohn Forte 		    bcmp(id + 4, target_ident, ident_size) == 0) {
1596fcf3ce44SJohn Forte 			return (ilport);
1597fcf3ce44SJohn Forte 		}
1598fcf3ce44SJohn Forte 	}
1599fcf3ce44SJohn Forte 	return (NULL);
1600fcf3ce44SJohn Forte }
1601fcf3ce44SJohn Forte 
1602fcf3ce44SJohn Forte stmf_i_scsi_session_t *
stmf_lookup_session_for_hostident(stmf_i_local_port_t * ilport,uint8_t * host_ident,uint16_t ident_size)1603fcf3ce44SJohn Forte stmf_lookup_session_for_hostident(stmf_i_local_port_t *ilport,
1604fcf3ce44SJohn Forte     uint8_t *host_ident, uint16_t ident_size)
1605fcf3ce44SJohn Forte {
1606fcf3ce44SJohn Forte 	stmf_i_scsi_session_t *iss;
1607fcf3ce44SJohn Forte 	uint8_t *id;
1608fcf3ce44SJohn Forte 
1609fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
1610fcf3ce44SJohn Forte 
1611fcf3ce44SJohn Forte 	for (iss = ilport->ilport_ss_list; iss; iss = iss->iss_next) {
1612fcf3ce44SJohn Forte 		id = (uint8_t *)iss->iss_ss->ss_rport_id;
1613fcf3ce44SJohn Forte 		if ((id[3] == ident_size) &&
1614fcf3ce44SJohn Forte 		    bcmp(id + 4, host_ident, ident_size) == 0) {
1615fcf3ce44SJohn Forte 			return (iss);
1616fcf3ce44SJohn Forte 		}
1617fcf3ce44SJohn Forte 	}
1618fcf3ce44SJohn Forte 	return (NULL);
1619fcf3ce44SJohn Forte }
1620fcf3ce44SJohn Forte 
1621fcf3ce44SJohn Forte stmf_i_lu_t *
stmf_luident_to_ilu(uint8_t * lu_ident)1622fcf3ce44SJohn Forte stmf_luident_to_ilu(uint8_t *lu_ident)
1623fcf3ce44SJohn Forte {
1624fcf3ce44SJohn Forte 	stmf_i_lu_t *ilu;
1625fcf3ce44SJohn Forte 
1626fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
1627fcf3ce44SJohn Forte 
1628fcf3ce44SJohn Forte 	for (ilu = stmf_state.stmf_ilulist; ilu; ilu = ilu->ilu_next) {
1629fcf3ce44SJohn Forte 		if (bcmp(&ilu->ilu_lu->lu_id->ident[0], lu_ident, 16) == 0)
1630fcf3ce44SJohn Forte 			return (ilu);
1631fcf3ce44SJohn Forte 	}
1632fcf3ce44SJohn Forte 
1633fcf3ce44SJohn Forte 	return (NULL);
1634fcf3ce44SJohn Forte }
1635fcf3ce44SJohn Forte 
1636fcf3ce44SJohn Forte /*
1637fcf3ce44SJohn Forte  * Assert stmf_lock is already held,
1638fcf3ce44SJohn Forte  * Just get the view map for the specific target group and host group
1639fcf3ce44SJohn Forte  * tgid and hgid can not be NULL
1640fcf3ce44SJohn Forte  */
1641fcf3ce44SJohn Forte stmf_lun_map_t *
stmf_get_ve_map_per_ids(stmf_id_data_t * tgid,stmf_id_data_t * hgid)1642fcf3ce44SJohn Forte stmf_get_ve_map_per_ids(stmf_id_data_t *tgid, stmf_id_data_t *hgid)
1643fcf3ce44SJohn Forte {
1644fcf3ce44SJohn Forte 	int found = 0;
1645fcf3ce44SJohn Forte 	stmf_ver_tg_t *vertg;
1646fcf3ce44SJohn Forte 	stmf_ver_hg_t *verhg;
1647fcf3ce44SJohn Forte 
1648fcf3ce44SJohn Forte 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
1649fcf3ce44SJohn Forte 
1650fcf3ce44SJohn Forte 	for (vertg = stmf_state.stmf_ver_tg_head;
1651fcf3ce44SJohn Forte 	    vertg; vertg = vertg->vert_next) {
1652fcf3ce44SJohn Forte 		if (vertg->vert_tg_ref == tgid) {
1653fcf3ce44SJohn Forte 			found = 1;
1654fcf3ce44SJohn Forte 			break;
1655fcf3ce44SJohn Forte 		}
1656fcf3ce44SJohn Forte 	}
1657fcf3ce44SJohn Forte 	if (!found)
1658fcf3ce44SJohn Forte 		return (NULL);
1659fcf3ce44SJohn Forte 
1660fcf3ce44SJohn Forte 	for (verhg = vertg->vert_verh_list; verhg; verhg = verhg->verh_next) {
1661fcf3ce44SJohn Forte 		if (verhg->verh_hg_ref == hgid) {
1662fcf3ce44SJohn Forte 			return (&verhg->verh_ve_map);
1663fcf3ce44SJohn Forte 		}
1664fcf3ce44SJohn Forte 	}
1665fcf3ce44SJohn Forte 	return (NULL);
1666fcf3ce44SJohn Forte }
166763ed874aStim szeto 
166863ed874aStim szeto 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)166963ed874aStim szeto stmf_validate_lun_view_entry(stmf_id_data_t *hg, stmf_id_data_t *tg,
167063ed874aStim szeto     uint8_t *lun, uint32_t *err_detail)
167163ed874aStim szeto {
167263ed874aStim szeto 	char			*phg, *ptg;
167363ed874aStim szeto 	stmf_lun_map_t		*ve_map = NULL;
167463ed874aStim szeto 	stmf_ver_hg_t		*verhg = NULL;
167563ed874aStim szeto 	stmf_ver_tg_t		*vertg = NULL;
167663ed874aStim szeto 	uint16_t		lun_num;
167763ed874aStim szeto 	stmf_status_t		ret = STMF_SUCCESS;
167863ed874aStim szeto 
167963ed874aStim szeto 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
168063ed874aStim szeto 
168163ed874aStim szeto 	ve_map = stmf_duplicate_ve_map(0);
168263ed874aStim szeto 	for (vertg = stmf_state.stmf_ver_tg_head; vertg != NULL;
168363ed874aStim szeto 	    vertg = vertg->vert_next) {
168463ed874aStim szeto 		ptg = (char *)vertg->vert_tg_ref->id_data;
168563ed874aStim szeto 		if ((ptg[0] != '*') && (tg->id_data[0] != '*') &&
168663ed874aStim szeto 		    (vertg->vert_tg_ref != tg)) {
168763ed874aStim szeto 			continue;
168863ed874aStim szeto 		}
168963ed874aStim szeto 		for (verhg = vertg->vert_verh_list; verhg != NULL;
169063ed874aStim szeto 		    verhg = verhg->verh_next) {
169163ed874aStim szeto 			phg = (char *)verhg->verh_hg_ref->id_data;
169263ed874aStim szeto 			if ((phg[0] != '*') && (hg->id_data[0] != '*') &&
169363ed874aStim szeto 			    (verhg->verh_hg_ref != hg)) {
169463ed874aStim szeto 				continue;
169563ed874aStim szeto 			}
169663ed874aStim szeto 			(void) stmf_merge_ve_map(&verhg->verh_ve_map, ve_map,
169763ed874aStim szeto 			    &ve_map, 0);
169863ed874aStim szeto 		}
169963ed874aStim szeto 	}
170063ed874aStim szeto 
170163ed874aStim szeto 	ret = STMF_SUCCESS;
170263ed874aStim szeto 	/* Return an available lun number */
170363ed874aStim szeto 	if (lun[2] == 0xFF) {
170463ed874aStim szeto 		/* Pick a LUN number */
170563ed874aStim szeto 		lun_num = stmf_get_next_free_lun(ve_map, lun);
170663ed874aStim szeto 		if (lun_num > 0x3FFF)
170763ed874aStim szeto 			ret = STMF_NOT_SUPPORTED;
170863ed874aStim szeto 	} else {
170963ed874aStim szeto 		lun_num = (uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8);
171063ed874aStim szeto 		if (stmf_get_ent_from_map(ve_map, lun_num) != NULL) {
171163ed874aStim szeto 			*err_detail = STMF_IOCERR_LU_NUMBER_IN_USE;
171263ed874aStim szeto 			ret = STMF_LUN_TAKEN;
171363ed874aStim szeto 		}
171463ed874aStim szeto 	}
171563ed874aStim szeto 	stmf_destroy_ve_map(ve_map);
171663ed874aStim szeto 
171763ed874aStim szeto 	return (ret);
171863ed874aStim szeto }
171963ed874aStim szeto 
172063ed874aStim szeto 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)172163ed874aStim szeto stmf_validate_lun_ve(uint8_t *hgname, uint16_t hgname_size,
172263ed874aStim szeto     uint8_t *tgname, uint16_t tgname_size,
172363ed874aStim szeto     uint8_t *luNbr, uint32_t *err_detail)
172463ed874aStim szeto {
172563ed874aStim szeto 	stmf_id_data_t		*hg;
172663ed874aStim szeto 	stmf_id_data_t		*tg;
172763ed874aStim szeto 	stmf_status_t		ret;
172863ed874aStim szeto 
172963ed874aStim szeto 	ASSERT(mutex_owned(&stmf_state.stmf_lock));
173063ed874aStim szeto 
173163ed874aStim szeto 	hg = stmf_lookup_id(&stmf_state.stmf_hg_list, hgname_size,
173263ed874aStim szeto 	    (uint8_t *)hgname);
173363ed874aStim szeto 	if (!hg) {
173463ed874aStim szeto 		*err_detail = STMF_IOCERR_INVALID_HG;
173563ed874aStim szeto 		return (ENOENT); /* could not find group */
173663ed874aStim szeto 	}
173763ed874aStim szeto 	tg = stmf_lookup_id(&stmf_state.stmf_tg_list, tgname_size,
173863ed874aStim szeto 	    (uint8_t *)tgname);
173963ed874aStim szeto 	if (!tg) {
174063ed874aStim szeto 		*err_detail = STMF_IOCERR_INVALID_TG;
174163ed874aStim szeto 		return (ENOENT); /* could not find group */
174263ed874aStim szeto 	}
174363ed874aStim szeto 	ret = stmf_validate_lun_view_entry(hg, tg, luNbr, err_detail);
174463ed874aStim szeto 
174563ed874aStim szeto 	if (ret == STMF_LUN_TAKEN) {
174663ed874aStim szeto 		return (EEXIST);
174763ed874aStim szeto 	} else if (ret == STMF_NOT_SUPPORTED) {
174863ed874aStim szeto 		return (E2BIG);
174963ed874aStim szeto 	} else if (ret != STMF_SUCCESS) {
175063ed874aStim szeto 		return (EINVAL);
175163ed874aStim szeto 	}
175263ed874aStim szeto 	return (0);
175363ed874aStim szeto }
1754