17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 580ab886dSwesolows * Common Development and Distribution License (the "License"). 680ab886dSwesolows * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 2180ab886dSwesolows 227c478bd9Sstevel@tonic-gate /* 23*a0261a43SJames C. McPherson * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <stdio.h> 287c478bd9Sstevel@tonic-gate #include <stdlib.h> 297c478bd9Sstevel@tonic-gate #include <stdarg.h> 307c478bd9Sstevel@tonic-gate #include <sys/types.h> 317c478bd9Sstevel@tonic-gate #include <sys/stat.h> 327c478bd9Sstevel@tonic-gate #include <fcntl.h> 337c478bd9Sstevel@tonic-gate #include <errno.h> 347c478bd9Sstevel@tonic-gate #include <unistd.h> 357c478bd9Sstevel@tonic-gate #include <stropts.h> 367c478bd9Sstevel@tonic-gate #include <strings.h> 377c478bd9Sstevel@tonic-gate #include <sys/param.h> 387c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 397c478bd9Sstevel@tonic-gate #include <locale.h> 407c478bd9Sstevel@tonic-gate #include <libintl.h> 417c478bd9Sstevel@tonic-gate #include <devid.h> 42*a0261a43SJames C. McPherson #include <sys/modctl.h> /* for MAXMODCONFNAME */ 43*a0261a43SJames C. McPherson #include <sys/scsi/adapters/scsi_vhci.h> 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate /* 46*a0261a43SJames C. McPherson * SAVE_DIR is the directory in which system files are saved. 47*a0261a43SJames C. McPherson * SAVE_DIR must be under the root filesystem, as this program is 487c478bd9Sstevel@tonic-gate * typically run before any other filesystems are mounted. 497c478bd9Sstevel@tonic-gate */ 507c478bd9Sstevel@tonic-gate #define SAVE_DIR "/etc/mpxio" 51*a0261a43SJames C. McPherson #define VHCI_CTL_NODE "/devices/scsi_vhci:devctl" 527c478bd9Sstevel@tonic-gate 53*a0261a43SJames C. McPherson /* nvlist property names, these are ALL string types */ 54*a0261a43SJames C. McPherson #define NVL_DEVID "nvl-devid" 55*a0261a43SJames C. McPherson #define NVL_PATH "nvl-path" 56*a0261a43SJames C. McPherson #define NVL_PHYSPATH "nvl-physpath" 57*a0261a43SJames C. McPherson #define NVL_MPXPATH "nvl-mpxiopath" 58*a0261a43SJames C. McPherson #define NVL_MPXEN "nvl-mpxioenabled" 597c478bd9Sstevel@tonic-gate 60*a0261a43SJames C. McPherson #define MPX_LIST 0x01 61*a0261a43SJames C. McPherson #define MPX_MAP 0x02 62*a0261a43SJames C. McPherson #define MPX_CAPABLE_CTRL 0x04 63*a0261a43SJames C. McPherson #define MPX_INIT 0x08 64*a0261a43SJames C. McPherson #define MPX_PHYSICAL 0x10 65*a0261a43SJames C. McPherson #define MPX_BOOTPATH 0x20 66*a0261a43SJames C. McPherson #define MPX_UPDATEVFSTAB 0x40 67*a0261a43SJames C. McPherson #define MPX_USAGE 0x80 68*a0261a43SJames C. McPherson #define MSG_INFO 0x01 69*a0261a43SJames C. McPherson #define MSG_ERROR 0x02 70*a0261a43SJames C. McPherson #define MSG_PANIC 0x04 7160fffc19Sjw149990 72*a0261a43SJames C. McPherson #define BOOT 0x01 73*a0261a43SJames C. McPherson #define NONBOOT 0x00 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate static di_node_t devinfo_root = DI_NODE_NIL; 76*a0261a43SJames C. McPherson static char *ondiskname = "/etc/mpxio/devid_path.cache"; 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate /* 79*a0261a43SJames C. McPherson * We use devid-keyed nvlists to keep track of the guid, traditional and 80*a0261a43SJames C. McPherson * MPxIO-enabled /dev/rdsk paths. Each of these nvlists is eventually 81*a0261a43SJames C. McPherson * added to our global nvlist and our on-disk nvlist. 827c478bd9Sstevel@tonic-gate */ 83*a0261a43SJames C. McPherson static nvlist_t *mapnvl; 84*a0261a43SJames C. McPherson static int mpxenabled = 0; 85*a0261a43SJames C. McPherson static int limctrl = -1; 86*a0261a43SJames C. McPherson static int guid = 0; 87*a0261a43SJames C. McPherson static char *drvlimit; 88*a0261a43SJames C. McPherson static int globarg = 0; 89*a0261a43SJames C. McPherson static int debugflag = 0; 90*a0261a43SJames C. McPherson static char *devicep; 91*a0261a43SJames C. McPherson static int readonlyroot = 0; 92*a0261a43SJames C. McPherson static int cap_N_option = 0; 93*a0261a43SJames C. McPherson 94*a0261a43SJames C. McPherson static void print_mpx_capable(di_node_t curnode); 95*a0261a43SJames C. McPherson static int popcheck_devnvl(di_node_t thisnode, nvlist_t *devnvl, 96*a0261a43SJames C. McPherson char *strdevid); 97*a0261a43SJames C. McPherson static int mpxio_nvl_boilerplate(di_node_t curnode); 98*a0261a43SJames C. McPherson static int validate_devnvl(); 99*a0261a43SJames C. McPherson static void report_map(char *argdev, int physpath); 100*a0261a43SJames C. McPherson static void list_devs(int listguids, int ctrl); 101*a0261a43SJames C. McPherson static void logmsg(int level, const char *msg, ...); 102*a0261a43SJames C. McPherson static char *find_link(di_node_t cnode); 103*a0261a43SJames C. McPherson static void usage(); 104*a0261a43SJames C. McPherson static void parse_args(int argc, char *argv[]); 105*a0261a43SJames C. McPherson static void get_devid(di_node_t node, ddi_devid_t *thisdevid); 106*a0261a43SJames C. McPherson static int print_bootpath(); 107*a0261a43SJames C. McPherson static void vhci_to_phci(char *devpath, char *physpath); 108*a0261a43SJames C. McPherson static int update_vfstab(); 109*a0261a43SJames C. McPherson 110*a0261a43SJames C. McPherson int 111*a0261a43SJames C. McPherson main(int argc, char **argv) 1127c478bd9Sstevel@tonic-gate { 113*a0261a43SJames C. McPherson struct stat cachestat; 114*a0261a43SJames C. McPherson int mapfd = 0; 115*a0261a43SJames C. McPherson int rv = 0; 116*a0261a43SJames C. McPherson char *ondiskbuf; 117*a0261a43SJames C. McPherson size_t newsz = 0; 1187c478bd9Sstevel@tonic-gate 119*a0261a43SJames C. McPherson parse_args(argc, argv); 120*a0261a43SJames C. McPherson errno = 0; 121*a0261a43SJames C. McPherson devinfo_root = di_init("/", DINFOCPYALL|DINFOFORCE); 122*a0261a43SJames C. McPherson logmsg(MSG_INFO, "errno = %d after " 123*a0261a43SJames C. McPherson "di_init(/,DINFOCPYALL|DINFOFORCE)\n", errno); 124*a0261a43SJames C. McPherson if (devinfo_root == NULL) { 125*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 126*a0261a43SJames C. McPherson gettext("Unable to take device tree snapshot " 127*a0261a43SJames C. McPherson "(%s: %d)\n"), strerror(errno), errno); 128*a0261a43SJames C. McPherson return (-1); 129*a0261a43SJames C. McPherson } 130*a0261a43SJames C. McPherson logmsg(MSG_INFO, "opened root di_node\n"); 1317c478bd9Sstevel@tonic-gate 132*a0261a43SJames C. McPherson if (globarg == MPX_CAPABLE_CTRL) { 133*a0261a43SJames C. McPherson /* we just want to find MPxIO-capable controllers and exit */ 134*a0261a43SJames C. McPherson if (drvlimit != NULL) { 135*a0261a43SJames C. McPherson print_mpx_capable(di_drv_first_node(drvlimit, 136*a0261a43SJames C. McPherson devinfo_root)); 137*a0261a43SJames C. McPherson } else { 138*a0261a43SJames C. McPherson print_mpx_capable(di_drv_first_node("fp", 139*a0261a43SJames C. McPherson devinfo_root)); 140*a0261a43SJames C. McPherson print_mpx_capable(di_drv_first_node("mpt", 141*a0261a43SJames C. McPherson devinfo_root)); 142*a0261a43SJames C. McPherson } 143*a0261a43SJames C. McPherson di_fini(devinfo_root); 144*a0261a43SJames C. McPherson return (0); 145*a0261a43SJames C. McPherson } 146*a0261a43SJames C. McPherson 147*a0261a43SJames C. McPherson mapfd = open(ondiskname, O_RDWR|O_CREAT|O_SYNC, S_IRUSR | S_IWUSR); 148*a0261a43SJames C. McPherson if (mapfd < 0) { 149*a0261a43SJames C. McPherson /* we could be in single-user, so try for RO */ 150*a0261a43SJames C. McPherson if ((mapfd = open(ondiskname, O_RDONLY)) < 0) { 151*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 152*a0261a43SJames C. McPherson gettext("Unable to open or create %s:%s\n"), 153*a0261a43SJames C. McPherson ondiskname, strerror(errno)); 154*a0261a43SJames C. McPherson return (errno); 155*a0261a43SJames C. McPherson } 156*a0261a43SJames C. McPherson readonlyroot = 1; 157*a0261a43SJames C. McPherson } 158*a0261a43SJames C. McPherson 159*a0261a43SJames C. McPherson if (stat(ondiskname, &cachestat) != 0) { 160*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 161*a0261a43SJames C. McPherson gettext("Unable to stat() %s: %s\n"), 162*a0261a43SJames C. McPherson ondiskname, strerror(errno)); 163*a0261a43SJames C. McPherson return (errno); 164*a0261a43SJames C. McPherson } 165*a0261a43SJames C. McPherson ondiskbuf = calloc(1, cachestat.st_size); 166*a0261a43SJames C. McPherson if (ondiskbuf == NULL) { 167*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 168*a0261a43SJames C. McPherson gettext("Unable to allocate memory for the devid " 169*a0261a43SJames C. McPherson "cache file: %s\n"), strerror(errno)); 170*a0261a43SJames C. McPherson return (errno); 171*a0261a43SJames C. McPherson } 172*a0261a43SJames C. McPherson rv = read(mapfd, ondiskbuf, cachestat.st_size); 173*a0261a43SJames C. McPherson if (rv != cachestat.st_size) { 174*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 175*a0261a43SJames C. McPherson gettext("Unable to read all of devid cache file (got %d " 176*a0261a43SJames C. McPherson "from expected %d bytes): %s\n"), 177*a0261a43SJames C. McPherson rv, cachestat.st_size, strerror(errno)); 178*a0261a43SJames C. McPherson return (errno); 179*a0261a43SJames C. McPherson } 180*a0261a43SJames C. McPherson errno = 0; 181*a0261a43SJames C. McPherson rv = nvlist_unpack(ondiskbuf, cachestat.st_size, &mapnvl, 0); 182*a0261a43SJames C. McPherson if (rv) { 183*a0261a43SJames C. McPherson logmsg(MSG_INFO, 184*a0261a43SJames C. McPherson "Unable to unpack devid cache file %s: %s (%d)\n", 185*a0261a43SJames C. McPherson ondiskname, strerror(rv), rv); 186*a0261a43SJames C. McPherson if (nvlist_alloc(&mapnvl, NV_UNIQUE_NAME, 0) != 0) { 187*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 188*a0261a43SJames C. McPherson gettext("Unable to allocate root property" 189*a0261a43SJames C. McPherson "list\n")); 190*a0261a43SJames C. McPherson return (errno); 191*a0261a43SJames C. McPherson } 192*a0261a43SJames C. McPherson } 193*a0261a43SJames C. McPherson free(ondiskbuf); 194*a0261a43SJames C. McPherson 195*a0261a43SJames C. McPherson if (validate_devnvl() < 0) { 196*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 197*a0261a43SJames C. McPherson gettext("unable to validate kernel with on-disk devid " 198*a0261a43SJames C. McPherson "cache file\n")); 199*a0261a43SJames C. McPherson return (errno); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* 203*a0261a43SJames C. McPherson * If we're in single-user mode or maintenance mode, we won't 204*a0261a43SJames C. McPherson * necessarily have a writable root device (ZFSroot; ufs root is 205*a0261a43SJames C. McPherson * different in that we _do_ have a writable root device. 206*a0261a43SJames C. McPherson * This causes problems for the devlink calls (see 207*a0261a43SJames C. McPherson * $SRC/lib/libdevinfo/devinfo_devlink.c) and we do not try to 208*a0261a43SJames C. McPherson * write out the devnvl if root is readonly. 2097c478bd9Sstevel@tonic-gate */ 210*a0261a43SJames C. McPherson if (!readonlyroot) { 211*a0261a43SJames C. McPherson rv = nvlist_size(mapnvl, &newsz, NV_ENCODE_NATIVE); 212*a0261a43SJames C. McPherson if (rv) { 213*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 214*a0261a43SJames C. McPherson gettext("Unable to determine size of packed " 215*a0261a43SJames C. McPherson "on-disk devid cache file %s: %s (%d).\n"), 216*a0261a43SJames C. McPherson ondiskname, strerror(rv), rv); 217*a0261a43SJames C. McPherson logmsg(MSG_ERROR, gettext("Terminating\n")); 218*a0261a43SJames C. McPherson nvlist_free(mapnvl); 219*a0261a43SJames C. McPherson (void) close(mapfd); 220*a0261a43SJames C. McPherson return (rv); 221*a0261a43SJames C. McPherson } 222*a0261a43SJames C. McPherson 223*a0261a43SJames C. McPherson if ((ondiskbuf = calloc(1, newsz)) == NULL) { 224*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 225*a0261a43SJames C. McPherson "Unable to allocate space for writing out new " 226*a0261a43SJames C. McPherson "on-disk devid cache file: %s\n", strerror(errno)); 227*a0261a43SJames C. McPherson (void) close(mapfd); 228*a0261a43SJames C. McPherson nvlist_free(mapnvl); 229*a0261a43SJames C. McPherson return (errno); 230*a0261a43SJames C. McPherson } 231*a0261a43SJames C. McPherson 232*a0261a43SJames C. McPherson rv = nvlist_pack(mapnvl, &ondiskbuf, &newsz, 233*a0261a43SJames C. McPherson NV_ENCODE_NATIVE, 0); 234*a0261a43SJames C. McPherson if (rv) { 235*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 236*a0261a43SJames C. McPherson gettext("Unable to pack on-disk devid cache " 237*a0261a43SJames C. McPherson "file: %s (%d)\n"), strerror(rv), rv); 238*a0261a43SJames C. McPherson (void) close(mapfd); 239*a0261a43SJames C. McPherson free(ondiskbuf); 240*a0261a43SJames C. McPherson nvlist_free(mapnvl); 241*a0261a43SJames C. McPherson return (rv); 242*a0261a43SJames C. McPherson } 243*a0261a43SJames C. McPherson 244*a0261a43SJames C. McPherson rv = lseek(mapfd, 0, 0); 245*a0261a43SJames C. McPherson if (rv == -1) { 246*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 247*a0261a43SJames C. McPherson gettext("Unable to seek to start of devid cache " 248*a0261a43SJames C. McPherson "file: %s (%d)\n"), strerror(errno), errno); 249*a0261a43SJames C. McPherson (void) close(mapfd); 250*a0261a43SJames C. McPherson free(ondiskbuf); 251*a0261a43SJames C. McPherson nvlist_free(mapnvl); 252*a0261a43SJames C. McPherson return (-1); 253*a0261a43SJames C. McPherson } 254*a0261a43SJames C. McPherson 255*a0261a43SJames C. McPherson if (write(mapfd, ondiskbuf, newsz) != newsz) { 256*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 257*a0261a43SJames C. McPherson gettext("Unable to completely write out " 258*a0261a43SJames C. McPherson "on-disk devid cache file: %s\n"), strerror(errno)); 259*a0261a43SJames C. McPherson (void) close(mapfd); 260*a0261a43SJames C. McPherson nvlist_free(mapnvl); 261*a0261a43SJames C. McPherson free(ondiskbuf); 262*a0261a43SJames C. McPherson return (errno); 263*a0261a43SJames C. McPherson } 264*a0261a43SJames C. McPherson } /* !readonlyroot */ 265*a0261a43SJames C. McPherson 266*a0261a43SJames C. McPherson /* Now we can process the command line args */ 267*a0261a43SJames C. McPherson if (globarg == MPX_PHYSICAL) { 268*a0261a43SJames C. McPherson report_map(devicep, BOOT); 269*a0261a43SJames C. McPherson } else if (globarg == MPX_BOOTPATH) { 270*a0261a43SJames C. McPherson rv = print_bootpath(); 271*a0261a43SJames C. McPherson di_fini(devinfo_root); 272*a0261a43SJames C. McPherson return (rv); 273*a0261a43SJames C. McPherson } else if (globarg == MPX_UPDATEVFSTAB) { 274*a0261a43SJames C. McPherson rv = update_vfstab(); 275*a0261a43SJames C. McPherson di_fini(devinfo_root); 276*a0261a43SJames C. McPherson return (rv); 277*a0261a43SJames C. McPherson } else if (globarg != MPX_INIT) { 278*a0261a43SJames C. McPherson if (globarg & MPX_LIST) 279*a0261a43SJames C. McPherson list_devs(guid, limctrl); 280*a0261a43SJames C. McPherson 281*a0261a43SJames C. McPherson if (globarg == MPX_MAP) 282*a0261a43SJames C. McPherson report_map(devicep, NONBOOT); 283*a0261a43SJames C. McPherson } else { 284*a0261a43SJames C. McPherson logmsg(MSG_INFO, "\nprivate devid cache file initialised\n"); 285*a0261a43SJames C. McPherson } 286*a0261a43SJames C. McPherson 287*a0261a43SJames C. McPherson nvlist_free(mapnvl); 288*a0261a43SJames C. McPherson di_fini(devinfo_root); 289*a0261a43SJames C. McPherson return (0); 290*a0261a43SJames C. McPherson } 291*a0261a43SJames C. McPherson 292*a0261a43SJames C. McPherson static void 293*a0261a43SJames C. McPherson usage() 294*a0261a43SJames C. McPherson { 295*a0261a43SJames C. McPherson (void) fprintf(stderr, 296*a0261a43SJames C. McPherson gettext("usage: stmsboot_util -b | -m devname | " 297*a0261a43SJames C. McPherson "-l <ctrl> | -L | [-g] | -n | -N | -i | -p devname\n")); 298*a0261a43SJames C. McPherson (void) fprintf(stderr, "\n\n"); 299*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-h\tprint this usage message\n")); 300*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-b\tretrieve the system's bootpath " 301*a0261a43SJames C. McPherson "setting\n")); 302*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-m devname\n")); 303*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tReports the current mapping for " 304*a0261a43SJames C. McPherson "devname\n")); 305*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-g\tprint the GUID for MPxIO-capable " 306*a0261a43SJames C. McPherson "devices. This\n")); 307*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\toption is only valid with the -L " 308*a0261a43SJames C. McPherson "or -l options\n")); 309*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-L | -l <ctrl>\n")); 310*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tList the 'native' to 'MPxIO' " 311*a0261a43SJames C. McPherson "device mappings. If <ctrl>\n")); 312*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tis specified, only print mappings " 313*a0261a43SJames C. McPherson "for those devices\n")); 314*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tattached via the specified " 315*a0261a43SJames C. McPherson "controller.\n")); 316*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-i\tinitialise the private devid " 317*a0261a43SJames C. McPherson "cache file and exit\n")); 318*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tThis option excludes all " 319*a0261a43SJames C. McPherson "others.\n")); 320*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-n\tprint the devfs paths for " 321*a0261a43SJames C. McPherson "multipath-capable\n")); 322*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tcontroller ports.\n")); 323*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-N\tprint the device aliases of " 324*a0261a43SJames C. McPherson "multipath-capable\n")); 325*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tcontroller ports.\n")); 326*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-p\tdevname\n")); 327*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tThis option provides the physical " 328*a0261a43SJames C. McPherson "devfs path for\n")); 329*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\ta specific device (devname). Used " 330*a0261a43SJames C. McPherson "to set the bootpath\n")); 331*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tvariable on x86/x64 systems\n")); 332*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-u\ttranslates device mappings in " 333*a0261a43SJames C. McPherson "/etc/vfstab as \n")); 334*a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\trequired. The output is written " 335*a0261a43SJames C. McPherson "to /etc/mpxio/vfstab.new\n\n")); 336*a0261a43SJames C. McPherson exit(2); 337*a0261a43SJames C. McPherson } 338*a0261a43SJames C. McPherson 3397c478bd9Sstevel@tonic-gate static void 3407c478bd9Sstevel@tonic-gate parse_args(int argc, char *argv[]) 3417c478bd9Sstevel@tonic-gate { 3427c478bd9Sstevel@tonic-gate char opt; 3437c478bd9Sstevel@tonic-gate 344*a0261a43SJames C. McPherson if (argc == 1) 345*a0261a43SJames C. McPherson usage(); 3467c478bd9Sstevel@tonic-gate 347*a0261a43SJames C. McPherson /* 348*a0261a43SJames C. McPherson * -b prints the bootpath property 349*a0261a43SJames C. McPherson * -d turns on debug mode for this utility (copious output!) 350*a0261a43SJames C. McPherson * -D drvname 351*a0261a43SJames C. McPherson * if supplied, indicates that we're going to operate on 352*a0261a43SJames C. McPherson * devices attached to this driver. 353*a0261a43SJames C. McPherson * -g if (-l or -L), prints guids for devices rather than paths 354*a0261a43SJames C. McPherson * -h prints the usage() help text. 355*a0261a43SJames C. McPherson * -i initialises the cache file and exits. 356*a0261a43SJames C. McPherson * -l controller 357*a0261a43SJames C. McPherson * list non-STMS to STMS device name mappings for the specific 358*a0261a43SJames C. McPherson * controller, when MPxIO is enabled only. 359*a0261a43SJames C. McPherson * -L list non-STMS to STMS device name mappings for all controllers 360*a0261a43SJames C. McPherson * when MPxIO is enabled only. 361*a0261a43SJames C. McPherson * -m devname 362*a0261a43SJames C. McPherson * prints the device path (/dev/rdsk) that devname maps to 363*a0261a43SJames C. McPherson * in the currently-running system. 364*a0261a43SJames C. McPherson * -n 365*a0261a43SJames C. McPherson * if supplied, returns name of STMS-capable controller nodes. 366*a0261a43SJames C. McPherson * If the -D drvname option is specified as well, we only report 367*a0261a43SJames C. McPherson * nodes attached with drvname. 368*a0261a43SJames C. McPherson * -N 369*a0261a43SJames C. McPherson * same as the -n option, except that we only print the 370*a0261a43SJames C. McPherson * node-name (dev_info :: devi_node_name). Multiple instances 371*a0261a43SJames C. McPherson * through the libdevinfo snapshot are uniqified and separated 372*a0261a43SJames C. McPherson * by the "|" character for direct use by egrep(1). 373*a0261a43SJames C. McPherson * -p devname 374*a0261a43SJames C. McPherson * prints the physical devfs path for devname. Only used to 375*a0261a43SJames C. McPherson * determine the bootpath. 376*a0261a43SJames C. McPherson * -u 377*a0261a43SJames C. McPherson * remaps devices in /etc/vfstab, saving the newly generated 378*a0261a43SJames C. McPherson * file to /etc/mpxio/vfstab.new. If we have any remapped 379*a0261a43SJames C. McPherson * devices, exit with status 0, otherwise -1 for error. 380*a0261a43SJames C. McPherson */ 381*a0261a43SJames C. McPherson while ((opt = getopt(argc, argv, "bdD:ghil:Lm:nNp:u")) != EOF) { 3827c478bd9Sstevel@tonic-gate switch (opt) { 383*a0261a43SJames C. McPherson case 'b': 384*a0261a43SJames C. McPherson globarg = MPX_BOOTPATH; 3857c478bd9Sstevel@tonic-gate break; 3867c478bd9Sstevel@tonic-gate case 'd': 387*a0261a43SJames C. McPherson debugflag = 1; 3887c478bd9Sstevel@tonic-gate break; 38960fffc19Sjw149990 case 'D': 390*a0261a43SJames C. McPherson if ((drvlimit = calloc(1, MAXMODCONFNAME)) == NULL) { 391*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 392*a0261a43SJames C. McPherson gettext("Unable to allocate memory for a " 393*a0261a43SJames C. McPherson "driver name: %s\n"), strerror(errno)); 394*a0261a43SJames C. McPherson exit(errno); 39560fffc19Sjw149990 } 396*a0261a43SJames C. McPherson bcopy(optarg, drvlimit, strlen(optarg)); 397*a0261a43SJames C. McPherson /* update this if adding support for a new driver */ 398*a0261a43SJames C. McPherson if ((strncmp(drvlimit, "fp", 2) == NULL) && 399*a0261a43SJames C. McPherson (strncmp(drvlimit, "mpt", 3) == NULL)) { 400*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 401*a0261a43SJames C. McPherson gettext("invalid parent driver (%s) " 402*a0261a43SJames C. McPherson "specified"), drvlimit); 403*a0261a43SJames C. McPherson usage(); 404*a0261a43SJames C. McPherson } 40560fffc19Sjw149990 break; 406*a0261a43SJames C. McPherson case 'h': 407*a0261a43SJames C. McPherson /* Just drop out and print the usage() output */ 408*a0261a43SJames C. McPherson globarg = MPX_USAGE; 409*a0261a43SJames C. McPherson break; 410*a0261a43SJames C. McPherson case 'i': 411*a0261a43SJames C. McPherson globarg = MPX_INIT; 412*a0261a43SJames C. McPherson break; 413*a0261a43SJames C. McPherson case 'l': 414*a0261a43SJames C. McPherson globarg |= MPX_LIST; 415*a0261a43SJames C. McPherson limctrl = (int)atol(optarg); 416*a0261a43SJames C. McPherson if (limctrl < 0) { 417*a0261a43SJames C. McPherson logmsg(MSG_INFO, 418*a0261a43SJames C. McPherson gettext("invalid controller number " 419*a0261a43SJames C. McPherson "(%d), checking all controllers\n"), 420*a0261a43SJames C. McPherson limctrl); 421*a0261a43SJames C. McPherson } 422*a0261a43SJames C. McPherson break; 423*a0261a43SJames C. McPherson case 'L': 424*a0261a43SJames C. McPherson globarg |= MPX_LIST; 425*a0261a43SJames C. McPherson break; 426*a0261a43SJames C. McPherson case 'g': 427*a0261a43SJames C. McPherson guid = 1; 428*a0261a43SJames C. McPherson break; 429*a0261a43SJames C. McPherson case 'm': 430*a0261a43SJames C. McPherson globarg = MPX_MAP; 431*a0261a43SJames C. McPherson if ((devicep = calloc(1, MAXPATHLEN)) == NULL) { 432*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 433*a0261a43SJames C. McPherson gettext("Unable to allocate space for a " 434*a0261a43SJames C. McPherson "device name\n")); 435*a0261a43SJames C. McPherson exit(errno); 436*a0261a43SJames C. McPherson } 437*a0261a43SJames C. McPherson devicep = strdup(optarg); 438*a0261a43SJames C. McPherson break; 439*a0261a43SJames C. McPherson case 'N': 440*a0261a43SJames C. McPherson cap_N_option = 1; 441*a0261a43SJames C. McPherson globarg = MPX_CAPABLE_CTRL; 442*a0261a43SJames C. McPherson break; 44360fffc19Sjw149990 case 'n': 444*a0261a43SJames C. McPherson globarg = MPX_CAPABLE_CTRL; 44560fffc19Sjw149990 break; 446*a0261a43SJames C. McPherson case 'p': 447*a0261a43SJames C. McPherson globarg = MPX_PHYSICAL; 448*a0261a43SJames C. McPherson if ((devicep = calloc(1, MAXPATHLEN)) == NULL) { 449*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 450*a0261a43SJames C. McPherson gettext("Unable to allocate space for a " 451*a0261a43SJames C. McPherson "device name\n")); 452*a0261a43SJames C. McPherson exit(errno); 453*a0261a43SJames C. McPherson } 454*a0261a43SJames C. McPherson devicep = strdup(optarg); 455*a0261a43SJames C. McPherson break; 456*a0261a43SJames C. McPherson case 'u': 457*a0261a43SJames C. McPherson globarg = MPX_UPDATEVFSTAB; 458*a0261a43SJames C. McPherson break; 4597c478bd9Sstevel@tonic-gate default: 460*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 461*a0261a43SJames C. McPherson gettext("Invalid command line option (%c)\n"), 462*a0261a43SJames C. McPherson opt); 463*a0261a43SJames C. McPherson usage(); 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate 467*a0261a43SJames C. McPherson if ((globarg >= MPX_USAGE) || (guid && (globarg != MPX_LIST))) 468*a0261a43SJames C. McPherson usage(); 469*a0261a43SJames C. McPherson 470*a0261a43SJames C. McPherson if ((drvlimit != NULL) && 471*a0261a43SJames C. McPherson ((globarg != MPX_LIST) && 472*a0261a43SJames C. McPherson (globarg != MPX_CAPABLE_CTRL))) 473*a0261a43SJames C. McPherson usage(); 47460fffc19Sjw149990 } 4757c478bd9Sstevel@tonic-gate 476*a0261a43SJames C. McPherson static void 477*a0261a43SJames C. McPherson logmsg(int level, const char *msg, ...) 4787c478bd9Sstevel@tonic-gate { 479*a0261a43SJames C. McPherson va_list ap; 4807c478bd9Sstevel@tonic-gate 481*a0261a43SJames C. McPherson if ((level >= MSG_ERROR) || 482*a0261a43SJames C. McPherson ((debugflag > 0) && (level >= MSG_INFO))) { 483*a0261a43SJames C. McPherson (void) fprintf(stdout, "stmsboot: "); 484*a0261a43SJames C. McPherson va_start(ap, msg); 485*a0261a43SJames C. McPherson (void) vfprintf(stdout, msg, ap); 486*a0261a43SJames C. McPherson va_end(ap); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate /* 491*a0261a43SJames C. McPherson * It's up to the caller to do any sorting or pretty-printing of the device 492*a0261a43SJames C. McPherson * mappings we report. Since we're storing the device links as just the cXtYdZ 493*a0261a43SJames C. McPherson * part, we'll add /dev/rdsk/ back on when we print the listing so we maintain 494*a0261a43SJames C. McPherson * compatibility with previous versions of this tool. There's a little bit 495*a0261a43SJames C. McPherson * of footwork involved to make sure that we show all the paths to a device 496*a0261a43SJames C. McPherson * rather than just the first one we stashed away. 4977c478bd9Sstevel@tonic-gate */ 4987c478bd9Sstevel@tonic-gate static void 499*a0261a43SJames C. McPherson list_devs(int listguids, int ctrl) 5007c478bd9Sstevel@tonic-gate { 501*a0261a43SJames C. McPherson nvlist_t *thisdevnvl; 502*a0261a43SJames C. McPherson nvpair_t *pair; 503*a0261a43SJames C. McPherson char *diskpath, *livepath, *key, *querydev; 504*a0261a43SJames C. McPherson char *matchctrl = NULL; 505*a0261a43SJames C. McPherson char checkctrl[MAXPATHLEN]; 506*a0261a43SJames C. McPherson int rv; 5077c478bd9Sstevel@tonic-gate 508*a0261a43SJames C. McPherson if (!mpxenabled) { 509*a0261a43SJames C. McPherson logmsg(MSG_ERROR, gettext("MPxIO is not enabled\n")); 510*a0261a43SJames C. McPherson return; 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate 513*a0261a43SJames C. McPherson if (listguids) { 514*a0261a43SJames C. McPherson (void) printf(gettext("non-STMS device name\t\t\tGUID\n" 515*a0261a43SJames C. McPherson "------------------------------------------" 516*a0261a43SJames C. McPherson "------------------------\n")); 5177c478bd9Sstevel@tonic-gate } else { 518*a0261a43SJames C. McPherson (void) printf(gettext("non-STMS device name\t\t\t" 519*a0261a43SJames C. McPherson "STMS device name\n" 520*a0261a43SJames C. McPherson "------------------------------------------" 521*a0261a43SJames C. McPherson "------------------------\n")); 522*a0261a43SJames C. McPherson } 523*a0261a43SJames C. McPherson 524*a0261a43SJames C. McPherson bzero(checkctrl, MAXPATHLEN); 525*a0261a43SJames C. McPherson pair = NULL; 526*a0261a43SJames C. McPherson while ((pair = nvlist_next_nvpair(mapnvl, pair)) 527*a0261a43SJames C. McPherson != NULL) { 528*a0261a43SJames C. McPherson boolean_t livescsivhcip = B_FALSE; 529*a0261a43SJames C. McPherson 530*a0261a43SJames C. McPherson if ((((rv = nvpair_value_string(pair, &querydev)) < 0) || 531*a0261a43SJames C. McPherson ((key = nvpair_name(pair)) == NULL)) || 532*a0261a43SJames C. McPherson ((strstr(key, "/pci") != NULL) || 533*a0261a43SJames C. McPherson (strstr(key, "/sbus") != NULL) || 534*a0261a43SJames C. McPherson (strstr(key, "/scsi_vhci") != NULL) || 535*a0261a43SJames C. McPherson (strncmp(key, "id1", 3) == 0))) { 536*a0261a43SJames C. McPherson logmsg(MSG_INFO, 537*a0261a43SJames C. McPherson "list_devs: rv = %d; (%s) is not a devlink, " 538*a0261a43SJames C. McPherson "continuing.\n", rv, 539*a0261a43SJames C. McPherson (key != NULL) ? key : "null"); 540*a0261a43SJames C. McPherson querydev = NULL; 541*a0261a43SJames C. McPherson continue; 542*a0261a43SJames C. McPherson } 543*a0261a43SJames C. McPherson 544*a0261a43SJames C. McPherson (void) nvlist_lookup_nvlist(mapnvl, querydev, &thisdevnvl); 545*a0261a43SJames C. McPherson (void) nvlist_lookup_boolean_value(thisdevnvl, NVL_MPXEN, 546*a0261a43SJames C. McPherson &livescsivhcip); 547*a0261a43SJames C. McPherson (void) nvlist_lookup_string(thisdevnvl, NVL_MPXPATH, 548*a0261a43SJames C. McPherson &livepath); 549*a0261a43SJames C. McPherson 550*a0261a43SJames C. McPherson if ((!livescsivhcip) || 551*a0261a43SJames C. McPherson (livescsivhcip && 552*a0261a43SJames C. McPherson (strncmp(key, livepath, strlen(key)) == 0))) 553*a0261a43SJames C. McPherson continue; 554*a0261a43SJames C. McPherson 555*a0261a43SJames C. McPherson (void) nvlist_lookup_string(thisdevnvl, NVL_PATH, 556*a0261a43SJames C. McPherson &diskpath); 557*a0261a43SJames C. McPherson 558*a0261a43SJames C. McPherson logmsg(MSG_INFO, 559*a0261a43SJames C. McPherson "list_devs: %s :: %s ::%s :: MPXEN (%s)\n", 560*a0261a43SJames C. McPherson key, diskpath, livepath, 561*a0261a43SJames C. McPherson ((livescsivhcip) ? "TRUE" : "FALSE")); 562*a0261a43SJames C. McPherson 563*a0261a43SJames C. McPherson if (ctrl > -1) { 564*a0261a43SJames C. McPherson (void) sprintf(checkctrl, "c%dt", ctrl); 565*a0261a43SJames C. McPherson matchctrl = strstr(key, checkctrl); 566*a0261a43SJames C. McPherson if (matchctrl == NULL) 567*a0261a43SJames C. McPherson continue; 568*a0261a43SJames C. McPherson } 569*a0261a43SJames C. McPherson if (listguids != 0) { 570*a0261a43SJames C. McPherson char *tempguid; 571*a0261a43SJames C. McPherson ddi_devid_t curdevid; 572*a0261a43SJames C. McPherson int rv; 573*a0261a43SJames C. McPherson 574*a0261a43SJames C. McPherson rv = devid_str_decode(querydev, &curdevid, NULL); 575*a0261a43SJames C. McPherson if (rv == -1) { 576*a0261a43SJames C. McPherson logmsg(MSG_INFO, "Unable to decode devid %s\n", 577*a0261a43SJames C. McPherson key); 578*a0261a43SJames C. McPherson continue; 579*a0261a43SJames C. McPherson } 580*a0261a43SJames C. McPherson tempguid = devid_to_guid(curdevid); 581*a0261a43SJames C. McPherson if (tempguid != NULL) 582*a0261a43SJames C. McPherson (void) printf("/dev/rdsk/%s\t%s\n", 583*a0261a43SJames C. McPherson diskpath, tempguid); 584*a0261a43SJames C. McPherson 585*a0261a43SJames C. McPherson devid_free_guid(tempguid); 586*a0261a43SJames C. McPherson devid_free(curdevid); 587*a0261a43SJames C. McPherson continue; 588*a0261a43SJames C. McPherson } 589*a0261a43SJames C. McPherson 590*a0261a43SJames C. McPherson (void) printf("/dev/rdsk/%s\t/dev/rdsk/%s\n", 591*a0261a43SJames C. McPherson (strstr(key, diskpath) == NULL) ? key : diskpath, 592*a0261a43SJames C. McPherson livepath); 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate /* 597*a0261a43SJames C. McPherson * We get passed a device name which we search the mapnvl for. If we find 598*a0261a43SJames C. McPherson * it, we print the mapping as it is found. It is up to the caller of this 599*a0261a43SJames C. McPherson * utility to do any pretty-printing of the results. If a device listed on 600*a0261a43SJames C. McPherson * the command line does not exist in the mapnvl, then we print NOT_MAPPED. 601*a0261a43SJames C. McPherson * Otherwise we print the command-line device name as it maps to what is 602*a0261a43SJames C. McPherson * stashed in the mapnvl - even if that's a "no change" device mapping. 6037c478bd9Sstevel@tonic-gate * 604*a0261a43SJames C. McPherson * Example output (-p maps to physpath=BOOT) 605*a0261a43SJames C. McPherson * # /lib/mpxio/stmsboot_util -p \ 606*a0261a43SJames C. McPherson * /pci@0,0/pci1022,7450@2/pci1000,3060@3/sd@1,0:a 607*a0261a43SJames C. McPherson * /scsi_vhci/disk@g500000e011e17720:a 6087c478bd9Sstevel@tonic-gate * 609*a0261a43SJames C. McPherson * Or the reverse: 610*a0261a43SJames C. McPherson * # /lib/mpxio/stmsboot_util -p /scsi_vhci/disk@g500000e011e17720:a 611*a0261a43SJames C. McPherson * /pci@0,0/pci1022,7450@2/pci1000,3060@3/sd@1,0:a 612*a0261a43SJames C. McPherson * 613*a0261a43SJames C. McPherson * For the -m option, used when we're trying to find the root device mapping: 614*a0261a43SJames C. McPherson * 615*a0261a43SJames C. McPherson * # /lib/mpxio/stmsboot_util -m /dev/dsk/c2t0d0s2 616*a0261a43SJames C. McPherson * /dev/dsk/c3t500000E011637CF0d0s2 617*a0261a43SJames C. McPherson */ 618*a0261a43SJames C. McPherson static void 619*a0261a43SJames C. McPherson report_map(char *argdev, int physpath) 620*a0261a43SJames C. McPherson { 621*a0261a43SJames C. McPherson nvlist_t *thisdev; 622*a0261a43SJames C. McPherson int rv = 0; 623*a0261a43SJames C. McPherson char *thisdevid; 624*a0261a43SJames C. McPherson char *mpxpath = NULL; 625*a0261a43SJames C. McPherson char *prefixt = NULL; 626*a0261a43SJames C. McPherson char *prefixp = NULL; 627*a0261a43SJames C. McPherson char *stripdev = NULL; 628*a0261a43SJames C. McPherson char *slice = NULL; 629*a0261a43SJames C. McPherson boolean_t mpxenp; 630*a0261a43SJames C. McPherson uint_t slicelen = 0; 631*a0261a43SJames C. McPherson 632*a0261a43SJames C. McPherson mpxenp = B_FALSE; 633*a0261a43SJames C. McPherson 634*a0261a43SJames C. McPherson if ((prefixt = calloc(1, strlen(argdev) + 1)) == NULL) { 635*a0261a43SJames C. McPherson logmsg(MSG_INFO, "Unable to allocate memory\n"); 636*a0261a43SJames C. McPherson (void) printf("NOT_MAPPED\n"); 637*a0261a43SJames C. McPherson return; 638*a0261a43SJames C. McPherson } 639*a0261a43SJames C. McPherson 640*a0261a43SJames C. McPherson (void) strlcpy(prefixt, argdev, strlen(argdev) + 1); 641*a0261a43SJames C. McPherson 642*a0261a43SJames C. McPherson slice = strrchr(argdev, (physpath == BOOT) ? ':' : 's'); 643*a0261a43SJames C. McPherson if (slice != NULL) { 644*a0261a43SJames C. McPherson slicelen = strlen(slice); 645*a0261a43SJames C. McPherson if (slicelen > 3) 646*a0261a43SJames C. McPherson /* invalid size - max is 3 chars */ 647*a0261a43SJames C. McPherson slicelen = 0; 648*a0261a43SJames C. McPherson } 649*a0261a43SJames C. McPherson 650*a0261a43SJames C. McPherson if ((stripdev = calloc(1, strlen(prefixt) + 1)) == NULL) { 651*a0261a43SJames C. McPherson logmsg(MSG_INFO, "Unable to allocate memory\n"); 652*a0261a43SJames C. McPherson (void) printf("NOT_MAPPED\n"); 653*a0261a43SJames C. McPherson free(prefixt); 654*a0261a43SJames C. McPherson return; 655*a0261a43SJames C. McPherson } 656*a0261a43SJames C. McPherson 657*a0261a43SJames C. McPherson if ((strstr(prefixt, "/scsi_vhci") == NULL) && 658*a0261a43SJames C. McPherson (strstr(prefixt, "/pci") == NULL) && 659*a0261a43SJames C. McPherson (strstr(prefixt, "/sbus") == NULL)) { 660*a0261a43SJames C. McPherson prefixp = strrchr(prefixt, '/'); 661*a0261a43SJames C. McPherson (void) strlcpy(stripdev, 662*a0261a43SJames C. McPherson (prefixp == NULL) ? prefixt : prefixp + 1, 663*a0261a43SJames C. McPherson (prefixp == NULL) ? 664*a0261a43SJames C. McPherson strlen(prefixt) + 1: strlen(prefixp) + 1); 665*a0261a43SJames C. McPherson if (prefixp != NULL) 666*a0261a43SJames C. McPherson prefixt[strlen(argdev) - strlen(prefixp) + 1] = '\0'; 667*a0261a43SJames C. McPherson } else { 668*a0261a43SJames C. McPherson if (physpath != BOOT) { 669*a0261a43SJames C. McPherson logmsg(MSG_INFO, "Invalid device path provided\n"); 670*a0261a43SJames C. McPherson (void) printf("NOT_MAPPED\n"); 671*a0261a43SJames C. McPherson free(stripdev); 672*a0261a43SJames C. McPherson free(prefixt); 673*a0261a43SJames C. McPherson return; 674*a0261a43SJames C. McPherson } 675*a0261a43SJames C. McPherson (void) strlcpy(stripdev, argdev, strlen(argdev) + 1); 676*a0261a43SJames C. McPherson } 677*a0261a43SJames C. McPherson 678*a0261a43SJames C. McPherson logmsg(MSG_INFO, 679*a0261a43SJames C. McPherson "stripdev (%s), prefixt(%s), prefixp(%s), slice(%s)\n", 680*a0261a43SJames C. McPherson (stripdev == NULL) ? "null" : stripdev, 681*a0261a43SJames C. McPherson (prefixt == NULL) ? "null" : prefixt, 682*a0261a43SJames C. McPherson (prefixp == NULL) ? "null" : prefixp, 683*a0261a43SJames C. McPherson (slice == NULL) ? "null" : slice); 684*a0261a43SJames C. McPherson 685*a0261a43SJames C. McPherson if (slicelen > 0) 686*a0261a43SJames C. McPherson stripdev[strlen(stripdev) - slicelen] = '\0'; 687*a0261a43SJames C. McPherson 688*a0261a43SJames C. McPherson /* search for the shortened version */ 689*a0261a43SJames C. McPherson rv = nvlist_lookup_string(mapnvl, stripdev, &thisdevid); 690*a0261a43SJames C. McPherson if (rv) { 691*a0261a43SJames C. McPherson if (physpath != BOOT) { 692*a0261a43SJames C. McPherson logmsg(MSG_INFO, 693*a0261a43SJames C. McPherson "searched mapnvl for '%s', got %s (%d)\n", 694*a0261a43SJames C. McPherson stripdev, strerror(rv), rv); 695*a0261a43SJames C. McPherson (void) printf("NOT_MAPPED\n"); 696*a0261a43SJames C. McPherson free(stripdev); 697*a0261a43SJames C. McPherson free(prefixt); 698*a0261a43SJames C. McPherson return; 699*a0261a43SJames C. McPherson } 700*a0261a43SJames C. McPherson } 701*a0261a43SJames C. McPherson 702*a0261a43SJames C. McPherson logmsg(MSG_INFO, "device %s has devid %s\n", stripdev, thisdevid); 703*a0261a43SJames C. McPherson 704*a0261a43SJames C. McPherson if (nvlist_lookup_nvlist(mapnvl, thisdevid, &thisdev) != 0) { 705*a0261a43SJames C. McPherson logmsg(MSG_INFO, "device (%s) in mapnvl but " 706*a0261a43SJames C. McPherson "not mapped!\n", thisdevid); 707*a0261a43SJames C. McPherson (void) printf("NOT_MAPPED\n"); 708*a0261a43SJames C. McPherson free(stripdev); 709*a0261a43SJames C. McPherson free(prefixt); 710*a0261a43SJames C. McPherson return; 711*a0261a43SJames C. McPherson } 712*a0261a43SJames C. McPherson 713*a0261a43SJames C. McPherson /* quick exit */ 714*a0261a43SJames C. McPherson if (!mpxenabled && (strstr(argdev, "/pci") != NULL || 715*a0261a43SJames C. McPherson strstr(argdev, "/sbus") != NULL)) { 716*a0261a43SJames C. McPherson (void) printf("%s\n", argdev); 717*a0261a43SJames C. McPherson free(stripdev); 718*a0261a43SJames C. McPherson free(prefixt); 719*a0261a43SJames C. McPherson return; 720*a0261a43SJames C. McPherson } 721*a0261a43SJames C. McPherson 722*a0261a43SJames C. McPherson (void) nvlist_lookup_boolean_value(thisdev, NVL_MPXEN, &mpxenp); 723*a0261a43SJames C. McPherson 724*a0261a43SJames C. McPherson if (physpath == BOOT) { 725*a0261a43SJames C. McPherson (void) nvlist_lookup_string(thisdev, NVL_PHYSPATH, &mpxpath); 726*a0261a43SJames C. McPherson if ((strstr(argdev, "/scsi_vhci") != NULL) && 727*a0261a43SJames C. McPherson (strncmp(argdev, mpxpath, strlen(mpxpath)) == 0)) { 728*a0261a43SJames C. McPherson /* Need to translate vhci to phci */ 729*a0261a43SJames C. McPherson char *realpath; 730*a0261a43SJames C. McPherson 731*a0261a43SJames C. McPherson if ((realpath = calloc(1, MAXPATHLEN + 1)) == NULL) { 732*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 733*a0261a43SJames C. McPherson gettext("Unable to allocate " 734*a0261a43SJames C. McPherson "memory for a path element\n")); 735*a0261a43SJames C. McPherson free(stripdev); 736*a0261a43SJames C. McPherson free(prefixt); 737*a0261a43SJames C. McPherson return; 738*a0261a43SJames C. McPherson } 739*a0261a43SJames C. McPherson vhci_to_phci(stripdev, realpath); 740*a0261a43SJames C. McPherson (void) printf("%s%s\n", realpath, 741*a0261a43SJames C. McPherson ((slicelen > 0) && slice != NULL) ? slice : ""); 742*a0261a43SJames C. McPherson free(realpath); 743*a0261a43SJames C. McPherson } else { 744*a0261a43SJames C. McPherson (void) printf("%s%s\n", mpxpath, 745*a0261a43SJames C. McPherson ((slicelen > 0) && slice != NULL) ? slice : ""); 746*a0261a43SJames C. McPherson } 747*a0261a43SJames C. McPherson } else { 748*a0261a43SJames C. McPherson (void) nvlist_lookup_string(thisdev, 749*a0261a43SJames C. McPherson ((readonlyroot) ? NVL_PHYSPATH : 750*a0261a43SJames C. McPherson ((mpxenp == B_TRUE) ? NVL_MPXPATH : NVL_PATH)), 751*a0261a43SJames C. McPherson &mpxpath); 752*a0261a43SJames C. McPherson logmsg(MSG_INFO, "mpxpath = %s\n", 753*a0261a43SJames C. McPherson (mpxpath == NULL) ? "null" : mpxpath); 754*a0261a43SJames C. McPherson if (readonlyroot || 755*a0261a43SJames C. McPherson (strstr(mpxpath, "/scsi_vhci") != NULL) || 756*a0261a43SJames C. McPherson (strstr(mpxpath, "/pci") != NULL) || 757*a0261a43SJames C. McPherson (strstr(mpxpath, "/sbus") != NULL)) { 758*a0261a43SJames C. McPherson /* 759*a0261a43SJames C. McPherson * If we see a physical path here it means that 760*a0261a43SJames C. McPherson * devlinks aren't fully initialised yet, so we 761*a0261a43SJames C. McPherson * are still in maintenance/single-user mode. 762*a0261a43SJames C. McPherson */ 763*a0261a43SJames C. McPherson (void) printf("/devices%s:%c\n", mpxpath, 764*a0261a43SJames C. McPherson slice[1] + '1'); 765*a0261a43SJames C. McPherson } else { 766*a0261a43SJames C. McPherson (void) printf("%s%s%s\n", 767*a0261a43SJames C. McPherson (prefixt[0] == '/') ? prefixt : "", 768*a0261a43SJames C. McPherson mpxpath, 769*a0261a43SJames C. McPherson ((slicelen > 0) && slice != NULL) ? slice : ""); 770*a0261a43SJames C. McPherson } 771*a0261a43SJames C. McPherson } 772*a0261a43SJames C. McPherson free(prefixt); 773*a0261a43SJames C. McPherson free(stripdev); 774*a0261a43SJames C. McPherson } 775*a0261a43SJames C. McPherson 776*a0261a43SJames C. McPherson /* 777*a0261a43SJames C. McPherson * Validate the in-kernel and on-disk forms of our devid cache, 778*a0261a43SJames C. McPherson * returns -1 for unfixable error and 0 for success. 7797c478bd9Sstevel@tonic-gate */ 7807c478bd9Sstevel@tonic-gate static int 781*a0261a43SJames C. McPherson validate_devnvl() 782*a0261a43SJames C. McPherson { 783*a0261a43SJames C. McPherson di_node_t curnode; 784*a0261a43SJames C. McPherson int rv1 = -1; 785*a0261a43SJames C. McPherson int rv2 = -1; 786*a0261a43SJames C. McPherson 787*a0261a43SJames C. McPherson /* 788*a0261a43SJames C. McPherson * Method: we walk through the kernel's concept of the device tree 789*a0261a43SJames C. McPherson * looking for "ssd" then "sd" nodes. 790*a0261a43SJames C. McPherson * We check to see whether the device's devid is already in our nvlist 791*a0261a43SJames C. McPherson * (on disk) nvlist cache file. If it is, we check that it's components 792*a0261a43SJames C. McPherson * match what we've got already and fill any missing fields. 793*a0261a43SJames C. McPherson * If the devid isn't in our on-disk nvlist already then we add it 794*a0261a43SJames C. McPherson * and populate the property nvpairs. 795*a0261a43SJames C. McPherson * 796*a0261a43SJames C. McPherson * At the end of this function we should have this program's concept 797*a0261a43SJames C. McPherson * of the devid-keyed nvlist matching what is in the ondisk form which 798*a0261a43SJames C. McPherson * is ready to be written out. 799*a0261a43SJames C. McPherson * If we can't do this, then we return -1. 800*a0261a43SJames C. McPherson */ 801*a0261a43SJames C. McPherson curnode = di_drv_first_node("ssd", devinfo_root); 802*a0261a43SJames C. McPherson if (curnode != DI_NODE_NIL) 803*a0261a43SJames C. McPherson rv1 = mpxio_nvl_boilerplate(curnode); 804*a0261a43SJames C. McPherson 805*a0261a43SJames C. McPherson curnode = di_drv_first_node("sd", devinfo_root); 806*a0261a43SJames C. McPherson if (curnode != DI_NODE_NIL) 807*a0261a43SJames C. McPherson rv2 = mpxio_nvl_boilerplate(curnode); 808*a0261a43SJames C. McPherson 809*a0261a43SJames C. McPherson if (rv1 + rv2 == -2) 810*a0261a43SJames C. McPherson return (-1); 811*a0261a43SJames C. McPherson 812*a0261a43SJames C. McPherson return (0); 813*a0261a43SJames C. McPherson } 814*a0261a43SJames C. McPherson 815*a0261a43SJames C. McPherson static int 816*a0261a43SJames C. McPherson mpxio_nvl_boilerplate(di_node_t curnode) 817*a0261a43SJames C. McPherson { 818*a0261a43SJames C. McPherson int rv; 819*a0261a43SJames C. McPherson char *strdevid; 820*a0261a43SJames C. McPherson ddi_devid_t curdevid; 821*a0261a43SJames C. McPherson nvlist_t *newnvl; 822*a0261a43SJames C. McPherson 823*a0261a43SJames C. McPherson for (; curnode != DI_NODE_NIL; curnode = di_drv_next_node(curnode)) { 824*a0261a43SJames C. McPherson errno = 0; 825*a0261a43SJames C. McPherson 826*a0261a43SJames C. McPherson curdevid = NULL; 827*a0261a43SJames C. McPherson get_devid(curnode, &curdevid); 828*a0261a43SJames C. McPherson if (curdevid == NULL) 829*a0261a43SJames C. McPherson /* 830*a0261a43SJames C. McPherson * There's no devid registered for this device 831*a0261a43SJames C. McPherson * so it's not cool enough to play with us 832*a0261a43SJames C. McPherson */ 833*a0261a43SJames C. McPherson continue; 834*a0261a43SJames C. McPherson 835*a0261a43SJames C. McPherson strdevid = devid_str_encode(curdevid, NULL); 836*a0261a43SJames C. McPherson /* does this exist in the on-disk cache? */ 837*a0261a43SJames C. McPherson rv = nvlist_lookup_nvlist(mapnvl, strdevid, &newnvl); 838*a0261a43SJames C. McPherson if (rv == ENOENT) { 839*a0261a43SJames C. McPherson logmsg(MSG_INFO, "nvlist for %s not found\n", strdevid); 840*a0261a43SJames C. McPherson /* no, so alloc a new nvl to store it */ 841*a0261a43SJames C. McPherson if (nvlist_alloc(&newnvl, NV_UNIQUE_NAME, 0) != 0) { 842*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 843*a0261a43SJames C. McPherson gettext("Unable to allocate space for " 844*a0261a43SJames C. McPherson "a devid property list: %s\n"), 845*a0261a43SJames C. McPherson strerror(errno)); 846*a0261a43SJames C. McPherson return (-1); 847*a0261a43SJames C. McPherson } 848*a0261a43SJames C. McPherson } else { 849*a0261a43SJames C. McPherson if ((rv != ENOTSUP) && (rv != EINVAL)) 850*a0261a43SJames C. McPherson logmsg(MSG_INFO, 851*a0261a43SJames C. McPherson "%s exists in ondisknvl, verifying\n", 852*a0261a43SJames C. McPherson strdevid); 853*a0261a43SJames C. McPherson } 854*a0261a43SJames C. McPherson 855*a0261a43SJames C. McPherson if (popcheck_devnvl(curnode, newnvl, strdevid) != 0) { 856*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 857*a0261a43SJames C. McPherson gettext("Unable to populate devid nvpair " 858*a0261a43SJames C. McPherson "for device with devid %s\n"), 859*a0261a43SJames C. McPherson strdevid); 860*a0261a43SJames C. McPherson devid_str_free(strdevid); 861*a0261a43SJames C. McPherson nvlist_free(newnvl); 862*a0261a43SJames C. McPherson return (-1); 863*a0261a43SJames C. McPherson } 864*a0261a43SJames C. McPherson 865*a0261a43SJames C. McPherson /* Now add newnvl into our cache. */ 866*a0261a43SJames C. McPherson errno = 0; 867*a0261a43SJames C. McPherson rv = nvlist_add_nvlist(mapnvl, strdevid, newnvl); 868*a0261a43SJames C. McPherson if (rv) { 869*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 870*a0261a43SJames C. McPherson gettext("Unable to add device (devid %s) " 871*a0261a43SJames C. McPherson "to in-kernel nvl: %s (%d)\n"), 872*a0261a43SJames C. McPherson strdevid, strerror(rv), rv); 873*a0261a43SJames C. McPherson devid_str_free(strdevid); 874*a0261a43SJames C. McPherson nvlist_free(newnvl); 875*a0261a43SJames C. McPherson return (-1); 876*a0261a43SJames C. McPherson } 877*a0261a43SJames C. McPherson logmsg(MSG_INFO, 878*a0261a43SJames C. McPherson gettext("added device (devid %s) to mapnvl\n\n"), 879*a0261a43SJames C. McPherson strdevid); 880*a0261a43SJames C. McPherson devid_str_free(strdevid); 881*a0261a43SJames C. McPherson } 882*a0261a43SJames C. McPherson return (0); 883*a0261a43SJames C. McPherson } 884*a0261a43SJames C. McPherson 885*a0261a43SJames C. McPherson /* 886*a0261a43SJames C. McPherson * Operates on a single di_node_t, collecting all the device properties 887*a0261a43SJames C. McPherson * that we need. devnvl is allocated by the caller, and we add our nvpairs 888*a0261a43SJames C. McPherson * to it if they don't already exist. 889*a0261a43SJames C. McPherson * 890*a0261a43SJames C. McPherson * We are _only_ interested in devices which have a devid. We pull in 891*a0261a43SJames C. McPherson * devices even when they're excluded via stmsboot -D (driver), because 892*a0261a43SJames C. McPherson * we don't want to miss out on any devid data that might be handy later. 893*a0261a43SJames C. McPherson */ 894*a0261a43SJames C. McPherson static int 895*a0261a43SJames C. McPherson popcheck_devnvl(di_node_t thisnode, nvlist_t *devnvl, char *strdevid) 896*a0261a43SJames C. McPherson { 897*a0261a43SJames C. McPherson char *path = NULL; 898*a0261a43SJames C. McPherson char *curpath = NULL; 899*a0261a43SJames C. McPherson char *devfspath = NULL; 900*a0261a43SJames C. McPherson int scsivhciparent = 0; 901*a0261a43SJames C. McPherson int rv = 0; 902*a0261a43SJames C. McPherson boolean_t mpxenp = B_FALSE; 903*a0261a43SJames C. McPherson 904*a0261a43SJames C. McPherson errno = 0; 905*a0261a43SJames C. McPherson devfspath = di_devfs_path(thisnode); 906*a0261a43SJames C. McPherson if (devfspath == NULL) { 907*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 908*a0261a43SJames C. McPherson gettext("Unable to determine devfs path for node: %s\n"), 909*a0261a43SJames C. McPherson strerror(errno)); 910*a0261a43SJames C. McPherson return (-1); 911*a0261a43SJames C. McPherson } 912*a0261a43SJames C. McPherson 913*a0261a43SJames C. McPherson /* Add a convenient devfspath to devid inverse map */ 914*a0261a43SJames C. McPherson if (nvlist_add_string(mapnvl, devfspath, strdevid) != 0) { 915*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 916*a0261a43SJames C. McPherson gettext("Unable to add device path %s with devid " 917*a0261a43SJames C. McPherson "%s to mapnvl\n"), devfspath, strdevid); 918*a0261a43SJames C. McPherson return (-1); 919*a0261a43SJames C. McPherson } 920*a0261a43SJames C. McPherson if (strncmp(di_driver_name(di_parent_node(thisnode)), 921*a0261a43SJames C. McPherson "scsi_vhci", 9) == 0) { 922*a0261a43SJames C. McPherson scsivhciparent = 1; 923*a0261a43SJames C. McPherson if (!mpxenabled) 924*a0261a43SJames C. McPherson mpxenabled++; 925*a0261a43SJames C. McPherson 926*a0261a43SJames C. McPherson rv = nvlist_lookup_boolean_value(devnvl, NVL_MPXEN, &mpxenp); 927*a0261a43SJames C. McPherson if (rv || (mpxenp == B_FALSE)) { 928*a0261a43SJames C. McPherson rv = nvlist_add_boolean_value(devnvl, 929*a0261a43SJames C. McPherson NVL_MPXEN, B_TRUE); 930*a0261a43SJames C. McPherson if (rv) { 931*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 932*a0261a43SJames C. McPherson gettext("Unable to add property %s " 933*a0261a43SJames C. McPherson "(set to B_TRUE) for device %s: " 934*a0261a43SJames C. McPherson "%s (%d)\n"), 935*a0261a43SJames C. McPherson NVL_MPXEN, devfspath, 936*a0261a43SJames C. McPherson strerror(rv), rv); 937*a0261a43SJames C. McPherson return (-1); 938*a0261a43SJames C. McPherson } 939*a0261a43SJames C. McPherson logmsg(MSG_INFO, "NVL_MPXEN :: (B_FALSE->B_TRUE)\n"); 940*a0261a43SJames C. McPherson } 941*a0261a43SJames C. McPherson } else { 942*a0261a43SJames C. McPherson /* turn _off_ the flag if it was enabled */ 943*a0261a43SJames C. McPherson rv = nvlist_add_boolean_value(devnvl, NVL_MPXEN, B_FALSE); 944*a0261a43SJames C. McPherson if (rv) { 945*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 946*a0261a43SJames C. McPherson gettext("Unable to add property %s " 947*a0261a43SJames C. McPherson "(set to B_FALSE) for device %s: %s (%d)\n"), 948*a0261a43SJames C. McPherson NVL_MPXEN, devfspath, 949*a0261a43SJames C. McPherson strerror(rv), rv); 950*a0261a43SJames C. McPherson return (-1); 951*a0261a43SJames C. McPherson } 952*a0261a43SJames C. McPherson logmsg(MSG_INFO, "NVL_MPXEN :: (B_TRUE-> B_FALSE)\n"); 953*a0261a43SJames C. McPherson } 954*a0261a43SJames C. McPherson 955*a0261a43SJames C. McPherson rv = nvlist_add_string(devnvl, NVL_PHYSPATH, devfspath); 956*a0261a43SJames C. McPherson if (rv) { 957*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 958*a0261a43SJames C. McPherson gettext("Unable to add physical device path (%s) " 959*a0261a43SJames C. McPherson "property to nvl\n")); 960*a0261a43SJames C. McPherson return (-1); 961*a0261a43SJames C. McPherson } 962*a0261a43SJames C. McPherson 963*a0261a43SJames C. McPherson if ((curpath = calloc(1, MAXPATHLEN)) == NULL) { 964*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 965*a0261a43SJames C. McPherson gettext("Unable to allocate space for current path\n")); 966*a0261a43SJames C. McPherson return (-1); 967*a0261a43SJames C. McPherson } 968*a0261a43SJames C. McPherson curpath = find_link(thisnode); 969*a0261a43SJames C. McPherson if (curpath == NULL) { 970*a0261a43SJames C. McPherson if (readonlyroot) { 971*a0261a43SJames C. McPherson return (0); 972*a0261a43SJames C. McPherson } 973*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 974*a0261a43SJames C. McPherson gettext("Unable to determine device path for node %s\n"), 975*a0261a43SJames C. McPherson devfspath); 976*a0261a43SJames C. McPherson return (-1); 977*a0261a43SJames C. McPherson } 978*a0261a43SJames C. McPherson 979*a0261a43SJames C. McPherson rv = nvlist_lookup_string(devnvl, NVL_MPXPATH, &path); 980*a0261a43SJames C. McPherson 981*a0261a43SJames C. McPherson if (path == NULL && scsivhciparent) 982*a0261a43SJames C. McPherson (void) nvlist_add_string(devnvl, NVL_MPXPATH, curpath); 983*a0261a43SJames C. McPherson 984*a0261a43SJames C. McPherson if (!scsivhciparent) { 985*a0261a43SJames C. McPherson (void) nvlist_add_string(devnvl, NVL_PATH, curpath); 986*a0261a43SJames C. McPherson path = curpath; 987*a0261a43SJames C. McPherson } 988*a0261a43SJames C. McPherson 989*a0261a43SJames C. McPherson /* 990*a0261a43SJames C. McPherson * This next block provides the path to devid inverse mapping 991*a0261a43SJames C. McPherson * that other functions require 992*a0261a43SJames C. McPherson */ 993*a0261a43SJames C. McPherson if (path != NULL) { 994*a0261a43SJames C. McPherson if (nvlist_add_string(mapnvl, path, strdevid) != 0) { 995*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 996*a0261a43SJames C. McPherson gettext("Unable to add device %s with devid " 997*a0261a43SJames C. McPherson "%s to mapnvl\n"), path, strdevid); 998*a0261a43SJames C. McPherson return (-1); 999*a0261a43SJames C. McPherson } 1000*a0261a43SJames C. McPherson logmsg(MSG_INFO, "popcheck_devnvl: added path %s :: %s\n", 1001*a0261a43SJames C. McPherson path, strdevid); 1002*a0261a43SJames C. McPherson if (nvlist_add_string(mapnvl, curpath, strdevid) != 0) { 1003*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1004*a0261a43SJames C. McPherson gettext("Unable to add device %s with devid " 1005*a0261a43SJames C. McPherson "%s to mapnvl: %s\n"), 1006*a0261a43SJames C. McPherson curpath, strdevid, strerror(errno)); 1007*a0261a43SJames C. McPherson return (-1); 1008*a0261a43SJames C. McPherson } 1009*a0261a43SJames C. McPherson logmsg(MSG_INFO, "popcheck_devnvl: added curpath %s :: %s\n", 1010*a0261a43SJames C. McPherson curpath, strdevid); 1011*a0261a43SJames C. McPherson } 1012*a0261a43SJames C. McPherson if (scsivhciparent) { 1013*a0261a43SJames C. McPherson if (nvlist_add_string(devnvl, NVL_MPXPATH, curpath) != 0) { 1014*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1015*a0261a43SJames C. McPherson gettext("Unable to add property %s for device " 1016*a0261a43SJames C. McPherson "%s: %s\n"), 1017*a0261a43SJames C. McPherson NVL_MPXPATH, devfspath, strerror(errno)); 1018*a0261a43SJames C. McPherson return (-1); 1019*a0261a43SJames C. McPherson } else { 1020*a0261a43SJames C. McPherson logmsg(MSG_INFO, "added curpath (%s) as NVL_MPXPATH " 1021*a0261a43SJames C. McPherson "to devnvl for devid %s\n", curpath, strdevid); 1022*a0261a43SJames C. McPherson } 1023*a0261a43SJames C. McPherson } 1024*a0261a43SJames C. McPherson return (0); 1025*a0261a43SJames C. McPherson } 1026*a0261a43SJames C. McPherson 1027*a0261a43SJames C. McPherson static void 1028*a0261a43SJames C. McPherson print_mpx_capable(di_node_t curnode) 1029*a0261a43SJames C. McPherson { 1030*a0261a43SJames C. McPherson char *prop; 1031*a0261a43SJames C. McPherson char *path; 1032*a0261a43SJames C. McPherson char *aliases = NULL; 1033*a0261a43SJames C. McPherson 1034*a0261a43SJames C. McPherson if (cap_N_option) { 1035*a0261a43SJames C. McPherson aliases = calloc(1, MAXPATHLEN + 1); 1036*a0261a43SJames C. McPherson if (aliases == NULL) { 1037*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1038*a0261a43SJames C. McPherson gettext("Unable to allocate memory for a device " 1039*a0261a43SJames C. McPherson "alias list\n")); 1040*a0261a43SJames C. McPherson return; 1041*a0261a43SJames C. McPherson } 1042*a0261a43SJames C. McPherson } 1043*a0261a43SJames C. McPherson 1044*a0261a43SJames C. McPherson for (; curnode != DI_NODE_NIL; curnode = di_drv_next_node(curnode)) { 1045*a0261a43SJames C. McPherson if (di_prop_lookup_strings(DDI_DEV_T_ANY, curnode, 1046*a0261a43SJames C. McPherson "initiator-port", &prop) >= 0) { 1047*a0261a43SJames C. McPherson if ((path = di_devfs_path(curnode)) == NULL) { 1048*a0261a43SJames C. McPherson logmsg(MSG_INFO, 1049*a0261a43SJames C. McPherson "Unable to find devfs path for device " 1050*a0261a43SJames C. McPherson "%s: %s\n", &curnode, strerror(errno)); 1051*a0261a43SJames C. McPherson continue; 1052*a0261a43SJames C. McPherson } 1053*a0261a43SJames C. McPherson if (cap_N_option) { 1054*a0261a43SJames C. McPherson char *nodename = di_node_name(curnode); 1055*a0261a43SJames C. McPherson /* nodename is never going to be null */ 1056*a0261a43SJames C. McPherson if (strstr(aliases, nodename) == NULL) 1057*a0261a43SJames C. McPherson /* haven't seen this nodename before */ 1058*a0261a43SJames C. McPherson (void) snprintf(aliases, 1059*a0261a43SJames C. McPherson MAXPATHLEN + 1, "%s|%s", 1060*a0261a43SJames C. McPherson ((aliases != NULL) ? aliases : ""), 1061*a0261a43SJames C. McPherson nodename); 1062*a0261a43SJames C. McPherson } else 1063*a0261a43SJames C. McPherson (void) printf("%s\n", path); 1064*a0261a43SJames C. McPherson } 1065*a0261a43SJames C. McPherson } 1066*a0261a43SJames C. McPherson if (cap_N_option) 1067*a0261a43SJames C. McPherson (void) printf("%s\n", aliases); 1068*a0261a43SJames C. McPherson } 1069*a0261a43SJames C. McPherson 1070*a0261a43SJames C. McPherson static int 1071*a0261a43SJames C. McPherson link_cb(di_devlink_t devlink, void *arg) 1072*a0261a43SJames C. McPherson { 1073*a0261a43SJames C. McPherson const char *result; 1074*a0261a43SJames C. McPherson 1075*a0261a43SJames C. McPherson result = di_devlink_path(devlink); 1076*a0261a43SJames C. McPherson if (result == NULL) { 1077*a0261a43SJames C. McPherson arg = (void *)"(null)"; 1078*a0261a43SJames C. McPherson } else { 1079*a0261a43SJames C. McPherson (void) strlcpy(arg, result, strlen(result)); 1080*a0261a43SJames C. McPherson } 1081*a0261a43SJames C. McPherson logmsg(MSG_INFO, "\nlink_cb::linkdata->resultstr = %s\n", 1082*a0261a43SJames C. McPherson ((result != NULL) ? result : "(null)")); 1083*a0261a43SJames C. McPherson return (DI_WALK_CONTINUE); 1084*a0261a43SJames C. McPherson } 1085*a0261a43SJames C. McPherson 1086*a0261a43SJames C. McPherson static char * 1087*a0261a43SJames C. McPherson find_link(di_node_t cnode) 1088*a0261a43SJames C. McPherson { 1089*a0261a43SJames C. McPherson di_minor_t devminor = DI_MINOR_NIL; 1090*a0261a43SJames C. McPherson di_devlink_handle_t hdl; 1091*a0261a43SJames C. McPherson char *devfspath = NULL; 1092*a0261a43SJames C. McPherson char *minorpath = NULL; 1093*a0261a43SJames C. McPherson char *linkname = NULL; 1094*a0261a43SJames C. McPherson char *cbresult = NULL; 1095*a0261a43SJames C. McPherson 1096*a0261a43SJames C. McPherson devfspath = di_devfs_path(cnode); 1097*a0261a43SJames C. McPherson if (cnode == DI_NODE_NIL) { 1098*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1099*a0261a43SJames C. McPherson gettext("find_ctrl must be called with non-null " 1100*a0261a43SJames C. McPherson "di_node_t\n")); 1101*a0261a43SJames C. McPherson return (NULL); 1102*a0261a43SJames C. McPherson } 1103*a0261a43SJames C. McPherson logmsg(MSG_INFO, "find_link: devfspath %s\n", devfspath); 1104*a0261a43SJames C. McPherson 1105*a0261a43SJames C. McPherson if (((cbresult = calloc(1, MAXPATHLEN)) == NULL) || 1106*a0261a43SJames C. McPherson ((minorpath = calloc(1, MAXPATHLEN)) == NULL) || 1107*a0261a43SJames C. McPherson ((linkname = calloc(1, MAXPATHLEN)) == NULL)) { 1108*a0261a43SJames C. McPherson logmsg(MSG_ERROR, "unable to allocate space for dev link\n"); 1109*a0261a43SJames C. McPherson return (NULL); 1110*a0261a43SJames C. McPherson } 1111*a0261a43SJames C. McPherson 1112*a0261a43SJames C. McPherson devminor = di_minor_next(cnode, devminor); 1113*a0261a43SJames C. McPherson hdl = di_devlink_init(di_devfs_minor_path(devminor), DI_MAKE_LINK); 1114*a0261a43SJames C. McPherson if (hdl == NULL) { 1115*a0261a43SJames C. McPherson logmsg((readonlyroot ? MSG_INFO : MSG_ERROR), 1116*a0261a43SJames C. McPherson gettext("unable to take devlink snapshot: %s\n"), 1117*a0261a43SJames C. McPherson strerror(errno)); 1118*a0261a43SJames C. McPherson return (NULL); 1119*a0261a43SJames C. McPherson } 1120*a0261a43SJames C. McPherson 1121*a0261a43SJames C. McPherson linkname = "^dsk/"; 1122*a0261a43SJames C. McPherson (void) snprintf(minorpath, MAXPATHLEN, "%s:c", devfspath); 1123*a0261a43SJames C. McPherson 1124*a0261a43SJames C. McPherson errno = 0; 1125*a0261a43SJames C. McPherson if (di_devlink_walk(hdl, linkname, minorpath, DI_PRIMARY_LINK, 1126*a0261a43SJames C. McPherson (void *)cbresult, link_cb) < 0) { 1127*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1128*a0261a43SJames C. McPherson gettext("Unable to walk devlink snapshot for %s: %s\n"), 1129*a0261a43SJames C. McPherson minorpath, strerror(errno)); 1130*a0261a43SJames C. McPherson return (NULL); 1131*a0261a43SJames C. McPherson } 1132*a0261a43SJames C. McPherson 1133*a0261a43SJames C. McPherson if (di_devlink_fini(&hdl) < 0) { 1134*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1135*a0261a43SJames C. McPherson gettext("Unable to close devlink snapshot: %s\n"), 1136*a0261a43SJames C. McPherson strerror(errno)); 1137*a0261a43SJames C. McPherson } 1138*a0261a43SJames C. McPherson if (strstr(cbresult, "dsk/") == NULL) 1139*a0261a43SJames C. McPherson return (devfspath); 1140*a0261a43SJames C. McPherson 1141*a0261a43SJames C. McPherson bzero(minorpath, MAXPATHLEN); 1142*a0261a43SJames C. McPherson /* strip off the trailing "s2" */ 1143*a0261a43SJames C. McPherson bcopy(cbresult, minorpath, strlen(cbresult) - 1); 1144*a0261a43SJames C. McPherson /* Now strip off the /dev/dsk/ prefix for output flexibility */ 1145*a0261a43SJames C. McPherson linkname = strrchr(minorpath, '/'); 1146*a0261a43SJames C. McPherson return (++linkname); 1147*a0261a43SJames C. McPherson } 1148*a0261a43SJames C. McPherson 1149*a0261a43SJames C. McPherson /* 1150*a0261a43SJames C. McPherson * handle case where device has been probed but its target driver is not 1151*a0261a43SJames C. McPherson * attached so enumeration has not quite finished. Opening the /devices 1152*a0261a43SJames C. McPherson * pathname will force the kernel to finish the enumeration process and 1153*a0261a43SJames C. McPherson * let us get the data we need. 1154*a0261a43SJames C. McPherson */ 1155*a0261a43SJames C. McPherson static void 1156*a0261a43SJames C. McPherson get_devid(di_node_t node, ddi_devid_t *thisdevid) 11577c478bd9Sstevel@tonic-gate { 11587c478bd9Sstevel@tonic-gate int fd; 1159*a0261a43SJames C. McPherson char realpath[MAXPATHLEN]; 1160*a0261a43SJames C. McPherson char *openpath = di_devfs_path(node); 11617c478bd9Sstevel@tonic-gate 1162*a0261a43SJames C. McPherson errno = 0; 1163*a0261a43SJames C. McPherson bzero(realpath, MAXPATHLEN); 1164*a0261a43SJames C. McPherson if (strstr(openpath, "/devices") == NULL) { 1165*a0261a43SJames C. McPherson (void) snprintf(realpath, MAXPATHLEN, 1166*a0261a43SJames C. McPherson "/devices%s:c,raw", openpath); 1167*a0261a43SJames C. McPherson fd = open(realpath, O_RDONLY|O_NDELAY); 116860fffc19Sjw149990 } else { 1169*a0261a43SJames C. McPherson fd = open(openpath, O_RDONLY|O_NDELAY); 117060fffc19Sjw149990 } 117160fffc19Sjw149990 1172*a0261a43SJames C. McPherson if (fd < 0) { 1173*a0261a43SJames C. McPherson logmsg(MSG_INFO, "Unable to open path %s: %s\n", 1174*a0261a43SJames C. McPherson openpath, strerror(errno)); 1175*a0261a43SJames C. McPherson return; 11767c478bd9Sstevel@tonic-gate } 11777c478bd9Sstevel@tonic-gate 1178*a0261a43SJames C. McPherson if (devid_get(fd, thisdevid) != 0) { 1179*a0261a43SJames C. McPherson logmsg(MSG_INFO, 1180*a0261a43SJames C. McPherson "'%s' node (%s) without a devid registered\n", 1181*a0261a43SJames C. McPherson di_driver_name(node), di_devfs_path(node)); 118260fffc19Sjw149990 } 11837c478bd9Sstevel@tonic-gate (void) close(fd); 11847c478bd9Sstevel@tonic-gate } 11857c478bd9Sstevel@tonic-gate 11868cecff49Sgp87344 static int 1187*a0261a43SJames C. McPherson print_bootpath() 11888cecff49Sgp87344 { 1189*a0261a43SJames C. McPherson char *bootprop = NULL; 11908cecff49Sgp87344 1191*a0261a43SJames C. McPherson if (di_prop_lookup_strings(DDI_DEV_T_ANY, devinfo_root, 1192*a0261a43SJames C. McPherson "bootpath", &bootprop) >= 0) { 1193*a0261a43SJames C. McPherson (void) printf("%s\n", bootprop); 11948cecff49Sgp87344 return (0); 1195*a0261a43SJames C. McPherson } else if (di_prop_lookup_strings(DDI_DEV_T_ANY, devinfo_root, 1196*a0261a43SJames C. McPherson "boot-path", &bootprop) >= 0) { 1197*a0261a43SJames C. McPherson (void) printf("%s\n", bootprop); 1198*a0261a43SJames C. McPherson return (0); 1199*a0261a43SJames C. McPherson } else { 1200*a0261a43SJames C. McPherson (void) printf("ERROR: no bootpath/boot-path property found\n"); 1201*a0261a43SJames C. McPherson return (ENOENT); 1202*a0261a43SJames C. McPherson } 12038cecff49Sgp87344 } 12048cecff49Sgp87344 12058cecff49Sgp87344 /* 1206*a0261a43SJames C. McPherson * We only call this routine if we have a scsi_vhci node and must 1207*a0261a43SJames C. McPherson * determine the actual physical path of its first online client 1208*a0261a43SJames C. McPherson * path. 12097c478bd9Sstevel@tonic-gate */ 1210*a0261a43SJames C. McPherson static void 1211*a0261a43SJames C. McPherson vhci_to_phci(char *devpath, char *physpath) 12127c478bd9Sstevel@tonic-gate { 12137c478bd9Sstevel@tonic-gate sv_iocdata_t ioc; 12145a4c37c9Sqh201292 sv_path_info_t *pi; 1215*a0261a43SJames C. McPherson int vhci_fd; 1216*a0261a43SJames C. McPherson int rv; 1217*a0261a43SJames C. McPherson uint_t npaths = 0; 12185a4c37c9Sqh201292 1219*a0261a43SJames C. McPherson vhci_fd = open(VHCI_CTL_NODE, O_RDWR); 1220*a0261a43SJames C. McPherson if (vhci_fd < 0) 1221*a0261a43SJames C. McPherson goto failure; 12225a4c37c9Sqh201292 12235a4c37c9Sqh201292 bzero(&ioc, sizeof (sv_iocdata_t)); 1224*a0261a43SJames C. McPherson ioc.client = devpath; 12255a4c37c9Sqh201292 ioc.ret_elem = &npaths; 1226*a0261a43SJames C. McPherson rv = ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, &ioc); 1227*a0261a43SJames C. McPherson if (rv || npaths == 0) { 1228*a0261a43SJames C. McPherson logmsg(MSG_INFO, 1229*a0261a43SJames C. McPherson "SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO ioctl() failed, " 1230*a0261a43SJames C. McPherson "%s (%d)\n", strerror(rv), rv); 1231*a0261a43SJames C. McPherson goto failure; 12325a4c37c9Sqh201292 } 12335a4c37c9Sqh201292 12345a4c37c9Sqh201292 bzero(&ioc, sizeof (sv_iocdata_t)); 1235*a0261a43SJames C. McPherson ioc.client = devpath; 12365a4c37c9Sqh201292 ioc.buf_elem = npaths; 12375a4c37c9Sqh201292 ioc.ret_elem = &npaths; 1238*a0261a43SJames C. McPherson if ((ioc.ret_buf = calloc(npaths, sizeof (sv_path_info_t))) 1239*a0261a43SJames C. McPherson == NULL) 1240*a0261a43SJames C. McPherson goto failure; 1241*a0261a43SJames C. McPherson rv = ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, &ioc); 1242*a0261a43SJames C. McPherson if (rv || npaths == 0) { 1243*a0261a43SJames C. McPherson logmsg(MSG_INFO, 1244*a0261a43SJames C. McPherson "SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO ioctl() (#2) " 1245*a0261a43SJames C. McPherson "failed, %s (%d)\n", strerror(rv), rv); 1246*a0261a43SJames C. McPherson goto failure; 12475a4c37c9Sqh201292 } 12485a4c37c9Sqh201292 12495a4c37c9Sqh201292 if (ioc.buf_elem < npaths) 12505a4c37c9Sqh201292 npaths = ioc.buf_elem; 12515a4c37c9Sqh201292 12525a4c37c9Sqh201292 pi = (sv_path_info_t *)ioc.ret_buf; 12535a4c37c9Sqh201292 while (npaths--) { 1254*a0261a43SJames C. McPherson if (pi->ret_state == MDI_PATHINFO_STATE_ONLINE) { 1255*a0261a43SJames C. McPherson char nodename[4]; 1256*a0261a43SJames C. McPherson 1257*a0261a43SJames C. McPherson bzero(nodename, 4); 1258*a0261a43SJames C. McPherson /* A hack, but nicer than a platform-specific ifdef */ 1259*a0261a43SJames C. McPherson if (strstr(devpath, "ssd") != NULL) { 1260*a0261a43SJames C. McPherson (void) snprintf(nodename, 4, "ssd"); 1261*a0261a43SJames C. McPherson } else { 1262*a0261a43SJames C. McPherson (void) snprintf(nodename, 4, "sd"); 1263*a0261a43SJames C. McPherson } 1264*a0261a43SJames C. McPherson (void) snprintf(physpath, MAXPATHLEN, "%s/%s@%s", 1265*a0261a43SJames C. McPherson pi->device.ret_phci, nodename, pi->ret_addr); 12665a4c37c9Sqh201292 free(ioc.ret_buf); 1267*a0261a43SJames C. McPherson return; 12685a4c37c9Sqh201292 } 12695a4c37c9Sqh201292 pi++; 12705a4c37c9Sqh201292 } 12715a4c37c9Sqh201292 1272*a0261a43SJames C. McPherson failure: 1273*a0261a43SJames C. McPherson (void) snprintf(physpath, MAXPATHLEN, "NOT_MAPPED"); 12745a4c37c9Sqh201292 } 12755a4c37c9Sqh201292 12765a4c37c9Sqh201292 /* 1277*a0261a43SJames C. McPherson * Write /etc/vfstab to /etc/vfstab.new, with any remapped device 1278*a0261a43SJames C. McPherson * names substituted. 12797c478bd9Sstevel@tonic-gate * 12807c478bd9Sstevel@tonic-gate * Returns: 1281*a0261a43SJames C. McPherson * 0 successful operation 12827c478bd9Sstevel@tonic-gate * -1 failed 12837c478bd9Sstevel@tonic-gate */ 12847c478bd9Sstevel@tonic-gate static int 1285*a0261a43SJames C. McPherson update_vfstab() 12867c478bd9Sstevel@tonic-gate { 1287*a0261a43SJames C. McPherson FILE *fdin, *fdout; 12887c478bd9Sstevel@tonic-gate char *buf, *tmpbuf; 1289*a0261a43SJames C. McPherson char fname[MAXPATHLEN]; 1290*a0261a43SJames C. McPherson int rv = -1, rval = -1; 12917c478bd9Sstevel@tonic-gate char cdev[MAXPATHLEN]; 12927c478bd9Sstevel@tonic-gate char bdev[MAXPATHLEN]; 12937c478bd9Sstevel@tonic-gate char mntpt[MAXPATHLEN]; 12947c478bd9Sstevel@tonic-gate char fstype[512]; 12957c478bd9Sstevel@tonic-gate char fsckpass[512]; 12967c478bd9Sstevel@tonic-gate char mntboot[512]; 1297*a0261a43SJames C. McPherson char mntopt[MAXPATHLEN]; 12987c478bd9Sstevel@tonic-gate char fmt[80]; 1299*a0261a43SJames C. McPherson char *prefixt = NULL; 1300*a0261a43SJames C. McPherson char *curdev = NULL; 1301*a0261a43SJames C. McPherson char *thisdevid = NULL; 1302*a0261a43SJames C. McPherson char *slice = NULL; 1303*a0261a43SJames C. McPherson nvlist_t *thisdev; 1304*a0261a43SJames C. McPherson boolean_t devmpx = B_FALSE; 13057c478bd9Sstevel@tonic-gate 1306*a0261a43SJames C. McPherson buf = calloc(1, MAXPATHLEN); 1307*a0261a43SJames C. McPherson tmpbuf = calloc(1, MAXPATHLEN); 1308*a0261a43SJames C. McPherson if (buf == NULL || tmpbuf == NULL) 13097c478bd9Sstevel@tonic-gate return (-1); 13107c478bd9Sstevel@tonic-gate 1311*a0261a43SJames C. McPherson (void) snprintf(fname, MAXPATHLEN, "/etc/mpxio/vfstab.new"); 1312*a0261a43SJames C. McPherson 1313*a0261a43SJames C. McPherson fdin = fopen("/etc/vfstab", "r"); 1314*a0261a43SJames C. McPherson fdout = fopen(fname, "w+"); 1315*a0261a43SJames C. McPherson if (fdin == NULL || fdout == NULL) { 1316*a0261a43SJames C. McPherson logmsg(MSG_INFO, "Unable to open vfstab or create a backup " 1317*a0261a43SJames C. McPherson "vfstab %s\n"); 1318*a0261a43SJames C. McPherson return (-1); 1319*a0261a43SJames C. McPherson } 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate (void) snprintf(fmt, sizeof (fmt), 13227c478bd9Sstevel@tonic-gate "%%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds", sizeof (bdev) - 1, 13237c478bd9Sstevel@tonic-gate sizeof (cdev) - 1, sizeof (mntpt) - 1, sizeof (fstype) - 1, 13247c478bd9Sstevel@tonic-gate sizeof (fsckpass) - 1, sizeof (mntboot) - 1, sizeof (mntopt) - 1); 13257c478bd9Sstevel@tonic-gate 1326*a0261a43SJames C. McPherson while (fgets(buf, MAXPATHLEN, fdin) != NULL) { 1327*a0261a43SJames C. McPherson if (strlen(buf) == (MAXPATHLEN - 1) && 1328*a0261a43SJames C. McPherson buf[MAXPATHLEN-2] != '\n') { 1329*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1330*a0261a43SJames C. McPherson gettext("/etc/vfstab line length too long, " 13317c478bd9Sstevel@tonic-gate "exceeded %2$d: \"%3$s\"\n"), 1332*a0261a43SJames C. McPherson MAXPATHLEN - 2, buf); 13337c478bd9Sstevel@tonic-gate goto out; 13347c478bd9Sstevel@tonic-gate } 13357c478bd9Sstevel@tonic-gate 1336*a0261a43SJames C. McPherson prefixt = NULL; 1337*a0261a43SJames C. McPherson curdev = NULL; 1338*a0261a43SJames C. McPherson slice = NULL; 1339*a0261a43SJames C. McPherson thisdevid = NULL; 1340*a0261a43SJames C. McPherson thisdev = NULL; 13417c478bd9Sstevel@tonic-gate 1342*a0261a43SJames C. McPherson /* LINTED - variable format specifier */ 1343*a0261a43SJames C. McPherson rv = sscanf(buf, fmt, bdev, cdev, mntpt, fstype, fsckpass, 1344*a0261a43SJames C. McPherson mntboot, mntopt); 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate /* 1347*a0261a43SJames C. McPherson * Walk through the lines in the input file (/etc/vfstab), 1348*a0261a43SJames C. McPherson * skipping anything which is _not_ a COGD (common or garden 1349*a0261a43SJames C. McPherson * disk), ie all the /devices, /system, /dev/md, /dev/vx and 1350*a0261a43SJames C. McPherson * /dev/zvol and so forth. 13517c478bd9Sstevel@tonic-gate */ 1352*a0261a43SJames C. McPherson if ((rv == 7) && (bdev[0] == '/') && 1353*a0261a43SJames C. McPherson (strstr(bdev, "/dev/dsk"))) { 1354*a0261a43SJames C. McPherson slice = strrchr(bdev, 's'); 1355*a0261a43SJames C. McPherson /* take a copy, strip off /dev/dsk/ */ 1356*a0261a43SJames C. McPherson prefixt = strrchr(bdev, 'c'); 1357*a0261a43SJames C. McPherson prefixt[strlen(bdev) - 9 - strlen(slice)] = '\0'; 1358*a0261a43SJames C. McPherson slice++; /* advance past the s */ 1359*a0261a43SJames C. McPherson rval = nvlist_lookup_string(mapnvl, prefixt, 1360*a0261a43SJames C. McPherson &thisdevid); 1361*a0261a43SJames C. McPherson if (rval) { 1362*a0261a43SJames C. McPherson /* Whoa, where did this device go?! */ 1363*a0261a43SJames C. McPherson logmsg(MSG_INFO, 1364*a0261a43SJames C. McPherson "error looking up device %s\n", prefixt); 1365*a0261a43SJames C. McPherson /* Comment-out this line in the new version */ 1366*a0261a43SJames C. McPherson (void) snprintf(tmpbuf, MAXPATHLEN, 1367*a0261a43SJames C. McPherson "# DEVICE NOT FOUND %s", buf); 1368*a0261a43SJames C. McPherson (void) fprintf(fdout, "%s", tmpbuf); 1369*a0261a43SJames C. McPherson continue; 1370*a0261a43SJames C. McPherson } else { 1371*a0261a43SJames C. McPherson /* The device exists in our mapnvl */ 1372*a0261a43SJames C. McPherson (void) nvlist_lookup_nvlist(mapnvl, thisdevid, 1373*a0261a43SJames C. McPherson &thisdev); 1374*a0261a43SJames C. McPherson (void) nvlist_lookup_boolean_value(thisdev, 1375*a0261a43SJames C. McPherson NVL_MPXEN, &devmpx); 1376*a0261a43SJames C. McPherson (void) nvlist_lookup_string(thisdev, 1377*a0261a43SJames C. McPherson ((devmpx == B_TRUE) 1378*a0261a43SJames C. McPherson ? NVL_MPXPATH : NVL_PATH), 1379*a0261a43SJames C. McPherson &curdev); 1380*a0261a43SJames C. McPherson } 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate 1383*a0261a43SJames C. McPherson if ((prefixt != NULL) && (curdev != NULL) && 1384*a0261a43SJames C. McPherson (rv = (strncmp(prefixt, curdev, strlen(prefixt)) != 0))) { 1385*a0261a43SJames C. McPherson /* Mapping change for this device */ 1386*a0261a43SJames C. McPherson if (strcmp(fstype, "swap") == 0) { 1387*a0261a43SJames C. McPherson (void) snprintf(tmpbuf, MAXPATHLEN, 1388*a0261a43SJames C. McPherson "/dev/dsk/%ss%s\t-\t-\tswap\t" 1389*a0261a43SJames C. McPherson "%s\t%s\t%s\n", 1390*a0261a43SJames C. McPherson curdev, slice, fsckpass, mntboot, mntopt); 1391*a0261a43SJames C. McPherson } else { 1392*a0261a43SJames C. McPherson (void) snprintf(tmpbuf, MAXPATHLEN, 1393*a0261a43SJames C. McPherson "/dev/dsk/%ss%s\t/dev/rdsk/%ss%s\t" 1394*a0261a43SJames C. McPherson "%s\t%s\t%s\t%s\t%s\n", 1395*a0261a43SJames C. McPherson curdev, slice, curdev, slice, 1396*a0261a43SJames C. McPherson mntpt, fstype, fsckpass, mntboot, mntopt); 1397*a0261a43SJames C. McPherson } 1398*a0261a43SJames C. McPherson errno = 0; 1399*a0261a43SJames C. McPherson (void) fprintf(fdout, "%s", tmpbuf); 1400*a0261a43SJames C. McPherson } else { 1401*a0261a43SJames C. McPherson (void) fprintf(fdout, "%s", buf); 1402*a0261a43SJames C. McPherson } 1403*a0261a43SJames C. McPherson 1404*a0261a43SJames C. McPherson errno = 0; 1405*a0261a43SJames C. McPherson if (fflush(fdout) != 0) { 1406*a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1407*a0261a43SJames C. McPherson gettext("fprintf failed to write to %s: %s (%d)\n"), 1408*a0261a43SJames C. McPherson fname, strerror(errno), errno); 14097c478bd9Sstevel@tonic-gate goto out; 14107c478bd9Sstevel@tonic-gate } 14117c478bd9Sstevel@tonic-gate } 14127c478bd9Sstevel@tonic-gate out: 1413*a0261a43SJames C. McPherson (void) fclose(fdin); 1414*a0261a43SJames C. McPherson (void) fclose(fdout); 14157c478bd9Sstevel@tonic-gate free(buf); 14167c478bd9Sstevel@tonic-gate free(tmpbuf); 1417*a0261a43SJames C. McPherson return (errno); 14188cecff49Sgp87344 } 1419