30 #include <sys/scsi/scsi.h>
  31 #include <sys/scsi/impl/scsi_reset_notify.h>
  32 #include <sys/disp.h>
  33 #include <sys/byteorder.h>
  34 #include <sys/atomic.h>
  35 
  36 #include <sys/stmf.h>
  37 #include <sys/lpif.h>
  38 #include <sys/portif.h>
  39 #include <sys/stmf_ioctl.h>
  40 
  41 #include "stmf_impl.h"
  42 #include "lun_map.h"
  43 #include "stmf_state.h"
  44 
  45 void stmf_update_sessions_per_ve(stmf_view_entry_t *ve,
  46                 stmf_lu_t *lu, int action);
  47 void stmf_add_lus_to_session_per_vemap(stmf_i_local_port_t *ilport,
  48                 stmf_i_scsi_session_t *iss, stmf_lun_map_t *vemap);
  49 stmf_id_data_t *stmf_lookup_group_for_host(uint8_t *ident, uint16_t ident_size);
  50 stmf_status_t stmf_add_ent_to_map(stmf_lun_map_t *sm, void *ent, uint8_t *lun);
  51 stmf_status_t stmf_remove_ent_from_map(stmf_lun_map_t *sm, uint8_t *lun);
  52 uint16_t stmf_get_next_free_lun(stmf_lun_map_t *sm, uint8_t *lun);
  53 stmf_status_t stmf_add_tg(uint8_t *tg_name, uint16_t tg_name_size,
  54                 int allow_special, uint32_t *err_detail);
  55 stmf_status_t stmf_add_hg(uint8_t *hg_name, uint16_t hg_name_size,
  56                 int allow_special, uint32_t *err_detail);
  57 stmf_i_local_port_t *stmf_targetident_to_ilport(uint8_t *target_ident,
  58                 uint16_t ident_size);
  59 stmf_i_scsi_session_t *stmf_lookup_session_for_hostident(
  60                 stmf_i_local_port_t *ilport, uint8_t *host_ident,
  61                 uint16_t ident_size);
  62 stmf_i_lu_t *stmf_luident_to_ilu(uint8_t *lu_ident);
  63 stmf_lun_map_t *stmf_get_ve_map_per_ids(stmf_id_data_t *tgid,
  64                 stmf_id_data_t *hgid);
  65 stmf_lun_map_t *stmf_duplicate_ve_map(stmf_lun_map_t *src);
  66 int stmf_merge_ve_map(stmf_lun_map_t *src, stmf_lun_map_t *dst,
  67                 stmf_lun_map_t **pp_ret_map, stmf_merge_flags_t mf);
  68 void stmf_destroy_ve_map(stmf_lun_map_t *dst);
  69 void stmf_free_id(stmf_id_data_t *id);
  70 
  71 
 
 
 162                                         idmemb_next = idmemb->id_next;
 163                                         stmf_free_id(idmemb);
 164                                 }
 165                         }
 166                         idgrp_next = idgrp->id_next;
 167                         stmf_free_id(idgrp);
 168                 }
 169                 stmf_state.stmf_tg_list.id_count = 0;
 170                 stmf_state.stmf_tg_list.idl_head =
 171                     stmf_state.stmf_tg_list.idl_tail = NULL;
 172         }
 173 
 174         for (ilport = stmf_state.stmf_ilportlist; ilport;
 175             ilport = ilport->ilport_next) {
 176                 ilport->ilport_tg = NULL;
 177         }
 178 }
 179 
 180 /*
 181  * Create luns map for session based on the view
 182  */
 183 stmf_status_t
 184 stmf_session_create_lun_map(stmf_i_local_port_t *ilport,
 185                 stmf_i_scsi_session_t *iss)
 186 {
 187         stmf_id_data_t *tg;
 188         stmf_id_data_t *hg;
 189         stmf_ver_tg_t   *vertg;
 190         char *phg_data, *ptg_data;
 191         stmf_ver_hg_t   *verhg;
 192         stmf_lun_map_t  *ve_map;
 193 
 194         ASSERT(mutex_owned(&stmf_state.stmf_lock));
 195 
 196         tg = ilport->ilport_tg;
 197         hg = stmf_lookup_group_for_host(iss->iss_ss->ss_rport_id->ident,
 198             iss->iss_ss->ss_rport_id->ident_length);
 199         iss->iss_hg = hg;
 200 
 201         /*
 
 219                             (verhg->verh_hg_ref != hg)))) {
 220                                 continue;
 221                         }
 222                         (void) stmf_merge_ve_map(&verhg->verh_ve_map, ve_map,
 223                             &ve_map, 0);
 224                 }
 225         }
 226 
 227 
 228         if (ve_map->lm_nluns) {
 229                 stmf_add_lus_to_session_per_vemap(ilport, iss, ve_map);
 230         }
 231         /* not configured, cannot access any luns for now */
 232 
 233         stmf_destroy_ve_map(ve_map);
 234 
 235         return (STMF_SUCCESS);
 236 }
 237 
 238 /*
 239  * destroy lun map for session
 240  */
 241 /* ARGSUSED */
 242 stmf_status_t
 243 stmf_session_destroy_lun_map(stmf_i_local_port_t *ilport,
 244                 stmf_i_scsi_session_t *iss)
 245 {
 246         stmf_lun_map_t *sm;
 247         stmf_i_lu_t *ilu;
 248         uint16_t n;
 249         stmf_lun_map_ent_t *ent;
 250 
 251         ASSERT(mutex_owned(&stmf_state.stmf_lock));
 252         /*
 253          * to avoid conflict with updating session's map,
 254          * which only grab stmf_lock
 255          */
 256         sm = iss->iss_sm;
 257         iss->iss_sm = NULL;
 258         iss->iss_hg = NULL;
 259         if (sm->lm_nentries) {
 260                 for (n = 0; n < sm->lm_nentries; n++) {
 261                         if ((ent = (stmf_lun_map_ent_t *)sm->lm_plus[n])
 262                             != NULL) {
 263                                 if (ent->ent_itl_datap) {
 264                                         stmf_do_itl_dereg(ent->ent_lu,
 265                                             ent->ent_itl_datap,
 266                                             STMF_ITL_REASON_IT_NEXUS_LOSS);
 267                                 }
 268                                 ilu = (stmf_i_lu_t *)
 269                                     ent->ent_lu->lu_stmf_private;
 270                                 atomic_dec_32(&ilu->ilu_ref_cnt);
 271                                 kmem_free(sm->lm_plus[n],
 272                                     sizeof (stmf_lun_map_ent_t));
 273                         }
 274                 }
 275                 kmem_free(sm->lm_plus,
 276                     sizeof (stmf_lun_map_ent_t *) * sm->lm_nentries);
 277         }
 278 
 279         kmem_free(sm, sizeof (*sm));
 280         return (STMF_SUCCESS);
 281 }
 282 
 283 /*
 284  * Expects the session lock to be held.
 285  */
 286 stmf_xfer_data_t *
 287 stmf_session_prepare_report_lun_data(stmf_lun_map_t *sm)
 288 {
 289         stmf_xfer_data_t *xd;
 290         uint16_t nluns, ent;
 291         uint32_t alloc_size, data_size;
 292         int i;
 293 
 294         nluns = sm->lm_nluns;
 295 
 296         data_size = 8 + (((uint32_t)nluns) << 3);
 297         if (nluns == 0) {
 298                 data_size += 8;
 299         }
 300         alloc_size = data_size + sizeof (stmf_xfer_data_t) - 4;
 301 
 302         xd = (stmf_xfer_data_t *)kmem_zalloc(alloc_size, KM_NOSLEEP);
 303 
 304         if (xd == NULL)
 
 373                 return;
 374 
 375         luid = ((stmf_i_lu_t *)lu->lu_stmf_private)->ilu_luid;
 376         if (!luid) {
 377                 /*
 378                  * we did not configure view for this lun, this should be
 379                  * an error
 380                  */
 381                 return;
 382         }
 383 
 384         for (ve = (stmf_view_entry_t *)luid->id_impl_specific;
 385             ve; ve = ve->ve_next) {
 386                 stmf_update_sessions_per_ve(ve, lu, 0);
 387                 if (ilu->ilu_ref_cnt == 0)
 388                         break;
 389         }
 390 }
 391 /*
 392  * add lu to a session, stmf_lock is already held
 393  */
 394 stmf_status_t
 395 stmf_add_lu_to_session(stmf_i_local_port_t *ilport,
 396                 stmf_i_scsi_session_t   *iss,
 397                 stmf_lu_t *lu,
 398                 uint8_t *lu_nbr)
 399 {
 400         stmf_lun_map_t *sm = iss->iss_sm;
 401         stmf_status_t ret;
 402         stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
 403         stmf_lun_map_ent_t *lun_map_ent;
 404         uint32_t new_flags = 0;
 405         uint16_t luNbr =
 406             ((uint16_t)lu_nbr[1] | (((uint16_t)(lu_nbr[0] & 0x3F)) << 8));
 407 
 408         ASSERT(mutex_owned(&stmf_state.stmf_lock));
 409         ASSERT(!stmf_get_ent_from_map(sm, luNbr));
 410 
 411         if ((sm->lm_nluns == 0) &&
 412             ((iss->iss_flags & ISS_BEING_CREATED) == 0)) {
 413                 new_flags = ISS_GOT_INITIAL_LUNS;
 414                 atomic_or_32(&ilport->ilport_flags, ILPORT_SS_GOT_INITIAL_LUNS);
 
 417 
 418         lun_map_ent = (stmf_lun_map_ent_t *)
 419             kmem_zalloc(sizeof (stmf_lun_map_ent_t), KM_SLEEP);
 420         lun_map_ent->ent_lu = lu;
 421         ret = stmf_add_ent_to_map(sm, (void *)lun_map_ent, lu_nbr);
 422         ASSERT(ret == STMF_SUCCESS);
 423         atomic_inc_32(&ilu->ilu_ref_cnt);
 424         /*
 425          * do not set lun inventory flag for standby port
 426          * as this would be handled from peer
 427          */
 428         if (ilport->ilport_standby == 0) {
 429                 new_flags |= ISS_LUN_INVENTORY_CHANGED;
 430         }
 431         atomic_or_32(&iss->iss_flags, new_flags);
 432         return (STMF_SUCCESS);
 433 }
 434 
 435 /*
 436  * remvoe lu from a session, stmf_lock is already held
 437  */
 438 /* ARGSUSED */
 439 stmf_status_t
 440 stmf_remove_lu_from_session(stmf_i_local_port_t *ilport,
 441                 stmf_i_scsi_session_t *iss,
 442                 stmf_lu_t *lu,
 443                 uint8_t *lu_nbr)
 444 {
 445         stmf_status_t ret;
 446         stmf_i_lu_t *ilu;
 447         stmf_lun_map_t *sm = iss->iss_sm;
 448         stmf_lun_map_ent_t *lun_map_ent;
 449         uint16_t luNbr =
 450             ((uint16_t)lu_nbr[1] | (((uint16_t)(lu_nbr[0] & 0x3F)) << 8));
 451 
 452         ASSERT(mutex_owned(&stmf_state.stmf_lock));
 453         lun_map_ent = stmf_get_ent_from_map(sm, luNbr);
 454         ASSERT(lun_map_ent && lun_map_ent->ent_lu == lu);
 455 
 456         ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
 457 
 458         ret = stmf_remove_ent_from_map(sm, lu_nbr);
 459         ASSERT(ret == STMF_SUCCESS);
 460         atomic_dec_32(&ilu->ilu_ref_cnt);
 461         iss->iss_flags |= ISS_LUN_INVENTORY_CHANGED;
 462         if (lun_map_ent->ent_itl_datap) {
 463                 stmf_do_itl_dereg(lu, lun_map_ent->ent_itl_datap,
 464                     STMF_ITL_REASON_USER_REQUEST);
 465         }
 466         kmem_free((void *)lun_map_ent, sizeof (stmf_lun_map_ent_t));
 467         return (STMF_SUCCESS);
 468 }
 469 
 470 /*
 471  * add or remove lu from all related sessions based on view entry,
 472  * action is 0 for delete, 1 for add
 473  */
 474 void
 475 stmf_update_sessions_per_ve(stmf_view_entry_t *ve,
 476                 stmf_lu_t *lu, int action)
 477 {
 478         stmf_i_lu_t *ilu_tmp;
 479         stmf_lu_t *lu_to_add;
 480         stmf_i_local_port_t *ilport;
 481         stmf_i_scsi_session_t *iss;
 482         stmf_id_list_t  *hostlist;
 483         stmf_id_list_t  *targetlist;
 484         int all_hg = 0, all_tg = 0;
 485 
 486         ASSERT(mutex_owned(&stmf_state.stmf_lock));
 487 
 
 502         hostlist = (stmf_id_list_t *)ve->ve_hg->id_impl_specific;
 503         targetlist = (stmf_id_list_t *)ve->ve_tg->id_impl_specific;
 504 
 505         if ((!all_hg && !hostlist->idl_head) ||
 506             (!all_tg && !targetlist->idl_head))
 507                 /* No sessions to be updated */
 508                 return;
 509 
 510         for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
 511             ilport = ilport->ilport_next) {
 512                 if (!all_tg && ilport->ilport_tg != ve->ve_tg)
 513                         continue;
 514                 /* This ilport belongs to the target group */
 515                 rw_enter(&ilport->ilport_lock, RW_WRITER);
 516                 for (iss = ilport->ilport_ss_list; iss != NULL;
 517                     iss = iss->iss_next) {
 518                         if (!all_hg && iss->iss_hg != ve->ve_hg)
 519                                 continue;
 520                         /* This host belongs to the host group */
 521                         if (action == 0) { /* to remove */
 522                                 (void) stmf_remove_lu_from_session(ilport, iss,
 523                                     lu_to_add, ve->ve_lun);
 524                                 if (ilu_tmp->ilu_ref_cnt == 0) {
 525                                         rw_exit(&ilport->ilport_lock);
 526                                         return;
 527                                 }
 528                         } else {
 529                                 (void) stmf_add_lu_to_session(ilport, iss,
 530                                     lu_to_add, ve->ve_lun);
 531                         }
 532                 }
 533                 rw_exit(&ilport->ilport_lock);
 534         }
 535 }
 536 
 537 /*
 538  * add luns in view entry map to a session,
 539  * and stmf_lock is already held
 540  */
 541 void
 542 stmf_add_lus_to_session_per_vemap(stmf_i_local_port_t *ilport,
 543                 stmf_i_scsi_session_t *iss,
 544                 stmf_lun_map_t *vemap)
 545 {
 546         stmf_lu_t *lu;
 547         stmf_i_lu_t *ilu;
 548         stmf_view_entry_t *ve;
 549         uint32_t        i;
 550 
 551         ASSERT(mutex_owned(&stmf_state.stmf_lock));
 552 
 553         for (i = 0; i < vemap->lm_nentries; i++) {
 554                 ve = (stmf_view_entry_t *)vemap->lm_plus[i];
 555                 if (!ve)
 556                         continue;
 557                 ilu = (stmf_i_lu_t *)ve->ve_luid->id_pt_to_object;
 558                 if (ilu && ilu->ilu_state == STMF_STATE_ONLINE) {
 559                         lu = ilu->ilu_lu;
 560                         (void) stmf_add_lu_to_session(ilport, iss, lu,
 561                             ve->ve_lun);
 562                 }
 563         }
 564 }
 565 /* remove luns in view entry map from a session */
 566 void
 567 stmf_remove_lus_from_session_per_vemap(stmf_i_local_port_t *ilport,
 568                 stmf_i_scsi_session_t *iss,
 569                 stmf_lun_map_t *vemap)
 570 {
 571         stmf_lu_t *lu;
 572         stmf_i_lu_t *ilu;
 573         stmf_view_entry_t *ve;
 574         uint32_t i;
 575 
 576         ASSERT(mutex_owned(&stmf_state.stmf_lock));
 577 
 578         for (i = 0; i < vemap->lm_nentries; i++) {
 579                 ve = (stmf_view_entry_t *)vemap->lm_plus[i];
 580                 if (!ve)
 581                         continue;
 582                 ilu = (stmf_i_lu_t *)ve->ve_luid->id_pt_to_object;
 583                 if (ilu && ilu->ilu_state == STMF_STATE_ONLINE) {
 584                         lu = ilu->ilu_lu;
 585                         (void) stmf_remove_lu_from_session(ilport, iss, lu,
 586                             ve->ve_lun);
 587                 }
 588         }
 589 }
 590 
 591 stmf_id_data_t *
 592 stmf_alloc_id(uint16_t id_size, uint16_t type, uint8_t *id_data,
 593                         uint32_t additional_size)
 594 {
 595         stmf_id_data_t *id;
 596         int struct_size, total_size, real_id_size;
 597 
 598         real_id_size = ((uint32_t)id_size + 7) & (~7);
 599         struct_size = (sizeof (*id) + 7) & (~7);
 600         total_size = ((additional_size + 7) & (~7)) + struct_size +
 601             real_id_size;
 602         id = (stmf_id_data_t *)kmem_zalloc(total_size, KM_SLEEP);
 603         id->id_type = type;
 604         id->id_data_size = id_size;
 605         id->id_data = ((uint8_t *)id) + struct_size;
 606         id->id_total_alloc_size = total_size;
 
 693         if (id->id_next) {
 694                 id->id_next->id_prev = id->id_prev;
 695         } else {
 696                 idlist->idl_tail = id->id_prev;
 697         }
 698 
 699         if (id->id_prev) {
 700                 id->id_prev->id_next = id->id_next;
 701         } else {
 702                 idlist->idl_head = id->id_next;
 703         }
 704         atomic_dec_32(&idlist->id_count);
 705 }
 706 
 707 
 708 /*
 709  * The refcnts of objects in a view entry are updated when then entry
 710  * is successfully added. ve_map is just another representation of the
 711  * view enrtries in a LU. Duplicating or merging a ve map does not
 712  * affect any refcnts.
 713  */
 714 stmf_lun_map_t *
 715 stmf_duplicate_ve_map(stmf_lun_map_t *src)
 716 {
 717         stmf_lun_map_t *dst;
 718         int i;
 719 
 720         dst = (stmf_lun_map_t *)kmem_zalloc(sizeof (*dst), KM_SLEEP);
 721 
 722         if (src == NULL)
 723                 return (dst);
 724 
 725         if (src->lm_nentries) {
 726                 dst->lm_plus = kmem_zalloc(dst->lm_nentries *
 727                     sizeof (void *), KM_SLEEP);
 728                 for (i = 0; i < dst->lm_nentries; i++) {
 729                         dst->lm_plus[i] = src->lm_plus[i];
 730                 }
 731         }
 732 
 733         return (dst);
 734 }
 735 
 736 void
 737 stmf_destroy_ve_map(stmf_lun_map_t *dst)
 738 {
 739         if (dst->lm_nentries) {
 740                 kmem_free(dst->lm_plus, dst->lm_nentries * sizeof (void *));
 741         }
 742         kmem_free(dst, sizeof (*dst));
 743 }
 744 
 745 int
 746 stmf_merge_ve_map(stmf_lun_map_t *src, stmf_lun_map_t *dst,
 747                 stmf_lun_map_t **pp_ret_map, stmf_merge_flags_t mf)
 748 {
 749         int i;
 750         int nentries;
 751         int to_create_space = 0;
 752 
 753         if (dst == NULL) {
 754                 *pp_ret_map = stmf_duplicate_ve_map(src);
 755                 return (1);
 756         }
 757 
 758         if (src == NULL || src->lm_nluns == 0) {
 759                 if (mf & MERGE_FLAG_RETURN_NEW_MAP)
 760                         *pp_ret_map = stmf_duplicate_ve_map(dst);
 761                 else
 762                         *pp_ret_map = dst;
 763                 return (1);
 764         }
 
1049         }
1050         ret = stmf_add_ent_to_map(&verhg_ex->verh_ve_map, ve, ve->ve_lun);
1051         ASSERT(ret == STMF_SUCCESS);
1052 
1053         /* we need to update the affected session */
1054         if (stmf_state.stmf_service_running) {
1055                 if (ilu && ilu->ilu_state == STMF_STATE_ONLINE)
1056                         stmf_update_sessions_per_ve(ve, ilu->ilu_lu, 1);
1057         }
1058 
1059         return (STMF_SUCCESS);
1060 add_ve_err_ret:
1061         if (luid_new) {
1062                 if (ilu)
1063                         ilu->ilu_luid = NULL;
1064                 stmf_free_id(luid);
1065         }
1066         return (ret);
1067 }
1068 
1069 stmf_status_t
1070 stmf_add_ent_to_map(stmf_lun_map_t *lm, void *ent, uint8_t *lun)
1071 {
1072         uint16_t n;
1073         if (((lun[0] & 0xc0) >> 6) != 0)
1074                 return (STMF_FAILURE);
1075 
1076         n = (uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8);
1077 try_again_to_add:
1078         if (lm->lm_nentries && (n < lm->lm_nentries)) {
1079                 if (lm->lm_plus[n] == NULL) {
1080                         lm->lm_plus[n] = ent;
1081                         lm->lm_nluns++;
1082                         return (STMF_SUCCESS);
1083                 } else {
1084                         return (STMF_LUN_TAKEN);
1085                 }
1086         } else {
1087                 void **pplu;
1088                 uint16_t m = n + 1;
1089                 m = ((m + 7) & ~7) & 0x7FFF;
1090                 pplu = (void **)kmem_zalloc(m * sizeof (void *), KM_SLEEP);
1091                 bcopy(lm->lm_plus, pplu,
1092                     lm->lm_nentries * sizeof (void *));
1093                 kmem_free(lm->lm_plus, lm->lm_nentries * sizeof (void *));
1094                 lm->lm_plus = pplu;
1095                 lm->lm_nentries = m;
1096                 goto try_again_to_add;
1097         }
1098 }
1099 
1100 
1101 stmf_status_t
1102 stmf_remove_ent_from_map(stmf_lun_map_t *lm, uint8_t *lun)
1103 {
1104         uint16_t n, i;
1105         uint8_t lutype = (lun[0] & 0xc0) >> 6;
1106         if (lutype != 0)
1107                 return (STMF_FAILURE);
1108 
1109         n = (uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8);
1110 
1111         if (n >= lm->lm_nentries)
1112                 return (STMF_NOT_FOUND);
1113         if (lm->lm_plus[n] == NULL)
1114                 return (STMF_NOT_FOUND);
1115 
1116         lm->lm_plus[n] = NULL;
1117         lm->lm_nluns--;
1118 
1119         for (i = 0; i < lm->lm_nentries; i++) {
1120                 if (lm->lm_plus[lm->lm_nentries - 1 - i] != NULL)
1121                         break;
1122         }
1123         i &= ~15;
1124         if (i >= 16) {
1125                 void **pplu;
1126                 uint16_t m;
1127                 m = lm->lm_nentries - i;
1128                 pplu = (void **)kmem_zalloc(m * sizeof (void *), KM_SLEEP);
1129                 bcopy(lm->lm_plus, pplu, m * sizeof (void *));
1130                 kmem_free(lm->lm_plus, lm->lm_nentries * sizeof (void *));
1131                 lm->lm_plus = pplu;
1132                 lm->lm_nentries = m;
1133         }
1134 
1135         return (STMF_SUCCESS);
1136 }
1137 
1138 uint16_t
1139 stmf_get_next_free_lun(stmf_lun_map_t *sm, uint8_t *lun)
1140 {
1141         uint16_t luNbr;
1142 
1143 
1144         if (sm->lm_nluns < 0x4000) {
1145                 for (luNbr = 0; luNbr < sm->lm_nentries; luNbr++) {
1146                         if (sm->lm_plus[luNbr] == NULL)
1147                                 break;
1148                 }
1149         } else {
1150                 return (0xFFFF);
1151         }
1152         if (lun) {
1153                 bzero(lun, 8);
1154                 lun[1] = luNbr & 0xff;
1155                 lun[0] = (luNbr >> 8) & 0xff;
1156         }
1157 
1158         return (luNbr);
1159 }
1160 
1161 void *
1162 stmf_get_ent_from_map(stmf_lun_map_t *sm, uint16_t lun_num)
1163 {
1164         if ((lun_num & 0xC000) == 0) {
1165                 if (sm->lm_nentries > lun_num)
1166                         return (sm->lm_plus[lun_num & 0x3FFF]);
1167                 else
1168                         return (NULL);
1169         }
1170 
1171         return (NULL);
1172 }
1173 
1174 int
1175 stmf_add_ve(uint8_t *hgname, uint16_t hgname_size,
1176                 uint8_t *tgname, uint16_t tgname_size,
1177                 uint8_t *lu_guid, uint32_t *ve_id,
1178                 uint8_t *luNbr, uint32_t *err_detail)
1179 {
1180         stmf_id_data_t *hg;
 
1475         }
1476         /* For host group member, update the session if needed */
1477         if (!stmf_state.stmf_service_running)
1478                 return (0);
1479         /* Need to consider all target group + this host group */
1480         id_alltgt = stmf_lookup_id(&stmf_state.stmf_tg_list,
1481             1, &grpname_forall);
1482         vemap_alltgt = stmf_get_ve_map_per_ids(id_alltgt, id_grp);
1483 
1484         /* check whether there are sessions may be affected */
1485         for (ilport = stmf_state.stmf_ilportlist; ilport;
1486             ilport = ilport->ilport_next) {
1487                 if (ilport->ilport_state != STMF_STATE_ONLINE)
1488                         continue;
1489                 iss = stmf_lookup_session_for_hostident(ilport,
1490                     entry_ident, entry_size);
1491                 if (iss) {
1492                         stmf_id_data_t *tgid;
1493                         iss->iss_hg = (void *)id_grp;
1494                         tgid = ilport->ilport_tg;
1495                         if (tgid) {
1496                                 vemap = stmf_get_ve_map_per_ids(tgid, id_grp);
1497                                 if (vemap)
1498                                         stmf_add_lus_to_session_per_vemap(
1499                                             ilport, iss, vemap);
1500                         }
1501                         if (vemap_alltgt)
1502                                 stmf_add_lus_to_session_per_vemap(ilport,
1503                                     iss, vemap_alltgt);
1504                 }
1505         }
1506 
1507         return (0);
1508 }
1509 
1510 int
1511 stmf_remove_group_member(uint8_t *grpname, uint16_t grpname_size,
1512                 uint8_t *entry_ident, uint16_t entry_size,
1513                 stmf_id_type_t entry_type, uint32_t *err_detail)
1514 {
1515         stmf_id_data_t  *id_grp, *id_alltgt;
1516         stmf_id_data_t  *id_member;
1517         stmf_lun_map_t *vemap,  *vemap_alltgt;
1518         uint8_t grpname_forall = '*';
1519         stmf_i_local_port_t *ilport;
1520         stmf_i_scsi_session_t *iss;
1521 
1522         ASSERT(mutex_owned(&stmf_state.stmf_lock));
1523         ASSERT(grpname[0] != '*');
 
1560                 return (0);
1561         }
1562         /* For host group member, update the session */
1563         if (!stmf_state.stmf_service_running)
1564                 return (0);
1565 
1566         /* Need to consider all target group + this host group */
1567         id_alltgt = stmf_lookup_id(&stmf_state.stmf_tg_list,
1568             1, &grpname_forall);
1569         vemap_alltgt = stmf_get_ve_map_per_ids(id_alltgt, id_grp);
1570 
1571         /* check if there are session related, if so, update it */
1572         for (ilport = stmf_state.stmf_ilportlist; ilport;
1573             ilport = ilport->ilport_next) {
1574                 if (ilport->ilport_state != STMF_STATE_ONLINE)
1575                         continue;
1576                 iss = stmf_lookup_session_for_hostident(ilport,
1577                     entry_ident, entry_size);
1578                 if (iss) {
1579                         stmf_id_data_t *tgid;
1580                         iss->iss_hg = NULL;
1581                         tgid = ilport->ilport_tg;
1582                         if (tgid) {
1583                                 vemap = stmf_get_ve_map_per_ids(tgid, id_grp);
1584                                 if (vemap)
1585                                         stmf_remove_lus_from_session_per_vemap(
1586                                             ilport, iss, vemap);
1587                         }
1588                         if (vemap_alltgt)
1589                                 stmf_remove_lus_from_session_per_vemap(ilport,
1590                                     iss, vemap_alltgt);
1591                 }
1592         }
1593 
1594         return (0);
1595 }
1596 
1597 /* Assert stmf_lock is already held */
1598 stmf_i_local_port_t *
1599 stmf_targetident_to_ilport(uint8_t *target_ident, uint16_t ident_size)
1600 {
1601         stmf_i_local_port_t *ilport;
1602         uint8_t *id;
1603 
1604         ASSERT(mutex_owned(&stmf_state.stmf_lock));
1605 
1606         for (ilport = stmf_state.stmf_ilportlist; ilport;
1607             ilport = ilport->ilport_next) {
1608                 id = (uint8_t *)ilport->ilport_lport->lport_id;
1609                 if ((id[3] == ident_size) &&
1610                     bcmp(id + 4, target_ident, ident_size) == 0) {
 
 | 
 
 
  30 #include <sys/scsi/scsi.h>
  31 #include <sys/scsi/impl/scsi_reset_notify.h>
  32 #include <sys/disp.h>
  33 #include <sys/byteorder.h>
  34 #include <sys/atomic.h>
  35 
  36 #include <sys/stmf.h>
  37 #include <sys/lpif.h>
  38 #include <sys/portif.h>
  39 #include <sys/stmf_ioctl.h>
  40 
  41 #include "stmf_impl.h"
  42 #include "lun_map.h"
  43 #include "stmf_state.h"
  44 
  45 void stmf_update_sessions_per_ve(stmf_view_entry_t *ve,
  46                 stmf_lu_t *lu, int action);
  47 void stmf_add_lus_to_session_per_vemap(stmf_i_local_port_t *ilport,
  48                 stmf_i_scsi_session_t *iss, stmf_lun_map_t *vemap);
  49 stmf_id_data_t *stmf_lookup_group_for_host(uint8_t *ident, uint16_t ident_size);
  50 static stmf_status_t stmf_add_ent_to_map(stmf_lun_map_t *sm, void *ent,
  51     uint8_t *lun);
  52 static stmf_status_t stmf_remove_ent_from_map(stmf_lun_map_t *sm, uint8_t *lun);
  53 uint16_t stmf_get_next_free_lun(stmf_lun_map_t *sm, uint8_t *lun);
  54 stmf_status_t stmf_add_tg(uint8_t *tg_name, uint16_t tg_name_size,
  55                 int allow_special, uint32_t *err_detail);
  56 stmf_status_t stmf_add_hg(uint8_t *hg_name, uint16_t hg_name_size,
  57                 int allow_special, uint32_t *err_detail);
  58 stmf_i_local_port_t *stmf_targetident_to_ilport(uint8_t *target_ident,
  59                 uint16_t ident_size);
  60 stmf_i_scsi_session_t *stmf_lookup_session_for_hostident(
  61                 stmf_i_local_port_t *ilport, uint8_t *host_ident,
  62                 uint16_t ident_size);
  63 stmf_i_lu_t *stmf_luident_to_ilu(uint8_t *lu_ident);
  64 stmf_lun_map_t *stmf_get_ve_map_per_ids(stmf_id_data_t *tgid,
  65                 stmf_id_data_t *hgid);
  66 stmf_lun_map_t *stmf_duplicate_ve_map(stmf_lun_map_t *src);
  67 int stmf_merge_ve_map(stmf_lun_map_t *src, stmf_lun_map_t *dst,
  68                 stmf_lun_map_t **pp_ret_map, stmf_merge_flags_t mf);
  69 void stmf_destroy_ve_map(stmf_lun_map_t *dst);
  70 void stmf_free_id(stmf_id_data_t *id);
  71 
  72 
 
 
 163                                         idmemb_next = idmemb->id_next;
 164                                         stmf_free_id(idmemb);
 165                                 }
 166                         }
 167                         idgrp_next = idgrp->id_next;
 168                         stmf_free_id(idgrp);
 169                 }
 170                 stmf_state.stmf_tg_list.id_count = 0;
 171                 stmf_state.stmf_tg_list.idl_head =
 172                     stmf_state.stmf_tg_list.idl_tail = NULL;
 173         }
 174 
 175         for (ilport = stmf_state.stmf_ilportlist; ilport;
 176             ilport = ilport->ilport_next) {
 177                 ilport->ilport_tg = NULL;
 178         }
 179 }
 180 
 181 /*
 182  * Create luns map for session based on the view
 183  * iss_lockp is held
 184  */
 185 stmf_status_t
 186 stmf_session_create_lun_map(stmf_i_local_port_t *ilport,
 187                 stmf_i_scsi_session_t *iss)
 188 {
 189         stmf_id_data_t *tg;
 190         stmf_id_data_t *hg;
 191         stmf_ver_tg_t   *vertg;
 192         char *phg_data, *ptg_data;
 193         stmf_ver_hg_t   *verhg;
 194         stmf_lun_map_t  *ve_map;
 195 
 196         ASSERT(mutex_owned(&stmf_state.stmf_lock));
 197 
 198         tg = ilport->ilport_tg;
 199         hg = stmf_lookup_group_for_host(iss->iss_ss->ss_rport_id->ident,
 200             iss->iss_ss->ss_rport_id->ident_length);
 201         iss->iss_hg = hg;
 202 
 203         /*
 
 221                             (verhg->verh_hg_ref != hg)))) {
 222                                 continue;
 223                         }
 224                         (void) stmf_merge_ve_map(&verhg->verh_ve_map, ve_map,
 225                             &ve_map, 0);
 226                 }
 227         }
 228 
 229 
 230         if (ve_map->lm_nluns) {
 231                 stmf_add_lus_to_session_per_vemap(ilport, iss, ve_map);
 232         }
 233         /* not configured, cannot access any luns for now */
 234 
 235         stmf_destroy_ve_map(ve_map);
 236 
 237         return (STMF_SUCCESS);
 238 }
 239 
 240 /*
 241  * Expects the session lock to be held.
 242  * iss_lockp is held
 243  */
 244 stmf_xfer_data_t *
 245 stmf_session_prepare_report_lun_data(stmf_lun_map_t *sm)
 246 {
 247         stmf_xfer_data_t *xd;
 248         uint16_t nluns, ent;
 249         uint32_t alloc_size, data_size;
 250         int i;
 251 
 252         nluns = sm->lm_nluns;
 253 
 254         data_size = 8 + (((uint32_t)nluns) << 3);
 255         if (nluns == 0) {
 256                 data_size += 8;
 257         }
 258         alloc_size = data_size + sizeof (stmf_xfer_data_t) - 4;
 259 
 260         xd = (stmf_xfer_data_t *)kmem_zalloc(alloc_size, KM_NOSLEEP);
 261 
 262         if (xd == NULL)
 
 331                 return;
 332 
 333         luid = ((stmf_i_lu_t *)lu->lu_stmf_private)->ilu_luid;
 334         if (!luid) {
 335                 /*
 336                  * we did not configure view for this lun, this should be
 337                  * an error
 338                  */
 339                 return;
 340         }
 341 
 342         for (ve = (stmf_view_entry_t *)luid->id_impl_specific;
 343             ve; ve = ve->ve_next) {
 344                 stmf_update_sessions_per_ve(ve, lu, 0);
 345                 if (ilu->ilu_ref_cnt == 0)
 346                         break;
 347         }
 348 }
 349 /*
 350  * add lu to a session, stmf_lock is already held
 351  * iss_lockp/ilport_lock already held
 352  */
 353 static stmf_status_t
 354 stmf_add_lu_to_session(stmf_i_local_port_t *ilport,
 355                 stmf_i_scsi_session_t   *iss,
 356                 stmf_lu_t *lu,
 357                 uint8_t *lu_nbr)
 358 {
 359         stmf_lun_map_t *sm = iss->iss_sm;
 360         stmf_status_t ret;
 361         stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
 362         stmf_lun_map_ent_t *lun_map_ent;
 363         uint32_t new_flags = 0;
 364         uint16_t luNbr =
 365             ((uint16_t)lu_nbr[1] | (((uint16_t)(lu_nbr[0] & 0x3F)) << 8));
 366 
 367         ASSERT(mutex_owned(&stmf_state.stmf_lock));
 368         ASSERT(!stmf_get_ent_from_map(sm, luNbr));
 369 
 370         if ((sm->lm_nluns == 0) &&
 371             ((iss->iss_flags & ISS_BEING_CREATED) == 0)) {
 372                 new_flags = ISS_GOT_INITIAL_LUNS;
 373                 atomic_or_32(&ilport->ilport_flags, ILPORT_SS_GOT_INITIAL_LUNS);
 
 376 
 377         lun_map_ent = (stmf_lun_map_ent_t *)
 378             kmem_zalloc(sizeof (stmf_lun_map_ent_t), KM_SLEEP);
 379         lun_map_ent->ent_lu = lu;
 380         ret = stmf_add_ent_to_map(sm, (void *)lun_map_ent, lu_nbr);
 381         ASSERT(ret == STMF_SUCCESS);
 382         atomic_inc_32(&ilu->ilu_ref_cnt);
 383         /*
 384          * do not set lun inventory flag for standby port
 385          * as this would be handled from peer
 386          */
 387         if (ilport->ilport_standby == 0) {
 388                 new_flags |= ISS_LUN_INVENTORY_CHANGED;
 389         }
 390         atomic_or_32(&iss->iss_flags, new_flags);
 391         return (STMF_SUCCESS);
 392 }
 393 
 394 /*
 395  * remvoe lu from a session, stmf_lock is already held
 396  * iss_lockp held
 397  */
 398 static void
 399 stmf_remove_lu_from_session(stmf_i_scsi_session_t *iss,
 400     stmf_lu_t *lu, uint8_t *lu_nbr)
 401 {
 402         stmf_status_t ret;
 403         stmf_i_lu_t *ilu;
 404         stmf_lun_map_t *sm = iss->iss_sm;
 405         stmf_lun_map_ent_t *lun_map_ent;
 406         uint16_t luNbr =
 407             ((uint16_t)lu_nbr[1] | (((uint16_t)(lu_nbr[0] & 0x3F)) << 8));
 408 
 409         ASSERT(mutex_owned(&stmf_state.stmf_lock));
 410         lun_map_ent = stmf_get_ent_from_map(sm, luNbr);
 411         ASSERT(lun_map_ent->ent_lu == lu);
 412         if (lun_map_ent == NULL) {
 413                 return;
 414         }
 415 
 416         ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
 417 
 418         ret = stmf_remove_ent_from_map(sm, lu_nbr);
 419         ASSERT(ret == STMF_SUCCESS);
 420         atomic_dec_32(&ilu->ilu_ref_cnt);
 421         iss->iss_flags |= ISS_LUN_INVENTORY_CHANGED;
 422         if (lun_map_ent->ent_itl_datap) {
 423                 stmf_do_itl_dereg(lu, lun_map_ent->ent_itl_datap,
 424                     STMF_ITL_REASON_USER_REQUEST);
 425         }
 426         kmem_free((void *)lun_map_ent, sizeof (stmf_lun_map_ent_t));
 427 }
 428 
 429 /*
 430  * add or remove lu from all related sessions based on view entry,
 431  * action is 0 for delete, 1 for add
 432  */
 433 void
 434 stmf_update_sessions_per_ve(stmf_view_entry_t *ve,
 435                 stmf_lu_t *lu, int action)
 436 {
 437         stmf_i_lu_t *ilu_tmp;
 438         stmf_lu_t *lu_to_add;
 439         stmf_i_local_port_t *ilport;
 440         stmf_i_scsi_session_t *iss;
 441         stmf_id_list_t  *hostlist;
 442         stmf_id_list_t  *targetlist;
 443         int all_hg = 0, all_tg = 0;
 444 
 445         ASSERT(mutex_owned(&stmf_state.stmf_lock));
 446 
 
 461         hostlist = (stmf_id_list_t *)ve->ve_hg->id_impl_specific;
 462         targetlist = (stmf_id_list_t *)ve->ve_tg->id_impl_specific;
 463 
 464         if ((!all_hg && !hostlist->idl_head) ||
 465             (!all_tg && !targetlist->idl_head))
 466                 /* No sessions to be updated */
 467                 return;
 468 
 469         for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
 470             ilport = ilport->ilport_next) {
 471                 if (!all_tg && ilport->ilport_tg != ve->ve_tg)
 472                         continue;
 473                 /* This ilport belongs to the target group */
 474                 rw_enter(&ilport->ilport_lock, RW_WRITER);
 475                 for (iss = ilport->ilport_ss_list; iss != NULL;
 476                     iss = iss->iss_next) {
 477                         if (!all_hg && iss->iss_hg != ve->ve_hg)
 478                                 continue;
 479                         /* This host belongs to the host group */
 480                         if (action == 0) { /* to remove */
 481                                 stmf_remove_lu_from_session(iss, lu_to_add,
 482                                     ve->ve_lun);
 483                                 if (ilu_tmp->ilu_ref_cnt == 0) {
 484                                         rw_exit(&ilport->ilport_lock);
 485                                         return;
 486                                 }
 487                         } else {
 488                                 (void) stmf_add_lu_to_session(ilport, iss,
 489                                     lu_to_add, ve->ve_lun);
 490                         }
 491                 }
 492                 rw_exit(&ilport->ilport_lock);
 493         }
 494 }
 495 
 496 /*
 497  * add luns in view entry map to a session,
 498  * and stmf_lock is already held
 499  */
 500 void
 501 stmf_add_lus_to_session_per_vemap(stmf_i_local_port_t *ilport,
 502                 stmf_i_scsi_session_t *iss,
 503                 stmf_lun_map_t *vemap)
 504 {
 505         stmf_lu_t *lu;
 506         stmf_i_lu_t *ilu;
 507         stmf_view_entry_t *ve;
 508         uint32_t        i;
 509 
 510         ASSERT(mutex_owned(&stmf_state.stmf_lock));
 511         for (i = 0; i < vemap->lm_nentries; i++) {
 512                 ve = (stmf_view_entry_t *)vemap->lm_plus[i];
 513                 if (!ve)
 514                         continue;
 515                 ilu = (stmf_i_lu_t *)ve->ve_luid->id_pt_to_object;
 516                 if (ilu && ilu->ilu_state == STMF_STATE_ONLINE) {
 517                         lu = ilu->ilu_lu;
 518                         (void) stmf_add_lu_to_session(ilport, iss, lu,
 519                             ve->ve_lun);
 520                 }
 521         }
 522 }
 523 /*
 524  * remove luns in view entry map from a session
 525  * iss_lockp held
 526  */
 527 void
 528 stmf_remove_lus_from_session_per_vemap(stmf_i_scsi_session_t *iss,
 529     stmf_lun_map_t *vemap)
 530 {
 531         stmf_lu_t *lu;
 532         stmf_i_lu_t *ilu;
 533         stmf_view_entry_t *ve;
 534         uint32_t i;
 535 
 536         ASSERT(mutex_owned(&stmf_state.stmf_lock));
 537 
 538         for (i = 0; i < vemap->lm_nentries; i++) {
 539                 ve = (stmf_view_entry_t *)vemap->lm_plus[i];
 540                 if (!ve)
 541                         continue;
 542                 ilu = (stmf_i_lu_t *)ve->ve_luid->id_pt_to_object;
 543                 if (ilu && ilu->ilu_state == STMF_STATE_ONLINE) {
 544                         lu = ilu->ilu_lu;
 545                         stmf_remove_lu_from_session(iss, lu, ve->ve_lun);
 546                 }
 547         }
 548 }
 549 
 550 stmf_id_data_t *
 551 stmf_alloc_id(uint16_t id_size, uint16_t type, uint8_t *id_data,
 552                         uint32_t additional_size)
 553 {
 554         stmf_id_data_t *id;
 555         int struct_size, total_size, real_id_size;
 556 
 557         real_id_size = ((uint32_t)id_size + 7) & (~7);
 558         struct_size = (sizeof (*id) + 7) & (~7);
 559         total_size = ((additional_size + 7) & (~7)) + struct_size +
 560             real_id_size;
 561         id = (stmf_id_data_t *)kmem_zalloc(total_size, KM_SLEEP);
 562         id->id_type = type;
 563         id->id_data_size = id_size;
 564         id->id_data = ((uint8_t *)id) + struct_size;
 565         id->id_total_alloc_size = total_size;
 
 652         if (id->id_next) {
 653                 id->id_next->id_prev = id->id_prev;
 654         } else {
 655                 idlist->idl_tail = id->id_prev;
 656         }
 657 
 658         if (id->id_prev) {
 659                 id->id_prev->id_next = id->id_next;
 660         } else {
 661                 idlist->idl_head = id->id_next;
 662         }
 663         atomic_dec_32(&idlist->id_count);
 664 }
 665 
 666 
 667 /*
 668  * The refcnts of objects in a view entry are updated when then entry
 669  * is successfully added. ve_map is just another representation of the
 670  * view enrtries in a LU. Duplicating or merging a ve map does not
 671  * affect any refcnts.
 672  * stmf_state.stmf_lock held
 673  */
 674 stmf_lun_map_t *
 675 stmf_duplicate_ve_map(stmf_lun_map_t *src)
 676 {
 677         stmf_lun_map_t *dst;
 678         int i;
 679 
 680         dst = (stmf_lun_map_t *)kmem_zalloc(sizeof (*dst), KM_SLEEP);
 681 
 682         if (src == NULL)
 683                 return (dst);
 684 
 685         if (src->lm_nentries) {
 686                 dst->lm_plus = kmem_zalloc(dst->lm_nentries *
 687                     sizeof (void *), KM_SLEEP);
 688                 for (i = 0; i < dst->lm_nentries; i++) {
 689                         dst->lm_plus[i] = src->lm_plus[i];
 690                 }
 691         }
 692 
 693         return (dst);
 694 }
 695 
 696 void
 697 stmf_destroy_ve_map(stmf_lun_map_t *dst)
 698 {
 699         if (dst->lm_nentries) {
 700                 kmem_free(dst->lm_plus, dst->lm_nentries * sizeof (void *));
 701         }
 702         kmem_free(dst, sizeof (*dst));
 703 }
 704 
 705 /*
 706  * stmf_state.stmf_lock held. Operations are stmf global in nature and
 707  * not session level.
 708  */
 709 int
 710 stmf_merge_ve_map(stmf_lun_map_t *src, stmf_lun_map_t *dst,
 711                 stmf_lun_map_t **pp_ret_map, stmf_merge_flags_t mf)
 712 {
 713         int i;
 714         int nentries;
 715         int to_create_space = 0;
 716 
 717         if (dst == NULL) {
 718                 *pp_ret_map = stmf_duplicate_ve_map(src);
 719                 return (1);
 720         }
 721 
 722         if (src == NULL || src->lm_nluns == 0) {
 723                 if (mf & MERGE_FLAG_RETURN_NEW_MAP)
 724                         *pp_ret_map = stmf_duplicate_ve_map(dst);
 725                 else
 726                         *pp_ret_map = dst;
 727                 return (1);
 728         }
 
1013         }
1014         ret = stmf_add_ent_to_map(&verhg_ex->verh_ve_map, ve, ve->ve_lun);
1015         ASSERT(ret == STMF_SUCCESS);
1016 
1017         /* we need to update the affected session */
1018         if (stmf_state.stmf_service_running) {
1019                 if (ilu && ilu->ilu_state == STMF_STATE_ONLINE)
1020                         stmf_update_sessions_per_ve(ve, ilu->ilu_lu, 1);
1021         }
1022 
1023         return (STMF_SUCCESS);
1024 add_ve_err_ret:
1025         if (luid_new) {
1026                 if (ilu)
1027                         ilu->ilu_luid = NULL;
1028                 stmf_free_id(luid);
1029         }
1030         return (ret);
1031 }
1032 
1033 /*
1034  * protected by stmf_state.stmf_lock when working on global lun map.
1035  * iss_lockp when working at the session level.
1036  */
1037 static stmf_status_t
1038 stmf_add_ent_to_map(stmf_lun_map_t *lm, void *ent, uint8_t *lun)
1039 {
1040         uint16_t n;
1041         if (((lun[0] & 0xc0) >> 6) != 0)
1042                 return (STMF_FAILURE);
1043 
1044         n = (uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8);
1045 try_again_to_add:
1046         if (lm->lm_nentries && (n < lm->lm_nentries)) {
1047                 if (lm->lm_plus[n] == NULL) {
1048                         lm->lm_plus[n] = ent;
1049                         lm->lm_nluns++;
1050                         return (STMF_SUCCESS);
1051                 } else {
1052                         return (STMF_LUN_TAKEN);
1053                 }
1054         } else {
1055                 void **pplu;
1056                 uint16_t m = n + 1;
1057                 m = ((m + 7) & ~7) & 0x7FFF;
1058                 pplu = (void **)kmem_zalloc(m * sizeof (void *), KM_SLEEP);
1059                 bcopy(lm->lm_plus, pplu,
1060                     lm->lm_nentries * sizeof (void *));
1061                 kmem_free(lm->lm_plus, lm->lm_nentries * sizeof (void *));
1062                 lm->lm_plus = pplu;
1063                 lm->lm_nentries = m;
1064                 goto try_again_to_add;
1065         }
1066 }
1067 
1068 
1069 /*
1070  * iss_lockp held when working on a session.
1071  * stmf_state.stmf_lock is held when working on the global views.
1072  */
1073 static stmf_status_t
1074 stmf_remove_ent_from_map(stmf_lun_map_t *lm, uint8_t *lun)
1075 {
1076         uint16_t n, i;
1077         uint8_t lutype = (lun[0] & 0xc0) >> 6;
1078         if (lutype != 0)
1079                 return (STMF_FAILURE);
1080 
1081         n = (uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8);
1082 
1083         if (n >= lm->lm_nentries)
1084                 return (STMF_NOT_FOUND);
1085         if (lm->lm_plus[n] == NULL)
1086                 return (STMF_NOT_FOUND);
1087 
1088         lm->lm_plus[n] = NULL;
1089         lm->lm_nluns--;
1090 
1091         for (i = 0; i < lm->lm_nentries; i++) {
1092                 if (lm->lm_plus[lm->lm_nentries - 1 - i] != NULL)
1093                         break;
1094         }
1095         i &= ~15;
1096         if (i >= 16) {
1097                 void **pplu;
1098                 uint16_t m;
1099                 m = lm->lm_nentries - i;
1100                 pplu = (void **)kmem_zalloc(m * sizeof (void *), KM_SLEEP);
1101                 bcopy(lm->lm_plus, pplu, m * sizeof (void *));
1102                 kmem_free(lm->lm_plus, lm->lm_nentries * sizeof (void *));
1103                 lm->lm_plus = pplu;
1104                 lm->lm_nentries = m;
1105         }
1106 
1107         return (STMF_SUCCESS);
1108 }
1109 
1110 /*
1111  * stmf_state.stmf_lock held
1112  */
1113 uint16_t
1114 stmf_get_next_free_lun(stmf_lun_map_t *sm, uint8_t *lun)
1115 {
1116         uint16_t luNbr;
1117 
1118 
1119         if (sm->lm_nluns < 0x4000) {
1120                 for (luNbr = 0; luNbr < sm->lm_nentries; luNbr++) {
1121                         if (sm->lm_plus[luNbr] == NULL)
1122                                 break;
1123                 }
1124         } else {
1125                 return (0xFFFF);
1126         }
1127         if (lun) {
1128                 bzero(lun, 8);
1129                 lun[1] = luNbr & 0xff;
1130                 lun[0] = (luNbr >> 8) & 0xff;
1131         }
1132 
1133         return (luNbr);
1134 }
1135 
1136 /*
1137  * stmf_state.stmf_lock is held when working on global view map
1138  * iss_lockp (RW_WRITER) is held when working on session map.
1139  */
1140 void *
1141 stmf_get_ent_from_map(stmf_lun_map_t *sm, uint16_t lun_num)
1142 {
1143         if ((lun_num & 0xC000) == 0) {
1144                 if (sm->lm_nentries > lun_num)
1145                         return (sm->lm_plus[lun_num & 0x3FFF]);
1146                 else
1147                         return (NULL);
1148         }
1149 
1150         return (NULL);
1151 }
1152 
1153 int
1154 stmf_add_ve(uint8_t *hgname, uint16_t hgname_size,
1155                 uint8_t *tgname, uint16_t tgname_size,
1156                 uint8_t *lu_guid, uint32_t *ve_id,
1157                 uint8_t *luNbr, uint32_t *err_detail)
1158 {
1159         stmf_id_data_t *hg;
 
1454         }
1455         /* For host group member, update the session if needed */
1456         if (!stmf_state.stmf_service_running)
1457                 return (0);
1458         /* Need to consider all target group + this host group */
1459         id_alltgt = stmf_lookup_id(&stmf_state.stmf_tg_list,
1460             1, &grpname_forall);
1461         vemap_alltgt = stmf_get_ve_map_per_ids(id_alltgt, id_grp);
1462 
1463         /* check whether there are sessions may be affected */
1464         for (ilport = stmf_state.stmf_ilportlist; ilport;
1465             ilport = ilport->ilport_next) {
1466                 if (ilport->ilport_state != STMF_STATE_ONLINE)
1467                         continue;
1468                 iss = stmf_lookup_session_for_hostident(ilport,
1469                     entry_ident, entry_size);
1470                 if (iss) {
1471                         stmf_id_data_t *tgid;
1472                         iss->iss_hg = (void *)id_grp;
1473                         tgid = ilport->ilport_tg;
1474                         rw_enter(iss->iss_lockp, RW_WRITER);
1475                         if (tgid) {
1476                                 vemap = stmf_get_ve_map_per_ids(tgid, id_grp);
1477                                 if (vemap)
1478                                         stmf_add_lus_to_session_per_vemap(
1479                                             ilport, iss, vemap);
1480                         }
1481                         if (vemap_alltgt)
1482                                 stmf_add_lus_to_session_per_vemap(ilport,
1483                                     iss, vemap_alltgt);
1484                         rw_exit(iss->iss_lockp);
1485                 }
1486         }
1487 
1488         return (0);
1489 }
1490 
1491 int
1492 stmf_remove_group_member(uint8_t *grpname, uint16_t grpname_size,
1493                 uint8_t *entry_ident, uint16_t entry_size,
1494                 stmf_id_type_t entry_type, uint32_t *err_detail)
1495 {
1496         stmf_id_data_t  *id_grp, *id_alltgt;
1497         stmf_id_data_t  *id_member;
1498         stmf_lun_map_t *vemap,  *vemap_alltgt;
1499         uint8_t grpname_forall = '*';
1500         stmf_i_local_port_t *ilport;
1501         stmf_i_scsi_session_t *iss;
1502 
1503         ASSERT(mutex_owned(&stmf_state.stmf_lock));
1504         ASSERT(grpname[0] != '*');
 
1541                 return (0);
1542         }
1543         /* For host group member, update the session */
1544         if (!stmf_state.stmf_service_running)
1545                 return (0);
1546 
1547         /* Need to consider all target group + this host group */
1548         id_alltgt = stmf_lookup_id(&stmf_state.stmf_tg_list,
1549             1, &grpname_forall);
1550         vemap_alltgt = stmf_get_ve_map_per_ids(id_alltgt, id_grp);
1551 
1552         /* check if there are session related, if so, update it */
1553         for (ilport = stmf_state.stmf_ilportlist; ilport;
1554             ilport = ilport->ilport_next) {
1555                 if (ilport->ilport_state != STMF_STATE_ONLINE)
1556                         continue;
1557                 iss = stmf_lookup_session_for_hostident(ilport,
1558                     entry_ident, entry_size);
1559                 if (iss) {
1560                         stmf_id_data_t *tgid;
1561                         rw_enter(iss->iss_lockp, RW_WRITER);
1562                         iss->iss_hg = NULL;
1563                         tgid = ilport->ilport_tg;
1564                         if (tgid) {
1565                                 vemap = stmf_get_ve_map_per_ids(tgid, id_grp);
1566                                 if (vemap)
1567                                         stmf_remove_lus_from_session_per_vemap(
1568                                             iss, vemap);
1569                         }
1570                         if (vemap_alltgt)
1571                                 stmf_remove_lus_from_session_per_vemap(iss,
1572                                     vemap_alltgt);
1573                         rw_exit(iss->iss_lockp);
1574                 }
1575         }
1576 
1577         return (0);
1578 }
1579 
1580 /* Assert stmf_lock is already held */
1581 stmf_i_local_port_t *
1582 stmf_targetident_to_ilport(uint8_t *target_ident, uint16_t ident_size)
1583 {
1584         stmf_i_local_port_t *ilport;
1585         uint8_t *id;
1586 
1587         ASSERT(mutex_owned(&stmf_state.stmf_lock));
1588 
1589         for (ilport = stmf_state.stmf_ilportlist; ilport;
1590             ilport = ilport->ilport_next) {
1591                 id = (uint8_t *)ilport->ilport_lport->lport_id;
1592                 if ((id[3] == ident_size) &&
1593                     bcmp(id + 4, target_ident, ident_size) == 0) {
 
 |