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