Print this page
XXXX introduce drv_sectohz
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/comstar/port/iscsit/iscsit_isns.c
+++ new/usr/src/uts/common/io/comstar/port/iscsit/iscsit_isns.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/cpuvar.h>
26 26 #include <sys/types.h>
27 27 #include <sys/conf.h>
28 28 #include <sys/file.h>
29 29 #include <sys/ddi.h>
30 30 #include <sys/sunddi.h>
31 31 #include <sys/socket.h>
32 32 #include <inet/tcp.h>
33 33 #include <sys/sdt.h>
34 34
35 35 #include <sys/stmf.h>
36 36 #include <sys/stmf_ioctl.h>
37 37 #include <sys/portif.h>
38 38 #include <sys/idm/idm.h>
39 39 #include <sys/idm/idm_so.h>
40 40 #include <sys/iscsit/iscsit_common.h>
41 41 #include <sys/iscsit/isns_protocol.h>
42 42 #include <sys/ksocket.h>
43 43
44 44 #include "iscsit.h"
45 45 #include "iscsit_isns.h"
46 46
47 47 /*
48 48 * iscsit_isns.c -- isns client that is part of the iscsit server
49 49 *
50 50 * The COMSTAR iSCSI target uses four pieces of iSNS functionality:
51 51 * - DevAttrReg to notify the iSNS server of our targets and portals.
52 52 * - DeregDev to notify when a target goes away or we shut down
53 53 * - DevAttrQry (self-query) to see if iSNS server still knows us.
54 54 * - Request ESI probes from iSNS server as a keepalive mechanism
55 55 *
56 56 * We send only two kinds of DevAttrReg messages.
57 57 *
58 58 * REPLACE-ALL the info the iSNS server knows about us:
59 59 * Set Flag in PDU header to ISNS_FLAG_REPLACE_REG
60 60 * Set "source" to same iSCSI target each time
61 61 * EID (Entity Identifier) == our DNS name
62 62 * "Delimiter"
63 63 * Object operated on = EID
64 64 * "Entity Portals" owned by this "network entity"
65 65 * List of targets
66 66 * (Targets with TPGT are followed by PGT and PG portal info)
67 67 *
68 68 * UPDATE-EXISTING - used to register/change one target at a time
69 69 * Flag for replace reg not set
70 70 * Source and EID and Delimiter and Object Operated On as above
71 71 * Single Target
72 72 * (Targets with TPGT are followed by PGT and PG portal info)
73 73 *
74 74 * Interfaces to iscsit
75 75 *
76 76 * iscsit_isns_init -- called when iscsi/target service goes online
77 77 * iscsit_isns_fini -- called when iscsi/target service goes offline
78 78 * iscsit_isns_register -- a new target comes online
79 79 * iscsit_isns_deregister -- target goes offline
80 80 * iscsit_isns_target_update -- called when a target is modified
81 81 * iscsit_isns_portal_online -- called when defining a new portal
82 82 * iscsit_isns_portal_offline -- no longer using a portal
83 83 *
84 84 * Copying Data Structures
85 85 *
86 86 * The above routines copy all the data they need, so iscsit can
87 87 * proceed without interfering with us. This is moving in the
88 88 * direction of having this isns_client be a standalone user-mode
89 89 * program. Specifically, we copy the target name, alias, and
90 90 * tpgt+portal information.
91 91 *
92 92 * The iscsit_isns_mutex protects the shadow copies of target and portal
93 93 * information. The ISNS_GLOBAL_LOCK protects the iSNS run time structures
94 94 * that the monitor thread uses. The routine isnst_copy_global_status_changes
95 95 * has to acquire both locks and copy all the required information from the
96 96 * global structs to the per-server structs. Once it completes, the monitor
97 97 * thread should run completely off the per-server copies.
98 98 *
99 99 * Global State vs Per-Server state
100 100 * There is a global list of targets and portals that is kept updated
101 101 * by iscsit. Each svr keeps its own list of targets that have been
102 102 * announced to the iSNS server.
103 103 *
104 104 * Invariants
105 105 *
106 106 * 1) If svr->svr_registered, then there is some itarget with
107 107 * itarget->target_registered.
108 108 * 2) If itarget->target_delete_needed, then also itarget->target_registered.
109 109 * (Corollary: Any time you remove the last registered target, you have
110 110 * to send an unregister-all message.)
111 111 * 3) If a target has a non-default portal, then the portal goes online
112 112 * before the target goes online, and comes offline afterwards.
113 113 * (This is enforced by the iscsit state machines.)
114 114 */
115 115 /* local defines */
116 116 #define MAX_XID (2^16)
117 117 #define ISNS_IDLE_TIME 60
118 118 #define MAX_RETRY (3)
119 119 #define ISNS_RCV_TIMER_SECONDS 5
120 120
121 121 #define VALID_NAME(NAME, LEN) \
122 122 ((LEN) > 0 && (NAME)[0] != 0 && (NAME)[(LEN) - 1] == 0)
123 123
124 124
125 125 #define ISNST_LOG if (iscsit_isns_logging) cmn_err
126 126
127 127 static kmutex_t isns_monitor_mutex;
128 128 volatile kthread_t *isns_monitor_thr_id;
129 129 static kt_did_t isns_monitor_thr_did;
130 130 static boolean_t isns_monitor_thr_running;
131 131
132 132 static kcondvar_t isns_idle_cv;
133 133
134 134 static uint16_t xid;
135 135 #define GET_XID() atomic_inc_16_nv(&xid)
136 136
137 137 static clock_t monitor_idle_interval;
138 138
139 139 /* The ISNS_GLOBAL_LOCK protects the per-server data structures */
140 140 #define ISNS_GLOBAL_LOCK() \
141 141 mutex_enter(&iscsit_global.global_isns_cfg.isns_mutex)
142 142
143 143 #define ISNS_GLOBAL_LOCK_HELD() \
144 144 MUTEX_HELD(&iscsit_global.global_isns_cfg.isns_mutex)
145 145
146 146 #define ISNS_GLOBAL_UNLOCK() \
147 147 mutex_exit(&iscsit_global.global_isns_cfg.isns_mutex)
148 148
149 149 /*
150 150 * "Configurable" parameters (set in /etc/system for now).
151 151 */
152 152 boolean_t iscsit_isns_logging = B_FALSE;
153 153
154 154
155 155 /*
156 156 * If fail this many times to send an update to the server, then
157 157 * declare the server non-responsive and reregister everything with
158 158 * the server when we next connect.
159 159 */
160 160 int isns_max_retry = MAX_RETRY;
161 161
162 162 /*
163 163 * The use of ESI probes to all active portals is not appropriate in
164 164 * all network environments, since the iSNS server may not have
165 165 * connectivity to all portals, so we turn it off by default.
166 166 */
167 167 boolean_t isns_use_esi = B_FALSE;
168 168
169 169 /*
170 170 * Interval to request ESI probes at, in seconds. The server is free
171 171 * to specify a different frequency in its response.
172 172 */
173 173 int isns_default_esi_interval = ISNS_DEFAULT_ESI_INTERVAL;
174 174
175 175
176 176 /*
177 177 * Registration Period -- we guarantee to check in with iSNS server at
178 178 * least this often. Used when ESI probes are turned off.
179 179 */
180 180 int isns_registration_period = ISNS_DEFAULT_REGISTRATION_PERIOD;
181 181
182 182 /*
183 183 * Socket connect, PDU receive, and PDU send must complete
184 184 * within this number of microseconds.
185 185 */
186 186 uint32_t isns_timeout_usec = ISNS_RCV_TIMER_SECONDS * 1000000;
187 187
188 188
189 189 /*
190 190 * iSNS Message size -- we start with the max that can fit into one PDU.
191 191 * If the message doesn't fit, we will expand at run time to a higher
192 192 * value. This parameter could be set in /etc/system if some particular
193 193 * installation knows it always goes over the standard limit.
194 194 */
195 195 uint32_t isns_message_buf_size = ISNSP_MAX_PDU_SIZE;
196 196
197 197 /*
198 198 * Number of seconds to wait after isnst_monitor thread starts up
199 199 * before sending first DevAttrReg message.
200 200 */
201 201 int isns_initial_delay = ISNS_INITIAL_DELAY;
202 202
203 203 /*
204 204 * Because of a bug in the Solaris isns server (c 2009), we cannot send a
205 205 * modify operation that changes the target's TPGTs. So just replace all.
206 206 * If the iSNS server does not have this bug, clear this flag.
207 207 * Changes take effect on each modify_target operation
208 208 */
209 209 boolean_t isns_modify_must_replace = B_TRUE;
210 210
211 211 /* If PDU sizes ever go over the following, we need to rearchitect */
212 212 #define ISNST_MAX_MSG_SIZE (16 * ISNSP_MAX_PDU_SIZE)
213 213
214 214 /*
215 215 * iSNS ESI thread state
216 216 */
217 217 static isns_esi_tinfo_t esi;
218 218
219 219 /*
220 220 * Our list of targets. Kept in lock-step synch with iscsit.
221 221 * The iscsit_isns_mutex protects the global data structures that are
222 222 * kept in lock-step with iscsit.
223 223 * NOTE: Now that isnst runs independently of iscsit, we could remove the
224 224 * shadow copies of iscsit structures, such as isns_target_list and
225 225 * isns_tpg_portals, and have isnst_copy_global_status_changes reconcile
226 226 * isnst directly with the iscsit data structures.
227 227 */
228 228 static kmutex_t iscsit_isns_mutex;
229 229 static avl_tree_t isns_target_list;
230 230 static boolean_t isns_targets_changed;
231 231
232 232 /*
233 233 * List of portals from TPGs. Protected by iscsit_isns_mutex.
234 234 */
235 235 static boolean_t isns_portals_changed;
236 236 static avl_tree_t isns_tpg_portals;
237 237 static boolean_t default_portal_online;
238 238
239 239 /* List of all portals. Protected by ISNS_GLOBAL_LOCK */
240 240 static avl_tree_t isns_all_portals;
241 241 static int num_default_portals;
242 242 static int num_tpg_portals;
243 243
244 244 /*
245 245 * Our entity identifier (fully-qualified hostname). Passed in from libiscsit.
246 246 */
247 247 static char *isns_eid = NULL;
248 248
249 249 /*
250 250 * in6addr_any is currently all zeroes, but use the macro in case this
251 251 * ever changes.
252 252 */
253 253 static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
254 254
255 255 static void
256 256 isnst_start();
257 257
258 258 static void
259 259 isnst_stop();
260 260
261 261 static void
262 262 iscsit_set_isns(boolean_t state);
263 263
264 264 static void
265 265 iscsit_add_isns(it_portal_t *cfg_svr);
266 266
267 267 static void
268 268 isnst_mark_delete_isns(iscsit_isns_svr_t *svr);
269 269
270 270 static void
271 271 isnst_finish_delete_isns(iscsit_isns_svr_t *svr);
272 272
273 273 static iscsit_isns_svr_t *
274 274 iscsit_isns_svr_lookup(struct sockaddr_storage *sa);
275 275
276 276 static void
277 277 isnst_monitor(void *arg);
278 278
279 279 static int
280 280 isnst_monitor_one_server(iscsit_isns_svr_t *svr, boolean_t enabled);
281 281
282 282 static void
283 283 isnst_monitor_awaken(void);
284 284
285 285 static boolean_t
286 286 isnst_update_server_timestamp(struct sockaddr_storage *sa);
287 287
288 288 static void
289 289 isnst_copy_global_status_changes(void);
290 290
291 291 static void
292 292 isnst_mark_deleted_targets(iscsit_isns_svr_t *svr);
293 293
294 294 static int
295 295 isnst_update_one_server(iscsit_isns_svr_t *svr, isns_target_t *target,
296 296 isns_reg_type_t reg);
297 297
298 298 static boolean_t isnst_retry_registration(int rsp_status_code);
299 299
300 300 static int isnst_register(iscsit_isns_svr_t *svr, isns_target_t *itarget,
301 301 isns_reg_type_t regtype);
302 302 static int isnst_deregister(iscsit_isns_svr_t *svr, isns_target_t *itarget);
303 303
304 304 static size_t
305 305 isnst_make_dereg_pdu(iscsit_isns_svr_t *svr, isns_pdu_t **pdu,
306 306 isns_target_t *itarge);
307 307
308 308 static int isnst_keepalive(iscsit_isns_svr_t *svr);
309 309 static size_t
310 310 isnst_make_keepalive_pdu(iscsit_isns_svr_t *svr, isns_pdu_t **pdu);
311 311
312 312 static isns_target_t *
313 313 isnst_get_registered_source(iscsit_isns_svr_t *srv);
314 314 static isns_target_t *
315 315 isnst_get_registered_source_locked(iscsit_isns_svr_t *srv);
316 316
317 317 static int
318 318 isnst_verify_rsp(iscsit_isns_svr_t *svr, isns_pdu_t *pdu,
319 319 isns_pdu_t *rsp, size_t rsp_size);
320 320
321 321 static uint16_t
322 322 isnst_pdu_get_op(isns_pdu_t *pdu, uint8_t **pp);
323 323
324 324 static size_t
325 325 isnst_make_reg_pdu(isns_pdu_t **pdu, isns_target_t *target,
326 326 iscsit_isns_svr_t *svr, isns_reg_type_t regtype);
327 327
328 328 static int
329 329 isnst_reg_pdu_add_entity_portals(isns_pdu_t *pdu, size_t pdu_size);
330 330
331 331 static int
332 332 isnst_reg_pdu_add_pg(isns_pdu_t *pdu, size_t pdu_size, isns_target_t *target);
333 333
334 334 static int
335 335 isnst_add_default_pg(isns_pdu_t *pdu, size_t pdu_size,
336 336 avl_tree_t *null_portal_list);
337 337
338 338 static int
339 339 isnst_add_tpg_pg(isns_pdu_t *pdu, size_t pdu_size,
340 340 isns_tpgt_t *tig, avl_tree_t *null_portal_list);
341 341
342 342 static int
343 343 isnst_add_null_pg(isns_pdu_t *pdu, size_t pdu_size,
344 344 avl_tree_t *null_portal_list);
345 345
346 346 static int
347 347 isnst_add_portal_attr(isns_pdu_t *pdu, size_t pdu_size,
348 348 uint32_t ip_attr_id, uint32_t port_attr_id,
349 349 struct sockaddr_storage *ss, boolean_t esi_info);
350 350
351 351 static size_t
352 352 isnst_create_pdu_header(uint16_t func_id, isns_pdu_t **pdu, uint16_t flags);
353 353
354 354 static int
355 355 isnst_add_attr(isns_pdu_t *pdu,
356 356 size_t max_pdu_size,
357 357 uint32_t attr_id,
358 358 uint32_t attr_len,
359 359 void *attr_data,
360 360 uint32_t attr_numeric_data);
361 361
362 362 static int
363 363 isnst_send_pdu(void *so, isns_pdu_t *pdu);
364 364
365 365 static size_t
366 366 isnst_rcv_pdu(void *so, isns_pdu_t **pdu);
367 367
368 368 static void *
369 369 isnst_open_so(struct sockaddr_storage *sa);
370 370
371 371 static void
372 372 isnst_close_so(void *);
373 373
374 374 static void
375 375 isnst_esi_thread(void *arg);
376 376
377 377 static void
378 378 isnst_handle_esi_req(ksocket_t so, isns_pdu_t *pdu, size_t pl_size);
379 379
380 380 static void isnst_esi_start(void);
381 381 static void isnst_esi_stop(void);
382 382 static isns_target_t *isnst_latch_to_target_list(isns_target_t *target,
383 383 avl_tree_t *list);
384 384 static void isnst_clear_target_list(iscsit_isns_svr_t *svr);
385 385 static void isnst_clear_from_target_list(isns_target_t *target,
386 386 avl_tree_t *target_list);
387 387 static int isnst_tgt_avl_compare(const void *t1, const void *t2);
388 388 static void isnst_set_server_status(iscsit_isns_svr_t *svr,
389 389 boolean_t registered);
390 390 static void isnst_monitor_start(void);
391 391 static void isnst_monitor_stop(void);
392 392
393 393 static void
394 394 isnst_monitor_default_portal_list(void);
395 395
396 396 static int
397 397 isnst_find_default_portals(idm_addr_list_t *alist);
398 398
399 399 static int
400 400 isnst_add_default_portals(idm_addr_list_t *alist);
401 401
402 402 static void
403 403 isnst_clear_default_portals(void);
404 404
405 405
406 406 static void
407 407 isnst_clear_portal_list(avl_tree_t *portal_list);
408 408
409 409 static void
410 410 isnst_copy_portal_list(avl_tree_t *t1, avl_tree_t *t2);
411 411
412 412 static isns_portal_t *
413 413 isnst_lookup_portal(struct sockaddr_storage *sa);
414 414
415 415 static isns_portal_t *
416 416 isnst_add_to_portal_list(struct sockaddr_storage *sa, avl_tree_t *portal_list);
417 417
418 418 static void
419 419 isnst_remove_from_portal_list(struct sockaddr_storage *sa,
420 420 avl_tree_t *portal_list);
421 421
422 422 static int
423 423 isnst_portal_avl_compare(const void *t1, const void *t2);
424 424
425 425
426 426
427 427
428 428
429 429
430 430 it_cfg_status_t
431 431 isnst_config_merge(it_config_t *cfg)
432 432 {
433 433 boolean_t new_isns_state = B_FALSE;
434 434 iscsit_isns_svr_t *isns_svr, *next_isns_svr;
435 435 it_portal_t *cfg_isns_svr;
436 436
437 437 ISNS_GLOBAL_LOCK();
438 438
439 439 /*
440 440 * Determine whether iSNS is enabled in the new config.
441 441 * Isns property may not be set up yet.
442 442 */
443 443 (void) nvlist_lookup_boolean_value(cfg->config_global_properties,
444 444 PROP_ISNS_ENABLED, &new_isns_state);
445 445
446 446 /* Delete iSNS servers that are no longer part of the config */
447 447 for (isns_svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs);
448 448 isns_svr != NULL;
449 449 isns_svr = next_isns_svr) {
450 450 next_isns_svr = list_next(
451 451 &iscsit_global.global_isns_cfg.isns_svrs, isns_svr);
452 452 if (it_sns_svr_lookup(cfg, &isns_svr->svr_sa) == NULL)
453 453 isnst_mark_delete_isns(isns_svr);
454 454 }
455 455
456 456 /* Add new iSNS servers */
457 457 for (cfg_isns_svr = cfg->config_isns_svr_list;
458 458 cfg_isns_svr != NULL;
459 459 cfg_isns_svr = cfg_isns_svr->portal_next) {
460 460 isns_svr = iscsit_isns_svr_lookup(&cfg_isns_svr->portal_addr);
461 461 if (isns_svr == NULL) {
462 462 iscsit_add_isns(cfg_isns_svr);
463 463 } else if (isns_svr->svr_delete_needed) {
464 464 /*
465 465 * If reactivating a server that was being
466 466 * deleted, turn it into a reset.
467 467 */
468 468 isns_svr->svr_delete_needed = B_FALSE;
469 469 isns_svr->svr_reset_needed = B_TRUE;
470 470 }
471 471 }
472 472
473 473 /*
474 474 * There is no "modify case" since the user specifies a complete
475 475 * server list each time. A modify is the same as a remove+add.
476 476 */
477 477
478 478 /* Start/Stop iSNS if necessary */
479 479 iscsit_set_isns(new_isns_state);
480 480
481 481 ISNS_GLOBAL_UNLOCK();
482 482
483 483
484 484 /* Wake up the monitor thread to complete the state change */
485 485 isnst_monitor_awaken();
486 486
487 487 return (0);
488 488 }
489 489
490 490 int
491 491 iscsit_isns_init(iscsit_hostinfo_t *hostinfo)
492 492 {
493 493 mutex_init(&iscsit_global.global_isns_cfg.isns_mutex, NULL,
494 494 MUTEX_DEFAULT, NULL);
495 495
496 496 ISNS_GLOBAL_LOCK();
497 497 mutex_init(&iscsit_isns_mutex, NULL, MUTEX_DEFAULT, NULL);
498 498
499 499 iscsit_global.global_isns_cfg.isns_state = B_FALSE;
500 500 list_create(&iscsit_global.global_isns_cfg.isns_svrs,
501 501 sizeof (iscsit_isns_svr_t), offsetof(iscsit_isns_svr_t, svr_ln));
502 502 avl_create(&isns_tpg_portals, isnst_portal_avl_compare,
503 503 sizeof (isns_portal_t), offsetof(isns_portal_t, portal_node));
504 504 avl_create(&isns_all_portals, isnst_portal_avl_compare,
505 505 sizeof (isns_portal_t), offsetof(isns_portal_t, portal_node));
506 506 num_default_portals = 0;
507 507 if (hostinfo->length > ISCSIT_MAX_HOSTNAME_LEN)
↓ open down ↓ |
507 lines elided |
↑ open up ↑ |
508 508 hostinfo->length = ISCSIT_MAX_HOSTNAME_LEN;
509 509 isns_eid = kmem_alloc(hostinfo->length, KM_SLEEP);
510 510 (void) strlcpy(isns_eid, hostinfo->fqhn, hostinfo->length);
511 511 avl_create(&isns_target_list, isnst_tgt_avl_compare,
512 512 sizeof (isns_target_t), offsetof(isns_target_t, target_node));
513 513
514 514 /* initialize isns client */
515 515 mutex_init(&isns_monitor_mutex, NULL, MUTEX_DEFAULT, NULL);
516 516 mutex_init(&esi.esi_mutex, NULL, MUTEX_DEFAULT, NULL);
517 517 isns_monitor_thr_id = NULL;
518 - monitor_idle_interval = ISNS_IDLE_TIME * drv_usectohz(1000000);
518 + monitor_idle_interval = drv_sectohz(ISNS_IDLE_TIME);
519 519 cv_init(&isns_idle_cv, NULL, CV_DEFAULT, NULL);
520 520 cv_init(&esi.esi_cv, NULL, CV_DEFAULT, NULL);
521 521 xid = 0;
522 522 ISNS_GLOBAL_UNLOCK();
523 523
524 524 return (0);
525 525 }
526 526
527 527 void
528 528 iscsit_isns_fini()
529 529 {
530 530 ISNS_GLOBAL_LOCK();
531 531
532 532 /*
533 533 * The following call to iscsit_set_isns waits until all the
534 534 * iSNS servers have been fully deactivated and the monitor and esi
535 535 * threads have stopped.
536 536 */
537 537 iscsit_set_isns(B_FALSE);
538 538
539 539 /* Clean up data structures */
540 540 mutex_destroy(&isns_monitor_mutex);
541 541 cv_destroy(&isns_idle_cv);
542 542 mutex_destroy(&esi.esi_mutex);
543 543 cv_destroy(&esi.esi_cv);
544 544 mutex_destroy(&iscsit_isns_mutex);
545 545
546 546 /*
547 547 * Free our EID and target list.
548 548 */
549 549
550 550 if (isns_eid) {
551 551 kmem_free(isns_eid, strlen(isns_eid) + 1);
552 552 isns_eid = NULL;
553 553 }
554 554
555 555 iscsit_global.global_isns_cfg.isns_state = B_FALSE;
556 556 avl_destroy(&isns_target_list);
557 557 list_destroy(&iscsit_global.global_isns_cfg.isns_svrs);
558 558 avl_destroy(&isns_tpg_portals);
559 559 avl_destroy(&isns_all_portals);
560 560 num_default_portals = 0;
561 561 ISNS_GLOBAL_UNLOCK();
562 562
563 563 mutex_destroy(&iscsit_global.global_isns_cfg.isns_mutex);
564 564 }
565 565
566 566 static void
567 567 iscsit_set_isns(boolean_t state)
568 568 {
569 569 iscsit_isns_svr_t *svr;
570 570
571 571 ASSERT(ISNS_GLOBAL_LOCK_HELD());
572 572
573 573 /*
574 574 * Update state and isns stop flag
575 575 */
576 576 if (iscsit_global.global_isns_cfg.isns_state != state) {
577 577 /* reset retry count for all servers */
578 578 for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs);
579 579 svr != NULL;
580 580 svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs,
581 581 svr)) {
582 582 svr->svr_retry_count = 0;
583 583 }
584 584
585 585 iscsit_global.global_isns_cfg.isns_state = state;
586 586
587 587 if (state) {
588 588 isnst_start();
589 589 } else {
590 590 isnst_stop();
591 591 }
592 592 }
593 593 }
594 594
595 595 void
596 596 iscsit_add_isns(it_portal_t *cfg_svr)
597 597 {
598 598 iscsit_isns_svr_t *svr;
599 599
600 600 ASSERT(ISNS_GLOBAL_LOCK_HELD());
601 601
602 602 svr = kmem_zalloc(sizeof (iscsit_isns_svr_t), KM_SLEEP);
603 603 bcopy(&cfg_svr->portal_addr, &svr->svr_sa,
604 604 sizeof (struct sockaddr_storage));
605 605 avl_create(&svr->svr_target_list, isnst_tgt_avl_compare,
606 606 sizeof (isns_target_t), offsetof(isns_target_t, target_node));
607 607 svr->svr_esi_interval = isns_default_esi_interval;
608 608
609 609 /* put it on the global isns server list */
610 610 list_insert_tail(&iscsit_global.global_isns_cfg.isns_svrs, svr);
611 611 }
612 612
613 613 void
614 614 isnst_mark_delete_isns(iscsit_isns_svr_t *svr)
615 615 {
616 616 ASSERT(ISNS_GLOBAL_LOCK_HELD());
617 617
618 618 /* If monitor thread not running, finish delete here */
619 619 if (iscsit_global.global_isns_cfg.isns_state == B_FALSE) {
620 620 isnst_finish_delete_isns(svr);
621 621 } else {
622 622 svr->svr_delete_needed = B_TRUE;
623 623 }
624 624
625 625 }
626 626
627 627 void
628 628 isnst_finish_delete_isns(iscsit_isns_svr_t *svr)
629 629 {
630 630
631 631 ASSERT(ISNS_GLOBAL_LOCK_HELD());
632 632 isnst_clear_target_list(svr);
633 633
634 634 list_remove(&iscsit_global.global_isns_cfg.isns_svrs, svr);
635 635 /* free the memory */
636 636 avl_destroy(&svr->svr_target_list);
637 637 kmem_free(svr, sizeof (*svr));
638 638 }
639 639
640 640 static iscsit_isns_svr_t *
641 641 iscsit_isns_svr_lookup(struct sockaddr_storage *sa)
642 642 {
643 643 iscsit_isns_svr_t *svr;
644 644 it_portal_t portal1;
645 645
646 646 ASSERT(ISNS_GLOBAL_LOCK_HELD());
647 647
648 648 bcopy(sa, &portal1.portal_addr, sizeof (struct sockaddr_storage));
649 649
650 650 for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs);
651 651 svr != NULL;
652 652 svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs, svr)) {
653 653 if (it_sa_compare(&svr->svr_sa, sa) == 0)
654 654 return (svr);
655 655 }
656 656
657 657 return (NULL);
658 658 }
659 659
660 660 static isns_target_info_t *
661 661 isnst_create_target_info(iscsit_tgt_t *target)
662 662 {
663 663
664 664 isns_target_info_t *ti;
665 665 isns_tpgt_t *tig;
666 666 isns_tpgt_addr_t *tip;
667 667 iscsit_tpgt_t *tpgt;
668 668 iscsit_tpg_t *tpg;
669 669 iscsit_portal_t *tp;
670 670 char *str;
671 671
672 672 /* Cannot hold the iscsit_isns_mutex here! */
673 673 ASSERT(! mutex_owned(&iscsit_isns_mutex));
674 674
675 675 ti = kmem_zalloc(sizeof (isns_target_info_t), KM_SLEEP);
676 676 list_create(&ti->ti_tpgt_list,
677 677 sizeof (isns_tpgt_t), offsetof(isns_tpgt_t, ti_tpgt_ln));
678 678 idm_refcnt_init(&ti->ti_refcnt, ti);
679 679
680 680 mutex_enter(&target->target_mutex);
681 681 (void) strncpy(ti->ti_tgt_name, target->target_name,
682 682 MAX_ISCSI_NODENAMELEN);
683 683
684 684
685 685 if (nvlist_lookup_string(target->target_props, PROP_ALIAS,
686 686 &str) == 0) {
687 687 (void) strncpy(ti->ti_tgt_alias, str, MAX_ISCSI_NODENAMELEN);
688 688 }
689 689
690 690 tpgt = avl_first(&target->target_tpgt_list);
691 691 ASSERT(tpgt != NULL);
692 692 do {
693 693 tig = kmem_zalloc(sizeof (isns_tpgt_t), KM_SLEEP);
694 694 list_create(&tig->ti_portal_list, sizeof (isns_tpgt_addr_t),
695 695 offsetof(isns_tpgt_addr_t, portal_ln));
696 696 tig->ti_tpgt_tag = tpgt->tpgt_tag;
697 697
698 698 /*
699 699 * Only need portal list for non-default portal.
700 700 */
701 701 if (tpgt->tpgt_tag != ISCSIT_DEFAULT_TPGT) {
702 702 tpg = tpgt->tpgt_tpg;
703 703
704 704 mutex_enter(&tpg->tpg_mutex);
705 705
706 706 tp = avl_first(&tpg->tpg_portal_list);
707 707 do {
708 708 tip = kmem_zalloc(sizeof (isns_tpgt_addr_t),
709 709 KM_SLEEP);
710 710 bcopy(&tp->portal_addr, &tip->portal_addr,
711 711 sizeof (tip->portal_addr));
712 712 list_insert_tail(&tig->ti_portal_list, tip);
713 713
714 714 tp = AVL_NEXT(&tpg->tpg_portal_list, tp);
715 715 } while (tp != NULL);
716 716 mutex_exit(&tpg->tpg_mutex);
717 717 }
718 718 list_insert_tail(&ti->ti_tpgt_list, tig);
719 719 tpgt = AVL_NEXT(&target->target_tpgt_list, tpgt);
720 720 } while (tpgt != NULL);
721 721 mutex_exit(&target->target_mutex);
722 722
723 723 return (ti);
724 724 }
725 725
726 726 static void
727 727 isnst_clear_target_info_cb(void *arg)
728 728 {
729 729 isns_target_info_t *ti = (isns_target_info_t *)arg;
730 730 isns_tpgt_t *tig;
731 731 isns_tpgt_addr_t *tip;
732 732
733 733 while ((tig = list_remove_head(&ti->ti_tpgt_list)) != NULL) {
734 734 while ((tip = list_remove_head(&tig->ti_portal_list)) != NULL) {
735 735 kmem_free(tip, sizeof (isns_tpgt_addr_t));
736 736 }
737 737 list_destroy(&tig->ti_portal_list);
738 738 kmem_free(tig, sizeof (isns_tpgt_t));
739 739 }
740 740 list_destroy(&ti->ti_tpgt_list);
741 741 idm_refcnt_destroy(&ti->ti_refcnt);
742 742 kmem_free(ti, sizeof (isns_target_info_t));
743 743 }
744 744
745 745
746 746 /*
747 747 * iscsit_isns_register
748 748 * called by iscsit when a target goes online
749 749 */
750 750 int
751 751 iscsit_isns_register(iscsit_tgt_t *target)
752 752 {
753 753 isns_target_t *itarget, tmptgt;
754 754 avl_index_t where;
755 755 isns_target_info_t *ti;
756 756
757 757 /* Create TI struct outside of isns_mutex */
758 758 ti = isnst_create_target_info(target);
759 759
760 760 mutex_enter(&iscsit_isns_mutex);
761 761
762 762 tmptgt.target = target;
763 763 if ((itarget = (isns_target_t *)avl_find(&isns_target_list,
764 764 &tmptgt, &where)) == NULL) {
765 765 itarget = kmem_zalloc(sizeof (isns_target_t), KM_SLEEP);
766 766
767 767 itarget->target = target;
768 768 avl_insert(&isns_target_list, (void *)itarget, where);
769 769 } else {
770 770 ASSERT(0);
771 771 }
772 772
773 773 /* Copy the target info so it will last beyond deregister */
774 774 itarget->target_info = ti;
775 775 idm_refcnt_hold(&ti->ti_refcnt);
776 776
777 777 isns_targets_changed = B_TRUE;
778 778
779 779 mutex_exit(&iscsit_isns_mutex);
780 780
781 781 isnst_monitor_awaken();
782 782 return (0);
783 783 }
784 784
785 785 /*
786 786 * iscsit_isns_deregister
787 787 * called by iscsit when a target goes offline
788 788 */
789 789 int
790 790 iscsit_isns_deregister(iscsit_tgt_t *target)
791 791 {
792 792 isns_target_t *itarget, tmptgt;
793 793 isns_target_info_t *ti;
794 794
795 795 tmptgt.target = target;
796 796
797 797 mutex_enter(&iscsit_isns_mutex);
798 798
799 799 itarget = avl_find(&isns_target_list, &tmptgt, NULL);
800 800 ASSERT(itarget != NULL);
801 801 ti = itarget->target_info;
802 802
803 803 /*
804 804 * The main thread is done with the target_info object.
805 805 * Make sure the delete callback is called when
806 806 * all the svrs are done with it.
807 807 */
808 808 idm_refcnt_rele(&ti->ti_refcnt);
809 809 idm_refcnt_async_wait_ref(&ti->ti_refcnt,
810 810 (idm_refcnt_cb_t *)&isnst_clear_target_info_cb);
811 811
812 812 itarget->target_info = NULL;
813 813 avl_remove(&isns_target_list, itarget);
814 814 kmem_free(itarget, sizeof (isns_target_t));
815 815
816 816 isns_targets_changed = B_TRUE;
817 817
818 818 mutex_exit(&iscsit_isns_mutex);
819 819
820 820 isnst_monitor_awaken();
821 821 return (0);
822 822 }
823 823
824 824 /*
825 825 * iscsit_isns_target_update
826 826 * This function is called by iscsit when a target's configuration
827 827 * has changed.
828 828 */
829 829
830 830 void
831 831 iscsit_isns_target_update(iscsit_tgt_t *target)
832 832 {
833 833 isns_target_t *itarget, tmptgt;
834 834 isns_target_info_t *ti;
835 835
836 836 /* Create new TI struct outside of isns_mutex */
837 837 ti = isnst_create_target_info(target);
838 838
839 839 mutex_enter(&iscsit_isns_mutex);
840 840
841 841 /*
842 842 * If iscsit calls us to modify a target, that target should
843 843 * already exist in the isns_svr_list.
844 844 */
845 845 tmptgt.target = target;
846 846 itarget = avl_find(&isns_target_list, &tmptgt, NULL);
847 847 if (itarget == NULL) {
848 848 /*
849 849 * If target-update gets called while the target is still
850 850 * offline, then there is nothing to do. The target will be
851 851 * completely registered when it comes online.
852 852 */
853 853 mutex_exit(&iscsit_isns_mutex);
854 854 /* Remove the target_info struct -- not needed */
855 855 isnst_clear_target_info_cb(ti);
856 856 return;
857 857 }
858 858
859 859 /* Remove the old target_info struct */
860 860 idm_refcnt_rele(&itarget->target_info->ti_refcnt);
861 861 idm_refcnt_async_wait_ref(&itarget->target_info->ti_refcnt,
862 862 (idm_refcnt_cb_t *)&isnst_clear_target_info_cb);
863 863
864 864 /* Link to new target_info struct */
865 865 itarget->target_info = ti;
866 866 idm_refcnt_hold(&ti->ti_refcnt);
867 867
868 868 itarget->target_update_needed = B_TRUE;
869 869
870 870 isns_targets_changed = B_TRUE;
871 871
872 872 mutex_exit(&iscsit_isns_mutex);
873 873
874 874 isnst_monitor_awaken();
875 875 }
876 876
877 877 static void
878 878 isnst_start()
879 879 {
880 880 ISNST_LOG(CE_NOTE, "**** isnst_start");
881 881
882 882 ASSERT(ISNS_GLOBAL_LOCK_HELD());
883 883
884 884 /*
885 885 * Start ESI thread(s)
886 886 */
887 887 isnst_esi_start();
888 888
889 889 /*
890 890 * Create a thread for monitoring server communications
891 891 */
892 892 isnst_monitor_start();
893 893 }
894 894
895 895 static void
896 896 isnst_stop()
897 897 {
898 898 ASSERT(ISNS_GLOBAL_LOCK_HELD());
899 899 ISNST_LOG(CE_NOTE, "**** isnst_stop");
900 900
901 901
902 902 ISNS_GLOBAL_UNLOCK();
903 903 isnst_esi_stop();
904 904 isnst_monitor_stop();
905 905 ISNS_GLOBAL_LOCK();
906 906 }
907 907
908 908 static void
909 909 isnst_monitor_start(void)
910 910 {
911 911 ISNST_LOG(CE_NOTE, "isnst_monitor_start");
912 912
913 913
914 914 mutex_enter(&isns_monitor_mutex);
915 915 ASSERT(!isns_monitor_thr_running);
916 916 isns_monitor_thr_id = thread_create(NULL, 0,
917 917 isnst_monitor, NULL, 0, &p0, TS_RUN, minclsyspri);
918 918 while (!isns_monitor_thr_running)
919 919 cv_wait(&isns_idle_cv, &isns_monitor_mutex);
920 920 mutex_exit(&isns_monitor_mutex);
921 921 }
922 922
923 923 static void
924 924 isnst_monitor_stop(void)
925 925 {
926 926 ISNST_LOG(CE_NOTE, "isnst_monitor_stop");
927 927
928 928 mutex_enter(&isns_monitor_mutex);
929 929 if (isns_monitor_thr_running) {
930 930 isns_monitor_thr_running = B_FALSE;
931 931 cv_signal(&isns_idle_cv);
932 932 mutex_exit(&isns_monitor_mutex);
933 933
934 934 thread_join(isns_monitor_thr_did);
935 935 return;
936 936 }
937 937 mutex_exit(&isns_monitor_mutex);
938 938 }
939 939
940 940 /*
941 941 * isnst_update_server_timestamp
942 942 *
943 943 * When we receive an ESI request, update the timestamp for the server.
944 944 * If we don't receive one for the specified period of time, we'll attempt
945 945 * to re-register.
946 946 *
947 947 */
948 948 static boolean_t
949 949 isnst_update_server_timestamp(struct sockaddr_storage *ss)
950 950 {
951 951 iscsit_isns_svr_t *svr;
952 952
953 953 ASSERT(ISNS_GLOBAL_LOCK_HELD());
954 954
955 955 /*
956 956 * Find the server and update the timestamp
957 957 */
958 958 for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs);
959 959 svr != NULL;
960 960 svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs, svr)) {
961 961 /*
962 962 * Note that the port number in incoming probe will be
963 963 * different than the iSNS server's port number.
964 964 */
965 965 if (idm_ss_compare(ss, &svr->svr_sa,
966 966 B_TRUE /* v4_mapped_as_v4 */,
967 967 B_FALSE /* don't compare_ports */) == 0) {
968 968 break;
969 969 }
970 970 }
971 971
972 972 if (svr != NULL) {
973 973 /* Update the timestamp we keep for this server */
974 974 svr->svr_last_msg = ddi_get_lbolt();
975 975 /*
976 976 * If we receive ESI probe from a server we are not
977 977 * registered to, then cause a re-reg attempt.
978 978 */
979 979 if (!svr->svr_registered) {
980 980 isnst_monitor_awaken();
981 981 }
982 982 return (B_TRUE);
983 983 }
984 984
985 985 return (B_FALSE);
986 986 }
987 987
988 988
989 989 /*
990 990 * isnst_monitor_all_servers -- loop through all servers
991 991 */
992 992
993 993
994 994 static void
995 995 isnst_monitor_all_servers()
996 996 {
997 997 iscsit_isns_svr_t *svr, *next_svr;
998 998 boolean_t enabled;
999 999 list_t *svr_list;
1000 1000 int rc;
1001 1001
1002 1002 svr_list = &iscsit_global.global_isns_cfg.isns_svrs;
1003 1003
1004 1004 ISNS_GLOBAL_LOCK();
1005 1005
1006 1006 isnst_copy_global_status_changes();
1007 1007
1008 1008 enabled = iscsit_global.global_isns_cfg.isns_state;
1009 1009 for (svr = list_head(svr_list); svr != NULL; svr = next_svr) {
1010 1010
1011 1011 svr->svr_monitor_hold = B_TRUE;
1012 1012 /*
1013 1013 * isnst_monitor_one_server can release ISNS_GLOBAL_LOCK
1014 1014 * internally. This allows isnst_config_merge to run
1015 1015 * even when messages to iSNS servers are pending.
1016 1016 */
1017 1017 rc = isnst_monitor_one_server(svr, enabled);
1018 1018 if (rc != 0) {
1019 1019 svr->svr_retry_count++;
1020 1020 if (svr->svr_registered &&
1021 1021 svr->svr_retry_count > isns_max_retry) {
1022 1022 char server_buf[IDM_SA_NTOP_BUFSIZ];
1023 1023
1024 1024 if (! svr->svr_reset_needed) {
1025 1025 ISNST_LOG(CE_WARN,
1026 1026 "isnst: iSNS server %s"
1027 1027 " not responding (rc=%d).",
1028 1028 idm_sa_ntop(&svr->svr_sa,
1029 1029 server_buf, sizeof (server_buf)),
1030 1030 rc);
1031 1031 svr->svr_reset_needed = B_TRUE;
1032 1032 }
1033 1033 }
1034 1034 } else {
1035 1035 svr->svr_retry_count = 0;
1036 1036 }
1037 1037 /*
1038 1038 * If we have finished unregistering this server,
1039 1039 * it is now OK to delete it.
1040 1040 */
1041 1041 svr->svr_monitor_hold = B_FALSE;
1042 1042 next_svr = list_next(svr_list, svr);
1043 1043 if (svr->svr_delete_needed == B_TRUE &&
1044 1044 svr->svr_registered == B_FALSE) {
1045 1045 isnst_finish_delete_isns(svr);
1046 1046 }
1047 1047 }
1048 1048 ISNS_GLOBAL_UNLOCK();
1049 1049 }
1050 1050
1051 1051 static void
1052 1052 isnst_monitor_awaken(void)
1053 1053 {
1054 1054 mutex_enter(&isns_monitor_mutex);
1055 1055 if (isns_monitor_thr_running) {
1056 1056 DTRACE_PROBE(iscsit__isns__monitor__awaken);
1057 1057 cv_signal(&isns_idle_cv);
1058 1058 }
1059 1059 mutex_exit(&isns_monitor_mutex);
1060 1060 }
1061 1061
1062 1062 /*
1063 1063 * isnst_monitor -- the monitor thread for iSNS
1064 1064 */
1065 1065 /*ARGSUSED*/
1066 1066 static void
1067 1067 isnst_monitor(void *arg)
1068 1068 {
1069 1069 mutex_enter(&isns_monitor_mutex);
1070 1070 isns_monitor_thr_did = curthread->t_did;
↓ open down ↓ |
542 lines elided |
↑ open up ↑ |
1071 1071 isns_monitor_thr_running = B_TRUE;
1072 1072 cv_signal(&isns_idle_cv);
1073 1073
1074 1074 /*
1075 1075 * Start with a short pause (5 sec) to allow all targets
1076 1076 * to be registered before we send register-all. This is
1077 1077 * purely an optimization to cut down on the number of
1078 1078 * messages we send to the iSNS server.
1079 1079 */
1080 1080 mutex_exit(&isns_monitor_mutex);
1081 - delay(drv_usectohz(isns_initial_delay * 1000000));
1081 + delay(drv_sectohz(isns_initial_delay));
1082 1082 mutex_enter(&isns_monitor_mutex);
1083 1083
1084 1084 /* Force an initialization of isns_all_portals */
1085 1085 mutex_enter(&iscsit_isns_mutex);
1086 1086 isns_portals_changed = B_TRUE;
1087 1087 mutex_exit(&iscsit_isns_mutex);
1088 1088
1089 1089 while (isns_monitor_thr_running) {
1090 1090
1091 1091 /* Update servers */
1092 1092 mutex_exit(&isns_monitor_mutex);
1093 1093 isnst_monitor_all_servers();
1094 1094 mutex_enter(&isns_monitor_mutex);
1095 1095
1096 1096 /* If something needs attention, go right to the top */
1097 1097 mutex_enter(&iscsit_isns_mutex);
1098 1098 if (isns_targets_changed || isns_portals_changed) {
1099 1099 DTRACE_PROBE(iscsit__isns__monitor__reenter);
1100 1100 mutex_exit(&iscsit_isns_mutex);
1101 1101 /* isns_monitor_mutex still held */
1102 1102 continue;
1103 1103 }
1104 1104 mutex_exit(&iscsit_isns_mutex);
1105 1105
1106 1106 /*
1107 1107 * Keep running until isns_monitor_thr_running is set to
1108 1108 * B_FALSE.
1109 1109 */
1110 1110 if (! isns_monitor_thr_running)
1111 1111 break;
1112 1112
1113 1113 DTRACE_PROBE(iscsit__isns__monitor__sleep);
1114 1114 (void) cv_reltimedwait(&isns_idle_cv, &isns_monitor_mutex,
1115 1115 monitor_idle_interval, TR_CLOCK_TICK);
1116 1116 DTRACE_PROBE1(iscsit__isns__monitor__wakeup,
1117 1117 boolean_t, isns_monitor_thr_running);
1118 1118 }
1119 1119
1120 1120 mutex_exit(&isns_monitor_mutex);
1121 1121
1122 1122 /* Update the servers one last time for deregistration */
1123 1123 isnst_monitor_all_servers();
1124 1124
1125 1125 /* Clean up the all-portals list */
1126 1126 ISNS_GLOBAL_LOCK();
1127 1127 isnst_clear_default_portals();
1128 1128 ISNS_GLOBAL_UNLOCK();
1129 1129
1130 1130 /* terminate the thread at the last */
1131 1131 thread_exit();
1132 1132 }
1133 1133
1134 1134 static int
1135 1135 isnst_monitor_one_server(iscsit_isns_svr_t *svr, boolean_t enabled)
1136 1136 {
1137 1137 int rc = 0;
1138 1138 isns_target_t *itarget;
1139 1139
1140 1140 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1141 1141
1142 1142 /*
1143 1143 * First, take care of the case where iSNS is no longer enabled.
1144 1144 *
1145 1145 */
1146 1146
1147 1147 if (enabled == B_FALSE || svr->svr_delete_needed) {
1148 1148 /*
1149 1149 * Just try one time to deregister all from server.
1150 1150 * Doesn't matter if this fails. We're disabled.
1151 1151 */
1152 1152 (void) isnst_update_one_server(svr, NULL, ISNS_DEREGISTER_ALL);
1153 1153 isnst_set_server_status(svr, B_FALSE);
1154 1154 return (0);
1155 1155 }
1156 1156
1157 1157 retry_replace_all:
1158 1158 /*
1159 1159 * If the server needs replace-all, check if it should
1160 1160 * be a DevDereg (i.e. if the last target is gone.)
1161 1161 */
1162 1162
1163 1163 if (svr->svr_registered && svr->svr_reset_needed) {
1164 1164 /* Send DevDereg if last registered target */
1165 1165 isns_target_t *jtarget;
1166 1166 for (jtarget = avl_first(&svr->svr_target_list);
1167 1167 jtarget != NULL;
1168 1168 jtarget = AVL_NEXT(&svr->svr_target_list, jtarget)) {
1169 1169 if (!jtarget->target_delete_needed) {
1170 1170 break;
1171 1171 }
1172 1172 }
1173 1173 /*
1174 1174 * jtarget is null IFF all tgts need deletion,
1175 1175 * and there are no new targets to register.
1176 1176 */
1177 1177 if (jtarget == NULL) {
1178 1178 rc = isnst_update_one_server(svr, NULL,
1179 1179 ISNS_DEREGISTER_ALL);
1180 1180 if (rc != 0) {
1181 1181 return (rc);
1182 1182 }
1183 1183 isnst_set_server_status(svr, B_FALSE);
1184 1184 return (0);
1185 1185 }
1186 1186 }
1187 1187
1188 1188 /*
1189 1189 * If the server is not yet registered, do the registration
1190 1190 */
1191 1191 if (! svr->svr_registered || svr->svr_reset_needed) {
1192 1192
1193 1193 if (avl_numnodes(&svr->svr_target_list) == 0) {
1194 1194 /* If no targets, nothing to register */
1195 1195 return (0);
1196 1196 }
1197 1197 if ((rc = isnst_update_one_server(svr, NULL,
1198 1198 ISNS_REGISTER_ALL)) != 0) {
1199 1199 /* Registration failed */
1200 1200 return (rc);
1201 1201 }
1202 1202 isnst_set_server_status(svr, B_TRUE);
1203 1203
1204 1204 }
1205 1205
1206 1206 /* The following checks are expensive, so only do them if needed */
1207 1207 if (svr->svr_targets_changed) {
1208 1208 isns_target_t *next_target;
1209 1209 /*
1210 1210 * If there is a target to be deleted, send the
1211 1211 * deletion request for one target at a time.
1212 1212 */
1213 1213 for (itarget = avl_first(&svr->svr_target_list);
1214 1214 itarget != NULL;
1215 1215 itarget = next_target) {
1216 1216 next_target = AVL_NEXT(&svr->svr_target_list, itarget);
1217 1217 if (itarget->target_delete_needed) {
1218 1218 /* See if last non-deleted target */
1219 1219 isns_target_t *jtarget;
1220 1220 ASSERT(itarget->target_registered);
1221 1221 for (jtarget =
1222 1222 avl_first(&svr->svr_target_list);
1223 1223 jtarget != NULL;
1224 1224 jtarget = AVL_NEXT(&svr->svr_target_list,
1225 1225 jtarget)) {
1226 1226 if (jtarget->target_registered &&
1227 1227 !jtarget->target_delete_needed) {
1228 1228 break;
1229 1229 }
1230 1230 }
1231 1231 /* jtarget is null if last registered tgt */
1232 1232 if (jtarget == NULL) {
1233 1233 /*
1234 1234 * Removing last tgt -- deregister all.
1235 1235 * Doesn't matter if this fails.
1236 1236 * We're disabled.
1237 1237 */
1238 1238 rc = isnst_update_one_server(svr,
1239 1239 NULL, ISNS_DEREGISTER_ALL);
1240 1240 if (rc != 0) {
1241 1241 return (rc);
1242 1242 }
1243 1243 isnst_set_server_status(svr, B_FALSE);
1244 1244 return (0);
1245 1245 }
1246 1246 rc = isnst_update_one_server(svr,
1247 1247 itarget, ISNS_DEREGISTER_TARGET);
1248 1248 if (rc != 0 && isnst_retry_registration(rc)) {
1249 1249 /* Retryable code => try replace-all */
1250 1250 svr->svr_reset_needed = B_TRUE;
1251 1251 goto retry_replace_all;
1252 1252 }
1253 1253
1254 1254 if (rc != 0) {
1255 1255 return (rc);
1256 1256 }
1257 1257 isnst_clear_from_target_list(itarget,
1258 1258 &svr->svr_target_list);
1259 1259 }
1260 1260 }
1261 1261
1262 1262 /* If any target needs a register or an update, do so */
1263 1263 itarget = avl_first(&svr->svr_target_list);
1264 1264 while (itarget) {
1265 1265 if (!itarget->target_registered ||
1266 1266 itarget->target_update_needed) {
1267 1267
1268 1268 /*
1269 1269 * Because of a bug in the isns
1270 1270 * server, we cannot send a modify
1271 1271 * operation that changes the target's
1272 1272 * TPGTs. So just replace all.
1273 1273 */
1274 1274 if (isns_modify_must_replace) {
1275 1275 svr->svr_reset_needed = B_TRUE;
1276 1276 goto retry_replace_all;
1277 1277 }
1278 1278 /* Try to update existing info for one tgt */
1279 1279 rc = isnst_update_one_server(svr,
1280 1280 itarget,
1281 1281 ISNS_MODIFY_TARGET);
1282 1282 if (rc != 0 && isnst_retry_registration(rc)) {
1283 1283 /* Retryable code => try replace-all */
1284 1284 svr->svr_reset_needed = B_TRUE;
1285 1285 goto retry_replace_all;
1286 1286 }
1287 1287 if (rc != 0) {
1288 1288 return (rc);
1289 1289 }
1290 1290 itarget->target_update_needed =
1291 1291 B_FALSE;
1292 1292 itarget->target_registered = B_TRUE;
1293 1293 }
1294 1294 itarget = AVL_NEXT(&svr->svr_target_list,
1295 1295 itarget);
1296 1296 }
1297 1297
1298 1298 /*
1299 1299 * We have gone through all the cases -- this server
1300 1300 * is now up to date.
1301 1301 */
1302 1302 svr->svr_targets_changed = B_FALSE;
1303 1303 }
1304 1304
1305 1305
1306 1306 if (isns_use_esi) {
1307 1307 /*
1308 1308 * If using ESI, and no ESI request is received within
1309 1309 * MAX_ESI_INTERVALS (3) number of intervals, we'll
1310 1310 * try to re-register with the server. The server will
1311 1311 * delete our information if we fail to respond for 2
1312 1312 * ESI intervals.
1313 1313 */
1314 1314 if (ddi_get_lbolt() >= (svr->svr_last_msg +
1315 1315 drv_usectohz(svr->svr_esi_interval * 1000000 *
1316 1316 MAX_ESI_INTERVALS))) {
1317 1317 /* re-register everything */
1318 1318 svr->svr_reset_needed = B_TRUE;
1319 1319 goto retry_replace_all;
1320 1320 }
1321 1321 } else {
1322 1322 /*
1323 1323 * If not using ESI, make sure to ping server during
1324 1324 * each registration period. Do this at half the
1325 1325 * registration interval, so we won't get timed out.
1326 1326 */
1327 1327 if (ddi_get_lbolt() >= (svr->svr_last_msg +
1328 1328 drv_usectohz(isns_registration_period * (1000000/3)))) {
1329 1329 /* Send a self-query as a keepalive. */
1330 1330 ISNS_GLOBAL_UNLOCK();
1331 1331 rc = isnst_keepalive(svr);
1332 1332 ISNS_GLOBAL_LOCK();
1333 1333 if (rc != 0 && isnst_retry_registration(rc)) {
1334 1334 /* Retryable code => try replace-all */
1335 1335 svr->svr_reset_needed = B_TRUE;
1336 1336 goto retry_replace_all;
1337 1337 }
1338 1338 if (rc != 0) {
1339 1339 return (rc);
1340 1340 }
1341 1341 }
1342 1342 }
1343 1343 return (0);
1344 1344
1345 1345 }
1346 1346
1347 1347 /*
1348 1348 * isnst_mark_deleted_target -- find tgt in svr list but not global list
1349 1349 */
1350 1350 static void
1351 1351 isnst_mark_deleted_targets(iscsit_isns_svr_t *svr)
1352 1352 {
1353 1353 isns_target_t *itarget, *nxt_target, tmptgt;
1354 1354
1355 1355 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1356 1356 ASSERT(mutex_owned(&iscsit_isns_mutex));
1357 1357
1358 1358 for (itarget = avl_first(&svr->svr_target_list);
1359 1359 itarget != NULL;
1360 1360 itarget = nxt_target) {
1361 1361 tmptgt.target = itarget->target;
1362 1362 nxt_target = AVL_NEXT(&svr->svr_target_list, itarget);
1363 1363 if (avl_find(&isns_target_list, &tmptgt, NULL) == NULL) {
1364 1364 if (itarget->target_registered) {
1365 1365 itarget->target_delete_needed = B_TRUE;
1366 1366 } else {
1367 1367 isnst_clear_from_target_list(itarget,
1368 1368 &svr->svr_target_list);
1369 1369 }
1370 1370 }
1371 1371 }
1372 1372 }
1373 1373
1374 1374 static isns_target_t *
1375 1375 isnst_latch_to_target_list(isns_target_t *jtarget, avl_tree_t *target_list)
1376 1376 {
1377 1377 isns_target_t *itarget, tmptgt;
1378 1378 avl_index_t where;
1379 1379
1380 1380 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1381 1381 ASSERT(mutex_owned(&iscsit_isns_mutex));
1382 1382 /*
1383 1383 * Make sure this target isn't already in our list.
1384 1384 */
1385 1385
1386 1386 tmptgt.target = jtarget->target;
1387 1387 if ((itarget = (isns_target_t *)avl_find(target_list,
1388 1388 &tmptgt, &where)) == NULL) {
1389 1389 itarget = kmem_zalloc(sizeof (isns_target_t), KM_SLEEP);
1390 1390
1391 1391 itarget->target = jtarget->target;
1392 1392 itarget->target_info = jtarget->target_info;
1393 1393 idm_refcnt_hold(&itarget->target_info->ti_refcnt);
1394 1394
1395 1395 avl_insert(target_list, (void *)itarget, where);
1396 1396 } else {
1397 1397 ASSERT(0);
1398 1398 }
1399 1399
1400 1400 return (itarget);
1401 1401 }
1402 1402
1403 1403 static void
1404 1404 isnst_clear_target_list(iscsit_isns_svr_t *svr)
1405 1405 {
1406 1406 isns_target_t *itarget;
1407 1407
1408 1408 while ((itarget = avl_first(&svr->svr_target_list)) != NULL) {
1409 1409 isnst_clear_from_target_list(itarget,
1410 1410 &svr->svr_target_list);
1411 1411 }
1412 1412 }
1413 1413
1414 1414 static void
1415 1415 isnst_clear_from_target_list(isns_target_t *jtarget, avl_tree_t *target_list)
1416 1416 {
1417 1417 isns_target_t *itarget, tmptgt;
1418 1418
1419 1419 tmptgt.target = jtarget->target;
1420 1420
1421 1421 if ((itarget = avl_find(target_list, &tmptgt, NULL))
1422 1422 != NULL) {
1423 1423
1424 1424 avl_remove(target_list, itarget);
1425 1425 idm_refcnt_rele(&itarget->target_info->ti_refcnt);
1426 1426 kmem_free(itarget, sizeof (isns_target_t));
1427 1427 } else {
1428 1428 ASSERT(0);
1429 1429 }
1430 1430 }
1431 1431
1432 1432 /*
1433 1433 * isnst_copy_global_status_changes -- update svrs to match iscsit
1434 1434 *
1435 1435 * At the end of this routine svr->svr_target_list has all the entries
1436 1436 * in the current isns_target_list plus any targets that are marked
1437 1437 * for deletion.
1438 1438 */
1439 1439 static void
1440 1440 isnst_copy_global_status_changes(void)
1441 1441 {
1442 1442 isns_target_t *ttarget, *itarget, tmptgt;
1443 1443 iscsit_isns_svr_t *svr;
1444 1444
1445 1445 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1446 1446
1447 1447 /*
1448 1448 * Copy info about recent transitions from global state to
1449 1449 * per-server state. We use the global state so that iscsit
1450 1450 * functions can proceed without blocking on slow-to-release
1451 1451 * iSNS locks.
1452 1452 */
1453 1453 mutex_enter(&iscsit_isns_mutex);
1454 1454
1455 1455 /*
1456 1456 * Periodically check for changed IP addresses. This function
1457 1457 * sets isns_all_portals to the current set, and sets
1458 1458 * isns_portals_changed if a portal is added or removed.
1459 1459 */
1460 1460 isnst_monitor_default_portal_list();
1461 1461
1462 1462 /* Initialize the per-server structs to some basic values */
1463 1463 for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs);
1464 1464 svr != NULL;
1465 1465 svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs,
1466 1466 svr)) {
1467 1467 if (isns_portals_changed && svr->svr_registered) {
1468 1468 /*
1469 1469 * Cause re-register, for now, when portals change.
1470 1470 * Eventually, we should add new portals one by one
1471 1471 */
1472 1472 svr->svr_reset_needed = B_TRUE;
1473 1473 }
1474 1474 if (!svr->svr_registered) {
1475 1475 /* To re-register, start with empty target list */
1476 1476 isnst_clear_target_list(svr);
1477 1477 /* And set flag to add all current targets, below */
1478 1478 isns_targets_changed = B_TRUE;
1479 1479 } else if (isns_targets_changed || svr->svr_reset_needed) {
1480 1480 /* Mark to look for target changes */
1481 1481 isnst_mark_deleted_targets(svr);
1482 1482 svr->svr_targets_changed = B_TRUE;
1483 1483 }
1484 1484 }
1485 1485
1486 1486 /*
1487 1487 * If any target has been modified, tell all the svrs to
1488 1488 * update that target.
1489 1489 */
1490 1490 if (isns_targets_changed) {
1491 1491 ttarget = avl_first(&isns_target_list);
1492 1492 while (ttarget) {
1493 1493 for (svr = list_head(
1494 1494 &iscsit_global.global_isns_cfg.isns_svrs);
1495 1495 svr != NULL;
1496 1496 svr = list_next(
1497 1497 &iscsit_global.global_isns_cfg.isns_svrs,
1498 1498 svr)) {
1499 1499 tmptgt.target = ttarget->target;
1500 1500 itarget = avl_find(
1501 1501 &svr->svr_target_list,
1502 1502 &tmptgt, NULL);
1503 1503
1504 1504 if (itarget == NULL) {
1505 1505 /* Add a new target */
1506 1506 (void) isnst_latch_to_target_list(
1507 1507 ttarget, &svr->svr_target_list);
1508 1508 } else if (ttarget->target_update_needed) {
1509 1509 /* Modify existing target */
1510 1510 itarget->target_update_needed =
1511 1511 B_TRUE;
1512 1512 /* Remove link to old target_info */
1513 1513 idm_refcnt_rele(
1514 1514 &itarget->target_info->ti_refcnt);
1515 1515 /* Link to new target_info struct */
1516 1516 itarget->target_info =
1517 1517 ttarget->target_info;
1518 1518 idm_refcnt_hold(
1519 1519 &itarget->target_info->ti_refcnt);
1520 1520 }
1521 1521 }
1522 1522 ttarget->target_update_needed = B_FALSE;
1523 1523 ttarget = AVL_NEXT(&isns_target_list, ttarget);
1524 1524 }
1525 1525 }
1526 1526
1527 1527 /*
1528 1528 * Now we have updated the per-server state for all servers.
1529 1529 * Clear the global state flags
1530 1530 */
1531 1531 isns_targets_changed = B_FALSE;
1532 1532 isns_portals_changed = B_FALSE;
1533 1533 mutex_exit(&iscsit_isns_mutex);
1534 1534 }
1535 1535
1536 1536 /*
1537 1537 * isnst_update_one_server releases ISNS_GLOBAL_LOCK internally and
1538 1538 * acquires it again as needed. This allows isnst_config_merge and
1539 1539 * isnst_esi_thread to run even while waiting for a response from the
1540 1540 * iSNS server (or a dead iSNS server).
1541 1541 */
1542 1542 static int
1543 1543 isnst_update_one_server(iscsit_isns_svr_t *svr, isns_target_t *itarget,
1544 1544 isns_reg_type_t reg)
1545 1545 {
1546 1546 int rc = 0;
1547 1547
1548 1548 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1549 1549 ISNS_GLOBAL_UNLOCK();
1550 1550
1551 1551 switch (reg) {
1552 1552 case ISNS_DEREGISTER_TARGET:
1553 1553 rc = isnst_deregister(svr, itarget);
1554 1554 break;
1555 1555
1556 1556 case ISNS_DEREGISTER_ALL:
1557 1557 rc = isnst_deregister(svr, NULL);
1558 1558 break;
1559 1559
1560 1560 case ISNS_MODIFY_TARGET:
1561 1561 case ISNS_REGISTER_TARGET:
1562 1562 rc = isnst_register(svr, itarget, reg);
1563 1563 break;
1564 1564
1565 1565 case ISNS_REGISTER_ALL:
1566 1566 rc = isnst_register(svr, NULL, reg);
1567 1567 break;
1568 1568
1569 1569 default:
1570 1570 ASSERT(0);
1571 1571 /* NOTREACHED */
1572 1572 }
1573 1573
1574 1574 ISNS_GLOBAL_LOCK();
1575 1575 return (rc);
1576 1576 }
1577 1577
1578 1578 /*
1579 1579 * isnst_retry_registration
1580 1580 *
1581 1581 * This function checks the return value from a registration pdu and
1582 1582 * determines whether or not we should retry this request. If the
1583 1583 * request is retried, it will do so as an "update", which means we
1584 1584 * re-register everything.
1585 1585 */
1586 1586
1587 1587 static boolean_t
1588 1588 isnst_retry_registration(int rsp_status_code)
1589 1589 {
1590 1590 boolean_t retry;
1591 1591
1592 1592 /*
1593 1593 * The following are the error codes that indicate isns-client
1594 1594 * and isns-server are out of synch. E.g. No-Such-Entry can
1595 1595 * occur on a keepalive if the server has timed out our
1596 1596 * connection. If we get one of these messages, we replace-all
1597 1597 * right away to get back in synch faster.
1598 1598 */
1599 1599 switch (rsp_status_code) {
1600 1600 case ISNS_RSP_INVALID_REGIS:
1601 1601 case ISNS_RSP_SRC_UNAUTHORIZED:
1602 1602 case ISNS_RSP_BUSY:
1603 1603 case ISNS_RSP_INVALID_UPDATE:
1604 1604 case ISNS_RSP_NO_SUCH_ENTRY:
1605 1605 retry = B_TRUE;
1606 1606 break;
1607 1607 default:
1608 1608 retry = B_FALSE;
1609 1609 break;
1610 1610 }
1611 1611
1612 1612 return (retry);
1613 1613 }
1614 1614
1615 1615
1616 1616
1617 1617 static int
1618 1618 isnst_register(iscsit_isns_svr_t *svr, isns_target_t *itarget,
1619 1619 isns_reg_type_t regtype)
1620 1620 {
1621 1621 struct sonode *so;
1622 1622 int rc = 0;
1623 1623 isns_pdu_t *pdu, *rsp;
1624 1624 size_t pdu_size, rsp_size;
1625 1625
1626 1626 /* create TCP connection to the isns server */
1627 1627 so = isnst_open_so(&svr->svr_sa);
1628 1628 if (so == NULL) {
1629 1629 return (-1);
1630 1630 }
1631 1631
1632 1632 pdu_size = isnst_make_reg_pdu(&pdu, itarget, svr, regtype);
1633 1633 if (pdu_size == 0) {
1634 1634 isnst_close_so(so);
1635 1635 return (-1);
1636 1636 }
1637 1637
1638 1638 rc = isnst_send_pdu(so, pdu);
1639 1639 if (rc != 0) {
1640 1640 kmem_free(pdu, pdu_size);
1641 1641 isnst_close_so(so);
1642 1642 return (rc);
1643 1643 }
1644 1644
1645 1645 rsp_size = isnst_rcv_pdu(so, &rsp);
1646 1646 if (rsp_size == 0) {
1647 1647 kmem_free(pdu, pdu_size);
1648 1648 isnst_close_so(so);
1649 1649 return (-1);
1650 1650 }
1651 1651
1652 1652 rc = isnst_verify_rsp(svr, pdu, rsp, rsp_size);
1653 1653
1654 1654 kmem_free(pdu, pdu_size);
1655 1655 kmem_free(rsp, rsp_size);
1656 1656 isnst_close_so(so);
1657 1657
1658 1658 return (rc);
1659 1659 }
1660 1660
1661 1661 /*
1662 1662 * isnst_make_reg_pdu:
1663 1663 * Cases:
1664 1664 * initial registration of all targets (replace-all)
1665 1665 * initial registration of a single target (update-existing)
1666 1666 * modify an existing target (update-existing)
1667 1667 */
1668 1668 static size_t
1669 1669 isnst_make_reg_pdu(isns_pdu_t **pdu, isns_target_t *itarget,
1670 1670 iscsit_isns_svr_t *svr, isns_reg_type_t regtype)
1671 1671 {
1672 1672 size_t pdu_size;
1673 1673 char *str;
1674 1674 int len;
1675 1675 isns_target_t *src;
1676 1676 boolean_t reg_all = B_FALSE;
1677 1677 uint16_t flags = 0;
1678 1678
1679 1679 ISNS_GLOBAL_LOCK();
1680 1680 ASSERT(svr->svr_monitor_hold);
1681 1681 /*
1682 1682 * svr could have an empty target list if svr was added
1683 1683 * by isnst_config_merge sometime after the last call to
1684 1684 * copy_global_status_changes. Just skip this chance
1685 1685 * to reregister. The next call to copy_global_status_changes
1686 1686 * will sort things out.
1687 1687 */
1688 1688 if (avl_numnodes(&svr->svr_target_list) == 0) {
1689 1689 /* If no targets, nothing to register */
1690 1690 ISNS_GLOBAL_UNLOCK();
1691 1691 return (0);
1692 1692 }
1693 1693 /*
1694 1694 * Find a source attribute for this registration.
1695 1695 *
1696 1696 * If updating a specific target for the first time, use that
1697 1697 * target.
1698 1698 * If already registered, use a registered target
1699 1699 * Otherwise, use the first target we are going to register.
1700 1700 */
1701 1701 if (itarget != NULL && ! svr->svr_registered) {
1702 1702 src = itarget;
1703 1703 } else if (svr->svr_registered) {
1704 1704 src = isnst_get_registered_source_locked(svr);
1705 1705 } else {
1706 1706 /*
1707 1707 * When registering to a server, and we don't know which
1708 1708 * of our targets the server might already know,
1709 1709 * cycle through each of our targets as source. The server
1710 1710 * does source validation. If the server knows any of our
1711 1711 * targets, it will eventually accept one of our registrations.
1712 1712 */
1713 1713 int i;
1714 1714 isns_target_t *jtarget;
1715 1715
1716 1716 if (svr->svr_last_target_index >=
1717 1717 avl_numnodes(&svr->svr_target_list) - 1) {
1718 1718 svr->svr_last_target_index = 0;
1719 1719 } else {
1720 1720 svr->svr_last_target_index++;
1721 1721 }
1722 1722 for (i = 0, jtarget = avl_first(&svr->svr_target_list);
1723 1723 i < svr->svr_last_target_index;
1724 1724 i++, jtarget = AVL_NEXT(&svr->svr_target_list, jtarget)) {
1725 1725 ASSERT(jtarget != NULL);
1726 1726 }
1727 1727 src = jtarget;
1728 1728 ASSERT(src != NULL);
1729 1729 }
1730 1730
1731 1731 /*
1732 1732 * Null target means we're replacing everything.
1733 1733 */
1734 1734 if (itarget == NULL) {
1735 1735 reg_all = B_TRUE;
1736 1736 flags = ISNS_FLAG_REPLACE_REG;
1737 1737 /* Reset itarget to the beginning of our list */
1738 1738 itarget = (isns_target_t *)avl_first(&svr->svr_target_list);
1739 1739 } else if (regtype == ISNS_REGISTER_TARGET) {
1740 1740 flags = ISNS_FLAG_REPLACE_REG;
1741 1741 ASSERT(!itarget->target_delete_needed);
1742 1742 }
1743 1743
1744 1744 pdu_size = isnst_create_pdu_header(ISNS_DEV_ATTR_REG, pdu, flags);
1745 1745 if (pdu_size == 0) {
1746 1746 ISNS_GLOBAL_UNLOCK();
1747 1747 return (0);
1748 1748 }
1749 1749
1750 1750 /* Source Attribute */
1751 1751
1752 1752 len = strlen(src->target_info->ti_tgt_name) + 1;
1753 1753 if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID,
1754 1754 len, src->target_info->ti_tgt_name, 0) != 0) {
1755 1755 goto pdu_error;
1756 1756 }
1757 1757
1758 1758 /*
1759 1759 * Message Key Attributes - EID
1760 1760 */
1761 1761 len = strlen(isns_eid) + 1;
1762 1762
1763 1763 if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID,
1764 1764 len, isns_eid, 0) != 0) {
1765 1765 goto pdu_error;
1766 1766 }
1767 1767
1768 1768 /* Delimiter */
1769 1769 if (isnst_add_attr(*pdu, pdu_size, ISNS_DELIMITER_ATTR_ID,
1770 1770 0, 0, 0) != 0) {
1771 1771 goto pdu_error;
1772 1772 }
1773 1773
1774 1774 /*
1775 1775 * Operating Attributes
1776 1776 */
1777 1777 if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID, len,
1778 1778 isns_eid, 0) != 0) {
1779 1779 goto pdu_error;
1780 1780 }
1781 1781
1782 1782
1783 1783 /* ENTITY Protocol - Section 6.2.2 */
1784 1784 if (isnst_add_attr(*pdu, pdu_size,
1785 1785 ISNS_ENTITY_PROTOCOL_ATTR_ID,
1786 1786 4, 0, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) {
1787 1787 goto pdu_error;
1788 1788 }
1789 1789
1790 1790 if (reg_all) {
1791 1791 /* Registration Period -- use if not using ESI */
1792 1792 if (!isns_use_esi &&
1793 1793 isnst_add_attr(*pdu, pdu_size,
1794 1794 ISNS_ENTITY_REG_PERIOD_ATTR_ID, 4,
1795 1795 0, isns_registration_period) != 0) {
1796 1796 goto pdu_error;
1797 1797 }
1798 1798 /*
1799 1799 * Network entity portal information - only when
1800 1800 * replacing all. Since targets are only registered
1801 1801 * to iSNS when their portals are already registered
1802 1802 * to iSNS, we can assume entity portals exist.
1803 1803 */
1804 1804 if (isnst_reg_pdu_add_entity_portals(*pdu, pdu_size) != 0) {
1805 1805 goto pdu_error;
1806 1806 }
1807 1807
1808 1808 /*
1809 1809 * Skip over delete-pending tgts. There must be at
1810 1810 * least one non-deleted tgt, or it is an error.
1811 1811 */
1812 1812 while (itarget->target_delete_needed) {
1813 1813 itarget = AVL_NEXT(&svr->svr_target_list,
1814 1814 itarget);
1815 1815 ASSERT(itarget != NULL);
1816 1816 }
1817 1817 }
1818 1818
1819 1819
1820 1820 /* Add information about each target or one target */
1821 1821 do {
1822 1822
1823 1823 /* iSCSI Name - Section 6.4.1 */
1824 1824 str = itarget->target_info->ti_tgt_name;
1825 1825 len = strlen(str) + 1;
1826 1826 if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID,
1827 1827 len, str, 0) != 0) {
1828 1828 goto pdu_error;
1829 1829 }
1830 1830
1831 1831 /* iSCSI Node Type */
1832 1832 if (isnst_add_attr(*pdu, pdu_size,
1833 1833 ISNS_ISCSI_NODE_TYPE_ATTR_ID, 4, 0,
1834 1834 ISNS_TARGET_NODE_TYPE) != 0) {
1835 1835 goto pdu_error;
1836 1836 }
1837 1837
1838 1838 /* iSCSI Alias */
1839 1839 str = itarget->target_info->ti_tgt_alias;
1840 1840 len = strnlen(str,
1841 1841 sizeof (itarget->target_info->ti_tgt_alias));
1842 1842 if (len) {
1843 1843 /* Found alias in property list */
1844 1844 if (isnst_add_attr(*pdu, pdu_size,
1845 1845 ISNS_ISCSI_ALIAS_ATTR_ID, len+1, str, 0) != 0) {
1846 1846 goto pdu_error;
1847 1847 }
1848 1848 }
1849 1849
1850 1850 if (isnst_reg_pdu_add_pg(*pdu, pdu_size, itarget) != 0) {
1851 1851 goto pdu_error;
1852 1852 }
1853 1853
1854 1854 /* If registering one target, then we are done. */
1855 1855 if (!reg_all) {
1856 1856 break;
1857 1857 }
1858 1858
1859 1859 /* Skip over delete-pending tgts */
1860 1860 do {
1861 1861 itarget = AVL_NEXT(&svr->svr_target_list, itarget);
1862 1862 } while (itarget != NULL && itarget->target_delete_needed);
1863 1863
1864 1864 } while (itarget != NULL);
1865 1865
1866 1866 ISNS_GLOBAL_UNLOCK();
1867 1867 return (pdu_size);
1868 1868
1869 1869 pdu_error:
1870 1870 /* packet too large, no memory (or other error) */
1871 1871 len = ntohs((*pdu)->payload_len);
1872 1872 if (len + 1000 > isns_message_buf_size) {
1873 1873 /* Increase the PDU size we will ask for next time */
1874 1874 if (isns_message_buf_size * 2 <= ISNST_MAX_MSG_SIZE) {
1875 1875 isns_message_buf_size *= 2;
1876 1876 ISNST_LOG(CE_NOTE,
1877 1877 "Increasing isns_message_buf_size to %d",
1878 1878 isns_message_buf_size);
1879 1879 } else {
1880 1880 cmn_err(CE_WARN, "iscsit: isns: no space"
1881 1881 " to send required PDU");
1882 1882 }
1883 1883 }
1884 1884
1885 1885 kmem_free(*pdu, pdu_size);
1886 1886 *pdu = NULL;
1887 1887
1888 1888 ISNS_GLOBAL_UNLOCK();
1889 1889 return (0);
1890 1890 }
1891 1891
1892 1892 static int
1893 1893 isnst_reg_pdu_add_entity_portals(isns_pdu_t *pdu, size_t pdu_size)
1894 1894 {
1895 1895 int rc = 0;
1896 1896 isns_portal_t *iportal;
1897 1897
1898 1898 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1899 1899
1900 1900 iportal = (isns_portal_t *)avl_first(&isns_all_portals);
1901 1901 while (iportal != NULL) {
1902 1902 /* Do not include ESI port if not using ESI */
1903 1903 if (isnst_add_portal_attr(pdu, pdu_size,
1904 1904 ISNS_PORTAL_IP_ADDR_ATTR_ID,
1905 1905 ISNS_PORTAL_PORT_ATTR_ID,
1906 1906 &iportal->portal_addr,
1907 1907 isns_use_esi /* ESI info */) != 0) {
1908 1908 rc = -1;
1909 1909 break;
1910 1910 }
1911 1911 iportal = AVL_NEXT(&isns_all_portals, iportal);
1912 1912 }
1913 1913
1914 1914 return (rc);
1915 1915 }
1916 1916
1917 1917
1918 1918 /*
1919 1919 * isnst_reg_pdu_add_pg -- add the PG and PGT entries for one target.
1920 1920 */
1921 1921 static int
1922 1922 isnst_reg_pdu_add_pg(isns_pdu_t *pdu, size_t pdu_size, isns_target_t *itarget)
1923 1923 {
1924 1924 int rval = 0;
1925 1925 avl_tree_t null_portals;
1926 1926 isns_target_info_t *ti;
1927 1927 isns_tpgt_t *tig;
1928 1928
1929 1929 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1930 1930
1931 1931 ti = itarget->target_info;
1932 1932
1933 1933 /*
1934 1934 * If all registered targets only use the default TPGT, then
1935 1935 * we can skip sending PG info to the iSNS server.
1936 1936 */
1937 1937 if (num_tpg_portals == 0)
1938 1938 return (0);
1939 1939
1940 1940 /*
1941 1941 * For each target, we start with the full portal list,
1942 1942 * and then remove portals as we add them to TPGTs for this target.
1943 1943 * At the end, all the remaining portals go into the "null pg".
1944 1944 * We use the "null_portals" list to track this.
1945 1945 */
1946 1946 avl_create(&null_portals, isnst_portal_avl_compare,
1947 1947 sizeof (isns_portal_t), offsetof(isns_portal_t, portal_node));
1948 1948 isnst_copy_portal_list(&isns_all_portals, &null_portals);
1949 1949
1950 1950 for (tig = list_head(&ti->ti_tpgt_list);
1951 1951 tig != NULL;
1952 1952 tig = list_next(&ti->ti_tpgt_list, tig)) {
1953 1953
1954 1954 if (tig->ti_tpgt_tag == ISCSIT_DEFAULT_TPGT) {
1955 1955 /* Add portal info from list of default portals */
1956 1956 if (isnst_add_default_pg(pdu, pdu_size,
1957 1957 &null_portals) != 0) {
1958 1958 rval = 1;
1959 1959 break;
1960 1960 }
1961 1961 } else {
1962 1962 /* Add portal info from this TPGT's entries */
1963 1963 if (isnst_add_tpg_pg(pdu, pdu_size, tig,
1964 1964 &null_portals) != 0) {
1965 1965 rval = 1;
1966 1966 break;
1967 1967 }
1968 1968 }
1969 1969 }
1970 1970
1971 1971 /* Add the remaining portals (if any) to the null PG */
1972 1972 if (rval == 0 &&
1973 1973 isnst_add_null_pg(pdu, pdu_size, &null_portals) != 0) {
1974 1974 rval = 1;
1975 1975 }
1976 1976 isnst_clear_portal_list(&null_portals);
1977 1977 avl_destroy(&null_portals);
1978 1978 return (rval);
1979 1979 }
1980 1980
1981 1981 /* Write one TPGT's info into the PDU */
1982 1982 static int
1983 1983 isnst_add_tpg_pg(isns_pdu_t *pdu, size_t pdu_size,
1984 1984 isns_tpgt_t *tig, avl_tree_t *null_portal_list)
1985 1985 {
1986 1986 isns_tpgt_addr_t *tip;
1987 1987 int rval = 0;
1988 1988
1989 1989 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1990 1990 ASSERT(tig->ti_tpgt_tag != ISCSIT_DEFAULT_TPGT);
1991 1991
1992 1992 /* Portal Group Tag */
1993 1993 if (isnst_add_attr(pdu, pdu_size,
1994 1994 ISNS_PG_TAG_ATTR_ID, 4, 0, tig->ti_tpgt_tag) != 0) {
1995 1995 rval = 1;
1996 1996 goto pg_done;
1997 1997 }
1998 1998
1999 1999 tip = list_head(&tig->ti_portal_list);
2000 2000 ASSERT(tip != NULL);
2001 2001 do {
2002 2002 /* PG Portal Addr and PG Portal Port */
2003 2003 if (isnst_add_portal_attr(pdu, pdu_size,
2004 2004 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID,
2005 2005 ISNS_PG_PORTAL_PORT_ATTR_ID,
2006 2006 &tip->portal_addr, B_FALSE /* ESI */) != 0) {
2007 2007 rval = 1;
2008 2008 goto pg_done;
2009 2009 }
2010 2010 isnst_remove_from_portal_list(&tip->portal_addr,
2011 2011 null_portal_list);
2012 2012
2013 2013 tip = list_next(&tig->ti_portal_list, tip);
2014 2014 } while (tip != NULL);
2015 2015
2016 2016 pg_done:
2017 2017 return (rval);
2018 2018 }
2019 2019
2020 2020 static int
2021 2021 isnst_add_default_pg(isns_pdu_t *pdu, size_t pdu_size,
2022 2022 avl_tree_t *null_portal_list)
2023 2023 {
2024 2024 isns_portal_t *iportal;
2025 2025
2026 2026 ASSERT(ISNS_GLOBAL_LOCK_HELD());
2027 2027
2028 2028 if (num_default_portals == 0) {
2029 2029 /*
2030 2030 * It is OK for a target with default-portals to be
2031 2031 * online from an STMF perspective and yet all
2032 2032 * default portals are down. if other (non-default)
2033 2033 * portals do exist, we will still announce the target
2034 2034 * to the isns server. In this case, we will specify
2035 2035 * all the active non-default portals as NULL portals.
2036 2036 * This is an OK state.
2037 2037 *
2038 2038 * There is a corner case if non-default portals have
2039 2039 * been marked online but the targets that use them
2040 2040 * are not fully online yet, AND all the default portals
2041 2041 * are down. In this case, the iSNS server will receive
2042 2042 * a DevAttrReg pdu that announces both non-default
2043 2043 * portals and default-portal-only targets. In other
2044 2044 * words, there may be no target that has an active
2045 2045 * portal. The iSNS spec does not forbid this case.
2046 2046 *
2047 2047 * Both of the above cases are somewhat theoretical.
2048 2048 * If the default portals are down we probably cannot
2049 2049 * get any messages through to the iSNS server anyway.
2050 2050 */
2051 2051 return (0);
2052 2052 }
2053 2053
2054 2054 /* Portal Group Tag */
2055 2055 if (isnst_add_attr(pdu, pdu_size,
2056 2056 ISNS_PG_TAG_ATTR_ID, 4, 0, ISCSIT_DEFAULT_TPGT) != 0) {
2057 2057 return (1);
2058 2058 }
2059 2059
2060 2060 for (iportal = avl_first(&isns_all_portals);
2061 2061 iportal != NULL;
2062 2062 iportal = AVL_NEXT(&isns_all_portals, iportal)) {
2063 2063 if (iportal->portal_default) {
2064 2064 /* PG Portal Addr and PG Portal Port */
2065 2065 if (isnst_add_portal_attr(pdu, pdu_size,
2066 2066 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID,
2067 2067 ISNS_PG_PORTAL_PORT_ATTR_ID,
2068 2068 &iportal->portal_addr, B_FALSE) != 0) {
2069 2069 return (1);
2070 2070 }
2071 2071 isnst_remove_from_portal_list(&iportal->portal_addr,
2072 2072 null_portal_list);
2073 2073 }
2074 2074 }
2075 2075
2076 2076 return (0);
2077 2077 }
2078 2078
2079 2079 static int
2080 2080 isnst_add_null_pg(isns_pdu_t *pdu, size_t pdu_size,
2081 2081 avl_tree_t *null_portal_list)
2082 2082 {
2083 2083 isns_portal_t *iportal;
2084 2084
2085 2085 /* If all portals accounted for, no NULL PG needed */
2086 2086 if (avl_numnodes(null_portal_list) == 0) {
2087 2087 return (0);
2088 2088 }
2089 2089
2090 2090 /* NULL Portal Group Tag means no access via these portals. */
2091 2091 if (isnst_add_attr(pdu, pdu_size,
2092 2092 ISNS_PG_TAG_ATTR_ID, 0, 0, 0) != 0) {
2093 2093 return (1);
2094 2094 }
2095 2095
2096 2096 for (iportal = avl_first(null_portal_list);
2097 2097 iportal != NULL;
2098 2098 iportal = AVL_NEXT(null_portal_list, iportal)) {
2099 2099 if (isnst_add_portal_attr(pdu, pdu_size,
2100 2100 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID,
2101 2101 ISNS_PG_PORTAL_PORT_ATTR_ID,
2102 2102 &iportal->portal_addr, B_FALSE) != 0) {
2103 2103 return (1);
2104 2104 }
2105 2105 }
2106 2106
2107 2107 return (0);
2108 2108 }
2109 2109
2110 2110 static int
2111 2111 isnst_add_portal_attr(isns_pdu_t *pdu, size_t pdu_size,
2112 2112 uint32_t ip_attr_id, uint32_t port_attr_id,
2113 2113 struct sockaddr_storage *ss, boolean_t esi_info)
2114 2114 {
2115 2115 struct sockaddr_in *in;
2116 2116 struct sockaddr_in6 *in6;
2117 2117 uint32_t attr_numeric_data;
2118 2118 void *inaddrp;
2119 2119
2120 2120 in = (struct sockaddr_in *)ss;
2121 2121 in6 = (struct sockaddr_in6 *)ss;
2122 2122
2123 2123 ASSERT((ss->ss_family == AF_INET) || (ss->ss_family == AF_INET6));
2124 2124
2125 2125 if (ss->ss_family == AF_INET) {
2126 2126 attr_numeric_data = sizeof (in_addr_t);
2127 2127 inaddrp = (void *)&in->sin_addr;
2128 2128 } else if (ss->ss_family == AF_INET6) {
2129 2129 attr_numeric_data = sizeof (in6_addr_t);
2130 2130 inaddrp = (void *)&in6->sin6_addr;
2131 2131 }
2132 2132
2133 2133 /* Portal Group Portal IP Address */
2134 2134 if (isnst_add_attr(pdu, pdu_size, ip_attr_id,
2135 2135 16, inaddrp, attr_numeric_data) != 0) {
2136 2136 return (1);
2137 2137 }
2138 2138
2139 2139 /* Portal Group Portal Port */
2140 2140 if (isnst_add_attr(pdu, pdu_size, port_attr_id,
2141 2141 4, 0, ntohs(in->sin_port)) != 0) {
2142 2142 return (1);
2143 2143 }
2144 2144
2145 2145 mutex_enter(&esi.esi_mutex);
2146 2146 if (esi_info && esi.esi_valid) {
2147 2147 /* ESI interval and port */
2148 2148 if (isnst_add_attr(pdu, pdu_size, ISNS_ESI_INTERVAL_ATTR_ID, 4,
2149 2149 NULL, isns_default_esi_interval) != 0) {
2150 2150 return (1);
2151 2151 }
2152 2152
2153 2153 if (isnst_add_attr(pdu, pdu_size, ISNS_ESI_PORT_ATTR_ID, 4,
2154 2154 NULL, esi.esi_port) != 0) {
2155 2155 return (1);
2156 2156 }
2157 2157 }
2158 2158 mutex_exit(&esi.esi_mutex);
2159 2159
2160 2160 return (0);
2161 2161 }
2162 2162
2163 2163 static int
2164 2164 isnst_deregister(iscsit_isns_svr_t *svr, isns_target_t *itarget)
2165 2165 {
2166 2166 int rc;
2167 2167 isns_pdu_t *pdu, *rsp;
2168 2168 size_t pdu_size, rsp_size;
2169 2169 struct sonode *so;
2170 2170
2171 2171 so = isnst_open_so(&svr->svr_sa);
2172 2172
2173 2173 if (so == NULL) {
2174 2174 return (-1);
2175 2175 }
2176 2176
2177 2177 pdu_size = isnst_make_dereg_pdu(svr, &pdu, itarget);
2178 2178 if (pdu_size == 0) {
2179 2179 isnst_close_so(so);
2180 2180 return (-1);
2181 2181 }
2182 2182
2183 2183 rc = isnst_send_pdu(so, pdu);
2184 2184 if (rc != 0) {
2185 2185 isnst_close_so(so);
2186 2186 kmem_free(pdu, pdu_size);
2187 2187 return (rc);
2188 2188 }
2189 2189
2190 2190 rsp_size = isnst_rcv_pdu(so, &rsp);
2191 2191 if (rsp_size == 0) {
2192 2192 isnst_close_so(so);
2193 2193 kmem_free(pdu, pdu_size);
2194 2194 return (-1);
2195 2195 }
2196 2196
2197 2197 rc = isnst_verify_rsp(svr, pdu, rsp, rsp_size);
2198 2198
2199 2199 isnst_close_so(so);
2200 2200 kmem_free(pdu, pdu_size);
2201 2201 kmem_free(rsp, rsp_size);
2202 2202
2203 2203 return (rc);
2204 2204 }
2205 2205
2206 2206 static int
2207 2207 isnst_keepalive(iscsit_isns_svr_t *svr)
2208 2208 {
2209 2209 int rc;
2210 2210 isns_pdu_t *pdu, *rsp;
2211 2211 size_t pdu_size, rsp_size;
2212 2212 struct sonode *so;
2213 2213
2214 2214 so = isnst_open_so(&svr->svr_sa);
2215 2215
2216 2216 if (so == NULL) {
2217 2217 return (-1);
2218 2218 }
2219 2219
2220 2220 pdu_size = isnst_make_keepalive_pdu(svr, &pdu);
2221 2221 if (pdu_size == 0) {
2222 2222 isnst_close_so(so);
2223 2223 return (-1);
2224 2224 }
2225 2225
2226 2226 rc = isnst_send_pdu(so, pdu);
2227 2227 if (rc != 0) {
2228 2228 isnst_close_so(so);
2229 2229 kmem_free(pdu, pdu_size);
2230 2230 return (rc);
2231 2231 }
2232 2232
2233 2233 rsp_size = isnst_rcv_pdu(so, &rsp);
2234 2234 if (rsp_size == 0) {
2235 2235 isnst_close_so(so);
2236 2236 kmem_free(pdu, pdu_size);
2237 2237 return (-1);
2238 2238 }
2239 2239
2240 2240 rc = isnst_verify_rsp(svr, pdu, rsp, rsp_size);
2241 2241
2242 2242 isnst_close_so(so);
2243 2243 kmem_free(pdu, pdu_size);
2244 2244 kmem_free(rsp, rsp_size);
2245 2245
2246 2246 return (rc);
2247 2247 }
2248 2248
2249 2249 static size_t
2250 2250 isnst_make_dereg_pdu(iscsit_isns_svr_t *svr, isns_pdu_t **pdu,
2251 2251 isns_target_t *itarget)
2252 2252 {
2253 2253 size_t pdu_size;
2254 2254 int len;
2255 2255 isns_target_t *src;
2256 2256
2257 2257 /*
2258 2258 * create DevDereg Message with all of target nodes
2259 2259 */
2260 2260 pdu_size = isnst_create_pdu_header(ISNS_DEV_DEREG, pdu, 0);
2261 2261 if (pdu_size == 0) {
2262 2262 return (0);
2263 2263 }
2264 2264
2265 2265 /*
2266 2266 * Source attribute - Must be a storage node in the same
2267 2267 * network entity.
2268 2268 */
2269 2269 if (svr->svr_registered) {
2270 2270 src = isnst_get_registered_source(svr);
2271 2271 } else if (itarget != NULL) {
2272 2272 src = itarget;
2273 2273 } else {
2274 2274 goto dereg_pdu_error;
2275 2275 }
2276 2276
2277 2277 len = strlen(src->target_info->ti_tgt_name) + 1;
2278 2278 if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID,
2279 2279 len, src->target_info->ti_tgt_name, 0) != 0) {
2280 2280 goto dereg_pdu_error;
2281 2281 }
2282 2282
2283 2283
2284 2284 /* Delimiter */
2285 2285 if (isnst_add_attr(*pdu, pdu_size, ISNS_DELIMITER_ATTR_ID,
2286 2286 0, 0, 0) != 0) {
2287 2287 goto dereg_pdu_error;
2288 2288 }
2289 2289
2290 2290 /*
2291 2291 * Operating attributes
2292 2292 */
2293 2293 if (itarget == NULL) {
2294 2294 /* dereg everything */
2295 2295 len = strlen(isns_eid) + 1;
2296 2296 if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID,
2297 2297 len, isns_eid, 0) != 0) {
2298 2298 goto dereg_pdu_error;
2299 2299 }
2300 2300 } else {
2301 2301 /* dereg one target only */
2302 2302 len = strlen(itarget->target_info->ti_tgt_name) + 1;
2303 2303 if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID,
2304 2304 len, itarget->target_info->ti_tgt_name, 0) != 0) {
2305 2305 goto dereg_pdu_error;
2306 2306 }
2307 2307 }
2308 2308
2309 2309 return (pdu_size);
2310 2310
2311 2311 dereg_pdu_error:
2312 2312 kmem_free(*pdu, pdu_size);
2313 2313 *pdu = NULL;
2314 2314
2315 2315 return (0);
2316 2316 }
2317 2317
2318 2318 static size_t
2319 2319 isnst_make_keepalive_pdu(iscsit_isns_svr_t *svr, isns_pdu_t **pdu)
2320 2320 {
2321 2321 size_t pdu_size;
2322 2322 int len;
2323 2323 isns_target_t *src;
2324 2324
2325 2325 ASSERT(svr->svr_registered);
2326 2326
2327 2327 /*
2328 2328 * create DevAttrQuery Message
2329 2329 */
2330 2330 pdu_size = isnst_create_pdu_header(ISNS_DEV_ATTR_QRY, pdu, 0);
2331 2331 if (pdu_size == 0) {
2332 2332 return (0);
2333 2333 }
2334 2334
2335 2335 /*
2336 2336 * Source attribute - Must be a iscsi target in the same
2337 2337 * network entity.
2338 2338 */
2339 2339 src = isnst_get_registered_source(svr);
2340 2340
2341 2341 len = strlen(src->target_info->ti_tgt_name) + 1;
2342 2342 if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID,
2343 2343 len, src->target_info->ti_tgt_name, 0) != 0) {
2344 2344 goto keepalive_pdu_error;
2345 2345 }
2346 2346
2347 2347 /* EID */
2348 2348 len = strlen(isns_eid) + 1;
2349 2349 if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID,
2350 2350 len, isns_eid, 0) != 0) {
2351 2351 goto keepalive_pdu_error;
2352 2352 }
2353 2353 /* Delimiter */
2354 2354 if (isnst_add_attr(*pdu, pdu_size, ISNS_DELIMITER_ATTR_ID,
2355 2355 0, 0, 0) != 0) {
2356 2356 goto keepalive_pdu_error;
2357 2357 }
2358 2358
2359 2359 /* Values to Fetch -- EID */
2360 2360 if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID,
2361 2361 0, 0, 0) != 0) {
2362 2362 goto keepalive_pdu_error;
2363 2363 }
2364 2364
2365 2365
2366 2366 return (pdu_size);
2367 2367
2368 2368 keepalive_pdu_error:
2369 2369 kmem_free(*pdu, pdu_size);
2370 2370 *pdu = NULL;
2371 2371
2372 2372 return (0);
2373 2373 }
2374 2374
2375 2375 static isns_target_t *
2376 2376 isnst_get_registered_source(iscsit_isns_svr_t *svr)
2377 2377 {
2378 2378 isns_target_t *itarget;
2379 2379
2380 2380 /*
2381 2381 * If svr is registered, then there must be at least one
2382 2382 * target that is registered to that svr.
2383 2383 */
2384 2384 ISNS_GLOBAL_LOCK();
2385 2385 ASSERT(svr->svr_monitor_hold);
2386 2386 itarget = isnst_get_registered_source_locked(svr);
2387 2387 ISNS_GLOBAL_UNLOCK();
2388 2388 return (itarget);
2389 2389 }
2390 2390
2391 2391 static isns_target_t *
2392 2392 isnst_get_registered_source_locked(iscsit_isns_svr_t *svr)
2393 2393 {
2394 2394 isns_target_t *itarget;
2395 2395
2396 2396 ASSERT(ISNS_GLOBAL_LOCK_HELD());
2397 2397 ASSERT(svr->svr_registered);
2398 2398 ASSERT((avl_numnodes(&svr->svr_target_list) != 0));
2399 2399
2400 2400 itarget = avl_first(&svr->svr_target_list);
2401 2401 do {
2402 2402 if (itarget->target_registered == B_TRUE)
2403 2403 break;
2404 2404 itarget = AVL_NEXT(&svr->svr_target_list, itarget);
2405 2405 } while (itarget != NULL);
2406 2406 ASSERT(itarget != NULL);
2407 2407 return (itarget);
2408 2408 }
2409 2409
2410 2410 static int
2411 2411 isnst_verify_rsp(iscsit_isns_svr_t *svr, isns_pdu_t *pdu,
2412 2412 isns_pdu_t *rsp, size_t rsp_size)
2413 2413 {
2414 2414 uint16_t func_id;
2415 2415 int payload_len, rsp_payload_len;
2416 2416 int status;
2417 2417 isns_resp_t *resp;
2418 2418 uint8_t *pp;
2419 2419 isns_tlv_t *attr;
2420 2420 uint32_t attr_len, attr_id, esi_interval;
2421 2421
2422 2422 /*
2423 2423 * Ensure we have at least a valid header (don't count the
2424 2424 * "payload" field.
2425 2425 */
2426 2426 if (rsp_size < offsetof(isns_pdu_t, payload)) {
2427 2427 ISNST_LOG(CE_WARN, "Invalid iSNS PDU header, %d of %d bytes",
2428 2428 (int)rsp_size, (int)offsetof(isns_pdu_t, payload));
2429 2429 return (-1);
2430 2430 }
2431 2431
2432 2432 /* Make sure we have the amount of data that the header specifies */
2433 2433 payload_len = ntohs(rsp->payload_len);
2434 2434 if (rsp_size < (payload_len + offsetof(isns_pdu_t, payload))) {
2435 2435 ISNST_LOG(CE_WARN, "Invalid iSNS response, %d of %d bytes",
2436 2436 (int)rsp_size,
2437 2437 (int)(payload_len + offsetof(isns_pdu_t, payload)));
2438 2438 return (-1);
2439 2439 }
2440 2440
2441 2441 /* Find the start of all operational parameters */
2442 2442 rsp_payload_len = isnst_pdu_get_op(rsp, &pp);
2443 2443 /*
2444 2444 * Make sure isnst_pdu_get_op didn't encounter an error
2445 2445 * in the attributes.
2446 2446 */
2447 2447 if (pp == NULL) {
2448 2448 return (-1);
2449 2449 }
2450 2450
2451 2451 /* verify response transaction id */
2452 2452 if (ntohs(rsp->xid) != ntohs(pdu->xid)) {
2453 2453 return (-1);
2454 2454 }
2455 2455
2456 2456 /* check the error code */
2457 2457 resp = (isns_resp_t *)((void *)&rsp->payload[0]);
2458 2458
2459 2459 status = ntohl(resp->status);
2460 2460
2461 2461 /* validate response function id */
2462 2462 func_id = ntohs(rsp->func_id);
2463 2463 switch (ntohs(pdu->func_id)) {
2464 2464 case ISNS_DEV_ATTR_REG:
2465 2465 if (func_id != ISNS_DEV_ATTR_REG_RSP) {
2466 2466 return (-1);
2467 2467 }
2468 2468
2469 2469 /* Only look through response if msg status says OK */
2470 2470 if (status != 0) {
2471 2471 break;
2472 2472 }
2473 2473 /*
2474 2474 * Get the ESI interval returned by the server. It could
2475 2475 * be different than what we asked for. We never know which
2476 2476 * portal a request may come in on, and any server could demand
2477 2477 * any interval. We'll simply keep track of the largest
2478 2478 * interval for use in monitoring.
2479 2479 */
2480 2480
2481 2481 attr = (isns_tlv_t *)((void *)pp);
2482 2482 while (rsp_payload_len >= 8) {
2483 2483 attr_len = ntohl(attr->attr_len);
2484 2484 attr_id = ntohl(attr->attr_id);
2485 2485 if (attr_id == ISNS_ESI_INTERVAL_ATTR_ID) {
2486 2486 if (attr_len != 4 ||
2487 2487 attr_len > rsp_payload_len - 8) {
2488 2488 /* Mal-formed packet */
2489 2489 return (-1);
2490 2490 }
2491 2491 esi_interval =
2492 2492 ntohl(*((uint32_t *)
2493 2493 ((void *)(&attr->attr_value))));
2494 2494
2495 2495 ISNS_GLOBAL_LOCK();
2496 2496 ASSERT(svr->svr_monitor_hold);
2497 2497 if (esi_interval > svr->svr_esi_interval)
2498 2498 svr->svr_esi_interval = esi_interval;
2499 2499 ISNS_GLOBAL_UNLOCK();
2500 2500
2501 2501 break;
2502 2502 }
2503 2503 rsp_payload_len -= (8 + attr_len);
2504 2504 attr = (isns_tlv_t *)
2505 2505 ((void *)((uint8_t *)attr + attr_len + 8));
2506 2506 }
2507 2507
2508 2508 break;
2509 2509 case ISNS_DEV_DEREG:
2510 2510 if (func_id != ISNS_DEV_DEREG_RSP) {
2511 2511 return (-1);
2512 2512 }
2513 2513 break;
2514 2514 case ISNS_DEV_ATTR_QRY:
2515 2515 /* Keepalive Response */
2516 2516 if (func_id != ISNS_DEV_ATTR_QRY_RSP) {
2517 2517 return (-1);
2518 2518 }
2519 2519
2520 2520 if (status == 0) {
2521 2521 boolean_t found_eid = B_FALSE;
2522 2522
2523 2523 /* Scan the operational parameters */
2524 2524 attr = (isns_tlv_t *)((void *)pp);
2525 2525 while (rsp_payload_len >= 8) {
2526 2526 attr_len = ntohl(attr->attr_len);
2527 2527 attr_id = ntohl(attr->attr_id);
2528 2528 if (attr_id == ISNS_EID_ATTR_ID &&
2529 2529 attr_len > 0 &&
2530 2530 attr_len <= rsp_payload_len - 8) {
2531 2531 /*
2532 2532 * If the isns server knows us, the
2533 2533 * response will include our EID in
2534 2534 * the operational parameters, i.e.
2535 2535 * after the delimiter.
2536 2536 * Just receiving this pattern
2537 2537 * is good enough to tell the isns
2538 2538 * server still knows us.
2539 2539 */
2540 2540 found_eid = B_TRUE;
2541 2541 break;
2542 2542 }
2543 2543
2544 2544 rsp_payload_len -= (8 + attr_len);
2545 2545 attr = (isns_tlv_t *)
2546 2546 ((void *)((uint8_t *)attr + attr_len + 8));
2547 2547 }
2548 2548 if (! found_eid) {
2549 2549 status = ISNS_RSP_NO_SUCH_ENTRY;
2550 2550 }
2551 2551 }
2552 2552 if (status == ISNS_RSP_NO_SUCH_ENTRY) {
2553 2553 char server_buf[IDM_SA_NTOP_BUFSIZ];
2554 2554 /*
2555 2555 * The iSNS server has forgotten about us.
2556 2556 * We will re-register everything.
2557 2557 * This can happen e.g. if ESI probes time out,
2558 2558 * or if the iSNS server does a factory reset.
2559 2559 */
2560 2560 ISNST_LOG(CE_WARN, "iscsit: iSNS server %s"
2561 2561 " forgot about us and has to be reminded.",
2562 2562 idm_sa_ntop(&svr->svr_sa,
2563 2563 server_buf, sizeof (server_buf)));
2564 2564 /* isnst_retry_registration will trigger the reset */
2565 2565 }
2566 2566
2567 2567 break;
2568 2568
2569 2569 default:
2570 2570 ASSERT(0);
2571 2571 break;
2572 2572 }
2573 2573
2574 2574 /* Update the last time we heard from this server */
2575 2575 if (status == 0) {
2576 2576 ISNS_GLOBAL_LOCK();
2577 2577 ASSERT(svr->svr_monitor_hold);
2578 2578 svr->svr_last_msg = ddi_get_lbolt();
2579 2579 ISNS_GLOBAL_UNLOCK();
2580 2580 }
2581 2581
2582 2582
2583 2583
2584 2584 return (status);
2585 2585 }
2586 2586
2587 2587 static uint16_t
2588 2588 isnst_pdu_get_op(isns_pdu_t *pdu, uint8_t **pp)
2589 2589 {
2590 2590 uint8_t *payload;
2591 2591 uint16_t payload_len;
2592 2592 isns_resp_t *resp;
2593 2593 isns_tlv_t *attr;
2594 2594 uint32_t attr_id;
2595 2595 uint32_t tlv_len;
2596 2596
2597 2597 /* get payload */
2598 2598 payload_len = ntohs(pdu->payload_len);
2599 2599 resp = (isns_resp_t *)((void *)&pdu->payload[0]);
2600 2600
2601 2601 /* find the operating attributes */
2602 2602 if (payload_len < sizeof (resp->status)) {
2603 2603 ISNST_LOG(CE_WARN, "Invalid iSNS response, %d payload bytes",
2604 2604 payload_len);
2605 2605 *pp = NULL;
2606 2606 return (0);
2607 2607 }
2608 2608
2609 2609 payload_len -= sizeof (resp->status);
2610 2610 payload = &resp->data[0];
2611 2611
2612 2612 while (payload_len >= (sizeof (isns_tlv_t) - 1)) {
2613 2613 attr = (isns_tlv_t *)((void *)payload);
2614 2614 tlv_len = offsetof(isns_tlv_t, attr_value) +
2615 2615 ntohl(attr->attr_len);
2616 2616 if (payload_len >= tlv_len) {
2617 2617 payload += tlv_len;
2618 2618 payload_len -= tlv_len;
2619 2619 attr_id = ntohl(attr->attr_id);
2620 2620 if (attr_id == ISNS_DELIMITER_ATTR_ID) {
2621 2621 break;
2622 2622 }
2623 2623 } else {
2624 2624 /* mal-formed packet */
2625 2625 payload = NULL;
2626 2626 payload_len = 0;
2627 2627 }
2628 2628 }
2629 2629
2630 2630 *pp = payload;
2631 2631
2632 2632 return (payload_len);
2633 2633 }
2634 2634
2635 2635 static size_t
2636 2636 isnst_create_pdu_header(uint16_t func_id, isns_pdu_t **pdu, uint16_t flags)
2637 2637 {
2638 2638 size_t pdu_size = isns_message_buf_size;
2639 2639
2640 2640 *pdu = (isns_pdu_t *)kmem_zalloc(pdu_size, KM_NOSLEEP);
2641 2641 if (*pdu != NULL) {
2642 2642 (*pdu)->version = htons((uint16_t)ISNSP_VERSION);
2643 2643 (*pdu)->func_id = htons((uint16_t)func_id);
2644 2644 (*pdu)->payload_len = htons(0);
2645 2645 (*pdu)->flags = htons(flags);
2646 2646
2647 2647 (*pdu)->xid = htons(GET_XID());
2648 2648 (*pdu)->seq = htons(0);
2649 2649 } else {
2650 2650 pdu_size = 0;
2651 2651 }
2652 2652
2653 2653 return (pdu_size);
2654 2654 }
2655 2655
2656 2656 static int
2657 2657 isnst_add_attr(isns_pdu_t *pdu,
2658 2658 size_t max_pdu_size,
2659 2659 uint32_t attr_id,
2660 2660 uint32_t attr_len,
2661 2661 void *attr_data,
2662 2662 uint32_t attr_numeric_data)
2663 2663 {
2664 2664 isns_tlv_t *attr_tlv;
2665 2665 uint8_t *payload_ptr;
2666 2666 uint16_t payload_len;
2667 2667 uint32_t normalized_attr_len;
2668 2668 uint64_t attr_tlv_len;
2669 2669
2670 2670 /* The attribute length must be 4-byte aligned. Section 5.1.3. */
2671 2671 normalized_attr_len = (attr_len % 4) == 0 ?
2672 2672 (attr_len) : (attr_len + (4 - (attr_len % 4)));
2673 2673 attr_tlv_len = ISNS_TLV_ATTR_ID_LEN +
2674 2674 ISNS_TLV_ATTR_LEN_LEN + normalized_attr_len;
2675 2675
2676 2676 /* Check if we are going to exceed the maximum PDU length. */
2677 2677 payload_len = ntohs(pdu->payload_len);
2678 2678 if ((payload_len + attr_tlv_len) > max_pdu_size) {
2679 2679 return (1);
2680 2680 }
2681 2681
2682 2682 attr_tlv = (isns_tlv_t *)kmem_zalloc(attr_tlv_len, KM_SLEEP);
2683 2683
2684 2684 attr_tlv->attr_id = htonl(attr_id);
2685 2685
2686 2686 switch (attr_id) {
2687 2687 case ISNS_DELIMITER_ATTR_ID:
2688 2688 break;
2689 2689
2690 2690 case ISNS_PORTAL_IP_ADDR_ATTR_ID:
2691 2691 case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID:
2692 2692 if (attr_numeric_data == sizeof (in_addr_t)) {
2693 2693 /* IPv4 */
2694 2694 attr_tlv->attr_value[10] = 0xFF;
2695 2695 attr_tlv->attr_value[11] = 0xFF;
2696 2696 bcopy(attr_data, ((attr_tlv->attr_value) + 12),
2697 2697 sizeof (in_addr_t));
2698 2698 } else if (attr_numeric_data == sizeof (in6_addr_t)) {
2699 2699 /* IPv6 */
2700 2700 bcopy(attr_data, attr_tlv->attr_value,
2701 2701 sizeof (in6_addr_t));
2702 2702 } else if (attr_numeric_data == 0) {
2703 2703 /* EMPTY */
2704 2704 /* Do nothing */
2705 2705 } else {
2706 2706 kmem_free(attr_tlv, attr_tlv_len);
2707 2707 attr_tlv = NULL;
2708 2708 return (1);
2709 2709 }
2710 2710 break;
2711 2711
2712 2712 case ISNS_EID_ATTR_ID:
2713 2713 case ISNS_ISCSI_NAME_ATTR_ID:
2714 2714 case ISNS_ISCSI_ALIAS_ATTR_ID:
2715 2715 case ISNS_PG_ISCSI_NAME_ATTR_ID:
2716 2716 if (attr_len && attr_data) {
2717 2717 bcopy((char *)attr_data,
2718 2718 attr_tlv->attr_value, attr_len);
2719 2719 }
2720 2720 break;
2721 2721
2722 2722 default:
2723 2723 if (attr_len == 8) {
2724 2724 *(uint64_t *)((void *)attr_tlv->attr_value) =
2725 2725 BE_64((uint64_t)attr_numeric_data);
2726 2726 } else if (attr_len == 4) {
2727 2727 *(uint32_t *)((void *)attr_tlv->attr_value) =
2728 2728 htonl((uint32_t)attr_numeric_data);
2729 2729 }
2730 2730 break;
2731 2731 }
2732 2732
2733 2733 attr_tlv->attr_len = htonl(normalized_attr_len);
2734 2734 /*
2735 2735 * Convert the network byte ordered payload length to host byte
2736 2736 * ordered for local address calculation.
2737 2737 */
2738 2738 payload_len = ntohs(pdu->payload_len);
2739 2739 payload_ptr = pdu->payload + payload_len;
2740 2740 bcopy(attr_tlv, payload_ptr, attr_tlv_len);
2741 2741 payload_len += attr_tlv_len;
2742 2742
2743 2743 /*
2744 2744 * Convert the host byte ordered payload length back to network
2745 2745 * byte ordered - it's now ready to be sent on the wire.
2746 2746 */
2747 2747 pdu->payload_len = htons(payload_len);
2748 2748
2749 2749 kmem_free(attr_tlv, attr_tlv_len);
2750 2750 attr_tlv = NULL;
2751 2751
2752 2752 return (0);
2753 2753 }
2754 2754
2755 2755 static void
2756 2756 isnst_so_timeout(void *so)
2757 2757 {
2758 2758 /* Wake up any sosend or sorecv blocked on this socket */
2759 2759 idm_soshutdown(so);
2760 2760 }
2761 2761
2762 2762 static int
2763 2763 isnst_send_pdu(void *so, isns_pdu_t *pdu)
2764 2764 {
2765 2765 size_t total_len, payload_len, send_len;
2766 2766 uint8_t *payload;
2767 2767 uint16_t flags, seq;
2768 2768 timeout_id_t send_timer;
2769 2769 iovec_t iov[2];
2770 2770 int rc;
2771 2771
2772 2772 ASSERT(! ISNS_GLOBAL_LOCK_HELD());
2773 2773
2774 2774 /* update pdu flags */
2775 2775 flags = ntohs(pdu->flags);
2776 2776 flags |= ISNS_FLAG_CLIENT;
2777 2777 flags |= ISNS_FLAG_FIRST_PDU;
2778 2778
2779 2779 /* initalize sequence number */
2780 2780 seq = 0;
2781 2781
2782 2782 payload = pdu->payload;
2783 2783
2784 2784 /* total payload length */
2785 2785 total_len = ntohs(pdu->payload_len);
2786 2786
2787 2787 /* fill in the pdu header */
2788 2788 iov[0].iov_base = (void *)pdu;
2789 2789 iov[0].iov_len = ISNSP_HEADER_SIZE;
2790 2790
2791 2791 do {
2792 2792 /* split the payload accordingly */
2793 2793 if (total_len > ISNSP_MAX_PAYLOAD_SIZE) {
2794 2794 payload_len = ISNSP_MAX_PAYLOAD_SIZE;
2795 2795 } else {
2796 2796 payload_len = total_len;
2797 2797 /* set the last pdu flag */
2798 2798 flags |= ISNS_FLAG_LAST_PDU;
2799 2799 }
2800 2800
2801 2801 /* set back the pdu flags */
2802 2802 pdu->flags = htons(flags);
2803 2803 /* set the sequence number */
2804 2804 pdu->seq = htons(seq);
2805 2805 /* set the payload length */
2806 2806 pdu->payload_len = htons(payload_len);
2807 2807
2808 2808 /* fill in the payload */
2809 2809 iov[1].iov_base = (void *)payload;
2810 2810 iov[1].iov_len = payload_len;
2811 2811
2812 2812 DTRACE_PROBE3(isnst__pdu__send, uint16_t, ntohs(pdu->func_id),
2813 2813 uint16_t, ntohs(pdu->payload_len), caddr_t, pdu);
2814 2814
2815 2815 /* send the pdu */
2816 2816 send_len = ISNSP_HEADER_SIZE + payload_len;
2817 2817 send_timer = timeout(isnst_so_timeout, so,
2818 2818 drv_usectohz(isns_timeout_usec));
2819 2819 rc = idm_iov_sosend(so, &iov[0], 2, send_len);
2820 2820 (void) untimeout(send_timer);
2821 2821
2822 2822 flags &= ~ISNS_FLAG_FIRST_PDU;
2823 2823 payload += payload_len;
2824 2824 total_len -= payload_len;
2825 2825
2826 2826 /* increase the sequence number */
2827 2827 seq ++;
2828 2828
2829 2829 } while (rc == 0 && total_len > 0);
2830 2830
2831 2831 return (rc);
2832 2832 }
2833 2833
2834 2834 static size_t
2835 2835 isnst_rcv_pdu(void *so, isns_pdu_t **pdu)
2836 2836 {
2837 2837 size_t total_pdu_len;
2838 2838 size_t total_payload_len;
2839 2839 size_t payload_len;
2840 2840 size_t combined_len;
2841 2841 isns_pdu_t tmp_pdu_hdr;
2842 2842 isns_pdu_t *combined_pdu;
2843 2843 uint8_t *payload;
2844 2844 uint8_t *combined_payload;
2845 2845 timeout_id_t rcv_timer;
2846 2846 uint16_t flags;
2847 2847 uint16_t seq;
2848 2848
2849 2849 ASSERT(! ISNS_GLOBAL_LOCK_HELD());
2850 2850
2851 2851 *pdu = NULL;
2852 2852 total_pdu_len = total_payload_len = 0;
2853 2853 payload = NULL;
2854 2854 seq = 0;
2855 2855
2856 2856 do {
2857 2857 /* receive the pdu header */
2858 2858 rcv_timer = timeout(isnst_so_timeout, so,
2859 2859 drv_usectohz(isns_timeout_usec));
2860 2860 if (idm_sorecv(so, &tmp_pdu_hdr, ISNSP_HEADER_SIZE) != 0 ||
2861 2861 ntohs(tmp_pdu_hdr.seq) != seq) {
2862 2862 (void) untimeout(rcv_timer);
2863 2863 goto rcv_error;
2864 2864 }
2865 2865 (void) untimeout(rcv_timer);
2866 2866
↓ open down ↓ |
1775 lines elided |
↑ open up ↑ |
2867 2867 /* receive the payload */
2868 2868 payload_len = ntohs(tmp_pdu_hdr.payload_len);
2869 2869 if (payload_len > ISNST_MAX_MSG_SIZE) {
2870 2870 goto rcv_error;
2871 2871 }
2872 2872 payload = kmem_alloc(payload_len, KM_NOSLEEP);
2873 2873 if (payload == NULL) {
2874 2874 goto rcv_error;
2875 2875 }
2876 2876 rcv_timer = timeout(isnst_so_timeout, so,
2877 - drv_usectohz(ISNS_RCV_TIMER_SECONDS * 1000000));
2877 + drv_sectohz(ISNS_RCV_TIMER_SECONDS));
2878 2878 if (idm_sorecv(so, payload, payload_len) != 0) {
2879 2879 (void) untimeout(rcv_timer);
2880 2880 goto rcv_error;
2881 2881 }
2882 2882 (void) untimeout(rcv_timer);
2883 2883
2884 2884 /* combine the pdu if it is not the first one */
2885 2885 if (total_pdu_len > 0) {
2886 2886 combined_len = total_pdu_len + payload_len;
2887 2887 combined_pdu = kmem_alloc(combined_len, KM_SLEEP);
2888 2888 if (combined_pdu == NULL) {
2889 2889 goto rcv_error;
2890 2890 }
2891 2891 bcopy(*pdu, combined_pdu, total_pdu_len);
2892 2892 combined_payload =
2893 2893 &combined_pdu->payload[total_payload_len];
2894 2894 bcopy(payload, combined_payload, payload_len);
2895 2895 kmem_free(*pdu, total_pdu_len);
2896 2896 kmem_free(payload, payload_len);
2897 2897 *pdu = combined_pdu;
2898 2898 total_payload_len += payload_len;
2899 2899 total_pdu_len += payload_len;
2900 2900 (*pdu)->payload_len = htons(total_payload_len);
2901 2901 } else {
2902 2902 total_payload_len = payload_len;
2903 2903 total_pdu_len = ISNSP_HEADER_SIZE + payload_len;
2904 2904 *pdu = kmem_alloc(total_pdu_len, KM_NOSLEEP);
2905 2905 if (*pdu == NULL) {
2906 2906 goto rcv_error;
2907 2907 }
2908 2908 bcopy(&tmp_pdu_hdr, *pdu, ISNSP_HEADER_SIZE);
2909 2909 bcopy(payload, &(*pdu)->payload[0], payload_len);
2910 2910 kmem_free(payload, payload_len);
2911 2911 }
2912 2912 payload = NULL;
2913 2913
2914 2914 /* the flags of pdu which is just received */
2915 2915 flags = ntohs(tmp_pdu_hdr.flags);
2916 2916
2917 2917 /* increase sequence number by one */
2918 2918 seq ++;
2919 2919 } while ((flags & ISNS_FLAG_LAST_PDU) == 0);
2920 2920
2921 2921 DTRACE_PROBE3(isnst__pdu__recv, uint16_t, ntohs((*pdu)->func_id),
2922 2922 size_t, total_payload_len, caddr_t, *pdu);
2923 2923
2924 2924 return (total_pdu_len);
2925 2925
2926 2926 rcv_error:
2927 2927 if (*pdu != NULL) {
2928 2928 kmem_free(*pdu, total_pdu_len);
2929 2929 *pdu = NULL;
2930 2930 }
2931 2931 if (payload != NULL) {
2932 2932 kmem_free(payload, payload_len);
2933 2933 }
2934 2934 return (0);
2935 2935 }
2936 2936
2937 2937 static void *
2938 2938 isnst_open_so(struct sockaddr_storage *sa)
2939 2939 {
2940 2940 int sa_sz;
2941 2941 ksocket_t so;
2942 2942
2943 2943 ASSERT(! ISNS_GLOBAL_LOCK_HELD());
2944 2944
2945 2945 /* determine local IP address */
2946 2946 if (sa->ss_family == AF_INET) {
2947 2947 /* IPv4 */
2948 2948 sa_sz = sizeof (struct sockaddr_in);
2949 2949
2950 2950 /* Create socket */
2951 2951 so = idm_socreate(AF_INET, SOCK_STREAM, 0);
2952 2952 } else {
2953 2953 /* IPv6 */
2954 2954 sa_sz = sizeof (struct sockaddr_in6);
2955 2955
2956 2956 /* Create socket */
2957 2957 so = idm_socreate(AF_INET6, SOCK_STREAM, 0);
2958 2958 }
2959 2959
2960 2960 if (so != NULL) {
2961 2961 if (idm_so_timed_socket_connect(so, sa, sa_sz,
2962 2962 isns_timeout_usec) != 0) {
2963 2963 /* not calling isnst_close_so() to */
2964 2964 /* make dtrace output look clear */
2965 2965 idm_soshutdown(so);
2966 2966 idm_sodestroy(so);
2967 2967 so = NULL;
2968 2968 }
2969 2969 }
2970 2970
2971 2971 if (so == NULL) {
2972 2972 char server_buf[IDM_SA_NTOP_BUFSIZ];
2973 2973 ISNST_LOG(CE_WARN, "open iSNS Server %s failed",
2974 2974 idm_sa_ntop(sa, server_buf,
2975 2975 sizeof (server_buf)));
2976 2976 DTRACE_PROBE1(isnst__connect__fail,
2977 2977 struct sockaddr_storage *, sa);
2978 2978 }
2979 2979
2980 2980 return (so);
2981 2981 }
2982 2982
2983 2983 static void
2984 2984 isnst_close_so(void *so)
2985 2985 {
2986 2986 idm_soshutdown(so);
2987 2987 idm_sodestroy(so);
2988 2988 }
2989 2989
2990 2990 /*
2991 2991 * ESI handling
2992 2992 */
2993 2993
2994 2994 static void
2995 2995 isnst_esi_start(void)
2996 2996 {
2997 2997 if (isns_use_esi == B_FALSE) {
2998 2998 ISNST_LOG(CE_NOTE, "ESI disabled by isns_use_esi=FALSE");
2999 2999 return;
3000 3000 }
3001 3001
3002 3002 ISNST_LOG(CE_NOTE, "isnst_esi_start");
3003 3003
3004 3004 mutex_enter(&esi.esi_mutex);
3005 3005 ASSERT(esi.esi_enabled == B_FALSE);
3006 3006 ASSERT(esi.esi_thread_running == B_FALSE);
3007 3007
3008 3008 esi.esi_enabled = B_TRUE;
3009 3009 esi.esi_valid = B_FALSE;
3010 3010 esi.esi_thread = thread_create(NULL, 0, isnst_esi_thread,
3011 3011 (void *)&esi, 0, &p0, TS_RUN, minclsyspri);
3012 3012
3013 3013 /*
3014 3014 * Wait for the thread to start
3015 3015 */
3016 3016 while (!esi.esi_thread_running) {
3017 3017 cv_wait(&esi.esi_cv, &esi.esi_mutex);
3018 3018 }
3019 3019 mutex_exit(&esi.esi_mutex);
3020 3020 }
3021 3021
3022 3022 static void
3023 3023 isnst_esi_stop()
3024 3024 {
3025 3025 boolean_t need_offline = B_FALSE;
3026 3026
3027 3027 ISNST_LOG(CE_NOTE, "isnst_esi_stop");
3028 3028
3029 3029 /* Shutdown ESI listening socket, wait for thread to terminate */
3030 3030 mutex_enter(&esi.esi_mutex);
3031 3031 if (esi.esi_enabled) {
3032 3032 esi.esi_enabled = B_FALSE;
3033 3033 if (esi.esi_valid) {
3034 3034 need_offline = B_TRUE;
3035 3035 }
3036 3036 mutex_exit(&esi.esi_mutex);
3037 3037 if (need_offline) {
3038 3038 idm_soshutdown(esi.esi_so);
3039 3039 idm_sodestroy(esi.esi_so);
3040 3040 }
3041 3041 thread_join(esi.esi_thread_did);
3042 3042 } else {
3043 3043 mutex_exit(&esi.esi_mutex);
3044 3044 }
3045 3045 }
3046 3046
3047 3047 /*
3048 3048 * isnst_esi_thread
3049 3049 *
3050 3050 * This function listens on a socket for incoming connections from an
3051 3051 * iSNS server until told to stop.
3052 3052 */
3053 3053
3054 3054 /*ARGSUSED*/
3055 3055 static void
3056 3056 isnst_esi_thread(void *arg)
3057 3057 {
3058 3058 ksocket_t newso;
3059 3059 struct sockaddr_in6 sin6;
3060 3060 socklen_t sin_addrlen;
3061 3061 uint32_t on = 1;
3062 3062 int rc;
3063 3063 isns_pdu_t *pdu;
3064 3064 size_t pl_size;
3065 3065
3066 3066 bzero(&sin6, sizeof (struct sockaddr_in6));
3067 3067 sin_addrlen = sizeof (struct sockaddr_in6);
3068 3068
3069 3069 esi.esi_thread_did = curthread->t_did;
3070 3070
3071 3071 mutex_enter(&esi.esi_mutex);
3072 3072
3073 3073 /*
3074 3074 * Mark the thread as running and the portal as no longer new.
3075 3075 */
3076 3076 esi.esi_thread_running = B_TRUE;
3077 3077 cv_signal(&esi.esi_cv);
↓ open down ↓ |
190 lines elided |
↑ open up ↑ |
3078 3078
3079 3079 while (esi.esi_enabled) {
3080 3080 /*
3081 3081 * Create a socket to listen for requests from the iSNS server.
3082 3082 */
3083 3083 if ((esi.esi_so = idm_socreate(PF_INET6, SOCK_STREAM, 0)) ==
3084 3084 NULL) {
3085 3085 ISNST_LOG(CE_WARN,
3086 3086 "isnst_esi_thread: Unable to create socket");
3087 3087 mutex_exit(&esi.esi_mutex);
3088 - delay(drv_usectohz(1000000));
3088 + delay(drv_sectohz(1));
3089 3089 mutex_enter(&esi.esi_mutex);
3090 3090 continue;
3091 3091 }
3092 3092
3093 3093 /*
3094 3094 * Set options, bind, and listen until we're told to stop
3095 3095 */
3096 3096 bzero(&sin6, sizeof (sin6));
3097 3097 sin6.sin6_family = AF_INET6;
3098 3098 sin6.sin6_port = htons(0);
3099 3099 sin6.sin6_addr = in6addr_any;
3100 3100
3101 3101 (void) ksocket_setsockopt(esi.esi_so, SOL_SOCKET,
3102 3102 SO_REUSEADDR, (char *)&on, sizeof (on), CRED());
3103 3103
3104 3104 if (ksocket_bind(esi.esi_so, (struct sockaddr *)&sin6,
3105 3105 sizeof (sin6), CRED()) != 0) {
3106 3106 ISNST_LOG(CE_WARN, "Unable to bind socket for ESI");
3107 3107 idm_sodestroy(esi.esi_so);
3108 3108 mutex_exit(&esi.esi_mutex);
3109 - delay(drv_usectohz(1000000));
3109 + delay(drv_sectohz(1));
3110 3110 mutex_enter(&esi.esi_mutex);
3111 3111 continue;
3112 3112 }
3113 3113
3114 3114 /*
3115 3115 * Get the port (sin6 is meaningless at this point)
3116 3116 */
3117 3117 (void) ksocket_getsockname(esi.esi_so,
3118 3118 (struct sockaddr *)(&sin6), &sin_addrlen, CRED());
3119 3119 esi.esi_port =
3120 3120 ntohs(((struct sockaddr_in6 *)(&sin6))->sin6_port);
3121 3121
3122 3122 if ((rc = ksocket_listen(esi.esi_so, 5, CRED())) != 0) {
3123 3123 ISNST_LOG(CE_WARN, "isnst_esi_thread: listen "
3124 3124 "failure 0x%x", rc);
3125 3125 idm_sodestroy(esi.esi_so);
3126 3126 mutex_exit(&esi.esi_mutex);
3127 - delay(drv_usectohz(1000000));
3127 + delay(drv_sectohz(1));
3128 3128 mutex_enter(&esi.esi_mutex);
3129 3129 continue;
3130 3130 }
3131 3131
3132 3132 ksocket_hold(esi.esi_so);
3133 3133 esi.esi_valid = B_TRUE;
3134 3134 while (esi.esi_enabled) {
3135 3135 mutex_exit(&esi.esi_mutex);
3136 3136
3137 3137 DTRACE_PROBE3(iscsit__isns__esi__accept__wait,
3138 3138 boolean_t, esi.esi_enabled,
3139 3139 ksocket_t, esi.esi_so,
3140 3140 struct sockaddr_in6, &sin6);
3141 3141 if ((rc = ksocket_accept(esi.esi_so, NULL, NULL,
3142 3142 &newso, CRED())) != 0) {
3143 3143 mutex_enter(&esi.esi_mutex);
3144 3144 DTRACE_PROBE2(iscsit__isns__esi__accept__fail,
3145 3145 int, rc, boolean_t, esi.esi_enabled);
3146 3146 /*
3147 3147 * If we were interrupted with EINTR
3148 3148 * it's not really a failure.
3149 3149 */
3150 3150 ISNST_LOG(CE_WARN, "isnst_esi_thread: "
3151 3151 "accept failure (0x%x)", rc);
3152 3152
3153 3153 if (rc == EINTR) {
3154 3154 continue;
3155 3155 } else {
3156 3156 break;
3157 3157 }
3158 3158 }
3159 3159 DTRACE_PROBE2(iscsit__isns__esi__accept,
3160 3160 boolean_t, esi.esi_enabled,
3161 3161 ksocket_t, newso);
3162 3162
3163 3163 pl_size = isnst_rcv_pdu(newso, &pdu);
3164 3164 if (pl_size == 0) {
3165 3165 ISNST_LOG(CE_WARN, "isnst_esi_thread: "
3166 3166 "rcv_pdu failure");
3167 3167 idm_soshutdown(newso);
3168 3168 idm_sodestroy(newso);
3169 3169
3170 3170 mutex_enter(&esi.esi_mutex);
3171 3171 continue;
3172 3172 }
3173 3173
3174 3174 isnst_handle_esi_req(newso, pdu, pl_size);
3175 3175
3176 3176 idm_soshutdown(newso);
3177 3177 idm_sodestroy(newso);
3178 3178
3179 3179 mutex_enter(&esi.esi_mutex);
3180 3180 }
3181 3181
3182 3182 idm_soshutdown(esi.esi_so);
3183 3183 ksocket_rele(esi.esi_so);
3184 3184 esi.esi_valid = B_FALSE;
3185 3185
3186 3186 /*
3187 3187 * If we're going to try to re-establish the listener then
3188 3188 * destroy this socket. Otherwise isnst_esi_stop already
3189 3189 * destroyed it.
3190 3190 */
3191 3191 if (esi.esi_enabled)
3192 3192 idm_sodestroy(esi.esi_so);
3193 3193 }
3194 3194
3195 3195 esi.esi_thread_running = B_FALSE;
3196 3196 cv_signal(&esi.esi_cv);
3197 3197 mutex_exit(&esi.esi_mutex);
3198 3198 esi_thread_exit:
3199 3199 thread_exit();
3200 3200 }
3201 3201
3202 3202 /*
3203 3203 * Handle an incoming ESI request
3204 3204 */
3205 3205
3206 3206 static void
3207 3207 isnst_handle_esi_req(ksocket_t ks, isns_pdu_t *pdu, size_t pdu_size)
3208 3208 {
3209 3209 isns_pdu_t *rsp_pdu;
3210 3210 isns_resp_t *rsp;
3211 3211 isns_tlv_t *attr;
3212 3212 uint32_t attr_len, attr_id;
3213 3213 size_t req_pl_len, rsp_size, tlv_len;
3214 3214 struct sockaddr_storage portal_ss;
3215 3215 struct sockaddr_storage server_ss;
3216 3216 struct sockaddr_in6 *portal_addr6;
3217 3217 boolean_t portal_addr_valid = B_FALSE;
3218 3218 boolean_t portal_port_valid = B_FALSE;
3219 3219 uint32_t esi_response = ISNS_RSP_SUCCESSFUL;
3220 3220 isns_portal_t *iportal;
3221 3221 socklen_t sa_len;
3222 3222
3223 3223
3224 3224 if (ntohs(pdu->func_id) != ISNS_ESI) {
3225 3225 ISNST_LOG(CE_WARN, "isnst_handle_esi_req: Unexpected func 0x%x",
3226 3226 pdu->func_id);
3227 3227 kmem_free(pdu, pdu_size);
3228 3228 return;
3229 3229 }
3230 3230
3231 3231 req_pl_len = ntohs(pdu->payload_len);
3232 3232 if (req_pl_len + offsetof(isns_pdu_t, payload) > pdu_size) {
3233 3233 ISNST_LOG(CE_WARN, "isnst_handle_esi_req: "
3234 3234 "payload exceeds PDU size (%d > %d)",
3235 3235 (int)(req_pl_len + offsetof(isns_pdu_t, payload)),
3236 3236 (int)pdu_size);
3237 3237 /* Not all data is present -- ignore */
3238 3238 kmem_free(pdu, pdu_size);
3239 3239 return;
3240 3240 }
3241 3241
3242 3242 if (req_pl_len + sizeof (uint32_t) > ISNSP_MAX_PAYLOAD_SIZE) {
3243 3243 ISNST_LOG(CE_WARN,
3244 3244 "isnst_handle_esi_req: PDU payload exceeds max (%ld bytes)",
3245 3245 req_pl_len + sizeof (uint32_t));
3246 3246 kmem_free(pdu, pdu_size);
3247 3247 return;
3248 3248 }
3249 3249
3250 3250 /*
3251 3251 * Check portal in ESI request and make sure it is valid. Return
3252 3252 * esi_response of ISNS_RSP_SUCCESSFUL if valid, otherwise don't
3253 3253 * respond at all. Get IP addr and port. Format of ESI
3254 3254 * is:
3255 3255 *
3256 3256 * ISNS_TIMESTAMP_ATTR_ID,
3257 3257 * ISNS_EID_ATTR_ID,
3258 3258 * ISNS_PORTAL_IP_ADDR_ATTR_ID,
3259 3259 * ISNS_PORTAL_PORT_ATTR_ID
3260 3260 */
3261 3261 bzero(&portal_ss, sizeof (struct sockaddr_storage));
3262 3262 portal_ss.ss_family = AF_INET6;
3263 3263 portal_addr6 = (struct sockaddr_in6 *)&portal_ss;
3264 3264 attr = (isns_tlv_t *)((void *)&pdu->payload);
3265 3265 attr_len = ntohl(attr->attr_len);
3266 3266 attr_id = ntohl(attr->attr_id);
3267 3267 tlv_len = attr_len + offsetof(isns_tlv_t, attr_value);
3268 3268 while (tlv_len <= req_pl_len) {
3269 3269 switch (attr_id) {
3270 3270 case ISNS_TIMESTAMP_ATTR_ID:
3271 3271 break;
3272 3272 case ISNS_EID_ATTR_ID:
3273 3273 break;
3274 3274 case ISNS_PORTAL_IP_ADDR_ATTR_ID:
3275 3275 if (attr_len > sizeof (struct in6_addr)) {
3276 3276 /* Bad attribute format */
3277 3277 esi_response = ISNS_RSP_MSG_FORMAT_ERROR;
3278 3278 } else {
3279 3279 portal_addr6->sin6_family = AF_INET6;
3280 3280 attr_len = min(attr_len,
3281 3281 sizeof (portal_addr6->sin6_addr));
3282 3282 bcopy(attr->attr_value,
3283 3283 portal_addr6->sin6_addr.s6_addr, attr_len);
3284 3284 portal_addr_valid = B_TRUE;
3285 3285 }
3286 3286 break;
3287 3287 case ISNS_PORTAL_PORT_ATTR_ID:
3288 3288 if (attr_len > sizeof (uint32_t)) {
3289 3289 /* Bad attribute format */
3290 3290 esi_response = ISNS_RSP_MSG_FORMAT_ERROR;
3291 3291 } else {
3292 3292 portal_addr6->sin6_port =
3293 3293 htons((uint16_t)BE_IN32(attr->attr_value));
3294 3294 portal_port_valid = B_TRUE;
3295 3295 }
3296 3296 break;
3297 3297 default:
3298 3298 /* Bad request format */
3299 3299 esi_response = ISNS_RSP_MSG_FORMAT_ERROR;
3300 3300 break;
3301 3301 }
3302 3302
3303 3303 /* If we've set an error then stop processing */
3304 3304 if (esi_response != ISNS_RSP_SUCCESSFUL) {
3305 3305 break;
3306 3306 }
3307 3307
3308 3308 /* Get next attribute */
3309 3309 req_pl_len -= tlv_len;
3310 3310 attr = (isns_tlv_t *)((void *)((uint8_t *)attr + tlv_len));
3311 3311 attr_len = ntohl(attr->attr_len);
3312 3312 attr_id = ntohl(attr->attr_id);
3313 3313 tlv_len = attr_len + offsetof(isns_tlv_t, attr_value);
3314 3314 }
3315 3315
3316 3316 if (!portal_port_valid)
3317 3317 portal_addr6->sin6_port = htons(ISCSI_LISTEN_PORT);
3318 3318
3319 3319 if (!portal_addr_valid) {
3320 3320 esi_response = ISNS_RSP_MSG_FORMAT_ERROR;
3321 3321 }
3322 3322
3323 3323 /*
3324 3324 * If we've detected an error or if the portal does not
3325 3325 * exist then drop the request. The server will eventually
3326 3326 * timeout the portal and eliminate it from the list.
3327 3327 */
3328 3328
3329 3329 if (esi_response != ISNS_RSP_SUCCESSFUL) {
3330 3330 kmem_free(pdu, pdu_size);
3331 3331 return;
3332 3332 }
3333 3333
3334 3334 /* Get the remote peer's IP address */
3335 3335 bzero(&server_ss, sizeof (server_ss));
3336 3336 sa_len = sizeof (server_ss);
3337 3337 if (ksocket_getpeername(ks, (struct sockaddr *)&server_ss, &sa_len,
3338 3338 CRED())) {
3339 3339 return;
3340 3340 }
3341 3341
3342 3342 if (iscsit_isns_logging) {
3343 3343 char server_buf[IDM_SA_NTOP_BUFSIZ];
3344 3344 char portal_buf[IDM_SA_NTOP_BUFSIZ];
3345 3345 ISNST_LOG(CE_NOTE, "ESI: svr %s -> portal %s",
3346 3346 idm_sa_ntop(&server_ss, server_buf,
3347 3347 sizeof (server_buf)),
3348 3348 idm_sa_ntop(&portal_ss, portal_buf,
3349 3349 sizeof (portal_buf)));
3350 3350 }
3351 3351
3352 3352
3353 3353 ISNS_GLOBAL_LOCK();
3354 3354 if (isnst_lookup_portal(&portal_ss) == NULL) {
3355 3355 ISNST_LOG(CE_WARN, "ESI req to non-active portal");
3356 3356 ISNS_GLOBAL_UNLOCK();
3357 3357 kmem_free(pdu, pdu_size);
3358 3358 return;
3359 3359 }
3360 3360
3361 3361 /*
3362 3362 * Update the server timestamp of how recently we have
3363 3363 * received an ESI request from this iSNS server.
3364 3364 * We ignore requests from servers we don't know.
3365 3365 */
3366 3366 if (! isnst_update_server_timestamp(&server_ss)) {
3367 3367 ISNST_LOG(CE_WARN, "ESI req from unknown server");
3368 3368 kmem_free(pdu, pdu_size);
3369 3369 ISNS_GLOBAL_UNLOCK();
3370 3370 return;
3371 3371 }
3372 3372
3373 3373 /*
3374 3374 * Update ESI timestamps for all portals with same IP address.
3375 3375 */
3376 3376 for (iportal = avl_first(&isns_all_portals);
3377 3377 iportal != NULL;
3378 3378 iportal = AVL_NEXT(&isns_all_portals, iportal)) {
3379 3379 if (idm_ss_compare(&iportal->portal_addr, &portal_ss,
3380 3380 B_TRUE, B_FALSE)) {
3381 3381 gethrestime(&iportal->portal_esi_timestamp);
3382 3382 }
3383 3383 }
3384 3384
3385 3385 ISNS_GLOBAL_UNLOCK();
3386 3386
3387 3387
3388 3388 /*
3389 3389 * Build response validating the portal
3390 3390 */
3391 3391 rsp_size = isnst_create_pdu_header(ISNS_ESI_RSP, &rsp_pdu, 0);
3392 3392
3393 3393 if (rsp_size == 0) {
3394 3394 ISNST_LOG(CE_WARN, "isnst_handle_esi_req: Can't get rsp pdu");
3395 3395 kmem_free(pdu, pdu_size);
3396 3396 return;
3397 3397 }
3398 3398
3399 3399 rsp = (isns_resp_t *)((void *)(&rsp_pdu->payload[0]));
3400 3400
3401 3401 /* Use xid from the request pdu */
3402 3402 rsp_pdu->xid = pdu->xid;
3403 3403 rsp->status = htonl(ISNS_RSP_SUCCESSFUL);
3404 3404
3405 3405 /* Copy original data */
3406 3406 req_pl_len = ntohs(pdu->payload_len);
3407 3407 bcopy(pdu->payload, rsp->data, req_pl_len);
3408 3408 rsp_pdu->payload_len = htons(req_pl_len + sizeof (uint32_t));
3409 3409
3410 3410 if (isnst_send_pdu(ks, rsp_pdu) != 0) {
3411 3411 ISNST_LOG(CE_WARN,
3412 3412 "isnst_handle_esi_req: Send response failed");
3413 3413 }
3414 3414
3415 3415 kmem_free(rsp_pdu, rsp_size);
3416 3416 kmem_free(pdu, pdu_size);
3417 3417
3418 3418 }
3419 3419
3420 3420 static int
3421 3421 isnst_tgt_avl_compare(const void *t1, const void *t2)
3422 3422 {
3423 3423 const isns_target_t *tgt1 = t1;
3424 3424 const isns_target_t *tgt2 = t2;
3425 3425
3426 3426 /*
3427 3427 * Sort by target (pointer to iscsit_tgt_t).
3428 3428 */
3429 3429
3430 3430 if (tgt1->target < tgt2->target) {
3431 3431 return (-1);
3432 3432 } else if (tgt1->target > tgt2->target) {
3433 3433 return (1);
3434 3434 }
3435 3435
3436 3436 return (0);
3437 3437 }
3438 3438
3439 3439 static void
3440 3440 isnst_set_server_status(iscsit_isns_svr_t *svr, boolean_t registered)
3441 3441 {
3442 3442 isns_target_t *itarget;
3443 3443
3444 3444 ASSERT(ISNS_GLOBAL_LOCK_HELD());
3445 3445
3446 3446 svr->svr_reset_needed = B_FALSE;
3447 3447 if (registered == B_TRUE) {
3448 3448 svr->svr_registered = B_TRUE;
3449 3449 svr->svr_last_msg = ddi_get_lbolt();
3450 3450 itarget = avl_first(&svr->svr_target_list);
3451 3451 while (itarget) {
3452 3452 isns_target_t *next_target;
3453 3453 next_target = AVL_NEXT(&svr->svr_target_list, itarget);
3454 3454 if (itarget->target_delete_needed) {
3455 3455 /* All deleted tgts removed */
3456 3456 isnst_clear_from_target_list(itarget,
3457 3457 &svr->svr_target_list);
3458 3458 } else {
3459 3459 /* Other tgts marked registered */
3460 3460 itarget->target_registered = B_TRUE;
3461 3461 /* No updates needed -- clean slate */
3462 3462 itarget->target_update_needed = B_FALSE;
3463 3463 }
3464 3464 itarget = next_target;
3465 3465 }
3466 3466 ASSERT(avl_numnodes(&svr->svr_target_list) > 0);
3467 3467 } else {
3468 3468 svr->svr_registered = B_FALSE;
3469 3469 isnst_clear_target_list(svr);
3470 3470 }
3471 3471 }
3472 3472
3473 3473 static void
3474 3474 isnst_monitor_default_portal_list(void)
3475 3475 {
3476 3476 idm_addr_list_t *new_portal_list = NULL;
3477 3477 uint32_t new_portal_list_size = 0;
3478 3478
3479 3479 ASSERT(ISNS_GLOBAL_LOCK_HELD());
3480 3480 ASSERT(mutex_owned(&iscsit_isns_mutex));
3481 3481
3482 3482 if (default_portal_online) {
3483 3483 new_portal_list_size = idm_get_ipaddr(&new_portal_list);
3484 3484 }
3485 3485
3486 3486 /*
3487 3487 * We compute a new list of portals if
3488 3488 * a) Something in itadm has changed a portal
3489 3489 * b) there are new default portals
3490 3490 * c) the default portal has gone offline
3491 3491 */
3492 3492 if (isns_portals_changed ||
3493 3493 ((new_portal_list_size != 0) &&
3494 3494 (isnst_find_default_portals(new_portal_list) !=
3495 3495 num_default_portals)) ||
3496 3496 ((new_portal_list_size == 0) && (num_default_portals > 0))) {
3497 3497
3498 3498 isnst_clear_default_portals();
3499 3499 isnst_copy_portal_list(&isns_tpg_portals,
3500 3500 &isns_all_portals);
3501 3501 num_tpg_portals = avl_numnodes(&isns_all_portals);
3502 3502 if (new_portal_list_size != 0) {
3503 3503 num_default_portals =
3504 3504 isnst_add_default_portals(new_portal_list);
3505 3505 }
3506 3506 }
3507 3507
3508 3508 /* Catch any case where we miss an update to TPG portals */
3509 3509 ASSERT(num_tpg_portals == avl_numnodes(&isns_tpg_portals));
3510 3510
3511 3511 if (new_portal_list != NULL) {
3512 3512 kmem_free(new_portal_list, new_portal_list_size);
3513 3513 }
3514 3514 }
3515 3515
3516 3516
3517 3517 static int
3518 3518 isnst_find_default_portals(idm_addr_list_t *alist)
3519 3519 {
3520 3520 idm_addr_t *dportal;
3521 3521 isns_portal_t *iportal;
3522 3522 struct sockaddr_storage sa;
3523 3523 int aidx;
3524 3524 int num_portals_found = 0;
3525 3525
3526 3526 for (aidx = 0; aidx < alist->al_out_cnt; aidx++) {
3527 3527 dportal = &alist->al_addrs[aidx];
3528 3528 dportal->a_port = ISCSI_LISTEN_PORT;
3529 3529 idm_addr_to_sa(dportal, &sa);
3530 3530 iportal = isnst_lookup_portal(&sa);
3531 3531 if (iportal == NULL) {
3532 3532 /* Found a non-matching default portal */
3533 3533 return (-1);
3534 3534 }
3535 3535 if (iportal->portal_default) {
3536 3536 num_portals_found++;
3537 3537 }
3538 3538 }
3539 3539 return (num_portals_found);
3540 3540 }
3541 3541
3542 3542 static void
3543 3543 isnst_clear_default_portals(void)
3544 3544 {
3545 3545 ASSERT(ISNS_GLOBAL_LOCK_HELD());
3546 3546
3547 3547 isnst_clear_portal_list(&isns_all_portals);
3548 3548 num_tpg_portals = 0;
3549 3549 num_default_portals = 0;
3550 3550 }
3551 3551
3552 3552 static int
3553 3553 isnst_add_default_portals(idm_addr_list_t *alist)
3554 3554 {
3555 3555 idm_addr_t *dportal;
3556 3556 isns_portal_t *iportal;
3557 3557 struct sockaddr_storage sa;
3558 3558 int aidx;
3559 3559
3560 3560 for (aidx = 0; aidx < alist->al_out_cnt; aidx++) {
3561 3561 dportal = &alist->al_addrs[aidx];
3562 3562 dportal->a_port = ISCSI_LISTEN_PORT;
3563 3563 idm_addr_to_sa(dportal, &sa);
3564 3564 iportal = isnst_add_to_portal_list(&sa, &isns_all_portals);
3565 3565 iportal->portal_default = B_TRUE;
3566 3566 }
3567 3567 return (alist->al_out_cnt);
3568 3568 }
3569 3569
3570 3570
3571 3571 static int
3572 3572 isnst_portal_avl_compare(const void *p1, const void *p2)
3573 3573 {
3574 3574 const isns_portal_t *portal1 = p1;
3575 3575 const isns_portal_t *portal2 = p2;
3576 3576
3577 3577 return (idm_ss_compare(&portal1->portal_addr, &portal2->portal_addr,
3578 3578 B_TRUE /* v4_mapped_as_v4 */, B_TRUE /* compare_ports */));
3579 3579 }
3580 3580
3581 3581 static void
3582 3582 isnst_clear_portal_list(avl_tree_t *portal_list)
3583 3583 {
3584 3584 isns_portal_t *iportal;
3585 3585 void *cookie = NULL;
3586 3586
3587 3587 while ((iportal = avl_destroy_nodes(portal_list, &cookie)) != NULL) {
3588 3588 kmem_free(iportal, sizeof (isns_portal_t));
3589 3589 }
3590 3590 }
3591 3591 static void
3592 3592 isnst_copy_portal_list(avl_tree_t *t1, avl_tree_t *t2)
3593 3593 {
3594 3594 isns_portal_t *iportal, *jportal;
3595 3595
3596 3596 iportal = (isns_portal_t *)avl_first(t1);
3597 3597 while (iportal) {
3598 3598 jportal = isnst_add_to_portal_list(&iportal->portal_addr, t2);
3599 3599 jportal->portal_iscsit = iportal->portal_iscsit;
3600 3600 iportal = AVL_NEXT(t1, iportal);
3601 3601 }
3602 3602 }
3603 3603
3604 3604
3605 3605 static isns_portal_t *
3606 3606 isnst_lookup_portal(struct sockaddr_storage *sa)
3607 3607 {
3608 3608 isns_portal_t *iportal, tmp_portal;
3609 3609 ASSERT(ISNS_GLOBAL_LOCK_HELD());
3610 3610
3611 3611 bcopy(sa, &tmp_portal.portal_addr, sizeof (*sa));
3612 3612 iportal = avl_find(&isns_all_portals, &tmp_portal, NULL);
3613 3613 return (iportal);
3614 3614 }
3615 3615
3616 3616 static isns_portal_t *
3617 3617 isnst_add_to_portal_list(struct sockaddr_storage *sa, avl_tree_t *portal_list)
3618 3618 {
3619 3619 isns_portal_t *iportal, tmp_portal;
3620 3620 avl_index_t where;
3621 3621 /*
3622 3622 * Make sure this portal isn't already in our list.
3623 3623 */
3624 3624
3625 3625 bcopy(sa, &tmp_portal.portal_addr, sizeof (*sa));
3626 3626
3627 3627 if ((iportal = (isns_portal_t *)avl_find(portal_list,
3628 3628 &tmp_portal, &where)) == NULL) {
3629 3629 iportal = kmem_zalloc(sizeof (isns_portal_t), KM_SLEEP);
3630 3630 bcopy(sa, &iportal->portal_addr, sizeof (*sa));
3631 3631 avl_insert(portal_list, (void *)iportal, where);
3632 3632 }
3633 3633
3634 3634 return (iportal);
3635 3635 }
3636 3636
3637 3637
3638 3638 static void
3639 3639 isnst_remove_from_portal_list(struct sockaddr_storage *sa,
3640 3640 avl_tree_t *portal_list)
3641 3641 {
3642 3642 isns_portal_t *iportal, tmp_portal;
3643 3643
3644 3644 bcopy(sa, &tmp_portal.portal_addr, sizeof (*sa));
3645 3645
3646 3646 if ((iportal = avl_find(portal_list, &tmp_portal, NULL))
3647 3647 != NULL) {
3648 3648 avl_remove(portal_list, iportal);
3649 3649 kmem_free(iportal, sizeof (isns_portal_t));
3650 3650 }
3651 3651 }
3652 3652
3653 3653 /*
3654 3654 * These functions are called by iscsit proper when a portal comes online
3655 3655 * or goes offline.
3656 3656 */
3657 3657
3658 3658 void
3659 3659 iscsit_isns_portal_online(iscsit_portal_t *portal)
3660 3660 {
3661 3661 isns_portal_t *iportal;
3662 3662
3663 3663 mutex_enter(&iscsit_isns_mutex);
3664 3664
3665 3665 if (portal->portal_default) {
3666 3666 /* Portals should only be onlined once */
3667 3667 ASSERT(default_portal_online == B_FALSE);
3668 3668 default_portal_online = B_TRUE;
3669 3669 } else {
3670 3670 iportal = isnst_add_to_portal_list(
3671 3671 &portal->portal_addr, &isns_tpg_portals);
3672 3672 iportal->portal_iscsit = portal;
3673 3673 }
3674 3674 isns_portals_changed = B_TRUE;
3675 3675
3676 3676 mutex_exit(&iscsit_isns_mutex);
3677 3677
3678 3678 isnst_monitor_awaken();
3679 3679 }
3680 3680
3681 3681 void
3682 3682 iscsit_isns_portal_offline(iscsit_portal_t *portal)
3683 3683 {
3684 3684 mutex_enter(&iscsit_isns_mutex);
3685 3685
3686 3686 if (portal->portal_default) {
3687 3687 /* Portals should only be offlined once */
3688 3688 ASSERT(default_portal_online == B_TRUE);
3689 3689 default_portal_online = B_FALSE;
3690 3690 } else {
3691 3691 isnst_remove_from_portal_list(&portal->portal_addr,
3692 3692 &isns_tpg_portals);
3693 3693 }
3694 3694 isns_portals_changed = B_TRUE;
3695 3695
3696 3696 mutex_exit(&iscsit_isns_mutex);
3697 3697
3698 3698 isnst_monitor_awaken();
3699 3699 }
↓ open down ↓ |
562 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX