10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51717Swesolows * Common Development and Distribution License (the "License").
61717Swesolows * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
211717Swesolows
220Sstevel@tonic-gate /*
2312168SJianfei.Wang@Sun.COM * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <stdio.h>
270Sstevel@tonic-gate #include <stdlib.h>
280Sstevel@tonic-gate #include <stdarg.h>
290Sstevel@tonic-gate #include <sys/types.h>
300Sstevel@tonic-gate #include <sys/stat.h>
310Sstevel@tonic-gate #include <fcntl.h>
320Sstevel@tonic-gate #include <errno.h>
330Sstevel@tonic-gate #include <unistd.h>
340Sstevel@tonic-gate #include <stropts.h>
350Sstevel@tonic-gate #include <strings.h>
360Sstevel@tonic-gate #include <sys/param.h>
370Sstevel@tonic-gate #include <libdevinfo.h>
380Sstevel@tonic-gate #include <locale.h>
390Sstevel@tonic-gate #include <libintl.h>
400Sstevel@tonic-gate #include <devid.h>
419325SSrivijitha.Dugganapalli@Sun.COM #include <sys/libdevid.h>
427498SJames.McPherson@Sun.COM #include <sys/modctl.h> /* for MAXMODCONFNAME */
437498SJames.McPherson@Sun.COM #include <sys/scsi/adapters/scsi_vhci.h>
440Sstevel@tonic-gate
450Sstevel@tonic-gate /*
467498SJames.McPherson@Sun.COM * SAVE_DIR is the directory in which system files are saved.
477498SJames.McPherson@Sun.COM * SAVE_DIR must be under the root filesystem, as this program is
480Sstevel@tonic-gate * typically run before any other filesystems are mounted.
490Sstevel@tonic-gate */
500Sstevel@tonic-gate #define SAVE_DIR "/etc/mpxio"
517498SJames.McPherson@Sun.COM #define VHCI_CTL_NODE "/devices/scsi_vhci:devctl"
520Sstevel@tonic-gate
537498SJames.McPherson@Sun.COM /* nvlist property names, these are ALL string types */
547498SJames.McPherson@Sun.COM #define NVL_DEVID "nvl-devid"
557498SJames.McPherson@Sun.COM #define NVL_PATH "nvl-path"
567498SJames.McPherson@Sun.COM #define NVL_PHYSPATH "nvl-physpath"
577498SJames.McPherson@Sun.COM #define NVL_MPXPATH "nvl-mpxiopath"
587498SJames.McPherson@Sun.COM #define NVL_MPXEN "nvl-mpxioenabled"
594022Sjw149990
607498SJames.McPherson@Sun.COM #define MPX_LIST 0x01
617498SJames.McPherson@Sun.COM #define MPX_MAP 0x02
627498SJames.McPherson@Sun.COM #define MPX_CAPABLE_CTRL 0x04
6312168SJianfei.Wang@Sun.COM #define MPX_DEV_PATH 0x06
647498SJames.McPherson@Sun.COM #define MPX_INIT 0x08
657498SJames.McPherson@Sun.COM #define MPX_PHYSICAL 0x10
667498SJames.McPherson@Sun.COM #define MPX_BOOTPATH 0x20
677498SJames.McPherson@Sun.COM #define MPX_UPDATEVFSTAB 0x40
6812168SJianfei.Wang@Sun.COM #define MPX_GETPATH 0x60
697498SJames.McPherson@Sun.COM #define MPX_USAGE 0x80
707498SJames.McPherson@Sun.COM #define MSG_INFO 0x01
717498SJames.McPherson@Sun.COM #define MSG_ERROR 0x02
727498SJames.McPherson@Sun.COM #define MSG_PANIC 0x04
734022Sjw149990
7412168SJianfei.Wang@Sun.COM #define BOOT_PATH 0x02
757498SJames.McPherson@Sun.COM #define BOOT 0x01
767498SJames.McPherson@Sun.COM #define NONBOOT 0x00
770Sstevel@tonic-gate
7812168SJianfei.Wang@Sun.COM #define DISPLAY_ONE_PATH 0x00
7912168SJianfei.Wang@Sun.COM #define DISPLAY_ALL_PATH 0x01
8012168SJianfei.Wang@Sun.COM
810Sstevel@tonic-gate static di_node_t devinfo_root = DI_NODE_NIL;
827498SJames.McPherson@Sun.COM static char *ondiskname = "/etc/mpxio/devid_path.cache";
830Sstevel@tonic-gate
840Sstevel@tonic-gate /*
857498SJames.McPherson@Sun.COM * We use devid-keyed nvlists to keep track of the guid, traditional and
867498SJames.McPherson@Sun.COM * MPxIO-enabled /dev/rdsk paths. Each of these nvlists is eventually
877498SJames.McPherson@Sun.COM * added to our global nvlist and our on-disk nvlist.
880Sstevel@tonic-gate */
897498SJames.McPherson@Sun.COM static nvlist_t *mapnvl;
907498SJames.McPherson@Sun.COM static int mpxenabled = 0;
917498SJames.McPherson@Sun.COM static int limctrl = -1;
929329SJianfei.Wang@Sun.COM static int mpxprop = 0;
937498SJames.McPherson@Sun.COM static int guid = 0;
947498SJames.McPherson@Sun.COM static char *drvlimit;
957498SJames.McPherson@Sun.COM static int globarg = 0;
967498SJames.McPherson@Sun.COM static int debugflag = 0;
977498SJames.McPherson@Sun.COM static char *devicep;
987498SJames.McPherson@Sun.COM static int readonlyroot = 0;
997498SJames.McPherson@Sun.COM static int cap_N_option = 0;
1007498SJames.McPherson@Sun.COM
1017498SJames.McPherson@Sun.COM static void print_mpx_capable(di_node_t curnode);
1027498SJames.McPherson@Sun.COM static int popcheck_devnvl(di_node_t thisnode, nvlist_t *devnvl,
1037498SJames.McPherson@Sun.COM char *strdevid);
1047498SJames.McPherson@Sun.COM static int mpxio_nvl_boilerplate(di_node_t curnode);
1057498SJames.McPherson@Sun.COM static int validate_devnvl();
1067498SJames.McPherson@Sun.COM static void report_map(char *argdev, int physpath);
1077498SJames.McPherson@Sun.COM static void list_devs(int listguids, int ctrl);
1087498SJames.McPherson@Sun.COM static void logmsg(int level, const char *msg, ...);
1097498SJames.McPherson@Sun.COM static char *find_link(di_node_t cnode);
1107498SJames.McPherson@Sun.COM static void usage();
1117498SJames.McPherson@Sun.COM static void parse_args(int argc, char *argv[]);
1127498SJames.McPherson@Sun.COM static void get_devid(di_node_t node, ddi_devid_t *thisdevid);
1137498SJames.McPherson@Sun.COM static int print_bootpath();
11412168SJianfei.Wang@Sun.COM static void vhci_to_phci(char *devpath, char *slice, int d_flag);
1157498SJames.McPherson@Sun.COM static int update_vfstab();
11612168SJianfei.Wang@Sun.COM static void report_dev_node_name(char *strdevfspath);
11712168SJianfei.Wang@Sun.COM static void print_node_name(char *drv_name, char *strdevfspath);
1187498SJames.McPherson@Sun.COM int
main(int argc,char ** argv)1197498SJames.McPherson@Sun.COM main(int argc, char **argv)
1200Sstevel@tonic-gate {
1217498SJames.McPherson@Sun.COM struct stat cachestat;
1227498SJames.McPherson@Sun.COM int mapfd = 0;
1237498SJames.McPherson@Sun.COM int rv = 0;
1247498SJames.McPherson@Sun.COM char *ondiskbuf;
1257498SJames.McPherson@Sun.COM size_t newsz = 0;
1267498SJames.McPherson@Sun.COM
1277498SJames.McPherson@Sun.COM parse_args(argc, argv);
1287498SJames.McPherson@Sun.COM errno = 0;
1297498SJames.McPherson@Sun.COM devinfo_root = di_init("/", DINFOCPYALL|DINFOFORCE);
1307498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "errno = %d after "
1317498SJames.McPherson@Sun.COM "di_init(/,DINFOCPYALL|DINFOFORCE)\n", errno);
1327498SJames.McPherson@Sun.COM if (devinfo_root == NULL) {
1337498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
1347498SJames.McPherson@Sun.COM gettext("Unable to take device tree snapshot "
1357498SJames.McPherson@Sun.COM "(%s: %d)\n"), strerror(errno), errno);
1367498SJames.McPherson@Sun.COM return (-1);
1377498SJames.McPherson@Sun.COM }
1387498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "opened root di_node\n");
1397498SJames.McPherson@Sun.COM
1407498SJames.McPherson@Sun.COM if (globarg == MPX_CAPABLE_CTRL) {
1417498SJames.McPherson@Sun.COM /* we just want to find MPxIO-capable controllers and exit */
1427498SJames.McPherson@Sun.COM if (drvlimit != NULL) {
1437498SJames.McPherson@Sun.COM print_mpx_capable(di_drv_first_node(drvlimit,
1447498SJames.McPherson@Sun.COM devinfo_root));
1457498SJames.McPherson@Sun.COM } else {
1467498SJames.McPherson@Sun.COM print_mpx_capable(di_drv_first_node("fp",
1477498SJames.McPherson@Sun.COM devinfo_root));
1487498SJames.McPherson@Sun.COM print_mpx_capable(di_drv_first_node("mpt",
1497498SJames.McPherson@Sun.COM devinfo_root));
1509907SJaven.Wu@Sun.COM print_mpx_capable(di_drv_first_node("mpt_sas",
1519907SJaven.Wu@Sun.COM devinfo_root));
15210696SDavid.Hollister@Sun.COM print_mpx_capable(di_drv_first_node("pmcs",
15310696SDavid.Hollister@Sun.COM devinfo_root));
1547498SJames.McPherson@Sun.COM }
1557498SJames.McPherson@Sun.COM di_fini(devinfo_root);
1567498SJames.McPherson@Sun.COM return (0);
1577498SJames.McPherson@Sun.COM }
1580Sstevel@tonic-gate
1597498SJames.McPherson@Sun.COM mapfd = open(ondiskname, O_RDWR|O_CREAT|O_SYNC, S_IRUSR | S_IWUSR);
1607498SJames.McPherson@Sun.COM if (mapfd < 0) {
1617498SJames.McPherson@Sun.COM /* we could be in single-user, so try for RO */
1627498SJames.McPherson@Sun.COM if ((mapfd = open(ondiskname, O_RDONLY)) < 0) {
1637498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
1647498SJames.McPherson@Sun.COM gettext("Unable to open or create %s:%s\n"),
1657498SJames.McPherson@Sun.COM ondiskname, strerror(errno));
1667498SJames.McPherson@Sun.COM return (errno);
1677498SJames.McPherson@Sun.COM }
1687498SJames.McPherson@Sun.COM readonlyroot = 1;
1697498SJames.McPherson@Sun.COM }
1707498SJames.McPherson@Sun.COM
1717498SJames.McPherson@Sun.COM if (stat(ondiskname, &cachestat) != 0) {
1727498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
1737498SJames.McPherson@Sun.COM gettext("Unable to stat() %s: %s\n"),
1747498SJames.McPherson@Sun.COM ondiskname, strerror(errno));
1757498SJames.McPherson@Sun.COM return (errno);
1767498SJames.McPherson@Sun.COM }
1777498SJames.McPherson@Sun.COM ondiskbuf = calloc(1, cachestat.st_size);
1787498SJames.McPherson@Sun.COM if (ondiskbuf == NULL) {
1797498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
1807498SJames.McPherson@Sun.COM gettext("Unable to allocate memory for the devid "
1817498SJames.McPherson@Sun.COM "cache file: %s\n"), strerror(errno));
1827498SJames.McPherson@Sun.COM return (errno);
1837498SJames.McPherson@Sun.COM }
1847498SJames.McPherson@Sun.COM rv = read(mapfd, ondiskbuf, cachestat.st_size);
1857498SJames.McPherson@Sun.COM if (rv != cachestat.st_size) {
1867498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
1877498SJames.McPherson@Sun.COM gettext("Unable to read all of devid cache file (got %d "
1887498SJames.McPherson@Sun.COM "from expected %d bytes): %s\n"),
1897498SJames.McPherson@Sun.COM rv, cachestat.st_size, strerror(errno));
1907498SJames.McPherson@Sun.COM return (errno);
1917498SJames.McPherson@Sun.COM }
1927498SJames.McPherson@Sun.COM errno = 0;
1937498SJames.McPherson@Sun.COM rv = nvlist_unpack(ondiskbuf, cachestat.st_size, &mapnvl, 0);
1947498SJames.McPherson@Sun.COM if (rv) {
1957498SJames.McPherson@Sun.COM logmsg(MSG_INFO,
1967498SJames.McPherson@Sun.COM "Unable to unpack devid cache file %s: %s (%d)\n",
1977498SJames.McPherson@Sun.COM ondiskname, strerror(rv), rv);
1987498SJames.McPherson@Sun.COM if (nvlist_alloc(&mapnvl, NV_UNIQUE_NAME, 0) != 0) {
1997498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
2007498SJames.McPherson@Sun.COM gettext("Unable to allocate root property"
2017498SJames.McPherson@Sun.COM "list\n"));
2027498SJames.McPherson@Sun.COM return (errno);
2037498SJames.McPherson@Sun.COM }
2047498SJames.McPherson@Sun.COM }
2057498SJames.McPherson@Sun.COM free(ondiskbuf);
2067498SJames.McPherson@Sun.COM
2077498SJames.McPherson@Sun.COM if (validate_devnvl() < 0) {
2087498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
2097498SJames.McPherson@Sun.COM gettext("unable to validate kernel with on-disk devid "
2107498SJames.McPherson@Sun.COM "cache file\n"));
2117498SJames.McPherson@Sun.COM return (errno);
2127498SJames.McPherson@Sun.COM }
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate /*
2157498SJames.McPherson@Sun.COM * If we're in single-user mode or maintenance mode, we won't
2167498SJames.McPherson@Sun.COM * necessarily have a writable root device (ZFSroot; ufs root is
2177498SJames.McPherson@Sun.COM * different in that we _do_ have a writable root device.
2187498SJames.McPherson@Sun.COM * This causes problems for the devlink calls (see
2197498SJames.McPherson@Sun.COM * $SRC/lib/libdevinfo/devinfo_devlink.c) and we do not try to
2207498SJames.McPherson@Sun.COM * write out the devnvl if root is readonly.
2210Sstevel@tonic-gate */
2227498SJames.McPherson@Sun.COM if (!readonlyroot) {
2237498SJames.McPherson@Sun.COM rv = nvlist_size(mapnvl, &newsz, NV_ENCODE_NATIVE);
2247498SJames.McPherson@Sun.COM if (rv) {
2257498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
2267498SJames.McPherson@Sun.COM gettext("Unable to determine size of packed "
2277498SJames.McPherson@Sun.COM "on-disk devid cache file %s: %s (%d).\n"),
2287498SJames.McPherson@Sun.COM ondiskname, strerror(rv), rv);
2297498SJames.McPherson@Sun.COM logmsg(MSG_ERROR, gettext("Terminating\n"));
2307498SJames.McPherson@Sun.COM nvlist_free(mapnvl);
2317498SJames.McPherson@Sun.COM (void) close(mapfd);
2327498SJames.McPherson@Sun.COM return (rv);
2337498SJames.McPherson@Sun.COM }
2347498SJames.McPherson@Sun.COM
2357498SJames.McPherson@Sun.COM if ((ondiskbuf = calloc(1, newsz)) == NULL) {
2367498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
2377498SJames.McPherson@Sun.COM "Unable to allocate space for writing out new "
2387498SJames.McPherson@Sun.COM "on-disk devid cache file: %s\n", strerror(errno));
2397498SJames.McPherson@Sun.COM (void) close(mapfd);
2407498SJames.McPherson@Sun.COM nvlist_free(mapnvl);
2417498SJames.McPherson@Sun.COM return (errno);
2427498SJames.McPherson@Sun.COM }
2437498SJames.McPherson@Sun.COM
2447498SJames.McPherson@Sun.COM rv = nvlist_pack(mapnvl, &ondiskbuf, &newsz,
2457498SJames.McPherson@Sun.COM NV_ENCODE_NATIVE, 0);
2467498SJames.McPherson@Sun.COM if (rv) {
2477498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
2487498SJames.McPherson@Sun.COM gettext("Unable to pack on-disk devid cache "
2497498SJames.McPherson@Sun.COM "file: %s (%d)\n"), strerror(rv), rv);
2507498SJames.McPherson@Sun.COM (void) close(mapfd);
2517498SJames.McPherson@Sun.COM free(ondiskbuf);
2527498SJames.McPherson@Sun.COM nvlist_free(mapnvl);
2537498SJames.McPherson@Sun.COM return (rv);
2547498SJames.McPherson@Sun.COM }
2557498SJames.McPherson@Sun.COM
2567498SJames.McPherson@Sun.COM rv = lseek(mapfd, 0, 0);
2577498SJames.McPherson@Sun.COM if (rv == -1) {
2587498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
2597498SJames.McPherson@Sun.COM gettext("Unable to seek to start of devid cache "
2607498SJames.McPherson@Sun.COM "file: %s (%d)\n"), strerror(errno), errno);
2617498SJames.McPherson@Sun.COM (void) close(mapfd);
2627498SJames.McPherson@Sun.COM free(ondiskbuf);
2637498SJames.McPherson@Sun.COM nvlist_free(mapnvl);
2647498SJames.McPherson@Sun.COM return (-1);
2657498SJames.McPherson@Sun.COM }
2667498SJames.McPherson@Sun.COM
2677498SJames.McPherson@Sun.COM if (write(mapfd, ondiskbuf, newsz) != newsz) {
2687498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
2697498SJames.McPherson@Sun.COM gettext("Unable to completely write out "
2707498SJames.McPherson@Sun.COM "on-disk devid cache file: %s\n"), strerror(errno));
2717498SJames.McPherson@Sun.COM (void) close(mapfd);
2727498SJames.McPherson@Sun.COM nvlist_free(mapnvl);
2737498SJames.McPherson@Sun.COM free(ondiskbuf);
2747498SJames.McPherson@Sun.COM return (errno);
2757498SJames.McPherson@Sun.COM }
2767498SJames.McPherson@Sun.COM } /* !readonlyroot */
2777498SJames.McPherson@Sun.COM
2787498SJames.McPherson@Sun.COM /* Now we can process the command line args */
2797498SJames.McPherson@Sun.COM if (globarg == MPX_PHYSICAL) {
2807498SJames.McPherson@Sun.COM report_map(devicep, BOOT);
2817498SJames.McPherson@Sun.COM } else if (globarg == MPX_BOOTPATH) {
2827498SJames.McPherson@Sun.COM rv = print_bootpath();
2837498SJames.McPherson@Sun.COM di_fini(devinfo_root);
2847498SJames.McPherson@Sun.COM return (rv);
2857498SJames.McPherson@Sun.COM } else if (globarg == MPX_UPDATEVFSTAB) {
2867498SJames.McPherson@Sun.COM rv = update_vfstab();
2877498SJames.McPherson@Sun.COM di_fini(devinfo_root);
2887498SJames.McPherson@Sun.COM return (rv);
28912168SJianfei.Wang@Sun.COM } else if (globarg == MPX_GETPATH) {
29012168SJianfei.Wang@Sun.COM report_dev_node_name(devicep);
29112168SJianfei.Wang@Sun.COM } else if (globarg == MPX_DEV_PATH) {
29212168SJianfei.Wang@Sun.COM report_map(devicep, BOOT_PATH);
2937498SJames.McPherson@Sun.COM } else if (globarg != MPX_INIT) {
2947498SJames.McPherson@Sun.COM if (globarg & MPX_LIST)
2957498SJames.McPherson@Sun.COM list_devs(guid, limctrl);
2967498SJames.McPherson@Sun.COM
2977498SJames.McPherson@Sun.COM if (globarg == MPX_MAP)
2987498SJames.McPherson@Sun.COM report_map(devicep, NONBOOT);
2997498SJames.McPherson@Sun.COM } else {
3007498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "\nprivate devid cache file initialised\n");
3017498SJames.McPherson@Sun.COM }
3027498SJames.McPherson@Sun.COM
3037498SJames.McPherson@Sun.COM nvlist_free(mapnvl);
3047498SJames.McPherson@Sun.COM di_fini(devinfo_root);
3057498SJames.McPherson@Sun.COM return (0);
3067498SJames.McPherson@Sun.COM }
3077498SJames.McPherson@Sun.COM
3087498SJames.McPherson@Sun.COM static void
usage()3097498SJames.McPherson@Sun.COM usage()
3107498SJames.McPherson@Sun.COM {
3117498SJames.McPherson@Sun.COM (void) fprintf(stderr,
3127498SJames.McPherson@Sun.COM gettext("usage: stmsboot_util -b | -m devname | "
3137498SJames.McPherson@Sun.COM "-l <ctrl> | -L | [-g] | -n | -N | -i | -p devname\n"));
3147498SJames.McPherson@Sun.COM (void) fprintf(stderr, "\n\n");
3157498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t-h\tprint this usage message\n"));
3167498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t-b\tretrieve the system's bootpath "
3177498SJames.McPherson@Sun.COM "setting\n"));
3187498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t-m devname\n"));
3197498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t\tReports the current mapping for "
3207498SJames.McPherson@Sun.COM "devname\n"));
3217498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t-g\tprint the GUID for MPxIO-capable "
3227498SJames.McPherson@Sun.COM "devices. This\n"));
3237498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t\toption is only valid with the -L "
3247498SJames.McPherson@Sun.COM "or -l options\n"));
3257498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t-L | -l <ctrl>\n"));
3267498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t\tList the 'native' to 'MPxIO' "
3277498SJames.McPherson@Sun.COM "device mappings. If <ctrl>\n"));
3287498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t\tis specified, only print mappings "
3297498SJames.McPherson@Sun.COM "for those devices\n"));
3307498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t\tattached via the specified "
3317498SJames.McPherson@Sun.COM "controller.\n"));
3327498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t-i\tinitialise the private devid "
3337498SJames.McPherson@Sun.COM "cache file and exit\n"));
3347498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t\tThis option excludes all "
3357498SJames.McPherson@Sun.COM "others.\n"));
3367498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t-n\tprint the devfs paths for "
3377498SJames.McPherson@Sun.COM "multipath-capable\n"));
3387498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t\tcontroller ports.\n"));
3397498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t-N\tprint the device aliases of "
3407498SJames.McPherson@Sun.COM "multipath-capable\n"));
3417498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t\tcontroller ports.\n"));
3427498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t-p\tdevname\n"));
3437498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t\tThis option provides the physical "
3447498SJames.McPherson@Sun.COM "devfs path for\n"));
3457498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t\ta specific device (devname). Used "
3467498SJames.McPherson@Sun.COM "to set the bootpath\n"));
3477498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t\tvariable on x86/x64 systems\n"));
3487498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t-u\ttranslates device mappings in "
3497498SJames.McPherson@Sun.COM "/etc/vfstab as \n"));
3507498SJames.McPherson@Sun.COM (void) fprintf(stderr, gettext("\t\trequired. The output is written "
3517498SJames.McPherson@Sun.COM "to /etc/mpxio/vfstab.new\n\n"));
3520Sstevel@tonic-gate exit(2);
3530Sstevel@tonic-gate }
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate static void
parse_args(int argc,char * argv[])3560Sstevel@tonic-gate parse_args(int argc, char *argv[])
3570Sstevel@tonic-gate {
3580Sstevel@tonic-gate char opt;
3590Sstevel@tonic-gate
3607498SJames.McPherson@Sun.COM if (argc == 1)
3617498SJames.McPherson@Sun.COM usage();
3620Sstevel@tonic-gate
3637498SJames.McPherson@Sun.COM /*
3647498SJames.McPherson@Sun.COM * -b prints the bootpath property
3657498SJames.McPherson@Sun.COM * -d turns on debug mode for this utility (copious output!)
3667498SJames.McPherson@Sun.COM * -D drvname
3677498SJames.McPherson@Sun.COM * if supplied, indicates that we're going to operate on
3687498SJames.McPherson@Sun.COM * devices attached to this driver.
3697498SJames.McPherson@Sun.COM * -g if (-l or -L), prints guids for devices rather than paths
3707498SJames.McPherson@Sun.COM * -h prints the usage() help text.
3717498SJames.McPherson@Sun.COM * -i initialises the cache file and exits.
3727498SJames.McPherson@Sun.COM * -l controller
3737498SJames.McPherson@Sun.COM * list non-STMS to STMS device name mappings for the specific
3747498SJames.McPherson@Sun.COM * controller, when MPxIO is enabled only.
3757498SJames.McPherson@Sun.COM * -L list non-STMS to STMS device name mappings for all controllers
3767498SJames.McPherson@Sun.COM * when MPxIO is enabled only.
3777498SJames.McPherson@Sun.COM * -m devname
3787498SJames.McPherson@Sun.COM * prints the device path (/dev/rdsk) that devname maps to
3797498SJames.McPherson@Sun.COM * in the currently-running system.
3807498SJames.McPherson@Sun.COM * -n
3817498SJames.McPherson@Sun.COM * if supplied, returns name of STMS-capable controller nodes.
3827498SJames.McPherson@Sun.COM * If the -D drvname option is specified as well, we only report
3837498SJames.McPherson@Sun.COM * nodes attached with drvname.
3847498SJames.McPherson@Sun.COM * -N
3857498SJames.McPherson@Sun.COM * same as the -n option, except that we only print the
3867498SJames.McPherson@Sun.COM * node-name (dev_info :: devi_node_name). Multiple instances
3877498SJames.McPherson@Sun.COM * through the libdevinfo snapshot are uniqified and separated
3887498SJames.McPherson@Sun.COM * by the "|" character for direct use by egrep(1).
3897498SJames.McPherson@Sun.COM * -p devname
3907498SJames.McPherson@Sun.COM * prints the physical devfs path for devname. Only used to
3917498SJames.McPherson@Sun.COM * determine the bootpath.
3927498SJames.McPherson@Sun.COM * -u
3937498SJames.McPherson@Sun.COM * remaps devices in /etc/vfstab, saving the newly generated
3947498SJames.McPherson@Sun.COM * file to /etc/mpxio/vfstab.new. If we have any remapped
3957498SJames.McPherson@Sun.COM * devices, exit with status 0, otherwise -1 for error.
3967498SJames.McPherson@Sun.COM */
39712168SJianfei.Wang@Sun.COM while ((opt = getopt(argc, argv, "bdD:ghil:Lm:nNo:p:q:u")) != EOF) {
3987498SJames.McPherson@Sun.COM switch (opt) {
3997498SJames.McPherson@Sun.COM case 'b':
4007498SJames.McPherson@Sun.COM globarg = MPX_BOOTPATH;
4010Sstevel@tonic-gate break;
4027498SJames.McPherson@Sun.COM case 'd':
4037498SJames.McPherson@Sun.COM debugflag = 1;
4047498SJames.McPherson@Sun.COM break;
4057498SJames.McPherson@Sun.COM case 'D':
4067498SJames.McPherson@Sun.COM if ((drvlimit = calloc(1, MAXMODCONFNAME)) == NULL) {
4077498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
4087498SJames.McPherson@Sun.COM gettext("Unable to allocate memory for a "
4097498SJames.McPherson@Sun.COM "driver name: %s\n"), strerror(errno));
4107498SJames.McPherson@Sun.COM exit(errno);
4117498SJames.McPherson@Sun.COM }
4127498SJames.McPherson@Sun.COM bcopy(optarg, drvlimit, strlen(optarg));
4137498SJames.McPherson@Sun.COM /* update this if adding support for a new driver */
4147498SJames.McPherson@Sun.COM if ((strncmp(drvlimit, "fp", 2) == NULL) &&
4159907SJaven.Wu@Sun.COM (strncmp(drvlimit, "mpt", 3) == NULL) &&
41610696SDavid.Hollister@Sun.COM (strncmp(drvlimit, "mpt_sas", 7) == NULL) &&
41710696SDavid.Hollister@Sun.COM (strncmp(drvlimit, "pmcs", 4) == NULL)) {
4187498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
4197498SJames.McPherson@Sun.COM gettext("invalid parent driver (%s) "
4207498SJames.McPherson@Sun.COM "specified"), drvlimit);
4217498SJames.McPherson@Sun.COM usage();
4227498SJames.McPherson@Sun.COM }
4237498SJames.McPherson@Sun.COM break;
4247498SJames.McPherson@Sun.COM case 'h':
4257498SJames.McPherson@Sun.COM /* Just drop out and print the usage() output */
4267498SJames.McPherson@Sun.COM globarg = MPX_USAGE;
4277498SJames.McPherson@Sun.COM break;
4287498SJames.McPherson@Sun.COM case 'i':
4297498SJames.McPherson@Sun.COM globarg = MPX_INIT;
4307498SJames.McPherson@Sun.COM break;
4310Sstevel@tonic-gate case 'l':
4327498SJames.McPherson@Sun.COM globarg |= MPX_LIST;
4337498SJames.McPherson@Sun.COM limctrl = (int)atol(optarg);
4347498SJames.McPherson@Sun.COM if (limctrl < 0) {
4357498SJames.McPherson@Sun.COM logmsg(MSG_INFO,
4367498SJames.McPherson@Sun.COM gettext("invalid controller number "
4377498SJames.McPherson@Sun.COM "(%d), checking all controllers\n"),
4387498SJames.McPherson@Sun.COM limctrl);
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate break;
4417498SJames.McPherson@Sun.COM case 'L':
4427498SJames.McPherson@Sun.COM globarg |= MPX_LIST;
4437498SJames.McPherson@Sun.COM break;
4440Sstevel@tonic-gate case 'g':
4457498SJames.McPherson@Sun.COM guid = 1;
4460Sstevel@tonic-gate break;
4477498SJames.McPherson@Sun.COM case 'm':
4487498SJames.McPherson@Sun.COM globarg = MPX_MAP;
4497498SJames.McPherson@Sun.COM if ((devicep = calloc(1, MAXPATHLEN)) == NULL) {
4507498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
4517498SJames.McPherson@Sun.COM gettext("Unable to allocate space for a "
4527498SJames.McPherson@Sun.COM "device name\n"));
4537498SJames.McPherson@Sun.COM exit(errno);
4547498SJames.McPherson@Sun.COM }
4557498SJames.McPherson@Sun.COM devicep = strdup(optarg);
4567498SJames.McPherson@Sun.COM break;
4577498SJames.McPherson@Sun.COM case 'N':
4587498SJames.McPherson@Sun.COM cap_N_option = 1;
4597498SJames.McPherson@Sun.COM globarg = MPX_CAPABLE_CTRL;
4607498SJames.McPherson@Sun.COM break;
4617498SJames.McPherson@Sun.COM case 'n':
4627498SJames.McPherson@Sun.COM globarg = MPX_CAPABLE_CTRL;
4633385Sqh201292 break;
46412168SJianfei.Wang@Sun.COM case 'o':
46512168SJianfei.Wang@Sun.COM globarg = MPX_GETPATH;
46612168SJianfei.Wang@Sun.COM if ((devicep = calloc(1, MAXPATHLEN)) == NULL) {
46712168SJianfei.Wang@Sun.COM logmsg(MSG_ERROR,
46812168SJianfei.Wang@Sun.COM gettext("Unable to allocate space for a "
46912168SJianfei.Wang@Sun.COM "device name\n"));
47012168SJianfei.Wang@Sun.COM exit(errno);
47112168SJianfei.Wang@Sun.COM }
47212168SJianfei.Wang@Sun.COM devicep = strdup(optarg);
47312168SJianfei.Wang@Sun.COM break;
4747498SJames.McPherson@Sun.COM case 'p':
4757498SJames.McPherson@Sun.COM globarg = MPX_PHYSICAL;
4767498SJames.McPherson@Sun.COM if ((devicep = calloc(1, MAXPATHLEN)) == NULL) {
4777498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
4787498SJames.McPherson@Sun.COM gettext("Unable to allocate space for a "
4797498SJames.McPherson@Sun.COM "device name\n"));
4807498SJames.McPherson@Sun.COM exit(errno);
4814022Sjw149990 }
4827498SJames.McPherson@Sun.COM devicep = strdup(optarg);
4837498SJames.McPherson@Sun.COM break;
48412168SJianfei.Wang@Sun.COM case 'q':
48512168SJianfei.Wang@Sun.COM globarg = MPX_DEV_PATH;
48612168SJianfei.Wang@Sun.COM if ((devicep = calloc(1, MAXPATHLEN)) == NULL) {
48712168SJianfei.Wang@Sun.COM logmsg(MSG_ERROR,
48812168SJianfei.Wang@Sun.COM gettext("Unable to allocate space for a "
48912168SJianfei.Wang@Sun.COM "device name\n"));
49012168SJianfei.Wang@Sun.COM exit(errno);
49112168SJianfei.Wang@Sun.COM }
49212168SJianfei.Wang@Sun.COM devicep = strdup(optarg);
49312168SJianfei.Wang@Sun.COM break;
4947498SJames.McPherson@Sun.COM case 'u':
4957498SJames.McPherson@Sun.COM globarg = MPX_UPDATEVFSTAB;
4964022Sjw149990 break;
4970Sstevel@tonic-gate default:
4987498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
4997498SJames.McPherson@Sun.COM gettext("Invalid command line option (%c)\n"),
5007498SJames.McPherson@Sun.COM opt);
5017498SJames.McPherson@Sun.COM usage();
5020Sstevel@tonic-gate }
5030Sstevel@tonic-gate }
5040Sstevel@tonic-gate
5057498SJames.McPherson@Sun.COM if ((globarg >= MPX_USAGE) || (guid && (globarg != MPX_LIST)))
5067498SJames.McPherson@Sun.COM usage();
5077498SJames.McPherson@Sun.COM
5087498SJames.McPherson@Sun.COM if ((drvlimit != NULL) &&
5097498SJames.McPherson@Sun.COM ((globarg != MPX_LIST) &&
5107498SJames.McPherson@Sun.COM (globarg != MPX_CAPABLE_CTRL)))
5117498SJames.McPherson@Sun.COM usage();
5127498SJames.McPherson@Sun.COM }
5137498SJames.McPherson@Sun.COM
5147498SJames.McPherson@Sun.COM static void
logmsg(int level,const char * msg,...)5157498SJames.McPherson@Sun.COM logmsg(int level, const char *msg, ...)
5167498SJames.McPherson@Sun.COM {
5177498SJames.McPherson@Sun.COM va_list ap;
5187498SJames.McPherson@Sun.COM
5197498SJames.McPherson@Sun.COM if ((level >= MSG_ERROR) ||
5207498SJames.McPherson@Sun.COM ((debugflag > 0) && (level >= MSG_INFO))) {
5217498SJames.McPherson@Sun.COM (void) fprintf(stdout, "stmsboot: ");
5227498SJames.McPherson@Sun.COM va_start(ap, msg);
5237498SJames.McPherson@Sun.COM (void) vfprintf(stdout, msg, ap);
5247498SJames.McPherson@Sun.COM va_end(ap);
5257498SJames.McPherson@Sun.COM }
5267498SJames.McPherson@Sun.COM }
5277498SJames.McPherson@Sun.COM
5287498SJames.McPherson@Sun.COM /*
5297498SJames.McPherson@Sun.COM * It's up to the caller to do any sorting or pretty-printing of the device
5307498SJames.McPherson@Sun.COM * mappings we report. Since we're storing the device links as just the cXtYdZ
5317498SJames.McPherson@Sun.COM * part, we'll add /dev/rdsk/ back on when we print the listing so we maintain
5327498SJames.McPherson@Sun.COM * compatibility with previous versions of this tool. There's a little bit
5337498SJames.McPherson@Sun.COM * of footwork involved to make sure that we show all the paths to a device
5347498SJames.McPherson@Sun.COM * rather than just the first one we stashed away.
5357498SJames.McPherson@Sun.COM */
5367498SJames.McPherson@Sun.COM static void
list_devs(int listguids,int ctrl)5377498SJames.McPherson@Sun.COM list_devs(int listguids, int ctrl)
5387498SJames.McPherson@Sun.COM {
5397498SJames.McPherson@Sun.COM nvlist_t *thisdevnvl;
5407498SJames.McPherson@Sun.COM nvpair_t *pair;
5417498SJames.McPherson@Sun.COM char *diskpath, *livepath, *key, *querydev;
5427498SJames.McPherson@Sun.COM char *matchctrl = NULL;
5437498SJames.McPherson@Sun.COM char checkctrl[MAXPATHLEN];
5447498SJames.McPherson@Sun.COM int rv;
5457498SJames.McPherson@Sun.COM
5467498SJames.McPherson@Sun.COM if (!mpxenabled) {
5479329SJianfei.Wang@Sun.COM if (mpxprop) {
5489329SJianfei.Wang@Sun.COM logmsg(MSG_ERROR, gettext("MPXIO disabled\n"));
5499329SJianfei.Wang@Sun.COM } else {
5509329SJianfei.Wang@Sun.COM logmsg(MSG_ERROR, gettext("No STMS devices have "
5519329SJianfei.Wang@Sun.COM "been found\n"));
5529329SJianfei.Wang@Sun.COM }
5537498SJames.McPherson@Sun.COM return;
5547498SJames.McPherson@Sun.COM }
5557498SJames.McPherson@Sun.COM
5567498SJames.McPherson@Sun.COM if (listguids) {
5577498SJames.McPherson@Sun.COM (void) printf(gettext("non-STMS device name\t\t\tGUID\n"
5587498SJames.McPherson@Sun.COM "------------------------------------------"
5597498SJames.McPherson@Sun.COM "------------------------\n"));
5607498SJames.McPherson@Sun.COM } else {
5617498SJames.McPherson@Sun.COM (void) printf(gettext("non-STMS device name\t\t\t"
5627498SJames.McPherson@Sun.COM "STMS device name\n"
5637498SJames.McPherson@Sun.COM "------------------------------------------"
5647498SJames.McPherson@Sun.COM "------------------------\n"));
5657498SJames.McPherson@Sun.COM }
5667498SJames.McPherson@Sun.COM
5677498SJames.McPherson@Sun.COM bzero(checkctrl, MAXPATHLEN);
5687498SJames.McPherson@Sun.COM pair = NULL;
5697498SJames.McPherson@Sun.COM while ((pair = nvlist_next_nvpair(mapnvl, pair))
5707498SJames.McPherson@Sun.COM != NULL) {
5717498SJames.McPherson@Sun.COM boolean_t livescsivhcip = B_FALSE;
5727498SJames.McPherson@Sun.COM
5737498SJames.McPherson@Sun.COM if ((((rv = nvpair_value_string(pair, &querydev)) < 0) ||
5747498SJames.McPherson@Sun.COM ((key = nvpair_name(pair)) == NULL)) ||
5757498SJames.McPherson@Sun.COM ((strstr(key, "/pci") != NULL) ||
5767498SJames.McPherson@Sun.COM (strstr(key, "/sbus") != NULL) ||
5777498SJames.McPherson@Sun.COM (strstr(key, "/scsi_vhci") != NULL) ||
5787498SJames.McPherson@Sun.COM (strncmp(key, "id1", 3) == 0))) {
5797498SJames.McPherson@Sun.COM logmsg(MSG_INFO,
5807498SJames.McPherson@Sun.COM "list_devs: rv = %d; (%s) is not a devlink, "
5817498SJames.McPherson@Sun.COM "continuing.\n", rv,
5827498SJames.McPherson@Sun.COM (key != NULL) ? key : "null");
5837498SJames.McPherson@Sun.COM querydev = NULL;
5847498SJames.McPherson@Sun.COM continue;
5857498SJames.McPherson@Sun.COM }
5867498SJames.McPherson@Sun.COM
5877498SJames.McPherson@Sun.COM (void) nvlist_lookup_nvlist(mapnvl, querydev, &thisdevnvl);
5887498SJames.McPherson@Sun.COM (void) nvlist_lookup_boolean_value(thisdevnvl, NVL_MPXEN,
5897498SJames.McPherson@Sun.COM &livescsivhcip);
5907498SJames.McPherson@Sun.COM (void) nvlist_lookup_string(thisdevnvl, NVL_MPXPATH,
5917498SJames.McPherson@Sun.COM &livepath);
5927498SJames.McPherson@Sun.COM
5937498SJames.McPherson@Sun.COM if ((!livescsivhcip) ||
5947498SJames.McPherson@Sun.COM (livescsivhcip &&
5957498SJames.McPherson@Sun.COM (strncmp(key, livepath, strlen(key)) == 0)))
5967498SJames.McPherson@Sun.COM continue;
5977498SJames.McPherson@Sun.COM
5987498SJames.McPherson@Sun.COM (void) nvlist_lookup_string(thisdevnvl, NVL_PATH,
5997498SJames.McPherson@Sun.COM &diskpath);
6007498SJames.McPherson@Sun.COM
6017498SJames.McPherson@Sun.COM logmsg(MSG_INFO,
6027498SJames.McPherson@Sun.COM "list_devs: %s :: %s ::%s :: MPXEN (%s)\n",
6037498SJames.McPherson@Sun.COM key, diskpath, livepath,
6047498SJames.McPherson@Sun.COM ((livescsivhcip) ? "TRUE" : "FALSE"));
6057498SJames.McPherson@Sun.COM
6067498SJames.McPherson@Sun.COM if (ctrl > -1) {
6077498SJames.McPherson@Sun.COM (void) sprintf(checkctrl, "c%dt", ctrl);
6087498SJames.McPherson@Sun.COM matchctrl = strstr(key, checkctrl);
6097498SJames.McPherson@Sun.COM if (matchctrl == NULL)
6107498SJames.McPherson@Sun.COM continue;
6117498SJames.McPherson@Sun.COM }
6127498SJames.McPherson@Sun.COM if (listguids != 0) {
6137498SJames.McPherson@Sun.COM char *tempguid;
6147498SJames.McPherson@Sun.COM ddi_devid_t curdevid;
6157498SJames.McPherson@Sun.COM int rv;
6167498SJames.McPherson@Sun.COM
6177498SJames.McPherson@Sun.COM rv = devid_str_decode(querydev, &curdevid, NULL);
6187498SJames.McPherson@Sun.COM if (rv == -1) {
6197498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "Unable to decode devid %s\n",
6207498SJames.McPherson@Sun.COM key);
6217498SJames.McPherson@Sun.COM continue;
6227498SJames.McPherson@Sun.COM }
6237498SJames.McPherson@Sun.COM tempguid = devid_to_guid(curdevid);
6247498SJames.McPherson@Sun.COM if (tempguid != NULL)
6257498SJames.McPherson@Sun.COM (void) printf("/dev/rdsk/%s\t%s\n",
6267498SJames.McPherson@Sun.COM diskpath, tempguid);
6277498SJames.McPherson@Sun.COM
6287498SJames.McPherson@Sun.COM devid_free_guid(tempguid);
6297498SJames.McPherson@Sun.COM devid_free(curdevid);
6307498SJames.McPherson@Sun.COM continue;
6317498SJames.McPherson@Sun.COM }
6327498SJames.McPherson@Sun.COM
6337498SJames.McPherson@Sun.COM (void) printf("/dev/rdsk/%s\t/dev/rdsk/%s\n",
6347498SJames.McPherson@Sun.COM (strstr(key, diskpath) == NULL) ? key : diskpath,
6357498SJames.McPherson@Sun.COM livepath);
6364022Sjw149990 }
6370Sstevel@tonic-gate }
6380Sstevel@tonic-gate
6397498SJames.McPherson@Sun.COM /*
6407498SJames.McPherson@Sun.COM * We get passed a device name which we search the mapnvl for. If we find
6417498SJames.McPherson@Sun.COM * it, we print the mapping as it is found. It is up to the caller of this
6427498SJames.McPherson@Sun.COM * utility to do any pretty-printing of the results. If a device listed on
6437498SJames.McPherson@Sun.COM * the command line does not exist in the mapnvl, then we print NOT_MAPPED.
6447498SJames.McPherson@Sun.COM * Otherwise we print the command-line device name as it maps to what is
6457498SJames.McPherson@Sun.COM * stashed in the mapnvl - even if that's a "no change" device mapping.
6467498SJames.McPherson@Sun.COM *
6477498SJames.McPherson@Sun.COM * Example output (-p maps to physpath=BOOT)
6487498SJames.McPherson@Sun.COM * # /lib/mpxio/stmsboot_util -p \
6497498SJames.McPherson@Sun.COM * /pci@0,0/pci1022,7450@2/pci1000,3060@3/sd@1,0:a
6507498SJames.McPherson@Sun.COM * /scsi_vhci/disk@g500000e011e17720:a
6517498SJames.McPherson@Sun.COM *
6527498SJames.McPherson@Sun.COM * Or the reverse:
6537498SJames.McPherson@Sun.COM * # /lib/mpxio/stmsboot_util -p /scsi_vhci/disk@g500000e011e17720:a
6547498SJames.McPherson@Sun.COM * /pci@0,0/pci1022,7450@2/pci1000,3060@3/sd@1,0:a
6557498SJames.McPherson@Sun.COM *
6567498SJames.McPherson@Sun.COM * For the -m option, used when we're trying to find the root device mapping:
6577498SJames.McPherson@Sun.COM *
6587498SJames.McPherson@Sun.COM * # /lib/mpxio/stmsboot_util -m /dev/dsk/c2t0d0s2
6597498SJames.McPherson@Sun.COM * /dev/dsk/c3t500000E011637CF0d0s2
6607498SJames.McPherson@Sun.COM */
6617498SJames.McPherson@Sun.COM static void
report_map(char * argdev,int physpath)6627498SJames.McPherson@Sun.COM report_map(char *argdev, int physpath)
6630Sstevel@tonic-gate {
6647498SJames.McPherson@Sun.COM nvlist_t *thisdev;
6657498SJames.McPherson@Sun.COM int rv = 0;
6667498SJames.McPherson@Sun.COM char *thisdevid;
6677498SJames.McPherson@Sun.COM char *mpxpath = NULL;
6687498SJames.McPherson@Sun.COM char *prefixt = NULL;
6697498SJames.McPherson@Sun.COM char *prefixp = NULL;
6707498SJames.McPherson@Sun.COM char *stripdev = NULL;
6717498SJames.McPherson@Sun.COM char *slice = NULL;
6727498SJames.McPherson@Sun.COM boolean_t mpxenp;
6737498SJames.McPherson@Sun.COM uint_t slicelen = 0;
6740Sstevel@tonic-gate
6757498SJames.McPherson@Sun.COM mpxenp = B_FALSE;
6760Sstevel@tonic-gate
6777498SJames.McPherson@Sun.COM if ((prefixt = calloc(1, strlen(argdev) + 1)) == NULL) {
6787498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "Unable to allocate memory\n");
6797498SJames.McPherson@Sun.COM (void) printf("NOT_MAPPED\n");
6807498SJames.McPherson@Sun.COM return;
6810Sstevel@tonic-gate }
6820Sstevel@tonic-gate
6837498SJames.McPherson@Sun.COM (void) strlcpy(prefixt, argdev, strlen(argdev) + 1);
6840Sstevel@tonic-gate
68512168SJianfei.Wang@Sun.COM slice = strrchr(argdev, (physpath == NONBOOT) ? 's' : ':');
6867498SJames.McPherson@Sun.COM if (slice != NULL) {
6877498SJames.McPherson@Sun.COM slicelen = strlen(slice);
6887498SJames.McPherson@Sun.COM if (slicelen > 3)
6897498SJames.McPherson@Sun.COM /* invalid size - max is 3 chars */
6907498SJames.McPherson@Sun.COM slicelen = 0;
6910Sstevel@tonic-gate }
6923385Sqh201292
6937498SJames.McPherson@Sun.COM if ((stripdev = calloc(1, strlen(prefixt) + 1)) == NULL) {
6947498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "Unable to allocate memory\n");
6957498SJames.McPherson@Sun.COM (void) printf("NOT_MAPPED\n");
6967498SJames.McPherson@Sun.COM free(prefixt);
6977498SJames.McPherson@Sun.COM return;
6983385Sqh201292 }
6990Sstevel@tonic-gate
7007498SJames.McPherson@Sun.COM if ((strstr(prefixt, "/scsi_vhci") == NULL) &&
7017498SJames.McPherson@Sun.COM (strstr(prefixt, "/pci") == NULL) &&
7027498SJames.McPherson@Sun.COM (strstr(prefixt, "/sbus") == NULL)) {
7037498SJames.McPherson@Sun.COM prefixp = strrchr(prefixt, '/');
7047498SJames.McPherson@Sun.COM (void) strlcpy(stripdev,
7057498SJames.McPherson@Sun.COM (prefixp == NULL) ? prefixt : prefixp + 1,
7067498SJames.McPherson@Sun.COM (prefixp == NULL) ?
7077498SJames.McPherson@Sun.COM strlen(prefixt) + 1: strlen(prefixp) + 1);
7087498SJames.McPherson@Sun.COM if (prefixp != NULL)
7097498SJames.McPherson@Sun.COM prefixt[strlen(argdev) - strlen(prefixp) + 1] = '\0';
7107498SJames.McPherson@Sun.COM } else {
71112168SJianfei.Wang@Sun.COM if ((physpath != BOOT) &&
71212168SJianfei.Wang@Sun.COM (physpath != BOOT_PATH)) {
7137498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "Invalid device path provided\n");
7147498SJames.McPherson@Sun.COM (void) printf("NOT_MAPPED\n");
7157498SJames.McPherson@Sun.COM free(stripdev);
7167498SJames.McPherson@Sun.COM free(prefixt);
7177498SJames.McPherson@Sun.COM return;
7187498SJames.McPherson@Sun.COM }
7197498SJames.McPherson@Sun.COM (void) strlcpy(stripdev, argdev, strlen(argdev) + 1);
7200Sstevel@tonic-gate }
7210Sstevel@tonic-gate
7227498SJames.McPherson@Sun.COM logmsg(MSG_INFO,
7237498SJames.McPherson@Sun.COM "stripdev (%s), prefixt(%s), prefixp(%s), slice(%s)\n",
7247498SJames.McPherson@Sun.COM (stripdev == NULL) ? "null" : stripdev,
7257498SJames.McPherson@Sun.COM (prefixt == NULL) ? "null" : prefixt,
7267498SJames.McPherson@Sun.COM (prefixp == NULL) ? "null" : prefixp,
7277498SJames.McPherson@Sun.COM (slice == NULL) ? "null" : slice);
7287498SJames.McPherson@Sun.COM
7297498SJames.McPherson@Sun.COM if (slicelen > 0)
7307498SJames.McPherson@Sun.COM stripdev[strlen(stripdev) - slicelen] = '\0';
7317498SJames.McPherson@Sun.COM
7327498SJames.McPherson@Sun.COM /* search for the shortened version */
7337498SJames.McPherson@Sun.COM rv = nvlist_lookup_string(mapnvl, stripdev, &thisdevid);
7347498SJames.McPherson@Sun.COM if (rv) {
73512168SJianfei.Wang@Sun.COM if ((physpath != BOOT) &&
73612168SJianfei.Wang@Sun.COM (physpath != BOOT_PATH)) {
7377498SJames.McPherson@Sun.COM logmsg(MSG_INFO,
7387498SJames.McPherson@Sun.COM "searched mapnvl for '%s', got %s (%d)\n",
7397498SJames.McPherson@Sun.COM stripdev, strerror(rv), rv);
7407498SJames.McPherson@Sun.COM (void) printf("NOT_MAPPED\n");
7417498SJames.McPherson@Sun.COM free(stripdev);
7427498SJames.McPherson@Sun.COM free(prefixt);
7437498SJames.McPherson@Sun.COM return;
7444022Sjw149990 }
7454022Sjw149990 }
7464022Sjw149990
7477498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "device %s has devid %s\n", stripdev, thisdevid);
7480Sstevel@tonic-gate
7497498SJames.McPherson@Sun.COM if (nvlist_lookup_nvlist(mapnvl, thisdevid, &thisdev) != 0) {
7507498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "device (%s) in mapnvl but "
7517498SJames.McPherson@Sun.COM "not mapped!\n", thisdevid);
7527498SJames.McPherson@Sun.COM (void) printf("NOT_MAPPED\n");
7537498SJames.McPherson@Sun.COM free(stripdev);
7547498SJames.McPherson@Sun.COM free(prefixt);
7557498SJames.McPherson@Sun.COM return;
7567498SJames.McPherson@Sun.COM }
7570Sstevel@tonic-gate
7587498SJames.McPherson@Sun.COM /* quick exit */
7597498SJames.McPherson@Sun.COM if (!mpxenabled && (strstr(argdev, "/pci") != NULL ||
7607498SJames.McPherson@Sun.COM strstr(argdev, "/sbus") != NULL)) {
7617498SJames.McPherson@Sun.COM (void) printf("%s\n", argdev);
7627498SJames.McPherson@Sun.COM free(stripdev);
7637498SJames.McPherson@Sun.COM free(prefixt);
7647498SJames.McPherson@Sun.COM return;
7650Sstevel@tonic-gate }
7660Sstevel@tonic-gate
7677498SJames.McPherson@Sun.COM (void) nvlist_lookup_boolean_value(thisdev, NVL_MPXEN, &mpxenp);
7687498SJames.McPherson@Sun.COM
7697498SJames.McPherson@Sun.COM if (physpath == BOOT) {
7707498SJames.McPherson@Sun.COM (void) nvlist_lookup_string(thisdev, NVL_PHYSPATH, &mpxpath);
7717498SJames.McPherson@Sun.COM if ((strstr(argdev, "/scsi_vhci") != NULL) &&
7727498SJames.McPherson@Sun.COM (strncmp(argdev, mpxpath, strlen(mpxpath)) == 0)) {
7737498SJames.McPherson@Sun.COM /* Need to translate vhci to phci */
77412168SJianfei.Wang@Sun.COM vhci_to_phci(stripdev, slice, DISPLAY_ONE_PATH);
77512168SJianfei.Wang@Sun.COM } else {
77612168SJianfei.Wang@Sun.COM (void) printf("%s%s\n", mpxpath,
7777498SJames.McPherson@Sun.COM ((slicelen > 0) && slice != NULL) ? slice : "");
77812168SJianfei.Wang@Sun.COM }
77912168SJianfei.Wang@Sun.COM } else if (physpath == BOOT_PATH) {
78012168SJianfei.Wang@Sun.COM (void) nvlist_lookup_string(thisdev, NVL_PHYSPATH, &mpxpath);
78112168SJianfei.Wang@Sun.COM if ((strstr(argdev, "/scsi_vhci") != NULL) &&
78212168SJianfei.Wang@Sun.COM (strncmp(argdev, mpxpath, strlen(mpxpath)) == 0)) {
78312168SJianfei.Wang@Sun.COM /* Need to translate vhci to phci */
78412168SJianfei.Wang@Sun.COM vhci_to_phci(stripdev, slice, DISPLAY_ALL_PATH);
7857498SJames.McPherson@Sun.COM } else {
7867498SJames.McPherson@Sun.COM (void) printf("%s%s\n", mpxpath,
7877498SJames.McPherson@Sun.COM ((slicelen > 0) && slice != NULL) ? slice : "");
7887498SJames.McPherson@Sun.COM }
7897498SJames.McPherson@Sun.COM } else {
7907498SJames.McPherson@Sun.COM (void) nvlist_lookup_string(thisdev,
7917498SJames.McPherson@Sun.COM ((readonlyroot) ? NVL_PHYSPATH :
7927498SJames.McPherson@Sun.COM ((mpxenp == B_TRUE) ? NVL_MPXPATH : NVL_PATH)),
7937498SJames.McPherson@Sun.COM &mpxpath);
7947498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "mpxpath = %s\n",
7957498SJames.McPherson@Sun.COM (mpxpath == NULL) ? "null" : mpxpath);
7967498SJames.McPherson@Sun.COM if (readonlyroot ||
7977498SJames.McPherson@Sun.COM (strstr(mpxpath, "/scsi_vhci") != NULL) ||
7987498SJames.McPherson@Sun.COM (strstr(mpxpath, "/pci") != NULL) ||
7997498SJames.McPherson@Sun.COM (strstr(mpxpath, "/sbus") != NULL)) {
8007498SJames.McPherson@Sun.COM /*
8017498SJames.McPherson@Sun.COM * If we see a physical path here it means that
8027498SJames.McPherson@Sun.COM * devlinks aren't fully initialised yet, so we
8037498SJames.McPherson@Sun.COM * are still in maintenance/single-user mode.
8047498SJames.McPherson@Sun.COM */
8057498SJames.McPherson@Sun.COM (void) printf("/devices%s:%c\n", mpxpath,
8067498SJames.McPherson@Sun.COM slice[1] + '1');
8077498SJames.McPherson@Sun.COM } else {
8087498SJames.McPherson@Sun.COM (void) printf("%s%s%s\n",
8097498SJames.McPherson@Sun.COM (prefixt[0] == '/') ? prefixt : "",
8107498SJames.McPherson@Sun.COM mpxpath,
8117498SJames.McPherson@Sun.COM ((slicelen > 0) && slice != NULL) ? slice : "");
8127498SJames.McPherson@Sun.COM }
8137498SJames.McPherson@Sun.COM }
8147498SJames.McPherson@Sun.COM free(prefixt);
8157498SJames.McPherson@Sun.COM free(stripdev);
8160Sstevel@tonic-gate }
8170Sstevel@tonic-gate
8180Sstevel@tonic-gate /*
8197498SJames.McPherson@Sun.COM * Validate the in-kernel and on-disk forms of our devid cache,
8207498SJames.McPherson@Sun.COM * returns -1 for unfixable error and 0 for success.
8210Sstevel@tonic-gate */
8220Sstevel@tonic-gate static int
validate_devnvl()8237498SJames.McPherson@Sun.COM validate_devnvl()
8240Sstevel@tonic-gate {
8257498SJames.McPherson@Sun.COM di_node_t curnode;
8267498SJames.McPherson@Sun.COM int rv1 = -1;
8277498SJames.McPherson@Sun.COM int rv2 = -1;
8287498SJames.McPherson@Sun.COM
8297498SJames.McPherson@Sun.COM /*
8307498SJames.McPherson@Sun.COM * Method: we walk through the kernel's concept of the device tree
8317498SJames.McPherson@Sun.COM * looking for "ssd" then "sd" nodes.
8327498SJames.McPherson@Sun.COM * We check to see whether the device's devid is already in our nvlist
8337498SJames.McPherson@Sun.COM * (on disk) nvlist cache file. If it is, we check that it's components
8347498SJames.McPherson@Sun.COM * match what we've got already and fill any missing fields.
8357498SJames.McPherson@Sun.COM * If the devid isn't in our on-disk nvlist already then we add it
8367498SJames.McPherson@Sun.COM * and populate the property nvpairs.
8377498SJames.McPherson@Sun.COM *
8387498SJames.McPherson@Sun.COM * At the end of this function we should have this program's concept
8397498SJames.McPherson@Sun.COM * of the devid-keyed nvlist matching what is in the ondisk form which
8407498SJames.McPherson@Sun.COM * is ready to be written out.
8417498SJames.McPherson@Sun.COM * If we can't do this, then we return -1.
8427498SJames.McPherson@Sun.COM */
8437498SJames.McPherson@Sun.COM curnode = di_drv_first_node("ssd", devinfo_root);
8447498SJames.McPherson@Sun.COM if (curnode != DI_NODE_NIL)
8457498SJames.McPherson@Sun.COM rv1 = mpxio_nvl_boilerplate(curnode);
8467498SJames.McPherson@Sun.COM
8477498SJames.McPherson@Sun.COM curnode = di_drv_first_node("sd", devinfo_root);
8487498SJames.McPherson@Sun.COM if (curnode != DI_NODE_NIL)
8497498SJames.McPherson@Sun.COM rv2 = mpxio_nvl_boilerplate(curnode);
8507498SJames.McPherson@Sun.COM
8517498SJames.McPherson@Sun.COM if (rv1 + rv2 == -2)
8527498SJames.McPherson@Sun.COM return (-1);
8537498SJames.McPherson@Sun.COM
8547498SJames.McPherson@Sun.COM return (0);
8557498SJames.McPherson@Sun.COM }
8567498SJames.McPherson@Sun.COM
85712168SJianfei.Wang@Sun.COM /*
85812168SJianfei.Wang@Sun.COM * According to devfs path name, it will print device node name.
85912168SJianfei.Wang@Sun.COM */
86012168SJianfei.Wang@Sun.COM static void
print_node_name(char * drv_name,char * strdevfspath)86112168SJianfei.Wang@Sun.COM print_node_name(char *drv_name, char *strdevfspath)
86212168SJianfei.Wang@Sun.COM {
86312168SJianfei.Wang@Sun.COM di_node_t curnode;
86412168SJianfei.Wang@Sun.COM char *devfspath = NULL;
86512168SJianfei.Wang@Sun.COM char *node_name = NULL;
86612168SJianfei.Wang@Sun.COM
86712168SJianfei.Wang@Sun.COM curnode = di_drv_first_node(drv_name, devinfo_root);
86812168SJianfei.Wang@Sun.COM for (; curnode != DI_NODE_NIL; curnode = di_drv_next_node(curnode)) {
86912168SJianfei.Wang@Sun.COM devfspath = di_devfs_path(curnode);
87012168SJianfei.Wang@Sun.COM logmsg(MSG_INFO, "find: devfspath %s\n", devfspath);
87112168SJianfei.Wang@Sun.COM
87212168SJianfei.Wang@Sun.COM if (devfspath == NULL)
87312168SJianfei.Wang@Sun.COM continue;
87412168SJianfei.Wang@Sun.COM
875*12924SJianfei.Wang@Sun.COM if ((strlen(strdevfspath) == strlen(devfspath)) &&
876*12924SJianfei.Wang@Sun.COM (strncmp(strdevfspath, devfspath,
877*12924SJianfei.Wang@Sun.COM strlen(devfspath)) == 0)) {
87812168SJianfei.Wang@Sun.COM node_name = find_link(curnode);
87912168SJianfei.Wang@Sun.COM if (node_name == NULL) {
88012168SJianfei.Wang@Sun.COM (void) printf("NOT MAPPED\n");
88112168SJianfei.Wang@Sun.COM } else {
88212168SJianfei.Wang@Sun.COM (void) printf("%s\n", node_name);
88312168SJianfei.Wang@Sun.COM }
88412168SJianfei.Wang@Sun.COM return;
88512168SJianfei.Wang@Sun.COM }
88612168SJianfei.Wang@Sun.COM }
88712168SJianfei.Wang@Sun.COM }
88812168SJianfei.Wang@Sun.COM
88912168SJianfei.Wang@Sun.COM /*
89012168SJianfei.Wang@Sun.COM * report device node name, search "ssd" and "sd" nodes,
89112168SJianfei.Wang@Sun.COM * print the device node name which device path is same as
89212168SJianfei.Wang@Sun.COM * parameter.
89312168SJianfei.Wang@Sun.COM */
89412168SJianfei.Wang@Sun.COM static void
report_dev_node_name(char * strdevfspath)89512168SJianfei.Wang@Sun.COM report_dev_node_name(char *strdevfspath)
89612168SJianfei.Wang@Sun.COM {
89712168SJianfei.Wang@Sun.COM logmsg(MSG_INFO, "strdevfspath: %s\n", strdevfspath);
89812168SJianfei.Wang@Sun.COM print_node_name("ssd", strdevfspath);
89912168SJianfei.Wang@Sun.COM print_node_name("sd", strdevfspath);
90012168SJianfei.Wang@Sun.COM }
90112168SJianfei.Wang@Sun.COM
9027498SJames.McPherson@Sun.COM static int
mpxio_nvl_boilerplate(di_node_t curnode)9037498SJames.McPherson@Sun.COM mpxio_nvl_boilerplate(di_node_t curnode)
9047498SJames.McPherson@Sun.COM {
9057498SJames.McPherson@Sun.COM int rv;
9067498SJames.McPherson@Sun.COM char *strdevid;
9077498SJames.McPherson@Sun.COM ddi_devid_t curdevid;
9087498SJames.McPherson@Sun.COM nvlist_t *newnvl;
9097498SJames.McPherson@Sun.COM
9107498SJames.McPherson@Sun.COM for (; curnode != DI_NODE_NIL; curnode = di_drv_next_node(curnode)) {
9117498SJames.McPherson@Sun.COM errno = 0;
9120Sstevel@tonic-gate
9137498SJames.McPherson@Sun.COM curdevid = NULL;
9147498SJames.McPherson@Sun.COM get_devid(curnode, &curdevid);
9157498SJames.McPherson@Sun.COM if (curdevid == NULL)
9167498SJames.McPherson@Sun.COM /*
9177498SJames.McPherson@Sun.COM * There's no devid registered for this device
9187498SJames.McPherson@Sun.COM * so it's not cool enough to play with us
9197498SJames.McPherson@Sun.COM */
9207498SJames.McPherson@Sun.COM continue;
9217498SJames.McPherson@Sun.COM
9227498SJames.McPherson@Sun.COM strdevid = devid_str_encode(curdevid, NULL);
9237498SJames.McPherson@Sun.COM /* does this exist in the on-disk cache? */
9247498SJames.McPherson@Sun.COM rv = nvlist_lookup_nvlist(mapnvl, strdevid, &newnvl);
9257498SJames.McPherson@Sun.COM if (rv == ENOENT) {
9267498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "nvlist for %s not found\n", strdevid);
9277498SJames.McPherson@Sun.COM /* no, so alloc a new nvl to store it */
9287498SJames.McPherson@Sun.COM if (nvlist_alloc(&newnvl, NV_UNIQUE_NAME, 0) != 0) {
9297498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
9307498SJames.McPherson@Sun.COM gettext("Unable to allocate space for "
9317498SJames.McPherson@Sun.COM "a devid property list: %s\n"),
9327498SJames.McPherson@Sun.COM strerror(errno));
9337498SJames.McPherson@Sun.COM return (-1);
9347498SJames.McPherson@Sun.COM }
9357498SJames.McPherson@Sun.COM } else {
9367498SJames.McPherson@Sun.COM if ((rv != ENOTSUP) && (rv != EINVAL))
9377498SJames.McPherson@Sun.COM logmsg(MSG_INFO,
9387498SJames.McPherson@Sun.COM "%s exists in ondisknvl, verifying\n",
9397498SJames.McPherson@Sun.COM strdevid);
9407498SJames.McPherson@Sun.COM }
9417498SJames.McPherson@Sun.COM
9427498SJames.McPherson@Sun.COM if (popcheck_devnvl(curnode, newnvl, strdevid) != 0) {
9437498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
9447498SJames.McPherson@Sun.COM gettext("Unable to populate devid nvpair "
9457498SJames.McPherson@Sun.COM "for device with devid %s\n"),
9467498SJames.McPherson@Sun.COM strdevid);
9477498SJames.McPherson@Sun.COM devid_str_free(strdevid);
9487498SJames.McPherson@Sun.COM nvlist_free(newnvl);
9497498SJames.McPherson@Sun.COM return (-1);
9507498SJames.McPherson@Sun.COM }
9517498SJames.McPherson@Sun.COM
9527498SJames.McPherson@Sun.COM /* Now add newnvl into our cache. */
9537498SJames.McPherson@Sun.COM errno = 0;
9547498SJames.McPherson@Sun.COM rv = nvlist_add_nvlist(mapnvl, strdevid, newnvl);
9557498SJames.McPherson@Sun.COM if (rv) {
9567498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
9577498SJames.McPherson@Sun.COM gettext("Unable to add device (devid %s) "
9587498SJames.McPherson@Sun.COM "to in-kernel nvl: %s (%d)\n"),
9597498SJames.McPherson@Sun.COM strdevid, strerror(rv), rv);
9607498SJames.McPherson@Sun.COM devid_str_free(strdevid);
9617498SJames.McPherson@Sun.COM nvlist_free(newnvl);
9627498SJames.McPherson@Sun.COM return (-1);
9637498SJames.McPherson@Sun.COM }
9647498SJames.McPherson@Sun.COM logmsg(MSG_INFO,
9657498SJames.McPherson@Sun.COM gettext("added device (devid %s) to mapnvl\n\n"),
9667498SJames.McPherson@Sun.COM strdevid);
9677498SJames.McPherson@Sun.COM devid_str_free(strdevid);
9680Sstevel@tonic-gate }
9690Sstevel@tonic-gate return (0);
9700Sstevel@tonic-gate }
9710Sstevel@tonic-gate
9720Sstevel@tonic-gate /*
9737498SJames.McPherson@Sun.COM * Operates on a single di_node_t, collecting all the device properties
9747498SJames.McPherson@Sun.COM * that we need. devnvl is allocated by the caller, and we add our nvpairs
9757498SJames.McPherson@Sun.COM * to it if they don't already exist.
9760Sstevel@tonic-gate *
9777498SJames.McPherson@Sun.COM * We are _only_ interested in devices which have a devid. We pull in
9787498SJames.McPherson@Sun.COM * devices even when they're excluded via stmsboot -D (driver), because
9797498SJames.McPherson@Sun.COM * we don't want to miss out on any devid data that might be handy later.
9800Sstevel@tonic-gate */
9810Sstevel@tonic-gate static int
popcheck_devnvl(di_node_t thisnode,nvlist_t * devnvl,char * strdevid)9827498SJames.McPherson@Sun.COM popcheck_devnvl(di_node_t thisnode, nvlist_t *devnvl, char *strdevid)
9830Sstevel@tonic-gate {
9847498SJames.McPherson@Sun.COM char *path = NULL;
9857498SJames.McPherson@Sun.COM char *curpath = NULL;
9867498SJames.McPherson@Sun.COM char *devfspath = NULL;
9879329SJianfei.Wang@Sun.COM char *prop = NULL;
9887498SJames.McPherson@Sun.COM int scsivhciparent = 0;
9897498SJames.McPherson@Sun.COM int rv = 0;
9907498SJames.McPherson@Sun.COM boolean_t mpxenp = B_FALSE;
9910Sstevel@tonic-gate
9927498SJames.McPherson@Sun.COM errno = 0;
9937498SJames.McPherson@Sun.COM devfspath = di_devfs_path(thisnode);
9947498SJames.McPherson@Sun.COM if (devfspath == NULL) {
9957498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
9967498SJames.McPherson@Sun.COM gettext("Unable to determine devfs path for node: %s\n"),
9970Sstevel@tonic-gate strerror(errno));
9980Sstevel@tonic-gate return (-1);
9990Sstevel@tonic-gate }
10000Sstevel@tonic-gate
10017498SJames.McPherson@Sun.COM /* Add a convenient devfspath to devid inverse map */
10027498SJames.McPherson@Sun.COM if (nvlist_add_string(mapnvl, devfspath, strdevid) != 0) {
10037498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
10047498SJames.McPherson@Sun.COM gettext("Unable to add device path %s with devid "
10057498SJames.McPherson@Sun.COM "%s to mapnvl\n"), devfspath, strdevid);
10067498SJames.McPherson@Sun.COM return (-1);
10070Sstevel@tonic-gate }
10089329SJianfei.Wang@Sun.COM if (di_prop_lookup_strings(DDI_DEV_T_ANY, di_parent_node(thisnode),
10099329SJianfei.Wang@Sun.COM "mpxio-disable", &prop) >= 0) {
10109329SJianfei.Wang@Sun.COM if (strncmp(prop, "yes", 3) == 0) {
10119329SJianfei.Wang@Sun.COM if (!mpxprop)
10129329SJianfei.Wang@Sun.COM mpxprop++;
10139329SJianfei.Wang@Sun.COM }
10149329SJianfei.Wang@Sun.COM }
10159329SJianfei.Wang@Sun.COM
10167498SJames.McPherson@Sun.COM if (strncmp(di_driver_name(di_parent_node(thisnode)),
10177498SJames.McPherson@Sun.COM "scsi_vhci", 9) == 0) {
10187498SJames.McPherson@Sun.COM scsivhciparent = 1;
10197498SJames.McPherson@Sun.COM if (!mpxenabled)
10207498SJames.McPherson@Sun.COM mpxenabled++;
10210Sstevel@tonic-gate
10227498SJames.McPherson@Sun.COM rv = nvlist_lookup_boolean_value(devnvl, NVL_MPXEN, &mpxenp);
10237498SJames.McPherson@Sun.COM if (rv || (mpxenp == B_FALSE)) {
10247498SJames.McPherson@Sun.COM rv = nvlist_add_boolean_value(devnvl,
10257498SJames.McPherson@Sun.COM NVL_MPXEN, B_TRUE);
10267498SJames.McPherson@Sun.COM if (rv) {
10277498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
10287498SJames.McPherson@Sun.COM gettext("Unable to add property %s "
10297498SJames.McPherson@Sun.COM "(set to B_TRUE) for device %s: "
10307498SJames.McPherson@Sun.COM "%s (%d)\n"),
10317498SJames.McPherson@Sun.COM NVL_MPXEN, devfspath,
10327498SJames.McPherson@Sun.COM strerror(rv), rv);
10337498SJames.McPherson@Sun.COM return (-1);
10347498SJames.McPherson@Sun.COM }
10357498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "NVL_MPXEN :: (B_FALSE->B_TRUE)\n");
10360Sstevel@tonic-gate }
10377498SJames.McPherson@Sun.COM } else {
10387498SJames.McPherson@Sun.COM /* turn _off_ the flag if it was enabled */
10397498SJames.McPherson@Sun.COM rv = nvlist_add_boolean_value(devnvl, NVL_MPXEN, B_FALSE);
10407498SJames.McPherson@Sun.COM if (rv) {
10417498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
10427498SJames.McPherson@Sun.COM gettext("Unable to add property %s "
10437498SJames.McPherson@Sun.COM "(set to B_FALSE) for device %s: %s (%d)\n"),
10447498SJames.McPherson@Sun.COM NVL_MPXEN, devfspath,
10457498SJames.McPherson@Sun.COM strerror(rv), rv);
10467498SJames.McPherson@Sun.COM return (-1);
10477498SJames.McPherson@Sun.COM }
10487498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "NVL_MPXEN :: (B_TRUE-> B_FALSE)\n");
10494022Sjw149990 }
10500Sstevel@tonic-gate
10517498SJames.McPherson@Sun.COM rv = nvlist_add_string(devnvl, NVL_PHYSPATH, devfspath);
10527498SJames.McPherson@Sun.COM if (rv) {
10537498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
10547498SJames.McPherson@Sun.COM gettext("Unable to add physical device path (%s) "
10557498SJames.McPherson@Sun.COM "property to nvl\n"));
10564147Sgp87344 return (-1);
10574147Sgp87344 }
10584147Sgp87344
10597498SJames.McPherson@Sun.COM if ((curpath = calloc(1, MAXPATHLEN)) == NULL) {
10607498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
10617498SJames.McPherson@Sun.COM gettext("Unable to allocate space for current path\n"));
10627498SJames.McPherson@Sun.COM return (-1);
10637498SJames.McPherson@Sun.COM }
10647498SJames.McPherson@Sun.COM curpath = find_link(thisnode);
10657498SJames.McPherson@Sun.COM if (curpath == NULL) {
10667498SJames.McPherson@Sun.COM if (readonlyroot) {
10677498SJames.McPherson@Sun.COM return (0);
10687498SJames.McPherson@Sun.COM }
10697498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
10707498SJames.McPherson@Sun.COM gettext("Unable to determine device path for node %s\n"),
10717498SJames.McPherson@Sun.COM devfspath);
10724147Sgp87344 return (-1);
10737498SJames.McPherson@Sun.COM }
10744147Sgp87344
10757498SJames.McPherson@Sun.COM rv = nvlist_lookup_string(devnvl, NVL_MPXPATH, &path);
10767498SJames.McPherson@Sun.COM
107712168SJianfei.Wang@Sun.COM if (scsivhciparent) {
10787498SJames.McPherson@Sun.COM (void) nvlist_add_string(devnvl, NVL_MPXPATH, curpath);
107912168SJianfei.Wang@Sun.COM } else {
10807498SJames.McPherson@Sun.COM (void) nvlist_add_string(devnvl, NVL_PATH, curpath);
10817498SJames.McPherson@Sun.COM path = curpath;
10827498SJames.McPherson@Sun.COM }
10837498SJames.McPherson@Sun.COM
10847498SJames.McPherson@Sun.COM /*
10857498SJames.McPherson@Sun.COM * This next block provides the path to devid inverse mapping
10867498SJames.McPherson@Sun.COM * that other functions require
10877498SJames.McPherson@Sun.COM */
10887498SJames.McPherson@Sun.COM if (path != NULL) {
10897498SJames.McPherson@Sun.COM if (nvlist_add_string(mapnvl, path, strdevid) != 0) {
10907498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
10917498SJames.McPherson@Sun.COM gettext("Unable to add device %s with devid "
10927498SJames.McPherson@Sun.COM "%s to mapnvl\n"), path, strdevid);
10937498SJames.McPherson@Sun.COM return (-1);
10947498SJames.McPherson@Sun.COM }
10957498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "popcheck_devnvl: added path %s :: %s\n",
10967498SJames.McPherson@Sun.COM path, strdevid);
109712168SJianfei.Wang@Sun.COM }
109812168SJianfei.Wang@Sun.COM
109912168SJianfei.Wang@Sun.COM if (nvlist_add_string(mapnvl, curpath, strdevid) != 0) {
11007498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
11017498SJames.McPherson@Sun.COM gettext("Unable to add device %s with devid "
11027498SJames.McPherson@Sun.COM "%s to mapnvl: %s\n"),
11037498SJames.McPherson@Sun.COM curpath, strdevid, strerror(errno));
11047498SJames.McPherson@Sun.COM return (-1);
11057498SJames.McPherson@Sun.COM }
110612168SJianfei.Wang@Sun.COM logmsg(MSG_INFO, "popcheck_devnvl: added curpath %s :: %s\n",
110712168SJianfei.Wang@Sun.COM curpath, strdevid);
110812168SJianfei.Wang@Sun.COM
11094147Sgp87344 return (0);
11104147Sgp87344 }
11114147Sgp87344
11127498SJames.McPherson@Sun.COM static void
print_mpx_capable(di_node_t curnode)11137498SJames.McPherson@Sun.COM print_mpx_capable(di_node_t curnode)
11147498SJames.McPherson@Sun.COM {
11157498SJames.McPherson@Sun.COM char *prop;
11167498SJames.McPherson@Sun.COM char *path;
11177498SJames.McPherson@Sun.COM char *aliases = NULL;
11184147Sgp87344
11197498SJames.McPherson@Sun.COM if (cap_N_option) {
11207498SJames.McPherson@Sun.COM aliases = calloc(1, MAXPATHLEN + 1);
11217498SJames.McPherson@Sun.COM if (aliases == NULL) {
11227498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
11237498SJames.McPherson@Sun.COM gettext("Unable to allocate memory for a device "
11247498SJames.McPherson@Sun.COM "alias list\n"));
11257498SJames.McPherson@Sun.COM return;
11267498SJames.McPherson@Sun.COM }
11270Sstevel@tonic-gate }
11280Sstevel@tonic-gate
11297498SJames.McPherson@Sun.COM for (; curnode != DI_NODE_NIL; curnode = di_drv_next_node(curnode)) {
11307498SJames.McPherson@Sun.COM if (di_prop_lookup_strings(DDI_DEV_T_ANY, curnode,
11317498SJames.McPherson@Sun.COM "initiator-port", &prop) >= 0) {
11327498SJames.McPherson@Sun.COM if ((path = di_devfs_path(curnode)) == NULL) {
11337498SJames.McPherson@Sun.COM logmsg(MSG_INFO,
11347498SJames.McPherson@Sun.COM "Unable to find devfs path for device "
11357498SJames.McPherson@Sun.COM "%s: %s\n", &curnode, strerror(errno));
11367498SJames.McPherson@Sun.COM continue;
11377498SJames.McPherson@Sun.COM }
11387498SJames.McPherson@Sun.COM if (cap_N_option) {
11397498SJames.McPherson@Sun.COM char *nodename = di_node_name(curnode);
11407498SJames.McPherson@Sun.COM /* nodename is never going to be null */
11417498SJames.McPherson@Sun.COM if (strstr(aliases, nodename) == NULL)
11427498SJames.McPherson@Sun.COM /* haven't seen this nodename before */
11437498SJames.McPherson@Sun.COM (void) snprintf(aliases,
11447498SJames.McPherson@Sun.COM MAXPATHLEN + 1, "%s|%s",
11457498SJames.McPherson@Sun.COM ((aliases != NULL) ? aliases : ""),
11467498SJames.McPherson@Sun.COM nodename);
11477498SJames.McPherson@Sun.COM } else
11487498SJames.McPherson@Sun.COM (void) printf("%s\n", path);
11497498SJames.McPherson@Sun.COM }
11507498SJames.McPherson@Sun.COM }
11517498SJames.McPherson@Sun.COM if (cap_N_option)
11527498SJames.McPherson@Sun.COM (void) printf("%s\n", aliases);
11537498SJames.McPherson@Sun.COM }
11547498SJames.McPherson@Sun.COM
11557498SJames.McPherson@Sun.COM static int
link_cb(di_devlink_t devlink,void * arg)11567498SJames.McPherson@Sun.COM link_cb(di_devlink_t devlink, void *arg)
11577498SJames.McPherson@Sun.COM {
11587498SJames.McPherson@Sun.COM const char *result;
11597498SJames.McPherson@Sun.COM
11607498SJames.McPherson@Sun.COM result = di_devlink_path(devlink);
11617498SJames.McPherson@Sun.COM if (result == NULL) {
11627498SJames.McPherson@Sun.COM arg = (void *)"(null)";
11637498SJames.McPherson@Sun.COM } else {
11647498SJames.McPherson@Sun.COM (void) strlcpy(arg, result, strlen(result));
11657498SJames.McPherson@Sun.COM }
11667498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "\nlink_cb::linkdata->resultstr = %s\n",
11677498SJames.McPherson@Sun.COM ((result != NULL) ? result : "(null)"));
11687498SJames.McPherson@Sun.COM return (DI_WALK_CONTINUE);
11697498SJames.McPherson@Sun.COM }
11707498SJames.McPherson@Sun.COM
11717498SJames.McPherson@Sun.COM static char *
find_link(di_node_t cnode)11727498SJames.McPherson@Sun.COM find_link(di_node_t cnode)
11737498SJames.McPherson@Sun.COM {
11747498SJames.McPherson@Sun.COM di_minor_t devminor = DI_MINOR_NIL;
11757498SJames.McPherson@Sun.COM di_devlink_handle_t hdl;
11767498SJames.McPherson@Sun.COM char *devfspath = NULL;
11777498SJames.McPherson@Sun.COM char *minorpath = NULL;
11787498SJames.McPherson@Sun.COM char *linkname = NULL;
11797498SJames.McPherson@Sun.COM char *cbresult = NULL;
11807498SJames.McPherson@Sun.COM
11817498SJames.McPherson@Sun.COM devfspath = di_devfs_path(cnode);
11827498SJames.McPherson@Sun.COM if (cnode == DI_NODE_NIL) {
11837498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
11847498SJames.McPherson@Sun.COM gettext("find_ctrl must be called with non-null "
11857498SJames.McPherson@Sun.COM "di_node_t\n"));
11867498SJames.McPherson@Sun.COM return (NULL);
11877498SJames.McPherson@Sun.COM }
11887498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "find_link: devfspath %s\n", devfspath);
11897498SJames.McPherson@Sun.COM
11907498SJames.McPherson@Sun.COM if (((cbresult = calloc(1, MAXPATHLEN)) == NULL) ||
11917498SJames.McPherson@Sun.COM ((minorpath = calloc(1, MAXPATHLEN)) == NULL) ||
11927498SJames.McPherson@Sun.COM ((linkname = calloc(1, MAXPATHLEN)) == NULL)) {
11937498SJames.McPherson@Sun.COM logmsg(MSG_ERROR, "unable to allocate space for dev link\n");
11947498SJames.McPherson@Sun.COM return (NULL);
11950Sstevel@tonic-gate }
11960Sstevel@tonic-gate
11977498SJames.McPherson@Sun.COM devminor = di_minor_next(cnode, devminor);
11987498SJames.McPherson@Sun.COM hdl = di_devlink_init(di_devfs_minor_path(devminor), DI_MAKE_LINK);
11997498SJames.McPherson@Sun.COM if (hdl == NULL) {
12007498SJames.McPherson@Sun.COM logmsg((readonlyroot ? MSG_INFO : MSG_ERROR),
12017498SJames.McPherson@Sun.COM gettext("unable to take devlink snapshot: %s\n"),
12027498SJames.McPherson@Sun.COM strerror(errno));
12037498SJames.McPherson@Sun.COM return (NULL);
12040Sstevel@tonic-gate }
12050Sstevel@tonic-gate
12067498SJames.McPherson@Sun.COM linkname = "^dsk/";
12077498SJames.McPherson@Sun.COM (void) snprintf(minorpath, MAXPATHLEN, "%s:c", devfspath);
12087498SJames.McPherson@Sun.COM
12097498SJames.McPherson@Sun.COM errno = 0;
12107498SJames.McPherson@Sun.COM if (di_devlink_walk(hdl, linkname, minorpath, DI_PRIMARY_LINK,
12117498SJames.McPherson@Sun.COM (void *)cbresult, link_cb) < 0) {
12127498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
12137498SJames.McPherson@Sun.COM gettext("Unable to walk devlink snapshot for %s: %s\n"),
12147498SJames.McPherson@Sun.COM minorpath, strerror(errno));
12157498SJames.McPherson@Sun.COM return (NULL);
12167498SJames.McPherson@Sun.COM }
12177498SJames.McPherson@Sun.COM
12187498SJames.McPherson@Sun.COM if (di_devlink_fini(&hdl) < 0) {
12197498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
12207498SJames.McPherson@Sun.COM gettext("Unable to close devlink snapshot: %s\n"),
12217498SJames.McPherson@Sun.COM strerror(errno));
12227498SJames.McPherson@Sun.COM }
12237498SJames.McPherson@Sun.COM if (strstr(cbresult, "dsk/") == NULL)
12247498SJames.McPherson@Sun.COM return (devfspath);
12257498SJames.McPherson@Sun.COM
12267498SJames.McPherson@Sun.COM bzero(minorpath, MAXPATHLEN);
12277498SJames.McPherson@Sun.COM /* strip off the trailing "s2" */
12287498SJames.McPherson@Sun.COM bcopy(cbresult, minorpath, strlen(cbresult) - 1);
12297498SJames.McPherson@Sun.COM /* Now strip off the /dev/dsk/ prefix for output flexibility */
12307498SJames.McPherson@Sun.COM linkname = strrchr(minorpath, '/');
12317498SJames.McPherson@Sun.COM return (++linkname);
12320Sstevel@tonic-gate }
12330Sstevel@tonic-gate
12340Sstevel@tonic-gate /*
12357498SJames.McPherson@Sun.COM * handle case where device has been probed but its target driver is not
12367498SJames.McPherson@Sun.COM * attached so enumeration has not quite finished. Opening the /devices
12377498SJames.McPherson@Sun.COM * pathname will force the kernel to finish the enumeration process and
12387498SJames.McPherson@Sun.COM * let us get the data we need.
12390Sstevel@tonic-gate */
12407498SJames.McPherson@Sun.COM static void
get_devid(di_node_t node,ddi_devid_t * thisdevid)12417498SJames.McPherson@Sun.COM get_devid(di_node_t node, ddi_devid_t *thisdevid)
12420Sstevel@tonic-gate {
12437498SJames.McPherson@Sun.COM int fd;
12447498SJames.McPherson@Sun.COM char realpath[MAXPATHLEN];
12457498SJames.McPherson@Sun.COM char *openpath = di_devfs_path(node);
12460Sstevel@tonic-gate
12477498SJames.McPherson@Sun.COM errno = 0;
12487498SJames.McPherson@Sun.COM bzero(realpath, MAXPATHLEN);
12497498SJames.McPherson@Sun.COM if (strstr(openpath, "/devices") == NULL) {
12507498SJames.McPherson@Sun.COM (void) snprintf(realpath, MAXPATHLEN,
12517498SJames.McPherson@Sun.COM "/devices%s:c,raw", openpath);
12527498SJames.McPherson@Sun.COM fd = open(realpath, O_RDONLY|O_NDELAY);
12537498SJames.McPherson@Sun.COM } else {
12547498SJames.McPherson@Sun.COM fd = open(openpath, O_RDONLY|O_NDELAY);
12550Sstevel@tonic-gate }
12560Sstevel@tonic-gate
12577498SJames.McPherson@Sun.COM if (fd < 0) {
12587498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "Unable to open path %s: %s\n",
12597498SJames.McPherson@Sun.COM openpath, strerror(errno));
12607498SJames.McPherson@Sun.COM return;
12614147Sgp87344 }
12624022Sjw149990
12637498SJames.McPherson@Sun.COM if (devid_get(fd, thisdevid) != 0) {
12647498SJames.McPherson@Sun.COM logmsg(MSG_INFO,
12657498SJames.McPherson@Sun.COM "'%s' node (%s) without a devid registered\n",
12667498SJames.McPherson@Sun.COM di_driver_name(node), di_devfs_path(node));
12674022Sjw149990 }
12687498SJames.McPherson@Sun.COM (void) close(fd);
12697498SJames.McPherson@Sun.COM }
12704022Sjw149990
12717498SJames.McPherson@Sun.COM static int
print_bootpath()12727498SJames.McPherson@Sun.COM print_bootpath()
12737498SJames.McPherson@Sun.COM {
12747498SJames.McPherson@Sun.COM char *bootprop = NULL;
12754022Sjw149990
12767498SJames.McPherson@Sun.COM if (di_prop_lookup_strings(DDI_DEV_T_ANY, devinfo_root,
12777498SJames.McPherson@Sun.COM "bootpath", &bootprop) >= 0) {
12787498SJames.McPherson@Sun.COM (void) printf("%s\n", bootprop);
12797498SJames.McPherson@Sun.COM return (0);
12807498SJames.McPherson@Sun.COM } else if (di_prop_lookup_strings(DDI_DEV_T_ANY, devinfo_root,
12817498SJames.McPherson@Sun.COM "boot-path", &bootprop) >= 0) {
12827498SJames.McPherson@Sun.COM (void) printf("%s\n", bootprop);
12837498SJames.McPherson@Sun.COM return (0);
12847498SJames.McPherson@Sun.COM } else {
12857498SJames.McPherson@Sun.COM (void) printf("ERROR: no bootpath/boot-path property found\n");
12867498SJames.McPherson@Sun.COM return (ENOENT);
12870Sstevel@tonic-gate }
12880Sstevel@tonic-gate }
12890Sstevel@tonic-gate
12909907SJaven.Wu@Sun.COM static void
get_phci_driver_name(char * phci_path,char ** driver_name)12919907SJaven.Wu@Sun.COM get_phci_driver_name(char *phci_path, char **driver_name)
12929907SJaven.Wu@Sun.COM {
12939907SJaven.Wu@Sun.COM di_node_t phci_node = DI_NODE_NIL;
12949907SJaven.Wu@Sun.COM char *tmp = NULL;
12959907SJaven.Wu@Sun.COM
12969907SJaven.Wu@Sun.COM phci_node = di_init(phci_path, DINFOCPYONE);
12979907SJaven.Wu@Sun.COM if (phci_node == DI_NODE_NIL) {
12989907SJaven.Wu@Sun.COM logmsg(MSG_ERROR,
12999907SJaven.Wu@Sun.COM gettext("Unable to take phci snapshot "
13009907SJaven.Wu@Sun.COM "(%s: %d)\n"), strerror(errno), errno);
13019907SJaven.Wu@Sun.COM return;
13029907SJaven.Wu@Sun.COM }
13039907SJaven.Wu@Sun.COM tmp = di_driver_name(phci_node);
13049907SJaven.Wu@Sun.COM if (tmp != NULL) {
13059907SJaven.Wu@Sun.COM (void) strncpy(*driver_name, tmp, 10);
13069907SJaven.Wu@Sun.COM }
13079907SJaven.Wu@Sun.COM di_fini(phci_node);
13089907SJaven.Wu@Sun.COM }
130912168SJianfei.Wang@Sun.COM
13100Sstevel@tonic-gate /*
13117498SJames.McPherson@Sun.COM * We only call this routine if we have a scsi_vhci node and must
13127498SJames.McPherson@Sun.COM * determine the actual physical path of its first online client
13137498SJames.McPherson@Sun.COM * path.
13143385Sqh201292 */
13157498SJames.McPherson@Sun.COM static void
vhci_to_phci(char * devpath,char * slice,int d_flag)131612168SJianfei.Wang@Sun.COM vhci_to_phci(char *devpath, char *slice, int d_flag)
13173385Sqh201292 {
13183385Sqh201292 sv_iocdata_t ioc;
13197498SJames.McPherson@Sun.COM sv_path_info_t *pi;
13207498SJames.McPherson@Sun.COM int vhci_fd;
13217498SJames.McPherson@Sun.COM int rv;
13227498SJames.McPherson@Sun.COM uint_t npaths = 0;
132312168SJianfei.Wang@Sun.COM char nodename[MAXPATHLEN];
132412168SJianfei.Wang@Sun.COM char *phci_driver = NULL;
13257498SJames.McPherson@Sun.COM
13267498SJames.McPherson@Sun.COM vhci_fd = open(VHCI_CTL_NODE, O_RDWR);
13277498SJames.McPherson@Sun.COM if (vhci_fd < 0)
13287498SJames.McPherson@Sun.COM goto failure;
13293385Sqh201292
13307498SJames.McPherson@Sun.COM bzero(&ioc, sizeof (sv_iocdata_t));
13317498SJames.McPherson@Sun.COM ioc.client = devpath;
13327498SJames.McPherson@Sun.COM ioc.ret_elem = &npaths;
13337498SJames.McPherson@Sun.COM rv = ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, &ioc);
13347498SJames.McPherson@Sun.COM if (rv || npaths == 0) {
13357498SJames.McPherson@Sun.COM logmsg(MSG_INFO,
13367498SJames.McPherson@Sun.COM "SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO ioctl() failed, "
13377498SJames.McPherson@Sun.COM "%s (%d)\n", strerror(rv), rv);
13387498SJames.McPherson@Sun.COM goto failure;
13393385Sqh201292 }
13403385Sqh201292
13413385Sqh201292 bzero(&ioc, sizeof (sv_iocdata_t));
13427498SJames.McPherson@Sun.COM ioc.client = devpath;
13433385Sqh201292 ioc.buf_elem = npaths;
13443385Sqh201292 ioc.ret_elem = &npaths;
13457498SJames.McPherson@Sun.COM if ((ioc.ret_buf = calloc(npaths, sizeof (sv_path_info_t)))
13467498SJames.McPherson@Sun.COM == NULL)
13477498SJames.McPherson@Sun.COM goto failure;
13487498SJames.McPherson@Sun.COM rv = ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, &ioc);
13497498SJames.McPherson@Sun.COM if (rv || npaths == 0) {
13507498SJames.McPherson@Sun.COM logmsg(MSG_INFO,
13517498SJames.McPherson@Sun.COM "SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO ioctl() (#2) "
13527498SJames.McPherson@Sun.COM "failed, %s (%d)\n", strerror(rv), rv);
135312168SJianfei.Wang@Sun.COM free(ioc.ret_buf);
13547498SJames.McPherson@Sun.COM goto failure;
13553385Sqh201292 }
13563385Sqh201292
13573385Sqh201292 if (ioc.buf_elem < npaths)
13583385Sqh201292 npaths = ioc.buf_elem;
13593385Sqh201292
136012168SJianfei.Wang@Sun.COM phci_driver = malloc(10);
136112168SJianfei.Wang@Sun.COM if (phci_driver == NULL) {
136212168SJianfei.Wang@Sun.COM logmsg(MSG_INFO,
136312168SJianfei.Wang@Sun.COM "vhci_to_phci: Memory allocation failed\n");
136412168SJianfei.Wang@Sun.COM free(ioc.ret_buf);
136512168SJianfei.Wang@Sun.COM goto failure;
136612168SJianfei.Wang@Sun.COM }
136712168SJianfei.Wang@Sun.COM
13683385Sqh201292 pi = (sv_path_info_t *)ioc.ret_buf;
13693385Sqh201292 while (npaths--) {
1370*12924SJianfei.Wang@Sun.COM bzero(nodename, MAXPATHLEN);
1371*12924SJianfei.Wang@Sun.COM bzero(phci_driver, 10);
137212168SJianfei.Wang@Sun.COM
1373*12924SJianfei.Wang@Sun.COM get_phci_driver_name(pi->device.ret_phci,
1374*12924SJianfei.Wang@Sun.COM &phci_driver);
1375*12924SJianfei.Wang@Sun.COM logmsg(MSG_INFO, "phci driver name: %s\n", phci_driver);
1376*12924SJianfei.Wang@Sun.COM /*
1377*12924SJianfei.Wang@Sun.COM * A hack, but nicer than a platform-specific ifdef
1378*12924SJianfei.Wang@Sun.COM * fp on SPARC using "ssd" as nodename
1379*12924SJianfei.Wang@Sun.COM * mpt use "sd" when mpxio disabled, use "disk" when
1380*12924SJianfei.Wang@Sun.COM * mpxio is enabled
1381*12924SJianfei.Wang@Sun.COM * for alll other cases, "disk" should be used as the
1382*12924SJianfei.Wang@Sun.COM * nodename
1383*12924SJianfei.Wang@Sun.COM */
1384*12924SJianfei.Wang@Sun.COM if (strstr(devpath, "ssd") != NULL) {
1385*12924SJianfei.Wang@Sun.COM (void) snprintf(nodename, 5, "ssd");
1386*12924SJianfei.Wang@Sun.COM } else if (strncmp(phci_driver, "mpt", 10) == 0) {
1387*12924SJianfei.Wang@Sun.COM (void) snprintf(nodename, 5, "sd");
1388*12924SJianfei.Wang@Sun.COM } else {
1389*12924SJianfei.Wang@Sun.COM (void) snprintf(nodename, 5, "disk");
1390*12924SJianfei.Wang@Sun.COM }
1391*12924SJianfei.Wang@Sun.COM if ((d_flag == DISPLAY_ONE_PATH) &&
1392*12924SJianfei.Wang@Sun.COM (pi->ret_state == MDI_PATHINFO_STATE_ONLINE)) {
1393*12924SJianfei.Wang@Sun.COM (void) printf("%s/%s@%s", pi->device.ret_phci,
1394*12924SJianfei.Wang@Sun.COM nodename, pi->ret_addr);
1395*12924SJianfei.Wang@Sun.COM if ((slice != NULL) && (strlen(slice) <= 3)) {
1396*12924SJianfei.Wang@Sun.COM (void) printf("%s\n", slice);
13977498SJames.McPherson@Sun.COM } else {
1398*12924SJianfei.Wang@Sun.COM (void) printf("\n");
13997498SJames.McPherson@Sun.COM }
1400*12924SJianfei.Wang@Sun.COM break;
1401*12924SJianfei.Wang@Sun.COM } else if (d_flag == DISPLAY_ALL_PATH) {
1402*12924SJianfei.Wang@Sun.COM (void) printf("%s/%s@%s", pi->device.ret_phci,
1403*12924SJianfei.Wang@Sun.COM nodename, pi->ret_addr);
1404*12924SJianfei.Wang@Sun.COM if ((slice != NULL) && (strlen(slice) <= 3)) {
1405*12924SJianfei.Wang@Sun.COM (void) printf("%s\n", slice);
1406*12924SJianfei.Wang@Sun.COM } else {
1407*12924SJianfei.Wang@Sun.COM (void) printf("\n");
140812168SJianfei.Wang@Sun.COM }
14093385Sqh201292 }
14103385Sqh201292 pi++;
14113385Sqh201292 }
141212168SJianfei.Wang@Sun.COM free(ioc.ret_buf);
141312168SJianfei.Wang@Sun.COM free(phci_driver);
141412168SJianfei.Wang@Sun.COM return;
14153385Sqh201292
14167498SJames.McPherson@Sun.COM failure:
141712168SJianfei.Wang@Sun.COM (void) printf("NOT_MAPPED\n");
14180Sstevel@tonic-gate }
14190Sstevel@tonic-gate
14200Sstevel@tonic-gate /*
14217498SJames.McPherson@Sun.COM * Write /etc/vfstab to /etc/vfstab.new, with any remapped device
14227498SJames.McPherson@Sun.COM * names substituted.
14230Sstevel@tonic-gate *
14240Sstevel@tonic-gate * Returns:
14259907SJaven.Wu@Sun.COM * 0 successful operation
14260Sstevel@tonic-gate * -1 failed
14270Sstevel@tonic-gate */
14280Sstevel@tonic-gate static int
update_vfstab()14297498SJames.McPherson@Sun.COM update_vfstab()
14300Sstevel@tonic-gate {
14317498SJames.McPherson@Sun.COM FILE *fdin, *fdout;
14320Sstevel@tonic-gate char *buf, *tmpbuf;
14337498SJames.McPherson@Sun.COM char fname[MAXPATHLEN];
14347498SJames.McPherson@Sun.COM int rv = -1, rval = -1;
14350Sstevel@tonic-gate char cdev[MAXPATHLEN];
14360Sstevel@tonic-gate char bdev[MAXPATHLEN];
14370Sstevel@tonic-gate char mntpt[MAXPATHLEN];
14380Sstevel@tonic-gate char fstype[512];
14390Sstevel@tonic-gate char fsckpass[512];
14400Sstevel@tonic-gate char mntboot[512];
14417498SJames.McPherson@Sun.COM char mntopt[MAXPATHLEN];
14420Sstevel@tonic-gate char fmt[80];
14437498SJames.McPherson@Sun.COM char *prefixt = NULL;
14447498SJames.McPherson@Sun.COM char *curdev = NULL;
14457498SJames.McPherson@Sun.COM char *thisdevid = NULL;
14467498SJames.McPherson@Sun.COM char *slice = NULL;
14477498SJames.McPherson@Sun.COM nvlist_t *thisdev;
14487498SJames.McPherson@Sun.COM boolean_t devmpx = B_FALSE;
14490Sstevel@tonic-gate
14507498SJames.McPherson@Sun.COM buf = calloc(1, MAXPATHLEN);
14517498SJames.McPherson@Sun.COM tmpbuf = calloc(1, MAXPATHLEN);
14527498SJames.McPherson@Sun.COM if (buf == NULL || tmpbuf == NULL)
14530Sstevel@tonic-gate return (-1);
14540Sstevel@tonic-gate
14557498SJames.McPherson@Sun.COM (void) snprintf(fname, MAXPATHLEN, "/etc/mpxio/vfstab.new");
14567498SJames.McPherson@Sun.COM
14577498SJames.McPherson@Sun.COM fdin = fopen("/etc/vfstab", "r");
14587498SJames.McPherson@Sun.COM fdout = fopen(fname, "w+");
14597498SJames.McPherson@Sun.COM if (fdin == NULL || fdout == NULL) {
14607498SJames.McPherson@Sun.COM logmsg(MSG_INFO, "Unable to open vfstab or create a backup "
14617498SJames.McPherson@Sun.COM "vfstab %s\n");
14627498SJames.McPherson@Sun.COM return (-1);
14637498SJames.McPherson@Sun.COM }
14640Sstevel@tonic-gate
14650Sstevel@tonic-gate (void) snprintf(fmt, sizeof (fmt),
14660Sstevel@tonic-gate "%%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds", sizeof (bdev) - 1,
14670Sstevel@tonic-gate sizeof (cdev) - 1, sizeof (mntpt) - 1, sizeof (fstype) - 1,
14680Sstevel@tonic-gate sizeof (fsckpass) - 1, sizeof (mntboot) - 1, sizeof (mntopt) - 1);
14690Sstevel@tonic-gate
14707498SJames.McPherson@Sun.COM while (fgets(buf, MAXPATHLEN, fdin) != NULL) {
14717498SJames.McPherson@Sun.COM if (strlen(buf) == (MAXPATHLEN - 1) &&
14727498SJames.McPherson@Sun.COM buf[MAXPATHLEN-2] != '\n') {
14737498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
14747498SJames.McPherson@Sun.COM gettext("/etc/vfstab line length too long, "
14750Sstevel@tonic-gate "exceeded %2$d: \"%3$s\"\n"),
14767498SJames.McPherson@Sun.COM MAXPATHLEN - 2, buf);
14770Sstevel@tonic-gate goto out;
14780Sstevel@tonic-gate }
14790Sstevel@tonic-gate
14807498SJames.McPherson@Sun.COM prefixt = NULL;
14817498SJames.McPherson@Sun.COM curdev = NULL;
14827498SJames.McPherson@Sun.COM slice = NULL;
14837498SJames.McPherson@Sun.COM thisdevid = NULL;
14847498SJames.McPherson@Sun.COM thisdev = NULL;
14850Sstevel@tonic-gate
14867498SJames.McPherson@Sun.COM /* LINTED - variable format specifier */
14877498SJames.McPherson@Sun.COM rv = sscanf(buf, fmt, bdev, cdev, mntpt, fstype, fsckpass,
14887498SJames.McPherson@Sun.COM mntboot, mntopt);
14890Sstevel@tonic-gate
14907498SJames.McPherson@Sun.COM /*
14917498SJames.McPherson@Sun.COM * Walk through the lines in the input file (/etc/vfstab),
14927498SJames.McPherson@Sun.COM * skipping anything which is _not_ a COGD (common or garden
14937498SJames.McPherson@Sun.COM * disk), ie all the /devices, /system, /dev/md, /dev/vx and
14947498SJames.McPherson@Sun.COM * /dev/zvol and so forth.
14957498SJames.McPherson@Sun.COM */
14967498SJames.McPherson@Sun.COM if ((rv == 7) && (bdev[0] == '/') &&
14977498SJames.McPherson@Sun.COM (strstr(bdev, "/dev/dsk"))) {
14987498SJames.McPherson@Sun.COM slice = strrchr(bdev, 's');
14997498SJames.McPherson@Sun.COM /* take a copy, strip off /dev/dsk/ */
15007498SJames.McPherson@Sun.COM prefixt = strrchr(bdev, 'c');
15017498SJames.McPherson@Sun.COM prefixt[strlen(bdev) - 9 - strlen(slice)] = '\0';
15027498SJames.McPherson@Sun.COM slice++; /* advance past the s */
15037498SJames.McPherson@Sun.COM rval = nvlist_lookup_string(mapnvl, prefixt,
15047498SJames.McPherson@Sun.COM &thisdevid);
15057498SJames.McPherson@Sun.COM if (rval) {
15067498SJames.McPherson@Sun.COM /* Whoa, where did this device go?! */
15077498SJames.McPherson@Sun.COM logmsg(MSG_INFO,
15087498SJames.McPherson@Sun.COM "error looking up device %s\n", prefixt);
15097498SJames.McPherson@Sun.COM /* Comment-out this line in the new version */
15107498SJames.McPherson@Sun.COM (void) snprintf(tmpbuf, MAXPATHLEN,
15117498SJames.McPherson@Sun.COM "# DEVICE NOT FOUND %s", buf);
15127498SJames.McPherson@Sun.COM (void) fprintf(fdout, "%s", tmpbuf);
15137498SJames.McPherson@Sun.COM continue;
15147498SJames.McPherson@Sun.COM } else {
15157498SJames.McPherson@Sun.COM /* The device exists in our mapnvl */
15167498SJames.McPherson@Sun.COM (void) nvlist_lookup_nvlist(mapnvl, thisdevid,
15177498SJames.McPherson@Sun.COM &thisdev);
15187498SJames.McPherson@Sun.COM (void) nvlist_lookup_boolean_value(thisdev,
15197498SJames.McPherson@Sun.COM NVL_MPXEN, &devmpx);
15207498SJames.McPherson@Sun.COM (void) nvlist_lookup_string(thisdev,
15217498SJames.McPherson@Sun.COM ((devmpx == B_TRUE)
15227498SJames.McPherson@Sun.COM ? NVL_MPXPATH : NVL_PATH),
15237498SJames.McPherson@Sun.COM &curdev);
15240Sstevel@tonic-gate }
15254022Sjw149990 }
15260Sstevel@tonic-gate
15277498SJames.McPherson@Sun.COM if ((prefixt != NULL) && (curdev != NULL) &&
15287498SJames.McPherson@Sun.COM (rv = (strncmp(prefixt, curdev, strlen(prefixt)) != 0))) {
15297498SJames.McPherson@Sun.COM /* Mapping change for this device */
15307498SJames.McPherson@Sun.COM if (strcmp(fstype, "swap") == 0) {
15317498SJames.McPherson@Sun.COM (void) snprintf(tmpbuf, MAXPATHLEN,
15327498SJames.McPherson@Sun.COM "/dev/dsk/%ss%s\t-\t-\tswap\t"
15337498SJames.McPherson@Sun.COM "%s\t%s\t%s\n",
15347498SJames.McPherson@Sun.COM curdev, slice, fsckpass, mntboot, mntopt);
15357498SJames.McPherson@Sun.COM } else {
15367498SJames.McPherson@Sun.COM (void) snprintf(tmpbuf, MAXPATHLEN,
15377498SJames.McPherson@Sun.COM "/dev/dsk/%ss%s\t/dev/rdsk/%ss%s\t"
15387498SJames.McPherson@Sun.COM "%s\t%s\t%s\t%s\t%s\n",
15397498SJames.McPherson@Sun.COM curdev, slice, curdev, slice,
15407498SJames.McPherson@Sun.COM mntpt, fstype, fsckpass, mntboot, mntopt);
15417498SJames.McPherson@Sun.COM }
15427498SJames.McPherson@Sun.COM errno = 0;
15437498SJames.McPherson@Sun.COM (void) fprintf(fdout, "%s", tmpbuf);
15447498SJames.McPherson@Sun.COM } else {
15457498SJames.McPherson@Sun.COM (void) fprintf(fdout, "%s", buf);
15460Sstevel@tonic-gate }
15470Sstevel@tonic-gate
15487498SJames.McPherson@Sun.COM errno = 0;
15497498SJames.McPherson@Sun.COM if (fflush(fdout) != 0) {
15507498SJames.McPherson@Sun.COM logmsg(MSG_ERROR,
15517498SJames.McPherson@Sun.COM gettext("fprintf failed to write to %s: %s (%d)\n"),
15527498SJames.McPherson@Sun.COM fname, strerror(errno), errno);
15537498SJames.McPherson@Sun.COM goto out;
15540Sstevel@tonic-gate }
15550Sstevel@tonic-gate }
15567498SJames.McPherson@Sun.COM out:
15577498SJames.McPherson@Sun.COM (void) fclose(fdin);
15587498SJames.McPherson@Sun.COM (void) fclose(fdout);
15597498SJames.McPherson@Sun.COM free(buf);
15607498SJames.McPherson@Sun.COM free(tmpbuf);
15617498SJames.McPherson@Sun.COM return (errno);
15620Sstevel@tonic-gate }
1563