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
iscsi_targetparam_init()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
iscsi_targetparam_cleanup()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 *
iscsi_targetparam_create(uchar_t * name)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
iscsi_targetparam_get_oid(uchar_t * name)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 */
iscsi_targetparam_get_name(uint32_t oid)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
iscsi_targetparam_remove_target(uint32_t oid)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 *
iscsi_targetparam_get_next_entry(iscsi_targetparam_entry_t * ref_entry)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
iscsi_targetparam_lock_list(krw_t type)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
iscsi_targetparam_unlock_list()233 iscsi_targetparam_unlock_list() {
234 rw_exit(&(iscsi_targets.target_list_lock));
235 }
236