1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 /*LINTLIBRARY*/ 28 29 30 /* 31 * This module is part of fibre channel interface library. 32 */ 33 34 /* 35 * I18N message number ranges 36 * This file: 11000 - 11499 37 * Shared common messages: 1 - 1999 38 */ 39 40 /* #define _POSIX_SOURCE 1 */ 41 42 /* Includes */ 43 #include <stdlib.h> 44 #include <stdio.h> 45 #include <sys/file.h> 46 #include <sys/errno.h> 47 #include <sys/types.h> 48 #include <sys/param.h> 49 #include <sys/stat.h> 50 #include <fcntl.h> 51 #include <unistd.h> 52 #include <errno.h> 53 #include <string.h> 54 #include <strings.h> 55 #include <sys/sunddi.h> 56 #include <sys/scsi/scsi.h> 57 #include <nl_types.h> 58 #include <l_common.h> 59 #include <stgcom.h> 60 #include <l_error.h> 61 #include <g_state.h> 62 63 /* Forward declarations */ 64 static int issue_lip(char *, int); 65 66 67 /* Global variables */ 68 extern uchar_t g_switch_to_alpa[]; 69 extern uchar_t g_sf_alpa_to_switch[]; 70 71 /* 72 * starts a device. 73 * 74 * RETURNS: 75 * 0 if O.K. 76 * non-zero otherwise 77 */ 78 int 79 g_dev_start(char *drv_path, int verbose) 80 { 81 int status; 82 83 if ((drv_path != NULL) && (*drv_path != '\0')) { 84 if (status = g_start(drv_path)) { 85 return (status); 86 } 87 } 88 return (L_INVALID_PATH); 89 } 90 91 92 93 /* 94 * stops a device. If the device was 95 * reserved by a host, it gets multiple 96 * paths to the device and try to stop the 97 * device using a different path. 98 * 99 * Returns: 100 * 0 if OK 101 * -1 otherwise 102 */ 103 104 int 105 g_dev_stop(char *drv_path, struct wwn_list_struct *wwn_list, 106 int verbose) 107 { 108 int status, err; 109 char *phys_path; 110 struct dlist *ml = NULL; 111 112 113 /* stop the device */ 114 /* Make the stop NOT immediate, so we wait. */ 115 if ((drv_path == NULL) || (*drv_path == '\0')) { 116 return (L_INVALID_PATH); 117 } 118 if ((status = g_stop(drv_path, 0)) != 0) { 119 /* 120 * In case of reservation conflict, 121 * get the multiple paths and try to 122 * stop the device through the path 123 * which held the reservations. 124 */ 125 if ((status & ~L_SCSI_ERROR) == STATUS_RESERVATION_CONFLICT) { 126 if ((phys_path = g_get_physical_name(drv_path)) 127 == NULL) { 128 return (L_INVALID_PATH); 129 } 130 if ((err = g_get_multipath(phys_path, &ml, 131 wwn_list, verbose)) != 0) { 132 return (err); 133 } 134 while (ml != NULL) { 135 if (g_stop(ml->logical_path, 0) == 0) { 136 (void) g_free_multipath(ml); 137 goto done; 138 } 139 ml = ml->next; 140 } 141 (void) g_free_multipath(ml); 142 } 143 return (status); 144 } 145 done: 146 return (0); 147 } 148 149 /* 150 * This function is for Leadville devices only 151 * It takes as input the actual path on which to issue the LIP and issues it 152 * 153 * INPUT : 154 * Path to the FCA devctl node. 155 * 156 * For example, 157 * /devices/pci@6,2000/pci@2/SUNW,qlc@4/fp@0,0:devctl 158 * 159 * No SCSI_VHCI paths will work. No checks are done and we'll let the ioctl 160 * handle any failures if it is passed in. 161 * 162 * RETURNS: 163 * 0 on Success 164 * non-zero otherwise 165 */ 166 static int 167 issue_lip(char *fp_path, int verbose) 168 { 169 int fp_fd; 170 la_wwn_t wwn; 171 fcio_t fcio; 172 173 /* 174 * open fp path with exclusive path, otherwise, 175 * FCIO_RESET_LINK ioctl will fail with permission 176 * denied error. 177 */ 178 if ((fp_fd = g_object_open(fp_path, O_RDONLY | O_EXCL)) < 0) { 179 return (L_OPEN_PATH_FAIL); 180 } 181 182 if (verbose) { 183 (void) fprintf(stdout, MSGSTR(11001, 184 " Reinitializing the loop at: %s\n"), fp_path); 185 } 186 187 fcio.fcio_cmd = FCIO_RESET_LINK; 188 fcio.fcio_xfer = FCIO_XFER_WRITE; 189 /* 190 * Reset the local loop here (fcio_ibuf = 0). 191 * Reset a remote loop on the Fabric by 192 * passing its node wwn (fcio_len = sizeof(nwwn) 193 * and fcio_ibuf = (caddr_t)&nwwn) to the port driver. 194 */ 195 (void) bzero((caddr_t)&wwn, sizeof (wwn)); 196 fcio.fcio_ilen = sizeof (wwn); 197 fcio.fcio_ibuf = (caddr_t)&wwn; 198 if (g_issue_fcio_ioctl(fp_fd, &fcio, verbose) != 0) { 199 I_DPRINTF(" issue_lip: FCIO_RESET_LINK" 200 " ioctl failed: %s\n", fp_path); 201 (void) close(fp_fd); 202 return (L_FCIO_RESET_LINK_FAIL); 203 } 204 (void) close(fp_fd); 205 return (0); 206 } 207 208 /* 209 * Issues the LIP (Loop Intialization Protocol) 210 * on a nexus path (in case of socal) or on an 211 * fp path (in case of fabric). 212 * 213 * RETURNS: 214 * 0 O.K. 215 * non-zero otherwise 216 */ 217 int 218 g_force_lip(char *path_phys, int verbose) 219 { 220 int fd, err = 0, i = 0, pathcnt = 0; 221 char nexus_path[MAXPATHLEN], *nexus_path_ptr; 222 char *charPtr, fp_path[MAXPATHLEN]; 223 struct stat stbuf; 224 uint_t dev_type; 225 mp_pathlist_t pathlist; 226 mp_pathinfo_t *pinfop; 227 228 /* return invalid path if path_phys NULL */ 229 if (path_phys == NULL) { 230 return (L_INVALID_PATH); 231 } 232 233 /* Make a copy of the arg passed in ... we'll need it down */ 234 (void) strcpy(fp_path, path_phys); 235 236 if (strstr(path_phys, SCSI_VHCI) != NULL) { 237 238 /* 239 * Its an MPXIO device path 240 * 241 * First, Get a list of all the pHCI for the given vHCI 242 * Then issue a LIP on all the pHCI FCAs that are in the 243 * MDI_PATHINFO_STATE_ONLINE or MDI_PATHINFO_STATE_STANDBY 244 * states. 245 */ 246 if (g_get_pathlist(fp_path, &pathlist)) { 247 return (L_INVALID_PATH); 248 } 249 for (i = 0; i < pathlist.path_count; i++) { 250 pinfop = &pathlist.path_info[i]; 251 if ((pinfop->path_state == 252 MDI_PATHINFO_STATE_ONLINE) || 253 (pinfop->path_state == 254 MDI_PATHINFO_STATE_STANDBY)) { 255 pathcnt++; 256 sprintf(fp_path, "%s%s", 257 pinfop->path_hba, FC_CTLR); 258 if (issue_lip(fp_path, verbose) != 0) { 259 err++; 260 } 261 } 262 } 263 free(pathlist.path_info); 264 if (err == 0) 265 return (0); 266 if (err == pathcnt) 267 return (L_FCIO_FORCE_LIP_FAIL); 268 return (L_FCIO_FORCE_LIP_PARTIAL_FAIL); 269 } 270 271 /* Non-MPXIO case */ 272 273 if ((dev_type = g_get_path_type(fp_path)) == 0) { 274 return (L_INVALID_PATH); 275 } 276 277 if (dev_type & FC_FCA_MASK) { 278 if (strstr(fp_path, DRV_NAME_SSD) || 279 strstr(fp_path, SES_NAME) || 280 strstr(fp_path, DRV_NAME_ST)) { 281 if ((charPtr = strrchr(fp_path, '/')) == NULL) { 282 return (L_INVALID_PATH); 283 } 284 *charPtr = '\0'; 285 /* append devctl to the path */ 286 (void) strcat(fp_path, FC_CTLR); 287 } else { 288 /* should have fp transport node to continue. */ 289 if (!(dev_type & FC_XPORT_MASK)) { 290 return (L_INVALID_PATH_TYPE); 291 } 292 if (stat(fp_path, &stbuf) < 0) { 293 return (L_LSTAT_ERROR); 294 } 295 if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 296 /* append devctl to the path */ 297 (void) strcat(fp_path, FC_CTLR); 298 } 299 } 300 return (issue_lip(fp_path, verbose)); 301 302 } else { /* for fc4 devices */ 303 if ((err = g_get_nexus_path(path_phys, 304 &nexus_path_ptr)) != 0) 305 return (err); 306 307 (void) strcpy(nexus_path, nexus_path_ptr); 308 (void) g_destroy_data(nexus_path_ptr); 309 P_DPRINTF(" g_force_lip: Force lip on:" 310 " Path %s\n", nexus_path); 311 312 /* open driver */ 313 if ((fd = g_object_open(nexus_path, 314 O_NDELAY | O_RDONLY)) == -1) 315 return (L_OPEN_PATH_FAIL); 316 317 if (verbose) { 318 (void) fprintf(stdout, 319 MSGSTR(11000, 320 " Forcing lip (Loop Initialization " 321 "Protocol)" 322 "\n on loop at: %s\n"), nexus_path); 323 } 324 if (ioctl(fd, FCIO_FORCE_LIP) != 0) { 325 I_DPRINTF(" FCIO_FORCE_LIP ioctl failed.\n"); 326 (void) close(fd); 327 return (L_FCIO_FORCE_LIP_FAIL); 328 } 329 (void) close(fd); 330 } 331 return (0); 332 } 333 334 335 336 /* 337 * Takes one or more drives offline. 338 * If the force flag is supplied then: (1) don't pass the exclusive flag 339 * to the acquire routine and (2) allow the offline to fail 340 * If any acquire fails, print an error message and continue. 341 * 342 * RETURNS: 343 * 0 iff each offline succeeds 344 * non-zero otherwise 345 */ 346 int 347 g_offline_drive(struct dlist *dl, int force_flag) 348 { 349 devctl_hdl_t devhdl; 350 351 352 /* for each drive attempt to take it offline */ 353 for (; dl != NULL; dl = dl->next) { 354 355 /* attempt to acquire the device */ 356 if ((devhdl = devctl_device_acquire(dl->dev_path, 357 force_flag ? 0 : DC_EXCL)) == NULL) { 358 if (errno != EBUSY) { 359 P_DPRINTF("%s: Could not acquire" 360 " the device: %s\n\n", 361 strerror(errno), dl->dev_path); 362 continue; 363 } 364 } 365 /* attempt to offline the drive */ 366 if ((devctl_device_offline(devhdl) != 0) && !force_flag) { 367 (void) devctl_release(devhdl); 368 return (L_DEV_BUSY); 369 } 370 371 /* offline succeeded -- release handle acquired above */ 372 (void) devctl_release(devhdl); 373 } 374 375 return (0); 376 } 377 378 379 380 /* 381 * Brings one or more drives online. 382 * If the force flag is supplied then: (1) don't pass the exclusive 383 * flag to the acquire routine and (2) allow the offline to fail 384 * If any acquire fails, continue with the next device. 385 * 386 * RETURNS: 387 * None. 388 */ 389 void 390 g_online_drive(struct dlist *dl, int force_flag) 391 { 392 devctl_hdl_t devhdl; 393 394 395 while (dl != NULL) { 396 if ((devhdl = devctl_device_acquire(dl->dev_path, 397 force_flag ? 0 : DC_EXCL)) != NULL) { 398 (void) devctl_device_online(devhdl); 399 (void) devctl_release(devhdl); 400 } 401 dl = dl->next; 402 } 403 } 404 405 406 407 void 408 g_ll_to_str(uchar_t *wwn_ll, char *wwn_str) 409 { 410 int j, k, fnib, snib; 411 uchar_t c; 412 413 for (j = 0, k = 0; j < 8; j++) { 414 c = wwn_ll[j]; 415 fnib = ((int)(c & 0xf0) >> 4); 416 snib = (c & 0x0f); 417 if (fnib >= 0 && fnib <= 9) 418 wwn_str[k++] = '0' + fnib; 419 else if (fnib >= 10 && fnib <= 15) 420 wwn_str[k++] = 'a' + fnib - 10; 421 if (snib >= 0 && snib <= 9) 422 wwn_str[k++] = '0' + snib; 423 else if (snib >= 10 && snib <= 15) 424 wwn_str[k++] = 'a' + snib - 10; 425 } 426 wwn_str[k] = '\0'; 427 } 428 429 430 431 /* 432 * Creates a list of nexus paths for each 433 * hotpluggable device and sends the list to g_force_lip(), 434 * which forces the LIP on each nexus path in the list. 435 * 436 * RETURNS: 437 * None. 438 */ 439 int 440 g_forcelip_all(struct hotplug_disk_list *disk_list) 441 { 442 char *p; 443 int len, ndevs = 0, err = 0; 444 struct dlist *dl; 445 struct loop_list { /* adp_name holds full dev path for MPXIO devices */ 446 char adp_name[MAXPATHLEN]; 447 struct loop_list *next; 448 struct loop_list *prev; 449 } *llist_head, *llist_tail, *llist, *llist1; 450 451 llist_head = llist_tail = NULL; 452 453 while (disk_list) { 454 if (disk_list->dev_location == SENA) { 455 dl = disk_list->seslist; 456 } else { 457 dl = disk_list->dlhead; 458 } 459 while (dl != NULL) { 460 if (strstr(dl->dev_path, SCSI_VHCI) == NULL) { 461 /* non-MPXIO device path */ 462 if (disk_list->dev_location == SENA) { 463 p = strstr(dl->dev_path, SLASH_SES); 464 } else { 465 p = strstr(dl->dev_path, SLSH_DRV_NAME_SSD); 466 if (p == NULL) { 467 p = strstr(dl->dev_path, 468 SLSH_DRV_NAME_ST); 469 } 470 } 471 if (p == NULL) { 472 P_DPRINTF( 473 " g_forcelip_all: Not able to do" 474 " LIP on this path because path " 475 "invalid.\n Path: %s\n", dl->dev_path); 476 dl = dl->next; 477 continue; 478 } 479 len = strlen(dl->dev_path) - strlen(p); 480 } else { 481 /* MPXIO path */ 482 len = strlen(dl->dev_path); 483 } 484 485 /* 486 * Avoid issuing forcelip 487 * on the same HA more than once 488 */ 489 if (llist_head != NULL) { 490 for (llist1 = llist_head; llist1 != NULL; 491 llist1 = llist1->next) { 492 if (strncmp(llist1->adp_name, 493 dl->dev_path, len) == 0) { 494 break; 495 } 496 } 497 if (llist1 != NULL) { 498 dl = dl->next; 499 continue; 500 } 501 } 502 if ((llist = (struct loop_list *) 503 g_zalloc(sizeof (struct loop_list))) == NULL) 504 return (L_MALLOC_FAILED); 505 (void) strncpy(llist->adp_name, dl->dev_path, len); 506 llist->adp_name[len] = '\0'; 507 ndevs++; 508 509 if (llist_head == NULL) { 510 llist_head = llist_tail = llist; 511 } else { 512 llist->prev = llist_tail; 513 llist_tail = llist_tail->next = llist; 514 } 515 dl = dl->next; 516 } 517 disk_list = disk_list->next; 518 } 519 520 while (llist_head) { 521 if ((err = g_force_lip(llist_head->adp_name, 0)) != 0) { 522 (void) g_destroy_data(llist); 523 (void) g_destroy_data(llist_head); 524 return (err); 525 } 526 llist = llist_head; 527 llist_head = llist_head->next; 528 (void) g_destroy_data((char *)llist); 529 } 530 (void) sleep(ndevs*10); 531 return (0); 532 } 533