1*fcf3ce44SJohn Forte /* 2*fcf3ce44SJohn Forte * CDDL HEADER START 3*fcf3ce44SJohn Forte * 4*fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5*fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6*fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7*fcf3ce44SJohn Forte * 8*fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10*fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11*fcf3ce44SJohn Forte * and limitations under the License. 12*fcf3ce44SJohn Forte * 13*fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14*fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16*fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17*fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18*fcf3ce44SJohn Forte * 19*fcf3ce44SJohn Forte * CDDL HEADER END 20*fcf3ce44SJohn Forte */ 21*fcf3ce44SJohn Forte /* 22*fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*fcf3ce44SJohn Forte * Use is subject to license terms. 24*fcf3ce44SJohn Forte */ 25*fcf3ce44SJohn Forte 26*fcf3ce44SJohn Forte 27*fcf3ce44SJohn Forte 28*fcf3ce44SJohn Forte /*LINTLIBRARY*/ 29*fcf3ce44SJohn Forte 30*fcf3ce44SJohn Forte 31*fcf3ce44SJohn Forte /* 32*fcf3ce44SJohn Forte * Hotplug program for SENA, RSM and SSA 33*fcf3ce44SJohn Forte * subsystems and individual FC_AL devices. 34*fcf3ce44SJohn Forte */ 35*fcf3ce44SJohn Forte 36*fcf3ce44SJohn Forte /* #define _POSIX_SOURCE 1 */ 37*fcf3ce44SJohn Forte 38*fcf3ce44SJohn Forte /* 39*fcf3ce44SJohn Forte * I18N message number ranges 40*fcf3ce44SJohn Forte * This file: 5500 - 5999 41*fcf3ce44SJohn Forte * Shared common messages: 1 - 1999 42*fcf3ce44SJohn Forte */ 43*fcf3ce44SJohn Forte 44*fcf3ce44SJohn Forte 45*fcf3ce44SJohn Forte /* Includes */ 46*fcf3ce44SJohn Forte #include <stdlib.h> 47*fcf3ce44SJohn Forte #include <stdio.h> 48*fcf3ce44SJohn Forte #include <sys/file.h> 49*fcf3ce44SJohn Forte #include <sys/errno.h> 50*fcf3ce44SJohn Forte #include <sys/types.h> 51*fcf3ce44SJohn Forte #include <sys/stat.h> 52*fcf3ce44SJohn Forte #include <sys/utsname.h> 53*fcf3ce44SJohn Forte #include <fcntl.h> 54*fcf3ce44SJohn Forte #include <unistd.h> 55*fcf3ce44SJohn Forte #include <errno.h> 56*fcf3ce44SJohn Forte #include <string.h> 57*fcf3ce44SJohn Forte #include <sys/sunddi.h> 58*fcf3ce44SJohn Forte #include <sys/ddi.h> /* for min */ 59*fcf3ce44SJohn Forte #include <sys/scsi/scsi.h> 60*fcf3ce44SJohn Forte #include <nl_types.h> 61*fcf3ce44SJohn Forte #include <dirent.h> 62*fcf3ce44SJohn Forte #include <sys/wait.h> 63*fcf3ce44SJohn Forte #include <l_common.h> 64*fcf3ce44SJohn Forte #include <l_error.h> 65*fcf3ce44SJohn Forte #include <stgcom.h> 66*fcf3ce44SJohn Forte #include <a_state.h> 67*fcf3ce44SJohn Forte #include <a5k.h> 68*fcf3ce44SJohn Forte #include <rom.h> 69*fcf3ce44SJohn Forte #include "hot.h" 70*fcf3ce44SJohn Forte #include "common.h" 71*fcf3ce44SJohn Forte #include "luxadm.h" 72*fcf3ce44SJohn Forte 73*fcf3ce44SJohn Forte 74*fcf3ce44SJohn Forte /* Internal variables. */ 75*fcf3ce44SJohn Forte static char *cmdStrg[][4] = { 76*fcf3ce44SJohn Forte { "disks", "-C", 0, 0 }, 77*fcf3ce44SJohn Forte { "disks", 0, 0, 0 }, 78*fcf3ce44SJohn Forte { "drvconfig", "-i", "ssd", 0 }, 79*fcf3ce44SJohn Forte { "drvconfig", 0, 0, 0 }, 80*fcf3ce44SJohn Forte { "devlinks", 0, 0, 0 }, 81*fcf3ce44SJohn Forte { "tapes", "-C", 0, 0 } 82*fcf3ce44SJohn Forte }; 83*fcf3ce44SJohn Forte 84*fcf3ce44SJohn Forte /* External variables */ 85*fcf3ce44SJohn Forte extern char *dtype[]; /* From adm.c */ 86*fcf3ce44SJohn Forte extern int Options; 87*fcf3ce44SJohn Forte extern const int OPTION_CAPF; 88*fcf3ce44SJohn Forte 89*fcf3ce44SJohn Forte /* Internal functions */ 90*fcf3ce44SJohn Forte /* SENA and Individual FC device Hotplug */ 91*fcf3ce44SJohn Forte static int h_pre_insert_encl_dev(timestruc_t *, timestruc_t *, 92*fcf3ce44SJohn Forte timestruc_t *); 93*fcf3ce44SJohn Forte static int h_post_insert_dev(timestruc_t, timestruc_t); 94*fcf3ce44SJohn Forte static int h_pre_remove_dev(Hotplug_Devlist *, 95*fcf3ce44SJohn Forte WWN_list *wwn_list, int, int); 96*fcf3ce44SJohn Forte static int h_post_remove_dev(Hotplug_Devlist *, int, int); 97*fcf3ce44SJohn Forte static int h_pre_hotplug(Hotplug_Devlist **, 98*fcf3ce44SJohn Forte WWN_list *, int, int, int); 99*fcf3ce44SJohn Forte static int h_post_hotplug(Hotplug_Devlist *, 100*fcf3ce44SJohn Forte WWN_list *, int, int, int, int); 101*fcf3ce44SJohn Forte static int h_post_insert_encl(timestruc_t); 102*fcf3ce44SJohn Forte static int h_pre_hotplug_sena(Hotplug_Devlist *, 103*fcf3ce44SJohn Forte WWN_list *, int, int, int); 104*fcf3ce44SJohn Forte static int h_post_hotplug_sena(Hotplug_Devlist *, 105*fcf3ce44SJohn Forte WWN_list *, int, int, int, int); 106*fcf3ce44SJohn Forte static int h_remove_ses_nodes(struct dlist *); 107*fcf3ce44SJohn Forte static int h_print_list_warn(Hotplug_Devlist *, int, int); 108*fcf3ce44SJohn Forte static int h_display_logical_nodes(struct dlist *); 109*fcf3ce44SJohn Forte static void h_print_logical_nodes(struct dlist *); 110*fcf3ce44SJohn Forte static int h_remove_nodes(struct dlist *); 111*fcf3ce44SJohn Forte static int h_print_list(Hotplug_Devlist *, int *, int); 112*fcf3ce44SJohn Forte static int h_get_fcdev_state(char *, char *, int, int *, int *, int); 113*fcf3ce44SJohn Forte static int h_chk_dev_busy(Hotplug_Devlist *, 114*fcf3ce44SJohn Forte WWN_list *, int *, int, int); 115*fcf3ce44SJohn Forte static int h_execCmnd(char **, int); 116*fcf3ce44SJohn Forte int hotplug(int, char **, int, int); 117*fcf3ce44SJohn Forte int h_insertSena_fcdev(); 118*fcf3ce44SJohn Forte static int h_find_new_device_link(char *, timestruc_t); 119*fcf3ce44SJohn Forte 120*fcf3ce44SJohn Forte 121*fcf3ce44SJohn Forte 122*fcf3ce44SJohn Forte /* 123*fcf3ce44SJohn Forte * Assists the user in hot inserting FC_AL 124*fcf3ce44SJohn Forte * individual device(s) and SENA enclosure(s). 125*fcf3ce44SJohn Forte * 126*fcf3ce44SJohn Forte * RETURNS: 127*fcf3ce44SJohn Forte * 0 if OK 128*fcf3ce44SJohn Forte * non-zero otherwise 129*fcf3ce44SJohn Forte */ 130*fcf3ce44SJohn Forte int 131*fcf3ce44SJohn Forte h_insertSena_fcdev() 132*fcf3ce44SJohn Forte { 133*fcf3ce44SJohn Forte timestruc_t ses_time, dsk_time, rmt_time; 134*fcf3ce44SJohn Forte int err; 135*fcf3ce44SJohn Forte struct stat ses_stat; 136*fcf3ce44SJohn Forte 137*fcf3ce44SJohn Forte if ((err = h_pre_insert_encl_dev(&ses_time, &dsk_time, 138*fcf3ce44SJohn Forte &rmt_time)) != 0) { 139*fcf3ce44SJohn Forte return (err); 140*fcf3ce44SJohn Forte } 141*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5500, 142*fcf3ce44SJohn Forte "Please hit <RETURN> when you have finished" 143*fcf3ce44SJohn Forte " adding Fibre Channel Enclosure(s)/Device(s): ")); 144*fcf3ce44SJohn Forte (void) getchar(); 145*fcf3ce44SJohn Forte 146*fcf3ce44SJohn Forte if ((err = h_post_insert_dev(dsk_time, rmt_time)) != 0) { 147*fcf3ce44SJohn Forte return (err); 148*fcf3ce44SJohn Forte } 149*fcf3ce44SJohn Forte 150*fcf3ce44SJohn Forte if (stat(SES_DIR, &ses_stat) < 0) { 151*fcf3ce44SJohn Forte /* 152*fcf3ce44SJohn Forte * Non existence of /dev/es dir indicates 153*fcf3ce44SJohn Forte * no ses devices inserted. 154*fcf3ce44SJohn Forte * No need to call h_post_insert_encl(). 155*fcf3ce44SJohn Forte */ 156*fcf3ce44SJohn Forte if (errno == ENOENT) { 157*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5662, 158*fcf3ce44SJohn Forte " No new enclosure(s) were added!!\n\n")); 159*fcf3ce44SJohn Forte return (0); 160*fcf3ce44SJohn Forte } else { 161*fcf3ce44SJohn Forte return (L_LSTAT_ES_DIR_ERROR); 162*fcf3ce44SJohn Forte } 163*fcf3ce44SJohn Forte } 164*fcf3ce44SJohn Forte 165*fcf3ce44SJohn Forte /* 166*fcf3ce44SJohn Forte * if the latest mod time of /dev/es is not newer than 167*fcf3ce44SJohn Forte * the original mod time no need to call 168*fcf3ce44SJohn Forte * h_post_insert_encl(). 169*fcf3ce44SJohn Forte */ 170*fcf3ce44SJohn Forte if ((&ses_time != (timestruc_t *)NULL) && 171*fcf3ce44SJohn Forte !(NEWER(ses_stat.st_ctim, ses_time))) { 172*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5662, 173*fcf3ce44SJohn Forte " No new enclosure(s) were added!!\n\n")); 174*fcf3ce44SJohn Forte return (0); 175*fcf3ce44SJohn Forte } 176*fcf3ce44SJohn Forte if ((err = h_post_insert_encl(ses_time)) != 0) { 177*fcf3ce44SJohn Forte return (err); 178*fcf3ce44SJohn Forte } 179*fcf3ce44SJohn Forte return (0); 180*fcf3ce44SJohn Forte } 181*fcf3ce44SJohn Forte 182*fcf3ce44SJohn Forte 183*fcf3ce44SJohn Forte 184*fcf3ce44SJohn Forte /* 185*fcf3ce44SJohn Forte * gets the devices state - check for disk's reservations. 186*fcf3ce44SJohn Forte * 187*fcf3ce44SJohn Forte * RETURNS: 188*fcf3ce44SJohn Forte * 0 if OK 189*fcf3ce44SJohn Forte * non-zero otherwise 190*fcf3ce44SJohn Forte */ 191*fcf3ce44SJohn Forte static int 192*fcf3ce44SJohn Forte h_get_fcdev_state(char *fc_dev, char *path_phys, int force_flag, 193*fcf3ce44SJohn Forte int *busy_flag, int *reserve_flag, int verbose_flag) 194*fcf3ce44SJohn Forte { 195*fcf3ce44SJohn Forte int err; 196*fcf3ce44SJohn Forte L_inquiry inq; 197*fcf3ce44SJohn Forte L_disk_state l_disk_state; 198*fcf3ce44SJohn Forte 199*fcf3ce44SJohn Forte 200*fcf3ce44SJohn Forte if ((err = g_get_inquiry(path_phys, &inq)) != 0) { 201*fcf3ce44SJohn Forte (void) fprintf(stderr, 202*fcf3ce44SJohn Forte MSGSTR(5501, 203*fcf3ce44SJohn Forte "Inquiry failed for %s\n"), 204*fcf3ce44SJohn Forte path_phys); 205*fcf3ce44SJohn Forte return (err); 206*fcf3ce44SJohn Forte } 207*fcf3ce44SJohn Forte if (inq.inq_port) { 208*fcf3ce44SJohn Forte if ((err = l_get_disk_port_status(path_phys, &l_disk_state, 209*fcf3ce44SJohn Forte FC_PORT_B, verbose_flag)) != 0) { 210*fcf3ce44SJohn Forte return (err); 211*fcf3ce44SJohn Forte } 212*fcf3ce44SJohn Forte } else { 213*fcf3ce44SJohn Forte if ((err = l_get_disk_port_status(path_phys, &l_disk_state, 214*fcf3ce44SJohn Forte FC_PORT_A, verbose_flag)) != 0) { 215*fcf3ce44SJohn Forte return (err); 216*fcf3ce44SJohn Forte } 217*fcf3ce44SJohn Forte } 218*fcf3ce44SJohn Forte 219*fcf3ce44SJohn Forte /* 220*fcf3ce44SJohn Forte * Don't print error msg. if disk is reserved 221*fcf3ce44SJohn Forte * and tried to be removed from the same port. 222*fcf3ce44SJohn Forte * If force flag is set, remove the disk without 223*fcf3ce44SJohn Forte * checking the disk reservations. 224*fcf3ce44SJohn Forte */ 225*fcf3ce44SJohn Forte if (!force_flag) { 226*fcf3ce44SJohn Forte if (((inq.inq_port) && 227*fcf3ce44SJohn Forte (l_disk_state.g_disk_state.d_state_flags[FC_PORT_B] & 228*fcf3ce44SJohn Forte L_RESERVED)) || 229*fcf3ce44SJohn Forte ((!inq.inq_port) && 230*fcf3ce44SJohn Forte (l_disk_state.g_disk_state.d_state_flags[FC_PORT_A] & 231*fcf3ce44SJohn Forte L_RESERVED))) { 232*fcf3ce44SJohn Forte *reserve_flag = 1; 233*fcf3ce44SJohn Forte } 234*fcf3ce44SJohn Forte } 235*fcf3ce44SJohn Forte return (0); 236*fcf3ce44SJohn Forte } 237*fcf3ce44SJohn Forte 238*fcf3ce44SJohn Forte 239*fcf3ce44SJohn Forte /* 240*fcf3ce44SJohn Forte * Forks a child process and let the child to 241*fcf3ce44SJohn Forte * execute a given command string by calling the 242*fcf3ce44SJohn Forte * the execvp() function. Then, the parent process 243*fcf3ce44SJohn Forte * waits for the child to exit. Once the parent process 244*fcf3ce44SJohn Forte * is notified by the kernel with the termination of 245*fcf3ce44SJohn Forte * the child, then the parent checks for the exit 246*fcf3ce44SJohn Forte * status of the child and return to the caller with -1 in case 247*fcf3ce44SJohn Forte * of error and zero otherwise. 248*fcf3ce44SJohn Forte * 249*fcf3ce44SJohn Forte * RETURNS: 250*fcf3ce44SJohn Forte * 0 if OK 251*fcf3ce44SJohn Forte * non-zero otherwise 252*fcf3ce44SJohn Forte */ 253*fcf3ce44SJohn Forte int 254*fcf3ce44SJohn Forte h_execCmnd(char *argStr[], int nArg) 255*fcf3ce44SJohn Forte { 256*fcf3ce44SJohn Forte pid_t pid; 257*fcf3ce44SJohn Forte int ix, status; 258*fcf3ce44SJohn Forte 259*fcf3ce44SJohn Forte if ((pid = fork()) < 0) { 260*fcf3ce44SJohn Forte (void) fprintf(stderr, 261*fcf3ce44SJohn Forte MSGSTR(133, 262*fcf3ce44SJohn Forte "Error: Failed to fork a process.\n")); 263*fcf3ce44SJohn Forte return (-1); 264*fcf3ce44SJohn Forte } else if (pid == 0) { 265*fcf3ce44SJohn Forte /* child process */ 266*fcf3ce44SJohn Forte if (execvp(argStr[0], argStr) < 0) { 267*fcf3ce44SJohn Forte (void) fprintf(stderr, 268*fcf3ce44SJohn Forte MSGSTR(5502, 269*fcf3ce44SJohn Forte " Error: execvp() failed to run " 270*fcf3ce44SJohn Forte "the command:")); 271*fcf3ce44SJohn Forte for (ix = 0; ix < nArg; ix++) { 272*fcf3ce44SJohn Forte (void) fprintf(stderr, 273*fcf3ce44SJohn Forte " %s", argStr[ix]); 274*fcf3ce44SJohn Forte } 275*fcf3ce44SJohn Forte (void) fprintf(stderr, "\n"); 276*fcf3ce44SJohn Forte /* let parent know about the error. */ 277*fcf3ce44SJohn Forte exit(ENOEXEC); 278*fcf3ce44SJohn Forte } 279*fcf3ce44SJohn Forte } 280*fcf3ce44SJohn Forte 281*fcf3ce44SJohn Forte /* parent executes the following. */ 282*fcf3ce44SJohn Forte if (waitpid(pid, &status, 0) != pid) { 283*fcf3ce44SJohn Forte (void) fprintf(stderr, 284*fcf3ce44SJohn Forte MSGSTR(5503, 285*fcf3ce44SJohn Forte "Error: waitpid() failed.\n")); 286*fcf3ce44SJohn Forte return (-1); 287*fcf3ce44SJohn Forte } 288*fcf3ce44SJohn Forte if (WIFEXITED(status) && 289*fcf3ce44SJohn Forte WEXITSTATUS(status) == ENOEXEC) { 290*fcf3ce44SJohn Forte /* child failed to run the command string. */ 291*fcf3ce44SJohn Forte return (-1); 292*fcf3ce44SJohn Forte } 293*fcf3ce44SJohn Forte return (0); 294*fcf3ce44SJohn Forte 295*fcf3ce44SJohn Forte } 296*fcf3ce44SJohn Forte 297*fcf3ce44SJohn Forte 298*fcf3ce44SJohn Forte 299*fcf3ce44SJohn Forte 300*fcf3ce44SJohn Forte /* 301*fcf3ce44SJohn Forte * frees the hotplug disk list structure. 302*fcf3ce44SJohn Forte * 303*fcf3ce44SJohn Forte * RETURNS: 304*fcf3ce44SJohn Forte * N/A 305*fcf3ce44SJohn Forte */ 306*fcf3ce44SJohn Forte void 307*fcf3ce44SJohn Forte h_free_hotplug_dlist(Hotplug_Devlist **hotplug_dlist) 308*fcf3ce44SJohn Forte { 309*fcf3ce44SJohn Forte Hotplug_Devlist *list = NULL; 310*fcf3ce44SJohn Forte 311*fcf3ce44SJohn Forte while (*hotplug_dlist != NULL) { 312*fcf3ce44SJohn Forte list = *hotplug_dlist; 313*fcf3ce44SJohn Forte *hotplug_dlist = (*hotplug_dlist)->next; 314*fcf3ce44SJohn Forte (void) g_free_multipath(list->seslist); 315*fcf3ce44SJohn Forte (void) g_free_multipath(list->dlhead); 316*fcf3ce44SJohn Forte (void) free((void *)list); 317*fcf3ce44SJohn Forte } 318*fcf3ce44SJohn Forte } 319*fcf3ce44SJohn Forte 320*fcf3ce44SJohn Forte 321*fcf3ce44SJohn Forte /* 322*fcf3ce44SJohn Forte * finds whether device (SENA or an FCAL device) is busy or not. 323*fcf3ce44SJohn Forte * 324*fcf3ce44SJohn Forte * OUTPUT: 325*fcf3ce44SJohn Forte * busy_flag = 1 (if device busy) 326*fcf3ce44SJohn Forte * 327*fcf3ce44SJohn Forte * RETURNS: 328*fcf3ce44SJohn Forte * 0 if O.K. 329*fcf3ce44SJohn Forte * non-zero otherwise 330*fcf3ce44SJohn Forte */ 331*fcf3ce44SJohn Forte static int 332*fcf3ce44SJohn Forte h_chk_dev_busy(Hotplug_Devlist *hotplug_dev, WWN_list *wwn_list, 333*fcf3ce44SJohn Forte int *busy_flag, int force_flag, int verbose_flag) 334*fcf3ce44SJohn Forte { 335*fcf3ce44SJohn Forte int err; 336*fcf3ce44SJohn Forte struct dlist *dlist; 337*fcf3ce44SJohn Forte 338*fcf3ce44SJohn Forte if (hotplug_dev->dev_type == DTYPE_ESI) { 339*fcf3ce44SJohn Forte if ((err = l_offline_photon(hotplug_dev, wwn_list, 340*fcf3ce44SJohn Forte force_flag, verbose_flag)) != 0) { 341*fcf3ce44SJohn Forte if (err == L_DEV_BUSY) { 342*fcf3ce44SJohn Forte *busy_flag = 1; 343*fcf3ce44SJohn Forte } else { 344*fcf3ce44SJohn Forte return (err); 345*fcf3ce44SJohn Forte } 346*fcf3ce44SJohn Forte } 347*fcf3ce44SJohn Forte for (dlist = hotplug_dev->dlhead; 348*fcf3ce44SJohn Forte dlist != NULL; dlist = dlist->next) { 349*fcf3ce44SJohn Forte (void) g_online_drive(dlist->multipath, 350*fcf3ce44SJohn Forte force_flag); 351*fcf3ce44SJohn Forte } 352*fcf3ce44SJohn Forte } else { 353*fcf3ce44SJohn Forte if ((err = g_offline_drive(hotplug_dev->dlhead, 354*fcf3ce44SJohn Forte force_flag)) != 0) { 355*fcf3ce44SJohn Forte if (err == L_DEV_BUSY) { 356*fcf3ce44SJohn Forte *busy_flag = 1; 357*fcf3ce44SJohn Forte } else { 358*fcf3ce44SJohn Forte return (err); 359*fcf3ce44SJohn Forte } 360*fcf3ce44SJohn Forte } 361*fcf3ce44SJohn Forte (void) g_online_drive(hotplug_dev->dlhead, force_flag); 362*fcf3ce44SJohn Forte } 363*fcf3ce44SJohn Forte return (0); 364*fcf3ce44SJohn Forte } 365*fcf3ce44SJohn Forte 366*fcf3ce44SJohn Forte 367*fcf3ce44SJohn Forte 368*fcf3ce44SJohn Forte /* 369*fcf3ce44SJohn Forte * prints the given list to stdout, 370*fcf3ce44SJohn Forte * gets the input from user whether 371*fcf3ce44SJohn Forte * to skip the busy devices or quit 372*fcf3ce44SJohn Forte * and passes that input to the calling 373*fcf3ce44SJohn Forte * function. 374*fcf3ce44SJohn Forte * 375*fcf3ce44SJohn Forte * OUTPUT: 376*fcf3ce44SJohn Forte * int *action 377*fcf3ce44SJohn Forte * s = Skip 378*fcf3ce44SJohn Forte * q = Quit 379*fcf3ce44SJohn Forte * 380*fcf3ce44SJohn Forte * RETURNS: 381*fcf3ce44SJohn Forte * 0 if OK 382*fcf3ce44SJohn Forte * non-zero otherwise 383*fcf3ce44SJohn Forte */ 384*fcf3ce44SJohn Forte static int 385*fcf3ce44SJohn Forte h_print_list(Hotplug_Devlist *bsyRsrv_disk_list, int *action, int enc_type) 386*fcf3ce44SJohn Forte { 387*fcf3ce44SJohn Forte Hotplug_Devlist *list; 388*fcf3ce44SJohn Forte int i = 1; 389*fcf3ce44SJohn Forte char choice[2]; 390*fcf3ce44SJohn Forte 391*fcf3ce44SJohn Forte (void) fprintf(stdout, 392*fcf3ce44SJohn Forte MSGSTR(5504, "The list of devices being used" 393*fcf3ce44SJohn Forte " (either busy or reserved) by the host:\n")); 394*fcf3ce44SJohn Forte for (list = bsyRsrv_disk_list; list != NULL; list = list->next, i++) { 395*fcf3ce44SJohn Forte if ((list->dev_type == DTYPE_DIRECT) && 396*fcf3ce44SJohn Forte (list->dev_location == SENA)) { 397*fcf3ce44SJohn Forte if (list->f_flag != NULL) { 398*fcf3ce44SJohn Forte if (enc_type == DAK_ENC_TYPE) { 399*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5663, 400*fcf3ce44SJohn Forte " %d: Box Name: \"%s\" slot %d\n"), 401*fcf3ce44SJohn Forte i, list->box_name, list->slot); 402*fcf3ce44SJohn Forte } else { 403*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(137, 404*fcf3ce44SJohn Forte " %d: Box Name: \"%s\" front slot %d\n"), 405*fcf3ce44SJohn Forte i, list->box_name, list->slot); 406*fcf3ce44SJohn Forte } 407*fcf3ce44SJohn Forte } else { 408*fcf3ce44SJohn Forte if (enc_type == DAK_ENC_TYPE) { 409*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5663, 410*fcf3ce44SJohn Forte " %d: Box Name: \"%s\" slot %d\n"), 411*fcf3ce44SJohn Forte i, list->box_name, list->slot + (MAX_DRIVES_DAK/2)); 412*fcf3ce44SJohn Forte } else { 413*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(136, 414*fcf3ce44SJohn Forte " %d: Box Name: \"%s\" rear slot %d\n"), 415*fcf3ce44SJohn Forte i, list->box_name, list->slot); 416*fcf3ce44SJohn Forte } 417*fcf3ce44SJohn Forte } 418*fcf3ce44SJohn Forte } else if (((list->dev_type == DTYPE_DIRECT) || 419*fcf3ce44SJohn Forte (list->dev_type == DTYPE_SEQUENTIAL)) && 420*fcf3ce44SJohn Forte (list->dev_location == NON_SENA)) { 421*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5505, 422*fcf3ce44SJohn Forte " %d: Device %s\n"), 423*fcf3ce44SJohn Forte i, list->dev_name); 424*fcf3ce44SJohn Forte } else if (list->dev_type == DTYPE_ESI) { 425*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5506, 426*fcf3ce44SJohn Forte " %d: Box: %s\n"), 427*fcf3ce44SJohn Forte i, list->box_name); 428*fcf3ce44SJohn Forte } 429*fcf3ce44SJohn Forte } 430*fcf3ce44SJohn Forte 431*fcf3ce44SJohn Forte /* Get the user input and continue accordingly. */ 432*fcf3ce44SJohn Forte (void) fprintf(stdout, 433*fcf3ce44SJohn Forte MSGSTR(5507, 434*fcf3ce44SJohn Forte "\n\nPlease enter 's' or <CR> to Skip the \"busy/reserved\"" 435*fcf3ce44SJohn Forte " device(s) or\n'q' to Quit and run the" 436*fcf3ce44SJohn Forte " subcommand with\n-F (force) option. [Default: s]: ")); 437*fcf3ce44SJohn Forte for (;;) { 438*fcf3ce44SJohn Forte (void) gets(choice); 439*fcf3ce44SJohn Forte if (choice[0] == 'q' || choice[0] == 'Q' || 440*fcf3ce44SJohn Forte choice[0] == 's' || choice[0] == 'S' || 441*fcf3ce44SJohn Forte choice[0] == '\0') { 442*fcf3ce44SJohn Forte break; 443*fcf3ce44SJohn Forte } 444*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5508, 445*fcf3ce44SJohn Forte " Enter an appropriate option [s,<CR>,q]: ")); 446*fcf3ce44SJohn Forte } 447*fcf3ce44SJohn Forte if (choice[0] == 'q' || choice[0] == 'Q') { 448*fcf3ce44SJohn Forte *action = QUIT; 449*fcf3ce44SJohn Forte } else { 450*fcf3ce44SJohn Forte *action = SKIP; 451*fcf3ce44SJohn Forte } 452*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n\n"); 453*fcf3ce44SJohn Forte return (0); 454*fcf3ce44SJohn Forte } 455*fcf3ce44SJohn Forte 456*fcf3ce44SJohn Forte 457*fcf3ce44SJohn Forte 458*fcf3ce44SJohn Forte /* 459*fcf3ce44SJohn Forte * prints the warning message. 460*fcf3ce44SJohn Forte * 461*fcf3ce44SJohn Forte * RETURNS: 462*fcf3ce44SJohn Forte * None. 463*fcf3ce44SJohn Forte */ 464*fcf3ce44SJohn Forte static void 465*fcf3ce44SJohn Forte h_prt_warning() 466*fcf3ce44SJohn Forte { 467*fcf3ce44SJohn Forte (void) fprintf(stderr, 468*fcf3ce44SJohn Forte MSGSTR(5509, 469*fcf3ce44SJohn Forte "\n WARNING!!! Please ensure that no" 470*fcf3ce44SJohn Forte " filesystems are mounted on these device(s).\n" 471*fcf3ce44SJohn Forte " All data on these devices should have been" 472*fcf3ce44SJohn Forte " backed up.\n\n\n")); 473*fcf3ce44SJohn Forte } 474*fcf3ce44SJohn Forte 475*fcf3ce44SJohn Forte 476*fcf3ce44SJohn Forte 477*fcf3ce44SJohn Forte /* 478*fcf3ce44SJohn Forte * handle helper-mode hotplug commands 479*fcf3ce44SJohn Forte * 480*fcf3ce44SJohn Forte * RETURNS: 481*fcf3ce44SJohn Forte * 0 if OK 482*fcf3ce44SJohn Forte * non-zero otherwise 483*fcf3ce44SJohn Forte */ 484*fcf3ce44SJohn Forte int 485*fcf3ce44SJohn Forte hotplug(int todo, char **argv, int verbose_flag, int force_flag) 486*fcf3ce44SJohn Forte { 487*fcf3ce44SJohn Forte char ses_path[MAXPATHLEN], dev_path[MAXPATHLEN]; 488*fcf3ce44SJohn Forte char *path_phys = NULL, code, node_wwn_s[WWN_S_LEN]; 489*fcf3ce44SJohn Forte char inq_path[MAXNAMELEN], *ptr = NULL; 490*fcf3ce44SJohn Forte uchar_t node_wwn[WWN_SIZE], port_wwn[WWN_SIZE]; 491*fcf3ce44SJohn Forte int tid, slot, path_index, dtype, f_r, err = 0; 492*fcf3ce44SJohn Forte int al_pa, i, dev_location, found_nullwwn = 0; 493*fcf3ce44SJohn Forte int busy_flag = 0, reserve_flag = 0, action = 0; 494*fcf3ce44SJohn Forte int pathcnt = 1; 495*fcf3ce44SJohn Forte L_state l_state; 496*fcf3ce44SJohn Forte gfc_map_t map; 497*fcf3ce44SJohn Forte Path_struct *path_struct; 498*fcf3ce44SJohn Forte WWN_list *wwn_list = NULL; 499*fcf3ce44SJohn Forte Box_list *box_list; 500*fcf3ce44SJohn Forte Hotplug_Devlist *disk_list, *disk_list_head, *disk_list_tail; 501*fcf3ce44SJohn Forte Hotplug_Devlist *bsyRsrv_dskLst_head, *bsyRsrv_dskLst_tail; 502*fcf3ce44SJohn Forte int enc_type; 503*fcf3ce44SJohn Forte L_inquiry inq; 504*fcf3ce44SJohn Forte char *physpath; 505*fcf3ce44SJohn Forte Path_struct *p_pathstruct; 506*fcf3ce44SJohn Forte char temp2path[MAXPATHLEN]; 507*fcf3ce44SJohn Forte mp_pathlist_t pathlist; 508*fcf3ce44SJohn Forte int p_pw = 0, p_on = 0, p_st = 0; 509*fcf3ce44SJohn Forte 510*fcf3ce44SJohn Forte /* Initialize structures and pointers here */ 511*fcf3ce44SJohn Forte disk_list_head = disk_list_tail = (Hotplug_Devlist *)NULL; 512*fcf3ce44SJohn Forte bsyRsrv_dskLst_head = (Hotplug_Devlist *)NULL; 513*fcf3ce44SJohn Forte bsyRsrv_dskLst_tail = (Hotplug_Devlist *)NULL; 514*fcf3ce44SJohn Forte map.dev_addr = NULL; 515*fcf3ce44SJohn Forte 516*fcf3ce44SJohn Forte #ifdef DEBUG 517*fcf3ce44SJohn Forte (void) fprintf(stderr, 518*fcf3ce44SJohn Forte "DEBUG: luxadm: hotplug() entering for \"%s\" ...\n", 519*fcf3ce44SJohn Forte argv[0] ? argv[0] : "<null ptr>"); 520*fcf3ce44SJohn Forte #endif 521*fcf3ce44SJohn Forte if ((err = l_get_box_list(&box_list, 0)) != 0) { 522*fcf3ce44SJohn Forte return (err); 523*fcf3ce44SJohn Forte } 524*fcf3ce44SJohn Forte 525*fcf3ce44SJohn Forte if (todo == REMOVE_DEVICE) { 526*fcf3ce44SJohn Forte (void) h_prt_warning(); 527*fcf3ce44SJohn Forte } 528*fcf3ce44SJohn Forte 529*fcf3ce44SJohn Forte /* 530*fcf3ce44SJohn Forte * At this point user want to insert or remove 531*fcf3ce44SJohn Forte * one or more pathnames they've specified. 532*fcf3ce44SJohn Forte */ 533*fcf3ce44SJohn Forte if ((err = g_get_wwn_list(&wwn_list, verbose_flag)) != 0) { 534*fcf3ce44SJohn Forte (void) l_free_box_list(&box_list); 535*fcf3ce44SJohn Forte return (err); 536*fcf3ce44SJohn Forte } 537*fcf3ce44SJohn Forte for (path_index = 0; argv[path_index] != NULL; path_index++) { 538*fcf3ce44SJohn Forte if ((err = l_convert_name(argv[path_index], &path_phys, 539*fcf3ce44SJohn Forte &path_struct, verbose_flag)) != 0) { 540*fcf3ce44SJohn Forte /* Make sure we have a device path. */ 541*fcf3ce44SJohn Forte (void) strcpy(inq_path, argv[path_index]); 542*fcf3ce44SJohn Forte if (((ptr = strstr(inq_path, ",")) != NULL) && 543*fcf3ce44SJohn Forte ((*(ptr + 1) == 'f') || (*(ptr + 1) == 'r') || 544*fcf3ce44SJohn Forte (*(ptr +1) == 's')) && 545*fcf3ce44SJohn Forte todo == REMOVE_DEVICE) { 546*fcf3ce44SJohn Forte if (err != -1) { 547*fcf3ce44SJohn Forte (void) print_errString(err, 548*fcf3ce44SJohn Forte argv[path_index]); 549*fcf3ce44SJohn Forte err = 0; 550*fcf3ce44SJohn Forte continue; 551*fcf3ce44SJohn Forte } 552*fcf3ce44SJohn Forte *ptr = NULL; 553*fcf3ce44SJohn Forte slot = path_struct->slot; 554*fcf3ce44SJohn Forte f_r = path_struct->f_flag; 555*fcf3ce44SJohn Forte if ((err = l_convert_name(inq_path, &path_phys, 556*fcf3ce44SJohn Forte &path_struct, verbose_flag)) != 0) { 557*fcf3ce44SJohn Forte (void) fprintf(stderr, "\n"); 558*fcf3ce44SJohn Forte (void) fprintf(stderr, 559*fcf3ce44SJohn Forte MSGSTR(33, 560*fcf3ce44SJohn Forte " Error: converting" 561*fcf3ce44SJohn Forte " %s to physical path.\n" 562*fcf3ce44SJohn Forte " Invalid pathname.\n"), 563*fcf3ce44SJohn Forte argv[path_index]); 564*fcf3ce44SJohn Forte if (err != -1) { 565*fcf3ce44SJohn Forte (void) print_errString(err, 566*fcf3ce44SJohn Forte argv[path_index]); 567*fcf3ce44SJohn Forte } 568*fcf3ce44SJohn Forte err = 0; 569*fcf3ce44SJohn Forte continue; 570*fcf3ce44SJohn Forte } 571*fcf3ce44SJohn Forte if ((err = print_devState(argv[path_index], 572*fcf3ce44SJohn Forte path_struct->p_physical_path, 573*fcf3ce44SJohn Forte f_r, slot, verbose_flag)) != 0) { 574*fcf3ce44SJohn Forte err = 0; 575*fcf3ce44SJohn Forte continue; 576*fcf3ce44SJohn Forte } 577*fcf3ce44SJohn Forte } 578*fcf3ce44SJohn Forte if (path_struct->ib_path_flag) { 579*fcf3ce44SJohn Forte path_phys = path_struct->p_physical_path; 580*fcf3ce44SJohn Forte } else { 581*fcf3ce44SJohn Forte if (err != -1) { 582*fcf3ce44SJohn Forte (void) print_errString(err, 583*fcf3ce44SJohn Forte argv[path_index]); 584*fcf3ce44SJohn Forte } else { 585*fcf3ce44SJohn Forte (void) fprintf(stderr, "\n"); 586*fcf3ce44SJohn Forte (void) fprintf(stderr, 587*fcf3ce44SJohn Forte MSGSTR(33, 588*fcf3ce44SJohn Forte " Error: converting" 589*fcf3ce44SJohn Forte " %s to physical path.\n" 590*fcf3ce44SJohn Forte " Invalid pathname.\n"), 591*fcf3ce44SJohn Forte argv[path_index]); 592*fcf3ce44SJohn Forte } 593*fcf3ce44SJohn Forte err = 0; 594*fcf3ce44SJohn Forte continue; 595*fcf3ce44SJohn Forte } 596*fcf3ce44SJohn Forte } 597*fcf3ce44SJohn Forte if (path_struct->slot_valid || 598*fcf3ce44SJohn Forte strstr(path_phys, DRV_NAME_SSD)) { 599*fcf3ce44SJohn Forte dtype = DTYPE_DIRECT; 600*fcf3ce44SJohn Forte } else if (strstr(path_phys, SLSH_DRV_NAME_ST)) { 601*fcf3ce44SJohn Forte dtype = DTYPE_SEQUENTIAL; 602*fcf3ce44SJohn Forte } else { 603*fcf3ce44SJohn Forte dtype = DTYPE_ESI; 604*fcf3ce44SJohn Forte } 605*fcf3ce44SJohn Forte 606*fcf3ce44SJohn Forte if (strstr(path_phys, SCSI_VHCI) != NULL) { 607*fcf3ce44SJohn Forte /* obtain phci */ 608*fcf3ce44SJohn Forte (void) strcpy(temp2path, path_phys); 609*fcf3ce44SJohn Forte if (err = g_get_pathlist(temp2path, &pathlist)) { 610*fcf3ce44SJohn Forte (void) print_errString(err, NULL); 611*fcf3ce44SJohn Forte exit(-1); 612*fcf3ce44SJohn Forte } 613*fcf3ce44SJohn Forte pathcnt = pathlist.path_count; 614*fcf3ce44SJohn Forte p_pw = p_on = p_st = 0; 615*fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) { 616*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state < 617*fcf3ce44SJohn Forte MAXPATHSTATE) { 618*fcf3ce44SJohn Forte if (strstr(pathlist.path_info[i]. 619*fcf3ce44SJohn Forte path_addr, 620*fcf3ce44SJohn Forte path_struct->argv) != NULL) { 621*fcf3ce44SJohn Forte p_pw = i; 622*fcf3ce44SJohn Forte break; 623*fcf3ce44SJohn Forte } 624*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state == 625*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 626*fcf3ce44SJohn Forte p_on = i; 627*fcf3ce44SJohn Forte } 628*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state == 629*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_STANDBY) { 630*fcf3ce44SJohn Forte p_st = i; 631*fcf3ce44SJohn Forte } 632*fcf3ce44SJohn Forte } 633*fcf3ce44SJohn Forte } 634*fcf3ce44SJohn Forte if (strstr(pathlist.path_info[p_pw].path_addr, 635*fcf3ce44SJohn Forte path_struct->argv) != NULL) { 636*fcf3ce44SJohn Forte /* matching input pwwn */ 637*fcf3ce44SJohn Forte (void) strcpy(temp2path, 638*fcf3ce44SJohn Forte pathlist.path_info[p_pw].path_hba); 639*fcf3ce44SJohn Forte } else if (pathlist.path_info[p_on].path_state == 640*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 641*fcf3ce44SJohn Forte /* on_line path */ 642*fcf3ce44SJohn Forte (void) strcpy(temp2path, 643*fcf3ce44SJohn Forte pathlist.path_info[p_on].path_hba); 644*fcf3ce44SJohn Forte } else { 645*fcf3ce44SJohn Forte /* standby or path0 */ 646*fcf3ce44SJohn Forte (void) strcpy(temp2path, 647*fcf3ce44SJohn Forte pathlist.path_info[p_st].path_hba); 648*fcf3ce44SJohn Forte } 649*fcf3ce44SJohn Forte free(pathlist.path_info); 650*fcf3ce44SJohn Forte (void) strcat(temp2path, FC_CTLR); 651*fcf3ce44SJohn Forte } else { 652*fcf3ce44SJohn Forte (void) strcpy(temp2path, path_phys); 653*fcf3ce44SJohn Forte } 654*fcf3ce44SJohn Forte 655*fcf3ce44SJohn Forte if ((err = g_get_dev_map(temp2path, &map, verbose_flag)) 656*fcf3ce44SJohn Forte != 0) { 657*fcf3ce44SJohn Forte return (err); 658*fcf3ce44SJohn Forte } 659*fcf3ce44SJohn Forte 660*fcf3ce44SJohn Forte if ((map.hba_addr.port_topology == FC_TOP_PUBLIC_LOOP) || 661*fcf3ce44SJohn Forte (map.hba_addr.port_topology == FC_TOP_FABRIC)) { 662*fcf3ce44SJohn Forte /* public or fabric loop device */ 663*fcf3ce44SJohn Forte free((void *)map.dev_addr); 664*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(5540, 665*fcf3ce44SJohn Forte "This operation is not " 666*fcf3ce44SJohn Forte "supported in this topology.\n")); 667*fcf3ce44SJohn Forte exit(-1); 668*fcf3ce44SJohn Forte } 669*fcf3ce44SJohn Forte 670*fcf3ce44SJohn Forte if (todo == REPLACE_DEVICE) { 671*fcf3ce44SJohn Forte (void) fprintf(stderr, 672*fcf3ce44SJohn Forte MSGSTR(5511, 673*fcf3ce44SJohn Forte "Error:" 674*fcf3ce44SJohn Forte " replace_device is not supported" 675*fcf3ce44SJohn Forte " on this subsystem.\n")); 676*fcf3ce44SJohn Forte exit(-1); 677*fcf3ce44SJohn Forte } 678*fcf3ce44SJohn Forte 679*fcf3ce44SJohn Forte if ((todo == REMOVE_DEVICE) && 680*fcf3ce44SJohn Forte (dtype == DTYPE_DIRECT || 681*fcf3ce44SJohn Forte dtype == DTYPE_SEQUENTIAL || 682*fcf3ce44SJohn Forte dtype == DTYPE_UNKNOWN)) { 683*fcf3ce44SJohn Forte if (l_chk_null_wwn(path_struct, ses_path, 684*fcf3ce44SJohn Forte &l_state, verbose_flag) == 1) { 685*fcf3ce44SJohn Forte found_nullwwn = 1; 686*fcf3ce44SJohn Forte /* 687*fcf3ce44SJohn Forte * set dev_path to NULL, 688*fcf3ce44SJohn Forte * if disk has null wwn. 689*fcf3ce44SJohn Forte */ 690*fcf3ce44SJohn Forte *dev_path = NULL; 691*fcf3ce44SJohn Forte dev_location = SENA; 692*fcf3ce44SJohn Forte goto getinfo; 693*fcf3ce44SJohn Forte } 694*fcf3ce44SJohn Forte } 695*fcf3ce44SJohn Forte 696*fcf3ce44SJohn Forte (void) strcpy(ses_path, path_phys); 697*fcf3ce44SJohn Forte 698*fcf3ce44SJohn Forte if (strstr(ses_path, "ses") == NULL && 699*fcf3ce44SJohn Forte l_get_ses_path(path_phys, ses_path, &map, 700*fcf3ce44SJohn Forte verbose_flag) != 0) { 701*fcf3ce44SJohn Forte 702*fcf3ce44SJohn Forte /* Could be a non-photon disk device */ 703*fcf3ce44SJohn Forte if ((todo == REMOVE_DEVICE) && 704*fcf3ce44SJohn Forte (dtype == DTYPE_DIRECT || 705*fcf3ce44SJohn Forte dtype == DTYPE_SEQUENTIAL)) { 706*fcf3ce44SJohn Forte dev_location = NON_SENA; 707*fcf3ce44SJohn Forte 708*fcf3ce44SJohn Forte if ((err = h_get_fcdev_state(argv[path_index], 709*fcf3ce44SJohn Forte path_phys, force_flag, 710*fcf3ce44SJohn Forte &busy_flag, &reserve_flag, 711*fcf3ce44SJohn Forte verbose_flag)) != 0) { 712*fcf3ce44SJohn Forte goto done; 713*fcf3ce44SJohn Forte } 714*fcf3ce44SJohn Forte (void) strcpy(dev_path, path_phys); 715*fcf3ce44SJohn Forte if ((err = g_get_wwn(dev_path, port_wwn, 716*fcf3ce44SJohn Forte node_wwn, &al_pa, 717*fcf3ce44SJohn Forte verbose_flag)) != 0) { 718*fcf3ce44SJohn Forte goto done; 719*fcf3ce44SJohn Forte } 720*fcf3ce44SJohn Forte (void) sprintf(node_wwn_s, 721*fcf3ce44SJohn Forte "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x", 722*fcf3ce44SJohn Forte node_wwn[0], node_wwn[1], node_wwn[2], 723*fcf3ce44SJohn Forte node_wwn[3], node_wwn[4], node_wwn[5], 724*fcf3ce44SJohn Forte node_wwn[6], node_wwn[7]); 725*fcf3ce44SJohn Forte tid = g_sf_alpa_to_switch[al_pa]; 726*fcf3ce44SJohn Forte goto loop; 727*fcf3ce44SJohn Forte } 728*fcf3ce44SJohn Forte continue; 729*fcf3ce44SJohn Forte } 730*fcf3ce44SJohn Forte 731*fcf3ce44SJohn Forte if (strstr(ses_path, "ses") != NULL) { 732*fcf3ce44SJohn Forte dev_location = SENA; 733*fcf3ce44SJohn Forte if ((err = l_convert_name(ses_path, &physpath, 734*fcf3ce44SJohn Forte &p_pathstruct, 0)) != 0) { 735*fcf3ce44SJohn Forte free(physpath); 736*fcf3ce44SJohn Forte free(p_pathstruct); 737*fcf3ce44SJohn Forte goto done; 738*fcf3ce44SJohn Forte 739*fcf3ce44SJohn Forte } 740*fcf3ce44SJohn Forte if ((err = g_get_inquiry(physpath, &inq)) != 0) { 741*fcf3ce44SJohn Forte free(physpath); 742*fcf3ce44SJohn Forte free(p_pathstruct); 743*fcf3ce44SJohn Forte goto done; 744*fcf3ce44SJohn Forte } 745*fcf3ce44SJohn Forte enc_type = l_get_enc_type(inq); 746*fcf3ce44SJohn Forte 747*fcf3ce44SJohn Forte } 748*fcf3ce44SJohn Forte if ((err = l_get_status(ses_path, 749*fcf3ce44SJohn Forte &l_state, verbose_flag)) != 0) { 750*fcf3ce44SJohn Forte goto done; 751*fcf3ce44SJohn Forte } 752*fcf3ce44SJohn Forte if (dtype == DTYPE_ESI) { 753*fcf3ce44SJohn Forte /* could be removing a photon */ 754*fcf3ce44SJohn Forte if (todo == REMOVE_DEVICE) { 755*fcf3ce44SJohn Forte /* 756*fcf3ce44SJohn Forte * Need the select ID (tid) for the IB. 757*fcf3ce44SJohn Forte */ 758*fcf3ce44SJohn Forte if ((err = g_get_wwn(ses_path, port_wwn, 759*fcf3ce44SJohn Forte node_wwn, &al_pa, 760*fcf3ce44SJohn Forte verbose_flag)) != 0) { 761*fcf3ce44SJohn Forte goto done; 762*fcf3ce44SJohn Forte } 763*fcf3ce44SJohn Forte (void) sprintf(node_wwn_s, 764*fcf3ce44SJohn Forte "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x", 765*fcf3ce44SJohn Forte node_wwn[0], node_wwn[1], node_wwn[2], 766*fcf3ce44SJohn Forte node_wwn[3], node_wwn[4], node_wwn[5], 767*fcf3ce44SJohn Forte node_wwn[6], node_wwn[7]); 768*fcf3ce44SJohn Forte tid = g_sf_alpa_to_switch[al_pa]; 769*fcf3ce44SJohn Forte *dev_path = '\0'; 770*fcf3ce44SJohn Forte /* 771*fcf3ce44SJohn Forte * Check if any disk in this photon 772*fcf3ce44SJohn Forte * is reserved by another host 773*fcf3ce44SJohn Forte */ 774*fcf3ce44SJohn Forte if (!force_flag) { 775*fcf3ce44SJohn Forte for ( 776*fcf3ce44SJohn Forte i = 0; 777*fcf3ce44SJohn Forte i < l_state.total_num_drv/2; 778*fcf3ce44SJohn Forte i++) { 779*fcf3ce44SJohn Forte if ((l_state.drv_front[i].g_disk_state.d_state_flags[PORT_A] & 780*fcf3ce44SJohn Forte L_RESERVED) || 781*fcf3ce44SJohn Forte (l_state.drv_front[i].g_disk_state.d_state_flags[PORT_B] & 782*fcf3ce44SJohn Forte L_RESERVED) || 783*fcf3ce44SJohn Forte (l_state.drv_rear[i].g_disk_state.d_state_flags[PORT_A] & 784*fcf3ce44SJohn Forte L_RESERVED) || 785*fcf3ce44SJohn Forte (l_state.drv_rear[i].g_disk_state.d_state_flags[PORT_B] & 786*fcf3ce44SJohn Forte L_RESERVED)) { 787*fcf3ce44SJohn Forte reserve_flag = 1; 788*fcf3ce44SJohn Forte } 789*fcf3ce44SJohn Forte } 790*fcf3ce44SJohn Forte } 791*fcf3ce44SJohn Forte goto loop; 792*fcf3ce44SJohn Forte } 793*fcf3ce44SJohn Forte (void) fprintf(stderr, 794*fcf3ce44SJohn Forte MSGSTR(5512, 795*fcf3ce44SJohn Forte "Error: %s already exists!!\n"), 796*fcf3ce44SJohn Forte argv[path_index]); 797*fcf3ce44SJohn Forte goto done; 798*fcf3ce44SJohn Forte } 799*fcf3ce44SJohn Forte getinfo: 800*fcf3ce44SJohn Forte if (!path_struct->slot_valid) { 801*fcf3ce44SJohn Forte /* We are passing the disks path */ 802*fcf3ce44SJohn Forte if ((err = l_get_slot(path_struct, &l_state, 803*fcf3ce44SJohn Forte verbose_flag)) != 0) { 804*fcf3ce44SJohn Forte goto done; 805*fcf3ce44SJohn Forte } 806*fcf3ce44SJohn Forte } 807*fcf3ce44SJohn Forte 808*fcf3ce44SJohn Forte slot = path_struct->slot; 809*fcf3ce44SJohn Forte if (path_struct->f_flag) { 810*fcf3ce44SJohn Forte tid = l_state.drv_front[slot].ib_status.sel_id; 811*fcf3ce44SJohn Forte code = l_state.drv_front[slot].ib_status.code; 812*fcf3ce44SJohn Forte (void) strcpy(node_wwn_s, 813*fcf3ce44SJohn Forte l_state.drv_front[slot].g_disk_state.node_wwn_s); 814*fcf3ce44SJohn Forte } else { 815*fcf3ce44SJohn Forte tid = l_state.drv_rear[slot].ib_status.sel_id; 816*fcf3ce44SJohn Forte code = l_state.drv_rear[slot].ib_status.code; 817*fcf3ce44SJohn Forte (void) strcpy(node_wwn_s, 818*fcf3ce44SJohn Forte l_state.drv_rear[slot].g_disk_state.node_wwn_s); 819*fcf3ce44SJohn Forte } 820*fcf3ce44SJohn Forte 821*fcf3ce44SJohn Forte if (found_nullwwn) { 822*fcf3ce44SJohn Forte goto loop; 823*fcf3ce44SJohn Forte } 824*fcf3ce44SJohn Forte 825*fcf3ce44SJohn Forte l_make_node(ses_path, tid, dev_path, &map, 0); 826*fcf3ce44SJohn Forte 827*fcf3ce44SJohn Forte if ((todo == INSERT_DEVICE) && 828*fcf3ce44SJohn Forte (g_device_in_map(&map, tid) || 829*fcf3ce44SJohn Forte (code != S_NOT_INSTALLED))) { 830*fcf3ce44SJohn Forte (void) fprintf(stderr, 831*fcf3ce44SJohn Forte MSGSTR(5513, "\nNotice: %s may " 832*fcf3ce44SJohn Forte "already be present.\n"), 833*fcf3ce44SJohn Forte argv[path_index]); 834*fcf3ce44SJohn Forte if (path_struct->f_flag) { 835*fcf3ce44SJohn Forte if ((l_state.drv_front[slot].l_state_flag 836*fcf3ce44SJohn Forte != L_NO_PATH_FOUND) && 837*fcf3ce44SJohn Forte (!l_state.drv_front[slot].ib_status.dev_off)) 838*fcf3ce44SJohn Forte continue; 839*fcf3ce44SJohn Forte } else { 840*fcf3ce44SJohn Forte if ((l_state.drv_rear[slot].l_state_flag 841*fcf3ce44SJohn Forte != L_NO_PATH_FOUND) && 842*fcf3ce44SJohn Forte (!l_state.drv_rear[slot].ib_status.dev_off)) 843*fcf3ce44SJohn Forte continue; 844*fcf3ce44SJohn Forte } 845*fcf3ce44SJohn Forte } 846*fcf3ce44SJohn Forte 847*fcf3ce44SJohn Forte /* Check if disk is reserved */ 848*fcf3ce44SJohn Forte if ((todo == REMOVE_DEVICE) && (!force_flag)) { 849*fcf3ce44SJohn Forte if (path_struct->f_flag) { 850*fcf3ce44SJohn Forte if ((l_state.drv_front[slot].g_disk_state.d_state_flags[PORT_A] & 851*fcf3ce44SJohn Forte L_RESERVED) || 852*fcf3ce44SJohn Forte (l_state.drv_front[slot].g_disk_state.d_state_flags[PORT_B] & 853*fcf3ce44SJohn Forte L_RESERVED)) { 854*fcf3ce44SJohn Forte reserve_flag = 1; 855*fcf3ce44SJohn Forte } 856*fcf3ce44SJohn Forte } else { 857*fcf3ce44SJohn Forte if ((l_state.drv_rear[slot].g_disk_state.d_state_flags[PORT_A] & 858*fcf3ce44SJohn Forte L_RESERVED) || 859*fcf3ce44SJohn Forte (l_state.drv_rear[slot].g_disk_state.d_state_flags[PORT_B] & 860*fcf3ce44SJohn Forte L_RESERVED)) { 861*fcf3ce44SJohn Forte reserve_flag = 1; 862*fcf3ce44SJohn Forte } 863*fcf3ce44SJohn Forte } 864*fcf3ce44SJohn Forte } 865*fcf3ce44SJohn Forte 866*fcf3ce44SJohn Forte loop: 867*fcf3ce44SJohn Forte if ((disk_list = (Hotplug_Devlist *) 868*fcf3ce44SJohn Forte calloc(1, sizeof (Hotplug_Devlist))) == NULL) { 869*fcf3ce44SJohn Forte (void) print_errString(L_MALLOC_FAILED, NULL); 870*fcf3ce44SJohn Forte goto done; 871*fcf3ce44SJohn Forte } 872*fcf3ce44SJohn Forte 873*fcf3ce44SJohn Forte /* 874*fcf3ce44SJohn Forte * dev_path is NULL when removing a whole encloser. We 875*fcf3ce44SJohn Forte * don't want to call g_get_multipath while removing whole 876*fcf3ce44SJohn Forte * enclosure. Its being taken care later in the code path 877*fcf3ce44SJohn Forte */ 878*fcf3ce44SJohn Forte 879*fcf3ce44SJohn Forte if ((todo != INSERT_DEVICE) && (dtype != DTYPE_ESI)) { 880*fcf3ce44SJohn Forte if ((err = g_get_multipath(dev_path, 881*fcf3ce44SJohn Forte &(disk_list->dlhead), 882*fcf3ce44SJohn Forte wwn_list, verbose_flag)) != 0) { 883*fcf3ce44SJohn Forte if (disk_list->dlhead != NULL) { 884*fcf3ce44SJohn Forte (void) g_free_multipath( 885*fcf3ce44SJohn Forte disk_list->dlhead); 886*fcf3ce44SJohn Forte } 887*fcf3ce44SJohn Forte goto done; 888*fcf3ce44SJohn Forte } 889*fcf3ce44SJohn Forte } 890*fcf3ce44SJohn Forte disk_list->dev_type = dtype; 891*fcf3ce44SJohn Forte disk_list->dev_location = dev_location; 892*fcf3ce44SJohn Forte (void) strcpy(disk_list->dev_name, 893*fcf3ce44SJohn Forte argv[path_index]); 894*fcf3ce44SJohn Forte disk_list->tid = tid; 895*fcf3ce44SJohn Forte (void) strcpy(disk_list->node_wwn_s, node_wwn_s); 896*fcf3ce44SJohn Forte if (dev_location == SENA) { 897*fcf3ce44SJohn Forte if ((err = l_get_allses(ses_path, box_list, 898*fcf3ce44SJohn Forte &(disk_list->seslist), 0)) != 0) { 899*fcf3ce44SJohn Forte if (disk_list->seslist != NULL) { 900*fcf3ce44SJohn Forte (void) g_free_multipath(disk_list->seslist); 901*fcf3ce44SJohn Forte } 902*fcf3ce44SJohn Forte goto done; 903*fcf3ce44SJohn Forte } 904*fcf3ce44SJohn Forte (void) strcpy(disk_list->box_name, 905*fcf3ce44SJohn Forte (char *)l_state.ib_tbl.enclosure_name); 906*fcf3ce44SJohn Forte disk_list->slot = slot; 907*fcf3ce44SJohn Forte disk_list->f_flag = path_struct->f_flag; 908*fcf3ce44SJohn Forte } 909*fcf3ce44SJohn Forte if (todo == REMOVE_DEVICE && !force_flag && !reserve_flag) { 910*fcf3ce44SJohn Forte if ((err = h_chk_dev_busy(disk_list, wwn_list, 911*fcf3ce44SJohn Forte &busy_flag, force_flag, verbose_flag)) != 0) { 912*fcf3ce44SJohn Forte goto done; 913*fcf3ce44SJohn Forte } 914*fcf3ce44SJohn Forte } 915*fcf3ce44SJohn Forte 916*fcf3ce44SJohn Forte if (reserve_flag || busy_flag) { 917*fcf3ce44SJohn Forte if (reserve_flag) 918*fcf3ce44SJohn Forte disk_list->reserve_flag = 1; 919*fcf3ce44SJohn Forte if (busy_flag) 920*fcf3ce44SJohn Forte disk_list->busy_flag = 1; 921*fcf3ce44SJohn Forte 922*fcf3ce44SJohn Forte if (bsyRsrv_dskLst_head == NULL) { 923*fcf3ce44SJohn Forte bsyRsrv_dskLst_head = 924*fcf3ce44SJohn Forte bsyRsrv_dskLst_tail = disk_list; 925*fcf3ce44SJohn Forte } else { 926*fcf3ce44SJohn Forte disk_list->prev = bsyRsrv_dskLst_tail; 927*fcf3ce44SJohn Forte bsyRsrv_dskLst_tail->next = disk_list; 928*fcf3ce44SJohn Forte bsyRsrv_dskLst_tail = disk_list; 929*fcf3ce44SJohn Forte } 930*fcf3ce44SJohn Forte reserve_flag = 0; 931*fcf3ce44SJohn Forte busy_flag = 0; 932*fcf3ce44SJohn Forte 933*fcf3ce44SJohn Forte } else if (disk_list_head == NULL) { 934*fcf3ce44SJohn Forte disk_list_head = disk_list_tail = disk_list; 935*fcf3ce44SJohn Forte } else { 936*fcf3ce44SJohn Forte disk_list->prev = disk_list_tail; 937*fcf3ce44SJohn Forte disk_list_tail->next = disk_list; 938*fcf3ce44SJohn Forte disk_list_tail = disk_list; 939*fcf3ce44SJohn Forte } 940*fcf3ce44SJohn Forte } 941*fcf3ce44SJohn Forte 942*fcf3ce44SJohn Forte if (bsyRsrv_dskLst_head != NULL) { 943*fcf3ce44SJohn Forte if ((err = h_print_list(bsyRsrv_dskLst_head, 944*fcf3ce44SJohn Forte &action, enc_type)) != 0) { 945*fcf3ce44SJohn Forte goto done; 946*fcf3ce44SJohn Forte } 947*fcf3ce44SJohn Forte if (action == SKIP) { 948*fcf3ce44SJohn Forte (void) h_free_hotplug_dlist(&bsyRsrv_dskLst_head); 949*fcf3ce44SJohn Forte } else if (action == QUIT) { 950*fcf3ce44SJohn Forte goto done; 951*fcf3ce44SJohn Forte } 952*fcf3ce44SJohn Forte } 953*fcf3ce44SJohn Forte if (disk_list_head != NULL) { 954*fcf3ce44SJohn Forte if ((h_print_list_warn(disk_list_head, todo, enc_type)) != 0) { 955*fcf3ce44SJohn Forte goto done; 956*fcf3ce44SJohn Forte } 957*fcf3ce44SJohn Forte if ((err = h_pre_hotplug(&disk_list_head, wwn_list, todo, verbose_flag, 958*fcf3ce44SJohn Forte force_flag)) != 0) { 959*fcf3ce44SJohn Forte goto done; 960*fcf3ce44SJohn Forte } 961*fcf3ce44SJohn Forte if (disk_list_head != NULL) { 962*fcf3ce44SJohn Forte if (todo == REMOVE_DEVICE) { 963*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5514, 964*fcf3ce44SJohn Forte "\nHit <Return> after " 965*fcf3ce44SJohn Forte "removing the device(s).")); 966*fcf3ce44SJohn Forte } else { 967*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5515, 968*fcf3ce44SJohn Forte "\nHit <Return> after " 969*fcf3ce44SJohn Forte "inserting the device(s).")); 970*fcf3ce44SJohn Forte } 971*fcf3ce44SJohn Forte (void) getchar(); 972*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 973*fcf3ce44SJohn Forte if ((err = h_post_hotplug(disk_list_head, wwn_list, 974*fcf3ce44SJohn Forte todo, verbose_flag, force_flag, 975*fcf3ce44SJohn Forte enc_type)) != 0) { 976*fcf3ce44SJohn Forte goto done; 977*fcf3ce44SJohn Forte } 978*fcf3ce44SJohn Forte } 979*fcf3ce44SJohn Forte } 980*fcf3ce44SJohn Forte done: 981*fcf3ce44SJohn Forte (void) l_free_box_list(&box_list); 982*fcf3ce44SJohn Forte (void) g_free_wwn_list(&wwn_list); 983*fcf3ce44SJohn Forte if (err && err != -1) { 984*fcf3ce44SJohn Forte return (err); 985*fcf3ce44SJohn Forte } 986*fcf3ce44SJohn Forte free((void *)map.dev_addr); 987*fcf3ce44SJohn Forte return (0); 988*fcf3ce44SJohn Forte } 989*fcf3ce44SJohn Forte 990*fcf3ce44SJohn Forte 991*fcf3ce44SJohn Forte 992*fcf3ce44SJohn Forte 993*fcf3ce44SJohn Forte /* 994*fcf3ce44SJohn Forte * Internal routine to clean up ../'s in paths. 995*fcf3ce44SJohn Forte * returns 0 if no "../" are left. 996*fcf3ce44SJohn Forte * 997*fcf3ce44SJohn Forte * Wouldn't it be nice if there was a standard system library 998*fcf3ce44SJohn Forte * routine to do this...? 999*fcf3ce44SJohn Forte */ 1000*fcf3ce44SJohn Forte static int 1001*fcf3ce44SJohn Forte cleanup_dotdot_path(char *path) 1002*fcf3ce44SJohn Forte { 1003*fcf3ce44SJohn Forte char holder[MAXPATHLEN]; 1004*fcf3ce44SJohn Forte char *dotdot; 1005*fcf3ce44SJohn Forte char *previous_slash; 1006*fcf3ce44SJohn Forte 1007*fcf3ce44SJohn Forte /* Find the first "/../" in the string */ 1008*fcf3ce44SJohn Forte dotdot = strstr(path, "/../"); 1009*fcf3ce44SJohn Forte if (dotdot == NULL) { 1010*fcf3ce44SJohn Forte return (0); 1011*fcf3ce44SJohn Forte } 1012*fcf3ce44SJohn Forte 1013*fcf3ce44SJohn Forte 1014*fcf3ce44SJohn Forte /* 1015*fcf3ce44SJohn Forte * If the [0] character is '/' and "../" immediatly 1016*fcf3ce44SJohn Forte * follows it, then we can strip the ../ 1017*fcf3ce44SJohn Forte * 1018*fcf3ce44SJohn Forte * /../../foo/bar == /foo/bar 1019*fcf3ce44SJohn Forte * 1020*fcf3ce44SJohn Forte */ 1021*fcf3ce44SJohn Forte if (dotdot == path) { 1022*fcf3ce44SJohn Forte strcpy(holder, &path[3]); /* strip "/.." */ 1023*fcf3ce44SJohn Forte strcpy(path, holder); 1024*fcf3ce44SJohn Forte return (1); 1025*fcf3ce44SJohn Forte } 1026*fcf3ce44SJohn Forte 1027*fcf3ce44SJohn Forte /* 1028*fcf3ce44SJohn Forte * Now look for the LAST "/" before the "/../" 1029*fcf3ce44SJohn Forte * as this is the parent dir we can get rid of. 1030*fcf3ce44SJohn Forte * We do this by temporarily truncating the string 1031*fcf3ce44SJohn Forte * at the '/' just before "../" using the dotdot pointer. 1032*fcf3ce44SJohn Forte */ 1033*fcf3ce44SJohn Forte *dotdot = '\0'; 1034*fcf3ce44SJohn Forte previous_slash = strrchr(path, '/'); 1035*fcf3ce44SJohn Forte if (previous_slash == NULL) { 1036*fcf3ce44SJohn Forte /* 1037*fcf3ce44SJohn Forte * hmm, somethings wrong. path looks something 1038*fcf3ce44SJohn Forte * like "foo/../bar/" so we can't really deal with it. 1039*fcf3ce44SJohn Forte */ 1040*fcf3ce44SJohn Forte return (0); 1041*fcf3ce44SJohn Forte } 1042*fcf3ce44SJohn Forte /* 1043*fcf3ce44SJohn Forte * Now truncate the path just after the previous '/' 1044*fcf3ce44SJohn Forte * and slam everything after the "../" back on 1045*fcf3ce44SJohn Forte */ 1046*fcf3ce44SJohn Forte *(previous_slash+1) = '\0'; 1047*fcf3ce44SJohn Forte (void) strcat(path, dotdot+4); 1048*fcf3ce44SJohn Forte return (1); /* We may have more "../"s */ 1049*fcf3ce44SJohn Forte } 1050*fcf3ce44SJohn Forte 1051*fcf3ce44SJohn Forte 1052*fcf3ce44SJohn Forte /* 1053*fcf3ce44SJohn Forte * Follow symbolic links from the logical device name to 1054*fcf3ce44SJohn Forte * the /devfs physical device name. To be complete, we 1055*fcf3ce44SJohn Forte * handle the case of multiple links. This function 1056*fcf3ce44SJohn Forte * either returns NULL (no links, or some other error), 1057*fcf3ce44SJohn Forte * or the physical device name, alloc'ed on the heap. 1058*fcf3ce44SJohn Forte * 1059*fcf3ce44SJohn Forte * For S10 the physical path may be non-existent. 1060*fcf3ce44SJohn Forte * 1061*fcf3ce44SJohn Forte * NOTE: If the path is relative, it will be forced into 1062*fcf3ce44SJohn Forte * an absolute path by pre-pending the pwd to it. 1063*fcf3ce44SJohn Forte */ 1064*fcf3ce44SJohn Forte char * 1065*fcf3ce44SJohn Forte h_get_physical_name_from_link(char *path) 1066*fcf3ce44SJohn Forte { 1067*fcf3ce44SJohn Forte struct stat stbuf; 1068*fcf3ce44SJohn Forte char source[MAXPATHLEN]; 1069*fcf3ce44SJohn Forte char scratch[MAXPATHLEN]; 1070*fcf3ce44SJohn Forte char pwd[MAXPATHLEN]; 1071*fcf3ce44SJohn Forte char *tmp; 1072*fcf3ce44SJohn Forte int cnt; 1073*fcf3ce44SJohn Forte 1074*fcf3ce44SJohn Forte /* return NULL if path is NULL */ 1075*fcf3ce44SJohn Forte if (path == NULL) { 1076*fcf3ce44SJohn Forte return (NULL); 1077*fcf3ce44SJohn Forte } 1078*fcf3ce44SJohn Forte 1079*fcf3ce44SJohn Forte strcpy(source, path); 1080*fcf3ce44SJohn Forte for (;;) { 1081*fcf3ce44SJohn Forte 1082*fcf3ce44SJohn Forte /* 1083*fcf3ce44SJohn Forte * First make sure the path is absolute. If not, make it. 1084*fcf3ce44SJohn Forte * If it's already an absolute path, we have no need 1085*fcf3ce44SJohn Forte * to determine the cwd, so the program should still 1086*fcf3ce44SJohn Forte * function within security-by-obscurity directories. 1087*fcf3ce44SJohn Forte */ 1088*fcf3ce44SJohn Forte if (source[0] != '/') { 1089*fcf3ce44SJohn Forte tmp = getcwd(pwd, MAXPATHLEN); 1090*fcf3ce44SJohn Forte if (tmp == NULL) { 1091*fcf3ce44SJohn Forte O_DPRINTF("getcwd() failed - %s\n", 1092*fcf3ce44SJohn Forte strerror(errno)); 1093*fcf3ce44SJohn Forte return (NULL); 1094*fcf3ce44SJohn Forte } 1095*fcf3ce44SJohn Forte /* 1096*fcf3ce44SJohn Forte * Handle special case of "./foo/bar" 1097*fcf3ce44SJohn Forte */ 1098*fcf3ce44SJohn Forte if (source[0] == '.' && source[1] == '/') { 1099*fcf3ce44SJohn Forte strcpy(scratch, source+2); 1100*fcf3ce44SJohn Forte } else { /* no "./" so just take everything */ 1101*fcf3ce44SJohn Forte strcpy(scratch, source); 1102*fcf3ce44SJohn Forte } 1103*fcf3ce44SJohn Forte strcpy(source, pwd); 1104*fcf3ce44SJohn Forte (void) strcat(source, "/"); 1105*fcf3ce44SJohn Forte (void) strcat(source, scratch); 1106*fcf3ce44SJohn Forte } 1107*fcf3ce44SJohn Forte 1108*fcf3ce44SJohn Forte /* 1109*fcf3ce44SJohn Forte * Clean up any "../"s that are in the path 1110*fcf3ce44SJohn Forte */ 1111*fcf3ce44SJohn Forte while (cleanup_dotdot_path(source)); 1112*fcf3ce44SJohn Forte 1113*fcf3ce44SJohn Forte /* 1114*fcf3ce44SJohn Forte * source is now an absolute path to the link we're 1115*fcf3ce44SJohn Forte * concerned with 1116*fcf3ce44SJohn Forte * 1117*fcf3ce44SJohn Forte * S10: Do NOT ignore dangling links, pointing to devfs nodes. 1118*fcf3ce44SJohn Forte */ 1119*fcf3ce44SJohn Forte if (strstr(source, "/devices")) { 1120*fcf3ce44SJohn Forte return (g_alloc_string(source)); 1121*fcf3ce44SJohn Forte } 1122*fcf3ce44SJohn Forte 1123*fcf3ce44SJohn Forte if (lstat(source, &stbuf) == -1) { 1124*fcf3ce44SJohn Forte O_DPRINTF("lstat() failed for - %s\n", 1125*fcf3ce44SJohn Forte source, strerror(errno)); 1126*fcf3ce44SJohn Forte return (NULL); 1127*fcf3ce44SJohn Forte } 1128*fcf3ce44SJohn Forte /* 1129*fcf3ce44SJohn Forte * If the file is not a link, we're done one 1130*fcf3ce44SJohn Forte * way or the other. If there were links, 1131*fcf3ce44SJohn Forte * return the full pathname of the resulting 1132*fcf3ce44SJohn Forte * file. 1133*fcf3ce44SJohn Forte * 1134*fcf3ce44SJohn Forte * Note: All of our temp's are on the stack, 1135*fcf3ce44SJohn Forte * so we have to copy the final result to the heap. 1136*fcf3ce44SJohn Forte */ 1137*fcf3ce44SJohn Forte if (!S_ISLNK(stbuf.st_mode)) { 1138*fcf3ce44SJohn Forte return (g_alloc_string(source)); 1139*fcf3ce44SJohn Forte } 1140*fcf3ce44SJohn Forte cnt = readlink(source, scratch, sizeof (scratch)); 1141*fcf3ce44SJohn Forte if (cnt < 0) { 1142*fcf3ce44SJohn Forte O_DPRINTF("readlink() failed - %s\n", 1143*fcf3ce44SJohn Forte strerror(errno)); 1144*fcf3ce44SJohn Forte return (NULL); 1145*fcf3ce44SJohn Forte } 1146*fcf3ce44SJohn Forte /* 1147*fcf3ce44SJohn Forte * scratch is on the heap, and for some reason readlink 1148*fcf3ce44SJohn Forte * doesn't always terminate things properly so we have 1149*fcf3ce44SJohn Forte * to make certain we're properly terminated 1150*fcf3ce44SJohn Forte */ 1151*fcf3ce44SJohn Forte scratch[cnt] = '\0'; 1152*fcf3ce44SJohn Forte 1153*fcf3ce44SJohn Forte /* 1154*fcf3ce44SJohn Forte * Now check to see if the link is relative. If so, 1155*fcf3ce44SJohn Forte * then we have to append it to the directory 1156*fcf3ce44SJohn Forte * which the source was in. (This is non trivial) 1157*fcf3ce44SJohn Forte */ 1158*fcf3ce44SJohn Forte if (scratch[0] != '/') { 1159*fcf3ce44SJohn Forte tmp = strrchr(source, '/'); 1160*fcf3ce44SJohn Forte if (tmp == NULL) { /* Whoa! Something's hosed! */ 1161*fcf3ce44SJohn Forte O_DPRINTF("Internal error... corrupt path.\n"); 1162*fcf3ce44SJohn Forte return (NULL); 1163*fcf3ce44SJohn Forte } 1164*fcf3ce44SJohn Forte /* Now strip off just the directory path */ 1165*fcf3ce44SJohn Forte *(tmp+1) = '\0'; /* Keeping the last '/' */ 1166*fcf3ce44SJohn Forte /* and append the new link */ 1167*fcf3ce44SJohn Forte (void) strcat(source, scratch); 1168*fcf3ce44SJohn Forte /* 1169*fcf3ce44SJohn Forte * Note: At this point, source should have "../"s 1170*fcf3ce44SJohn Forte * but we'll clean it up in the next pass through 1171*fcf3ce44SJohn Forte * the loop. 1172*fcf3ce44SJohn Forte */ 1173*fcf3ce44SJohn Forte } else { 1174*fcf3ce44SJohn Forte /* It's an absolute link so no worries */ 1175*fcf3ce44SJohn Forte strcpy(source, scratch); 1176*fcf3ce44SJohn Forte } 1177*fcf3ce44SJohn Forte } 1178*fcf3ce44SJohn Forte /* Never reach here */ 1179*fcf3ce44SJohn Forte } 1180*fcf3ce44SJohn Forte 1181*fcf3ce44SJohn Forte /* 1182*fcf3ce44SJohn Forte * Function for getting physical pathnames 1183*fcf3ce44SJohn Forte * 1184*fcf3ce44SJohn Forte * For S10 the physical path may not exist at the time devctl calls 1185*fcf3ce44SJohn Forte * are made. So we should not return error if stat fails on /devices path. 1186*fcf3ce44SJohn Forte * 1187*fcf3ce44SJohn Forte * This function can handle 2 different inputs. 1188*fcf3ce44SJohn Forte * 1189*fcf3ce44SJohn Forte * 1) Inputs of the form /dev/rdsk/cNtNdNsN 1190*fcf3ce44SJohn Forte * These are identified by being a link 1191*fcf3ce44SJohn Forte * The physical path they are linked to is returned. 1192*fcf3ce44SJohn Forte * 1193*fcf3ce44SJohn Forte * 2) Inputs of the form /devices/... 1194*fcf3ce44SJohn Forte * These are actual physical names. 1195*fcf3ce44SJohn Forte * They are not converted. 1196*fcf3ce44SJohn Forte */ 1197*fcf3ce44SJohn Forte char * 1198*fcf3ce44SJohn Forte h_get_physical_name(char *path) 1199*fcf3ce44SJohn Forte { 1200*fcf3ce44SJohn Forte struct stat stbuf; 1201*fcf3ce44SJohn Forte char s[MAXPATHLEN]; 1202*fcf3ce44SJohn Forte char savedir[MAXPATHLEN]; 1203*fcf3ce44SJohn Forte char *result = NULL; 1204*fcf3ce44SJohn Forte int status = 0; 1205*fcf3ce44SJohn Forte 1206*fcf3ce44SJohn Forte /* return invalid path if path NULL */ 1207*fcf3ce44SJohn Forte if (path == NULL) { 1208*fcf3ce44SJohn Forte return (NULL); 1209*fcf3ce44SJohn Forte } 1210*fcf3ce44SJohn Forte 1211*fcf3ce44SJohn Forte (void) strcpy(s, path); 1212*fcf3ce44SJohn Forte 1213*fcf3ce44SJohn Forte status = lstat(s, &stbuf); 1214*fcf3ce44SJohn Forte 1215*fcf3ce44SJohn Forte /* 1216*fcf3ce44SJohn Forte * S10: If string is devfs node we allow failed lstat. 1217*fcf3ce44SJohn Forte */ 1218*fcf3ce44SJohn Forte if ((status == -1) || !S_ISLNK(stbuf.st_mode)) { 1219*fcf3ce44SJohn Forte /* Make sure a full path as that is required. */ 1220*fcf3ce44SJohn Forte if (strstr(s, "/devices")) { 1221*fcf3ce44SJohn Forte result = g_alloc_string(s); 1222*fcf3ce44SJohn Forte } else { 1223*fcf3ce44SJohn Forte if (getcwd(savedir, 1224*fcf3ce44SJohn Forte sizeof (savedir)) == NULL) { 1225*fcf3ce44SJohn Forte return (NULL); 1226*fcf3ce44SJohn Forte } 1227*fcf3ce44SJohn Forte /* 1228*fcf3ce44SJohn Forte * Check for this format: 1229*fcf3ce44SJohn Forte * ./ssd@0,1:g,raw 1230*fcf3ce44SJohn Forte */ 1231*fcf3ce44SJohn Forte if (s[0] == '.') { 1232*fcf3ce44SJohn Forte (void) strcat(savedir, &s[1]); 1233*fcf3ce44SJohn Forte } else { 1234*fcf3ce44SJohn Forte (void) strcat(savedir, "/"); 1235*fcf3ce44SJohn Forte (void) strcat(savedir, s); 1236*fcf3ce44SJohn Forte } 1237*fcf3ce44SJohn Forte if ((status != -1) || strstr(s, "/devices")) { 1238*fcf3ce44SJohn Forte result = g_alloc_string(savedir); 1239*fcf3ce44SJohn Forte } 1240*fcf3ce44SJohn Forte } 1241*fcf3ce44SJohn Forte } else { 1242*fcf3ce44SJohn Forte /* 1243*fcf3ce44SJohn Forte * Entry is linked file 1244*fcf3ce44SJohn Forte * so follow link to physical name 1245*fcf3ce44SJohn Forte */ 1246*fcf3ce44SJohn Forte result = h_get_physical_name_from_link(path); 1247*fcf3ce44SJohn Forte } 1248*fcf3ce44SJohn Forte 1249*fcf3ce44SJohn Forte exit: 1250*fcf3ce44SJohn Forte return (result); 1251*fcf3ce44SJohn Forte } 1252*fcf3ce44SJohn Forte 1253*fcf3ce44SJohn Forte 1254*fcf3ce44SJohn Forte /* 1255*fcf3ce44SJohn Forte * handle expert-mode hotplug commands 1256*fcf3ce44SJohn Forte * 1257*fcf3ce44SJohn Forte * return 0 iff all is okay 1258*fcf3ce44SJohn Forte */ 1259*fcf3ce44SJohn Forte int 1260*fcf3ce44SJohn Forte hotplug_e(int todo, char **argv, int verbose_flag, int force_flag) 1261*fcf3ce44SJohn Forte { 1262*fcf3ce44SJohn Forte char *path_phys = NULL; 1263*fcf3ce44SJohn Forte char bus_path[MAXPATHLEN]; 1264*fcf3ce44SJohn Forte char *ptr; 1265*fcf3ce44SJohn Forte int exit_code; 1266*fcf3ce44SJohn Forte devctl_hdl_t dcp; 1267*fcf3ce44SJohn Forte uint_t devstate; 1268*fcf3ce44SJohn Forte int i = 0, pathcnt = 1; 1269*fcf3ce44SJohn Forte mp_pathlist_t pathlist; 1270*fcf3ce44SJohn Forte int p_pw = 0, p_on = 0, p_st = 0; 1271*fcf3ce44SJohn Forte 1272*fcf3ce44SJohn Forte 1273*fcf3ce44SJohn Forte switch (todo) { 1274*fcf3ce44SJohn Forte case DEV_ONLINE: 1275*fcf3ce44SJohn Forte case DEV_OFFLINE: 1276*fcf3ce44SJohn Forte case DEV_GETSTATE: 1277*fcf3ce44SJohn Forte case DEV_RESET: 1278*fcf3ce44SJohn Forte /* get physical name */ 1279*fcf3ce44SJohn Forte if ((path_phys = h_get_physical_name(argv[0])) == NULL) { 1280*fcf3ce44SJohn Forte 1281*fcf3ce44SJohn Forte (void) fprintf(stderr, 1282*fcf3ce44SJohn Forte MSGSTR(112, "Error: Invalid pathname (%s)"), 1283*fcf3ce44SJohn Forte argv[0]); 1284*fcf3ce44SJohn Forte (void) fprintf(stderr, "\n"); 1285*fcf3ce44SJohn Forte return (1); 1286*fcf3ce44SJohn Forte } 1287*fcf3ce44SJohn Forte 1288*fcf3ce44SJohn Forte if (verbose_flag) { 1289*fcf3ce44SJohn Forte (void) fprintf(stdout, 1290*fcf3ce44SJohn Forte MSGSTR(5516, 1291*fcf3ce44SJohn Forte "phys path = \"%s\"\n"), 1292*fcf3ce44SJohn Forte path_phys); 1293*fcf3ce44SJohn Forte } 1294*fcf3ce44SJohn Forte 1295*fcf3ce44SJohn Forte /* acquire rights to hack on device */ 1296*fcf3ce44SJohn Forte if ((dcp = devctl_device_acquire(path_phys, 1297*fcf3ce44SJohn Forte force_flag ? 0 : DC_EXCL)) == NULL) { 1298*fcf3ce44SJohn Forte 1299*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(5517, 1300*fcf3ce44SJohn Forte "Error: can't acquire \"%s\": %s\n"), 1301*fcf3ce44SJohn Forte path_phys, strerror(errno)); 1302*fcf3ce44SJohn Forte return (1); 1303*fcf3ce44SJohn Forte } 1304*fcf3ce44SJohn Forte 1305*fcf3ce44SJohn Forte switch (todo) { 1306*fcf3ce44SJohn Forte case DEV_ONLINE: 1307*fcf3ce44SJohn Forte exit_code = devctl_device_online(dcp); 1308*fcf3ce44SJohn Forte break; 1309*fcf3ce44SJohn Forte case DEV_OFFLINE: 1310*fcf3ce44SJohn Forte exit_code = devctl_device_offline(dcp); 1311*fcf3ce44SJohn Forte break; 1312*fcf3ce44SJohn Forte case DEV_GETSTATE: 1313*fcf3ce44SJohn Forte if ((exit_code = devctl_device_getstate(dcp, 1314*fcf3ce44SJohn Forte &devstate)) == 0) { 1315*fcf3ce44SJohn Forte print_dev_state(argv[0], devstate); 1316*fcf3ce44SJohn Forte } 1317*fcf3ce44SJohn Forte break; 1318*fcf3ce44SJohn Forte case DEV_RESET: 1319*fcf3ce44SJohn Forte exit_code = devctl_device_reset(dcp); 1320*fcf3ce44SJohn Forte break; 1321*fcf3ce44SJohn Forte } 1322*fcf3ce44SJohn Forte 1323*fcf3ce44SJohn Forte if (exit_code != 0) { 1324*fcf3ce44SJohn Forte perror(MSGSTR(5518, "devctl")); 1325*fcf3ce44SJohn Forte } 1326*fcf3ce44SJohn Forte 1327*fcf3ce44SJohn Forte /* all done now -- release device */ 1328*fcf3ce44SJohn Forte devctl_release(dcp); 1329*fcf3ce44SJohn Forte break; 1330*fcf3ce44SJohn Forte 1331*fcf3ce44SJohn Forte /* for hotplugging bus operations */ 1332*fcf3ce44SJohn Forte case BUS_QUIESCE: 1333*fcf3ce44SJohn Forte case BUS_UNQUIESCE: 1334*fcf3ce44SJohn Forte case BUS_GETSTATE: 1335*fcf3ce44SJohn Forte case BUS_RESET: 1336*fcf3ce44SJohn Forte case BUS_RESETALL: 1337*fcf3ce44SJohn Forte /* get physical name */ 1338*fcf3ce44SJohn Forte if ((path_phys = h_get_physical_name(argv[0])) == 1339*fcf3ce44SJohn Forte NULL) { 1340*fcf3ce44SJohn Forte (void) fprintf(stderr, 1341*fcf3ce44SJohn Forte MSGSTR(112, "Error: Invalid pathname (%s)"), 1342*fcf3ce44SJohn Forte argv[0]); 1343*fcf3ce44SJohn Forte (void) fprintf(stderr, "\n"); 1344*fcf3ce44SJohn Forte return (1); 1345*fcf3ce44SJohn Forte } 1346*fcf3ce44SJohn Forte if (verbose_flag) { 1347*fcf3ce44SJohn Forte printf(MSGSTR(5519, "phys path = \"%s\"\n"), path_phys); 1348*fcf3ce44SJohn Forte } 1349*fcf3ce44SJohn Forte 1350*fcf3ce44SJohn Forte /* acquire rights to hack on device */ 1351*fcf3ce44SJohn Forte /* delete leaf part from path_phys. */ 1352*fcf3ce44SJohn Forte if (strstr(path_phys, SCSI_VHCI) != NULL) { 1353*fcf3ce44SJohn Forte /* obtain phci */ 1354*fcf3ce44SJohn Forte (void) strcpy(bus_path, path_phys); 1355*fcf3ce44SJohn Forte if (g_get_pathlist(bus_path, &pathlist)) { 1356*fcf3ce44SJohn Forte (void) fprintf(stderr, 1357*fcf3ce44SJohn Forte MSGSTR(112, "Error: Invalid pathname (%s)"), 1358*fcf3ce44SJohn Forte path_phys); 1359*fcf3ce44SJohn Forte (void) fprintf(stderr, "\n"); 1360*fcf3ce44SJohn Forte return (1); 1361*fcf3ce44SJohn Forte } 1362*fcf3ce44SJohn Forte pathcnt = pathlist.path_count; 1363*fcf3ce44SJohn Forte p_pw = p_on = p_st = 0; 1364*fcf3ce44SJohn Forte for (i = 0; i < pathcnt; i++) { 1365*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state < 1366*fcf3ce44SJohn Forte MAXPATHSTATE) { 1367*fcf3ce44SJohn Forte if (strstr(pathlist.path_info[i]. 1368*fcf3ce44SJohn Forte path_addr, 1369*fcf3ce44SJohn Forte argv[0]) != NULL) { 1370*fcf3ce44SJohn Forte p_pw = i; 1371*fcf3ce44SJohn Forte break; 1372*fcf3ce44SJohn Forte } 1373*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state == 1374*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 1375*fcf3ce44SJohn Forte p_on = i; 1376*fcf3ce44SJohn Forte } 1377*fcf3ce44SJohn Forte if (pathlist.path_info[i].path_state == 1378*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_STANDBY) { 1379*fcf3ce44SJohn Forte p_st = i; 1380*fcf3ce44SJohn Forte } 1381*fcf3ce44SJohn Forte } 1382*fcf3ce44SJohn Forte } 1383*fcf3ce44SJohn Forte if (strstr(pathlist.path_info[p_pw].path_addr, 1384*fcf3ce44SJohn Forte argv[0]) != NULL) { 1385*fcf3ce44SJohn Forte /* matching input pwwn */ 1386*fcf3ce44SJohn Forte (void) strcpy(bus_path, 1387*fcf3ce44SJohn Forte pathlist.path_info[p_pw].path_hba); 1388*fcf3ce44SJohn Forte } else if (pathlist.path_info[p_on].path_state == 1389*fcf3ce44SJohn Forte MDI_PATHINFO_STATE_ONLINE) { 1390*fcf3ce44SJohn Forte /* on_line path */ 1391*fcf3ce44SJohn Forte (void) strcpy(bus_path, 1392*fcf3ce44SJohn Forte pathlist.path_info[p_on].path_hba); 1393*fcf3ce44SJohn Forte } else { 1394*fcf3ce44SJohn Forte /* standby or path0 */ 1395*fcf3ce44SJohn Forte (void) strcpy(bus_path, 1396*fcf3ce44SJohn Forte pathlist.path_info[p_st].path_hba); 1397*fcf3ce44SJohn Forte } 1398*fcf3ce44SJohn Forte free(pathlist.path_info); 1399*fcf3ce44SJohn Forte } else { 1400*fcf3ce44SJohn Forte 1401*fcf3ce44SJohn Forte (void) strcpy(bus_path, path_phys); 1402*fcf3ce44SJohn Forte ptr = strrchr(bus_path, '/'); 1403*fcf3ce44SJohn Forte if (ptr) { 1404*fcf3ce44SJohn Forte *ptr = '\0'; 1405*fcf3ce44SJohn Forte } else { 1406*fcf3ce44SJohn Forte (void) fprintf(stderr, 1407*fcf3ce44SJohn Forte MSGSTR(112, "Error: Invalid pathname (%s)"), 1408*fcf3ce44SJohn Forte path_phys); 1409*fcf3ce44SJohn Forte (void) fprintf(stderr, "\n"); 1410*fcf3ce44SJohn Forte return (1); 1411*fcf3ce44SJohn Forte } 1412*fcf3ce44SJohn Forte } 1413*fcf3ce44SJohn Forte 1414*fcf3ce44SJohn Forte if ((dcp = devctl_bus_acquire(bus_path, 1415*fcf3ce44SJohn Forte force_flag ? 0 : DC_EXCL)) == NULL) { 1416*fcf3ce44SJohn Forte (void) fprintf(stderr, 1417*fcf3ce44SJohn Forte MSGSTR(5521, 1418*fcf3ce44SJohn Forte " Error: can't acquire bus node from" 1419*fcf3ce44SJohn Forte " the path \"%s\": %s\n"), 1420*fcf3ce44SJohn Forte bus_path, strerror(errno)); 1421*fcf3ce44SJohn Forte return (1); 1422*fcf3ce44SJohn Forte } 1423*fcf3ce44SJohn Forte 1424*fcf3ce44SJohn Forte switch (todo) { 1425*fcf3ce44SJohn Forte case BUS_QUIESCE: 1426*fcf3ce44SJohn Forte exit_code = devctl_bus_quiesce(dcp); 1427*fcf3ce44SJohn Forte break; 1428*fcf3ce44SJohn Forte case BUS_UNQUIESCE: 1429*fcf3ce44SJohn Forte exit_code = devctl_bus_unquiesce(dcp); 1430*fcf3ce44SJohn Forte break; 1431*fcf3ce44SJohn Forte case BUS_GETSTATE: 1432*fcf3ce44SJohn Forte if ((exit_code = devctl_bus_getstate(dcp, 1433*fcf3ce44SJohn Forte &devstate)) == 0) { 1434*fcf3ce44SJohn Forte print_bus_state(argv[0], devstate); 1435*fcf3ce44SJohn Forte } 1436*fcf3ce44SJohn Forte break; 1437*fcf3ce44SJohn Forte case BUS_RESET: 1438*fcf3ce44SJohn Forte exit_code = devctl_bus_reset(dcp); 1439*fcf3ce44SJohn Forte break; 1440*fcf3ce44SJohn Forte case BUS_RESETALL: 1441*fcf3ce44SJohn Forte exit_code = devctl_bus_resetall(dcp); 1442*fcf3ce44SJohn Forte break; 1443*fcf3ce44SJohn Forte } 1444*fcf3ce44SJohn Forte 1445*fcf3ce44SJohn Forte if (exit_code != 0) { 1446*fcf3ce44SJohn Forte perror(MSGSTR(5522, "devctl")); 1447*fcf3ce44SJohn Forte } 1448*fcf3ce44SJohn Forte 1449*fcf3ce44SJohn Forte /* all done now -- release device */ 1450*fcf3ce44SJohn Forte devctl_release(dcp); 1451*fcf3ce44SJohn Forte break; 1452*fcf3ce44SJohn Forte } 1453*fcf3ce44SJohn Forte 1454*fcf3ce44SJohn Forte return (exit_code); 1455*fcf3ce44SJohn Forte } 1456*fcf3ce44SJohn Forte 1457*fcf3ce44SJohn Forte 1458*fcf3ce44SJohn Forte 1459*fcf3ce44SJohn Forte /* 1460*fcf3ce44SJohn Forte * Prepares an individual FC_AL device 1461*fcf3ce44SJohn Forte * to be removed from the specified 1462*fcf3ce44SJohn Forte * slot. 1463*fcf3ce44SJohn Forte * 1464*fcf3ce44SJohn Forte * RETURNS: 1465*fcf3ce44SJohn Forte * 0 if OK 1466*fcf3ce44SJohn Forte * non-zero otherwise. 1467*fcf3ce44SJohn Forte */ 1468*fcf3ce44SJohn Forte static int 1469*fcf3ce44SJohn Forte h_pre_remove_dev(Hotplug_Devlist *hotplug_disk, WWN_list *wwn_list, 1470*fcf3ce44SJohn Forte int verbose_flag, int force_flag) 1471*fcf3ce44SJohn Forte { 1472*fcf3ce44SJohn Forte char *dev_path, device_name[MAXNAMELEN]; 1473*fcf3ce44SJohn Forte int err; 1474*fcf3ce44SJohn Forte 1475*fcf3ce44SJohn Forte /* Initialize pointers */ 1476*fcf3ce44SJohn Forte dev_path = NULL; 1477*fcf3ce44SJohn Forte 1478*fcf3ce44SJohn Forte if (hotplug_disk->dlhead != NULL) { 1479*fcf3ce44SJohn Forte dev_path = hotplug_disk->dlhead->dev_path; 1480*fcf3ce44SJohn Forte (void) strcpy(device_name, (hotplug_disk->dlhead)->logical_path); 1481*fcf3ce44SJohn Forte } 1482*fcf3ce44SJohn Forte (void) fprintf(stdout, 1483*fcf3ce44SJohn Forte MSGSTR(157, 1484*fcf3ce44SJohn Forte "stopping: %s...."), device_name); 1485*fcf3ce44SJohn Forte if (!(strstr(dev_path, SLSH_DRV_NAME_ST))) { 1486*fcf3ce44SJohn Forte if ((err = g_dev_stop(dev_path, wwn_list, verbose_flag)) != 0) 1487*fcf3ce44SJohn Forte return (err); 1488*fcf3ce44SJohn Forte } 1489*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(156, "Done\n")); 1490*fcf3ce44SJohn Forte 1491*fcf3ce44SJohn Forte (void) fprintf(stdout, 1492*fcf3ce44SJohn Forte MSGSTR(158, "offlining: %s...."), device_name); 1493*fcf3ce44SJohn Forte if ((err = g_offline_drive(hotplug_disk->dlhead, 1494*fcf3ce44SJohn Forte force_flag)) != 0) { 1495*fcf3ce44SJohn Forte (void) fprintf(stdout, 1496*fcf3ce44SJohn Forte MSGSTR(160, 1497*fcf3ce44SJohn Forte "\nonlining: %s\n"), device_name); 1498*fcf3ce44SJohn Forte 1499*fcf3ce44SJohn Forte (void) g_online_drive(hotplug_disk->dlhead, force_flag); 1500*fcf3ce44SJohn Forte (void) fprintf(stdout, 1501*fcf3ce44SJohn Forte MSGSTR(159, "starting: %s...."), 1502*fcf3ce44SJohn Forte device_name); 1503*fcf3ce44SJohn Forte if ((err = g_dev_start(dev_path, 0)) != 0) { 1504*fcf3ce44SJohn Forte return (err); 1505*fcf3ce44SJohn Forte } 1506*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(156, "Done\n")); 1507*fcf3ce44SJohn Forte return (err); 1508*fcf3ce44SJohn Forte } 1509*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(156, "Done\n")); 1510*fcf3ce44SJohn Forte return (0); 1511*fcf3ce44SJohn Forte } 1512*fcf3ce44SJohn Forte 1513*fcf3ce44SJohn Forte 1514*fcf3ce44SJohn Forte 1515*fcf3ce44SJohn Forte /* 1516*fcf3ce44SJohn Forte * Prepares a SENA enclosure or SENA FC_AL device 1517*fcf3ce44SJohn Forte * to be inserted/removed from a specified slot. 1518*fcf3ce44SJohn Forte * 1519*fcf3ce44SJohn Forte * RETURNS: 1520*fcf3ce44SJohn Forte * 0 if OK 1521*fcf3ce44SJohn Forte * non-zero otherwise. 1522*fcf3ce44SJohn Forte */ 1523*fcf3ce44SJohn Forte static int 1524*fcf3ce44SJohn Forte h_pre_hotplug_sena(Hotplug_Devlist *hotplug_dev, 1525*fcf3ce44SJohn Forte WWN_list *wwn_list, int todo, 1526*fcf3ce44SJohn Forte int verbose_flag, int force_flag) 1527*fcf3ce44SJohn Forte { 1528*fcf3ce44SJohn Forte int slot, f_r, i, found_null_wwn = 0, err; 1529*fcf3ce44SJohn Forte char *ses_path, *dev_path, code; 1530*fcf3ce44SJohn Forte char node_wwn_s[WWN_SIZE], device_name[MAXNAMELEN]; 1531*fcf3ce44SJohn Forte struct l_state_struct l_state; 1532*fcf3ce44SJohn Forte struct dlist *dl; 1533*fcf3ce44SJohn Forte 1534*fcf3ce44SJohn Forte 1535*fcf3ce44SJohn Forte if (hotplug_dev->dev_type == DTYPE_ESI) { 1536*fcf3ce44SJohn Forte /* entire photon is being removed */ 1537*fcf3ce44SJohn Forte if ((err = l_offline_photon(hotplug_dev, wwn_list, 1538*fcf3ce44SJohn Forte force_flag, verbose_flag)) != 0) { 1539*fcf3ce44SJohn Forte return (err); 1540*fcf3ce44SJohn Forte } 1541*fcf3ce44SJohn Forte return (0); 1542*fcf3ce44SJohn Forte } 1543*fcf3ce44SJohn Forte 1544*fcf3ce44SJohn Forte /* if device is an individual sena disk */ 1545*fcf3ce44SJohn Forte dl = hotplug_dev->seslist; 1546*fcf3ce44SJohn Forte while (dl) { 1547*fcf3ce44SJohn Forte ses_path = dl->dev_path; 1548*fcf3ce44SJohn Forte if ((err = l_get_status(ses_path, &l_state, 1549*fcf3ce44SJohn Forte verbose_flag)) == 0) 1550*fcf3ce44SJohn Forte break; 1551*fcf3ce44SJohn Forte dl = dl->next; 1552*fcf3ce44SJohn Forte } 1553*fcf3ce44SJohn Forte if (dl == NULL) { 1554*fcf3ce44SJohn Forte return (L_GET_STATUS_FAILED); 1555*fcf3ce44SJohn Forte } 1556*fcf3ce44SJohn Forte 1557*fcf3ce44SJohn Forte f_r = hotplug_dev->f_flag; 1558*fcf3ce44SJohn Forte slot = hotplug_dev->slot; 1559*fcf3ce44SJohn Forte (void) l_get_drive_name(device_name, slot, f_r, hotplug_dev->box_name); 1560*fcf3ce44SJohn Forte 1561*fcf3ce44SJohn Forte /* check if disk has null wwn */ 1562*fcf3ce44SJohn Forte if (f_r) { 1563*fcf3ce44SJohn Forte (void) strncpy(node_wwn_s, 1564*fcf3ce44SJohn Forte l_state.drv_front[slot].g_disk_state.node_wwn_s, WWN_SIZE); 1565*fcf3ce44SJohn Forte } else { 1566*fcf3ce44SJohn Forte (void) strncpy(node_wwn_s, 1567*fcf3ce44SJohn Forte l_state.drv_rear[slot].g_disk_state.node_wwn_s, WWN_SIZE); 1568*fcf3ce44SJohn Forte } 1569*fcf3ce44SJohn Forte for (i = 0; i < WWN_SIZE; i++) { 1570*fcf3ce44SJohn Forte if (node_wwn_s[i] != '0') 1571*fcf3ce44SJohn Forte break; 1572*fcf3ce44SJohn Forte found_null_wwn = 1; 1573*fcf3ce44SJohn Forte } 1574*fcf3ce44SJohn Forte 1575*fcf3ce44SJohn Forte switch (todo) { 1576*fcf3ce44SJohn Forte case INSERT_DEVICE: 1577*fcf3ce44SJohn Forte if (hotplug_dev->f_flag) { 1578*fcf3ce44SJohn Forte code = 1579*fcf3ce44SJohn Forte l_state.drv_front[slot].ib_status.code; 1580*fcf3ce44SJohn Forte } else { 1581*fcf3ce44SJohn Forte code = 1582*fcf3ce44SJohn Forte l_state.drv_rear[slot].ib_status.code; 1583*fcf3ce44SJohn Forte } 1584*fcf3ce44SJohn Forte if (code & S_NOT_INSTALLED) { 1585*fcf3ce44SJohn Forte /* 1586*fcf3ce44SJohn Forte * At this point we know that the drive is not 1587*fcf3ce44SJohn Forte * there. Turn on the RQST INSERT bit to make 1588*fcf3ce44SJohn Forte * the LED blink 1589*fcf3ce44SJohn Forte */ 1590*fcf3ce44SJohn Forte if ((err = l_encl_status_page_funcs 1591*fcf3ce44SJohn Forte (SET_RQST_INSRT, 0, todo, 1592*fcf3ce44SJohn Forte ses_path, &l_state, f_r, slot, 1593*fcf3ce44SJohn Forte verbose_flag)) != 0) { 1594*fcf3ce44SJohn Forte (void) print_errString(err, 1595*fcf3ce44SJohn Forte device_name); 1596*fcf3ce44SJohn Forte (void) fprintf(stderr, 1597*fcf3ce44SJohn Forte MSGSTR(5530, 1598*fcf3ce44SJohn Forte " %s: could not turn " 1599*fcf3ce44SJohn Forte "on LED\n"), 1600*fcf3ce44SJohn Forte device_name); 1601*fcf3ce44SJohn Forte } 1602*fcf3ce44SJohn Forte } else { 1603*fcf3ce44SJohn Forte /* 1604*fcf3ce44SJohn Forte * Drive is there so start it. 1605*fcf3ce44SJohn Forte */ 1606*fcf3ce44SJohn Forte if ((err = l_encl_status_page_funcs 1607*fcf3ce44SJohn Forte (SET_DRV_ON, 0, todo, 1608*fcf3ce44SJohn Forte ses_path, &l_state, f_r, slot, 1609*fcf3ce44SJohn Forte verbose_flag)) != 0) { 1610*fcf3ce44SJohn Forte (void) print_errString(err, 1611*fcf3ce44SJohn Forte device_name); 1612*fcf3ce44SJohn Forte (void) fprintf(stderr, 1613*fcf3ce44SJohn Forte MSGSTR(5531, 1614*fcf3ce44SJohn Forte " could not enable" 1615*fcf3ce44SJohn Forte " %s\n"), 1616*fcf3ce44SJohn Forte device_name); 1617*fcf3ce44SJohn Forte } 1618*fcf3ce44SJohn Forte } 1619*fcf3ce44SJohn Forte break; 1620*fcf3ce44SJohn Forte 1621*fcf3ce44SJohn Forte case REMOVE_DEVICE: 1622*fcf3ce44SJohn Forte /* 1623*fcf3ce44SJohn Forte * if disk has null wwn, then 1624*fcf3ce44SJohn Forte * there is no need to check the 1625*fcf3ce44SJohn Forte * disk/loop status. 1626*fcf3ce44SJohn Forte */ 1627*fcf3ce44SJohn Forte if (found_null_wwn == 1) { 1628*fcf3ce44SJohn Forte if (getenv("_LUX_W_DEBUG") != NULL) { 1629*fcf3ce44SJohn Forte (void) fprintf(stdout, 1630*fcf3ce44SJohn Forte "Device %s has " 1631*fcf3ce44SJohn Forte "null WWN.\n", 1632*fcf3ce44SJohn Forte device_name); 1633*fcf3ce44SJohn Forte } 1634*fcf3ce44SJohn Forte goto rmv; 1635*fcf3ce44SJohn Forte } 1636*fcf3ce44SJohn Forte if (hotplug_dev->f_flag) { 1637*fcf3ce44SJohn Forte if ( 1638*fcf3ce44SJohn Forte l_state.drv_front[slot].ib_status.code 1639*fcf3ce44SJohn Forte == S_NOT_INSTALLED) { 1640*fcf3ce44SJohn Forte (void) fprintf(stderr, 1641*fcf3ce44SJohn Forte MSGSTR(86, 1642*fcf3ce44SJohn Forte " Notice: %s may already" 1643*fcf3ce44SJohn Forte " be removed.\n"), 1644*fcf3ce44SJohn Forte device_name); 1645*fcf3ce44SJohn Forte return (0); 1646*fcf3ce44SJohn Forte } 1647*fcf3ce44SJohn Forte } else if ( 1648*fcf3ce44SJohn Forte l_state.drv_rear[slot].ib_status.code 1649*fcf3ce44SJohn Forte == S_NOT_INSTALLED) { 1650*fcf3ce44SJohn Forte (void) fprintf(stderr, 1651*fcf3ce44SJohn Forte MSGSTR(86, 1652*fcf3ce44SJohn Forte " Notice: %s may already" 1653*fcf3ce44SJohn Forte " be removed.\n"), 1654*fcf3ce44SJohn Forte device_name); 1655*fcf3ce44SJohn Forte return (0); 1656*fcf3ce44SJohn Forte } 1657*fcf3ce44SJohn Forte 1658*fcf3ce44SJohn Forte rmv: 1659*fcf3ce44SJohn Forte if (hotplug_dev->dlhead == NULL) { 1660*fcf3ce44SJohn Forte dev_path = NULL; 1661*fcf3ce44SJohn Forte } else { 1662*fcf3ce44SJohn Forte dev_path = hotplug_dev->dlhead->dev_path; 1663*fcf3ce44SJohn Forte } 1664*fcf3ce44SJohn Forte 1665*fcf3ce44SJohn Forte (void) fprintf(stdout, 1666*fcf3ce44SJohn Forte MSGSTR(157, 1667*fcf3ce44SJohn Forte "stopping: %s...."), device_name); 1668*fcf3ce44SJohn Forte if ((err = g_dev_stop(dev_path, wwn_list, 0)) != 0) { 1669*fcf3ce44SJohn Forte return (err); 1670*fcf3ce44SJohn Forte } 1671*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(156, "Done\n")); 1672*fcf3ce44SJohn Forte 1673*fcf3ce44SJohn Forte (void) fprintf(stdout, 1674*fcf3ce44SJohn Forte MSGSTR(158, "offlining: %s...."), 1675*fcf3ce44SJohn Forte device_name); 1676*fcf3ce44SJohn Forte if ((err = g_offline_drive(hotplug_dev->dlhead, 1677*fcf3ce44SJohn Forte force_flag)) != 0) { 1678*fcf3ce44SJohn Forte (void) fprintf(stdout, 1679*fcf3ce44SJohn Forte MSGSTR(160, 1680*fcf3ce44SJohn Forte "\nonlining: %s\n"), device_name); 1681*fcf3ce44SJohn Forte (void) g_online_drive(hotplug_dev->dlhead, force_flag); 1682*fcf3ce44SJohn Forte 1683*fcf3ce44SJohn Forte (void) fprintf(stdout, 1684*fcf3ce44SJohn Forte MSGSTR(159, "starting: %s...."), 1685*fcf3ce44SJohn Forte device_name); 1686*fcf3ce44SJohn Forte (void) g_dev_start(dev_path, 0); 1687*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(156, "Done\n")); 1688*fcf3ce44SJohn Forte return (err); 1689*fcf3ce44SJohn Forte } 1690*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(156, "Done\n")); 1691*fcf3ce44SJohn Forte 1692*fcf3ce44SJohn Forte /* 1693*fcf3ce44SJohn Forte * Take the drive off the loop 1694*fcf3ce44SJohn Forte * and blink the LED. 1695*fcf3ce44SJohn Forte */ 1696*fcf3ce44SJohn Forte if (hotplug_dev->dev_location == SENA) { 1697*fcf3ce44SJohn Forte if ((err = l_encl_status_page_funcs(SET_RQST_RMV, 0, 1698*fcf3ce44SJohn Forte todo, ses_path, &l_state, f_r, 1699*fcf3ce44SJohn Forte slot, verbose_flag)) != 0) { 1700*fcf3ce44SJohn Forte (void) print_errString(err, device_name); 1701*fcf3ce44SJohn Forte (void) fprintf(stderr, 1702*fcf3ce44SJohn Forte MSGSTR(5539, 1703*fcf3ce44SJohn Forte " %s: could not blink" 1704*fcf3ce44SJohn Forte " the yellow LED\n"), 1705*fcf3ce44SJohn Forte device_name); 1706*fcf3ce44SJohn Forte } 1707*fcf3ce44SJohn Forte } 1708*fcf3ce44SJohn Forte break; 1709*fcf3ce44SJohn Forte } 1710*fcf3ce44SJohn Forte return (0); 1711*fcf3ce44SJohn Forte } 1712*fcf3ce44SJohn Forte 1713*fcf3ce44SJohn Forte 1714*fcf3ce44SJohn Forte 1715*fcf3ce44SJohn Forte /* 1716*fcf3ce44SJohn Forte * Performs the post removal operations for 1717*fcf3ce44SJohn Forte * a SENA enclosure or a SENA FC_AL disk. 1718*fcf3ce44SJohn Forte * 1719*fcf3ce44SJohn Forte * RETURNS: 1720*fcf3ce44SJohn Forte * 0 if OK 1721*fcf3ce44SJohn Forte * non-zero otherwise 1722*fcf3ce44SJohn Forte */ 1723*fcf3ce44SJohn Forte static int 1724*fcf3ce44SJohn Forte h_post_hotplug_sena(Hotplug_Devlist *hotplug_dev, 1725*fcf3ce44SJohn Forte WWN_list *wwn_list, int todo, 1726*fcf3ce44SJohn Forte int verbose_flag, int force_flag, int enc_type) 1727*fcf3ce44SJohn Forte { 1728*fcf3ce44SJohn Forte char *ses_path, *dev_path = NULL, device_name[MAXNAMELEN]; 1729*fcf3ce44SJohn Forte int tid, slot, f_r, al_pa, timeout = 0; 1730*fcf3ce44SJohn Forte uchar_t port_wwn[WWN_SIZE], node_wwn[WWN_SIZE]; 1731*fcf3ce44SJohn Forte char code; 1732*fcf3ce44SJohn Forte int wait_spinup_flag = 0, wait_map_flag = 0; 1733*fcf3ce44SJohn Forte int wait_node_flag = 0, err = 0, nArg; 1734*fcf3ce44SJohn Forte gfc_map_t map; 1735*fcf3ce44SJohn Forte WWN_list *newWwn_list = NULL; 1736*fcf3ce44SJohn Forte struct dlist *dl, *dl1; 1737*fcf3ce44SJohn Forte struct l_state_struct l_state; 1738*fcf3ce44SJohn Forte 1739*fcf3ce44SJohn Forte 1740*fcf3ce44SJohn Forte dl = hotplug_dev->seslist; 1741*fcf3ce44SJohn Forte slot = hotplug_dev->slot; 1742*fcf3ce44SJohn Forte f_r = hotplug_dev->f_flag; 1743*fcf3ce44SJohn Forte tid = hotplug_dev->tid; 1744*fcf3ce44SJohn Forte 1745*fcf3ce44SJohn Forte if (hotplug_dev->dev_type == DTYPE_ESI) { 1746*fcf3ce44SJohn Forte /* 1747*fcf3ce44SJohn Forte * See if photon has really been removed. If not, 1748*fcf3ce44SJohn Forte * try onlining the devices if applicable 1749*fcf3ce44SJohn Forte */ 1750*fcf3ce44SJohn Forte H_DPRINTF(" post_hotplug_sena: Seeing if enclosure " 1751*fcf3ce44SJohn Forte "has really been removed:\n" 1752*fcf3ce44SJohn Forte " tid=0x%x, ses_path %s\n", 1753*fcf3ce44SJohn Forte tid, dl->dev_path); 1754*fcf3ce44SJohn Forte 1755*fcf3ce44SJohn Forte while (dl) { 1756*fcf3ce44SJohn Forte ses_path = dl->dev_path; 1757*fcf3ce44SJohn Forte if ((err = g_get_dev_map(ses_path, &map, 0)) == 0) { 1758*fcf3ce44SJohn Forte if ((map.hba_addr.port_topology == 1759*fcf3ce44SJohn Forte FC_TOP_PUBLIC_LOOP) || 1760*fcf3ce44SJohn Forte (map.hba_addr.port_topology == 1761*fcf3ce44SJohn Forte FC_TOP_FABRIC)) { 1762*fcf3ce44SJohn Forte /* public or fabric loop device */ 1763*fcf3ce44SJohn Forte free((void *)map.dev_addr); 1764*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5540, 1765*fcf3ce44SJohn Forte "This operation is not " 1766*fcf3ce44SJohn Forte "supported in this topology.\n")); 1767*fcf3ce44SJohn Forte return (0); 1768*fcf3ce44SJohn Forte } 1769*fcf3ce44SJohn Forte if ((err = g_get_wwn(ses_path, port_wwn, 1770*fcf3ce44SJohn Forte node_wwn, &al_pa, verbose_flag)) == 0) { 1771*fcf3ce44SJohn Forte tid = g_sf_alpa_to_switch[al_pa]; 1772*fcf3ce44SJohn Forte if (g_device_in_map(&map, tid)) { 1773*fcf3ce44SJohn Forte free((void *)map.dev_addr); 1774*fcf3ce44SJohn Forte break; 1775*fcf3ce44SJohn Forte } 1776*fcf3ce44SJohn Forte } 1777*fcf3ce44SJohn Forte FREE_DEV_ADDR(map.dev_addr); 1778*fcf3ce44SJohn Forte } 1779*fcf3ce44SJohn Forte 1780*fcf3ce44SJohn Forte dl = dl->next; 1781*fcf3ce44SJohn Forte } 1782*fcf3ce44SJohn Forte FREE_DEV_ADDR(map.dev_addr); 1783*fcf3ce44SJohn Forte if (dl) { 1784*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5640, 1785*fcf3ce44SJohn Forte "Photon \"%s\" not removed." 1786*fcf3ce44SJohn Forte " Onlining Drives in enclosure.\n"), 1787*fcf3ce44SJohn Forte hotplug_dev->box_name); 1788*fcf3ce44SJohn Forte for (dl = hotplug_dev->dlhead; dl; ) { 1789*fcf3ce44SJohn Forte (void) g_online_drive(dl->multipath, 1790*fcf3ce44SJohn Forte force_flag); 1791*fcf3ce44SJohn Forte (void) g_free_multipath(dl->multipath); 1792*fcf3ce44SJohn Forte dl1 = dl; 1793*fcf3ce44SJohn Forte dl = dl->next; 1794*fcf3ce44SJohn Forte (void) free(dl1); 1795*fcf3ce44SJohn Forte } 1796*fcf3ce44SJohn Forte hotplug_dev->dlhead = NULL; 1797*fcf3ce44SJohn Forte return (0); 1798*fcf3ce44SJohn Forte } 1799*fcf3ce44SJohn Forte /* 1800*fcf3ce44SJohn Forte * Remove logical nodes for this 1801*fcf3ce44SJohn Forte * photon, this includes ses and 1802*fcf3ce44SJohn Forte * /dev/dsk entries. 1803*fcf3ce44SJohn Forte * In Solaris7, disks with -C option 1804*fcf3ce44SJohn Forte * removes the /dev/dsk entries. 1805*fcf3ce44SJohn Forte * The -C option is available 1806*fcf3ce44SJohn Forte * only for Solaris7. From Solaris8 1807*fcf3ce44SJohn Forte * or higher releases, the "disks" 1808*fcf3ce44SJohn Forte * program will be replaced by the 1809*fcf3ce44SJohn Forte * devfsadm program. 1810*fcf3ce44SJohn Forte */ 1811*fcf3ce44SJohn Forte /* pass "disks -C" as cmdStrg. */ 1812*fcf3ce44SJohn Forte nArg = 2; 1813*fcf3ce44SJohn Forte if (h_execCmnd(cmdStrg[0], nArg) != 0) { 1814*fcf3ce44SJohn Forte for (dl = hotplug_dev->dlhead; 1815*fcf3ce44SJohn Forte dl != NULL; dl = dl->next) { 1816*fcf3ce44SJohn Forte if ((err = h_remove_nodes(dl->multipath)) 1817*fcf3ce44SJohn Forte != 0) { 1818*fcf3ce44SJohn Forte return (err); 1819*fcf3ce44SJohn Forte } 1820*fcf3ce44SJohn Forte } 1821*fcf3ce44SJohn Forte } else { 1822*fcf3ce44SJohn Forte (void) fprintf(stdout, 1823*fcf3ce44SJohn Forte MSGSTR(5541, 1824*fcf3ce44SJohn Forte " Logical Nodes being removed" 1825*fcf3ce44SJohn Forte " under /dev/dsk/ and /dev/rdsk:\n")); 1826*fcf3ce44SJohn Forte for (dl = hotplug_dev->dlhead; 1827*fcf3ce44SJohn Forte dl != NULL; dl = dl->next) { 1828*fcf3ce44SJohn Forte (void) h_print_logical_nodes(dl->multipath); 1829*fcf3ce44SJohn Forte } 1830*fcf3ce44SJohn Forte } 1831*fcf3ce44SJohn Forte 1832*fcf3ce44SJohn Forte for (dl = hotplug_dev->dlhead; dl != NULL; ) { 1833*fcf3ce44SJohn Forte (void) g_free_multipath(dl->multipath); 1834*fcf3ce44SJohn Forte dl1 = dl; 1835*fcf3ce44SJohn Forte dl = dl->next; 1836*fcf3ce44SJohn Forte (void) free(dl1); 1837*fcf3ce44SJohn Forte } 1838*fcf3ce44SJohn Forte hotplug_dev->dlhead = NULL; 1839*fcf3ce44SJohn Forte if ((err = h_remove_ses_nodes(hotplug_dev->seslist)) != 0) { 1840*fcf3ce44SJohn Forte return (err); 1841*fcf3ce44SJohn Forte } 1842*fcf3ce44SJohn Forte return (0); 1843*fcf3ce44SJohn Forte } 1844*fcf3ce44SJohn Forte 1845*fcf3ce44SJohn Forte /* post hotplug operations for a SENA disk. */ 1846*fcf3ce44SJohn Forte if (enc_type == DAK_ENC_TYPE) { 1847*fcf3ce44SJohn Forte (void) sprintf(device_name, MSGSTR(5664, 1848*fcf3ce44SJohn Forte " Drive in Box Name \"%s\" slot %d"), 1849*fcf3ce44SJohn Forte hotplug_dev->box_name, 1850*fcf3ce44SJohn Forte f_r ? slot : slot + (MAX_DRIVES_DAK/2)); 1851*fcf3ce44SJohn Forte } else { 1852*fcf3ce44SJohn Forte if (tid & 0x10) { 1853*fcf3ce44SJohn Forte (void) sprintf(device_name, MSGSTR(5542, 1854*fcf3ce44SJohn Forte " Drive in Box Name \"%s\" rear slot %d"), 1855*fcf3ce44SJohn Forte hotplug_dev->box_name, slot); 1856*fcf3ce44SJohn Forte } else { 1857*fcf3ce44SJohn Forte (void) sprintf(device_name, MSGSTR(5543, 1858*fcf3ce44SJohn Forte " Drive in Box Name \"%s\" front slot %d"), 1859*fcf3ce44SJohn Forte hotplug_dev->box_name, slot); 1860*fcf3ce44SJohn Forte } 1861*fcf3ce44SJohn Forte } 1862*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s\n", device_name); 1863*fcf3ce44SJohn Forte 1864*fcf3ce44SJohn Forte dl = hotplug_dev->seslist; 1865*fcf3ce44SJohn Forte while (dl) { 1866*fcf3ce44SJohn Forte ses_path = dl->dev_path; 1867*fcf3ce44SJohn Forte if ((err = l_get_status(ses_path, &l_state, 1868*fcf3ce44SJohn Forte verbose_flag)) == 0) 1869*fcf3ce44SJohn Forte break; 1870*fcf3ce44SJohn Forte dl = dl->next; 1871*fcf3ce44SJohn Forte } 1872*fcf3ce44SJohn Forte if (dl == NULL) { 1873*fcf3ce44SJohn Forte print_errString(err, ses_path); 1874*fcf3ce44SJohn Forte return (L_GET_STATUS_FAILED); 1875*fcf3ce44SJohn Forte } 1876*fcf3ce44SJohn Forte 1877*fcf3ce44SJohn Forte code = 0; 1878*fcf3ce44SJohn Forte while (((err = l_encl_status_page_funcs(OVERALL_STATUS, 1879*fcf3ce44SJohn Forte &code, todo, ses_path, &l_state, f_r, slot, 1880*fcf3ce44SJohn Forte verbose_flag)) != 0) || (code != 0)) { 1881*fcf3ce44SJohn Forte if (err) { 1882*fcf3ce44SJohn Forte (void) print_errString(err, ses_path); 1883*fcf3ce44SJohn Forte } else if (todo == REMOVE_DEVICE) { 1884*fcf3ce44SJohn Forte if (code == S_OK) { 1885*fcf3ce44SJohn Forte (void) fprintf(stderr, 1886*fcf3ce44SJohn Forte MSGSTR(5544, 1887*fcf3ce44SJohn Forte "\n Warning: Device has not been" 1888*fcf3ce44SJohn Forte " removed from the enclosure\n" 1889*fcf3ce44SJohn Forte " and is still on the loop.")); 1890*fcf3ce44SJohn Forte return (0); 1891*fcf3ce44SJohn Forte } else { 1892*fcf3ce44SJohn Forte (void) fprintf(stderr, 1893*fcf3ce44SJohn Forte MSGSTR(5545, 1894*fcf3ce44SJohn Forte " Notice: Device has not been" 1895*fcf3ce44SJohn Forte " removed from the enclosure.\n" 1896*fcf3ce44SJohn Forte " It has been removed from the" 1897*fcf3ce44SJohn Forte " loop and is ready to be\n" 1898*fcf3ce44SJohn Forte " removed" 1899*fcf3ce44SJohn Forte " from the enclosure, and" 1900*fcf3ce44SJohn Forte " the LED is blinking.\n\n")); 1901*fcf3ce44SJohn Forte } 1902*fcf3ce44SJohn Forte goto loop2; 1903*fcf3ce44SJohn Forte } else if ((todo == INSERT_DEVICE) && 1904*fcf3ce44SJohn Forte ((code != S_NOT_AVAILABLE) || 1905*fcf3ce44SJohn Forte (timeout > 1906*fcf3ce44SJohn Forte PHOTON_SPINUP_TIMEOUT) || 1907*fcf3ce44SJohn Forte err)) { 1908*fcf3ce44SJohn Forte (void) fprintf(stderr, 1909*fcf3ce44SJohn Forte MSGSTR(5546, 1910*fcf3ce44SJohn Forte "\n Warning: Disk status is" 1911*fcf3ce44SJohn Forte " Not OK!\n\n")); 1912*fcf3ce44SJohn Forte return (0); 1913*fcf3ce44SJohn Forte } 1914*fcf3ce44SJohn Forte (void) sleep(PHOTON_SPINUP_DELAY); 1915*fcf3ce44SJohn Forte if (wait_spinup_flag++ == 0) { 1916*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5547, 1917*fcf3ce44SJohn Forte " Waiting for the disk to spin up:")); 1918*fcf3ce44SJohn Forte } else { 1919*fcf3ce44SJohn Forte (void) fprintf(stdout, "."); 1920*fcf3ce44SJohn Forte } 1921*fcf3ce44SJohn Forte timeout++; 1922*fcf3ce44SJohn Forte } 1923*fcf3ce44SJohn Forte if (wait_spinup_flag) { 1924*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 1925*fcf3ce44SJohn Forte } 1926*fcf3ce44SJohn Forte loop2: 1927*fcf3ce44SJohn Forte switch (todo) { 1928*fcf3ce44SJohn Forte case INSERT_DEVICE: 1929*fcf3ce44SJohn Forte /* check loop map that drive is present */ 1930*fcf3ce44SJohn Forte for (;;) { 1931*fcf3ce44SJohn Forte dl = hotplug_dev->seslist; 1932*fcf3ce44SJohn Forte map.dev_addr = (gfc_port_dev_info_t *)NULL; 1933*fcf3ce44SJohn Forte while (dl) { 1934*fcf3ce44SJohn Forte ses_path = dl->dev_path; 1935*fcf3ce44SJohn Forte if ((err = g_get_dev_map(ses_path, 1936*fcf3ce44SJohn Forte &map, verbose_flag)) != 0) { 1937*fcf3ce44SJohn Forte (void) fprintf(stderr, 1938*fcf3ce44SJohn Forte MSGSTR(5548, 1939*fcf3ce44SJohn Forte " Error: Could not get" 1940*fcf3ce44SJohn Forte " map for %s.\n"), 1941*fcf3ce44SJohn Forte ses_path); 1942*fcf3ce44SJohn Forte return (err); 1943*fcf3ce44SJohn Forte } 1944*fcf3ce44SJohn Forte if (g_device_in_map(&map, tid)) { 1945*fcf3ce44SJohn Forte goto loop3; 1946*fcf3ce44SJohn Forte } 1947*fcf3ce44SJohn Forte FREE_DEV_ADDR(map.dev_addr); 1948*fcf3ce44SJohn Forte dl = dl->next; 1949*fcf3ce44SJohn Forte } 1950*fcf3ce44SJohn Forte if (timeout > PHOTON_SPINUP_TIMEOUT) { 1951*fcf3ce44SJohn Forte (void) fprintf(stderr, 1952*fcf3ce44SJohn Forte MSGSTR(5549, 1953*fcf3ce44SJohn Forte " Warning: Device not in" 1954*fcf3ce44SJohn Forte " loop map.\n")); 1955*fcf3ce44SJohn Forte FREE_DEV_ADDR(map.dev_addr); 1956*fcf3ce44SJohn Forte return (0); 1957*fcf3ce44SJohn Forte } 1958*fcf3ce44SJohn Forte if (wait_map_flag++ == 0) { 1959*fcf3ce44SJohn Forte (void) fprintf(stdout, 1960*fcf3ce44SJohn Forte MSGSTR(5550, 1961*fcf3ce44SJohn Forte " Waiting for the device " 1962*fcf3ce44SJohn Forte "to appear in the loop map:")); 1963*fcf3ce44SJohn Forte } else { 1964*fcf3ce44SJohn Forte (void) fprintf(stdout, "."); 1965*fcf3ce44SJohn Forte } 1966*fcf3ce44SJohn Forte timeout++; 1967*fcf3ce44SJohn Forte (void) sleep(PHOTON_SPINUP_DELAY); 1968*fcf3ce44SJohn Forte } 1969*fcf3ce44SJohn Forte loop3: 1970*fcf3ce44SJohn Forte if (wait_map_flag) { 1971*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 1972*fcf3ce44SJohn Forte } 1973*fcf3ce44SJohn Forte 1974*fcf3ce44SJohn Forte /* 1975*fcf3ce44SJohn Forte * Run drvconfig and disks to create 1976*fcf3ce44SJohn Forte * logical nodes 1977*fcf3ce44SJohn Forte */ 1978*fcf3ce44SJohn Forte for (;;) { 1979*fcf3ce44SJohn Forte /* pass "disks" as cmdStrg */ 1980*fcf3ce44SJohn Forte nArg = 3; 1981*fcf3ce44SJohn Forte if (h_execCmnd(cmdStrg[2], nArg) != 0) { 1982*fcf3ce44SJohn Forte (void) fprintf(stderr, 1983*fcf3ce44SJohn Forte MSGSTR(5551, 1984*fcf3ce44SJohn Forte " Could not " 1985*fcf3ce44SJohn Forte "run drvconfig.\n")); 1986*fcf3ce44SJohn Forte FREE_DEV_ADDR(map.dev_addr); 1987*fcf3ce44SJohn Forte return (L_DRVCONFIG_ERROR); 1988*fcf3ce44SJohn Forte } 1989*fcf3ce44SJohn Forte 1990*fcf3ce44SJohn Forte if (l_device_present(ses_path, tid, &map, 1991*fcf3ce44SJohn Forte verbose_flag, &dev_path) == 1) 1992*fcf3ce44SJohn Forte break; 1993*fcf3ce44SJohn Forte if (timeout > PHOTON_SPINUP_TIMEOUT) { 1994*fcf3ce44SJohn Forte (void) fprintf(stderr, 1995*fcf3ce44SJohn Forte MSGSTR(5552, 1996*fcf3ce44SJohn Forte " Warning: Could not find " 1997*fcf3ce44SJohn Forte "any node for inserted " 1998*fcf3ce44SJohn Forte "device\n")); 1999*fcf3ce44SJohn Forte FREE_DEV_ADDR(map.dev_addr); 2000*fcf3ce44SJohn Forte return (0); 2001*fcf3ce44SJohn Forte } 2002*fcf3ce44SJohn Forte if (wait_node_flag++ == 0) { 2003*fcf3ce44SJohn Forte (void) fprintf(stdout, 2004*fcf3ce44SJohn Forte MSGSTR(5553, 2005*fcf3ce44SJohn Forte " Waiting for the logical " 2006*fcf3ce44SJohn Forte "node to be created:")); 2007*fcf3ce44SJohn Forte } else { 2008*fcf3ce44SJohn Forte (void) fprintf(stdout, "."); 2009*fcf3ce44SJohn Forte } 2010*fcf3ce44SJohn Forte timeout++; 2011*fcf3ce44SJohn Forte (void) sleep(PHOTON_SPINUP_DELAY); 2012*fcf3ce44SJohn Forte } 2013*fcf3ce44SJohn Forte FREE_DEV_ADDR(map.dev_addr); 2014*fcf3ce44SJohn Forte if (wait_node_flag) { 2015*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 2016*fcf3ce44SJohn Forte } 2017*fcf3ce44SJohn Forte /* 2018*fcf3ce44SJohn Forte * In Solaris7, disks with -C 2019*fcf3ce44SJohn Forte * option creates the new links 2020*fcf3ce44SJohn Forte * and removes any stale links. 2021*fcf3ce44SJohn Forte * In pre-Solaris7 releases, just 2022*fcf3ce44SJohn Forte * disks should do it all. 2023*fcf3ce44SJohn Forte */ 2024*fcf3ce44SJohn Forte /* pass "disks -C" as cmdStrg */ 2025*fcf3ce44SJohn Forte nArg = 2; 2026*fcf3ce44SJohn Forte if (h_execCmnd(cmdStrg[0], nArg) != 0) { 2027*fcf3ce44SJohn Forte return (L_DISKS_ERROR); 2028*fcf3ce44SJohn Forte } 2029*fcf3ce44SJohn Forte /* 2030*fcf3ce44SJohn Forte * Get a new wwn list here in order to 2031*fcf3ce44SJohn Forte * get the multiple paths to a newly added 2032*fcf3ce44SJohn Forte * device. 2033*fcf3ce44SJohn Forte */ 2034*fcf3ce44SJohn Forte if ((err = g_get_wwn_list(&newWwn_list, 2035*fcf3ce44SJohn Forte verbose_flag)) != 0) { 2036*fcf3ce44SJohn Forte return (err); 2037*fcf3ce44SJohn Forte } 2038*fcf3ce44SJohn Forte if ((err = g_get_multipath(dev_path, &dl, 2039*fcf3ce44SJohn Forte newWwn_list, 0)) != 0) { 2040*fcf3ce44SJohn Forte return (err); 2041*fcf3ce44SJohn Forte } 2042*fcf3ce44SJohn Forte if ((err = h_display_logical_nodes(dl)) != 0) { 2043*fcf3ce44SJohn Forte return (err); 2044*fcf3ce44SJohn Forte } 2045*fcf3ce44SJohn Forte break; 2046*fcf3ce44SJohn Forte 2047*fcf3ce44SJohn Forte case REMOVE_DEVICE: 2048*fcf3ce44SJohn Forte /* 2049*fcf3ce44SJohn Forte * TBD 2050*fcf3ce44SJohn Forte * Need to check all loops. 2051*fcf3ce44SJohn Forte */ 2052*fcf3ce44SJohn Forte /* check whether device is still in loop map */ 2053*fcf3ce44SJohn Forte if ((err = g_get_dev_map(ses_path, &map, 2054*fcf3ce44SJohn Forte verbose_flag)) != 0) { 2055*fcf3ce44SJohn Forte return (err); 2056*fcf3ce44SJohn Forte } 2057*fcf3ce44SJohn Forte 2058*fcf3ce44SJohn Forte if ((map.hba_addr.port_topology == 2059*fcf3ce44SJohn Forte FC_TOP_PUBLIC_LOOP) || 2060*fcf3ce44SJohn Forte (map.hba_addr.port_topology == 2061*fcf3ce44SJohn Forte FC_TOP_FABRIC)) { 2062*fcf3ce44SJohn Forte /* public or fabric loop device */ 2063*fcf3ce44SJohn Forte free((void *)map.dev_addr); 2064*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(5540, 2065*fcf3ce44SJohn Forte "This operation is not " 2066*fcf3ce44SJohn Forte "supported in this topology.\n")); 2067*fcf3ce44SJohn Forte /* 2068*fcf3ce44SJohn Forte * calling routine expects a 0 return code 2069*fcf3ce44SJohn Forte * or a pre-defined luxadm error code. 2070*fcf3ce44SJohn Forte * Here we do not have a pre-defined error 2071*fcf3ce44SJohn Forte * code, a 0 is returned. 2072*fcf3ce44SJohn Forte */ 2073*fcf3ce44SJohn Forte return (0); 2074*fcf3ce44SJohn Forte } 2075*fcf3ce44SJohn Forte 2076*fcf3ce44SJohn Forte if (g_device_in_map(&map, tid)) { 2077*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(5554, 2078*fcf3ce44SJohn Forte " Warning: Device still in the loop map.\n")); 2079*fcf3ce44SJohn Forte FREE_DEV_ADDR(map.dev_addr); 2080*fcf3ce44SJohn Forte return (0); 2081*fcf3ce44SJohn Forte } 2082*fcf3ce44SJohn Forte FREE_DEV_ADDR(map.dev_addr); 2083*fcf3ce44SJohn Forte /* 2084*fcf3ce44SJohn Forte * In Solaris7, "disks -C" program 2085*fcf3ce44SJohn Forte * removes the /dev/{r}dsk entries. 2086*fcf3ce44SJohn Forte * The -C option is available only 2087*fcf3ce44SJohn Forte * for Solaris7. From Solaris8 or 2088*fcf3ce44SJohn Forte * higher releases, the "disks" program 2089*fcf3ce44SJohn Forte * will be replaced by devfsadm. 2090*fcf3ce44SJohn Forte */ 2091*fcf3ce44SJohn Forte /* pass "disks -C" as cmdStrg */ 2092*fcf3ce44SJohn Forte nArg = 2; 2093*fcf3ce44SJohn Forte if (h_execCmnd(cmdStrg[0], nArg) != 0) { 2094*fcf3ce44SJohn Forte return (L_DISKS_ERROR); 2095*fcf3ce44SJohn Forte } 2096*fcf3ce44SJohn Forte (void) fprintf(stdout, 2097*fcf3ce44SJohn Forte MSGSTR(5555, 2098*fcf3ce44SJohn Forte " Logical Nodes being removed" 2099*fcf3ce44SJohn Forte " under /dev/dsk/ and /dev/rdsk:\n")); 2100*fcf3ce44SJohn Forte (void) h_print_logical_nodes( 2101*fcf3ce44SJohn Forte hotplug_dev->dlhead); 2102*fcf3ce44SJohn Forte break; 2103*fcf3ce44SJohn Forte } 2104*fcf3ce44SJohn Forte return (0); 2105*fcf3ce44SJohn Forte } 2106*fcf3ce44SJohn Forte 2107*fcf3ce44SJohn Forte 2108*fcf3ce44SJohn Forte 2109*fcf3ce44SJohn Forte 2110*fcf3ce44SJohn Forte /* 2111*fcf3ce44SJohn Forte * Creates new ses entries under /dev/es 2112*fcf3ce44SJohn Forte * directory for the newly added 2113*fcf3ce44SJohn Forte * enclosures. 2114*fcf3ce44SJohn Forte * 2115*fcf3ce44SJohn Forte * RETURNS: 2116*fcf3ce44SJohn Forte * 0 if OK 2117*fcf3ce44SJohn Forte * non-zero otherwise 2118*fcf3ce44SJohn Forte */ 2119*fcf3ce44SJohn Forte static int 2120*fcf3ce44SJohn Forte h_post_insert_encl(timestruc_t ses_lastmtim) 2121*fcf3ce44SJohn Forte { 2122*fcf3ce44SJohn Forte struct stat ses_stat; 2123*fcf3ce44SJohn Forte char lname[MAXPATHLEN]; 2124*fcf3ce44SJohn Forte int err, found_newlink = 0; 2125*fcf3ce44SJohn Forte DIR *dir; 2126*fcf3ce44SJohn Forte struct dirent *dirent; 2127*fcf3ce44SJohn Forte Box_list *bl1, *box_list = NULL; 2128*fcf3ce44SJohn Forte 2129*fcf3ce44SJohn Forte 2130*fcf3ce44SJohn Forte if ((dir = opendir(SES_DIR)) == NULL) { 2131*fcf3ce44SJohn Forte return (L_OPEN_ES_DIR_FAILED); 2132*fcf3ce44SJohn Forte } 2133*fcf3ce44SJohn Forte if ((err = l_get_box_list(&box_list, 0)) != 0) { 2134*fcf3ce44SJohn Forte closedir(dir); 2135*fcf3ce44SJohn Forte return (err); 2136*fcf3ce44SJohn Forte } 2137*fcf3ce44SJohn Forte 2138*fcf3ce44SJohn Forte /* 2139*fcf3ce44SJohn Forte * The mod time of /dev/es was newer than the mod time prior to 2140*fcf3ce44SJohn Forte * insert so dir entry is checked at this time. 2141*fcf3ce44SJohn Forte */ 2142*fcf3ce44SJohn Forte while ((dirent = readdir(dir)) != (struct dirent *)NULL) { 2143*fcf3ce44SJohn Forte if (strcmp(dirent->d_name, ".") == 0 || 2144*fcf3ce44SJohn Forte strcmp(dirent->d_name, "..") == 0) 2145*fcf3ce44SJohn Forte continue; 2146*fcf3ce44SJohn Forte 2147*fcf3ce44SJohn Forte (void) sprintf(lname, SES_DIR"/%s", dirent->d_name); 2148*fcf3ce44SJohn Forte if (lstat(lname, &ses_stat) < 0) { 2149*fcf3ce44SJohn Forte (void) print_errString(L_LSTAT_ES_DIR_ERROR, 2150*fcf3ce44SJohn Forte lname); 2151*fcf3ce44SJohn Forte continue; 2152*fcf3ce44SJohn Forte } 2153*fcf3ce44SJohn Forte 2154*fcf3ce44SJohn Forte for (bl1 = box_list; bl1; bl1 = bl1->box_next) { 2155*fcf3ce44SJohn Forte if (strstr(lname, bl1->b_physical_path)) 2156*fcf3ce44SJohn Forte break; 2157*fcf3ce44SJohn Forte } 2158*fcf3ce44SJohn Forte 2159*fcf3ce44SJohn Forte if (box_list && bl1) 2160*fcf3ce44SJohn Forte continue; 2161*fcf3ce44SJohn Forte 2162*fcf3ce44SJohn Forte if (NEWER(ses_stat.st_ctim, ses_lastmtim)) { 2163*fcf3ce44SJohn Forte /* New enclosure was detected. */ 2164*fcf3ce44SJohn Forte found_newlink++; 2165*fcf3ce44SJohn Forte if (found_newlink == 1) { 2166*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5556, 2167*fcf3ce44SJohn Forte " New Logical Nodes under /dev/es:\n")); 2168*fcf3ce44SJohn Forte } 2169*fcf3ce44SJohn Forte (void) fprintf(stdout, "\t%s\n", 2170*fcf3ce44SJohn Forte dirent->d_name); 2171*fcf3ce44SJohn Forte } 2172*fcf3ce44SJohn Forte } 2173*fcf3ce44SJohn Forte if (!found_newlink) { 2174*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5662, 2175*fcf3ce44SJohn Forte " No new enclosure(s) were added!!\n\n")); 2176*fcf3ce44SJohn Forte } 2177*fcf3ce44SJohn Forte 2178*fcf3ce44SJohn Forte closedir(dir); 2179*fcf3ce44SJohn Forte 2180*fcf3ce44SJohn Forte (void) l_free_box_list(&box_list); 2181*fcf3ce44SJohn Forte return (0); 2182*fcf3ce44SJohn Forte } 2183*fcf3ce44SJohn Forte 2184*fcf3ce44SJohn Forte 2185*fcf3ce44SJohn Forte 2186*fcf3ce44SJohn Forte /* 2187*fcf3ce44SJohn Forte * performs the post removal of individual 2188*fcf3ce44SJohn Forte * FC_AL disks. 2189*fcf3ce44SJohn Forte * 2190*fcf3ce44SJohn Forte * RETURNS: 2191*fcf3ce44SJohn Forte * 0 if OK 2192*fcf3ce44SJohn Forte * non-zero otherwise 2193*fcf3ce44SJohn Forte */ 2194*fcf3ce44SJohn Forte static int 2195*fcf3ce44SJohn Forte h_post_remove_dev(Hotplug_Devlist *hotplug_disk, 2196*fcf3ce44SJohn Forte int todo, int verbose_flag) 2197*fcf3ce44SJohn Forte { 2198*fcf3ce44SJohn Forte char device_name[MAXNAMELEN], *dev_path = NULL; 2199*fcf3ce44SJohn Forte int tid, err; 2200*fcf3ce44SJohn Forte gfc_map_t map; 2201*fcf3ce44SJohn Forte int nArg; 2202*fcf3ce44SJohn Forte 2203*fcf3ce44SJohn Forte 2204*fcf3ce44SJohn Forte tid = hotplug_disk->tid; 2205*fcf3ce44SJohn Forte (void) sprintf(device_name, 2206*fcf3ce44SJohn Forte MSGSTR(5557, 2207*fcf3ce44SJohn Forte "\n Device: %s"), 2208*fcf3ce44SJohn Forte (hotplug_disk->dlhead)->logical_path); 2209*fcf3ce44SJohn Forte 2210*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s\n", device_name); 2211*fcf3ce44SJohn Forte 2212*fcf3ce44SJohn Forte dev_path = (hotplug_disk->dlhead)->dev_path; 2213*fcf3ce44SJohn Forte 2214*fcf3ce44SJohn Forte /* 2215*fcf3ce44SJohn Forte * On qlc, after a forcelip on a FC combo box, it sometimes takes 17 2216*fcf3ce44SJohn Forte * seconds for the loop to come back online. During this 17 seconds, 2217*fcf3ce44SJohn Forte * g_get_dev_map * will return L_NO_DEVICES_FOUND. This delay 2218*fcf3ce44SJohn Forte * has been added to assure that the L_NO_DEVICES_FOUND returned from 2219*fcf3ce44SJohn Forte * g_get_dev_map is not the result of the 17 second delay on FC combo. 2220*fcf3ce44SJohn Forte * This only affects qlc. 2221*fcf3ce44SJohn Forte */ 2222*fcf3ce44SJohn Forte if ((err = g_get_dev_map(dev_path, &map, verbose_flag)) != 0) { 2223*fcf3ce44SJohn Forte if ((err == L_NO_DEVICES_FOUND) && 2224*fcf3ce44SJohn Forte (strstr(dev_path, "SUNW,qlc@") != NULL)) { 2225*fcf3ce44SJohn Forte sleep(QLC_LIP_DELAY); 2226*fcf3ce44SJohn Forte if ((err = g_get_dev_map(dev_path, &map, verbose_flag)) 2227*fcf3ce44SJohn Forte != 0) { 2228*fcf3ce44SJohn Forte if (err != L_NO_DEVICES_FOUND) 2229*fcf3ce44SJohn Forte return (err); 2230*fcf3ce44SJohn Forte } 2231*fcf3ce44SJohn Forte } else if (err != L_NO_DEVICES_FOUND) 2232*fcf3ce44SJohn Forte return (err); 2233*fcf3ce44SJohn Forte } 2234*fcf3ce44SJohn Forte 2235*fcf3ce44SJohn Forte /* 2236*fcf3ce44SJohn Forte * if g_get_dev_map returns L_NO_DEVICES_FOUND, then there are not 2237*fcf3ce44SJohn Forte * devices attached to the HBA and there is no sense in calling 2238*fcf3ce44SJohn Forte * g_device_in_map(). 2239*fcf3ce44SJohn Forte */ 2240*fcf3ce44SJohn Forte if (err != L_NO_DEVICES_FOUND) { 2241*fcf3ce44SJohn Forte if ((map.hba_addr.port_topology == FC_TOP_PUBLIC_LOOP) || 2242*fcf3ce44SJohn Forte (map.hba_addr.port_topology == FC_TOP_FABRIC)) { 2243*fcf3ce44SJohn Forte /* public or fabric loop device */ 2244*fcf3ce44SJohn Forte free((void *)map.dev_addr); 2245*fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(5540, 2246*fcf3ce44SJohn Forte "This operation is not " 2247*fcf3ce44SJohn Forte "supported in this topology.\n")); 2248*fcf3ce44SJohn Forte return (0); 2249*fcf3ce44SJohn Forte } 2250*fcf3ce44SJohn Forte 2251*fcf3ce44SJohn Forte if (g_device_in_map(&map, tid) != 0) { 2252*fcf3ce44SJohn Forte (void) fprintf(stderr, 2253*fcf3ce44SJohn Forte MSGSTR(5558, 2254*fcf3ce44SJohn Forte " Warning: Device has" 2255*fcf3ce44SJohn Forte " not been removed from\n" 2256*fcf3ce44SJohn Forte " the slot and is still" 2257*fcf3ce44SJohn Forte " in the loop map.\n\n")); 2258*fcf3ce44SJohn Forte free((void *)map.dev_addr); 2259*fcf3ce44SJohn Forte return (0); 2260*fcf3ce44SJohn Forte } 2261*fcf3ce44SJohn Forte free((void *)map.dev_addr); 2262*fcf3ce44SJohn Forte } 2263*fcf3ce44SJohn Forte /* 2264*fcf3ce44SJohn Forte * In Solaris7, "disks -C" program 2265*fcf3ce44SJohn Forte * removes the /dev/{r}dsk entries. 2266*fcf3ce44SJohn Forte * The -C option is available only 2267*fcf3ce44SJohn Forte * for Solaris7. From Solaris8 or 2268*fcf3ce44SJohn Forte * higher releases, the "disks" program 2269*fcf3ce44SJohn Forte * will be replaced by devfsadm. 2270*fcf3ce44SJohn Forte */ 2271*fcf3ce44SJohn Forte /* pass "disks -C" as cmdStrg. */ 2272*fcf3ce44SJohn Forte nArg = 2; 2273*fcf3ce44SJohn Forte if (h_execCmnd(cmdStrg[0], nArg) != 0) { 2274*fcf3ce44SJohn Forte return (L_DISKS_ERROR); 2275*fcf3ce44SJohn Forte } 2276*fcf3ce44SJohn Forte /* pass "tapes -C as cmdStrg. */ 2277*fcf3ce44SJohn Forte if (h_execCmnd(cmdStrg[5], nArg) != 0) { 2278*fcf3ce44SJohn Forte return (L_TAPES_ERROR); 2279*fcf3ce44SJohn Forte } 2280*fcf3ce44SJohn Forte (void) h_print_logical_nodes(hotplug_disk->dlhead); 2281*fcf3ce44SJohn Forte 2282*fcf3ce44SJohn Forte return (0); 2283*fcf3ce44SJohn Forte } 2284*fcf3ce44SJohn Forte 2285*fcf3ce44SJohn Forte 2286*fcf3ce44SJohn Forte 2287*fcf3ce44SJohn Forte /* 2288*fcf3ce44SJohn Forte * Gets the last modification time for 2289*fcf3ce44SJohn Forte * /dev/es/ and /dev/rdsk directories 2290*fcf3ce44SJohn Forte * and passes these values to the caller. 2291*fcf3ce44SJohn Forte * 2292*fcf3ce44SJohn Forte * RETURNS: 2293*fcf3ce44SJohn Forte * 0 if OK 2294*fcf3ce44SJohn Forte * non-zero in case of error 2295*fcf3ce44SJohn Forte */ 2296*fcf3ce44SJohn Forte static int 2297*fcf3ce44SJohn Forte h_pre_insert_encl_dev(timestruc_t *ses_time, timestruc_t *dsk_time, 2298*fcf3ce44SJohn Forte timestruc_t *rmt_time) 2299*fcf3ce44SJohn Forte { 2300*fcf3ce44SJohn Forte struct stat ses_stat, dsk_stat, rmt_stat; 2301*fcf3ce44SJohn Forte 2302*fcf3ce44SJohn Forte if (stat(SES_DIR, &ses_stat) < 0) { 2303*fcf3ce44SJohn Forte /* 2304*fcf3ce44SJohn Forte * Even if there exists no /dev/es don't fail it. 2305*fcf3ce44SJohn Forte * The host doesn't have to have any enclosure device 2306*fcf3ce44SJohn Forte * configured. 2307*fcf3ce44SJohn Forte */ 2308*fcf3ce44SJohn Forte if (errno == ENOENT) { 2309*fcf3ce44SJohn Forte ses_time = (timestruc_t *)NULL; 2310*fcf3ce44SJohn Forte } else { 2311*fcf3ce44SJohn Forte return (L_LSTAT_ES_DIR_ERROR); 2312*fcf3ce44SJohn Forte } 2313*fcf3ce44SJohn Forte } else { 2314*fcf3ce44SJohn Forte *ses_time = ses_stat.st_mtim; 2315*fcf3ce44SJohn Forte } 2316*fcf3ce44SJohn Forte 2317*fcf3ce44SJohn Forte if (stat(DEV_DSK_DIR, &dsk_stat) < 0) { 2318*fcf3ce44SJohn Forte return (L_STAT_DEV_DIR_ERROR); 2319*fcf3ce44SJohn Forte } else { 2320*fcf3ce44SJohn Forte *dsk_time = dsk_stat.st_mtim; 2321*fcf3ce44SJohn Forte } 2322*fcf3ce44SJohn Forte if (stat(DEV_TAPE_DIR, &rmt_stat) < 0) { 2323*fcf3ce44SJohn Forte /* 2324*fcf3ce44SJohn Forte * Even if there exists no /dev/rmt don't fail it. 2325*fcf3ce44SJohn Forte * The host doesn't have to have any tape device 2326*fcf3ce44SJohn Forte * configured. 2327*fcf3ce44SJohn Forte */ 2328*fcf3ce44SJohn Forte if (errno == ENOENT) { 2329*fcf3ce44SJohn Forte rmt_time = (timestruc_t *)NULL; 2330*fcf3ce44SJohn Forte } else { 2331*fcf3ce44SJohn Forte return (L_STAT_RMT_DIR_ERROR); 2332*fcf3ce44SJohn Forte } 2333*fcf3ce44SJohn Forte } else { 2334*fcf3ce44SJohn Forte *rmt_time = rmt_stat.st_mtim; 2335*fcf3ce44SJohn Forte } 2336*fcf3ce44SJohn Forte 2337*fcf3ce44SJohn Forte return (0); 2338*fcf3ce44SJohn Forte } 2339*fcf3ce44SJohn Forte 2340*fcf3ce44SJohn Forte 2341*fcf3ce44SJohn Forte 2342*fcf3ce44SJohn Forte /* 2343*fcf3ce44SJohn Forte * Waits for loop intialization to complete 2344*fcf3ce44SJohn Forte * and runs drvconfig, disks and devlinks to create device nodes 2345*fcf3ce44SJohn Forte * for devices that are being added and prints the newly created 2346*fcf3ce44SJohn Forte * /dev/rdsk entries. 2347*fcf3ce44SJohn Forte * 2348*fcf3ce44SJohn Forte * RETURNS: 2349*fcf3ce44SJohn Forte * 0 if OK 2350*fcf3ce44SJohn Forte * non-zero in case of error 2351*fcf3ce44SJohn Forte */ 2352*fcf3ce44SJohn Forte 2353*fcf3ce44SJohn Forte static int 2354*fcf3ce44SJohn Forte h_post_insert_dev(timestruc_t dsk_lastmtim, timestruc_t rmt_lastmtim) 2355*fcf3ce44SJohn Forte { 2356*fcf3ce44SJohn Forte int found_newlink = 0, nArg; 2357*fcf3ce44SJohn Forte 2358*fcf3ce44SJohn Forte (void) fprintf(stdout, 2359*fcf3ce44SJohn Forte MSGSTR(5560, 2360*fcf3ce44SJohn Forte "\nWaiting for Loop Initialization to complete...\n")); 2361*fcf3ce44SJohn Forte 2362*fcf3ce44SJohn Forte /* 2363*fcf3ce44SJohn Forte * We sleep here to let the system create nodes. Not sleeping 2364*fcf3ce44SJohn Forte * could cause the drvconfig below to run too soon. 2365*fcf3ce44SJohn Forte */ 2366*fcf3ce44SJohn Forte 2367*fcf3ce44SJohn Forte (void) sleep(NODE_CREATION_TIME); 2368*fcf3ce44SJohn Forte 2369*fcf3ce44SJohn Forte /* 2370*fcf3ce44SJohn Forte * Run drvconfig and disks to create 2371*fcf3ce44SJohn Forte * logical nodes 2372*fcf3ce44SJohn Forte */ 2373*fcf3ce44SJohn Forte /* pass "drvconfig" as cmdStrg */ 2374*fcf3ce44SJohn Forte nArg = 1; 2375*fcf3ce44SJohn Forte if (h_execCmnd(cmdStrg[3], nArg) != 0) { 2376*fcf3ce44SJohn Forte return (L_DRVCONFIG_ERROR); 2377*fcf3ce44SJohn Forte } 2378*fcf3ce44SJohn Forte 2379*fcf3ce44SJohn Forte /* 2380*fcf3ce44SJohn Forte * In 2.7, disks with the -C 2381*fcf3ce44SJohn Forte * option should be used to 2382*fcf3ce44SJohn Forte * create new links and remove 2383*fcf3ce44SJohn Forte * any stale links. 2384*fcf3ce44SJohn Forte * In pre-2.7 releases, just 2385*fcf3ce44SJohn Forte * disks should do it all. 2386*fcf3ce44SJohn Forte */ 2387*fcf3ce44SJohn Forte 2388*fcf3ce44SJohn Forte /* pass "disks -C" as cmdStrg */ 2389*fcf3ce44SJohn Forte nArg = 2; 2390*fcf3ce44SJohn Forte if (h_execCmnd(cmdStrg[0], nArg) != 0) { 2391*fcf3ce44SJohn Forte return (L_DISKS_ERROR); 2392*fcf3ce44SJohn Forte } 2393*fcf3ce44SJohn Forte /* pass "tapes -C as cmdStrg */ 2394*fcf3ce44SJohn Forte if (h_execCmnd(cmdStrg[5], nArg) != 0) { 2395*fcf3ce44SJohn Forte return (L_TAPES_ERROR); 2396*fcf3ce44SJohn Forte } 2397*fcf3ce44SJohn Forte 2398*fcf3ce44SJohn Forte /* pass "devlinks" as cmdStrg */ 2399*fcf3ce44SJohn Forte nArg = 1; 2400*fcf3ce44SJohn Forte if (h_execCmnd(cmdStrg[4], nArg) != 0) { 2401*fcf3ce44SJohn Forte return (L_DEVLINKS_ERROR); 2402*fcf3ce44SJohn Forte } 2403*fcf3ce44SJohn Forte 2404*fcf3ce44SJohn Forte /* check /dev/dsk and /dev/rmt for new links */ 2405*fcf3ce44SJohn Forte found_newlink = h_find_new_device_link(DEV_DSK_DIR, dsk_lastmtim) + 2406*fcf3ce44SJohn Forte h_find_new_device_link(DEV_TAPE_DIR, rmt_lastmtim); 2407*fcf3ce44SJohn Forte 2408*fcf3ce44SJohn Forte if (!found_newlink) { 2409*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5562, 2410*fcf3ce44SJohn Forte " No new device(s) were added!!\n\n")); 2411*fcf3ce44SJohn Forte } 2412*fcf3ce44SJohn Forte 2413*fcf3ce44SJohn Forte return (0); 2414*fcf3ce44SJohn Forte } 2415*fcf3ce44SJohn Forte 2416*fcf3ce44SJohn Forte 2417*fcf3ce44SJohn Forte 2418*fcf3ce44SJohn Forte /* 2419*fcf3ce44SJohn Forte * Performs the pre hotplug operations on SENA enclosure(s), 2420*fcf3ce44SJohn Forte * SENA disk(s) and individual fcal disk(s). 2421*fcf3ce44SJohn Forte * If the device is failed to remove, then it removes the device from the 2422*fcf3ce44SJohn Forte * hotplug list and continues with the next device in the list. 2423*fcf3ce44SJohn Forte * 2424*fcf3ce44SJohn Forte * RETURNS: 2425*fcf3ce44SJohn Forte * 0 if OK 2426*fcf3ce44SJohn Forte * prints an error message to stderr and returns 0 2427*fcf3ce44SJohn Forte */ 2428*fcf3ce44SJohn Forte static int 2429*fcf3ce44SJohn Forte h_pre_hotplug(Hotplug_Devlist **disk_list_head_ptr, 2430*fcf3ce44SJohn Forte WWN_list *wwn_list, int todo, 2431*fcf3ce44SJohn Forte int verbose_flag, int force_flag) 2432*fcf3ce44SJohn Forte { 2433*fcf3ce44SJohn Forte Hotplug_Devlist *list, *disk_list; 2434*fcf3ce44SJohn Forte int err = 0; 2435*fcf3ce44SJohn Forte 2436*fcf3ce44SJohn Forte disk_list = *disk_list_head_ptr; 2437*fcf3ce44SJohn Forte while (disk_list != NULL) { 2438*fcf3ce44SJohn Forte if ((disk_list->dev_type == DTYPE_ESI) || 2439*fcf3ce44SJohn Forte (disk_list->dev_location == SENA)) { 2440*fcf3ce44SJohn Forte if ((err = h_pre_hotplug_sena(disk_list, wwn_list, 2441*fcf3ce44SJohn Forte todo, verbose_flag, force_flag)) != 0) { 2442*fcf3ce44SJohn Forte (void) print_errString(err, 2443*fcf3ce44SJohn Forte disk_list->dev_name); 2444*fcf3ce44SJohn Forte goto delete; 2445*fcf3ce44SJohn Forte } 2446*fcf3ce44SJohn Forte } else if (disk_list->dev_location == NON_SENA) { 2447*fcf3ce44SJohn Forte if ((err = h_pre_remove_dev(disk_list, wwn_list, 2448*fcf3ce44SJohn Forte verbose_flag, force_flag)) != 0) { 2449*fcf3ce44SJohn Forte (void) print_errString(err, 2450*fcf3ce44SJohn Forte disk_list->dev_name); 2451*fcf3ce44SJohn Forte goto delete; 2452*fcf3ce44SJohn Forte } 2453*fcf3ce44SJohn Forte } 2454*fcf3ce44SJohn Forte disk_list = disk_list->next; 2455*fcf3ce44SJohn Forte continue; 2456*fcf3ce44SJohn Forte delete: 2457*fcf3ce44SJohn Forte list = disk_list->prev; 2458*fcf3ce44SJohn Forte if (list != NULL) { 2459*fcf3ce44SJohn Forte list->next = disk_list->next; 2460*fcf3ce44SJohn Forte if (list->next != NULL) 2461*fcf3ce44SJohn Forte list->next->prev = list; 2462*fcf3ce44SJohn Forte } 2463*fcf3ce44SJohn Forte list = disk_list; 2464*fcf3ce44SJohn Forte disk_list = disk_list->next; 2465*fcf3ce44SJohn Forte if (list == *disk_list_head_ptr) 2466*fcf3ce44SJohn Forte *disk_list_head_ptr = disk_list; 2467*fcf3ce44SJohn Forte (void) g_free_multipath(list->seslist); 2468*fcf3ce44SJohn Forte (void) g_free_multipath(list->dlhead); 2469*fcf3ce44SJohn Forte (void) free(list); 2470*fcf3ce44SJohn Forte } 2471*fcf3ce44SJohn Forte return (0); 2472*fcf3ce44SJohn Forte } 2473*fcf3ce44SJohn Forte 2474*fcf3ce44SJohn Forte 2475*fcf3ce44SJohn Forte 2476*fcf3ce44SJohn Forte /* 2477*fcf3ce44SJohn Forte * Performs the post removal of a list of SENA enclosure(s), 2478*fcf3ce44SJohn Forte * SENA disk(s) and individual fcal disk(s). 2479*fcf3ce44SJohn Forte * 2480*fcf3ce44SJohn Forte * RETURNS: 2481*fcf3ce44SJohn Forte * 0 O.K. 2482*fcf3ce44SJohn Forte * non-zero otherwise 2483*fcf3ce44SJohn Forte */ 2484*fcf3ce44SJohn Forte static int 2485*fcf3ce44SJohn Forte h_post_hotplug(Hotplug_Devlist *hotplug_dlist, 2486*fcf3ce44SJohn Forte WWN_list *wwn_list, int todo, 2487*fcf3ce44SJohn Forte int verbose_flag, int force_flag, int enc_type) 2488*fcf3ce44SJohn Forte { 2489*fcf3ce44SJohn Forte Hotplug_Devlist *list; 2490*fcf3ce44SJohn Forte int err; 2491*fcf3ce44SJohn Forte 2492*fcf3ce44SJohn Forte /* Do a lip on every loop so that we get the latest loop maps */ 2493*fcf3ce44SJohn Forte if (todo != INSERT_DEVICE) { 2494*fcf3ce44SJohn Forte if ((err = g_forcelip_all(hotplug_dlist)) != 0) { 2495*fcf3ce44SJohn Forte return (err); 2496*fcf3ce44SJohn Forte } 2497*fcf3ce44SJohn Forte } 2498*fcf3ce44SJohn Forte 2499*fcf3ce44SJohn Forte while (hotplug_dlist != NULL) { 2500*fcf3ce44SJohn Forte if ((hotplug_dlist->dev_location == SENA) || 2501*fcf3ce44SJohn Forte (hotplug_dlist->dev_type == DTYPE_ESI)) { 2502*fcf3ce44SJohn Forte if ((err = h_post_hotplug_sena(hotplug_dlist, wwn_list, todo, 2503*fcf3ce44SJohn Forte verbose_flag, force_flag, enc_type)) != 0) 2504*fcf3ce44SJohn Forte (void) print_errString(err, hotplug_dlist->dev_name); 2505*fcf3ce44SJohn Forte } else if (hotplug_dlist->dev_location == NON_SENA) { 2506*fcf3ce44SJohn Forte if ((err = h_post_remove_dev(hotplug_dlist, 2507*fcf3ce44SJohn Forte todo, verbose_flag)) != 0) 2508*fcf3ce44SJohn Forte (void) print_errString(err, 2509*fcf3ce44SJohn Forte hotplug_dlist->dev_name); 2510*fcf3ce44SJohn Forte } 2511*fcf3ce44SJohn Forte list = hotplug_dlist; 2512*fcf3ce44SJohn Forte hotplug_dlist = hotplug_dlist->next; 2513*fcf3ce44SJohn Forte (void) g_free_multipath(list->seslist); 2514*fcf3ce44SJohn Forte (void) g_free_multipath(list->dlhead); 2515*fcf3ce44SJohn Forte (void) free(list); 2516*fcf3ce44SJohn Forte } 2517*fcf3ce44SJohn Forte return (0); 2518*fcf3ce44SJohn Forte } 2519*fcf3ce44SJohn Forte 2520*fcf3ce44SJohn Forte 2521*fcf3ce44SJohn Forte /* 2522*fcf3ce44SJohn Forte * removes the device's logical paths. 2523*fcf3ce44SJohn Forte * 2524*fcf3ce44SJohn Forte * RETURNS: 2525*fcf3ce44SJohn Forte * 0 if OK 2526*fcf3ce44SJohn Forte * non-zero otherwise 2527*fcf3ce44SJohn Forte */ 2528*fcf3ce44SJohn Forte static int 2529*fcf3ce44SJohn Forte h_remove_nodes(struct dlist *dl) 2530*fcf3ce44SJohn Forte { 2531*fcf3ce44SJohn Forte char link[MAXPATHLEN], path[MAXPATHLEN]; 2532*fcf3ce44SJohn Forte char lname[MAXPATHLEN], *ptr; 2533*fcf3ce44SJohn Forte DIR *dir; 2534*fcf3ce44SJohn Forte struct dirent *dirent; 2535*fcf3ce44SJohn Forte struct dlist *dlist; 2536*fcf3ce44SJohn Forte 2537*fcf3ce44SJohn Forte if ((dir = opendir(DEV_DSK_DIR)) == NULL) { 2538*fcf3ce44SJohn Forte return (L_READ_DEV_DIR_ERROR); 2539*fcf3ce44SJohn Forte } 2540*fcf3ce44SJohn Forte if (dl == NULL) { 2541*fcf3ce44SJohn Forte /* pass "disks" as cmdStrg */ 2542*fcf3ce44SJohn Forte if (h_execCmnd(cmdStrg[1], 1) != 0) { 2543*fcf3ce44SJohn Forte return (L_DISKS_ERROR); 2544*fcf3ce44SJohn Forte } 2545*fcf3ce44SJohn Forte } 2546*fcf3ce44SJohn Forte 2547*fcf3ce44SJohn Forte (void) fprintf(stdout, 2548*fcf3ce44SJohn Forte MSGSTR(5563, 2549*fcf3ce44SJohn Forte " Removing Logical Nodes: \n")); 2550*fcf3ce44SJohn Forte 2551*fcf3ce44SJohn Forte while ((dirent = readdir(dir)) != (struct dirent *)NULL) { 2552*fcf3ce44SJohn Forte if (strcmp(dirent->d_name, ".") == 0 || 2553*fcf3ce44SJohn Forte strcmp(dirent->d_name, "..") == 0) { 2554*fcf3ce44SJohn Forte continue; 2555*fcf3ce44SJohn Forte } 2556*fcf3ce44SJohn Forte (void) sprintf(lname, DEV_DSK_DIR"/%s", dirent->d_name); 2557*fcf3ce44SJohn Forte if (readlink((const char *)lname, (char *)link, 2558*fcf3ce44SJohn Forte (size_t)MAXPATHLEN) <= 0) { 2559*fcf3ce44SJohn Forte (void) fprintf(stderr, 2560*fcf3ce44SJohn Forte MSGSTR(5564, 2561*fcf3ce44SJohn Forte " Error: Could not read %s\n"), 2562*fcf3ce44SJohn Forte lname); 2563*fcf3ce44SJohn Forte continue; 2564*fcf3ce44SJohn Forte } 2565*fcf3ce44SJohn Forte for (dlist = dl; dlist != NULL; dlist = dlist->next) { 2566*fcf3ce44SJohn Forte (void) strcpy(path, dlist->dev_path); 2567*fcf3ce44SJohn Forte ptr = strrchr(path, ':'); 2568*fcf3ce44SJohn Forte if (ptr) 2569*fcf3ce44SJohn Forte *ptr = '\0'; 2570*fcf3ce44SJohn Forte if (strstr(link, path)) { 2571*fcf3ce44SJohn Forte (void) unlink(lname); 2572*fcf3ce44SJohn Forte (void) sprintf(lname, "/dev/rdsk/%s", 2573*fcf3ce44SJohn Forte dirent->d_name); 2574*fcf3ce44SJohn Forte (void) fprintf(stdout, 2575*fcf3ce44SJohn Forte MSGSTR(5565, 2576*fcf3ce44SJohn Forte "\tRemoving %s\n"), 2577*fcf3ce44SJohn Forte dirent->d_name); 2578*fcf3ce44SJohn Forte (void) unlink(lname); 2579*fcf3ce44SJohn Forte } 2580*fcf3ce44SJohn Forte } 2581*fcf3ce44SJohn Forte } 2582*fcf3ce44SJohn Forte closedir(dir); 2583*fcf3ce44SJohn Forte return (0); 2584*fcf3ce44SJohn Forte } 2585*fcf3ce44SJohn Forte 2586*fcf3ce44SJohn Forte 2587*fcf3ce44SJohn Forte 2588*fcf3ce44SJohn Forte /* 2589*fcf3ce44SJohn Forte * removes the SENA's ses paths. 2590*fcf3ce44SJohn Forte * 2591*fcf3ce44SJohn Forte * RETURNS: 2592*fcf3ce44SJohn Forte * 0 if OK 2593*fcf3ce44SJohn Forte * non-zero otherwise 2594*fcf3ce44SJohn Forte */ 2595*fcf3ce44SJohn Forte static int 2596*fcf3ce44SJohn Forte h_remove_ses_nodes(struct dlist *dlist) 2597*fcf3ce44SJohn Forte { 2598*fcf3ce44SJohn Forte char link[MAXPATHLEN], lname[MAXPATHLEN]; 2599*fcf3ce44SJohn Forte DIR *dir; 2600*fcf3ce44SJohn Forte struct dirent *dirent; 2601*fcf3ce44SJohn Forte struct dlist *dl; 2602*fcf3ce44SJohn Forte 2603*fcf3ce44SJohn Forte 2604*fcf3ce44SJohn Forte if ((dir = opendir(SES_DIR)) == NULL) { 2605*fcf3ce44SJohn Forte return (L_READ_DEV_DIR_ERROR); 2606*fcf3ce44SJohn Forte } 2607*fcf3ce44SJohn Forte 2608*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5566, " Removing Ses Nodes:\n")); 2609*fcf3ce44SJohn Forte 2610*fcf3ce44SJohn Forte /* 2611*fcf3ce44SJohn Forte * Remove the ses entries 2612*fcf3ce44SJohn Forte * of the form ses<#> 2613*fcf3ce44SJohn Forte * from the /dev/es directory. 2614*fcf3ce44SJohn Forte */ 2615*fcf3ce44SJohn Forte 2616*fcf3ce44SJohn Forte while ((dirent = readdir(dir)) != (struct dirent *)NULL) { 2617*fcf3ce44SJohn Forte if (strcmp(dirent->d_name, ".") == 0 || 2618*fcf3ce44SJohn Forte strcmp(dirent->d_name, "..") == 0) 2619*fcf3ce44SJohn Forte continue; 2620*fcf3ce44SJohn Forte 2621*fcf3ce44SJohn Forte (void) sprintf(lname, SES_DIR"/%s", dirent->d_name); 2622*fcf3ce44SJohn Forte if (readlink((const char *)lname, (char *)link, 2623*fcf3ce44SJohn Forte (size_t)MAXPATHLEN) <= 0) { 2624*fcf3ce44SJohn Forte (void) fprintf(stderr, 2625*fcf3ce44SJohn Forte MSGSTR(5564, 2626*fcf3ce44SJohn Forte " Error: Could not read %s\n"), 2627*fcf3ce44SJohn Forte lname); 2628*fcf3ce44SJohn Forte continue; 2629*fcf3ce44SJohn Forte } 2630*fcf3ce44SJohn Forte for (dl = dlist; dl != NULL; dl = dl->next) { 2631*fcf3ce44SJohn Forte if (strstr(link, dl->dev_path)) { 2632*fcf3ce44SJohn Forte (void) fprintf(stdout, 2633*fcf3ce44SJohn Forte MSGSTR(5568, 2634*fcf3ce44SJohn Forte "\tRemoving %s\n"), 2635*fcf3ce44SJohn Forte lname); 2636*fcf3ce44SJohn Forte (void) unlink(lname); 2637*fcf3ce44SJohn Forte } 2638*fcf3ce44SJohn Forte } 2639*fcf3ce44SJohn Forte } 2640*fcf3ce44SJohn Forte closedir(dir); 2641*fcf3ce44SJohn Forte (void) g_free_multipath(dlist); 2642*fcf3ce44SJohn Forte return (0); 2643*fcf3ce44SJohn Forte } 2644*fcf3ce44SJohn Forte 2645*fcf3ce44SJohn Forte 2646*fcf3ce44SJohn Forte /* 2647*fcf3ce44SJohn Forte * prints the device's logical 2648*fcf3ce44SJohn Forte * paths for disks to stdout. 2649*fcf3ce44SJohn Forte * 2650*fcf3ce44SJohn Forte * RETURNS: 2651*fcf3ce44SJohn Forte * 0 if OK 2652*fcf3ce44SJohn Forte * non-zero otherwise 2653*fcf3ce44SJohn Forte */ 2654*fcf3ce44SJohn Forte static void 2655*fcf3ce44SJohn Forte h_print_logical_nodes(struct dlist *disk_list) 2656*fcf3ce44SJohn Forte { 2657*fcf3ce44SJohn Forte char *lpath, *ptr, *buf_ptr, buf[MAXNAMELEN], dev[MAXNAMELEN]; 2658*fcf3ce44SJohn Forte struct dlist *dlist; 2659*fcf3ce44SJohn Forte int i, found_dev = 0; 2660*fcf3ce44SJohn Forte char *tape_entries[] = { "", "b", "bn", "c", "cb", "cbn", "cn", 2661*fcf3ce44SJohn Forte "h", "hb", "hbn", "hn", "l", "lb", 2662*fcf3ce44SJohn Forte "lbn", "ln", "m", "mb", "mbn", "mn", 2663*fcf3ce44SJohn Forte "n", "u", "ub", "ubn", "un", NULL}; 2664*fcf3ce44SJohn Forte 2665*fcf3ce44SJohn Forte for (dlist = disk_list; dlist != NULL; dlist = dlist->next) { 2666*fcf3ce44SJohn Forte lpath = dlist->logical_path; 2667*fcf3ce44SJohn Forte if ((ptr = strrchr(lpath, 'c')) == NULL) 2668*fcf3ce44SJohn Forte continue; 2669*fcf3ce44SJohn Forte (void) strcpy(buf, ptr); 2670*fcf3ce44SJohn Forte if ((ptr = strrchr(buf, 's')) == NULL) 2671*fcf3ce44SJohn Forte continue; 2672*fcf3ce44SJohn Forte *(++ptr) = NULL; 2673*fcf3ce44SJohn Forte found_dev++; 2674*fcf3ce44SJohn Forte if (found_dev == 1) 2675*fcf3ce44SJohn Forte (void) fprintf(stdout, 2676*fcf3ce44SJohn Forte MSGSTR(5559, " Logical Nodes being " 2677*fcf3ce44SJohn Forte "removed under /dev/dsk/ and " 2678*fcf3ce44SJohn Forte "/dev/rdsk:\n")); 2679*fcf3ce44SJohn Forte for (i = 0; i <= 7; i++) { 2680*fcf3ce44SJohn Forte (void) sprintf(dev, "%s%d", buf, i); 2681*fcf3ce44SJohn Forte (void) fprintf(stdout, "\t%s\n", dev); 2682*fcf3ce44SJohn Forte } 2683*fcf3ce44SJohn Forte } 2684*fcf3ce44SJohn Forte found_dev = 0; 2685*fcf3ce44SJohn Forte for (dlist = disk_list; dlist != NULL; dlist = dlist->next) { 2686*fcf3ce44SJohn Forte lpath = dlist->logical_path; 2687*fcf3ce44SJohn Forte if (strstr(lpath, DEV_TAPE_DIR)) { 2688*fcf3ce44SJohn Forte if ((ptr = strrchr(lpath, '/')) == NULL) 2689*fcf3ce44SJohn Forte continue; 2690*fcf3ce44SJohn Forte found_dev++; 2691*fcf3ce44SJohn Forte if (found_dev == 1) 2692*fcf3ce44SJohn Forte (void) fprintf(stdout, "Logical Nodes being " 2693*fcf3ce44SJohn Forte "removed under /dev/rmt:\n"); 2694*fcf3ce44SJohn Forte ptr++; 2695*fcf3ce44SJohn Forte buf_ptr = ptr; 2696*fcf3ce44SJohn Forte while (*ptr >= '0' && *ptr <= '9') 2697*fcf3ce44SJohn Forte ptr++; 2698*fcf3ce44SJohn Forte *ptr = NULL; 2699*fcf3ce44SJohn Forte for (i = 0, ptr = tape_entries[0]; 2700*fcf3ce44SJohn Forte ptr != NULL; 2701*fcf3ce44SJohn Forte i++, ptr = tape_entries[i]) { 2702*fcf3ce44SJohn Forte (void) sprintf(dev, "%s%s", buf_ptr, ptr); 2703*fcf3ce44SJohn Forte (void) fprintf(stdout, "\t%s\n", dev); 2704*fcf3ce44SJohn Forte } 2705*fcf3ce44SJohn Forte } 2706*fcf3ce44SJohn Forte } 2707*fcf3ce44SJohn Forte } 2708*fcf3ce44SJohn Forte 2709*fcf3ce44SJohn Forte /* 2710*fcf3ce44SJohn Forte * displays logical paths to a 2711*fcf3ce44SJohn Forte * device to stdout. 2712*fcf3ce44SJohn Forte * 2713*fcf3ce44SJohn Forte * RETURNS: 2714*fcf3ce44SJohn Forte * 0 if OK 2715*fcf3ce44SJohn Forte * non-zero otherwise 2716*fcf3ce44SJohn Forte */ 2717*fcf3ce44SJohn Forte static int 2718*fcf3ce44SJohn Forte h_display_logical_nodes(struct dlist *dlist) 2719*fcf3ce44SJohn Forte { 2720*fcf3ce44SJohn Forte char link[MAXPATHLEN], path[MAXPATHLEN]; 2721*fcf3ce44SJohn Forte char lname[MAXPATHLEN], *d1; 2722*fcf3ce44SJohn Forte DIR *dir; 2723*fcf3ce44SJohn Forte struct dirent *dirent; 2724*fcf3ce44SJohn Forte struct dlist *dl; 2725*fcf3ce44SJohn Forte 2726*fcf3ce44SJohn Forte 2727*fcf3ce44SJohn Forte if ((dir = opendir(DEV_DSK_DIR)) == NULL) { 2728*fcf3ce44SJohn Forte return (L_READ_DEV_DIR_ERROR); 2729*fcf3ce44SJohn Forte } 2730*fcf3ce44SJohn Forte (void) fprintf(stdout, 2731*fcf3ce44SJohn Forte MSGSTR(5569, 2732*fcf3ce44SJohn Forte " Logical Nodes under /dev/dsk and /dev/rdsk :\n")); 2733*fcf3ce44SJohn Forte 2734*fcf3ce44SJohn Forte while ((dirent = readdir(dir)) != (struct dirent *)NULL) { 2735*fcf3ce44SJohn Forte if (strcmp(dirent->d_name, ".") == 0 || 2736*fcf3ce44SJohn Forte strcmp(dirent->d_name, "..") == 0) { 2737*fcf3ce44SJohn Forte continue; 2738*fcf3ce44SJohn Forte } 2739*fcf3ce44SJohn Forte (void) sprintf(lname, DEV_DSK_DIR"/%s", dirent->d_name); 2740*fcf3ce44SJohn Forte if (readlink((const char *)lname, (char *)link, 2741*fcf3ce44SJohn Forte (size_t)MAXPATHLEN) <= 0) { 2742*fcf3ce44SJohn Forte (void) print_errString(L_SYMLINK_ERROR, lname); 2743*fcf3ce44SJohn Forte continue; 2744*fcf3ce44SJohn Forte } 2745*fcf3ce44SJohn Forte for (dl = dlist; dl; dl = dl->next) { 2746*fcf3ce44SJohn Forte (void) strcpy(path, dl->dev_path); 2747*fcf3ce44SJohn Forte d1 = strrchr(path, ':'); 2748*fcf3ce44SJohn Forte if (d1) 2749*fcf3ce44SJohn Forte *d1 = '\0'; 2750*fcf3ce44SJohn Forte if (strstr(link, path)) { 2751*fcf3ce44SJohn Forte (void) fprintf(stdout, 2752*fcf3ce44SJohn Forte "\t%s\n", 2753*fcf3ce44SJohn Forte dirent->d_name); 2754*fcf3ce44SJohn Forte } 2755*fcf3ce44SJohn Forte } 2756*fcf3ce44SJohn Forte } 2757*fcf3ce44SJohn Forte 2758*fcf3ce44SJohn Forte closedir(dir); 2759*fcf3ce44SJohn Forte return (0); 2760*fcf3ce44SJohn Forte } 2761*fcf3ce44SJohn Forte 2762*fcf3ce44SJohn Forte 2763*fcf3ce44SJohn Forte 2764*fcf3ce44SJohn Forte /* 2765*fcf3ce44SJohn Forte * prints a list of devices which 2766*fcf3ce44SJohn Forte * will be inserted or removed 2767*fcf3ce44SJohn Forte * to the stdout and asks for 2768*fcf3ce44SJohn Forte * the user's confirmation. 2769*fcf3ce44SJohn Forte * 2770*fcf3ce44SJohn Forte * RETURNS: 2771*fcf3ce44SJohn Forte * 0 if OK 2772*fcf3ce44SJohn Forte * non-zero otherwise 2773*fcf3ce44SJohn Forte */ 2774*fcf3ce44SJohn Forte static int 2775*fcf3ce44SJohn Forte h_print_list_warn(Hotplug_Devlist *disk_list_head, int todo, int enc_type) 2776*fcf3ce44SJohn Forte { 2777*fcf3ce44SJohn Forte int i; 2778*fcf3ce44SJohn Forte char choice[2]; 2779*fcf3ce44SJohn Forte struct dlist *dl_ses, *dl_multi; 2780*fcf3ce44SJohn Forte Hotplug_Devlist *disk_list = disk_list_head; 2781*fcf3ce44SJohn Forte 2782*fcf3ce44SJohn Forte (void) fprintf(stdout, 2783*fcf3ce44SJohn Forte MSGSTR(5570, "The list of devices which will be ")); 2784*fcf3ce44SJohn Forte switch (todo) { 2785*fcf3ce44SJohn Forte case INSERT_DEVICE: 2786*fcf3ce44SJohn Forte (void) fprintf(stdout, 2787*fcf3ce44SJohn Forte MSGSTR(5571, "inserted is:\n")); 2788*fcf3ce44SJohn Forte break; 2789*fcf3ce44SJohn Forte case REMOVE_DEVICE: 2790*fcf3ce44SJohn Forte (void) fprintf(stdout, 2791*fcf3ce44SJohn Forte MSGSTR(5572, "removed is:\n")); 2792*fcf3ce44SJohn Forte break; 2793*fcf3ce44SJohn Forte } 2794*fcf3ce44SJohn Forte 2795*fcf3ce44SJohn Forte for (i = 1; disk_list; i++, disk_list = disk_list->next) { 2796*fcf3ce44SJohn Forte if ((disk_list->dev_type == DTYPE_DIRECT) && 2797*fcf3ce44SJohn Forte (disk_list->dev_location == SENA)) { 2798*fcf3ce44SJohn Forte if (disk_list->f_flag != NULL) { 2799*fcf3ce44SJohn Forte if (enc_type == DAK_ENC_TYPE) { 2800*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5665, 2801*fcf3ce44SJohn Forte " %d: Box Name: \"%s\" slot %d\n"), 2802*fcf3ce44SJohn Forte i, disk_list->box_name, disk_list->slot); 2803*fcf3ce44SJohn Forte } else { 2804*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(137, 2805*fcf3ce44SJohn Forte " %d: Box Name: \"%s\" front slot %d\n"), 2806*fcf3ce44SJohn Forte i, disk_list->box_name, disk_list->slot); 2807*fcf3ce44SJohn Forte } 2808*fcf3ce44SJohn Forte } else { 2809*fcf3ce44SJohn Forte if (enc_type == DAK_ENC_TYPE) { 2810*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5665, 2811*fcf3ce44SJohn Forte " %d: Box Name: \"%s\" slot %d\n"), 2812*fcf3ce44SJohn Forte i, disk_list->box_name, 2813*fcf3ce44SJohn Forte disk_list->slot + (MAX_DRIVES_DAK/2)); 2814*fcf3ce44SJohn Forte } else { 2815*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(136, 2816*fcf3ce44SJohn Forte " %d: Box Name: \"%s\" rear slot %d\n"), 2817*fcf3ce44SJohn Forte i, disk_list->box_name, disk_list->slot); 2818*fcf3ce44SJohn Forte } 2819*fcf3ce44SJohn Forte } 2820*fcf3ce44SJohn Forte } else if (((disk_list->dev_type == DTYPE_DIRECT) || 2821*fcf3ce44SJohn Forte (disk_list->dev_type == DTYPE_SEQUENTIAL)) && 2822*fcf3ce44SJohn Forte (disk_list->dev_location == NON_SENA)) { 2823*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5573, 2824*fcf3ce44SJohn Forte " %d: Device name: %s\n"), 2825*fcf3ce44SJohn Forte i, disk_list->dev_name); 2826*fcf3ce44SJohn Forte } else if (disk_list->dev_type == DTYPE_ESI) { 2827*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5574, 2828*fcf3ce44SJohn Forte " %d: Box name: %s\n"), 2829*fcf3ce44SJohn Forte i, disk_list->box_name); 2830*fcf3ce44SJohn Forte } 2831*fcf3ce44SJohn Forte if (getenv("_LUX_H_DEBUG") != NULL) { 2832*fcf3ce44SJohn Forte if (disk_list->dev_location == SENA) { 2833*fcf3ce44SJohn Forte (void) fprintf(stdout, 2834*fcf3ce44SJohn Forte " Select ID:\t0x%x\n", 2835*fcf3ce44SJohn Forte disk_list->tid); 2836*fcf3ce44SJohn Forte if (disk_list->dev_type != DTYPE_ESI) { 2837*fcf3ce44SJohn Forte if (enc_type == DAK_ENC_TYPE) { 2838*fcf3ce44SJohn Forte (void) fprintf(stdout, 2839*fcf3ce44SJohn Forte " Location: \tSlot %d \n", 2840*fcf3ce44SJohn Forte disk_list->f_flag 2841*fcf3ce44SJohn Forte ? disk_list->slot 2842*fcf3ce44SJohn Forte : disk_list->slot 2843*fcf3ce44SJohn Forte +MAX_DRIVES_DAK/2); 2844*fcf3ce44SJohn Forte } else { 2845*fcf3ce44SJohn Forte (void) fprintf(stdout, 2846*fcf3ce44SJohn Forte " Location: \tSlot %d %s \n", 2847*fcf3ce44SJohn Forte disk_list->slot, disk_list->f_flag 2848*fcf3ce44SJohn Forte ? "front" : "rear"); 2849*fcf3ce44SJohn Forte } 2850*fcf3ce44SJohn Forte } 2851*fcf3ce44SJohn Forte } 2852*fcf3ce44SJohn Forte } 2853*fcf3ce44SJohn Forte if (todo == REMOVE_DEVICE) { 2854*fcf3ce44SJohn Forte (void) fprintf(stdout, " "); 2855*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(90, "Node WWN:")); 2856*fcf3ce44SJohn Forte (void) fprintf(stdout, " %s\n", 2857*fcf3ce44SJohn Forte disk_list->node_wwn_s); 2858*fcf3ce44SJohn Forte 2859*fcf3ce44SJohn Forte (void) fprintf(stdout, " "); 2860*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(35, "Device Type:")); 2861*fcf3ce44SJohn Forte if (disk_list->dev_type == DTYPE_ESI) { 2862*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5581, 2863*fcf3ce44SJohn Forte " SENA (%s)\n"), 2864*fcf3ce44SJohn Forte dtype[disk_list->dev_type]); 2865*fcf3ce44SJohn Forte } else { 2866*fcf3ce44SJohn Forte (void) fprintf(stdout, "%s\n", 2867*fcf3ce44SJohn Forte dtype[disk_list->dev_type]); 2868*fcf3ce44SJohn Forte } 2869*fcf3ce44SJohn Forte 2870*fcf3ce44SJohn Forte if (disk_list->dev_type == DTYPE_ESI) { 2871*fcf3ce44SJohn Forte dl_ses = disk_list->seslist; 2872*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5575, 2873*fcf3ce44SJohn Forte " SES Paths:\n")); 2874*fcf3ce44SJohn Forte while (dl_ses) { 2875*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5576, 2876*fcf3ce44SJohn Forte " %s\n"), dl_ses->dev_path); 2877*fcf3ce44SJohn Forte dl_ses = dl_ses->next; 2878*fcf3ce44SJohn Forte } 2879*fcf3ce44SJohn Forte } else { 2880*fcf3ce44SJohn Forte dl_multi = disk_list->dlhead; 2881*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5577, 2882*fcf3ce44SJohn Forte " Device Paths:\n")); 2883*fcf3ce44SJohn Forte while (dl_multi) { 2884*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5578, 2885*fcf3ce44SJohn Forte " %s\n"), 2886*fcf3ce44SJohn Forte dl_multi->logical_path); 2887*fcf3ce44SJohn Forte dl_multi = dl_multi->next; 2888*fcf3ce44SJohn Forte } 2889*fcf3ce44SJohn Forte } 2890*fcf3ce44SJohn Forte } 2891*fcf3ce44SJohn Forte (void) fprintf(stdout, "\n"); 2892*fcf3ce44SJohn Forte } 2893*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5579, 2894*fcf3ce44SJohn Forte "\nPlease verify the above list of devices" 2895*fcf3ce44SJohn Forte " and\nthen enter 'c' or <CR> to Continue" 2896*fcf3ce44SJohn Forte " or 'q' to Quit. [Default: c]: ")); 2897*fcf3ce44SJohn Forte 2898*fcf3ce44SJohn Forte /* Get the user input and continue accordingly. */ 2899*fcf3ce44SJohn Forte for (;;) { 2900*fcf3ce44SJohn Forte (void) gets(choice); 2901*fcf3ce44SJohn Forte if (choice[0] == 'c' || choice[0] == 'C' || 2902*fcf3ce44SJohn Forte choice[0] == 'q' || choice[0] == 'Q' || 2903*fcf3ce44SJohn Forte choice[0] == '\0') { 2904*fcf3ce44SJohn Forte break; 2905*fcf3ce44SJohn Forte } 2906*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5580, 2907*fcf3ce44SJohn Forte " Enter an appropriate option [c,<CR>,q]: ")); 2908*fcf3ce44SJohn Forte } 2909*fcf3ce44SJohn Forte 2910*fcf3ce44SJohn Forte if (choice[0] == 'q' || choice[0] == 'Q') { 2911*fcf3ce44SJohn Forte return (-1); 2912*fcf3ce44SJohn Forte } 2913*fcf3ce44SJohn Forte return (0); 2914*fcf3ce44SJohn Forte } 2915*fcf3ce44SJohn Forte 2916*fcf3ce44SJohn Forte 2917*fcf3ce44SJohn Forte static int 2918*fcf3ce44SJohn Forte h_find_new_device_link(char *device_dir, timestruc_t lastmtim) 2919*fcf3ce44SJohn Forte { 2920*fcf3ce44SJohn Forte struct stat dsk_stat; 2921*fcf3ce44SJohn Forte char lname[MAXPATHLEN], link[MAXPATHLEN]; 2922*fcf3ce44SJohn Forte char *link_ptr; 2923*fcf3ce44SJohn Forte DIR *dir; 2924*fcf3ce44SJohn Forte struct dirent *dirent; 2925*fcf3ce44SJohn Forte int found_newlink = 0; 2926*fcf3ce44SJohn Forte 2927*fcf3ce44SJohn Forte 2928*fcf3ce44SJohn Forte if ((dir = opendir(device_dir)) == NULL) { 2929*fcf3ce44SJohn Forte if (errno == ENOENT) { 2930*fcf3ce44SJohn Forte return (0); 2931*fcf3ce44SJohn Forte } else { 2932*fcf3ce44SJohn Forte return (L_READ_DEV_DIR_ERROR); 2933*fcf3ce44SJohn Forte } 2934*fcf3ce44SJohn Forte } 2935*fcf3ce44SJohn Forte 2936*fcf3ce44SJohn Forte while ((dirent = readdir(dir)) != (struct dirent *)NULL) { 2937*fcf3ce44SJohn Forte if (strcmp(dirent->d_name, ".") == 0 || 2938*fcf3ce44SJohn Forte strcmp(dirent->d_name, "..") == 0) { 2939*fcf3ce44SJohn Forte continue; 2940*fcf3ce44SJohn Forte } 2941*fcf3ce44SJohn Forte (void) sprintf(lname, "%s/%s", device_dir, dirent->d_name); 2942*fcf3ce44SJohn Forte if (lstat(lname, &dsk_stat) < 0) { 2943*fcf3ce44SJohn Forte (void) print_errString(L_LSTAT_ES_DIR_ERROR, 2944*fcf3ce44SJohn Forte lname); 2945*fcf3ce44SJohn Forte continue; 2946*fcf3ce44SJohn Forte } 2947*fcf3ce44SJohn Forte if (readlink((const char *)lname, (char *)link, 2948*fcf3ce44SJohn Forte (size_t)MAXPATHLEN) <= 0) { 2949*fcf3ce44SJohn Forte (void) print_errString(L_SYMLINK_ERROR, lname); 2950*fcf3ce44SJohn Forte continue; 2951*fcf3ce44SJohn Forte } 2952*fcf3ce44SJohn Forte 2953*fcf3ce44SJohn Forte /* 2954*fcf3ce44SJohn Forte * "link" can be a relative pathname. But, since 2955*fcf3ce44SJohn Forte * g_get_path_type() only accepts absolute paths, we 2956*fcf3ce44SJohn Forte * will skip to the part where "/devices/" begins and pass a 2957*fcf3ce44SJohn Forte * pointer from there. Since "link" is got from readlink(), 2958*fcf3ce44SJohn Forte * it is unlikely that it will not have /devices string, but 2959*fcf3ce44SJohn Forte * we will check for it anyways. 2960*fcf3ce44SJohn Forte */ 2961*fcf3ce44SJohn Forte if (!(link_ptr = strstr(link, "/devices/"))) 2962*fcf3ce44SJohn Forte continue; 2963*fcf3ce44SJohn Forte if (!g_get_path_type(link_ptr)) { 2964*fcf3ce44SJohn Forte continue; 2965*fcf3ce44SJohn Forte } 2966*fcf3ce44SJohn Forte if (NEWER(dsk_stat.st_ctim, lastmtim)) { 2967*fcf3ce44SJohn Forte found_newlink++; 2968*fcf3ce44SJohn Forte if (found_newlink == 1) { 2969*fcf3ce44SJohn Forte if (! (strcmp(device_dir, DEV_DSK_DIR))) { 2970*fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(5561, 2971*fcf3ce44SJohn Forte " New Logical Nodes under " 2972*fcf3ce44SJohn Forte "/dev/dsk and /dev/rdsk :\n")); 2973*fcf3ce44SJohn Forte } else { /* device_dir is /dev/rmt */ 2974*fcf3ce44SJohn Forte (void) fprintf(stdout, "New Logical " 2975*fcf3ce44SJohn Forte "Node under /dev/rmt:\n"); 2976*fcf3ce44SJohn Forte } 2977*fcf3ce44SJohn Forte } 2978*fcf3ce44SJohn Forte (void) fprintf(stdout, "\t%s\n", dirent->d_name); 2979*fcf3ce44SJohn Forte } 2980*fcf3ce44SJohn Forte } 2981*fcf3ce44SJohn Forte closedir(dir); 2982*fcf3ce44SJohn Forte return (found_newlink); 2983*fcf3ce44SJohn Forte } 2984*fcf3ce44SJohn Forte 2985*fcf3ce44SJohn Forte 2986*fcf3ce44SJohn Forte /* 2987*fcf3ce44SJohn Forte * prints the device state. 2988*fcf3ce44SJohn Forte * 2989*fcf3ce44SJohn Forte * RETURNS: 2990*fcf3ce44SJohn Forte * None. 2991*fcf3ce44SJohn Forte */ 2992*fcf3ce44SJohn Forte void 2993*fcf3ce44SJohn Forte print_dev_state(char *devname, int state) 2994*fcf3ce44SJohn Forte { 2995*fcf3ce44SJohn Forte (void) printf("\t%s: ", devname); 2996*fcf3ce44SJohn Forte if (state & DEVICE_ONLINE) { 2997*fcf3ce44SJohn Forte (void) printf(MSGSTR(3000, "Online")); 2998*fcf3ce44SJohn Forte if (state & DEVICE_BUSY) { 2999*fcf3ce44SJohn Forte (void) printf(" "); 3000*fcf3ce44SJohn Forte (void) printf(MSGSTR(37, "Busy")); 3001*fcf3ce44SJohn Forte } 3002*fcf3ce44SJohn Forte if (state & DEVICE_DOWN) { 3003*fcf3ce44SJohn Forte (void) printf(" "); 3004*fcf3ce44SJohn Forte (void) printf(MSGSTR(118, "Down")); 3005*fcf3ce44SJohn Forte } 3006*fcf3ce44SJohn Forte } else { 3007*fcf3ce44SJohn Forte if (state & DEVICE_OFFLINE) { 3008*fcf3ce44SJohn Forte (void) printf(MSGSTR(3001, "Offline")); 3009*fcf3ce44SJohn Forte if (state & DEVICE_DOWN) { 3010*fcf3ce44SJohn Forte (void) printf(" "); 3011*fcf3ce44SJohn Forte (void) printf(MSGSTR(118, "Down")); 3012*fcf3ce44SJohn Forte } 3013*fcf3ce44SJohn Forte } 3014*fcf3ce44SJohn Forte } 3015*fcf3ce44SJohn Forte (void) printf("\n"); 3016*fcf3ce44SJohn Forte } 3017*fcf3ce44SJohn Forte 3018*fcf3ce44SJohn Forte 3019*fcf3ce44SJohn Forte /* 3020*fcf3ce44SJohn Forte * prints the bus state. 3021*fcf3ce44SJohn Forte * 3022*fcf3ce44SJohn Forte * RETURNS: 3023*fcf3ce44SJohn Forte * None. 3024*fcf3ce44SJohn Forte */ 3025*fcf3ce44SJohn Forte void 3026*fcf3ce44SJohn Forte print_bus_state(char *devname, int state) 3027*fcf3ce44SJohn Forte { 3028*fcf3ce44SJohn Forte (void) printf("\t%s: ", devname); 3029*fcf3ce44SJohn Forte if (state == BUS_QUIESCED) { 3030*fcf3ce44SJohn Forte (void) printf(MSGSTR(3002, "Quiesced")); 3031*fcf3ce44SJohn Forte } else if (state == BUS_ACTIVE) { 3032*fcf3ce44SJohn Forte (void) printf(MSGSTR(39, "Active")); 3033*fcf3ce44SJohn Forte } else if (state == BUS_SHUTDOWN) { 3034*fcf3ce44SJohn Forte (void) printf(MSGSTR(3003, "Shutdown")); 3035*fcf3ce44SJohn Forte } 3036*fcf3ce44SJohn Forte (void) printf("\n"); 3037*fcf3ce44SJohn Forte } 3038