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 /* 237fc66be0Sjianfei wang - Sun Microsystems - Beijing China * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <stdio.h> 277c478bd9Sstevel@tonic-gate #include <stdlib.h> 287c478bd9Sstevel@tonic-gate #include <stdarg.h> 297c478bd9Sstevel@tonic-gate #include <sys/types.h> 307c478bd9Sstevel@tonic-gate #include <sys/stat.h> 317c478bd9Sstevel@tonic-gate #include <fcntl.h> 327c478bd9Sstevel@tonic-gate #include <errno.h> 337c478bd9Sstevel@tonic-gate #include <unistd.h> 347c478bd9Sstevel@tonic-gate #include <stropts.h> 357c478bd9Sstevel@tonic-gate #include <strings.h> 367c478bd9Sstevel@tonic-gate #include <sys/param.h> 377c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 387c478bd9Sstevel@tonic-gate #include <locale.h> 397c478bd9Sstevel@tonic-gate #include <libintl.h> 407c478bd9Sstevel@tonic-gate #include <devid.h> 41ed141cfcSsrivijitha dugganapalli #include <sys/libdevid.h> 42a0261a43SJames C. McPherson #include <sys/modctl.h> /* for MAXMODCONFNAME */ 43a0261a43SJames C. McPherson #include <sys/scsi/adapters/scsi_vhci.h> 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate /* 46a0261a43SJames C. McPherson * SAVE_DIR is the directory in which system files are saved. 47a0261a43SJames 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" 51a0261a43SJames C. McPherson #define VHCI_CTL_NODE "/devices/scsi_vhci:devctl" 527c478bd9Sstevel@tonic-gate 53a0261a43SJames C. McPherson /* nvlist property names, these are ALL string types */ 54a0261a43SJames C. McPherson #define NVL_DEVID "nvl-devid" 55a0261a43SJames C. McPherson #define NVL_PATH "nvl-path" 56a0261a43SJames C. McPherson #define NVL_PHYSPATH "nvl-physpath" 57a0261a43SJames C. McPherson #define NVL_MPXPATH "nvl-mpxiopath" 58a0261a43SJames C. McPherson #define NVL_MPXEN "nvl-mpxioenabled" 597c478bd9Sstevel@tonic-gate 60a0261a43SJames C. McPherson #define MPX_LIST 0x01 61a0261a43SJames C. McPherson #define MPX_MAP 0x02 62a0261a43SJames C. McPherson #define MPX_CAPABLE_CTRL 0x04 637fc66be0Sjianfei wang - Sun Microsystems - Beijing China #define MPX_DEV_PATH 0x06 64a0261a43SJames C. McPherson #define MPX_INIT 0x08 65a0261a43SJames C. McPherson #define MPX_PHYSICAL 0x10 66a0261a43SJames C. McPherson #define MPX_BOOTPATH 0x20 67a0261a43SJames C. McPherson #define MPX_UPDATEVFSTAB 0x40 687fc66be0Sjianfei wang - Sun Microsystems - Beijing China #define MPX_GETPATH 0x60 69a0261a43SJames C. McPherson #define MPX_USAGE 0x80 70a0261a43SJames C. McPherson #define MSG_INFO 0x01 71a0261a43SJames C. McPherson #define MSG_ERROR 0x02 72a0261a43SJames C. McPherson #define MSG_PANIC 0x04 7360fffc19Sjw149990 747fc66be0Sjianfei wang - Sun Microsystems - Beijing China #define BOOT_PATH 0x02 75a0261a43SJames C. McPherson #define BOOT 0x01 76a0261a43SJames C. McPherson #define NONBOOT 0x00 777c478bd9Sstevel@tonic-gate 787fc66be0Sjianfei wang - Sun Microsystems - Beijing China #define DISPLAY_ONE_PATH 0x00 797fc66be0Sjianfei wang - Sun Microsystems - Beijing China #define DISPLAY_ALL_PATH 0x01 807fc66be0Sjianfei wang - Sun Microsystems - Beijing China 817c478bd9Sstevel@tonic-gate static di_node_t devinfo_root = DI_NODE_NIL; 82a0261a43SJames C. McPherson static char *ondiskname = "/etc/mpxio/devid_path.cache"; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* 85a0261a43SJames C. McPherson * We use devid-keyed nvlists to keep track of the guid, traditional and 86a0261a43SJames C. McPherson * MPxIO-enabled /dev/rdsk paths. Each of these nvlists is eventually 87a0261a43SJames C. McPherson * added to our global nvlist and our on-disk nvlist. 887c478bd9Sstevel@tonic-gate */ 89a0261a43SJames C. McPherson static nvlist_t *mapnvl; 90a0261a43SJames C. McPherson static int mpxenabled = 0; 91a0261a43SJames C. McPherson static int limctrl = -1; 9235c62094Sjianfei wang - Sun Microsystems - Beijing China static int mpxprop = 0; 93a0261a43SJames C. McPherson static int guid = 0; 94a0261a43SJames C. McPherson static char *drvlimit; 95a0261a43SJames C. McPherson static int globarg = 0; 96a0261a43SJames C. McPherson static int debugflag = 0; 97a0261a43SJames C. McPherson static char *devicep; 98a0261a43SJames C. McPherson static int readonlyroot = 0; 99a0261a43SJames C. McPherson static int cap_N_option = 0; 100a0261a43SJames C. McPherson 101a0261a43SJames C. McPherson static void print_mpx_capable(di_node_t curnode); 102a0261a43SJames C. McPherson static int popcheck_devnvl(di_node_t thisnode, nvlist_t *devnvl, 103a0261a43SJames C. McPherson char *strdevid); 104a0261a43SJames C. McPherson static int mpxio_nvl_boilerplate(di_node_t curnode); 105a0261a43SJames C. McPherson static int validate_devnvl(); 106a0261a43SJames C. McPherson static void report_map(char *argdev, int physpath); 107a0261a43SJames C. McPherson static void list_devs(int listguids, int ctrl); 108a0261a43SJames C. McPherson static void logmsg(int level, const char *msg, ...); 109a0261a43SJames C. McPherson static char *find_link(di_node_t cnode); 110a0261a43SJames C. McPherson static void usage(); 111a0261a43SJames C. McPherson static void parse_args(int argc, char *argv[]); 112a0261a43SJames C. McPherson static void get_devid(di_node_t node, ddi_devid_t *thisdevid); 113a0261a43SJames C. McPherson static int print_bootpath(); 1147fc66be0Sjianfei wang - Sun Microsystems - Beijing China static void vhci_to_phci(char *devpath, char *slice, int d_flag); 115a0261a43SJames C. McPherson static int update_vfstab(); 1167fc66be0Sjianfei wang - Sun Microsystems - Beijing China static void report_dev_node_name(char *strdevfspath); 1177fc66be0Sjianfei wang - Sun Microsystems - Beijing China static void print_node_name(char *drv_name, char *strdevfspath); 118a0261a43SJames C. McPherson int 119a0261a43SJames C. McPherson main(int argc, char **argv) 1207c478bd9Sstevel@tonic-gate { 121a0261a43SJames C. McPherson struct stat cachestat; 122a0261a43SJames C. McPherson int mapfd = 0; 123a0261a43SJames C. McPherson int rv = 0; 124a0261a43SJames C. McPherson char *ondiskbuf; 125a0261a43SJames C. McPherson size_t newsz = 0; 1267c478bd9Sstevel@tonic-gate 127a0261a43SJames C. McPherson parse_args(argc, argv); 128a0261a43SJames C. McPherson errno = 0; 129a0261a43SJames C. McPherson devinfo_root = di_init("/", DINFOCPYALL|DINFOFORCE); 130a0261a43SJames C. McPherson logmsg(MSG_INFO, "errno = %d after " 131a0261a43SJames C. McPherson "di_init(/,DINFOCPYALL|DINFOFORCE)\n", errno); 132a0261a43SJames C. McPherson if (devinfo_root == NULL) { 133a0261a43SJames C. McPherson logmsg(MSG_ERROR, 134a0261a43SJames C. McPherson gettext("Unable to take device tree snapshot " 135a0261a43SJames C. McPherson "(%s: %d)\n"), strerror(errno), errno); 136a0261a43SJames C. McPherson return (-1); 137a0261a43SJames C. McPherson } 138a0261a43SJames C. McPherson logmsg(MSG_INFO, "opened root di_node\n"); 1397c478bd9Sstevel@tonic-gate 140a0261a43SJames C. McPherson if (globarg == MPX_CAPABLE_CTRL) { 141a0261a43SJames C. McPherson /* we just want to find MPxIO-capable controllers and exit */ 142a0261a43SJames C. McPherson if (drvlimit != NULL) { 143a0261a43SJames C. McPherson print_mpx_capable(di_drv_first_node(drvlimit, 144a0261a43SJames C. McPherson devinfo_root)); 145a0261a43SJames C. McPherson } else { 146a0261a43SJames C. McPherson print_mpx_capable(di_drv_first_node("fp", 147a0261a43SJames C. McPherson devinfo_root)); 148a0261a43SJames C. McPherson print_mpx_capable(di_drv_first_node("mpt", 149a0261a43SJames C. McPherson devinfo_root)); 1505b504601Sjiang wu - Sun Microsystems - Beijing China print_mpx_capable(di_drv_first_node("mpt_sas", 1515b504601Sjiang wu - Sun Microsystems - Beijing China devinfo_root)); 1524c06356bSdh142964 print_mpx_capable(di_drv_first_node("pmcs", 1534c06356bSdh142964 devinfo_root)); 154a0261a43SJames C. McPherson } 155a0261a43SJames C. McPherson di_fini(devinfo_root); 156a0261a43SJames C. McPherson return (0); 157a0261a43SJames C. McPherson } 158a0261a43SJames C. McPherson 159a0261a43SJames C. McPherson mapfd = open(ondiskname, O_RDWR|O_CREAT|O_SYNC, S_IRUSR | S_IWUSR); 160a0261a43SJames C. McPherson if (mapfd < 0) { 161a0261a43SJames C. McPherson /* we could be in single-user, so try for RO */ 162a0261a43SJames C. McPherson if ((mapfd = open(ondiskname, O_RDONLY)) < 0) { 163a0261a43SJames C. McPherson logmsg(MSG_ERROR, 164a0261a43SJames C. McPherson gettext("Unable to open or create %s:%s\n"), 165a0261a43SJames C. McPherson ondiskname, strerror(errno)); 166a0261a43SJames C. McPherson return (errno); 167a0261a43SJames C. McPherson } 168a0261a43SJames C. McPherson readonlyroot = 1; 169a0261a43SJames C. McPherson } 170a0261a43SJames C. McPherson 171a0261a43SJames C. McPherson if (stat(ondiskname, &cachestat) != 0) { 172a0261a43SJames C. McPherson logmsg(MSG_ERROR, 173a0261a43SJames C. McPherson gettext("Unable to stat() %s: %s\n"), 174a0261a43SJames C. McPherson ondiskname, strerror(errno)); 175a0261a43SJames C. McPherson return (errno); 176a0261a43SJames C. McPherson } 177a0261a43SJames C. McPherson ondiskbuf = calloc(1, cachestat.st_size); 178a0261a43SJames C. McPherson if (ondiskbuf == NULL) { 179a0261a43SJames C. McPherson logmsg(MSG_ERROR, 180a0261a43SJames C. McPherson gettext("Unable to allocate memory for the devid " 181a0261a43SJames C. McPherson "cache file: %s\n"), strerror(errno)); 182a0261a43SJames C. McPherson return (errno); 183a0261a43SJames C. McPherson } 184a0261a43SJames C. McPherson rv = read(mapfd, ondiskbuf, cachestat.st_size); 185a0261a43SJames C. McPherson if (rv != cachestat.st_size) { 186a0261a43SJames C. McPherson logmsg(MSG_ERROR, 187a0261a43SJames C. McPherson gettext("Unable to read all of devid cache file (got %d " 188a0261a43SJames C. McPherson "from expected %d bytes): %s\n"), 189a0261a43SJames C. McPherson rv, cachestat.st_size, strerror(errno)); 190a0261a43SJames C. McPherson return (errno); 191a0261a43SJames C. McPherson } 192a0261a43SJames C. McPherson errno = 0; 193a0261a43SJames C. McPherson rv = nvlist_unpack(ondiskbuf, cachestat.st_size, &mapnvl, 0); 194a0261a43SJames C. McPherson if (rv) { 195a0261a43SJames C. McPherson logmsg(MSG_INFO, 196a0261a43SJames C. McPherson "Unable to unpack devid cache file %s: %s (%d)\n", 197a0261a43SJames C. McPherson ondiskname, strerror(rv), rv); 198a0261a43SJames C. McPherson if (nvlist_alloc(&mapnvl, NV_UNIQUE_NAME, 0) != 0) { 199a0261a43SJames C. McPherson logmsg(MSG_ERROR, 200a0261a43SJames C. McPherson gettext("Unable to allocate root property" 201a0261a43SJames C. McPherson "list\n")); 202a0261a43SJames C. McPherson return (errno); 203a0261a43SJames C. McPherson } 204a0261a43SJames C. McPherson } 205a0261a43SJames C. McPherson free(ondiskbuf); 206a0261a43SJames C. McPherson 207a0261a43SJames C. McPherson if (validate_devnvl() < 0) { 208a0261a43SJames C. McPherson logmsg(MSG_ERROR, 209a0261a43SJames C. McPherson gettext("unable to validate kernel with on-disk devid " 210a0261a43SJames C. McPherson "cache file\n")); 211a0261a43SJames C. McPherson return (errno); 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* 215a0261a43SJames C. McPherson * If we're in single-user mode or maintenance mode, we won't 216a0261a43SJames C. McPherson * necessarily have a writable root device (ZFSroot; ufs root is 217a0261a43SJames C. McPherson * different in that we _do_ have a writable root device. 218a0261a43SJames C. McPherson * This causes problems for the devlink calls (see 219a0261a43SJames C. McPherson * $SRC/lib/libdevinfo/devinfo_devlink.c) and we do not try to 220a0261a43SJames C. McPherson * write out the devnvl if root is readonly. 2217c478bd9Sstevel@tonic-gate */ 222a0261a43SJames C. McPherson if (!readonlyroot) { 223a0261a43SJames C. McPherson rv = nvlist_size(mapnvl, &newsz, NV_ENCODE_NATIVE); 224a0261a43SJames C. McPherson if (rv) { 225a0261a43SJames C. McPherson logmsg(MSG_ERROR, 226a0261a43SJames C. McPherson gettext("Unable to determine size of packed " 227a0261a43SJames C. McPherson "on-disk devid cache file %s: %s (%d).\n"), 228a0261a43SJames C. McPherson ondiskname, strerror(rv), rv); 229a0261a43SJames C. McPherson logmsg(MSG_ERROR, gettext("Terminating\n")); 230a0261a43SJames C. McPherson nvlist_free(mapnvl); 231a0261a43SJames C. McPherson (void) close(mapfd); 232a0261a43SJames C. McPherson return (rv); 233a0261a43SJames C. McPherson } 234a0261a43SJames C. McPherson 235a0261a43SJames C. McPherson if ((ondiskbuf = calloc(1, newsz)) == NULL) { 236a0261a43SJames C. McPherson logmsg(MSG_ERROR, 237a0261a43SJames C. McPherson "Unable to allocate space for writing out new " 238a0261a43SJames C. McPherson "on-disk devid cache file: %s\n", strerror(errno)); 239a0261a43SJames C. McPherson (void) close(mapfd); 240a0261a43SJames C. McPherson nvlist_free(mapnvl); 241a0261a43SJames C. McPherson return (errno); 242a0261a43SJames C. McPherson } 243a0261a43SJames C. McPherson 244a0261a43SJames C. McPherson rv = nvlist_pack(mapnvl, &ondiskbuf, &newsz, 245a0261a43SJames C. McPherson NV_ENCODE_NATIVE, 0); 246a0261a43SJames C. McPherson if (rv) { 247a0261a43SJames C. McPherson logmsg(MSG_ERROR, 248a0261a43SJames C. McPherson gettext("Unable to pack on-disk devid cache " 249a0261a43SJames C. McPherson "file: %s (%d)\n"), strerror(rv), rv); 250a0261a43SJames C. McPherson (void) close(mapfd); 251a0261a43SJames C. McPherson free(ondiskbuf); 252a0261a43SJames C. McPherson nvlist_free(mapnvl); 253a0261a43SJames C. McPherson return (rv); 254a0261a43SJames C. McPherson } 255a0261a43SJames C. McPherson 256a0261a43SJames C. McPherson rv = lseek(mapfd, 0, 0); 257a0261a43SJames C. McPherson if (rv == -1) { 258a0261a43SJames C. McPherson logmsg(MSG_ERROR, 259a0261a43SJames C. McPherson gettext("Unable to seek to start of devid cache " 260a0261a43SJames C. McPherson "file: %s (%d)\n"), strerror(errno), errno); 261a0261a43SJames C. McPherson (void) close(mapfd); 262a0261a43SJames C. McPherson free(ondiskbuf); 263a0261a43SJames C. McPherson nvlist_free(mapnvl); 264a0261a43SJames C. McPherson return (-1); 265a0261a43SJames C. McPherson } 266a0261a43SJames C. McPherson 267a0261a43SJames C. McPherson if (write(mapfd, ondiskbuf, newsz) != newsz) { 268a0261a43SJames C. McPherson logmsg(MSG_ERROR, 269a0261a43SJames C. McPherson gettext("Unable to completely write out " 270a0261a43SJames C. McPherson "on-disk devid cache file: %s\n"), strerror(errno)); 271a0261a43SJames C. McPherson (void) close(mapfd); 272a0261a43SJames C. McPherson nvlist_free(mapnvl); 273a0261a43SJames C. McPherson free(ondiskbuf); 274a0261a43SJames C. McPherson return (errno); 275a0261a43SJames C. McPherson } 276a0261a43SJames C. McPherson } /* !readonlyroot */ 277a0261a43SJames C. McPherson 278a0261a43SJames C. McPherson /* Now we can process the command line args */ 279a0261a43SJames C. McPherson if (globarg == MPX_PHYSICAL) { 280a0261a43SJames C. McPherson report_map(devicep, BOOT); 281a0261a43SJames C. McPherson } else if (globarg == MPX_BOOTPATH) { 282a0261a43SJames C. McPherson rv = print_bootpath(); 283a0261a43SJames C. McPherson di_fini(devinfo_root); 284a0261a43SJames C. McPherson return (rv); 285a0261a43SJames C. McPherson } else if (globarg == MPX_UPDATEVFSTAB) { 286a0261a43SJames C. McPherson rv = update_vfstab(); 287a0261a43SJames C. McPherson di_fini(devinfo_root); 288a0261a43SJames C. McPherson return (rv); 2897fc66be0Sjianfei wang - Sun Microsystems - Beijing China } else if (globarg == MPX_GETPATH) { 2907fc66be0Sjianfei wang - Sun Microsystems - Beijing China report_dev_node_name(devicep); 2917fc66be0Sjianfei wang - Sun Microsystems - Beijing China } else if (globarg == MPX_DEV_PATH) { 2927fc66be0Sjianfei wang - Sun Microsystems - Beijing China report_map(devicep, BOOT_PATH); 293a0261a43SJames C. McPherson } else if (globarg != MPX_INIT) { 294a0261a43SJames C. McPherson if (globarg & MPX_LIST) 295a0261a43SJames C. McPherson list_devs(guid, limctrl); 296a0261a43SJames C. McPherson 297a0261a43SJames C. McPherson if (globarg == MPX_MAP) 298a0261a43SJames C. McPherson report_map(devicep, NONBOOT); 299a0261a43SJames C. McPherson } else { 300a0261a43SJames C. McPherson logmsg(MSG_INFO, "\nprivate devid cache file initialised\n"); 301a0261a43SJames C. McPherson } 302a0261a43SJames C. McPherson 303a0261a43SJames C. McPherson nvlist_free(mapnvl); 304a0261a43SJames C. McPherson di_fini(devinfo_root); 305a0261a43SJames C. McPherson return (0); 306a0261a43SJames C. McPherson } 307a0261a43SJames C. McPherson 308a0261a43SJames C. McPherson static void 309a0261a43SJames C. McPherson usage() 310a0261a43SJames C. McPherson { 311a0261a43SJames C. McPherson (void) fprintf(stderr, 312a0261a43SJames C. McPherson gettext("usage: stmsboot_util -b | -m devname | " 313a0261a43SJames C. McPherson "-l <ctrl> | -L | [-g] | -n | -N | -i | -p devname\n")); 314a0261a43SJames C. McPherson (void) fprintf(stderr, "\n\n"); 315a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-h\tprint this usage message\n")); 316a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-b\tretrieve the system's bootpath " 317a0261a43SJames C. McPherson "setting\n")); 318a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-m devname\n")); 319a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tReports the current mapping for " 320a0261a43SJames C. McPherson "devname\n")); 321a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-g\tprint the GUID for MPxIO-capable " 322a0261a43SJames C. McPherson "devices. This\n")); 323a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\toption is only valid with the -L " 324a0261a43SJames C. McPherson "or -l options\n")); 325a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-L | -l <ctrl>\n")); 326a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tList the 'native' to 'MPxIO' " 327a0261a43SJames C. McPherson "device mappings. If <ctrl>\n")); 328a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tis specified, only print mappings " 329a0261a43SJames C. McPherson "for those devices\n")); 330a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tattached via the specified " 331a0261a43SJames C. McPherson "controller.\n")); 332a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-i\tinitialise the private devid " 333a0261a43SJames C. McPherson "cache file and exit\n")); 334a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tThis option excludes all " 335a0261a43SJames C. McPherson "others.\n")); 336a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-n\tprint the devfs paths for " 337a0261a43SJames C. McPherson "multipath-capable\n")); 338a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tcontroller ports.\n")); 339a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-N\tprint the device aliases of " 340a0261a43SJames C. McPherson "multipath-capable\n")); 341a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tcontroller ports.\n")); 342a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-p\tdevname\n")); 343a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tThis option provides the physical " 344a0261a43SJames C. McPherson "devfs path for\n")); 345a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\ta specific device (devname). Used " 346a0261a43SJames C. McPherson "to set the bootpath\n")); 347a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\tvariable on x86/x64 systems\n")); 348a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t-u\ttranslates device mappings in " 349a0261a43SJames C. McPherson "/etc/vfstab as \n")); 350a0261a43SJames C. McPherson (void) fprintf(stderr, gettext("\t\trequired. The output is written " 351a0261a43SJames C. McPherson "to /etc/mpxio/vfstab.new\n\n")); 352a0261a43SJames C. McPherson exit(2); 353a0261a43SJames C. McPherson } 354a0261a43SJames C. McPherson 3557c478bd9Sstevel@tonic-gate static void 3567c478bd9Sstevel@tonic-gate parse_args(int argc, char *argv[]) 3577c478bd9Sstevel@tonic-gate { 3587c478bd9Sstevel@tonic-gate char opt; 3597c478bd9Sstevel@tonic-gate 360a0261a43SJames C. McPherson if (argc == 1) 361a0261a43SJames C. McPherson usage(); 3627c478bd9Sstevel@tonic-gate 363a0261a43SJames C. McPherson /* 364a0261a43SJames C. McPherson * -b prints the bootpath property 365a0261a43SJames C. McPherson * -d turns on debug mode for this utility (copious output!) 366a0261a43SJames C. McPherson * -D drvname 367a0261a43SJames C. McPherson * if supplied, indicates that we're going to operate on 368a0261a43SJames C. McPherson * devices attached to this driver. 369a0261a43SJames C. McPherson * -g if (-l or -L), prints guids for devices rather than paths 370a0261a43SJames C. McPherson * -h prints the usage() help text. 371a0261a43SJames C. McPherson * -i initialises the cache file and exits. 372a0261a43SJames C. McPherson * -l controller 373a0261a43SJames C. McPherson * list non-STMS to STMS device name mappings for the specific 374a0261a43SJames C. McPherson * controller, when MPxIO is enabled only. 375a0261a43SJames C. McPherson * -L list non-STMS to STMS device name mappings for all controllers 376a0261a43SJames C. McPherson * when MPxIO is enabled only. 377a0261a43SJames C. McPherson * -m devname 378a0261a43SJames C. McPherson * prints the device path (/dev/rdsk) that devname maps to 379a0261a43SJames C. McPherson * in the currently-running system. 380a0261a43SJames C. McPherson * -n 381a0261a43SJames C. McPherson * if supplied, returns name of STMS-capable controller nodes. 382a0261a43SJames C. McPherson * If the -D drvname option is specified as well, we only report 383a0261a43SJames C. McPherson * nodes attached with drvname. 384a0261a43SJames C. McPherson * -N 385a0261a43SJames C. McPherson * same as the -n option, except that we only print the 386a0261a43SJames C. McPherson * node-name (dev_info :: devi_node_name). Multiple instances 387a0261a43SJames C. McPherson * through the libdevinfo snapshot are uniqified and separated 388a0261a43SJames C. McPherson * by the "|" character for direct use by egrep(1). 389a0261a43SJames C. McPherson * -p devname 390a0261a43SJames C. McPherson * prints the physical devfs path for devname. Only used to 391a0261a43SJames C. McPherson * determine the bootpath. 392a0261a43SJames C. McPherson * -u 393a0261a43SJames C. McPherson * remaps devices in /etc/vfstab, saving the newly generated 394a0261a43SJames C. McPherson * file to /etc/mpxio/vfstab.new. If we have any remapped 395a0261a43SJames C. McPherson * devices, exit with status 0, otherwise -1 for error. 396a0261a43SJames C. McPherson */ 3977fc66be0Sjianfei wang - Sun Microsystems - Beijing China while ((opt = getopt(argc, argv, "bdD:ghil:Lm:nNo:p:q:u")) != EOF) { 3987c478bd9Sstevel@tonic-gate switch (opt) { 399a0261a43SJames C. McPherson case 'b': 400a0261a43SJames C. McPherson globarg = MPX_BOOTPATH; 4017c478bd9Sstevel@tonic-gate break; 4027c478bd9Sstevel@tonic-gate case 'd': 403a0261a43SJames C. McPherson debugflag = 1; 4047c478bd9Sstevel@tonic-gate break; 40560fffc19Sjw149990 case 'D': 406a0261a43SJames C. McPherson if ((drvlimit = calloc(1, MAXMODCONFNAME)) == NULL) { 407a0261a43SJames C. McPherson logmsg(MSG_ERROR, 408a0261a43SJames C. McPherson gettext("Unable to allocate memory for a " 409a0261a43SJames C. McPherson "driver name: %s\n"), strerror(errno)); 410a0261a43SJames C. McPherson exit(errno); 41160fffc19Sjw149990 } 412a0261a43SJames C. McPherson bcopy(optarg, drvlimit, strlen(optarg)); 413a0261a43SJames C. McPherson /* update this if adding support for a new driver */ 414a0261a43SJames C. McPherson if ((strncmp(drvlimit, "fp", 2) == NULL) && 4155b504601Sjiang wu - Sun Microsystems - Beijing China (strncmp(drvlimit, "mpt", 3) == NULL) && 4164c06356bSdh142964 (strncmp(drvlimit, "mpt_sas", 7) == NULL) && 4174c06356bSdh142964 (strncmp(drvlimit, "pmcs", 4) == NULL)) { 418a0261a43SJames C. McPherson logmsg(MSG_ERROR, 419a0261a43SJames C. McPherson gettext("invalid parent driver (%s) " 420a0261a43SJames C. McPherson "specified"), drvlimit); 421a0261a43SJames C. McPherson usage(); 422a0261a43SJames C. McPherson } 42360fffc19Sjw149990 break; 424a0261a43SJames C. McPherson case 'h': 425a0261a43SJames C. McPherson /* Just drop out and print the usage() output */ 426a0261a43SJames C. McPherson globarg = MPX_USAGE; 427a0261a43SJames C. McPherson break; 428a0261a43SJames C. McPherson case 'i': 429a0261a43SJames C. McPherson globarg = MPX_INIT; 430a0261a43SJames C. McPherson break; 431a0261a43SJames C. McPherson case 'l': 432a0261a43SJames C. McPherson globarg |= MPX_LIST; 433a0261a43SJames C. McPherson limctrl = (int)atol(optarg); 434a0261a43SJames C. McPherson if (limctrl < 0) { 435a0261a43SJames C. McPherson logmsg(MSG_INFO, 436a0261a43SJames C. McPherson gettext("invalid controller number " 437a0261a43SJames C. McPherson "(%d), checking all controllers\n"), 438a0261a43SJames C. McPherson limctrl); 439a0261a43SJames C. McPherson } 440a0261a43SJames C. McPherson break; 441a0261a43SJames C. McPherson case 'L': 442a0261a43SJames C. McPherson globarg |= MPX_LIST; 443a0261a43SJames C. McPherson break; 444a0261a43SJames C. McPherson case 'g': 445a0261a43SJames C. McPherson guid = 1; 446a0261a43SJames C. McPherson break; 447a0261a43SJames C. McPherson case 'm': 448a0261a43SJames C. McPherson globarg = MPX_MAP; 449a0261a43SJames C. McPherson if ((devicep = calloc(1, MAXPATHLEN)) == NULL) { 450a0261a43SJames C. McPherson logmsg(MSG_ERROR, 451a0261a43SJames C. McPherson gettext("Unable to allocate space for a " 452a0261a43SJames C. McPherson "device name\n")); 453a0261a43SJames C. McPherson exit(errno); 454a0261a43SJames C. McPherson } 455a0261a43SJames C. McPherson devicep = strdup(optarg); 456a0261a43SJames C. McPherson break; 457a0261a43SJames C. McPherson case 'N': 458a0261a43SJames C. McPherson cap_N_option = 1; 459a0261a43SJames C. McPherson globarg = MPX_CAPABLE_CTRL; 460a0261a43SJames C. McPherson break; 46160fffc19Sjw149990 case 'n': 462a0261a43SJames C. McPherson globarg = MPX_CAPABLE_CTRL; 46360fffc19Sjw149990 break; 4647fc66be0Sjianfei wang - Sun Microsystems - Beijing China case 'o': 4657fc66be0Sjianfei wang - Sun Microsystems - Beijing China globarg = MPX_GETPATH; 4667fc66be0Sjianfei wang - Sun Microsystems - Beijing China if ((devicep = calloc(1, MAXPATHLEN)) == NULL) { 4677fc66be0Sjianfei wang - Sun Microsystems - Beijing China logmsg(MSG_ERROR, 4687fc66be0Sjianfei wang - Sun Microsystems - Beijing China gettext("Unable to allocate space for a " 4697fc66be0Sjianfei wang - Sun Microsystems - Beijing China "device name\n")); 4707fc66be0Sjianfei wang - Sun Microsystems - Beijing China exit(errno); 4717fc66be0Sjianfei wang - Sun Microsystems - Beijing China } 4727fc66be0Sjianfei wang - Sun Microsystems - Beijing China devicep = strdup(optarg); 4737fc66be0Sjianfei wang - Sun Microsystems - Beijing China break; 474a0261a43SJames C. McPherson case 'p': 475a0261a43SJames C. McPherson globarg = MPX_PHYSICAL; 476a0261a43SJames C. McPherson if ((devicep = calloc(1, MAXPATHLEN)) == NULL) { 477a0261a43SJames C. McPherson logmsg(MSG_ERROR, 478a0261a43SJames C. McPherson gettext("Unable to allocate space for a " 479a0261a43SJames C. McPherson "device name\n")); 480a0261a43SJames C. McPherson exit(errno); 481a0261a43SJames C. McPherson } 482a0261a43SJames C. McPherson devicep = strdup(optarg); 483a0261a43SJames C. McPherson break; 4847fc66be0Sjianfei wang - Sun Microsystems - Beijing China case 'q': 4857fc66be0Sjianfei wang - Sun Microsystems - Beijing China globarg = MPX_DEV_PATH; 4867fc66be0Sjianfei wang - Sun Microsystems - Beijing China if ((devicep = calloc(1, MAXPATHLEN)) == NULL) { 4877fc66be0Sjianfei wang - Sun Microsystems - Beijing China logmsg(MSG_ERROR, 4887fc66be0Sjianfei wang - Sun Microsystems - Beijing China gettext("Unable to allocate space for a " 4897fc66be0Sjianfei wang - Sun Microsystems - Beijing China "device name\n")); 4907fc66be0Sjianfei wang - Sun Microsystems - Beijing China exit(errno); 4917fc66be0Sjianfei wang - Sun Microsystems - Beijing China } 4927fc66be0Sjianfei wang - Sun Microsystems - Beijing China devicep = strdup(optarg); 4937fc66be0Sjianfei wang - Sun Microsystems - Beijing China break; 494a0261a43SJames C. McPherson case 'u': 495a0261a43SJames C. McPherson globarg = MPX_UPDATEVFSTAB; 496a0261a43SJames C. McPherson break; 4977c478bd9Sstevel@tonic-gate default: 498a0261a43SJames C. McPherson logmsg(MSG_ERROR, 499a0261a43SJames C. McPherson gettext("Invalid command line option (%c)\n"), 500a0261a43SJames C. McPherson opt); 501a0261a43SJames C. McPherson usage(); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 505a0261a43SJames C. McPherson if ((globarg >= MPX_USAGE) || (guid && (globarg != MPX_LIST))) 506a0261a43SJames C. McPherson usage(); 507a0261a43SJames C. McPherson 508a0261a43SJames C. McPherson if ((drvlimit != NULL) && 509a0261a43SJames C. McPherson ((globarg != MPX_LIST) && 510a0261a43SJames C. McPherson (globarg != MPX_CAPABLE_CTRL))) 511a0261a43SJames C. McPherson usage(); 51260fffc19Sjw149990 } 5137c478bd9Sstevel@tonic-gate 514a0261a43SJames C. McPherson static void 515a0261a43SJames C. McPherson logmsg(int level, const char *msg, ...) 5167c478bd9Sstevel@tonic-gate { 517a0261a43SJames C. McPherson va_list ap; 5187c478bd9Sstevel@tonic-gate 519a0261a43SJames C. McPherson if ((level >= MSG_ERROR) || 520a0261a43SJames C. McPherson ((debugflag > 0) && (level >= MSG_INFO))) { 521a0261a43SJames C. McPherson (void) fprintf(stdout, "stmsboot: "); 522a0261a43SJames C. McPherson va_start(ap, msg); 523a0261a43SJames C. McPherson (void) vfprintf(stdout, msg, ap); 524a0261a43SJames C. McPherson va_end(ap); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate /* 529a0261a43SJames C. McPherson * It's up to the caller to do any sorting or pretty-printing of the device 530a0261a43SJames C. McPherson * mappings we report. Since we're storing the device links as just the cXtYdZ 531a0261a43SJames C. McPherson * part, we'll add /dev/rdsk/ back on when we print the listing so we maintain 532a0261a43SJames C. McPherson * compatibility with previous versions of this tool. There's a little bit 533a0261a43SJames C. McPherson * of footwork involved to make sure that we show all the paths to a device 534a0261a43SJames C. McPherson * rather than just the first one we stashed away. 5357c478bd9Sstevel@tonic-gate */ 5367c478bd9Sstevel@tonic-gate static void 537a0261a43SJames C. McPherson list_devs(int listguids, int ctrl) 5387c478bd9Sstevel@tonic-gate { 539a0261a43SJames C. McPherson nvlist_t *thisdevnvl; 540a0261a43SJames C. McPherson nvpair_t *pair; 541a0261a43SJames C. McPherson char *diskpath, *livepath, *key, *querydev; 542a0261a43SJames C. McPherson char *matchctrl = NULL; 543a0261a43SJames C. McPherson char checkctrl[MAXPATHLEN]; 544a0261a43SJames C. McPherson int rv; 5457c478bd9Sstevel@tonic-gate 546a0261a43SJames C. McPherson if (!mpxenabled) { 54735c62094Sjianfei wang - Sun Microsystems - Beijing China if (mpxprop) { 54835c62094Sjianfei wang - Sun Microsystems - Beijing China logmsg(MSG_ERROR, gettext("MPXIO disabled\n")); 54935c62094Sjianfei wang - Sun Microsystems - Beijing China } else { 55035c62094Sjianfei wang - Sun Microsystems - Beijing China logmsg(MSG_ERROR, gettext("No STMS devices have " 55135c62094Sjianfei wang - Sun Microsystems - Beijing China "been found\n")); 55235c62094Sjianfei wang - Sun Microsystems - Beijing China } 553a0261a43SJames C. McPherson return; 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate 556a0261a43SJames C. McPherson if (listguids) { 557a0261a43SJames C. McPherson (void) printf(gettext("non-STMS device name\t\t\tGUID\n" 558a0261a43SJames C. McPherson "------------------------------------------" 559a0261a43SJames C. McPherson "------------------------\n")); 5607c478bd9Sstevel@tonic-gate } else { 561a0261a43SJames C. McPherson (void) printf(gettext("non-STMS device name\t\t\t" 562a0261a43SJames C. McPherson "STMS device name\n" 563a0261a43SJames C. McPherson "------------------------------------------" 564a0261a43SJames C. McPherson "------------------------\n")); 565a0261a43SJames C. McPherson } 566a0261a43SJames C. McPherson 567a0261a43SJames C. McPherson bzero(checkctrl, MAXPATHLEN); 568a0261a43SJames C. McPherson pair = NULL; 569a0261a43SJames C. McPherson while ((pair = nvlist_next_nvpair(mapnvl, pair)) 570a0261a43SJames C. McPherson != NULL) { 571a0261a43SJames C. McPherson boolean_t livescsivhcip = B_FALSE; 572a0261a43SJames C. McPherson 573a0261a43SJames C. McPherson if ((((rv = nvpair_value_string(pair, &querydev)) < 0) || 574a0261a43SJames C. McPherson ((key = nvpair_name(pair)) == NULL)) || 575a0261a43SJames C. McPherson ((strstr(key, "/pci") != NULL) || 576a0261a43SJames C. McPherson (strstr(key, "/sbus") != NULL) || 577a0261a43SJames C. McPherson (strstr(key, "/scsi_vhci") != NULL) || 578a0261a43SJames C. McPherson (strncmp(key, "id1", 3) == 0))) { 579a0261a43SJames C. McPherson logmsg(MSG_INFO, 580a0261a43SJames C. McPherson "list_devs: rv = %d; (%s) is not a devlink, " 581a0261a43SJames C. McPherson "continuing.\n", rv, 582a0261a43SJames C. McPherson (key != NULL) ? key : "null"); 583a0261a43SJames C. McPherson querydev = NULL; 584a0261a43SJames C. McPherson continue; 585a0261a43SJames C. McPherson } 586a0261a43SJames C. McPherson 587a0261a43SJames C. McPherson (void) nvlist_lookup_nvlist(mapnvl, querydev, &thisdevnvl); 588a0261a43SJames C. McPherson (void) nvlist_lookup_boolean_value(thisdevnvl, NVL_MPXEN, 589a0261a43SJames C. McPherson &livescsivhcip); 590a0261a43SJames C. McPherson (void) nvlist_lookup_string(thisdevnvl, NVL_MPXPATH, 591a0261a43SJames C. McPherson &livepath); 592a0261a43SJames C. McPherson 593a0261a43SJames C. McPherson if ((!livescsivhcip) || 594a0261a43SJames C. McPherson (livescsivhcip && 595a0261a43SJames C. McPherson (strncmp(key, livepath, strlen(key)) == 0))) 596a0261a43SJames C. McPherson continue; 597a0261a43SJames C. McPherson 598a0261a43SJames C. McPherson (void) nvlist_lookup_string(thisdevnvl, NVL_PATH, 599a0261a43SJames C. McPherson &diskpath); 600a0261a43SJames C. McPherson 601a0261a43SJames C. McPherson logmsg(MSG_INFO, 602a0261a43SJames C. McPherson "list_devs: %s :: %s ::%s :: MPXEN (%s)\n", 603a0261a43SJames C. McPherson key, diskpath, livepath, 604a0261a43SJames C. McPherson ((livescsivhcip) ? "TRUE" : "FALSE")); 605a0261a43SJames C. McPherson 606a0261a43SJames C. McPherson if (ctrl > -1) { 607a0261a43SJames C. McPherson (void) sprintf(checkctrl, "c%dt", ctrl); 608a0261a43SJames C. McPherson matchctrl = strstr(key, checkctrl); 609a0261a43SJames C. McPherson if (matchctrl == NULL) 610a0261a43SJames C. McPherson continue; 611a0261a43SJames C. McPherson } 612a0261a43SJames C. McPherson if (listguids != 0) { 613a0261a43SJames C. McPherson char *tempguid; 614a0261a43SJames C. McPherson ddi_devid_t curdevid; 615a0261a43SJames C. McPherson int rv; 616a0261a43SJames C. McPherson 617a0261a43SJames C. McPherson rv = devid_str_decode(querydev, &curdevid, NULL); 618a0261a43SJames C. McPherson if (rv == -1) { 619a0261a43SJames C. McPherson logmsg(MSG_INFO, "Unable to decode devid %s\n", 620a0261a43SJames C. McPherson key); 621a0261a43SJames C. McPherson continue; 622a0261a43SJames C. McPherson } 623a0261a43SJames C. McPherson tempguid = devid_to_guid(curdevid); 624a0261a43SJames C. McPherson if (tempguid != NULL) 625a0261a43SJames C. McPherson (void) printf("/dev/rdsk/%s\t%s\n", 626a0261a43SJames C. McPherson diskpath, tempguid); 627a0261a43SJames C. McPherson 628a0261a43SJames C. McPherson devid_free_guid(tempguid); 629a0261a43SJames C. McPherson devid_free(curdevid); 630a0261a43SJames C. McPherson continue; 631a0261a43SJames C. McPherson } 632a0261a43SJames C. McPherson 633a0261a43SJames C. McPherson (void) printf("/dev/rdsk/%s\t/dev/rdsk/%s\n", 634a0261a43SJames C. McPherson (strstr(key, diskpath) == NULL) ? key : diskpath, 635a0261a43SJames C. McPherson livepath); 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate } 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate /* 640a0261a43SJames C. McPherson * We get passed a device name which we search the mapnvl for. If we find 641a0261a43SJames C. McPherson * it, we print the mapping as it is found. It is up to the caller of this 642a0261a43SJames C. McPherson * utility to do any pretty-printing of the results. If a device listed on 643a0261a43SJames C. McPherson * the command line does not exist in the mapnvl, then we print NOT_MAPPED. 644a0261a43SJames C. McPherson * Otherwise we print the command-line device name as it maps to what is 645a0261a43SJames C. McPherson * stashed in the mapnvl - even if that's a "no change" device mapping. 6467c478bd9Sstevel@tonic-gate * 647a0261a43SJames C. McPherson * Example output (-p maps to physpath=BOOT) 648a0261a43SJames C. McPherson * # /lib/mpxio/stmsboot_util -p \ 649a0261a43SJames C. McPherson * /pci@0,0/pci1022,7450@2/pci1000,3060@3/sd@1,0:a 650a0261a43SJames C. McPherson * /scsi_vhci/disk@g500000e011e17720:a 6517c478bd9Sstevel@tonic-gate * 652a0261a43SJames C. McPherson * Or the reverse: 653a0261a43SJames C. McPherson * # /lib/mpxio/stmsboot_util -p /scsi_vhci/disk@g500000e011e17720:a 654a0261a43SJames C. McPherson * /pci@0,0/pci1022,7450@2/pci1000,3060@3/sd@1,0:a 655a0261a43SJames C. McPherson * 656a0261a43SJames C. McPherson * For the -m option, used when we're trying to find the root device mapping: 657a0261a43SJames C. McPherson * 658a0261a43SJames C. McPherson * # /lib/mpxio/stmsboot_util -m /dev/dsk/c2t0d0s2 659a0261a43SJames C. McPherson * /dev/dsk/c3t500000E011637CF0d0s2 660a0261a43SJames C. McPherson */ 661a0261a43SJames C. McPherson static void 662a0261a43SJames C. McPherson report_map(char *argdev, int physpath) 663a0261a43SJames C. McPherson { 664a0261a43SJames C. McPherson nvlist_t *thisdev; 665a0261a43SJames C. McPherson int rv = 0; 666a0261a43SJames C. McPherson char *thisdevid; 667a0261a43SJames C. McPherson char *mpxpath = NULL; 668a0261a43SJames C. McPherson char *prefixt = NULL; 669a0261a43SJames C. McPherson char *prefixp = NULL; 670a0261a43SJames C. McPherson char *stripdev = NULL; 671a0261a43SJames C. McPherson char *slice = NULL; 672a0261a43SJames C. McPherson boolean_t mpxenp; 673a0261a43SJames C. McPherson uint_t slicelen = 0; 674a0261a43SJames C. McPherson 675a0261a43SJames C. McPherson mpxenp = B_FALSE; 676a0261a43SJames C. McPherson 677a0261a43SJames C. McPherson if ((prefixt = calloc(1, strlen(argdev) + 1)) == NULL) { 678a0261a43SJames C. McPherson logmsg(MSG_INFO, "Unable to allocate memory\n"); 679a0261a43SJames C. McPherson (void) printf("NOT_MAPPED\n"); 680a0261a43SJames C. McPherson return; 681a0261a43SJames C. McPherson } 682a0261a43SJames C. McPherson 683a0261a43SJames C. McPherson (void) strlcpy(prefixt, argdev, strlen(argdev) + 1); 684a0261a43SJames C. McPherson 6857fc66be0Sjianfei wang - Sun Microsystems - Beijing China slice = strrchr(argdev, (physpath == NONBOOT) ? 's' : ':'); 686a0261a43SJames C. McPherson if (slice != NULL) { 687a0261a43SJames C. McPherson slicelen = strlen(slice); 688a0261a43SJames C. McPherson if (slicelen > 3) 689a0261a43SJames C. McPherson /* invalid size - max is 3 chars */ 690a0261a43SJames C. McPherson slicelen = 0; 691a0261a43SJames C. McPherson } 692a0261a43SJames C. McPherson 693a0261a43SJames C. McPherson if ((stripdev = calloc(1, strlen(prefixt) + 1)) == NULL) { 694a0261a43SJames C. McPherson logmsg(MSG_INFO, "Unable to allocate memory\n"); 695a0261a43SJames C. McPherson (void) printf("NOT_MAPPED\n"); 696a0261a43SJames C. McPherson free(prefixt); 697a0261a43SJames C. McPherson return; 698a0261a43SJames C. McPherson } 699a0261a43SJames C. McPherson 700a0261a43SJames C. McPherson if ((strstr(prefixt, "/scsi_vhci") == NULL) && 701a0261a43SJames C. McPherson (strstr(prefixt, "/pci") == NULL) && 702a0261a43SJames C. McPherson (strstr(prefixt, "/sbus") == NULL)) { 703a0261a43SJames C. McPherson prefixp = strrchr(prefixt, '/'); 704a0261a43SJames C. McPherson (void) strlcpy(stripdev, 705a0261a43SJames C. McPherson (prefixp == NULL) ? prefixt : prefixp + 1, 706a0261a43SJames C. McPherson (prefixp == NULL) ? 707a0261a43SJames C. McPherson strlen(prefixt) + 1: strlen(prefixp) + 1); 708a0261a43SJames C. McPherson if (prefixp != NULL) 709a0261a43SJames C. McPherson prefixt[strlen(argdev) - strlen(prefixp) + 1] = '\0'; 710a0261a43SJames C. McPherson } else { 7117fc66be0Sjianfei wang - Sun Microsystems - Beijing China if ((physpath != BOOT) && 7127fc66be0Sjianfei wang - Sun Microsystems - Beijing China (physpath != BOOT_PATH)) { 713a0261a43SJames C. McPherson logmsg(MSG_INFO, "Invalid device path provided\n"); 714a0261a43SJames C. McPherson (void) printf("NOT_MAPPED\n"); 715a0261a43SJames C. McPherson free(stripdev); 716a0261a43SJames C. McPherson free(prefixt); 717a0261a43SJames C. McPherson return; 718a0261a43SJames C. McPherson } 719a0261a43SJames C. McPherson (void) strlcpy(stripdev, argdev, strlen(argdev) + 1); 720a0261a43SJames C. McPherson } 721a0261a43SJames C. McPherson 722a0261a43SJames C. McPherson logmsg(MSG_INFO, 723a0261a43SJames C. McPherson "stripdev (%s), prefixt(%s), prefixp(%s), slice(%s)\n", 724a0261a43SJames C. McPherson (stripdev == NULL) ? "null" : stripdev, 725a0261a43SJames C. McPherson (prefixt == NULL) ? "null" : prefixt, 726a0261a43SJames C. McPherson (prefixp == NULL) ? "null" : prefixp, 727a0261a43SJames C. McPherson (slice == NULL) ? "null" : slice); 728a0261a43SJames C. McPherson 729a0261a43SJames C. McPherson if (slicelen > 0) 730a0261a43SJames C. McPherson stripdev[strlen(stripdev) - slicelen] = '\0'; 731a0261a43SJames C. McPherson 732a0261a43SJames C. McPherson /* search for the shortened version */ 733a0261a43SJames C. McPherson rv = nvlist_lookup_string(mapnvl, stripdev, &thisdevid); 734a0261a43SJames C. McPherson if (rv) { 7357fc66be0Sjianfei wang - Sun Microsystems - Beijing China if ((physpath != BOOT) && 7367fc66be0Sjianfei wang - Sun Microsystems - Beijing China (physpath != BOOT_PATH)) { 737a0261a43SJames C. McPherson logmsg(MSG_INFO, 738a0261a43SJames C. McPherson "searched mapnvl for '%s', got %s (%d)\n", 739a0261a43SJames C. McPherson stripdev, strerror(rv), rv); 740a0261a43SJames C. McPherson (void) printf("NOT_MAPPED\n"); 741a0261a43SJames C. McPherson free(stripdev); 742a0261a43SJames C. McPherson free(prefixt); 743a0261a43SJames C. McPherson return; 744a0261a43SJames C. McPherson } 745a0261a43SJames C. McPherson } 746a0261a43SJames C. McPherson 747a0261a43SJames C. McPherson logmsg(MSG_INFO, "device %s has devid %s\n", stripdev, thisdevid); 748a0261a43SJames C. McPherson 749a0261a43SJames C. McPherson if (nvlist_lookup_nvlist(mapnvl, thisdevid, &thisdev) != 0) { 750a0261a43SJames C. McPherson logmsg(MSG_INFO, "device (%s) in mapnvl but " 751a0261a43SJames C. McPherson "not mapped!\n", thisdevid); 752a0261a43SJames C. McPherson (void) printf("NOT_MAPPED\n"); 753a0261a43SJames C. McPherson free(stripdev); 754a0261a43SJames C. McPherson free(prefixt); 755a0261a43SJames C. McPherson return; 756a0261a43SJames C. McPherson } 757a0261a43SJames C. McPherson 758a0261a43SJames C. McPherson /* quick exit */ 759a0261a43SJames C. McPherson if (!mpxenabled && (strstr(argdev, "/pci") != NULL || 760a0261a43SJames C. McPherson strstr(argdev, "/sbus") != NULL)) { 761a0261a43SJames C. McPherson (void) printf("%s\n", argdev); 762a0261a43SJames C. McPherson free(stripdev); 763a0261a43SJames C. McPherson free(prefixt); 764a0261a43SJames C. McPherson return; 765a0261a43SJames C. McPherson } 766a0261a43SJames C. McPherson 767a0261a43SJames C. McPherson (void) nvlist_lookup_boolean_value(thisdev, NVL_MPXEN, &mpxenp); 768a0261a43SJames C. McPherson 769a0261a43SJames C. McPherson if (physpath == BOOT) { 770a0261a43SJames C. McPherson (void) nvlist_lookup_string(thisdev, NVL_PHYSPATH, &mpxpath); 771a0261a43SJames C. McPherson if ((strstr(argdev, "/scsi_vhci") != NULL) && 772a0261a43SJames C. McPherson (strncmp(argdev, mpxpath, strlen(mpxpath)) == 0)) { 773a0261a43SJames C. McPherson /* Need to translate vhci to phci */ 7747fc66be0Sjianfei wang - Sun Microsystems - Beijing China vhci_to_phci(stripdev, slice, DISPLAY_ONE_PATH); 7757fc66be0Sjianfei wang - Sun Microsystems - Beijing China } else { 7767fc66be0Sjianfei wang - Sun Microsystems - Beijing China (void) printf("%s%s\n", mpxpath, 777a0261a43SJames C. McPherson ((slicelen > 0) && slice != NULL) ? slice : ""); 7787fc66be0Sjianfei wang - Sun Microsystems - Beijing China } 7797fc66be0Sjianfei wang - Sun Microsystems - Beijing China } else if (physpath == BOOT_PATH) { 7807fc66be0Sjianfei wang - Sun Microsystems - Beijing China (void) nvlist_lookup_string(thisdev, NVL_PHYSPATH, &mpxpath); 7817fc66be0Sjianfei wang - Sun Microsystems - Beijing China if ((strstr(argdev, "/scsi_vhci") != NULL) && 7827fc66be0Sjianfei wang - Sun Microsystems - Beijing China (strncmp(argdev, mpxpath, strlen(mpxpath)) == 0)) { 7837fc66be0Sjianfei wang - Sun Microsystems - Beijing China /* Need to translate vhci to phci */ 7847fc66be0Sjianfei wang - Sun Microsystems - Beijing China vhci_to_phci(stripdev, slice, DISPLAY_ALL_PATH); 785a0261a43SJames C. McPherson } else { 786a0261a43SJames C. McPherson (void) printf("%s%s\n", mpxpath, 787a0261a43SJames C. McPherson ((slicelen > 0) && slice != NULL) ? slice : ""); 788a0261a43SJames C. McPherson } 789a0261a43SJames C. McPherson } else { 790a0261a43SJames C. McPherson (void) nvlist_lookup_string(thisdev, 791a0261a43SJames C. McPherson ((readonlyroot) ? NVL_PHYSPATH : 792a0261a43SJames C. McPherson ((mpxenp == B_TRUE) ? NVL_MPXPATH : NVL_PATH)), 793a0261a43SJames C. McPherson &mpxpath); 794a0261a43SJames C. McPherson logmsg(MSG_INFO, "mpxpath = %s\n", 795a0261a43SJames C. McPherson (mpxpath == NULL) ? "null" : mpxpath); 796a0261a43SJames C. McPherson if (readonlyroot || 797a0261a43SJames C. McPherson (strstr(mpxpath, "/scsi_vhci") != NULL) || 798a0261a43SJames C. McPherson (strstr(mpxpath, "/pci") != NULL) || 799a0261a43SJames C. McPherson (strstr(mpxpath, "/sbus") != NULL)) { 800a0261a43SJames C. McPherson /* 801a0261a43SJames C. McPherson * If we see a physical path here it means that 802a0261a43SJames C. McPherson * devlinks aren't fully initialised yet, so we 803a0261a43SJames C. McPherson * are still in maintenance/single-user mode. 804a0261a43SJames C. McPherson */ 805a0261a43SJames C. McPherson (void) printf("/devices%s:%c\n", mpxpath, 806a0261a43SJames C. McPherson slice[1] + '1'); 807a0261a43SJames C. McPherson } else { 808a0261a43SJames C. McPherson (void) printf("%s%s%s\n", 809a0261a43SJames C. McPherson (prefixt[0] == '/') ? prefixt : "", 810a0261a43SJames C. McPherson mpxpath, 811a0261a43SJames C. McPherson ((slicelen > 0) && slice != NULL) ? slice : ""); 812a0261a43SJames C. McPherson } 813a0261a43SJames C. McPherson } 814a0261a43SJames C. McPherson free(prefixt); 815a0261a43SJames C. McPherson free(stripdev); 816a0261a43SJames C. McPherson } 817a0261a43SJames C. McPherson 818a0261a43SJames C. McPherson /* 819a0261a43SJames C. McPherson * Validate the in-kernel and on-disk forms of our devid cache, 820a0261a43SJames C. McPherson * returns -1 for unfixable error and 0 for success. 8217c478bd9Sstevel@tonic-gate */ 8227c478bd9Sstevel@tonic-gate static int 823a0261a43SJames C. McPherson validate_devnvl() 824a0261a43SJames C. McPherson { 825a0261a43SJames C. McPherson di_node_t curnode; 826a0261a43SJames C. McPherson int rv1 = -1; 827a0261a43SJames C. McPherson int rv2 = -1; 828a0261a43SJames C. McPherson 829a0261a43SJames C. McPherson /* 830a0261a43SJames C. McPherson * Method: we walk through the kernel's concept of the device tree 831a0261a43SJames C. McPherson * looking for "ssd" then "sd" nodes. 832a0261a43SJames C. McPherson * We check to see whether the device's devid is already in our nvlist 833a0261a43SJames C. McPherson * (on disk) nvlist cache file. If it is, we check that it's components 834a0261a43SJames C. McPherson * match what we've got already and fill any missing fields. 835a0261a43SJames C. McPherson * If the devid isn't in our on-disk nvlist already then we add it 836a0261a43SJames C. McPherson * and populate the property nvpairs. 837a0261a43SJames C. McPherson * 838a0261a43SJames C. McPherson * At the end of this function we should have this program's concept 839a0261a43SJames C. McPherson * of the devid-keyed nvlist matching what is in the ondisk form which 840a0261a43SJames C. McPherson * is ready to be written out. 841a0261a43SJames C. McPherson * If we can't do this, then we return -1. 842a0261a43SJames C. McPherson */ 843a0261a43SJames C. McPherson curnode = di_drv_first_node("ssd", devinfo_root); 844a0261a43SJames C. McPherson if (curnode != DI_NODE_NIL) 845a0261a43SJames C. McPherson rv1 = mpxio_nvl_boilerplate(curnode); 846a0261a43SJames C. McPherson 847a0261a43SJames C. McPherson curnode = di_drv_first_node("sd", devinfo_root); 848a0261a43SJames C. McPherson if (curnode != DI_NODE_NIL) 849a0261a43SJames C. McPherson rv2 = mpxio_nvl_boilerplate(curnode); 850a0261a43SJames C. McPherson 851a0261a43SJames C. McPherson if (rv1 + rv2 == -2) 852a0261a43SJames C. McPherson return (-1); 853a0261a43SJames C. McPherson 854a0261a43SJames C. McPherson return (0); 855a0261a43SJames C. McPherson } 856a0261a43SJames C. McPherson 8577fc66be0Sjianfei wang - Sun Microsystems - Beijing China /* 8587fc66be0Sjianfei wang - Sun Microsystems - Beijing China * According to devfs path name, it will print device node name. 8597fc66be0Sjianfei wang - Sun Microsystems - Beijing China */ 8607fc66be0Sjianfei wang - Sun Microsystems - Beijing China static void 8617fc66be0Sjianfei wang - Sun Microsystems - Beijing China print_node_name(char *drv_name, char *strdevfspath) 8627fc66be0Sjianfei wang - Sun Microsystems - Beijing China { 8637fc66be0Sjianfei wang - Sun Microsystems - Beijing China di_node_t curnode; 8647fc66be0Sjianfei wang - Sun Microsystems - Beijing China char *devfspath = NULL; 8657fc66be0Sjianfei wang - Sun Microsystems - Beijing China char *node_name = NULL; 8667fc66be0Sjianfei wang - Sun Microsystems - Beijing China 8677fc66be0Sjianfei wang - Sun Microsystems - Beijing China curnode = di_drv_first_node(drv_name, devinfo_root); 8687fc66be0Sjianfei wang - Sun Microsystems - Beijing China for (; curnode != DI_NODE_NIL; curnode = di_drv_next_node(curnode)) { 8697fc66be0Sjianfei wang - Sun Microsystems - Beijing China devfspath = di_devfs_path(curnode); 8707fc66be0Sjianfei wang - Sun Microsystems - Beijing China logmsg(MSG_INFO, "find: devfspath %s\n", devfspath); 8717fc66be0Sjianfei wang - Sun Microsystems - Beijing China 8727fc66be0Sjianfei wang - Sun Microsystems - Beijing China if (devfspath == NULL) 8737fc66be0Sjianfei wang - Sun Microsystems - Beijing China continue; 8747fc66be0Sjianfei wang - Sun Microsystems - Beijing China 875*9955cef3Sjianfei wang - Sun Microsystems - Beijing China if ((strlen(strdevfspath) == strlen(devfspath)) && 876*9955cef3Sjianfei wang - Sun Microsystems - Beijing China (strncmp(strdevfspath, devfspath, 877*9955cef3Sjianfei wang - Sun Microsystems - Beijing China strlen(devfspath)) == 0)) { 8787fc66be0Sjianfei wang - Sun Microsystems - Beijing China node_name = find_link(curnode); 8797fc66be0Sjianfei wang - Sun Microsystems - Beijing China if (node_name == NULL) { 8807fc66be0Sjianfei wang - Sun Microsystems - Beijing China (void) printf("NOT MAPPED\n"); 8817fc66be0Sjianfei wang - Sun Microsystems - Beijing China } else { 8827fc66be0Sjianfei wang - Sun Microsystems - Beijing China (void) printf("%s\n", node_name); 8837fc66be0Sjianfei wang - Sun Microsystems - Beijing China } 8847fc66be0Sjianfei wang - Sun Microsystems - Beijing China return; 8857fc66be0Sjianfei wang - Sun Microsystems - Beijing China } 8867fc66be0Sjianfei wang - Sun Microsystems - Beijing China } 8877fc66be0Sjianfei wang - Sun Microsystems - Beijing China } 8887fc66be0Sjianfei wang - Sun Microsystems - Beijing China 8897fc66be0Sjianfei wang - Sun Microsystems - Beijing China /* 8907fc66be0Sjianfei wang - Sun Microsystems - Beijing China * report device node name, search "ssd" and "sd" nodes, 8917fc66be0Sjianfei wang - Sun Microsystems - Beijing China * print the device node name which device path is same as 8927fc66be0Sjianfei wang - Sun Microsystems - Beijing China * parameter. 8937fc66be0Sjianfei wang - Sun Microsystems - Beijing China */ 8947fc66be0Sjianfei wang - Sun Microsystems - Beijing China static void 8957fc66be0Sjianfei wang - Sun Microsystems - Beijing China report_dev_node_name(char *strdevfspath) 8967fc66be0Sjianfei wang - Sun Microsystems - Beijing China { 8977fc66be0Sjianfei wang - Sun Microsystems - Beijing China logmsg(MSG_INFO, "strdevfspath: %s\n", strdevfspath); 8987fc66be0Sjianfei wang - Sun Microsystems - Beijing China print_node_name("ssd", strdevfspath); 8997fc66be0Sjianfei wang - Sun Microsystems - Beijing China print_node_name("sd", strdevfspath); 9007fc66be0Sjianfei wang - Sun Microsystems - Beijing China } 9017fc66be0Sjianfei wang - Sun Microsystems - Beijing China 902a0261a43SJames C. McPherson static int 903a0261a43SJames C. McPherson mpxio_nvl_boilerplate(di_node_t curnode) 904a0261a43SJames C. McPherson { 905a0261a43SJames C. McPherson int rv; 906a0261a43SJames C. McPherson char *strdevid; 907a0261a43SJames C. McPherson ddi_devid_t curdevid; 908a0261a43SJames C. McPherson nvlist_t *newnvl; 909a0261a43SJames C. McPherson 910a0261a43SJames C. McPherson for (; curnode != DI_NODE_NIL; curnode = di_drv_next_node(curnode)) { 911a0261a43SJames C. McPherson errno = 0; 912a0261a43SJames C. McPherson 913a0261a43SJames C. McPherson curdevid = NULL; 914a0261a43SJames C. McPherson get_devid(curnode, &curdevid); 915a0261a43SJames C. McPherson if (curdevid == NULL) 916a0261a43SJames C. McPherson /* 917a0261a43SJames C. McPherson * There's no devid registered for this device 918a0261a43SJames C. McPherson * so it's not cool enough to play with us 919a0261a43SJames C. McPherson */ 920a0261a43SJames C. McPherson continue; 921a0261a43SJames C. McPherson 922a0261a43SJames C. McPherson strdevid = devid_str_encode(curdevid, NULL); 923a0261a43SJames C. McPherson /* does this exist in the on-disk cache? */ 924a0261a43SJames C. McPherson rv = nvlist_lookup_nvlist(mapnvl, strdevid, &newnvl); 925a0261a43SJames C. McPherson if (rv == ENOENT) { 926a0261a43SJames C. McPherson logmsg(MSG_INFO, "nvlist for %s not found\n", strdevid); 927a0261a43SJames C. McPherson /* no, so alloc a new nvl to store it */ 928a0261a43SJames C. McPherson if (nvlist_alloc(&newnvl, NV_UNIQUE_NAME, 0) != 0) { 929a0261a43SJames C. McPherson logmsg(MSG_ERROR, 930a0261a43SJames C. McPherson gettext("Unable to allocate space for " 931a0261a43SJames C. McPherson "a devid property list: %s\n"), 932a0261a43SJames C. McPherson strerror(errno)); 933a0261a43SJames C. McPherson return (-1); 934a0261a43SJames C. McPherson } 935a0261a43SJames C. McPherson } else { 936a0261a43SJames C. McPherson if ((rv != ENOTSUP) && (rv != EINVAL)) 937a0261a43SJames C. McPherson logmsg(MSG_INFO, 938a0261a43SJames C. McPherson "%s exists in ondisknvl, verifying\n", 939a0261a43SJames C. McPherson strdevid); 940a0261a43SJames C. McPherson } 941a0261a43SJames C. McPherson 942a0261a43SJames C. McPherson if (popcheck_devnvl(curnode, newnvl, strdevid) != 0) { 943a0261a43SJames C. McPherson logmsg(MSG_ERROR, 944a0261a43SJames C. McPherson gettext("Unable to populate devid nvpair " 945a0261a43SJames C. McPherson "for device with devid %s\n"), 946a0261a43SJames C. McPherson strdevid); 947a0261a43SJames C. McPherson devid_str_free(strdevid); 948a0261a43SJames C. McPherson nvlist_free(newnvl); 949a0261a43SJames C. McPherson return (-1); 950a0261a43SJames C. McPherson } 951a0261a43SJames C. McPherson 952a0261a43SJames C. McPherson /* Now add newnvl into our cache. */ 953a0261a43SJames C. McPherson errno = 0; 954a0261a43SJames C. McPherson rv = nvlist_add_nvlist(mapnvl, strdevid, newnvl); 955a0261a43SJames C. McPherson if (rv) { 956a0261a43SJames C. McPherson logmsg(MSG_ERROR, 957a0261a43SJames C. McPherson gettext("Unable to add device (devid %s) " 958a0261a43SJames C. McPherson "to in-kernel nvl: %s (%d)\n"), 959a0261a43SJames C. McPherson strdevid, strerror(rv), rv); 960a0261a43SJames C. McPherson devid_str_free(strdevid); 961a0261a43SJames C. McPherson nvlist_free(newnvl); 962a0261a43SJames C. McPherson return (-1); 963a0261a43SJames C. McPherson } 964a0261a43SJames C. McPherson logmsg(MSG_INFO, 965a0261a43SJames C. McPherson gettext("added device (devid %s) to mapnvl\n\n"), 966a0261a43SJames C. McPherson strdevid); 967a0261a43SJames C. McPherson devid_str_free(strdevid); 968a0261a43SJames C. McPherson } 969a0261a43SJames C. McPherson return (0); 970a0261a43SJames C. McPherson } 971a0261a43SJames C. McPherson 972a0261a43SJames C. McPherson /* 973a0261a43SJames C. McPherson * Operates on a single di_node_t, collecting all the device properties 974a0261a43SJames C. McPherson * that we need. devnvl is allocated by the caller, and we add our nvpairs 975a0261a43SJames C. McPherson * to it if they don't already exist. 976a0261a43SJames C. McPherson * 977a0261a43SJames C. McPherson * We are _only_ interested in devices which have a devid. We pull in 978a0261a43SJames C. McPherson * devices even when they're excluded via stmsboot -D (driver), because 979a0261a43SJames C. McPherson * we don't want to miss out on any devid data that might be handy later. 980a0261a43SJames C. McPherson */ 981a0261a43SJames C. McPherson static int 982a0261a43SJames C. McPherson popcheck_devnvl(di_node_t thisnode, nvlist_t *devnvl, char *strdevid) 983a0261a43SJames C. McPherson { 984a0261a43SJames C. McPherson char *path = NULL; 985a0261a43SJames C. McPherson char *curpath = NULL; 986a0261a43SJames C. McPherson char *devfspath = NULL; 98735c62094Sjianfei wang - Sun Microsystems - Beijing China char *prop = NULL; 988a0261a43SJames C. McPherson int scsivhciparent = 0; 989a0261a43SJames C. McPherson int rv = 0; 990a0261a43SJames C. McPherson boolean_t mpxenp = B_FALSE; 991a0261a43SJames C. McPherson 992a0261a43SJames C. McPherson errno = 0; 993a0261a43SJames C. McPherson devfspath = di_devfs_path(thisnode); 994a0261a43SJames C. McPherson if (devfspath == NULL) { 995a0261a43SJames C. McPherson logmsg(MSG_ERROR, 996a0261a43SJames C. McPherson gettext("Unable to determine devfs path for node: %s\n"), 997a0261a43SJames C. McPherson strerror(errno)); 998a0261a43SJames C. McPherson return (-1); 999a0261a43SJames C. McPherson } 1000a0261a43SJames C. McPherson 1001a0261a43SJames C. McPherson /* Add a convenient devfspath to devid inverse map */ 1002a0261a43SJames C. McPherson if (nvlist_add_string(mapnvl, devfspath, strdevid) != 0) { 1003a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1004a0261a43SJames C. McPherson gettext("Unable to add device path %s with devid " 1005a0261a43SJames C. McPherson "%s to mapnvl\n"), devfspath, strdevid); 1006a0261a43SJames C. McPherson return (-1); 1007a0261a43SJames C. McPherson } 100835c62094Sjianfei wang - Sun Microsystems - Beijing China if (di_prop_lookup_strings(DDI_DEV_T_ANY, di_parent_node(thisnode), 100935c62094Sjianfei wang - Sun Microsystems - Beijing China "mpxio-disable", &prop) >= 0) { 101035c62094Sjianfei wang - Sun Microsystems - Beijing China if (strncmp(prop, "yes", 3) == 0) { 101135c62094Sjianfei wang - Sun Microsystems - Beijing China if (!mpxprop) 101235c62094Sjianfei wang - Sun Microsystems - Beijing China mpxprop++; 101335c62094Sjianfei wang - Sun Microsystems - Beijing China } 101435c62094Sjianfei wang - Sun Microsystems - Beijing China } 101535c62094Sjianfei wang - Sun Microsystems - Beijing China 1016a0261a43SJames C. McPherson if (strncmp(di_driver_name(di_parent_node(thisnode)), 1017a0261a43SJames C. McPherson "scsi_vhci", 9) == 0) { 1018a0261a43SJames C. McPherson scsivhciparent = 1; 1019a0261a43SJames C. McPherson if (!mpxenabled) 1020a0261a43SJames C. McPherson mpxenabled++; 1021a0261a43SJames C. McPherson 1022a0261a43SJames C. McPherson rv = nvlist_lookup_boolean_value(devnvl, NVL_MPXEN, &mpxenp); 1023a0261a43SJames C. McPherson if (rv || (mpxenp == B_FALSE)) { 1024a0261a43SJames C. McPherson rv = nvlist_add_boolean_value(devnvl, 1025a0261a43SJames C. McPherson NVL_MPXEN, B_TRUE); 1026a0261a43SJames C. McPherson if (rv) { 1027a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1028a0261a43SJames C. McPherson gettext("Unable to add property %s " 1029a0261a43SJames C. McPherson "(set to B_TRUE) for device %s: " 1030a0261a43SJames C. McPherson "%s (%d)\n"), 1031a0261a43SJames C. McPherson NVL_MPXEN, devfspath, 1032a0261a43SJames C. McPherson strerror(rv), rv); 1033a0261a43SJames C. McPherson return (-1); 1034a0261a43SJames C. McPherson } 1035a0261a43SJames C. McPherson logmsg(MSG_INFO, "NVL_MPXEN :: (B_FALSE->B_TRUE)\n"); 1036a0261a43SJames C. McPherson } 1037a0261a43SJames C. McPherson } else { 1038a0261a43SJames C. McPherson /* turn _off_ the flag if it was enabled */ 1039a0261a43SJames C. McPherson rv = nvlist_add_boolean_value(devnvl, NVL_MPXEN, B_FALSE); 1040a0261a43SJames C. McPherson if (rv) { 1041a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1042a0261a43SJames C. McPherson gettext("Unable to add property %s " 1043a0261a43SJames C. McPherson "(set to B_FALSE) for device %s: %s (%d)\n"), 1044a0261a43SJames C. McPherson NVL_MPXEN, devfspath, 1045a0261a43SJames C. McPherson strerror(rv), rv); 1046a0261a43SJames C. McPherson return (-1); 1047a0261a43SJames C. McPherson } 1048a0261a43SJames C. McPherson logmsg(MSG_INFO, "NVL_MPXEN :: (B_TRUE-> B_FALSE)\n"); 1049a0261a43SJames C. McPherson } 1050a0261a43SJames C. McPherson 1051a0261a43SJames C. McPherson rv = nvlist_add_string(devnvl, NVL_PHYSPATH, devfspath); 1052a0261a43SJames C. McPherson if (rv) { 1053a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1054a0261a43SJames C. McPherson gettext("Unable to add physical device path (%s) " 1055a0261a43SJames C. McPherson "property to nvl\n")); 1056a0261a43SJames C. McPherson return (-1); 1057a0261a43SJames C. McPherson } 1058a0261a43SJames C. McPherson 1059a0261a43SJames C. McPherson if ((curpath = calloc(1, MAXPATHLEN)) == NULL) { 1060a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1061a0261a43SJames C. McPherson gettext("Unable to allocate space for current path\n")); 1062a0261a43SJames C. McPherson return (-1); 1063a0261a43SJames C. McPherson } 1064a0261a43SJames C. McPherson curpath = find_link(thisnode); 1065a0261a43SJames C. McPherson if (curpath == NULL) { 1066a0261a43SJames C. McPherson if (readonlyroot) { 1067a0261a43SJames C. McPherson return (0); 1068a0261a43SJames C. McPherson } 1069a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1070a0261a43SJames C. McPherson gettext("Unable to determine device path for node %s\n"), 1071a0261a43SJames C. McPherson devfspath); 1072a0261a43SJames C. McPherson return (-1); 1073a0261a43SJames C. McPherson } 1074a0261a43SJames C. McPherson 1075a0261a43SJames C. McPherson rv = nvlist_lookup_string(devnvl, NVL_MPXPATH, &path); 1076a0261a43SJames C. McPherson 10777fc66be0Sjianfei wang - Sun Microsystems - Beijing China if (scsivhciparent) { 1078a0261a43SJames C. McPherson (void) nvlist_add_string(devnvl, NVL_MPXPATH, curpath); 10797fc66be0Sjianfei wang - Sun Microsystems - Beijing China } else { 1080a0261a43SJames C. McPherson (void) nvlist_add_string(devnvl, NVL_PATH, curpath); 1081a0261a43SJames C. McPherson path = curpath; 1082a0261a43SJames C. McPherson } 1083a0261a43SJames C. McPherson 1084a0261a43SJames C. McPherson /* 1085a0261a43SJames C. McPherson * This next block provides the path to devid inverse mapping 1086a0261a43SJames C. McPherson * that other functions require 1087a0261a43SJames C. McPherson */ 1088a0261a43SJames C. McPherson if (path != NULL) { 1089a0261a43SJames C. McPherson if (nvlist_add_string(mapnvl, path, strdevid) != 0) { 1090a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1091a0261a43SJames C. McPherson gettext("Unable to add device %s with devid " 1092a0261a43SJames C. McPherson "%s to mapnvl\n"), path, strdevid); 1093a0261a43SJames C. McPherson return (-1); 1094a0261a43SJames C. McPherson } 1095a0261a43SJames C. McPherson logmsg(MSG_INFO, "popcheck_devnvl: added path %s :: %s\n", 1096a0261a43SJames C. McPherson path, strdevid); 10977fc66be0Sjianfei wang - Sun Microsystems - Beijing China } 10987fc66be0Sjianfei wang - Sun Microsystems - Beijing China 1099a0261a43SJames C. McPherson if (nvlist_add_string(mapnvl, curpath, strdevid) != 0) { 1100a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1101a0261a43SJames C. McPherson gettext("Unable to add device %s with devid " 1102a0261a43SJames C. McPherson "%s to mapnvl: %s\n"), 1103a0261a43SJames C. McPherson curpath, strdevid, strerror(errno)); 1104a0261a43SJames C. McPherson return (-1); 1105a0261a43SJames C. McPherson } 1106a0261a43SJames C. McPherson logmsg(MSG_INFO, "popcheck_devnvl: added curpath %s :: %s\n", 1107a0261a43SJames C. McPherson curpath, strdevid); 11087fc66be0Sjianfei wang - Sun Microsystems - Beijing China 1109a0261a43SJames C. McPherson return (0); 1110a0261a43SJames C. McPherson } 1111a0261a43SJames C. McPherson 1112a0261a43SJames C. McPherson static void 1113a0261a43SJames C. McPherson print_mpx_capable(di_node_t curnode) 1114a0261a43SJames C. McPherson { 1115a0261a43SJames C. McPherson char *prop; 1116a0261a43SJames C. McPherson char *path; 1117a0261a43SJames C. McPherson char *aliases = NULL; 1118a0261a43SJames C. McPherson 1119a0261a43SJames C. McPherson if (cap_N_option) { 1120a0261a43SJames C. McPherson aliases = calloc(1, MAXPATHLEN + 1); 1121a0261a43SJames C. McPherson if (aliases == NULL) { 1122a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1123a0261a43SJames C. McPherson gettext("Unable to allocate memory for a device " 1124a0261a43SJames C. McPherson "alias list\n")); 1125a0261a43SJames C. McPherson return; 1126a0261a43SJames C. McPherson } 1127a0261a43SJames C. McPherson } 1128a0261a43SJames C. McPherson 1129a0261a43SJames C. McPherson for (; curnode != DI_NODE_NIL; curnode = di_drv_next_node(curnode)) { 1130a0261a43SJames C. McPherson if (di_prop_lookup_strings(DDI_DEV_T_ANY, curnode, 1131a0261a43SJames C. McPherson "initiator-port", &prop) >= 0) { 1132a0261a43SJames C. McPherson if ((path = di_devfs_path(curnode)) == NULL) { 1133a0261a43SJames C. McPherson logmsg(MSG_INFO, 1134a0261a43SJames C. McPherson "Unable to find devfs path for device " 1135a0261a43SJames C. McPherson "%s: %s\n", &curnode, strerror(errno)); 1136a0261a43SJames C. McPherson continue; 1137a0261a43SJames C. McPherson } 1138a0261a43SJames C. McPherson if (cap_N_option) { 1139a0261a43SJames C. McPherson char *nodename = di_node_name(curnode); 1140a0261a43SJames C. McPherson /* nodename is never going to be null */ 1141a0261a43SJames C. McPherson if (strstr(aliases, nodename) == NULL) 1142a0261a43SJames C. McPherson /* haven't seen this nodename before */ 1143a0261a43SJames C. McPherson (void) snprintf(aliases, 1144a0261a43SJames C. McPherson MAXPATHLEN + 1, "%s|%s", 1145a0261a43SJames C. McPherson ((aliases != NULL) ? aliases : ""), 1146a0261a43SJames C. McPherson nodename); 1147a0261a43SJames C. McPherson } else 1148a0261a43SJames C. McPherson (void) printf("%s\n", path); 1149a0261a43SJames C. McPherson } 1150a0261a43SJames C. McPherson } 1151a0261a43SJames C. McPherson if (cap_N_option) 1152a0261a43SJames C. McPherson (void) printf("%s\n", aliases); 1153a0261a43SJames C. McPherson } 1154a0261a43SJames C. McPherson 1155a0261a43SJames C. McPherson static int 1156a0261a43SJames C. McPherson link_cb(di_devlink_t devlink, void *arg) 1157a0261a43SJames C. McPherson { 1158a0261a43SJames C. McPherson const char *result; 1159a0261a43SJames C. McPherson 1160a0261a43SJames C. McPherson result = di_devlink_path(devlink); 1161a0261a43SJames C. McPherson if (result == NULL) { 1162a0261a43SJames C. McPherson arg = (void *)"(null)"; 1163a0261a43SJames C. McPherson } else { 1164a0261a43SJames C. McPherson (void) strlcpy(arg, result, strlen(result)); 1165a0261a43SJames C. McPherson } 1166a0261a43SJames C. McPherson logmsg(MSG_INFO, "\nlink_cb::linkdata->resultstr = %s\n", 1167a0261a43SJames C. McPherson ((result != NULL) ? result : "(null)")); 1168a0261a43SJames C. McPherson return (DI_WALK_CONTINUE); 1169a0261a43SJames C. McPherson } 1170a0261a43SJames C. McPherson 1171a0261a43SJames C. McPherson static char * 1172a0261a43SJames C. McPherson find_link(di_node_t cnode) 1173a0261a43SJames C. McPherson { 1174a0261a43SJames C. McPherson di_minor_t devminor = DI_MINOR_NIL; 1175a0261a43SJames C. McPherson di_devlink_handle_t hdl; 1176a0261a43SJames C. McPherson char *devfspath = NULL; 1177a0261a43SJames C. McPherson char *minorpath = NULL; 1178a0261a43SJames C. McPherson char *linkname = NULL; 1179a0261a43SJames C. McPherson char *cbresult = NULL; 1180a0261a43SJames C. McPherson 1181a0261a43SJames C. McPherson devfspath = di_devfs_path(cnode); 1182a0261a43SJames C. McPherson if (cnode == DI_NODE_NIL) { 1183a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1184a0261a43SJames C. McPherson gettext("find_ctrl must be called with non-null " 1185a0261a43SJames C. McPherson "di_node_t\n")); 1186a0261a43SJames C. McPherson return (NULL); 1187a0261a43SJames C. McPherson } 1188a0261a43SJames C. McPherson logmsg(MSG_INFO, "find_link: devfspath %s\n", devfspath); 1189a0261a43SJames C. McPherson 1190a0261a43SJames C. McPherson if (((cbresult = calloc(1, MAXPATHLEN)) == NULL) || 1191a0261a43SJames C. McPherson ((minorpath = calloc(1, MAXPATHLEN)) == NULL) || 1192a0261a43SJames C. McPherson ((linkname = calloc(1, MAXPATHLEN)) == NULL)) { 1193a0261a43SJames C. McPherson logmsg(MSG_ERROR, "unable to allocate space for dev link\n"); 1194a0261a43SJames C. McPherson return (NULL); 1195a0261a43SJames C. McPherson } 1196a0261a43SJames C. McPherson 1197a0261a43SJames C. McPherson devminor = di_minor_next(cnode, devminor); 1198a0261a43SJames C. McPherson hdl = di_devlink_init(di_devfs_minor_path(devminor), DI_MAKE_LINK); 1199a0261a43SJames C. McPherson if (hdl == NULL) { 1200a0261a43SJames C. McPherson logmsg((readonlyroot ? MSG_INFO : MSG_ERROR), 1201a0261a43SJames C. McPherson gettext("unable to take devlink snapshot: %s\n"), 1202a0261a43SJames C. McPherson strerror(errno)); 1203a0261a43SJames C. McPherson return (NULL); 1204a0261a43SJames C. McPherson } 1205a0261a43SJames C. McPherson 1206a0261a43SJames C. McPherson linkname = "^dsk/"; 1207a0261a43SJames C. McPherson (void) snprintf(minorpath, MAXPATHLEN, "%s:c", devfspath); 1208a0261a43SJames C. McPherson 1209a0261a43SJames C. McPherson errno = 0; 1210a0261a43SJames C. McPherson if (di_devlink_walk(hdl, linkname, minorpath, DI_PRIMARY_LINK, 1211a0261a43SJames C. McPherson (void *)cbresult, link_cb) < 0) { 1212a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1213a0261a43SJames C. McPherson gettext("Unable to walk devlink snapshot for %s: %s\n"), 1214a0261a43SJames C. McPherson minorpath, strerror(errno)); 1215a0261a43SJames C. McPherson return (NULL); 1216a0261a43SJames C. McPherson } 1217a0261a43SJames C. McPherson 1218a0261a43SJames C. McPherson if (di_devlink_fini(&hdl) < 0) { 1219a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1220a0261a43SJames C. McPherson gettext("Unable to close devlink snapshot: %s\n"), 1221a0261a43SJames C. McPherson strerror(errno)); 1222a0261a43SJames C. McPherson } 1223a0261a43SJames C. McPherson if (strstr(cbresult, "dsk/") == NULL) 1224a0261a43SJames C. McPherson return (devfspath); 1225a0261a43SJames C. McPherson 1226a0261a43SJames C. McPherson bzero(minorpath, MAXPATHLEN); 1227a0261a43SJames C. McPherson /* strip off the trailing "s2" */ 1228a0261a43SJames C. McPherson bcopy(cbresult, minorpath, strlen(cbresult) - 1); 1229a0261a43SJames C. McPherson /* Now strip off the /dev/dsk/ prefix for output flexibility */ 1230a0261a43SJames C. McPherson linkname = strrchr(minorpath, '/'); 1231a0261a43SJames C. McPherson return (++linkname); 1232a0261a43SJames C. McPherson } 1233a0261a43SJames C. McPherson 1234a0261a43SJames C. McPherson /* 1235a0261a43SJames C. McPherson * handle case where device has been probed but its target driver is not 1236a0261a43SJames C. McPherson * attached so enumeration has not quite finished. Opening the /devices 1237a0261a43SJames C. McPherson * pathname will force the kernel to finish the enumeration process and 1238a0261a43SJames C. McPherson * let us get the data we need. 1239a0261a43SJames C. McPherson */ 1240a0261a43SJames C. McPherson static void 1241a0261a43SJames C. McPherson get_devid(di_node_t node, ddi_devid_t *thisdevid) 12427c478bd9Sstevel@tonic-gate { 12437c478bd9Sstevel@tonic-gate int fd; 1244a0261a43SJames C. McPherson char realpath[MAXPATHLEN]; 1245a0261a43SJames C. McPherson char *openpath = di_devfs_path(node); 12467c478bd9Sstevel@tonic-gate 1247a0261a43SJames C. McPherson errno = 0; 1248a0261a43SJames C. McPherson bzero(realpath, MAXPATHLEN); 1249a0261a43SJames C. McPherson if (strstr(openpath, "/devices") == NULL) { 1250a0261a43SJames C. McPherson (void) snprintf(realpath, MAXPATHLEN, 1251a0261a43SJames C. McPherson "/devices%s:c,raw", openpath); 1252a0261a43SJames C. McPherson fd = open(realpath, O_RDONLY|O_NDELAY); 125360fffc19Sjw149990 } else { 1254a0261a43SJames C. McPherson fd = open(openpath, O_RDONLY|O_NDELAY); 125560fffc19Sjw149990 } 125660fffc19Sjw149990 1257a0261a43SJames C. McPherson if (fd < 0) { 1258a0261a43SJames C. McPherson logmsg(MSG_INFO, "Unable to open path %s: %s\n", 1259a0261a43SJames C. McPherson openpath, strerror(errno)); 1260a0261a43SJames C. McPherson return; 12617c478bd9Sstevel@tonic-gate } 12627c478bd9Sstevel@tonic-gate 1263a0261a43SJames C. McPherson if (devid_get(fd, thisdevid) != 0) { 1264a0261a43SJames C. McPherson logmsg(MSG_INFO, 1265a0261a43SJames C. McPherson "'%s' node (%s) without a devid registered\n", 1266a0261a43SJames C. McPherson di_driver_name(node), di_devfs_path(node)); 126760fffc19Sjw149990 } 12687c478bd9Sstevel@tonic-gate (void) close(fd); 12697c478bd9Sstevel@tonic-gate } 12707c478bd9Sstevel@tonic-gate 12718cecff49Sgp87344 static int 1272a0261a43SJames C. McPherson print_bootpath() 12738cecff49Sgp87344 { 1274a0261a43SJames C. McPherson char *bootprop = NULL; 12758cecff49Sgp87344 1276a0261a43SJames C. McPherson if (di_prop_lookup_strings(DDI_DEV_T_ANY, devinfo_root, 1277a0261a43SJames C. McPherson "bootpath", &bootprop) >= 0) { 1278a0261a43SJames C. McPherson (void) printf("%s\n", bootprop); 12798cecff49Sgp87344 return (0); 1280a0261a43SJames C. McPherson } else if (di_prop_lookup_strings(DDI_DEV_T_ANY, devinfo_root, 1281a0261a43SJames C. McPherson "boot-path", &bootprop) >= 0) { 1282a0261a43SJames C. McPherson (void) printf("%s\n", bootprop); 1283a0261a43SJames C. McPherson return (0); 1284a0261a43SJames C. McPherson } else { 1285a0261a43SJames C. McPherson (void) printf("ERROR: no bootpath/boot-path property found\n"); 1286a0261a43SJames C. McPherson return (ENOENT); 1287a0261a43SJames C. McPherson } 12888cecff49Sgp87344 } 12898cecff49Sgp87344 12905b504601Sjiang wu - Sun Microsystems - Beijing China static void 12915b504601Sjiang wu - Sun Microsystems - Beijing China get_phci_driver_name(char *phci_path, char **driver_name) 12925b504601Sjiang wu - Sun Microsystems - Beijing China { 12935b504601Sjiang wu - Sun Microsystems - Beijing China di_node_t phci_node = DI_NODE_NIL; 12945b504601Sjiang wu - Sun Microsystems - Beijing China char *tmp = NULL; 12955b504601Sjiang wu - Sun Microsystems - Beijing China 12965b504601Sjiang wu - Sun Microsystems - Beijing China phci_node = di_init(phci_path, DINFOCPYONE); 12975b504601Sjiang wu - Sun Microsystems - Beijing China if (phci_node == DI_NODE_NIL) { 12985b504601Sjiang wu - Sun Microsystems - Beijing China logmsg(MSG_ERROR, 12995b504601Sjiang wu - Sun Microsystems - Beijing China gettext("Unable to take phci snapshot " 13005b504601Sjiang wu - Sun Microsystems - Beijing China "(%s: %d)\n"), strerror(errno), errno); 13015b504601Sjiang wu - Sun Microsystems - Beijing China return; 13025b504601Sjiang wu - Sun Microsystems - Beijing China } 13035b504601Sjiang wu - Sun Microsystems - Beijing China tmp = di_driver_name(phci_node); 13045b504601Sjiang wu - Sun Microsystems - Beijing China if (tmp != NULL) { 13055b504601Sjiang wu - Sun Microsystems - Beijing China (void) strncpy(*driver_name, tmp, 10); 13065b504601Sjiang wu - Sun Microsystems - Beijing China } 13075b504601Sjiang wu - Sun Microsystems - Beijing China di_fini(phci_node); 13085b504601Sjiang wu - Sun Microsystems - Beijing China } 13097fc66be0Sjianfei wang - Sun Microsystems - Beijing China 13108cecff49Sgp87344 /* 1311a0261a43SJames C. McPherson * We only call this routine if we have a scsi_vhci node and must 1312a0261a43SJames C. McPherson * determine the actual physical path of its first online client 1313a0261a43SJames C. McPherson * path. 13147c478bd9Sstevel@tonic-gate */ 1315a0261a43SJames C. McPherson static void 13167fc66be0Sjianfei wang - Sun Microsystems - Beijing China vhci_to_phci(char *devpath, char *slice, int d_flag) 13177c478bd9Sstevel@tonic-gate { 13187c478bd9Sstevel@tonic-gate sv_iocdata_t ioc; 13195a4c37c9Sqh201292 sv_path_info_t *pi; 1320a0261a43SJames C. McPherson int vhci_fd; 1321a0261a43SJames C. McPherson int rv; 1322a0261a43SJames C. McPherson uint_t npaths = 0; 13237fc66be0Sjianfei wang - Sun Microsystems - Beijing China char nodename[MAXPATHLEN]; 13247fc66be0Sjianfei wang - Sun Microsystems - Beijing China char *phci_driver = NULL; 13255a4c37c9Sqh201292 1326a0261a43SJames C. McPherson vhci_fd = open(VHCI_CTL_NODE, O_RDWR); 1327a0261a43SJames C. McPherson if (vhci_fd < 0) 1328a0261a43SJames C. McPherson goto failure; 13295a4c37c9Sqh201292 13305a4c37c9Sqh201292 bzero(&ioc, sizeof (sv_iocdata_t)); 1331a0261a43SJames C. McPherson ioc.client = devpath; 13325a4c37c9Sqh201292 ioc.ret_elem = &npaths; 1333a0261a43SJames C. McPherson rv = ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, &ioc); 1334a0261a43SJames C. McPherson if (rv || npaths == 0) { 1335a0261a43SJames C. McPherson logmsg(MSG_INFO, 1336a0261a43SJames C. McPherson "SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO ioctl() failed, " 1337a0261a43SJames C. McPherson "%s (%d)\n", strerror(rv), rv); 1338a0261a43SJames C. McPherson goto failure; 13395a4c37c9Sqh201292 } 13405a4c37c9Sqh201292 13415a4c37c9Sqh201292 bzero(&ioc, sizeof (sv_iocdata_t)); 1342a0261a43SJames C. McPherson ioc.client = devpath; 13435a4c37c9Sqh201292 ioc.buf_elem = npaths; 13445a4c37c9Sqh201292 ioc.ret_elem = &npaths; 1345a0261a43SJames C. McPherson if ((ioc.ret_buf = calloc(npaths, sizeof (sv_path_info_t))) 1346a0261a43SJames C. McPherson == NULL) 1347a0261a43SJames C. McPherson goto failure; 1348a0261a43SJames C. McPherson rv = ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, &ioc); 1349a0261a43SJames C. McPherson if (rv || npaths == 0) { 1350a0261a43SJames C. McPherson logmsg(MSG_INFO, 1351a0261a43SJames C. McPherson "SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO ioctl() (#2) " 1352a0261a43SJames C. McPherson "failed, %s (%d)\n", strerror(rv), rv); 13537fc66be0Sjianfei wang - Sun Microsystems - Beijing China free(ioc.ret_buf); 1354a0261a43SJames C. McPherson goto failure; 13555a4c37c9Sqh201292 } 13565a4c37c9Sqh201292 13575a4c37c9Sqh201292 if (ioc.buf_elem < npaths) 13585a4c37c9Sqh201292 npaths = ioc.buf_elem; 13595a4c37c9Sqh201292 13605b504601Sjiang wu - Sun Microsystems - Beijing China phci_driver = malloc(10); 13615b504601Sjiang wu - Sun Microsystems - Beijing China if (phci_driver == NULL) { 13625b504601Sjiang wu - Sun Microsystems - Beijing China logmsg(MSG_INFO, 13635b504601Sjiang wu - Sun Microsystems - Beijing China "vhci_to_phci: Memory allocation failed\n"); 13647fc66be0Sjianfei wang - Sun Microsystems - Beijing China free(ioc.ret_buf); 13655b504601Sjiang wu - Sun Microsystems - Beijing China goto failure; 13665b504601Sjiang wu - Sun Microsystems - Beijing China } 13677fc66be0Sjianfei wang - Sun Microsystems - Beijing China 13687fc66be0Sjianfei wang - Sun Microsystems - Beijing China pi = (sv_path_info_t *)ioc.ret_buf; 13697fc66be0Sjianfei wang - Sun Microsystems - Beijing China while (npaths--) { 13707fc66be0Sjianfei wang - Sun Microsystems - Beijing China bzero(nodename, MAXPATHLEN); 13715b504601Sjiang wu - Sun Microsystems - Beijing China bzero(phci_driver, 10); 13727fc66be0Sjianfei wang - Sun Microsystems - Beijing China 13735b504601Sjiang wu - Sun Microsystems - Beijing China get_phci_driver_name(pi->device.ret_phci, 13745b504601Sjiang wu - Sun Microsystems - Beijing China &phci_driver); 13755b504601Sjiang wu - Sun Microsystems - Beijing China logmsg(MSG_INFO, "phci driver name: %s\n", phci_driver); 13765b504601Sjiang wu - Sun Microsystems - Beijing China /* 13775b504601Sjiang wu - Sun Microsystems - Beijing China * A hack, but nicer than a platform-specific ifdef 13785b504601Sjiang wu - Sun Microsystems - Beijing China * fp on SPARC using "ssd" as nodename 13795b504601Sjiang wu - Sun Microsystems - Beijing China * mpt use "sd" when mpxio disabled, use "disk" when 13805b504601Sjiang wu - Sun Microsystems - Beijing China * mpxio is enabled 13815b504601Sjiang wu - Sun Microsystems - Beijing China * for alll other cases, "disk" should be used as the 13825b504601Sjiang wu - Sun Microsystems - Beijing China * nodename 13835b504601Sjiang wu - Sun Microsystems - Beijing China */ 1384a0261a43SJames C. McPherson if (strstr(devpath, "ssd") != NULL) { 13855b504601Sjiang wu - Sun Microsystems - Beijing China (void) snprintf(nodename, 5, "ssd"); 13865b504601Sjiang wu - Sun Microsystems - Beijing China } else if (strncmp(phci_driver, "mpt", 10) == 0) { 13875b504601Sjiang wu - Sun Microsystems - Beijing China (void) snprintf(nodename, 5, "sd"); 1388a0261a43SJames C. McPherson } else { 13895b504601Sjiang wu - Sun Microsystems - Beijing China (void) snprintf(nodename, 5, "disk"); 1390a0261a43SJames C. McPherson } 1391*9955cef3Sjianfei wang - Sun Microsystems - Beijing China if ((d_flag == DISPLAY_ONE_PATH) && 1392*9955cef3Sjianfei wang - Sun Microsystems - Beijing China (pi->ret_state == MDI_PATHINFO_STATE_ONLINE)) { 13937fc66be0Sjianfei wang - Sun Microsystems - Beijing China (void) printf("%s/%s@%s", pi->device.ret_phci, 13947fc66be0Sjianfei wang - Sun Microsystems - Beijing China nodename, pi->ret_addr); 13957fc66be0Sjianfei wang - Sun Microsystems - Beijing China if ((slice != NULL) && (strlen(slice) <= 3)) { 13967fc66be0Sjianfei wang - Sun Microsystems - Beijing China (void) printf("%s\n", slice); 13977fc66be0Sjianfei wang - Sun Microsystems - Beijing China } else { 13987fc66be0Sjianfei wang - Sun Microsystems - Beijing China (void) printf("\n"); 13997fc66be0Sjianfei wang - Sun Microsystems - Beijing China } 14007fc66be0Sjianfei wang - Sun Microsystems - Beijing China break; 14017fc66be0Sjianfei wang - Sun Microsystems - Beijing China } else if (d_flag == DISPLAY_ALL_PATH) { 14027fc66be0Sjianfei wang - Sun Microsystems - Beijing China (void) printf("%s/%s@%s", pi->device.ret_phci, 14037fc66be0Sjianfei wang - Sun Microsystems - Beijing China nodename, pi->ret_addr); 14047fc66be0Sjianfei wang - Sun Microsystems - Beijing China if ((slice != NULL) && (strlen(slice) <= 3)) { 14057fc66be0Sjianfei wang - Sun Microsystems - Beijing China (void) printf("%s\n", slice); 14067fc66be0Sjianfei wang - Sun Microsystems - Beijing China } else { 14077fc66be0Sjianfei wang - Sun Microsystems - Beijing China (void) printf("\n"); 14087fc66be0Sjianfei wang - Sun Microsystems - Beijing China } 14097fc66be0Sjianfei wang - Sun Microsystems - Beijing China } 14105a4c37c9Sqh201292 pi++; 14115a4c37c9Sqh201292 } 14127fc66be0Sjianfei wang - Sun Microsystems - Beijing China free(ioc.ret_buf); 14137fc66be0Sjianfei wang - Sun Microsystems - Beijing China free(phci_driver); 14147fc66be0Sjianfei wang - Sun Microsystems - Beijing China return; 14155a4c37c9Sqh201292 1416a0261a43SJames C. McPherson failure: 14177fc66be0Sjianfei wang - Sun Microsystems - Beijing China (void) printf("NOT_MAPPED\n"); 14185a4c37c9Sqh201292 } 14195a4c37c9Sqh201292 14205a4c37c9Sqh201292 /* 1421a0261a43SJames C. McPherson * Write /etc/vfstab to /etc/vfstab.new, with any remapped device 1422a0261a43SJames C. McPherson * names substituted. 14237c478bd9Sstevel@tonic-gate * 14247c478bd9Sstevel@tonic-gate * Returns: 1425a0261a43SJames C. McPherson * 0 successful operation 14267c478bd9Sstevel@tonic-gate * -1 failed 14277c478bd9Sstevel@tonic-gate */ 14287c478bd9Sstevel@tonic-gate static int 1429a0261a43SJames C. McPherson update_vfstab() 14307c478bd9Sstevel@tonic-gate { 1431a0261a43SJames C. McPherson FILE *fdin, *fdout; 14327c478bd9Sstevel@tonic-gate char *buf, *tmpbuf; 1433a0261a43SJames C. McPherson char fname[MAXPATHLEN]; 1434a0261a43SJames C. McPherson int rv = -1, rval = -1; 14357c478bd9Sstevel@tonic-gate char cdev[MAXPATHLEN]; 14367c478bd9Sstevel@tonic-gate char bdev[MAXPATHLEN]; 14377c478bd9Sstevel@tonic-gate char mntpt[MAXPATHLEN]; 14387c478bd9Sstevel@tonic-gate char fstype[512]; 14397c478bd9Sstevel@tonic-gate char fsckpass[512]; 14407c478bd9Sstevel@tonic-gate char mntboot[512]; 1441a0261a43SJames C. McPherson char mntopt[MAXPATHLEN]; 14427c478bd9Sstevel@tonic-gate char fmt[80]; 1443a0261a43SJames C. McPherson char *prefixt = NULL; 1444a0261a43SJames C. McPherson char *curdev = NULL; 1445a0261a43SJames C. McPherson char *thisdevid = NULL; 1446a0261a43SJames C. McPherson char *slice = NULL; 1447a0261a43SJames C. McPherson nvlist_t *thisdev; 1448a0261a43SJames C. McPherson boolean_t devmpx = B_FALSE; 14497c478bd9Sstevel@tonic-gate 1450a0261a43SJames C. McPherson buf = calloc(1, MAXPATHLEN); 1451a0261a43SJames C. McPherson tmpbuf = calloc(1, MAXPATHLEN); 1452a0261a43SJames C. McPherson if (buf == NULL || tmpbuf == NULL) 14537c478bd9Sstevel@tonic-gate return (-1); 14547c478bd9Sstevel@tonic-gate 1455a0261a43SJames C. McPherson (void) snprintf(fname, MAXPATHLEN, "/etc/mpxio/vfstab.new"); 1456a0261a43SJames C. McPherson 1457a0261a43SJames C. McPherson fdin = fopen("/etc/vfstab", "r"); 1458a0261a43SJames C. McPherson fdout = fopen(fname, "w+"); 1459a0261a43SJames C. McPherson if (fdin == NULL || fdout == NULL) { 1460a0261a43SJames C. McPherson logmsg(MSG_INFO, "Unable to open vfstab or create a backup " 1461a0261a43SJames C. McPherson "vfstab %s\n"); 1462a0261a43SJames C. McPherson return (-1); 1463a0261a43SJames C. McPherson } 14647c478bd9Sstevel@tonic-gate 14657c478bd9Sstevel@tonic-gate (void) snprintf(fmt, sizeof (fmt), 14667c478bd9Sstevel@tonic-gate "%%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds", sizeof (bdev) - 1, 14677c478bd9Sstevel@tonic-gate sizeof (cdev) - 1, sizeof (mntpt) - 1, sizeof (fstype) - 1, 14687c478bd9Sstevel@tonic-gate sizeof (fsckpass) - 1, sizeof (mntboot) - 1, sizeof (mntopt) - 1); 14697c478bd9Sstevel@tonic-gate 1470a0261a43SJames C. McPherson while (fgets(buf, MAXPATHLEN, fdin) != NULL) { 1471a0261a43SJames C. McPherson if (strlen(buf) == (MAXPATHLEN - 1) && 1472a0261a43SJames C. McPherson buf[MAXPATHLEN-2] != '\n') { 1473a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1474a0261a43SJames C. McPherson gettext("/etc/vfstab line length too long, " 14757c478bd9Sstevel@tonic-gate "exceeded %2$d: \"%3$s\"\n"), 1476a0261a43SJames C. McPherson MAXPATHLEN - 2, buf); 14777c478bd9Sstevel@tonic-gate goto out; 14787c478bd9Sstevel@tonic-gate } 14797c478bd9Sstevel@tonic-gate 1480a0261a43SJames C. McPherson prefixt = NULL; 1481a0261a43SJames C. McPherson curdev = NULL; 1482a0261a43SJames C. McPherson slice = NULL; 1483a0261a43SJames C. McPherson thisdevid = NULL; 1484a0261a43SJames C. McPherson thisdev = NULL; 14857c478bd9Sstevel@tonic-gate 1486a0261a43SJames C. McPherson /* LINTED - variable format specifier */ 1487a0261a43SJames C. McPherson rv = sscanf(buf, fmt, bdev, cdev, mntpt, fstype, fsckpass, 1488a0261a43SJames C. McPherson mntboot, mntopt); 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate /* 1491a0261a43SJames C. McPherson * Walk through the lines in the input file (/etc/vfstab), 1492a0261a43SJames C. McPherson * skipping anything which is _not_ a COGD (common or garden 1493a0261a43SJames C. McPherson * disk), ie all the /devices, /system, /dev/md, /dev/vx and 1494a0261a43SJames C. McPherson * /dev/zvol and so forth. 14957c478bd9Sstevel@tonic-gate */ 1496a0261a43SJames C. McPherson if ((rv == 7) && (bdev[0] == '/') && 1497a0261a43SJames C. McPherson (strstr(bdev, "/dev/dsk"))) { 1498a0261a43SJames C. McPherson slice = strrchr(bdev, 's'); 1499a0261a43SJames C. McPherson /* take a copy, strip off /dev/dsk/ */ 1500a0261a43SJames C. McPherson prefixt = strrchr(bdev, 'c'); 1501a0261a43SJames C. McPherson prefixt[strlen(bdev) - 9 - strlen(slice)] = '\0'; 1502a0261a43SJames C. McPherson slice++; /* advance past the s */ 1503a0261a43SJames C. McPherson rval = nvlist_lookup_string(mapnvl, prefixt, 1504a0261a43SJames C. McPherson &thisdevid); 1505a0261a43SJames C. McPherson if (rval) { 1506a0261a43SJames C. McPherson /* Whoa, where did this device go?! */ 1507a0261a43SJames C. McPherson logmsg(MSG_INFO, 1508a0261a43SJames C. McPherson "error looking up device %s\n", prefixt); 1509a0261a43SJames C. McPherson /* Comment-out this line in the new version */ 1510a0261a43SJames C. McPherson (void) snprintf(tmpbuf, MAXPATHLEN, 1511a0261a43SJames C. McPherson "# DEVICE NOT FOUND %s", buf); 1512a0261a43SJames C. McPherson (void) fprintf(fdout, "%s", tmpbuf); 1513a0261a43SJames C. McPherson continue; 1514a0261a43SJames C. McPherson } else { 1515a0261a43SJames C. McPherson /* The device exists in our mapnvl */ 1516a0261a43SJames C. McPherson (void) nvlist_lookup_nvlist(mapnvl, thisdevid, 1517a0261a43SJames C. McPherson &thisdev); 1518a0261a43SJames C. McPherson (void) nvlist_lookup_boolean_value(thisdev, 1519a0261a43SJames C. McPherson NVL_MPXEN, &devmpx); 1520a0261a43SJames C. McPherson (void) nvlist_lookup_string(thisdev, 1521a0261a43SJames C. McPherson ((devmpx == B_TRUE) 1522a0261a43SJames C. McPherson ? NVL_MPXPATH : NVL_PATH), 1523a0261a43SJames C. McPherson &curdev); 1524a0261a43SJames C. McPherson } 15257c478bd9Sstevel@tonic-gate } 15267c478bd9Sstevel@tonic-gate 1527a0261a43SJames C. McPherson if ((prefixt != NULL) && (curdev != NULL) && 1528a0261a43SJames C. McPherson (rv = (strncmp(prefixt, curdev, strlen(prefixt)) != 0))) { 1529a0261a43SJames C. McPherson /* Mapping change for this device */ 1530a0261a43SJames C. McPherson if (strcmp(fstype, "swap") == 0) { 1531a0261a43SJames C. McPherson (void) snprintf(tmpbuf, MAXPATHLEN, 1532a0261a43SJames C. McPherson "/dev/dsk/%ss%s\t-\t-\tswap\t" 1533a0261a43SJames C. McPherson "%s\t%s\t%s\n", 1534a0261a43SJames C. McPherson curdev, slice, fsckpass, mntboot, mntopt); 1535a0261a43SJames C. McPherson } else { 1536a0261a43SJames C. McPherson (void) snprintf(tmpbuf, MAXPATHLEN, 1537a0261a43SJames C. McPherson "/dev/dsk/%ss%s\t/dev/rdsk/%ss%s\t" 1538a0261a43SJames C. McPherson "%s\t%s\t%s\t%s\t%s\n", 1539a0261a43SJames C. McPherson curdev, slice, curdev, slice, 1540a0261a43SJames C. McPherson mntpt, fstype, fsckpass, mntboot, mntopt); 1541a0261a43SJames C. McPherson } 1542a0261a43SJames C. McPherson errno = 0; 1543a0261a43SJames C. McPherson (void) fprintf(fdout, "%s", tmpbuf); 1544a0261a43SJames C. McPherson } else { 1545a0261a43SJames C. McPherson (void) fprintf(fdout, "%s", buf); 1546a0261a43SJames C. McPherson } 1547a0261a43SJames C. McPherson 1548a0261a43SJames C. McPherson errno = 0; 1549a0261a43SJames C. McPherson if (fflush(fdout) != 0) { 1550a0261a43SJames C. McPherson logmsg(MSG_ERROR, 1551a0261a43SJames C. McPherson gettext("fprintf failed to write to %s: %s (%d)\n"), 1552a0261a43SJames C. McPherson fname, strerror(errno), errno); 15537c478bd9Sstevel@tonic-gate goto out; 15547c478bd9Sstevel@tonic-gate } 15557c478bd9Sstevel@tonic-gate } 15567c478bd9Sstevel@tonic-gate out: 1557a0261a43SJames C. McPherson (void) fclose(fdin); 1558a0261a43SJames C. McPherson (void) fclose(fdout); 15597c478bd9Sstevel@tonic-gate free(buf); 15607c478bd9Sstevel@tonic-gate free(tmpbuf); 1561a0261a43SJames C. McPherson return (errno); 15628cecff49Sgp87344 } 1563