Print this page
9702 HBA drivers don't need the redundant devfs_clean step
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_lun.c
+++ new/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_lun.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
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
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 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 24 * Use is subject to license terms.
24 25 *
26 + */
27 +
28 +/*
29 + * Copyright 2018 Nexenta Systems, Inc.
30 + */
31 +
32 +/*
25 33 * iSCSI logical unit interfaces
26 34 */
27 35
28 36 #include "iscsi.h"
29 -#include <sys/fs/dv_node.h> /* devfs_clean */
30 37 #include <sys/bootprops.h>
31 38 #include <sys/sysevent/eventdefs.h>
32 39 #include <sys/sysevent/dev.h>
33 40
34 41 /* tpgt bytes in string form */
35 42 #define TPGT_EXT_SIZE 5
36 43
37 44 /* logical unit number bytes in string form */
38 45 #define LUN_EXT_SIZE 10
39 46
40 47 /*
41 48 * Addition addr size of size of ',' + max str form of tpgt (2 bytes) +
42 49 * ',' + max str form of logical unit number (4 bytes).
43 50 */
44 51 #define ADDR_EXT_SIZE (1 + TPGT_EXT_SIZE + 1 + LUN_EXT_SIZE)
45 52
46 53 /* internal interfaces */
47 54 static iscsi_status_t iscsi_lun_virt_create(iscsi_sess_t *isp,
48 55 uint16_t lun_num, iscsi_lun_t *ilp, struct scsi_inquiry *inq);
49 56 static iscsi_status_t iscsi_lun_phys_create(iscsi_sess_t *isp,
50 57 uint16_t lun_num, iscsi_lun_t *ilp, struct scsi_inquiry *inq);
51 58
52 59 extern dev_info_t *scsi_vhci_dip;
53 60 extern ib_boot_prop_t *iscsiboot_prop;
54 61
55 62 /*
56 63 * +--------------------------------------------------------------------+
57 64 * | External Connection Interfaces |
58 65 * +--------------------------------------------------------------------+
59 66 */
60 67
61 68
62 69 /*
63 70 * iscsi_lun_create - This function will create a lun mapping.
64 71 * logic specific to MPxIO vs. NDI node creation is switched
65 72 * out to a helper function.
66 73 */
67 74 iscsi_status_t
68 75 iscsi_lun_create(iscsi_sess_t *isp, uint16_t lun_num, uint8_t lun_addr_type,
69 76 struct scsi_inquiry *inq, char *guid)
70 77 {
71 78 iscsi_status_t rtn = ISCSI_STATUS_INTERNAL_ERROR;
72 79 iscsi_hba_t *ihp = NULL;
73 80 iscsi_lun_t *ilp = NULL;
74 81 iscsi_lun_t *ilp_tmp = NULL;
75 82 char *addr = NULL;
76 83 uint16_t boot_lun_num = 0;
77 84 uint64_t *lun_num_ptr = NULL;
78 85 uint32_t oid_tmp = 0;
79 86
80 87 ASSERT(isp != NULL);
81 88 ihp = isp->sess_hba;
82 89 ASSERT(ihp != NULL);
83 90
84 91 mutex_enter(&iscsi_oid_mutex);
85 92 oid_tmp = iscsi_oid++;
86 93 mutex_exit(&iscsi_oid_mutex);
87 94
88 95 rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
89 96 /*
90 97 * Check whether it has already existed in the list.
91 98 */
92 99 for (ilp_tmp = isp->sess_lun_list; ilp_tmp != NULL;
93 100 ilp_tmp = ilp_tmp->lun_next) {
94 101 if (ilp_tmp->lun_num == lun_num) {
95 102 /*
96 103 * The logic unit has already existed in the list,
97 104 * return with success.
98 105 */
99 106 rw_exit(&isp->sess_lun_list_rwlock);
100 107 return (ISCSI_STATUS_SUCCESS);
101 108 }
102 109 }
103 110
104 111 addr = kmem_zalloc((strlen((char *)isp->sess_name) +
105 112 ADDR_EXT_SIZE + 1), KM_SLEEP);
106 113 (void) snprintf(addr,
107 114 (strlen((char *)isp->sess_name) +
108 115 ADDR_EXT_SIZE + 1),
109 116 "%02X%02X%s%04X,%d", isp->sess_isid[4],
110 117 isp->sess_isid[5], isp->sess_name,
111 118 isp->sess_tpgt_nego & 0xFFFF, lun_num);
112 119
113 120 /* allocate space for lun struct */
114 121 ilp = kmem_zalloc(sizeof (iscsi_lun_t), KM_SLEEP);
115 122 ilp->lun_sig = ISCSI_SIG_LUN;
116 123 ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
117 124 ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
118 125
119 126 /* initialize common LU information */
120 127 ilp->lun_num = lun_num;
121 128 ilp->lun_addr_type = lun_addr_type;
122 129 ilp->lun_sess = isp;
123 130 ilp->lun_addr = addr;
124 131 ilp->lun_type = inq->inq_dtype & DTYPE_MASK;
125 132 ilp->lun_oid = oid_tmp;
126 133
127 134 bcopy(inq->inq_vid, ilp->lun_vid, sizeof (inq->inq_vid));
128 135 bcopy(inq->inq_pid, ilp->lun_pid, sizeof (inq->inq_pid));
129 136
130 137 /* store GUID if valid one exists */
131 138 if (guid != NULL) {
132 139 ilp->lun_guid_size = strlen(guid) + 1;
133 140 ilp->lun_guid = kmem_zalloc(ilp->lun_guid_size, KM_SLEEP);
134 141 (void) strcpy(ilp->lun_guid, guid);
135 142 } else {
136 143 ilp->lun_guid_size = 0;
137 144 ilp->lun_guid = NULL;
138 145 }
139 146
140 147 /*
141 148 * We need to add the lun to our lists now because during the
142 149 * lun creation we will get called back into multiple times
143 150 * depending on the createion type. These callbacks will
144 151 * occur via our tran_init_lun, tran_get_name, tran_get_bus_addr,
145 152 * tran_init_pkt, tran_start.
146 153 */
147 154 if (isp->sess_lun_list == NULL) {
148 155 isp->sess_lun_list = ilp;
149 156 } else {
150 157 ilp->lun_next = isp->sess_lun_list;
151 158 isp->sess_lun_list = ilp;
152 159 }
153 160
154 161 /* Attempt to create a scsi_vhci binding if GUID is available */
155 162 if ((ihp->hba_mpxio_enabled == B_TRUE) &&
156 163 (guid != NULL)) {
157 164 rtn = iscsi_lun_virt_create(isp, lun_num, ilp, inq);
158 165 }
159 166 if (!ISCSI_SUCCESS(rtn)) {
160 167 /* unable to bind under scsi_vhci, failback to ndi */
161 168 rtn = iscsi_lun_phys_create(isp, lun_num, ilp, inq);
162 169 }
163 170
164 171 /*
165 172 * If NOT successful we need to remove the lun from the
166 173 * session and free any related resources.
167 174 */
168 175 if (!ISCSI_SUCCESS(rtn)) {
169 176 if (ilp == isp->sess_lun_list) {
170 177 /* if head, set head to our next */
171 178 isp->sess_lun_list = ilp->lun_next;
172 179 } else {
173 180 /* if not head, set prev lun's next to our next */
174 181 for (ilp_tmp = isp->sess_lun_list; ilp_tmp;
175 182 ilp_tmp = ilp_tmp->lun_next) {
176 183 if (ilp_tmp->lun_next == ilp) {
177 184 ilp_tmp->lun_next = ilp->lun_next;
178 185 break;
179 186 }
180 187 }
181 188 }
182 189
183 190 kmem_free(ilp->lun_addr,
184 191 (strlen((char *)isp->sess_name) +
185 192 ADDR_EXT_SIZE + 1));
186 193 ilp->lun_addr = NULL;
187 194
188 195 if (ilp->lun_guid != NULL) {
189 196 kmem_free(ilp->lun_guid, ilp->lun_guid_size);
190 197 ilp->lun_guid = NULL;
191 198 }
192 199 kmem_free(ilp, sizeof (iscsi_lun_t));
193 200 } else {
194 201 ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
195 202 ilp->lun_state |= ISCSI_LUN_STATE_ONLINE;
196 203 ilp->lun_time_online = ddi_get_time();
197 204
198 205 /* Check whether this is the required LUN for iscsi boot */
199 206 if (iscsiboot_prop != NULL && isp->sess_boot == B_TRUE &&
200 207 iscsiboot_prop->boot_tgt.lun_online == 0) {
201 208 lun_num_ptr =
202 209 (uint64_t *)iscsiboot_prop->boot_tgt.tgt_boot_lun;
203 210 boot_lun_num = (uint16_t)(*lun_num_ptr);
204 211 if (boot_lun_num == ilp->lun_num) {
205 212 /*
206 213 * During iscsi boot, the boot lun has been
207 214 * online, we should set the "online flag".
208 215 */
209 216 iscsiboot_prop->boot_tgt.lun_online = 1;
210 217 }
211 218 }
212 219 }
213 220 rw_exit(&isp->sess_lun_list_rwlock);
214 221
215 222 return (rtn);
216 223 }
217 224
218 225 /*
219 226 * iscsi_lun_destroy - offline and remove lun
220 227 *
221 228 * This interface is called when a name service change has
222 229 * occured and the storage is no longer available to this
223 230 * initiator. This function will offline and free the
224 231 * solaris node resources. Then it will free all iscsi lun
225 232 * resources.
226 233 *
227 234 * This function can fail with ISCSI_STATUS_BUSY if the
228 235 * logical unit is in use. The user should unmount or
229 236 * close the device and perform the nameservice operation
230 237 * again if this occurs.
231 238 */
232 239 iscsi_status_t
233 240 iscsi_lun_destroy(iscsi_hba_t *ihp, iscsi_lun_t *ilp)
234 241 {
235 242 iscsi_status_t status = ISCSI_STATUS_SUCCESS;
236 243 iscsi_sess_t *isp = NULL;
237 244 iscsi_lun_t *t_ilp = NULL;
238 245
239 246 ASSERT(ilp != NULL);
240 247 isp = ilp->lun_sess;
241 248 ASSERT(isp != NULL);
242 249
243 250 /* attempt to offline and free solaris node */
244 251 status = iscsi_lun_offline(ihp, ilp, B_TRUE);
245 252
246 253 /* If we successfully unplumbed the lun remove it from our lists */
247 254 if (ISCSI_SUCCESS(status)) {
248 255 if (isp->sess_lun_list == ilp) {
249 256 /* target first item in list */
250 257 isp->sess_lun_list = ilp->lun_next;
251 258 } else {
252 259 /*
253 260 * search session list for ilp pointing
254 261 * to lun being removed. Then
255 262 * update that luns next pointer.
256 263 */
257 264 t_ilp = isp->sess_lun_list;
258 265 while (t_ilp->lun_next != NULL) {
259 266 if (t_ilp->lun_next == ilp) {
260 267 break;
261 268 }
262 269 t_ilp = t_ilp->lun_next;
263 270 }
264 271 if (t_ilp->lun_next == ilp) {
265 272 t_ilp->lun_next = ilp->lun_next;
266 273 } else {
267 274 /* couldn't find session */
268 275 ASSERT(FALSE);
269 276 }
270 277 }
271 278
272 279 /* release its memory */
273 280 kmem_free(ilp->lun_addr, (strlen((char *)isp->sess_name) +
274 281 ADDR_EXT_SIZE + 1));
275 282 ilp->lun_addr = NULL;
276 283 if (ilp->lun_guid != NULL) {
277 284 kmem_free(ilp->lun_guid, ilp->lun_guid_size);
278 285 ilp->lun_guid = NULL;
279 286 }
280 287 kmem_free(ilp, sizeof (iscsi_lun_t));
281 288 ilp = NULL;
282 289 }
283 290
284 291 return (status);
285 292 }
286 293
287 294 /*
288 295 * +--------------------------------------------------------------------+
289 296 * | External Logical Unit Interfaces |
290 297 * +--------------------------------------------------------------------+
291 298 */
292 299
293 300 /*
294 301 * iscsi_lun_virt_create - Creates solaris logical unit via MDI
295 302 */
296 303 static iscsi_status_t
297 304 iscsi_lun_virt_create(iscsi_sess_t *isp, uint16_t lun_num, iscsi_lun_t *ilp,
298 305 struct scsi_inquiry *inq)
299 306 {
300 307 iscsi_status_t rtn = ISCSI_STATUS_INTERNAL_ERROR;
301 308 int mdi_rtn = MDI_FAILURE;
302 309 iscsi_hba_t *ihp = NULL;
303 310 mdi_pathinfo_t *pip = NULL;
304 311 char *nodename = NULL;
305 312 char **compatible = NULL;
306 313 int ncompatible = 0;
307 314 int circ = 0;
308 315
309 316 ASSERT(isp != NULL);
310 317 ASSERT(ilp != NULL);
311 318 ihp = isp->sess_hba;
312 319 ASSERT(ihp != NULL);
313 320
314 321 /*
315 322 * Generate compatible property
316 323 */
317 324 scsi_hba_nodename_compatible_get(inq, "vhci",
318 325 inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
319 326
320 327 /* if nodename can't be determined then print a message and skip it */
321 328 if (nodename == NULL) {
322 329 cmn_err(CE_WARN, "iscsi driver found no compatible driver "
323 330 "for %s lun %d dtype:0x%02x", isp->sess_name, lun_num,
324 331 inq->inq_dtype);
325 332 return (ISCSI_STATUS_INTERNAL_ERROR);
326 333 }
327 334
328 335 /*
329 336 *
330 337 */
331 338 ndi_devi_enter(scsi_vhci_dip, &circ);
332 339 mdi_rtn = mdi_pi_alloc_compatible(ihp->hba_dip, nodename,
333 340 ilp->lun_guid, ilp->lun_addr, compatible, ncompatible,
334 341 0, &pip);
335 342
336 343 if (mdi_rtn == MDI_SUCCESS) {
337 344 mdi_pi_set_phci_private(pip, (caddr_t)ilp);
338 345
339 346 if (mdi_prop_update_string(pip, MDI_GUID,
340 347 ilp->lun_guid) != DDI_SUCCESS) {
341 348 cmn_err(CE_WARN, "iscsi driver unable to create "
342 349 "property for %s lun %d (MDI_GUID)",
343 350 isp->sess_name, lun_num);
344 351 mdi_rtn = MDI_FAILURE;
345 352 goto virt_create_done;
346 353 }
347 354
348 355 if (mdi_prop_update_int(pip, TARGET_PROP,
349 356 isp->sess_oid) != DDI_SUCCESS) {
350 357 cmn_err(CE_WARN, "iscsi driver unable to create "
351 358 "property for %s lun %d (TARGET_PROP)",
352 359 isp->sess_name, lun_num);
353 360 mdi_rtn = MDI_FAILURE;
354 361 goto virt_create_done;
355 362 }
356 363
357 364 if (mdi_prop_update_int(pip, LUN_PROP,
358 365 ilp->lun_num) != DDI_SUCCESS) {
359 366 cmn_err(CE_WARN, "iscsi driver unable to create "
360 367 "property for %s lun %d (LUN_PROP)",
361 368 isp->sess_name, lun_num);
362 369 mdi_rtn = MDI_FAILURE;
363 370 goto virt_create_done;
364 371 }
365 372
366 373 if (mdi_prop_update_string_array(pip, "compatible",
367 374 compatible, ncompatible) !=
368 375 DDI_PROP_SUCCESS) {
369 376 cmn_err(CE_WARN, "iscsi driver unable to create "
370 377 "property for %s lun %d (COMPATIBLE)",
371 378 isp->sess_name, lun_num);
372 379 mdi_rtn = MDI_FAILURE;
373 380 goto virt_create_done;
374 381 }
375 382
376 383 mdi_rtn = mdi_pi_online(pip, 0);
377 384 if (mdi_rtn == MDI_NOT_SUPPORTED) {
378 385 mdi_rtn = MDI_FAILURE;
379 386 goto virt_create_done;
380 387 }
381 388
382 389 ilp->lun_pip = pip;
383 390 ilp->lun_dip = NULL;
384 391
385 392 virt_create_done:
386 393
387 394 if (pip && mdi_rtn != MDI_SUCCESS) {
388 395 ilp->lun_pip = NULL;
389 396 ilp->lun_dip = NULL;
390 397 (void) mdi_prop_remove(pip, NULL);
391 398 (void) mdi_pi_free(pip, 0);
392 399 } else {
393 400 rtn = ISCSI_STATUS_SUCCESS;
394 401 }
395 402 }
396 403 ndi_devi_exit(scsi_vhci_dip, circ);
397 404
398 405 scsi_hba_nodename_compatible_free(nodename, compatible);
399 406
400 407 return (rtn);
401 408 }
402 409
403 410
404 411 /*
405 412 * iscsi_lun_phys_create - creates solaris logical unit via NDI
406 413 */
407 414 static iscsi_status_t
408 415 iscsi_lun_phys_create(iscsi_sess_t *isp, uint16_t lun_num,
409 416 iscsi_lun_t *ilp, struct scsi_inquiry *inq)
410 417 {
411 418 iscsi_status_t rtn = ISCSI_STATUS_INTERNAL_ERROR;
412 419 int ndi_rtn = NDI_FAILURE;
413 420 iscsi_hba_t *ihp = NULL;
414 421 dev_info_t *lun_dip = NULL;
415 422 char *nodename = NULL;
416 423 char **compatible = NULL;
417 424 int ncompatible = 0;
418 425 char *scsi_binding_set = NULL;
419 426 char instance[32];
420 427 int circ = 0;
421 428
422 429 ASSERT(isp != NULL);
423 430 ASSERT(ilp != NULL);
424 431 ihp = isp->sess_hba;
425 432 ASSERT(ihp != NULL);
426 433 ASSERT(inq != NULL);
427 434
428 435 /* get the 'scsi-binding-set' property */
429 436 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, isp->sess_hba->hba_dip,
430 437 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
431 438 &scsi_binding_set) != DDI_PROP_SUCCESS) {
432 439 scsi_binding_set = NULL;
433 440 }
434 441
435 442 /* generate compatible property */
436 443 scsi_hba_nodename_compatible_get(inq, scsi_binding_set,
437 444 inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
438 445 if (scsi_binding_set)
439 446 ddi_prop_free(scsi_binding_set);
440 447
441 448 /* if nodename can't be determined then print a message and skip it */
442 449 if (nodename == NULL) {
443 450 cmn_err(CE_WARN, "iscsi driver found no compatible driver "
444 451 "for %s lun %d", isp->sess_name, lun_num);
445 452 return (ISCSI_STATUS_INTERNAL_ERROR);
446 453 }
447 454
448 455 ndi_devi_enter(ihp->hba_dip, &circ);
449 456
450 457 ndi_rtn = ndi_devi_alloc(ihp->hba_dip, nodename,
451 458 DEVI_SID_NODEID, &lun_dip);
452 459
453 460 /* if lun alloc success, set props */
454 461 if (ndi_rtn == NDI_SUCCESS) {
455 462
456 463 if (ndi_prop_update_int(DDI_DEV_T_NONE,
457 464 lun_dip, TARGET_PROP, (int)isp->sess_oid) !=
458 465 DDI_PROP_SUCCESS) {
459 466 cmn_err(CE_WARN, "iscsi driver unable to create "
460 467 "property for %s lun %d (TARGET_PROP)",
461 468 isp->sess_name, lun_num);
462 469 ndi_rtn = NDI_FAILURE;
463 470 goto phys_create_done;
464 471 }
465 472
466 473 if (ndi_prop_update_int(DDI_DEV_T_NONE,
467 474 lun_dip, LUN_PROP, (int)ilp->lun_num) !=
468 475 DDI_PROP_SUCCESS) {
469 476 cmn_err(CE_WARN, "iscsi driver unable to create "
470 477 "property for %s lun %d (LUN_PROP)",
471 478 isp->sess_name, lun_num);
472 479 ndi_rtn = NDI_FAILURE;
473 480 goto phys_create_done;
474 481 }
475 482
476 483 if (ndi_prop_update_string_array(DDI_DEV_T_NONE,
477 484 lun_dip, "compatible", compatible, ncompatible)
478 485 != DDI_PROP_SUCCESS) {
479 486 cmn_err(CE_WARN, "iscsi driver unable to create "
480 487 "property for %s lun %d (COMPATIBLE)",
481 488 isp->sess_name, lun_num);
482 489 ndi_rtn = NDI_FAILURE;
483 490 goto phys_create_done;
484 491 }
485 492
486 493 phys_create_done:
487 494 /* If props were setup ok, online the lun */
488 495 if (ndi_rtn == NDI_SUCCESS) {
489 496 /* Try to online the new node */
490 497 ndi_rtn = ndi_devi_online(lun_dip, 0);
491 498 }
492 499
493 500 /* If success set rtn flag, else unwire alloc'd lun */
494 501 if (ndi_rtn == NDI_SUCCESS) {
495 502 rtn = ISCSI_STATUS_SUCCESS;
496 503 /*
497 504 * Assign the instance number for the dev_link
498 505 * generator. This will ensure the link name is
499 506 * unique and persistent across reboots.
500 507 */
501 508 (void) snprintf(instance, 32, "%d",
502 509 ddi_get_instance(lun_dip));
503 510 (void) ndi_prop_update_string(DDI_DEV_T_NONE,
504 511 lun_dip, NDI_GUID, instance);
505 512 } else {
506 513 cmn_err(CE_WARN, "iscsi driver unable to online "
507 514 "%s lun %d", isp->sess_name, lun_num);
508 515 ndi_prop_remove_all(lun_dip);
509 516 (void) ndi_devi_free(lun_dip);
510 517 }
511 518
512 519 }
513 520 ndi_devi_exit(ihp->hba_dip, circ);
514 521
515 522 ilp->lun_dip = lun_dip;
516 523 ilp->lun_pip = NULL;
517 524
518 525 scsi_hba_nodename_compatible_free(nodename, compatible);
519 526
520 527 return (rtn);
521 528 }
522 529
523 530
524 531 /*
525 532 * iscsi_lun_online - _di_online logical unit
526 533 *
527 534 * This is called after a path has recovered it will cause
528 535 * an offline path to become online/active again.
529 536 */
530 537 void
531 538 iscsi_lun_online(iscsi_hba_t *ihp, iscsi_lun_t *ilp)
532 539 {
533 540 int circ = 0;
534 541 int rval = 0;
535 542 uint64_t *lun_num_ptr = NULL;
536 543 uint16_t boot_lun_num = 0;
537 544 iscsi_sess_t *isp = NULL;
538 545 boolean_t online = B_FALSE;
539 546 nvlist_t *attr_list = NULL;
540 547 char *pathname = NULL;
541 548 dev_info_t *lun_dip = NULL;
542 549
543 550 ASSERT(ilp != NULL);
544 551 ASSERT((ilp->lun_pip != NULL) || (ilp->lun_dip != NULL));
545 552
546 553 if (ilp->lun_pip != NULL) {
547 554 ndi_devi_enter(scsi_vhci_dip, &circ);
548 555 rval = mdi_pi_online(ilp->lun_pip, 0);
549 556 ndi_devi_exit(scsi_vhci_dip, circ);
550 557 if (rval == MDI_SUCCESS) {
551 558 ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
552 559 ilp->lun_state |= ISCSI_LUN_STATE_ONLINE;
553 560 ilp->lun_time_online = ddi_get_time();
554 561 online = B_TRUE;
555 562 }
556 563
557 564 } else if (ilp->lun_dip != NULL) {
558 565 ndi_devi_enter(ihp->hba_dip, &circ);
559 566 rval = ndi_devi_online(ilp->lun_dip, 0);
560 567 ndi_devi_exit(ihp->hba_dip, circ);
561 568 if (rval == NDI_SUCCESS) {
562 569 ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
563 570 ilp->lun_state |= ISCSI_LUN_STATE_ONLINE;
564 571 ilp->lun_time_online = ddi_get_time();
565 572 online = B_TRUE;
566 573 }
567 574 }
568 575
569 576 /* Check whether this is the required LUN for iscsi boot */
570 577 if (iscsiboot_prop != NULL &&
571 578 iscsiboot_prop->boot_tgt.lun_online == 0) {
572 579 isp = ilp->lun_sess;
573 580 if (isp->sess_boot == B_TRUE) {
574 581 lun_num_ptr =
575 582 (uint64_t *)iscsiboot_prop->boot_tgt.tgt_boot_lun;
576 583 boot_lun_num = (uint16_t)(*lun_num_ptr);
577 584 if (boot_lun_num == ilp->lun_num) {
578 585 /*
579 586 * During iscsi boot, the boot lun has been
580 587 * online, we should set the "online flag".
581 588 */
582 589 iscsiboot_prop->boot_tgt.lun_online = 1;
583 590 }
584 591 }
585 592 }
586 593
587 594 /*
588 595 * If the LUN has been online and it is a disk,
589 596 * send out a system event.
590 597 */
591 598 if (online == B_TRUE && ilp->lun_type == DTYPE_DIRECT) {
592 599 if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_SLEEP) !=
593 600 DDI_SUCCESS) {
594 601 return;
595 602 }
596 603
597 604 if (ilp->lun_pip != NULL) {
598 605 lun_dip = mdi_pi_get_client(ilp->lun_pip);
599 606 } else {
600 607 lun_dip = ilp->lun_dip;
601 608 }
602 609
603 610 pathname = kmem_zalloc(MAXNAMELEN + 1, KM_SLEEP);
604 611 (void) ddi_pathname(lun_dip, pathname);
605 612
606 613 if (nvlist_add_string(attr_list, DEV_PHYS_PATH, pathname) !=
607 614 DDI_SUCCESS) {
608 615 nvlist_free(attr_list);
609 616 kmem_free(pathname, MAXNAMELEN + 1);
610 617 return;
611 618 }
612 619 iscsi_send_sysevent(ihp, EC_DEV_ADD, ESC_DISK, attr_list);
613 620 kmem_free(pathname, MAXNAMELEN + 1);
614 621 nvlist_free(attr_list);
615 622 }
616 623 }
617 624
618 625 /*
619 626 * iscsi_lun_offline - attempt _di_offline [and optional _di_free]
620 627 *
621 628 * This function is called via two paths. When a transport
622 629 * path has failed it will be called to offline the logical
623 630 * unit. When nameservice access has been removed it will
624 631 * be called to both offline and free the logical unit.
625 632 * (This operates soley on the solaris node states.
626 633 * iscsi_lun_destroy() should be called when attempting
627 634 * to free all iscsi lun resources.)
628 635 *
629 636 * This function can fail with ISCSI_STATUS_BUSY if the
630 637 * logical unit is in use. The user should unmount or
631 638 * close the device and perform the nameservice operation
632 639 * again if this occurs.
633 640 *
↓ open down ↓ |
594 lines elided |
↑ open up ↑ |
634 641 * If we fail to offline a LUN that we don't want to destroy,
635 642 * we will mark it with invalid state. If this LUN still
636 643 * exists on the target, we can have another chance to online
637 644 * it again when we do the LUN enumeration.
638 645 */
639 646 iscsi_status_t
640 647 iscsi_lun_offline(iscsi_hba_t *ihp, iscsi_lun_t *ilp, boolean_t lun_free)
641 648 {
642 649 iscsi_status_t status = ISCSI_STATUS_SUCCESS;
643 650 int circ = 0;
644 - dev_info_t *cdip, *pdip;
645 - char *devname = NULL;
651 + dev_info_t *cdip;
646 652 char *pathname = NULL;
647 - int rval;
648 653 boolean_t offline = B_FALSE;
649 654 nvlist_t *attr_list = NULL;
650 655
651 656 ASSERT(ilp != NULL);
652 657 ASSERT((ilp->lun_pip != NULL) || (ilp->lun_dip != NULL));
653 658
654 - /*
655 - * Since we carry the logical units parent
656 - * lock across the offline call it will not
657 - * issue devfs_clean() and may fail with a
658 - * devi_ref count > 0.
659 - */
660 - if (ilp->lun_pip == NULL) {
659 + if (ilp->lun_pip == NULL)
661 660 cdip = ilp->lun_dip;
662 - } else {
661 + else
663 662 cdip = mdi_pi_get_client(ilp->lun_pip);
664 - }
665 663
666 - if ((cdip != NULL) &&
667 - (lun_free == B_TRUE) &&
668 - (ilp->lun_state & ISCSI_LUN_STATE_ONLINE)) {
669 - /*
670 - * Make sure node is attached otherwise
671 - * it won't have related cache nodes to
672 - * clean up. i_ddi_devi_attached is
673 - * similiar to i_ddi_node_state(cdip) >=
674 - * DS_ATTACHED. We should clean up only
675 - * when lun_free is set.
676 - */
677 - if (i_ddi_devi_attached(cdip)) {
678 -
679 - /* Get parent dip */
680 - pdip = ddi_get_parent(cdip);
681 -
682 - /* Get full devname */
683 - devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
684 - ndi_devi_enter(pdip, &circ);
685 - (void) ddi_deviname(cdip, devname);
686 - /* Release lock before devfs_clean() */
687 - ndi_devi_exit(pdip, circ);
688 -
689 - /* Clean cache */
690 - (void) devfs_clean(pdip, devname + 1, DV_CLEAN_FORCE);
691 - kmem_free(devname, MAXNAMELEN + 1);
692 - }
693 - }
694 -
695 664 if (cdip != NULL && ilp->lun_type == DTYPE_DIRECT) {
696 665 pathname = kmem_zalloc(MAXNAMELEN + 1, KM_SLEEP);
697 666 (void) ddi_pathname(cdip, pathname);
698 667 }
699 668
700 669 /* Attempt to offline the logical units */
701 670 if (ilp->lun_pip != NULL) {
702 -
703 671 /* virt/mdi */
704 672 ndi_devi_enter(scsi_vhci_dip, &circ);
705 - if ((lun_free == B_TRUE) &&
706 - (ilp->lun_state & ISCSI_LUN_STATE_ONLINE)) {
707 - rval = mdi_pi_offline(ilp->lun_pip,
708 - NDI_DEVI_REMOVE);
709 - } else {
710 - rval = mdi_pi_offline(ilp->lun_pip, 0);
711 - }
712 -
713 - if (rval == MDI_SUCCESS) {
673 + if (mdi_pi_offline(ilp->lun_pip, 0) == MDI_SUCCESS) {
714 674 ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
715 675 ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
716 676 if (lun_free == B_TRUE) {
717 677 (void) mdi_prop_remove(ilp->lun_pip, NULL);
718 678 (void) mdi_pi_free(ilp->lun_pip, 0);
719 679 }
720 680 offline = B_TRUE;
721 681 } else {
722 682 status = ISCSI_STATUS_BUSY;
723 683 if (lun_free == B_FALSE) {
724 684 ilp->lun_state |= ISCSI_LUN_STATE_INVALID;
725 685 offline = B_TRUE;
726 686 }
727 687 }
728 688 ndi_devi_exit(scsi_vhci_dip, circ);
729 689
730 690 } else {
731 -
732 691 /* phys/ndi */
692 + int flags = NDI_DEVFS_CLEAN;
693 +
733 694 ndi_devi_enter(ihp->hba_dip, &circ);
734 - if ((lun_free == B_TRUE) &&
735 - (ilp->lun_state & ISCSI_LUN_STATE_ONLINE)) {
736 - rval = ndi_devi_offline(
737 - ilp->lun_dip, NDI_DEVI_REMOVE);
738 - } else {
739 - rval = ndi_devi_offline(
740 - ilp->lun_dip, 0);
741 - }
742 - if (rval != NDI_SUCCESS) {
695 + if (lun_free == B_TRUE &&
696 + (ilp->lun_state & ISCSI_LUN_STATE_ONLINE))
697 + flags |= NDI_DEVI_REMOVE;
698 + if (ndi_devi_offline(ilp->lun_dip, flags) != NDI_SUCCESS) {
743 699 status = ISCSI_STATUS_BUSY;
744 700 if (lun_free == B_FALSE) {
745 701 ilp->lun_state |= ISCSI_LUN_STATE_INVALID;
746 702 offline = B_TRUE;
747 703 }
748 704 } else {
749 705 ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
750 706 ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
751 707 offline = B_TRUE;
752 708 }
753 709 ndi_devi_exit(ihp->hba_dip, circ);
754 710 }
755 711
756 712 if (offline == B_TRUE && pathname != NULL &&
757 713 ilp->lun_type == DTYPE_DIRECT) {
758 714 if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_SLEEP) !=
759 715 DDI_SUCCESS) {
760 716 kmem_free(pathname, MAXNAMELEN + 1);
761 717 return (status);
762 718 }
763 719
764 720 if (nvlist_add_string(attr_list, DEV_PHYS_PATH, pathname) !=
765 721 DDI_SUCCESS) {
766 722 nvlist_free(attr_list);
767 723 kmem_free(pathname, MAXNAMELEN + 1);
768 724 return (status);
769 725 }
770 726
771 727 iscsi_send_sysevent(ihp, EC_DEV_REMOVE, ESC_DISK, attr_list);
772 728 nvlist_free(attr_list);
773 729 }
774 730
775 731 if (pathname != NULL) {
776 732 kmem_free(pathname, MAXNAMELEN + 1);
777 733 }
778 734
779 735 return (status);
780 736 }
↓ open down ↓ |
28 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX