17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 580ab886dSwesolows * Common Development and Distribution License (the "License"). 680ab886dSwesolows * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 2180ab886dSwesolows 227c478bd9Sstevel@tonic-gate /* 23*5a4c37c9Sqh201292 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <stdio.h> 307c478bd9Sstevel@tonic-gate #include <stdlib.h> 317c478bd9Sstevel@tonic-gate #include <stdarg.h> 327c478bd9Sstevel@tonic-gate #include <sys/types.h> 337c478bd9Sstevel@tonic-gate #include <sys/stat.h> 347c478bd9Sstevel@tonic-gate #include <fcntl.h> 357c478bd9Sstevel@tonic-gate #include <errno.h> 367c478bd9Sstevel@tonic-gate #include <unistd.h> 377c478bd9Sstevel@tonic-gate #include <stropts.h> 387c478bd9Sstevel@tonic-gate #include <strings.h> 397c478bd9Sstevel@tonic-gate #include <dirent.h> 407c478bd9Sstevel@tonic-gate #include <sys/param.h> 417c478bd9Sstevel@tonic-gate #include <sys/scsi/adapters/scsi_vhci.h> 427c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 437c478bd9Sstevel@tonic-gate #include <libgen.h> 447c478bd9Sstevel@tonic-gate #include <dlfcn.h> 457c478bd9Sstevel@tonic-gate #include <link.h> 467c478bd9Sstevel@tonic-gate #include <locale.h> 477c478bd9Sstevel@tonic-gate #include <libintl.h> 487c478bd9Sstevel@tonic-gate #include <sys/syscall.h> 497c478bd9Sstevel@tonic-gate #include <sys/vfstab.h> 507c478bd9Sstevel@tonic-gate #include <sys/mount.h> 517c478bd9Sstevel@tonic-gate #include <devid.h> 527c478bd9Sstevel@tonic-gate #include <sys/libdevid.h> 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #define VHCI_CTL_NODE "/devices/scsi_vhci:devctl" 557c478bd9Sstevel@tonic-gate #define SLASH_DEVICES "/devices/" 56*5a4c37c9Sqh201292 57*5a4c37c9Sqh201292 #ifdef sparc 58*5a4c37c9Sqh201292 #define DISK_NODE_NAME "ssd" 59*5a4c37c9Sqh201292 #define DISK_DRV_NAME "ssd" 60*5a4c37c9Sqh201292 #define SLASH_DISK_AT "/ssd@" 61*5a4c37c9Sqh201292 #define DISK_AT_G "ssd@g" 62*5a4c37c9Sqh201292 #else /* sparc */ 63*5a4c37c9Sqh201292 #define DISK_NODE_NAME "disk" 64*5a4c37c9Sqh201292 #define DISK_DRV_NAME "sd" 65*5a4c37c9Sqh201292 #define SLASH_DISK_AT "/disk@" 66*5a4c37c9Sqh201292 #define DISK_AT_G "disk@g" 67*5a4c37c9Sqh201292 #endif 68*5a4c37c9Sqh201292 697c478bd9Sstevel@tonic-gate #define SLASH_FP_AT "/fp@" 707c478bd9Sstevel@tonic-gate #define SLASH_SCSI_VHCI "/scsi_vhci" 717c478bd9Sstevel@tonic-gate #define DEV_DSK "/dev/dsk/" 727c478bd9Sstevel@tonic-gate #define DEV_RDSK "/dev/rdsk/" 737c478bd9Sstevel@tonic-gate #define SYS_FILENAME_LEN 256 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate /* 767c478bd9Sstevel@tonic-gate * Save directory is the directory in which system files are saved. 777c478bd9Sstevel@tonic-gate * Save directory must be under the root filesystem, as this program is 787c478bd9Sstevel@tonic-gate * typically run before any other filesystems are mounted. 797c478bd9Sstevel@tonic-gate */ 807c478bd9Sstevel@tonic-gate #define SAVE_DIR "/etc/mpxio" 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate /* fcp driver publishes this property */ 837c478bd9Sstevel@tonic-gate #define NODE_WWN_PROP "node-wwn" 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate typedef enum { 867c478bd9Sstevel@tonic-gate CLIENT_TYPE_UNKNOWN, 877c478bd9Sstevel@tonic-gate CLIENT_TYPE_PHCI, 887c478bd9Sstevel@tonic-gate CLIENT_TYPE_VHCI 897c478bd9Sstevel@tonic-gate } client_type_t; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate struct devlink_cbarg { 927c478bd9Sstevel@tonic-gate char *devlink; 937c478bd9Sstevel@tonic-gate size_t len; 947c478bd9Sstevel@tonic-gate }; 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate static di_node_t devinfo_root = DI_NODE_NIL; 977c478bd9Sstevel@tonic-gate static di_devlink_handle_t devlink_hdl = NULL; 987c478bd9Sstevel@tonic-gate static int vhci_fd = -1; 997c478bd9Sstevel@tonic-gate static int patch_vfstab, cap_m_option, debug; 1007c478bd9Sstevel@tonic-gate static int list_option, list_guid_mappings, list_controllernum = -1; 1017c478bd9Sstevel@tonic-gate static char *mapdev = ""; 102*5a4c37c9Sqh201292 static char *map_vhciname = ""; 1037c478bd9Sstevel@tonic-gate static char *stmsboot = "stmsboot"; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate static int make_temp(char *, char *, char *, size_t); 1067c478bd9Sstevel@tonic-gate static void commit_change(char *, char *, char *, int); 1077c478bd9Sstevel@tonic-gate static int map_devname(char *, char *, size_t, int); 1087c478bd9Sstevel@tonic-gate static int update_vfstab(char *, char *); 1097c478bd9Sstevel@tonic-gate static int list_mappings(int, int); 1107c478bd9Sstevel@tonic-gate static int canopen(char *); 1117c478bd9Sstevel@tonic-gate static void logerr(char *, ...); 1127c478bd9Sstevel@tonic-gate static void logdmsg(char *, ...); 1137c478bd9Sstevel@tonic-gate static void *s_malloc(const size_t); 1147c478bd9Sstevel@tonic-gate static char *s_strdup(const char *); 1157c478bd9Sstevel@tonic-gate static void s_strlcpy(char *, const char *, size_t); 116264d6c47Seota /* 117264d6c47Seota * Using an exit function not marked __NORETURN causes a warning with gcc. 118264d6c47Seota * To suppress the warning, use __NORETURN attribute. 119264d6c47Seota */ 120264d6c47Seota static void clean_exit(int)__NORETURN; 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate /* 1237c478bd9Sstevel@tonic-gate * Print usage and exit. 1247c478bd9Sstevel@tonic-gate */ 1257c478bd9Sstevel@tonic-gate static void 1267c478bd9Sstevel@tonic-gate usage(char *argv0) 1277c478bd9Sstevel@tonic-gate { 1287c478bd9Sstevel@tonic-gate char *progname; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate progname = strrchr(argv0, '/'); 1317c478bd9Sstevel@tonic-gate if (progname != NULL) 1327c478bd9Sstevel@tonic-gate progname++; 1337c478bd9Sstevel@tonic-gate else 1347c478bd9Sstevel@tonic-gate progname = argv0; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate /* 1377c478bd9Sstevel@tonic-gate * -u update /etc/vfstab 1387c478bd9Sstevel@tonic-gate * -m devname 1397c478bd9Sstevel@tonic-gate * if devname is phci based name and not open-able, map it to 1407c478bd9Sstevel@tonic-gate * vhci based /devices name. 1417c478bd9Sstevel@tonic-gate * if devname is vhci based name and not open-able, map it to 1427c478bd9Sstevel@tonic-gate * phci based /devices name. 1437c478bd9Sstevel@tonic-gate * -M devname 1447c478bd9Sstevel@tonic-gate * same as -m except that /dev link is printed instead of 1457c478bd9Sstevel@tonic-gate * /devices name. 1467c478bd9Sstevel@tonic-gate * -l controller 1477c478bd9Sstevel@tonic-gate * list non-STMS to STMS device name mappings for the specific 1487c478bd9Sstevel@tonic-gate * controller 1497c478bd9Sstevel@tonic-gate * -L list non-STMS to STMS device name mappings for all controllers 150*5a4c37c9Sqh201292 * -p devname 151*5a4c37c9Sqh201292 * if devname is vhci based name and open-able, get the first 152*5a4c37c9Sqh201292 * onlined phci based name without /devices prefix. 153*5a4c37c9Sqh201292 * Used in stmsboot to update the phci based bootpath. 1547c478bd9Sstevel@tonic-gate */ 1557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("usage: %s -u | -m devname | " 156*5a4c37c9Sqh201292 "-M devname | -l controller | -L | -p devname\n"), progname); 1577c478bd9Sstevel@tonic-gate exit(2); 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate /* 1617c478bd9Sstevel@tonic-gate * Parse command line arguments. 1627c478bd9Sstevel@tonic-gate */ 1637c478bd9Sstevel@tonic-gate static void 1647c478bd9Sstevel@tonic-gate parse_args(int argc, char *argv[]) 1657c478bd9Sstevel@tonic-gate { 1667c478bd9Sstevel@tonic-gate char opt; 1677c478bd9Sstevel@tonic-gate int n = 0; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate if (argc == 1) { 1707c478bd9Sstevel@tonic-gate usage(argv[0]); 1717c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate 174*5a4c37c9Sqh201292 while ((opt = getopt(argc, argv, "udm:M:Ll:gp:")) != EOF) { 1757c478bd9Sstevel@tonic-gate switch (opt) { 1767c478bd9Sstevel@tonic-gate case 'u': 1777c478bd9Sstevel@tonic-gate patch_vfstab = 1; 1787c478bd9Sstevel@tonic-gate n++; 1797c478bd9Sstevel@tonic-gate break; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate case 'd': 1827c478bd9Sstevel@tonic-gate debug = 1; 1837c478bd9Sstevel@tonic-gate break; 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate case 'm': 1867c478bd9Sstevel@tonic-gate mapdev = s_strdup(optarg); 1877c478bd9Sstevel@tonic-gate n++; 1887c478bd9Sstevel@tonic-gate break; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate case 'M': 1917c478bd9Sstevel@tonic-gate mapdev = s_strdup(optarg); 1927c478bd9Sstevel@tonic-gate cap_m_option = 1; 1937c478bd9Sstevel@tonic-gate n++; 1947c478bd9Sstevel@tonic-gate break; 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate case 'L': 1977c478bd9Sstevel@tonic-gate list_option = 1; 1987c478bd9Sstevel@tonic-gate n++; 1997c478bd9Sstevel@tonic-gate break; 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate case 'l': 2027c478bd9Sstevel@tonic-gate list_option = 1; 2037c478bd9Sstevel@tonic-gate list_controllernum = (int)atol(optarg); 2047c478bd9Sstevel@tonic-gate if (list_controllernum < 0) { 2057c478bd9Sstevel@tonic-gate logerr(gettext("controller number %d is " 2067c478bd9Sstevel@tonic-gate "invalid\n"), list_controllernum); 2077c478bd9Sstevel@tonic-gate clean_exit(1); 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate n++; 2107c478bd9Sstevel@tonic-gate break; 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate case 'g': 2137c478bd9Sstevel@tonic-gate /* 2147c478bd9Sstevel@tonic-gate * private option to display non-STMS device name 2157c478bd9Sstevel@tonic-gate * to GUID mappings. 2167c478bd9Sstevel@tonic-gate */ 2177c478bd9Sstevel@tonic-gate list_guid_mappings = 1; 2187c478bd9Sstevel@tonic-gate n++; 2197c478bd9Sstevel@tonic-gate break; 220*5a4c37c9Sqh201292 case 'p': 221*5a4c37c9Sqh201292 /* 222*5a4c37c9Sqh201292 * map openable vhci based name to phci base name 223*5a4c37c9Sqh201292 */ 224*5a4c37c9Sqh201292 map_vhciname = s_strdup(optarg); 225*5a4c37c9Sqh201292 n++; 226*5a4c37c9Sqh201292 break; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate default: 2297c478bd9Sstevel@tonic-gate usage(argv[0]); 2307c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate if (n != 1) 2357c478bd9Sstevel@tonic-gate usage(argv[0]); 2367c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 23980ab886dSwesolows int 2407c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 2417c478bd9Sstevel@tonic-gate { 2427c478bd9Sstevel@tonic-gate char save_vfstab[SYS_FILENAME_LEN], tmp_vfstab[SYS_FILENAME_LEN]; 2437c478bd9Sstevel@tonic-gate int vfstab_updated; 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 2467c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate if (getuid() != 0) { 2497c478bd9Sstevel@tonic-gate logerr(gettext("must be super-user to run this program\n")); 2507c478bd9Sstevel@tonic-gate clean_exit(1); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate parse_args(argc, argv); 2547c478bd9Sstevel@tonic-gate (void) umask(022); 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * NOTE: The mpxio boot-up script executes this program with the 2587c478bd9Sstevel@tonic-gate * mapping (-m) option before the /usr is even mounted and when the 2597c478bd9Sstevel@tonic-gate * root filesystem is still mounted read-only. 2607c478bd9Sstevel@tonic-gate */ 2617c478bd9Sstevel@tonic-gate if (*mapdev != '\0') { 2627c478bd9Sstevel@tonic-gate char newname[MAXPATHLEN]; 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate if (map_devname(mapdev, newname, sizeof (newname), 2657c478bd9Sstevel@tonic-gate cap_m_option) == 0) { 2667c478bd9Sstevel@tonic-gate (void) printf("%s\n", newname); 2677c478bd9Sstevel@tonic-gate clean_exit(0); 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate clean_exit(1); 2707c478bd9Sstevel@tonic-gate } 271*5a4c37c9Sqh201292 if (*map_vhciname != '\0') { 272*5a4c37c9Sqh201292 char newname[MAXPATHLEN]; 273*5a4c37c9Sqh201292 274*5a4c37c9Sqh201292 if (map_openable_vhciname(map_vhciname, newname, 275*5a4c37c9Sqh201292 sizeof (newname)) == 0) { 276*5a4c37c9Sqh201292 (void) printf("%s\n", newname); 277*5a4c37c9Sqh201292 clean_exit(0); 278*5a4c37c9Sqh201292 } 279*5a4c37c9Sqh201292 clean_exit(1); 280*5a4c37c9Sqh201292 } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate if (list_option || list_guid_mappings) { 2837c478bd9Sstevel@tonic-gate if (list_mappings(list_controllernum, list_guid_mappings) == 0) 2847c478bd9Sstevel@tonic-gate clean_exit(0); 2857c478bd9Sstevel@tonic-gate clean_exit(1); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate /* create a directory where a copy of the system files are saved */ 2897c478bd9Sstevel@tonic-gate if (patch_vfstab) { 2907c478bd9Sstevel@tonic-gate if (mkdirp(SAVE_DIR, 0755) != 0 && errno != EEXIST) { 2917c478bd9Sstevel@tonic-gate logerr(gettext("mkdirp: failed to create %1$s: %2$s\n"), 2927c478bd9Sstevel@tonic-gate SAVE_DIR, strerror(errno)); 2937c478bd9Sstevel@tonic-gate clean_exit(1); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate if (make_temp(VFSTAB, save_vfstab, tmp_vfstab, 2977c478bd9Sstevel@tonic-gate SYS_FILENAME_LEN) != 0) 2987c478bd9Sstevel@tonic-gate clean_exit(1); 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate /* build new vfstab without modifying the existing one */ 3017c478bd9Sstevel@tonic-gate if ((vfstab_updated = update_vfstab(VFSTAB, tmp_vfstab)) 3027c478bd9Sstevel@tonic-gate == -1) { 3037c478bd9Sstevel@tonic-gate logerr(gettext("failed to update %s\n"), VFSTAB); 3047c478bd9Sstevel@tonic-gate clean_exit(1); 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate commit_change(VFSTAB, save_vfstab, tmp_vfstab, vfstab_updated); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate clean_exit(0); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate /* 3147c478bd9Sstevel@tonic-gate * Make saved and temporary filenames in SAVE_DIR. 3157c478bd9Sstevel@tonic-gate * 3167c478bd9Sstevel@tonic-gate * ex: if the filename is /etc/vfstab then the save_filename and tmp_filename 3177c478bd9Sstevel@tonic-gate * would be SAVE_DIR/vfstab and SAVE_DIR/vfstab.tmp respectively. 3187c478bd9Sstevel@tonic-gate * 3197c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 3207c478bd9Sstevel@tonic-gate */ 3217c478bd9Sstevel@tonic-gate static int 3227c478bd9Sstevel@tonic-gate make_temp(char *filename, char *save_filename, char *tmp_filename, size_t len) 3237c478bd9Sstevel@tonic-gate { 3247c478bd9Sstevel@tonic-gate char *ptr; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate if ((ptr = strrchr(filename, '/')) == NULL) { 3277c478bd9Sstevel@tonic-gate logdmsg("invalid file %s\n", filename); 3287c478bd9Sstevel@tonic-gate return (-1); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate (void) snprintf(save_filename, len, "%s%s", SAVE_DIR, ptr); 3317c478bd9Sstevel@tonic-gate (void) snprintf(tmp_filename, len, "%s%s.tmp", SAVE_DIR, ptr); 3327c478bd9Sstevel@tonic-gate logdmsg("make_temp: %s: save = %s, temp = %s\n", filename, 3337c478bd9Sstevel@tonic-gate save_filename, tmp_filename); 3347c478bd9Sstevel@tonic-gate return (0); 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate /* 3387c478bd9Sstevel@tonic-gate * Commit the changes made to the system file 3397c478bd9Sstevel@tonic-gate */ 3407c478bd9Sstevel@tonic-gate static void 3417c478bd9Sstevel@tonic-gate commit_change(char *filename, char *save_filename, char *tmp_filename, 3427c478bd9Sstevel@tonic-gate int updated) 3437c478bd9Sstevel@tonic-gate { 3447c478bd9Sstevel@tonic-gate int x; 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate if (updated) { 3477c478bd9Sstevel@tonic-gate /* save the original */ 3487c478bd9Sstevel@tonic-gate if ((x = rename(filename, save_filename)) != 0) { 3497c478bd9Sstevel@tonic-gate logerr(gettext("rename %1$s to %2$s failed: %3$s\n"), 3507c478bd9Sstevel@tonic-gate filename, save_filename, strerror(errno)); 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate /* now rename the new file to the actual file */ 3547c478bd9Sstevel@tonic-gate if (rename(tmp_filename, filename) != 0) { 3557c478bd9Sstevel@tonic-gate logerr(gettext("rename %1$s to %2$s failed: %3$s\n"), 3567c478bd9Sstevel@tonic-gate tmp_filename, filename, strerror(errno)); 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate /* restore the original */ 3597c478bd9Sstevel@tonic-gate if (x == 0 && rename(save_filename, filename) != 0) { 3607c478bd9Sstevel@tonic-gate logerr( 3617c478bd9Sstevel@tonic-gate gettext("rename %1$s to %2$s failed: %3$s\n" 3627c478bd9Sstevel@tonic-gate "%4$s is a copy of the original %5$s file" 3637c478bd9Sstevel@tonic-gate "\n"), 3647c478bd9Sstevel@tonic-gate save_filename, filename, strerror(errno), 3657c478bd9Sstevel@tonic-gate save_filename, filename); 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate } else 3687c478bd9Sstevel@tonic-gate (void) printf(gettext("%1$s: %2$s has been updated.\n"), 3697c478bd9Sstevel@tonic-gate stmsboot, filename); 3707c478bd9Sstevel@tonic-gate } else { 3717c478bd9Sstevel@tonic-gate /* remove the temp file */ 3727c478bd9Sstevel@tonic-gate (void) unlink(tmp_filename); 3737c478bd9Sstevel@tonic-gate (void) printf(gettext("%1$s: %2$s was not modified as no " 3747c478bd9Sstevel@tonic-gate "changes were needed.\n"), stmsboot, filename); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * Get the GUID of the device. 3807c478bd9Sstevel@tonic-gate * 3817c478bd9Sstevel@tonic-gate * physpath /devices name without the /devices prefix and minor name 3827c478bd9Sstevel@tonic-gate * component. 3837c478bd9Sstevel@tonic-gate * guid caller supplied buffer where the GUID will be placed on return 3847c478bd9Sstevel@tonic-gate * guid_len length of the caller supplied guid buffer. 3857c478bd9Sstevel@tonic-gate * no_dealy_flag if set open the device with O_NDELAY 3867c478bd9Sstevel@tonic-gate * node di_node corresponding to physpath if already available, 3877c478bd9Sstevel@tonic-gate * otherwise pass DI_NODE_NIL. 3887c478bd9Sstevel@tonic-gate * 3897c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 3907c478bd9Sstevel@tonic-gate */ 3917c478bd9Sstevel@tonic-gate static int 3927c478bd9Sstevel@tonic-gate get_guid(char *physpath, char *guid, int guid_len, int no_delay_flag, 3937c478bd9Sstevel@tonic-gate di_node_t node) 3947c478bd9Sstevel@tonic-gate { 3957c478bd9Sstevel@tonic-gate int fd; 3967c478bd9Sstevel@tonic-gate ddi_devid_t devid; 3977c478bd9Sstevel@tonic-gate int rv = -1; 3987c478bd9Sstevel@tonic-gate char *i_guid = NULL; 3997c478bd9Sstevel@tonic-gate char physpath_raw[MAXPATHLEN]; 4007c478bd9Sstevel@tonic-gate uchar_t *wwnp; 4017c478bd9Sstevel@tonic-gate int i, n, snapshot_taken = 0; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate logdmsg("get_guid: physpath = %s\n", physpath); 4047c478bd9Sstevel@tonic-gate 405*5a4c37c9Sqh201292 #ifdef sparc 4067c478bd9Sstevel@tonic-gate (void) snprintf(physpath_raw, MAXPATHLEN, 4077c478bd9Sstevel@tonic-gate "/devices%s:a,raw", physpath); 408*5a4c37c9Sqh201292 #else 409*5a4c37c9Sqh201292 (void) snprintf(physpath_raw, MAXPATHLEN, 410*5a4c37c9Sqh201292 "/devices%s:c,raw", physpath); 411*5a4c37c9Sqh201292 #endif 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate *guid = '\0'; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate if (no_delay_flag) 4167c478bd9Sstevel@tonic-gate no_delay_flag = O_NDELAY; 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate /* 4197c478bd9Sstevel@tonic-gate * Open the raw device 4207c478bd9Sstevel@tonic-gate * Without the O_DELAY flag, the open will fail on standby paths of 4217c478bd9Sstevel@tonic-gate * T3 if its mp_support mode is "mpxio". 4227c478bd9Sstevel@tonic-gate */ 4237c478bd9Sstevel@tonic-gate if ((fd = open(physpath_raw, O_RDONLY | no_delay_flag)) == -1) { 4247c478bd9Sstevel@tonic-gate logdmsg("get_guid: failed to open %s: %s\n", physpath_raw, 4257c478bd9Sstevel@tonic-gate strerror(errno)); 4267c478bd9Sstevel@tonic-gate return (-1); 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate if (devid_get(fd, &devid) == 0) { 4307c478bd9Sstevel@tonic-gate i_guid = devid_to_guid(devid); 4317c478bd9Sstevel@tonic-gate devid_free(devid); 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate if (i_guid != NULL) { 4347c478bd9Sstevel@tonic-gate s_strlcpy(guid, i_guid, guid_len); 4357c478bd9Sstevel@tonic-gate devid_free_guid(i_guid); 4367c478bd9Sstevel@tonic-gate rv = 0; 4377c478bd9Sstevel@tonic-gate goto out; 4387c478bd9Sstevel@tonic-gate } else 4397c478bd9Sstevel@tonic-gate logdmsg("get_guid: devid_to_guid() failed\n"); 4407c478bd9Sstevel@tonic-gate } else 4417c478bd9Sstevel@tonic-gate logdmsg("get_guid: devid_get() failed: %s\n", strerror(errno)); 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate /* fallback to node name as the guid as this is what fcp driver does */ 4447c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 4457c478bd9Sstevel@tonic-gate if ((node = di_init(physpath, DINFOCPYALL | DINFOFORCE)) 4467c478bd9Sstevel@tonic-gate == DI_NODE_NIL) { 4477c478bd9Sstevel@tonic-gate logdmsg("get_guid: di_init on %s failed: %s\n", 4487c478bd9Sstevel@tonic-gate physpath, strerror(errno)); 4497c478bd9Sstevel@tonic-gate goto out; 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate snapshot_taken = 1; 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate if ((n = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, NODE_WWN_PROP, 4557c478bd9Sstevel@tonic-gate &wwnp)) == -1) { 4567c478bd9Sstevel@tonic-gate logdmsg("get_guid: di_prop_lookup_bytes() failed to lookup " 4577c478bd9Sstevel@tonic-gate "%s: %s\n", NODE_WWN_PROP, strerror(errno)); 4587c478bd9Sstevel@tonic-gate goto out; 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate if (guid_len >= ((n * 2) + 1)) { 4627c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) { 4637c478bd9Sstevel@tonic-gate (void) sprintf(guid + (i * 2), "%02x", (uint_t)(*wwnp)); 4647c478bd9Sstevel@tonic-gate wwnp++; 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate rv = 0; 4677c478bd9Sstevel@tonic-gate } else 4687c478bd9Sstevel@tonic-gate logerr(gettext("insufficient buffer size: need %1$d " 4697c478bd9Sstevel@tonic-gate "bytes, passed %2$d bytes\n"), (n * 2) + 1, guid_len); 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate out: 4727c478bd9Sstevel@tonic-gate if (snapshot_taken) 4737c478bd9Sstevel@tonic-gate di_fini(node); 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate (void) close(fd); 4767c478bd9Sstevel@tonic-gate logdmsg("get_guid: GUID = %s\n", guid); 4777c478bd9Sstevel@tonic-gate return (rv); 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate /* 4817c478bd9Sstevel@tonic-gate * Given client_name return whether it is a phci or vhci based name. 4827c478bd9Sstevel@tonic-gate * client_name is /devices name of a client without the /devices prefix. 4837c478bd9Sstevel@tonic-gate * 4847c478bd9Sstevel@tonic-gate * client_name Return value 485*5a4c37c9Sqh201292 * on sparc: 4867c478bd9Sstevel@tonic-gate * .../fp@xxx/ssd@yyy CLIENT_TYPE_PHCI 4877c478bd9Sstevel@tonic-gate * .../scsi_vhci/ssd@yyy CLIENT_TYPE_VHCI 4887c478bd9Sstevel@tonic-gate * other CLIENT_TYPE_UNKNOWN 489*5a4c37c9Sqh201292 * on x86: 490*5a4c37c9Sqh201292 * .../fp@xxx/disk@yyy CLIENT_TYPE_PHCI 491*5a4c37c9Sqh201292 * .../scsi_vhci/disk@yyy CLIENT_TYPE_VHCI 492*5a4c37c9Sqh201292 * other CLIENT_TYPE_UNKNOWN 4937c478bd9Sstevel@tonic-gate */ 4947c478bd9Sstevel@tonic-gate static client_type_t 4957c478bd9Sstevel@tonic-gate client_name_type(char *client_name) 4967c478bd9Sstevel@tonic-gate { 4977c478bd9Sstevel@tonic-gate client_type_t client_type = CLIENT_TYPE_UNKNOWN; 4987c478bd9Sstevel@tonic-gate char *p1, *p2; 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate if (*client_name != '/') 5017c478bd9Sstevel@tonic-gate return (CLIENT_TYPE_UNKNOWN); 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate if ((p1 = strrchr(client_name, '/')) == NULL || 504*5a4c37c9Sqh201292 strncmp(p1, SLASH_DISK_AT, sizeof (SLASH_DISK_AT) - 1) != 0) 5057c478bd9Sstevel@tonic-gate return (CLIENT_TYPE_UNKNOWN); 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate *p1 = '\0'; 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate if ((p2 = strrchr(client_name, '/')) != NULL) { 5107c478bd9Sstevel@tonic-gate if (strncmp(p2, SLASH_FP_AT, sizeof (SLASH_FP_AT) - 1) == 0) 5117c478bd9Sstevel@tonic-gate client_type = CLIENT_TYPE_PHCI; 5127c478bd9Sstevel@tonic-gate else if (strncmp(p2, SLASH_SCSI_VHCI, 5137c478bd9Sstevel@tonic-gate sizeof (SLASH_SCSI_VHCI) - 1) == 0) 5147c478bd9Sstevel@tonic-gate client_type = CLIENT_TYPE_VHCI; 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate *p1 = '/'; 5187c478bd9Sstevel@tonic-gate return (client_type); 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate /* 5227c478bd9Sstevel@tonic-gate * Map phci based client name to vhci based client name. 5237c478bd9Sstevel@tonic-gate * 5247c478bd9Sstevel@tonic-gate * phci_name 5257c478bd9Sstevel@tonic-gate * phci based client /devices name without the /devices prefix and 5267c478bd9Sstevel@tonic-gate * minor name component. 527*5a4c37c9Sqh201292 * ex: 528*5a4c37c9Sqh201292 * for sparc: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0 529*5a4c37c9Sqh201292 * for x86: /pci@8,600000/SUNW,qlc@4/fp@0,0/disk@w2100002037cd9f72,0 5307c478bd9Sstevel@tonic-gate * 5317c478bd9Sstevel@tonic-gate * vhci_name 5327c478bd9Sstevel@tonic-gate * Caller supplied buffer where vhci /devices name will be placed on 5337c478bd9Sstevel@tonic-gate * return (without the /devices prefix and minor name component). 534*5a4c37c9Sqh201292 * ex: 535*5a4c37c9Sqh201292 * for sparc: /scsi_vhci/ssd@g2000002037cd9f72 536*5a4c37c9Sqh201292 * for x86: /scsi_vhci/disk@g2000002037cd9f72 5377c478bd9Sstevel@tonic-gate * 5387c478bd9Sstevel@tonic-gate * vhci_name_len 5397c478bd9Sstevel@tonic-gate * Length of the caller supplied vhci_name buffer. 5407c478bd9Sstevel@tonic-gate * 5417c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 5427c478bd9Sstevel@tonic-gate */ 5437c478bd9Sstevel@tonic-gate static int 5447c478bd9Sstevel@tonic-gate phci_to_vhci(char *phci_name, char *vhci_name, size_t vhci_name_len) 5457c478bd9Sstevel@tonic-gate { 5467c478bd9Sstevel@tonic-gate sv_iocdata_t ioc; 5477c478bd9Sstevel@tonic-gate char *slash; 5487c478bd9Sstevel@tonic-gate char vhci_name_buf[MAXPATHLEN]; 5497c478bd9Sstevel@tonic-gate char phci_name_buf[MAXPATHLEN]; 5507c478bd9Sstevel@tonic-gate char addr_buf[MAXNAMELEN]; 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate logdmsg("phci_to_vhci: client = %s\n", phci_name); 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate s_strlcpy(phci_name_buf, phci_name, MAXPATHLEN); 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate if (client_name_type(phci_name_buf) != CLIENT_TYPE_PHCI || 5577c478bd9Sstevel@tonic-gate (slash = strrchr(phci_name_buf, '/')) == NULL || 558*5a4c37c9Sqh201292 strncmp(slash, SLASH_DISK_AT, sizeof (SLASH_DISK_AT) - 1) != 0) { 5597c478bd9Sstevel@tonic-gate logdmsg("phci_to_vhci: %s is not of CLIENT_TYPE_PHCI\n", 5607c478bd9Sstevel@tonic-gate phci_name); 5617c478bd9Sstevel@tonic-gate return (-1); 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate if (vhci_fd < 0) { 5657c478bd9Sstevel@tonic-gate if ((vhci_fd = open(VHCI_CTL_NODE, O_RDWR)) < 0) 5667c478bd9Sstevel@tonic-gate return (-1); 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate *slash = '\0'; 570*5a4c37c9Sqh201292 s_strlcpy(addr_buf, slash + sizeof (SLASH_DISK_AT) - 1, MAXNAMELEN); 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate bzero(&ioc, sizeof (sv_iocdata_t)); 5737c478bd9Sstevel@tonic-gate ioc.client = vhci_name_buf; 5747c478bd9Sstevel@tonic-gate ioc.phci = phci_name_buf; 5757c478bd9Sstevel@tonic-gate ioc.addr = addr_buf; 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate if (ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_NAME, &ioc) != 0) { 5787c478bd9Sstevel@tonic-gate logdmsg("SCSI_VHCI_GET_CLIENT_NAME on %s " 5797c478bd9Sstevel@tonic-gate "failed: %s\n", phci_name, strerror(errno)); 5807c478bd9Sstevel@tonic-gate return (-1); 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate s_strlcpy(vhci_name, vhci_name_buf, vhci_name_len); 5847c478bd9Sstevel@tonic-gate logdmsg("phci_to_vhci: %s maps to %s\n", phci_name, vhci_name); 5857c478bd9Sstevel@tonic-gate return (0); 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate /* 5897c478bd9Sstevel@tonic-gate * Map vhci based client name to phci based client name. 5907c478bd9Sstevel@tonic-gate * If the client has multiple paths, only one of the paths with which client 5917c478bd9Sstevel@tonic-gate * can be accessed is returned. This function does not use SCSI_VHCI ioctls 5927c478bd9Sstevel@tonic-gate * as it is called on mpxio disabled paths. 5937c478bd9Sstevel@tonic-gate * 5947c478bd9Sstevel@tonic-gate * vhci_name 5957c478bd9Sstevel@tonic-gate * vhci based client /devices name without the /devices prefix and 5967c478bd9Sstevel@tonic-gate * minor name component. 597*5a4c37c9Sqh201292 * ex: 598*5a4c37c9Sqh201292 * sparc: /scsi_vhci/ssd@g2000002037cd9f72 599*5a4c37c9Sqh201292 * x86: /scsi_vhci/disk@g2000002037cd9f72 6007c478bd9Sstevel@tonic-gate * 6017c478bd9Sstevel@tonic-gate * phci_name 6027c478bd9Sstevel@tonic-gate * Caller supplied buffer where phci /devices name will be placed on 6037c478bd9Sstevel@tonic-gate * return (without the /devices prefix and minor name component). 604*5a4c37c9Sqh201292 * ex: 605*5a4c37c9Sqh201292 * sparc: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0 606*5a4c37c9Sqh201292 * x86: /pci@8,600000/SUNW,qlc@4/fp@0,0/disk@w2100002037cd9f72,0 6077c478bd9Sstevel@tonic-gate * 6087c478bd9Sstevel@tonic-gate * phci_name_len 6097c478bd9Sstevel@tonic-gate * Length of the caller supplied phci_name buffer. 6107c478bd9Sstevel@tonic-gate * 6117c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 6127c478bd9Sstevel@tonic-gate */ 6137c478bd9Sstevel@tonic-gate static int 6147c478bd9Sstevel@tonic-gate vhci_to_phci(char *vhci_name, char *phci_name, size_t phci_name_len) 6157c478bd9Sstevel@tonic-gate { 6167c478bd9Sstevel@tonic-gate di_node_t node, parent; 6177c478bd9Sstevel@tonic-gate char *vhci_guid, *devfspath; 6187c478bd9Sstevel@tonic-gate char phci_guid[MAXPATHLEN]; 6197c478bd9Sstevel@tonic-gate char *parent_name, *node_name; 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: client = %s\n", vhci_name); 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate if (client_name_type(vhci_name) != CLIENT_TYPE_VHCI) { 6247c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: %s is not of CLIENT_TYPE_VHCI\n", 6257c478bd9Sstevel@tonic-gate vhci_name); 6267c478bd9Sstevel@tonic-gate return (-1); 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate if ((vhci_guid = strrchr(vhci_name, '@')) == NULL || 6307c478bd9Sstevel@tonic-gate *(++vhci_guid) != 'g') { 6317c478bd9Sstevel@tonic-gate logerr(gettext("couldn't get guid from %s\n"), vhci_name); 6327c478bd9Sstevel@tonic-gate return (-1); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate /* point to guid */ 6367c478bd9Sstevel@tonic-gate ++vhci_guid; 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate /* 6397c478bd9Sstevel@tonic-gate * Get devinfo snapshot and walk all ssd nodes whose parent is fp. 6407c478bd9Sstevel@tonic-gate * For each node get the guid and match it with vhci_guid. 6417c478bd9Sstevel@tonic-gate */ 6427c478bd9Sstevel@tonic-gate if (devinfo_root == DI_NODE_NIL) { 6437c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: taking devinfo snapshot\n"); 6447c478bd9Sstevel@tonic-gate if ((devinfo_root = di_init("/", DINFOCPYALL | DINFOFORCE)) 6457c478bd9Sstevel@tonic-gate == DI_NODE_NIL) { 6467c478bd9Sstevel@tonic-gate logerr(gettext("di_init failed: %s\n"), 6477c478bd9Sstevel@tonic-gate strerror(errno)); 6487c478bd9Sstevel@tonic-gate return (-1); 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: done taking devinfo snapshot\n"); 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 653*5a4c37c9Sqh201292 for (node = di_drv_first_node(DISK_DRV_NAME, devinfo_root); 6547c478bd9Sstevel@tonic-gate node != DI_NODE_NIL; node = di_drv_next_node(node)) { 6557c478bd9Sstevel@tonic-gate if ((node_name = di_node_name(node)) == NULL || 656*5a4c37c9Sqh201292 strcmp(node_name, DISK_NODE_NAME) != 0 || 6577c478bd9Sstevel@tonic-gate (parent = di_parent_node(node)) == DI_NODE_NIL || 6587c478bd9Sstevel@tonic-gate (parent_name = di_node_name(parent)) == NULL || 6597c478bd9Sstevel@tonic-gate strcmp(parent_name, "fp") != 0 || 6607c478bd9Sstevel@tonic-gate (devfspath = di_devfs_path(node)) == NULL) 6617c478bd9Sstevel@tonic-gate continue; 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate /* 6647c478bd9Sstevel@tonic-gate * Don't set no_delay_flag to have get_guid() fail on 6657c478bd9Sstevel@tonic-gate * standby paths of T3. So we'll find the preferred paths. 6667c478bd9Sstevel@tonic-gate */ 6677c478bd9Sstevel@tonic-gate if (get_guid(devfspath, phci_guid, 6687c478bd9Sstevel@tonic-gate sizeof (phci_guid), 0, node) == 0 && 6697c478bd9Sstevel@tonic-gate strcmp(phci_guid, vhci_guid) == 0) { 6707c478bd9Sstevel@tonic-gate s_strlcpy(phci_name, devfspath, phci_name_len); 6717c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 6727c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: %s maps to %s\n", vhci_name, 6737c478bd9Sstevel@tonic-gate phci_name); 6747c478bd9Sstevel@tonic-gate return (0); 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 6787c478bd9Sstevel@tonic-gate } 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: couldn't get phci name for %s\n", vhci_name); 6817c478bd9Sstevel@tonic-gate return (-1); 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate /* 685*5a4c37c9Sqh201292 * Map vhci based client name to phci based client name. 686*5a4c37c9Sqh201292 * If the client has multiple paths, only one of the paths with which client 687*5a4c37c9Sqh201292 * can be accessed is returned. 688*5a4c37c9Sqh201292 * This function uses SCSI_VHCI ioctls to get the phci paths 689*5a4c37c9Sqh201292 * 690*5a4c37c9Sqh201292 * vhci_name 691*5a4c37c9Sqh201292 * vhci based client /devices name without the /devices prefix and 692*5a4c37c9Sqh201292 * minor name component. 693*5a4c37c9Sqh201292 * ex: 694*5a4c37c9Sqh201292 * sparc: /scsi_vhci/ssd@g2000002037cd9f72 695*5a4c37c9Sqh201292 * x86: /scsi_vhci/disk@g2000002037cd9f72 696*5a4c37c9Sqh201292 * 697*5a4c37c9Sqh201292 * phci_name 698*5a4c37c9Sqh201292 * Caller supplied buffer where phci /devices name will be placed on 699*5a4c37c9Sqh201292 * return (without the /devices prefix and minor name component). 700*5a4c37c9Sqh201292 * ex: 701*5a4c37c9Sqh201292 * sparc: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0 702*5a4c37c9Sqh201292 * x86: /pci@8,600000/SUNW,qlc@4/fp@0,0/disk@w2100002037cd9f72,0 703*5a4c37c9Sqh201292 * 704*5a4c37c9Sqh201292 * phci_name_len 705*5a4c37c9Sqh201292 * Length of the caller supplied phci_name buffer. 706*5a4c37c9Sqh201292 * 707*5a4c37c9Sqh201292 * Returns 0 on success, -1 on failure. 708*5a4c37c9Sqh201292 */ 709*5a4c37c9Sqh201292 710*5a4c37c9Sqh201292 static int 711*5a4c37c9Sqh201292 vhci_to_phci_by_ioctl(char *vhci_name, char *phci_name, size_t phci_name_len) 712*5a4c37c9Sqh201292 { 713*5a4c37c9Sqh201292 sv_iocdata_t ioc; 714*5a4c37c9Sqh201292 uint_t npaths; 715*5a4c37c9Sqh201292 char *node_name, *at; 716*5a4c37c9Sqh201292 char vhci_name_buf[MAXPATHLEN]; 717*5a4c37c9Sqh201292 int ret; 718*5a4c37c9Sqh201292 sv_path_info_t *pi; 719*5a4c37c9Sqh201292 720*5a4c37c9Sqh201292 logdmsg("vhci_to_phci_by_ioctl: client = %s\n", vhci_name); 721*5a4c37c9Sqh201292 722*5a4c37c9Sqh201292 if (vhci_fd < 0) { 723*5a4c37c9Sqh201292 if ((vhci_fd = open(VHCI_CTL_NODE, O_RDWR)) < 0) 724*5a4c37c9Sqh201292 return (-1); 725*5a4c37c9Sqh201292 } 726*5a4c37c9Sqh201292 727*5a4c37c9Sqh201292 (void) strlcpy(vhci_name_buf, vhci_name, MAXPATHLEN); 728*5a4c37c9Sqh201292 729*5a4c37c9Sqh201292 /* first get the number paths */ 730*5a4c37c9Sqh201292 bzero(&ioc, sizeof (sv_iocdata_t)); 731*5a4c37c9Sqh201292 ioc.client = vhci_name_buf; 732*5a4c37c9Sqh201292 ioc.ret_elem = &npaths; 733*5a4c37c9Sqh201292 if ((ret = ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, 734*5a4c37c9Sqh201292 &ioc)) != 0 || npaths == 0) { 735*5a4c37c9Sqh201292 logdmsg("SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO on %s " 736*5a4c37c9Sqh201292 "failed: %s\n", vhci_name, 737*5a4c37c9Sqh201292 ret?strerror(errno):"got 0 paths"); 738*5a4c37c9Sqh201292 return (-1); 739*5a4c37c9Sqh201292 } 740*5a4c37c9Sqh201292 741*5a4c37c9Sqh201292 /* now allocate memory for the path information and get all paths */ 742*5a4c37c9Sqh201292 bzero(&ioc, sizeof (sv_iocdata_t)); 743*5a4c37c9Sqh201292 ioc.client = vhci_name_buf; 744*5a4c37c9Sqh201292 ioc.buf_elem = npaths; 745*5a4c37c9Sqh201292 ioc.ret_elem = &npaths; 746*5a4c37c9Sqh201292 if ((ioc.ret_buf = (sv_path_info_t *)calloc(npaths, 747*5a4c37c9Sqh201292 sizeof (sv_path_info_t))) == NULL) 748*5a4c37c9Sqh201292 return (-1); 749*5a4c37c9Sqh201292 if ((ret = ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, 750*5a4c37c9Sqh201292 &ioc)) != 0 || npaths == 0) { 751*5a4c37c9Sqh201292 logdmsg("SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO on %s " 752*5a4c37c9Sqh201292 "failed: %s\n", vhci_name, 753*5a4c37c9Sqh201292 ret?strerror(errno):"got 0 paths"); 754*5a4c37c9Sqh201292 goto out; 755*5a4c37c9Sqh201292 } 756*5a4c37c9Sqh201292 757*5a4c37c9Sqh201292 if (ioc.buf_elem < npaths) 758*5a4c37c9Sqh201292 npaths = ioc.buf_elem; 759*5a4c37c9Sqh201292 if ((node_name = strrchr(vhci_name_buf, '/')) == NULL || 760*5a4c37c9Sqh201292 (at = strchr(node_name, '@')) == NULL) 761*5a4c37c9Sqh201292 goto out; 762*5a4c37c9Sqh201292 763*5a4c37c9Sqh201292 node_name++; 764*5a4c37c9Sqh201292 *at = '\0'; 765*5a4c37c9Sqh201292 766*5a4c37c9Sqh201292 /* 767*5a4c37c9Sqh201292 * return the first online paths as non-online paths may 768*5a4c37c9Sqh201292 * not be accessible in the target environment. 769*5a4c37c9Sqh201292 */ 770*5a4c37c9Sqh201292 pi = (sv_path_info_t *)ioc.ret_buf; 771*5a4c37c9Sqh201292 while (npaths--) { 772*5a4c37c9Sqh201292 if (MDI_PATHINFO_STATE_ONLINE == pi->ret_state) { 773*5a4c37c9Sqh201292 (void) snprintf(phci_name, phci_name_len, "%s/%s@%s", 774*5a4c37c9Sqh201292 pi->device.ret_phci, node_name, 775*5a4c37c9Sqh201292 pi->ret_addr); 776*5a4c37c9Sqh201292 logdmsg("vhci_to_phci_by_ioctl: %s maps to %s\n", 777*5a4c37c9Sqh201292 vhci_name, phci_name); 778*5a4c37c9Sqh201292 free(ioc.ret_buf); 779*5a4c37c9Sqh201292 return (0); 780*5a4c37c9Sqh201292 } 781*5a4c37c9Sqh201292 pi++; 782*5a4c37c9Sqh201292 } 783*5a4c37c9Sqh201292 784*5a4c37c9Sqh201292 out: 785*5a4c37c9Sqh201292 logdmsg("vhci_to_phci_by_ioctl: couldn't get phci name for %s\n", 786*5a4c37c9Sqh201292 vhci_name); 787*5a4c37c9Sqh201292 free(ioc.ret_buf); 788*5a4c37c9Sqh201292 return (-1); 789*5a4c37c9Sqh201292 790*5a4c37c9Sqh201292 } 791*5a4c37c9Sqh201292 792*5a4c37c9Sqh201292 /* 7937c478bd9Sstevel@tonic-gate * Map physname from phci name space to vhci name space or vice-versa 7947c478bd9Sstevel@tonic-gate * 7957c478bd9Sstevel@tonic-gate * physname 7967c478bd9Sstevel@tonic-gate * phci or vhci based client /devices name without the /devices prefix and 7977c478bd9Sstevel@tonic-gate * minor name component. 7987c478bd9Sstevel@tonic-gate * 7997c478bd9Sstevel@tonic-gate * new_physname 8007c478bd9Sstevel@tonic-gate * Caller supplied buffer where the mapped physical name is stored on 8017c478bd9Sstevel@tonic-gate * return (without the /devices prefix and minor name component). 8027c478bd9Sstevel@tonic-gate * 8037c478bd9Sstevel@tonic-gate * len 8047c478bd9Sstevel@tonic-gate * Length of the caller supplied new_physname buffer. 8057c478bd9Sstevel@tonic-gate * 8067c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 8077c478bd9Sstevel@tonic-gate */ 8087c478bd9Sstevel@tonic-gate static int 8097c478bd9Sstevel@tonic-gate map_physname(char *physname, char *new_physname, size_t len) 8107c478bd9Sstevel@tonic-gate { 8117c478bd9Sstevel@tonic-gate int type; 8127c478bd9Sstevel@tonic-gate int rv; 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate if ((type = client_name_type(physname)) == CLIENT_TYPE_VHCI) 8157c478bd9Sstevel@tonic-gate rv = vhci_to_phci(physname, new_physname, len); 8167c478bd9Sstevel@tonic-gate else if (type == CLIENT_TYPE_PHCI) 8177c478bd9Sstevel@tonic-gate rv = phci_to_vhci(physname, new_physname, len); 8187c478bd9Sstevel@tonic-gate else 8197c478bd9Sstevel@tonic-gate rv = -1; 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate return (rv); 8227c478bd9Sstevel@tonic-gate } 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate /* 8257c478bd9Sstevel@tonic-gate * Given a phci or vhci devname which is either a /dev link or /devices name 8267c478bd9Sstevel@tonic-gate * get the corresponding physical node path (without the /devices prefix) 8277c478bd9Sstevel@tonic-gate * and minor name. 8287c478bd9Sstevel@tonic-gate * 8297c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 8307c478bd9Sstevel@tonic-gate */ 8317c478bd9Sstevel@tonic-gate static int 8327c478bd9Sstevel@tonic-gate get_physname_minor(char *devname, char *physname, int physname_len, 8337c478bd9Sstevel@tonic-gate char *minorname, int minorname_len) 8347c478bd9Sstevel@tonic-gate { 8357c478bd9Sstevel@tonic-gate int linksize; 8367c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 8377c478bd9Sstevel@tonic-gate char *p, *m; 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate if (strncmp(devname, DEV_DSK, sizeof (DEV_DSK) - 1) == 0 || 8407c478bd9Sstevel@tonic-gate strncmp(devname, DEV_RDSK, sizeof (DEV_RDSK) - 1) == 0) { 8417c478bd9Sstevel@tonic-gate if ((linksize = readlink(devname, buf, MAXPATHLEN)) 8427c478bd9Sstevel@tonic-gate > 0 && linksize <= (MAXPATHLEN - 1)) { 8437c478bd9Sstevel@tonic-gate buf[linksize] = '\0'; 8447c478bd9Sstevel@tonic-gate } else 8457c478bd9Sstevel@tonic-gate return (-1); 8467c478bd9Sstevel@tonic-gate } else 8477c478bd9Sstevel@tonic-gate s_strlcpy(buf, devname, MAXPATHLEN); 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate if ((p = strstr(buf, SLASH_DEVICES)) == NULL) 8507c478bd9Sstevel@tonic-gate return (-1); 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate /* point to '/' after /devices */ 8537c478bd9Sstevel@tonic-gate p += sizeof (SLASH_DEVICES) - 2; 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate if ((m = strrchr(p, ':')) == NULL) { 8567c478bd9Sstevel@tonic-gate logdmsg("get_physname_minor: no minor name component in %s\n", 8577c478bd9Sstevel@tonic-gate buf); 8587c478bd9Sstevel@tonic-gate return (-1); 8597c478bd9Sstevel@tonic-gate } 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate *m = '\0'; 8627c478bd9Sstevel@tonic-gate m++; 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate if (client_name_type(p) == CLIENT_TYPE_UNKNOWN) 8657c478bd9Sstevel@tonic-gate return (-1); 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate s_strlcpy(physname, p, physname_len); 8687c478bd9Sstevel@tonic-gate s_strlcpy(minorname, m, minorname_len); 8697c478bd9Sstevel@tonic-gate logdmsg("get_physname_minor: %s: physname = %s, minor = %s\n", 8707c478bd9Sstevel@tonic-gate devname, physname, minorname); 8717c478bd9Sstevel@tonic-gate return (0); 8727c478bd9Sstevel@tonic-gate } 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate static int 8757c478bd9Sstevel@tonic-gate devlink_callback(di_devlink_t devlink, void *argptr) 8767c478bd9Sstevel@tonic-gate { 8777c478bd9Sstevel@tonic-gate const char *link; 8787c478bd9Sstevel@tonic-gate struct devlink_cbarg *argp = argptr; 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate if ((link = di_devlink_path(devlink)) != NULL) { 8817c478bd9Sstevel@tonic-gate s_strlcpy(argp->devlink, link, argp->len); 8827c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 8867c478bd9Sstevel@tonic-gate } 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate /* 8897c478bd9Sstevel@tonic-gate * Lookup the /dev link corresponding to physname and minorname. 8907c478bd9Sstevel@tonic-gate * 8917c478bd9Sstevel@tonic-gate * physname client /devices path without the /devices prefix and minor 8927c478bd9Sstevel@tonic-gate * name component. 8937c478bd9Sstevel@tonic-gate * minorname client minor name. 8947c478bd9Sstevel@tonic-gate * devlink caller supplied buffer where the /dev link is placed on return. 8957c478bd9Sstevel@tonic-gate * len caller supplied devlink buffer length 8967c478bd9Sstevel@tonic-gate * 8977c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 8987c478bd9Sstevel@tonic-gate */ 8997c478bd9Sstevel@tonic-gate static int 9007c478bd9Sstevel@tonic-gate lookup_devlink(char *physname, char *minorname, char *devlink, size_t len) 9017c478bd9Sstevel@tonic-gate { 9027c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 9037c478bd9Sstevel@tonic-gate struct devlink_cbarg arg; 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate if (devlink_hdl == NULL) { 9067c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: taking devlink snapshot\n"); 9077c478bd9Sstevel@tonic-gate if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 9087c478bd9Sstevel@tonic-gate logerr(gettext("di_devlink_init failed: %s\n"), 9097c478bd9Sstevel@tonic-gate strerror(errno)); 9107c478bd9Sstevel@tonic-gate clean_exit(1); 9117c478bd9Sstevel@tonic-gate } 9127c478bd9Sstevel@tonic-gate } 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate *devlink = '\0'; 9157c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, "%s:%s", physname, minorname); 9167c478bd9Sstevel@tonic-gate arg.devlink = devlink; 9177c478bd9Sstevel@tonic-gate arg.len = len; 9187c478bd9Sstevel@tonic-gate if (di_devlink_walk(devlink_hdl, NULL, buf, DI_PRIMARY_LINK, &arg, 9197c478bd9Sstevel@tonic-gate devlink_callback) != 0) { 9207c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: di_devlink_walk on %s failed: %s\n", 9217c478bd9Sstevel@tonic-gate buf, strerror(errno)); 9227c478bd9Sstevel@tonic-gate return (-1); 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate if (*devlink == '\0') { 9267c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: failed to lookup devlink for %s\n", 9277c478bd9Sstevel@tonic-gate buf); 9287c478bd9Sstevel@tonic-gate return (-1); 9297c478bd9Sstevel@tonic-gate } 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: /dev link for %s:%s = %s\n", physname, 9327c478bd9Sstevel@tonic-gate minorname, devlink); 9337c478bd9Sstevel@tonic-gate return (0); 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate /* 9377c478bd9Sstevel@tonic-gate * open infile for reading and return its file pointer in *fp_in. 9387c478bd9Sstevel@tonic-gate * open outfile for writing and return its file pointer in *fp_out. 9397c478bd9Sstevel@tonic-gate * 9407c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 9417c478bd9Sstevel@tonic-gate */ 9427c478bd9Sstevel@tonic-gate static int 9437c478bd9Sstevel@tonic-gate open_in_out_files(char *infile, char *outfile, FILE **fp_in, FILE **fp_out) 9447c478bd9Sstevel@tonic-gate { 9457c478bd9Sstevel@tonic-gate FILE *fin = NULL; 9467c478bd9Sstevel@tonic-gate FILE *fout = NULL; 9477c478bd9Sstevel@tonic-gate struct stat sbuf; 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate if ((fin = fopen(infile, "r")) == NULL) { 9507c478bd9Sstevel@tonic-gate logerr(gettext("failed to fopen %1$s: %2$s\n"), 9517c478bd9Sstevel@tonic-gate infile, strerror(errno)); 9527c478bd9Sstevel@tonic-gate goto out; 9537c478bd9Sstevel@tonic-gate } 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate if (fstat(fileno(fin), &sbuf) != 0) { 9567c478bd9Sstevel@tonic-gate logerr(gettext("fstat failed on %1$s: %2$s\n"), 9577c478bd9Sstevel@tonic-gate infile, strerror(errno)); 9587c478bd9Sstevel@tonic-gate goto out; 9597c478bd9Sstevel@tonic-gate } 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate if ((fout = fopen(outfile, "w")) == NULL) { 9627c478bd9Sstevel@tonic-gate logerr(gettext("failed to fopen %1$s: %2$s\n"), 9637c478bd9Sstevel@tonic-gate outfile, strerror(errno)); 9647c478bd9Sstevel@tonic-gate goto out; 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate if (fchmod(fileno(fout), (sbuf.st_mode & 0777)) != 0) { 9687c478bd9Sstevel@tonic-gate logerr(gettext("failed to fchmod %1$s to 0%2$o: %3$s\n"), 9697c478bd9Sstevel@tonic-gate outfile, sbuf.st_mode & 0777, strerror(errno)); 9707c478bd9Sstevel@tonic-gate goto out; 9717c478bd9Sstevel@tonic-gate } 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate if (fchown(fileno(fout), sbuf.st_uid, sbuf.st_gid) != 0) { 9747c478bd9Sstevel@tonic-gate logerr(gettext("failed to fchown %1$s to uid %2$d and " 9757c478bd9Sstevel@tonic-gate "gid %3$d: %4$s\n"), 9767c478bd9Sstevel@tonic-gate outfile, sbuf.st_uid, sbuf.st_gid, strerror(errno)); 9777c478bd9Sstevel@tonic-gate goto out; 9787c478bd9Sstevel@tonic-gate } 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate *fp_in = fin; 9817c478bd9Sstevel@tonic-gate *fp_out = fout; 9827c478bd9Sstevel@tonic-gate return (0); 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate out: 9857c478bd9Sstevel@tonic-gate if (fin != NULL) 9867c478bd9Sstevel@tonic-gate (void) fclose(fin); 9877c478bd9Sstevel@tonic-gate if (fout != NULL) 9887c478bd9Sstevel@tonic-gate (void) fclose(fout); 9897c478bd9Sstevel@tonic-gate return (-1); 9907c478bd9Sstevel@tonic-gate } 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate /* 9937c478bd9Sstevel@tonic-gate * If the devname is a phci based name and not open-able, map it to vhci 9947c478bd9Sstevel@tonic-gate * based name. If the devname is a vhci based name and not open-able, map it 9957c478bd9Sstevel@tonic-gate * to phci based name. 9967c478bd9Sstevel@tonic-gate * 9977c478bd9Sstevel@tonic-gate * devname either a /dev link or /devices name to client device 9987c478bd9Sstevel@tonic-gate * new_devname caller supplied buffer where the mapped device name is 9997c478bd9Sstevel@tonic-gate * placed on return. 10007c478bd9Sstevel@tonic-gate * len caller supplied new_devname buffer length 10017c478bd9Sstevel@tonic-gate * devlink_flag pass 1 if requesting the /dev link to the mapped device. 10027c478bd9Sstevel@tonic-gate * pass 0 if requesting the /devices name of the mapped device. 10037c478bd9Sstevel@tonic-gate * 10047c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 10057c478bd9Sstevel@tonic-gate */ 10067c478bd9Sstevel@tonic-gate static int 10077c478bd9Sstevel@tonic-gate map_devname(char *devname, char *new_devname, size_t len, int devlink_flag) 10087c478bd9Sstevel@tonic-gate { 10097c478bd9Sstevel@tonic-gate char physname[MAXPATHLEN]; 10107c478bd9Sstevel@tonic-gate char minor[MAXNAMELEN]; 1011*5a4c37c9Sqh201292 char new_physname[MAXPATHLEN]; 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate if (get_physname_minor(devname, physname, sizeof (physname), 10147c478bd9Sstevel@tonic-gate minor, sizeof (minor)) == 0 && 10157c478bd9Sstevel@tonic-gate canopen(devname) == 0 && 10167c478bd9Sstevel@tonic-gate map_physname(physname, new_physname, sizeof (new_physname)) == 0) { 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate if (devlink_flag) { 10197c478bd9Sstevel@tonic-gate if (lookup_devlink(new_physname, minor, new_devname, 10207c478bd9Sstevel@tonic-gate len) == 0) 10217c478bd9Sstevel@tonic-gate return (0); 10227c478bd9Sstevel@tonic-gate } else { 10237c478bd9Sstevel@tonic-gate (void) snprintf(new_devname, len, "/devices%s:%s", 10247c478bd9Sstevel@tonic-gate new_physname, minor); 10257c478bd9Sstevel@tonic-gate return (0); 10267c478bd9Sstevel@tonic-gate } 10277c478bd9Sstevel@tonic-gate } 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate return (-1); 10307c478bd9Sstevel@tonic-gate } 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate /* 1033*5a4c37c9Sqh201292 * If the devname is a vhci based name and open-able, map it to phci 1034*5a4c37c9Sqh201292 * based name. 1035*5a4c37c9Sqh201292 * 1036*5a4c37c9Sqh201292 * devname either a /dev link or /devices name to client device 1037*5a4c37c9Sqh201292 * new_devname caller supplied buffer where the mapped device name without 1038*5a4c37c9Sqh201292 * /devices prefix is placed on return. 1039*5a4c37c9Sqh201292 * len caller supplied new_devname buffer length 1040*5a4c37c9Sqh201292 */ 1041*5a4c37c9Sqh201292 static int 1042*5a4c37c9Sqh201292 map_openable_vhciname(char *devname, char *new_devname, size_t len) 1043*5a4c37c9Sqh201292 { 1044*5a4c37c9Sqh201292 char physname[MAXPATHLEN]; 1045*5a4c37c9Sqh201292 char minor[MAXNAMELEN]; 1046*5a4c37c9Sqh201292 char new_physname[MAXPATHLEN]; 1047*5a4c37c9Sqh201292 1048*5a4c37c9Sqh201292 if (get_physname_minor(devname, physname, sizeof (physname), 1049*5a4c37c9Sqh201292 minor, sizeof (minor)) == 0 && 1050*5a4c37c9Sqh201292 canopen(devname) == 1 && 1051*5a4c37c9Sqh201292 client_name_type(physname) == CLIENT_TYPE_VHCI && 1052*5a4c37c9Sqh201292 vhci_to_phci_by_ioctl(physname, new_physname, 1053*5a4c37c9Sqh201292 sizeof (new_physname)) == 0) { 1054*5a4c37c9Sqh201292 (void) snprintf(new_devname, len, "%s:%s", 1055*5a4c37c9Sqh201292 new_physname, minor); 1056*5a4c37c9Sqh201292 return (0); 1057*5a4c37c9Sqh201292 } 1058*5a4c37c9Sqh201292 1059*5a4c37c9Sqh201292 return (-1); 1060*5a4c37c9Sqh201292 } 1061*5a4c37c9Sqh201292 /* 10627c478bd9Sstevel@tonic-gate * Make a new /etc/vfstab: 10637c478bd9Sstevel@tonic-gate * Read vfstab_in, convert the device name entries to appropriate vhci or phci 10647c478bd9Sstevel@tonic-gate * based names, and write to vfstab_out. Only device names whose physical 10657c478bd9Sstevel@tonic-gate * paths are either phci or vhci based names and not open-able are considered 10667c478bd9Sstevel@tonic-gate * for conversion. Open-able device name entries are not converted as it 10677c478bd9Sstevel@tonic-gate * means that the device is already accessible; hence no need to convert. 10687c478bd9Sstevel@tonic-gate * 10697c478bd9Sstevel@tonic-gate * Returns: 10707c478bd9Sstevel@tonic-gate * 0 successful but vfstab_out contents are the same as vfstab_in 10717c478bd9Sstevel@tonic-gate * 1 successful and vfstab_out changed from vfstab_in 10727c478bd9Sstevel@tonic-gate * -1 failed 10737c478bd9Sstevel@tonic-gate */ 10747c478bd9Sstevel@tonic-gate static int 10757c478bd9Sstevel@tonic-gate update_vfstab(char *vfstab_in, char *vfstab_out) 10767c478bd9Sstevel@tonic-gate { 10777c478bd9Sstevel@tonic-gate FILE *fp_in, *fp_out; 10787c478bd9Sstevel@tonic-gate char *buf, *tmpbuf; 10797c478bd9Sstevel@tonic-gate char *vfs_cache[2]; 10807c478bd9Sstevel@tonic-gate int idx = 0, count = 0; 10817c478bd9Sstevel@tonic-gate int rv = -1; 10827c478bd9Sstevel@tonic-gate int vfstab_updated = 0; 10837c478bd9Sstevel@tonic-gate int i; 10847c478bd9Sstevel@tonic-gate char cdev[MAXPATHLEN]; 10857c478bd9Sstevel@tonic-gate char bdev[MAXPATHLEN]; 10867c478bd9Sstevel@tonic-gate char mntpt[MAXPATHLEN]; 10877c478bd9Sstevel@tonic-gate char fstype[512]; 10887c478bd9Sstevel@tonic-gate char fsckpass[512]; 10897c478bd9Sstevel@tonic-gate char mntboot[512]; 10907c478bd9Sstevel@tonic-gate char mntopt[MAX_MNTOPT_STR]; 10917c478bd9Sstevel@tonic-gate char phys_bdev[MAXPATHLEN], phys_cdev[MAXPATHLEN]; 10927c478bd9Sstevel@tonic-gate char bdev_minor[MAXNAMELEN], cdev_minor[MAXNAMELEN]; 10937c478bd9Sstevel@tonic-gate char new_physname[MAXPATHLEN]; 10947c478bd9Sstevel@tonic-gate char new_bdevlink[MAXPATHLEN], new_cdevlink[MAXPATHLEN]; 10957c478bd9Sstevel@tonic-gate char fmt[80]; 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate if (open_in_out_files(vfstab_in, vfstab_out, &fp_in, &fp_out) != 0) 10987c478bd9Sstevel@tonic-gate return (-1); 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate /* 11017c478bd9Sstevel@tonic-gate * Read one line at time from vfstab_in. If no conversion is needed 11027c478bd9Sstevel@tonic-gate * for the line simply write the line to vfstab_out. If conversion is 11037c478bd9Sstevel@tonic-gate * needed, first write the existing line as a comment to vfstab_out 11047c478bd9Sstevel@tonic-gate * and then write the converted line. 11057c478bd9Sstevel@tonic-gate * 11067c478bd9Sstevel@tonic-gate * To avoid commented entries piling up in vfstab in case if the 11077c478bd9Sstevel@tonic-gate * user runs stmsboot multiple times to switch on and off from mpxio, 11087c478bd9Sstevel@tonic-gate * add the commented line only if not already there. To do this 11097c478bd9Sstevel@tonic-gate * cache the last two vfstab lines processed and add the commented 11107c478bd9Sstevel@tonic-gate * entry only if it is not found in the cache. We only need to cache 11117c478bd9Sstevel@tonic-gate * the last two lines because a device can have at most two names - 11127c478bd9Sstevel@tonic-gate * one mpxio and one non-mpxio name. Therefore for any device name 11137c478bd9Sstevel@tonic-gate * entry we at most add two comments - one with mpxio name and one 11147c478bd9Sstevel@tonic-gate * with non-mpxio name - no matter how many times stmsboot is run. 11157c478bd9Sstevel@tonic-gate */ 11167c478bd9Sstevel@tonic-gate buf = (char *)s_malloc(VFS_LINE_MAX); 11177c478bd9Sstevel@tonic-gate tmpbuf = (char *)s_malloc(VFS_LINE_MAX); 11187c478bd9Sstevel@tonic-gate vfs_cache[0] = (char *)s_malloc(VFS_LINE_MAX); 11197c478bd9Sstevel@tonic-gate vfs_cache[1] = (char *)s_malloc(VFS_LINE_MAX); 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate (void) snprintf(fmt, sizeof (fmt), 11227c478bd9Sstevel@tonic-gate "%%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds", sizeof (bdev) - 1, 11237c478bd9Sstevel@tonic-gate sizeof (cdev) - 1, sizeof (mntpt) - 1, sizeof (fstype) - 1, 11247c478bd9Sstevel@tonic-gate sizeof (fsckpass) - 1, sizeof (mntboot) - 1, sizeof (mntopt) - 1); 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate while (fgets(buf, VFS_LINE_MAX, fp_in) != NULL) { 11277c478bd9Sstevel@tonic-gate if (strlen(buf) == (VFS_LINE_MAX - 1) && 11287c478bd9Sstevel@tonic-gate buf[VFS_LINE_MAX-2] != '\n') { 11297c478bd9Sstevel@tonic-gate logerr(gettext("%1$s line size too long, " 11307c478bd9Sstevel@tonic-gate "exceeded %2$d: \"%3$s\"\n"), 11317c478bd9Sstevel@tonic-gate VFSTAB, VFS_LINE_MAX - 2, buf); 11327c478bd9Sstevel@tonic-gate goto out; 11337c478bd9Sstevel@tonic-gate } 11347c478bd9Sstevel@tonic-gate 11357c478bd9Sstevel@tonic-gate /* LINTED - format specifier */ 11367c478bd9Sstevel@tonic-gate if ((sscanf(buf, fmt, bdev, cdev, mntpt, 11377c478bd9Sstevel@tonic-gate fstype, fsckpass, mntboot, mntopt) != 7) || 11387c478bd9Sstevel@tonic-gate (bdev[0] == '#') || 11397c478bd9Sstevel@tonic-gate (get_physname_minor(bdev, phys_bdev, sizeof (phys_bdev), 11407c478bd9Sstevel@tonic-gate bdev_minor, sizeof (bdev_minor)) != 0) || 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate (strcmp(fstype, "swap") != 0 && 11437c478bd9Sstevel@tonic-gate ((get_physname_minor(cdev, phys_cdev, sizeof (phys_cdev), 11447c478bd9Sstevel@tonic-gate cdev_minor, sizeof (cdev_minor)) != 0) || 11457c478bd9Sstevel@tonic-gate (strcmp(phys_bdev, phys_cdev) != 0))) || 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate canopen(bdev) || 11487c478bd9Sstevel@tonic-gate (map_physname(phys_bdev, new_physname, 11497c478bd9Sstevel@tonic-gate sizeof (new_physname)) != 0) || 11507c478bd9Sstevel@tonic-gate (lookup_devlink(new_physname, bdev_minor, new_bdevlink, 11517c478bd9Sstevel@tonic-gate sizeof (new_bdevlink)) != 0) || 11527c478bd9Sstevel@tonic-gate 11537c478bd9Sstevel@tonic-gate (strcmp(fstype, "swap") != 0 && 11547c478bd9Sstevel@tonic-gate (lookup_devlink(new_physname, cdev_minor, new_cdevlink, 11557c478bd9Sstevel@tonic-gate sizeof (new_cdevlink)) != 0))) { 11567c478bd9Sstevel@tonic-gate 11577c478bd9Sstevel@tonic-gate /* cache the last two entries */ 11587c478bd9Sstevel@tonic-gate (void) strlcpy(vfs_cache[idx], buf, VFS_LINE_MAX); 11597c478bd9Sstevel@tonic-gate idx = (idx == 0) ? 1 : 0; 11607c478bd9Sstevel@tonic-gate if (count < 2) 11617c478bd9Sstevel@tonic-gate count++; 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate if (fputs(buf, fp_out) == EOF) { 11647c478bd9Sstevel@tonic-gate logerr(gettext("fputs \"%1$s\" to %2$s " 11657c478bd9Sstevel@tonic-gate "failed: %3$s\n"), 11667c478bd9Sstevel@tonic-gate buf, vfstab_out, strerror(errno)); 11677c478bd9Sstevel@tonic-gate goto out; 11687c478bd9Sstevel@tonic-gate } 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate } else { 11717c478bd9Sstevel@tonic-gate /* 11727c478bd9Sstevel@tonic-gate * comment the entry in vfstab only if it is not 11737c478bd9Sstevel@tonic-gate * already in the cache. 11747c478bd9Sstevel@tonic-gate */ 11757c478bd9Sstevel@tonic-gate if (client_name_type(phys_bdev) == CLIENT_TYPE_VHCI) 11767c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, VFS_LINE_MAX, 11777c478bd9Sstevel@tonic-gate "# mpxio: %s", buf); 11787c478bd9Sstevel@tonic-gate else 11797c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, VFS_LINE_MAX, 11807c478bd9Sstevel@tonic-gate "# non-mpxio: %s", buf); 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 11837c478bd9Sstevel@tonic-gate if (strcmp(vfs_cache[i], tmpbuf) == 0) 11847c478bd9Sstevel@tonic-gate break; 11857c478bd9Sstevel@tonic-gate } 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate if (i == count) { 11887c478bd9Sstevel@tonic-gate if (fputs(tmpbuf, fp_out) == EOF) { 11897c478bd9Sstevel@tonic-gate logerr(gettext("fputs \"%1$s\" to %2$s " 11907c478bd9Sstevel@tonic-gate "failed: %3$s\n"), tmpbuf, 11917c478bd9Sstevel@tonic-gate vfstab_out, strerror(errno)); 11927c478bd9Sstevel@tonic-gate goto out; 11937c478bd9Sstevel@tonic-gate } 11947c478bd9Sstevel@tonic-gate } 11957c478bd9Sstevel@tonic-gate 11967c478bd9Sstevel@tonic-gate count = 0; 11977c478bd9Sstevel@tonic-gate idx = 0; 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate if (fprintf(fp_out, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", 12007c478bd9Sstevel@tonic-gate new_bdevlink, 12017c478bd9Sstevel@tonic-gate (strcmp(fstype, "swap") != 0) ? new_cdevlink : cdev, 12027c478bd9Sstevel@tonic-gate mntpt, fstype, fsckpass, mntboot, mntopt) < 0) { 12037c478bd9Sstevel@tonic-gate logerr(gettext("fprintf failed to write to " 12047c478bd9Sstevel@tonic-gate "%1$s: %2$s\n"), 12057c478bd9Sstevel@tonic-gate vfstab_out, strerror(errno)); 12067c478bd9Sstevel@tonic-gate goto out; 12077c478bd9Sstevel@tonic-gate } 12087c478bd9Sstevel@tonic-gate vfstab_updated = 1; 12097c478bd9Sstevel@tonic-gate } 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate rv = vfstab_updated; 12137c478bd9Sstevel@tonic-gate out: 12147c478bd9Sstevel@tonic-gate (void) fclose(fp_in); 12157c478bd9Sstevel@tonic-gate (void) fclose(fp_out); 12167c478bd9Sstevel@tonic-gate free(buf); 12177c478bd9Sstevel@tonic-gate free(tmpbuf); 12187c478bd9Sstevel@tonic-gate free(vfs_cache[0]); 12197c478bd9Sstevel@tonic-gate free(vfs_cache[1]); 12207c478bd9Sstevel@tonic-gate return (rv); 12217c478bd9Sstevel@tonic-gate } 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate /* 12247c478bd9Sstevel@tonic-gate * if guidmap is 0, list non-STMS to STMS device name mappings for the 12257c478bd9Sstevel@tonic-gate * specified controller. 12267c478bd9Sstevel@tonic-gate * if guidmap is 1, list non-STMS to GUID mappings for the specified controller. 12277c478bd9Sstevel@tonic-gate * If controller is -1 list mappings for all controllers. 12287c478bd9Sstevel@tonic-gate * 12297c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 12307c478bd9Sstevel@tonic-gate */ 12317c478bd9Sstevel@tonic-gate static int 12327c478bd9Sstevel@tonic-gate list_mappings(int controller, int guidmap) 12337c478bd9Sstevel@tonic-gate { 12347c478bd9Sstevel@tonic-gate int cnum, len, mapped; 12357c478bd9Sstevel@tonic-gate int header = 1; 12367c478bd9Sstevel@tonic-gate char *p1, *p2; 12377c478bd9Sstevel@tonic-gate DIR *dirp; 12387c478bd9Sstevel@tonic-gate struct dirent *direntry; 12397c478bd9Sstevel@tonic-gate char devname[MAXPATHLEN]; 12407c478bd9Sstevel@tonic-gate char physname[MAXPATHLEN]; 12417c478bd9Sstevel@tonic-gate char new_devname[MAXPATHLEN]; 12427c478bd9Sstevel@tonic-gate char new_physname[MAXPATHLEN]; 12437c478bd9Sstevel@tonic-gate char guid[MAXPATHLEN]; 12447c478bd9Sstevel@tonic-gate char minor[MAXNAMELEN]; 12457c478bd9Sstevel@tonic-gate 12467c478bd9Sstevel@tonic-gate if ((dirp = opendir("/dev/rdsk")) == NULL) 12477c478bd9Sstevel@tonic-gate return (-1); 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate while ((direntry = readdir(dirp)) != NULL) { 12507c478bd9Sstevel@tonic-gate if (strcmp(direntry->d_name, ".") == 0 || 12517c478bd9Sstevel@tonic-gate strcmp(direntry->d_name, "..") == 0 || 12527c478bd9Sstevel@tonic-gate (len = strlen(direntry->d_name)) < 2 || 12537c478bd9Sstevel@tonic-gate strcmp(direntry->d_name + len - 2, "s0") != 0 || 12547c478bd9Sstevel@tonic-gate sscanf(direntry->d_name, "c%dt", &cnum) != 1 || 12557c478bd9Sstevel@tonic-gate (controller != -1 && controller != cnum)) 12567c478bd9Sstevel@tonic-gate continue; 12577c478bd9Sstevel@tonic-gate 12587c478bd9Sstevel@tonic-gate (void) snprintf(devname, MAXPATHLEN, "/dev/rdsk/%s", 12597c478bd9Sstevel@tonic-gate direntry->d_name); 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate if (get_physname_minor(devname, physname, sizeof (physname), 12627c478bd9Sstevel@tonic-gate minor, sizeof (minor)) != 0 || 12637c478bd9Sstevel@tonic-gate client_name_type(physname) != CLIENT_TYPE_PHCI) 12647c478bd9Sstevel@tonic-gate continue; 12657c478bd9Sstevel@tonic-gate 12667c478bd9Sstevel@tonic-gate /* 12677c478bd9Sstevel@tonic-gate * First try phci_to_vhci() mapping. It will work if the 12687c478bd9Sstevel@tonic-gate * device is under MPxIO control. If the device is not under 12697c478bd9Sstevel@tonic-gate * MPxIO, phci_to_vhci() will fail in which case try to lookup 12707c478bd9Sstevel@tonic-gate * if an old mapping exists using guid lookup. 12717c478bd9Sstevel@tonic-gate */ 12727c478bd9Sstevel@tonic-gate mapped = 1; 12737c478bd9Sstevel@tonic-gate if (phci_to_vhci(physname, new_physname, 12747c478bd9Sstevel@tonic-gate sizeof (new_physname)) != 0) { 12757c478bd9Sstevel@tonic-gate if (get_guid(physname, guid, sizeof (guid), 1, 12767c478bd9Sstevel@tonic-gate DI_NODE_NIL) == 0) 12777c478bd9Sstevel@tonic-gate (void) snprintf(new_physname, MAXPATHLEN, 1278*5a4c37c9Sqh201292 "/scsi_vhci/%s%s", DISK_AT_G, guid); 12797c478bd9Sstevel@tonic-gate else 12807c478bd9Sstevel@tonic-gate mapped = 0; 12817c478bd9Sstevel@tonic-gate } 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate if (mapped == 0) 12847c478bd9Sstevel@tonic-gate continue; 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate /* strip the slice number part */ 12877c478bd9Sstevel@tonic-gate devname[strlen(devname) - 2] = '\0'; 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate if (guidmap == 0) { 12907c478bd9Sstevel@tonic-gate if (lookup_devlink(new_physname, minor, 12917c478bd9Sstevel@tonic-gate new_devname, sizeof (new_devname)) != 0) 12927c478bd9Sstevel@tonic-gate continue; 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate /* strip the slice number part */ 12957c478bd9Sstevel@tonic-gate new_devname[strlen(new_devname) - 2] = '\0'; 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate if (header) { 12987c478bd9Sstevel@tonic-gate (void) printf( 12997c478bd9Sstevel@tonic-gate gettext("non-STMS device name\t\t\t" 13007c478bd9Sstevel@tonic-gate "STMS device name\n" 13017c478bd9Sstevel@tonic-gate "------------------------------------------" 13027c478bd9Sstevel@tonic-gate "------------------------\n")); 13037c478bd9Sstevel@tonic-gate header = 0; 13047c478bd9Sstevel@tonic-gate } 13057c478bd9Sstevel@tonic-gate (void) printf("%s\t\t%s\n", devname, new_devname); 13067c478bd9Sstevel@tonic-gate } else { 13077c478bd9Sstevel@tonic-gate /* extract guid part */ 1308*5a4c37c9Sqh201292 if ((p1 = strstr(new_physname, DISK_AT_G)) == NULL) { 13097c478bd9Sstevel@tonic-gate logdmsg("invalid vhci: %s\n", new_physname); 13107c478bd9Sstevel@tonic-gate continue; 13117c478bd9Sstevel@tonic-gate } 1312*5a4c37c9Sqh201292 p1 += sizeof (DISK_AT_G) - 1; 13137c478bd9Sstevel@tonic-gate if ((p2 = strrchr(p1, ':')) != NULL) 13147c478bd9Sstevel@tonic-gate *p2 = '\0'; 13157c478bd9Sstevel@tonic-gate 13167c478bd9Sstevel@tonic-gate if (header) { 13177c478bd9Sstevel@tonic-gate (void) printf( 13187c478bd9Sstevel@tonic-gate gettext("non-STMS device name\t\t\tGUID\n" 13197c478bd9Sstevel@tonic-gate "------------------------------------------" 13207c478bd9Sstevel@tonic-gate "------------------------\n")); 13217c478bd9Sstevel@tonic-gate header = 0; 13227c478bd9Sstevel@tonic-gate } 13237c478bd9Sstevel@tonic-gate (void) printf("%s\t\t%s\n", devname, p1); 13247c478bd9Sstevel@tonic-gate } 13257c478bd9Sstevel@tonic-gate } 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate (void) closedir(dirp); 13287c478bd9Sstevel@tonic-gate return (0); 13297c478bd9Sstevel@tonic-gate } 13307c478bd9Sstevel@tonic-gate 13317c478bd9Sstevel@tonic-gate /* 13327c478bd9Sstevel@tonic-gate * Check if the file can be opened. 13337c478bd9Sstevel@tonic-gate * 13347c478bd9Sstevel@tonic-gate * Return 1 if the file can be opened, 0 otherwise. 13357c478bd9Sstevel@tonic-gate */ 13367c478bd9Sstevel@tonic-gate static int 13377c478bd9Sstevel@tonic-gate canopen(char *filename) 13387c478bd9Sstevel@tonic-gate { 13397c478bd9Sstevel@tonic-gate int fd; 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate if ((fd = open(filename, O_RDONLY)) == -1) 13427c478bd9Sstevel@tonic-gate return (0); 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate (void) close(fd); 13457c478bd9Sstevel@tonic-gate return (1); 13467c478bd9Sstevel@tonic-gate } 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate static void 13497c478bd9Sstevel@tonic-gate logerr(char *msg, ...) 13507c478bd9Sstevel@tonic-gate { 13517c478bd9Sstevel@tonic-gate va_list ap; 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", stmsboot); 13547c478bd9Sstevel@tonic-gate va_start(ap, msg); 13557c478bd9Sstevel@tonic-gate /* LINTED - format specifier */ 13567c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, msg, ap); 13577c478bd9Sstevel@tonic-gate va_end(ap); 13587c478bd9Sstevel@tonic-gate } 13597c478bd9Sstevel@tonic-gate 13607c478bd9Sstevel@tonic-gate /* log debug message */ 13617c478bd9Sstevel@tonic-gate static void 13627c478bd9Sstevel@tonic-gate logdmsg(char *msg, ...) 13637c478bd9Sstevel@tonic-gate { 13647c478bd9Sstevel@tonic-gate va_list ap; 13657c478bd9Sstevel@tonic-gate 13667c478bd9Sstevel@tonic-gate if (debug) { 13677c478bd9Sstevel@tonic-gate va_start(ap, msg); 13687c478bd9Sstevel@tonic-gate /* LINTED - format specifier */ 13697c478bd9Sstevel@tonic-gate (void) vprintf(msg, ap); 13707c478bd9Sstevel@tonic-gate va_end(ap); 13717c478bd9Sstevel@tonic-gate } 13727c478bd9Sstevel@tonic-gate } 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate static void * 13757c478bd9Sstevel@tonic-gate s_malloc(const size_t size) 13767c478bd9Sstevel@tonic-gate { 13777c478bd9Sstevel@tonic-gate void *rp; 13787c478bd9Sstevel@tonic-gate 13797c478bd9Sstevel@tonic-gate if ((rp = malloc(size)) == NULL) { 13807c478bd9Sstevel@tonic-gate logerr(gettext("malloc failed to allocate %d bytes\n"), size); 13817c478bd9Sstevel@tonic-gate clean_exit(1); 13827c478bd9Sstevel@tonic-gate } 13837c478bd9Sstevel@tonic-gate return (rp); 13847c478bd9Sstevel@tonic-gate } 13857c478bd9Sstevel@tonic-gate 13867c478bd9Sstevel@tonic-gate static char * 13877c478bd9Sstevel@tonic-gate s_strdup(const char *ptr) 13887c478bd9Sstevel@tonic-gate { 13897c478bd9Sstevel@tonic-gate void *rp; 13907c478bd9Sstevel@tonic-gate 13917c478bd9Sstevel@tonic-gate if ((rp = strdup(ptr)) == NULL) { 13927c478bd9Sstevel@tonic-gate logerr(gettext("strdup failed to dup %s\n"), ptr); 13937c478bd9Sstevel@tonic-gate clean_exit(1); 13947c478bd9Sstevel@tonic-gate } 13957c478bd9Sstevel@tonic-gate return (rp); 13967c478bd9Sstevel@tonic-gate } 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate static void 13997c478bd9Sstevel@tonic-gate s_strlcpy(char *dst, const char *src, size_t dstsize) 14007c478bd9Sstevel@tonic-gate { 14017c478bd9Sstevel@tonic-gate int n; 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate if ((n = strlcpy(dst, src, dstsize)) >= dstsize) { 14047c478bd9Sstevel@tonic-gate logerr(gettext("strlcpy: destination buffer size is %1$d " 14057c478bd9Sstevel@tonic-gate "bytes, need to at least %2$d bytes\n"), dstsize, n + 1); 14067c478bd9Sstevel@tonic-gate clean_exit(1); 14077c478bd9Sstevel@tonic-gate } 14087c478bd9Sstevel@tonic-gate } 14097c478bd9Sstevel@tonic-gate 14107c478bd9Sstevel@tonic-gate static void 14117c478bd9Sstevel@tonic-gate clean_exit(int status) 14127c478bd9Sstevel@tonic-gate { 14137c478bd9Sstevel@tonic-gate if (devinfo_root != DI_NODE_NIL) 14147c478bd9Sstevel@tonic-gate di_fini(devinfo_root); 14157c478bd9Sstevel@tonic-gate 14167c478bd9Sstevel@tonic-gate if (devlink_hdl != NULL) 14177c478bd9Sstevel@tonic-gate (void) di_devlink_fini(&devlink_hdl); 14187c478bd9Sstevel@tonic-gate 14197c478bd9Sstevel@tonic-gate if (vhci_fd != -1) 14207c478bd9Sstevel@tonic-gate (void) close(vhci_fd); 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate exit(status); 14237c478bd9Sstevel@tonic-gate } 1424