1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * iSCSI session interfaces 26 */ 27 28 #include "iscsi.h" /* main header */ 29 #include <sys/scsi/adapters/iscsi_if.h> /* ioctl interfaces */ 30 /* protocol structs and defines */ 31 #include <sys/iscsi_protocol.h> 32 #include "iscsi_targetparam.h" 33 #include "persistent.h" 34 #include <sys/scsi/adapters/iscsi_door.h> 35 #include <sys/dlpi.h> 36 #include <sys/ethernet.h> 37 #include <sys/utsname.h> 38 39 static iscsi_targetparams_t iscsi_targets; 40 static iscsi_targetparam_entry_t *iscsi_targetparam_create(); 41 42 /* 43 * Initializes the target list structure. Called from iscsi_attach. 44 */ 45 void 46 iscsi_targetparam_init() { 47 iscsi_targets.target_list = NULL; 48 rw_init(&(iscsi_targets.target_list_lock), NULL, 49 RW_DRIVER, NULL); 50 } 51 52 /* 53 * Frees target param list and destroys the list lock. 54 */ 55 void 56 iscsi_targetparam_cleanup() { 57 iscsi_targetparam_entry_t *curr_entry, *tmp_entry; 58 59 iscsi_targetparam_lock_list(RW_WRITER); 60 61 curr_entry = iscsi_targets.target_list; 62 while (curr_entry) { 63 tmp_entry = curr_entry->next; 64 kmem_free(curr_entry, sizeof (iscsi_targetparam_entry_t)); 65 curr_entry = tmp_entry; 66 } 67 68 iscsi_targetparam_unlock_list(); 69 rw_destroy(&iscsi_targets.target_list_lock); 70 } 71 72 /* 73 * Creates a target param entry and adds it to the target param 74 * entry list. 75 * 76 */ 77 static iscsi_targetparam_entry_t * 78 iscsi_targetparam_create(uchar_t *name) { 79 iscsi_targetparam_entry_t *target; 80 81 ASSERT(name != NULL); 82 83 target = kmem_alloc(sizeof (iscsi_targetparam_entry_t), 84 KM_SLEEP); 85 (void) strlcpy((char *)target->target_name, (char *)name, 86 sizeof (target->target_name)); 87 88 /* assign unique key for the target */ 89 mutex_enter(&iscsi_oid_mutex); 90 target->target_oid = iscsi_oid++; 91 mutex_exit(&iscsi_oid_mutex); 92 93 /* Add new target to the target list */ 94 iscsi_targetparam_lock_list(RW_WRITER); 95 if (iscsi_targets.target_list == NULL) { 96 iscsi_targets.target_list = target; 97 iscsi_targets.target_list->next = NULL; 98 } else { 99 target->next = iscsi_targets.target_list; 100 iscsi_targets.target_list = target; 101 } 102 iscsi_targetparam_unlock_list(); 103 return (target); 104 } 105 106 /* 107 * Returns a target param entry's oid given the target name. If the target 108 * param entry cannot be found one is created and the new oid is returned. 109 * 110 */ 111 uint32_t 112 iscsi_targetparam_get_oid(uchar_t *name) { 113 int name_length; 114 iscsi_targetparam_entry_t *curr_entry; 115 116 ASSERT(name != NULL); 117 name_length = strlen((char *)name); 118 119 iscsi_targetparam_lock_list(RW_READER); 120 curr_entry = iscsi_targetparam_get_next_entry(NULL); 121 while (curr_entry != NULL) { 122 if ((name_length == strlen((char *)curr_entry->target_name)) && 123 (bcmp(curr_entry->target_name, 124 (char *)name, name_length) == 0)) { 125 iscsi_targetparam_unlock_list(); 126 return (curr_entry->target_oid); 127 } 128 curr_entry = iscsi_targetparam_get_next_entry(curr_entry); 129 } 130 iscsi_targetparam_unlock_list(); 131 132 curr_entry = iscsi_targetparam_create(name); 133 return (curr_entry->target_oid); 134 } 135 136 /* 137 * Returns a target param entry's target name given its oid. If the oid cannot 138 * be found, NULL is returned. 139 * 140 */ 141 uchar_t *iscsi_targetparam_get_name(uint32_t oid) { 142 iscsi_targetparam_entry_t *curr_entry; 143 144 iscsi_targetparam_lock_list(RW_READER); 145 curr_entry = iscsi_targetparam_get_next_entry(NULL); 146 while (curr_entry != NULL) { 147 if (curr_entry->target_oid == oid) { 148 iscsi_targetparam_unlock_list(); 149 return (curr_entry->target_name); 150 } 151 curr_entry = iscsi_targetparam_get_next_entry(curr_entry); 152 } 153 iscsi_targetparam_unlock_list(); 154 return (NULL); 155 } 156 157 158 /* 159 * Removes a target param entry from the target param entry list. The 160 * oid is used to lookup the entry to be removed. 161 * 162 */ 163 int 164 iscsi_targetparam_remove_target(uint32_t oid) { 165 iscsi_targetparam_entry_t *prev_entry, *curr_entry; 166 167 prev_entry = NULL; 168 169 iscsi_targetparam_lock_list(RW_WRITER); 170 curr_entry = iscsi_targetparam_get_next_entry(NULL); 171 while (curr_entry != NULL) { 172 if (curr_entry->target_oid == oid) { 173 174 if (prev_entry == NULL) { 175 iscsi_targets.target_list = curr_entry->next; 176 } else if (curr_entry->next == NULL) { 177 ASSERT(prev_entry != NULL); 178 prev_entry->next = NULL; 179 } else { 180 ASSERT(prev_entry != NULL); 181 ASSERT(curr_entry != NULL); 182 prev_entry->next = curr_entry->next; 183 } 184 185 kmem_free(curr_entry, 186 sizeof (iscsi_targetparam_entry_t)); 187 188 iscsi_targetparam_unlock_list(); 189 return (0); 190 } 191 192 prev_entry = curr_entry; 193 curr_entry = iscsi_targetparam_get_next_entry(curr_entry); 194 } 195 196 iscsi_targetparam_unlock_list(); 197 return (0); 198 } 199 200 /* 201 * Returns the next element in the target param entry list. If 202 * NULL is passed as the reference entry then the first item in 203 * the list is returned. NULL will be returned when the last 204 * element in the list is used as the reference entry. 205 * 206 */ 207 iscsi_targetparam_entry_t * 208 iscsi_targetparam_get_next_entry(iscsi_targetparam_entry_t *ref_entry) { 209 iscsi_targetparam_entry_t *entry; 210 211 if (ref_entry == NULL) { 212 entry = iscsi_targets.target_list; 213 } else { 214 entry = ref_entry->next; 215 } 216 return (entry); 217 } 218 219 /* 220 * Lock target param list. 221 * 222 */ 223 void 224 iscsi_targetparam_lock_list(krw_t type) { 225 rw_enter(&(iscsi_targets.target_list_lock), type); 226 } 227 228 /* 229 * Unlock target param list. 230 * 231 */ 232 void 233 iscsi_targetparam_unlock_list() { 234 rw_exit(&(iscsi_targets.target_list_lock)); 235 } 236