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 /* 235a4c37c9Sqh201292 * 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/" 565a4c37c9Sqh201292 575a4c37c9Sqh201292 #ifdef sparc 585a4c37c9Sqh201292 #define DISK_NODE_NAME "ssd" 595a4c37c9Sqh201292 #define DISK_DRV_NAME "ssd" 605a4c37c9Sqh201292 #define SLASH_DISK_AT "/ssd@" 615a4c37c9Sqh201292 #else /* sparc */ 625a4c37c9Sqh201292 #define DISK_NODE_NAME "disk" 635a4c37c9Sqh201292 #define DISK_DRV_NAME "sd" 645a4c37c9Sqh201292 #define SLASH_DISK_AT "/disk@" 655a4c37c9Sqh201292 #endif 665a4c37c9Sqh201292 67*60fffc19Sjw149990 #define DISK_AT_G "disk@g" 687c478bd9Sstevel@tonic-gate #define SLASH_FP_AT "/fp@" 697c478bd9Sstevel@tonic-gate #define SLASH_SCSI_VHCI "/scsi_vhci" 70*60fffc19Sjw149990 #define SLASH_SD_AT "/sd@" 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 85*60fffc19Sjw149990 /* 86*60fffc19Sjw149990 * For SAS, we look for "sas-$drivername", eg sas-mpt, but 87*60fffc19Sjw149990 * we strncat the driver name later once we've parsed the 88*60fffc19Sjw149990 * args passed in from the shell. 89*60fffc19Sjw149990 */ 90*60fffc19Sjw149990 #define SASPROP "sas-" 91*60fffc19Sjw149990 92*60fffc19Sjw149990 937c478bd9Sstevel@tonic-gate typedef enum { 947c478bd9Sstevel@tonic-gate CLIENT_TYPE_UNKNOWN, 957c478bd9Sstevel@tonic-gate CLIENT_TYPE_PHCI, 967c478bd9Sstevel@tonic-gate CLIENT_TYPE_VHCI 977c478bd9Sstevel@tonic-gate } client_type_t; 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate struct devlink_cbarg { 1007c478bd9Sstevel@tonic-gate char *devlink; 1017c478bd9Sstevel@tonic-gate size_t len; 1027c478bd9Sstevel@tonic-gate }; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate static di_node_t devinfo_root = DI_NODE_NIL; 1057c478bd9Sstevel@tonic-gate static di_devlink_handle_t devlink_hdl = NULL; 1067c478bd9Sstevel@tonic-gate static int vhci_fd = -1; 1077c478bd9Sstevel@tonic-gate static int patch_vfstab, cap_m_option, debug; 1087c478bd9Sstevel@tonic-gate static int list_option, list_guid_mappings, list_controllernum = -1; 1097c478bd9Sstevel@tonic-gate static char *mapdev = ""; 1105a4c37c9Sqh201292 static char *map_vhciname = ""; 1117c478bd9Sstevel@tonic-gate static char *stmsboot = "stmsboot"; 1127c478bd9Sstevel@tonic-gate 113*60fffc19Sjw149990 char *drvname = (char *)NULL; /* "fp" or "mpt" or ... */ 114*60fffc19Sjw149990 /* "node-wwn" if drvname=fp, or "sas-$drivername" otherwise */ 115*60fffc19Sjw149990 char *drvprop = (char *)NULL; 116*60fffc19Sjw149990 static int parent = 0; /* for "-n" usage */ 117*60fffc19Sjw149990 1187c478bd9Sstevel@tonic-gate static int make_temp(char *, char *, char *, size_t); 1197c478bd9Sstevel@tonic-gate static void commit_change(char *, char *, char *, int); 1207c478bd9Sstevel@tonic-gate static int map_devname(char *, char *, size_t, int); 1217c478bd9Sstevel@tonic-gate static int update_vfstab(char *, char *); 1227c478bd9Sstevel@tonic-gate static int list_mappings(int, int); 1237c478bd9Sstevel@tonic-gate static int canopen(char *); 124*60fffc19Sjw149990 static client_type_t client_by_props(char *path); 125*60fffc19Sjw149990 static void list_nodes(char *drivername); 126*60fffc19Sjw149990 1277c478bd9Sstevel@tonic-gate static void logerr(char *, ...); 1287c478bd9Sstevel@tonic-gate static void logdmsg(char *, ...); 1297c478bd9Sstevel@tonic-gate static void *s_malloc(const size_t); 1307c478bd9Sstevel@tonic-gate static char *s_strdup(const char *); 1317c478bd9Sstevel@tonic-gate static void s_strlcpy(char *, const char *, size_t); 132cfcc3aa4Sqh201292 static int map_openable_vhciname(char *, char *, size_t); 133264d6c47Seota /* 134264d6c47Seota * Using an exit function not marked __NORETURN causes a warning with gcc. 135264d6c47Seota * To suppress the warning, use __NORETURN attribute. 136264d6c47Seota */ 137264d6c47Seota static void clean_exit(int)__NORETURN; 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate /* 1407c478bd9Sstevel@tonic-gate * Print usage and exit. 1417c478bd9Sstevel@tonic-gate */ 1427c478bd9Sstevel@tonic-gate static void 1437c478bd9Sstevel@tonic-gate usage(char *argv0) 1447c478bd9Sstevel@tonic-gate { 1457c478bd9Sstevel@tonic-gate char *progname; 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate progname = strrchr(argv0, '/'); 1487c478bd9Sstevel@tonic-gate if (progname != NULL) 1497c478bd9Sstevel@tonic-gate progname++; 1507c478bd9Sstevel@tonic-gate else 1517c478bd9Sstevel@tonic-gate progname = argv0; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate /* 1547c478bd9Sstevel@tonic-gate * -u update /etc/vfstab 1557c478bd9Sstevel@tonic-gate * -m devname 1567c478bd9Sstevel@tonic-gate * if devname is phci based name and not open-able, map it to 1577c478bd9Sstevel@tonic-gate * vhci based /devices name. 1587c478bd9Sstevel@tonic-gate * if devname is vhci based name and not open-able, map it to 1597c478bd9Sstevel@tonic-gate * phci based /devices name. 1607c478bd9Sstevel@tonic-gate * -M devname 1617c478bd9Sstevel@tonic-gate * same as -m except that /dev link is printed instead of 1627c478bd9Sstevel@tonic-gate * /devices name. 1637c478bd9Sstevel@tonic-gate * -l controller 1647c478bd9Sstevel@tonic-gate * list non-STMS to STMS device name mappings for the specific 1657c478bd9Sstevel@tonic-gate * controller 1667c478bd9Sstevel@tonic-gate * -L list non-STMS to STMS device name mappings for all controllers 1675a4c37c9Sqh201292 * -p devname 1685a4c37c9Sqh201292 * if devname is vhci based name and open-able, get the first 1695a4c37c9Sqh201292 * onlined phci based name without /devices prefix. 1705a4c37c9Sqh201292 * Used in stmsboot to update the phci based bootpath. 171*60fffc19Sjw149990 * -D drvname 172*60fffc19Sjw149990 * if supplied, indicates that we're going to operate on 173*60fffc19Sjw149990 * devices attached to this driver 174*60fffc19Sjw149990 * -n 175*60fffc19Sjw149990 * if supplied, returns name of the node containing "fp" or 176*60fffc19Sjw149990 * "sas-$driver", appends "sd@" or "ssd@" or "disk@". Can only 177*60fffc19Sjw149990 * be used if -D drv is specified as well 1787c478bd9Sstevel@tonic-gate */ 1797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("usage: %s -u | -m devname | " 180*60fffc19Sjw149990 "-M devname | -l controller | -L | \n" 181*60fffc19Sjw149990 "\t\t-p devname | -D { fp | mpt } | -n\n"), progname); 1827c478bd9Sstevel@tonic-gate exit(2); 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate /* 1867c478bd9Sstevel@tonic-gate * Parse command line arguments. 1877c478bd9Sstevel@tonic-gate */ 1887c478bd9Sstevel@tonic-gate static void 1897c478bd9Sstevel@tonic-gate parse_args(int argc, char *argv[]) 1907c478bd9Sstevel@tonic-gate { 1917c478bd9Sstevel@tonic-gate char opt; 1927c478bd9Sstevel@tonic-gate int n = 0; 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate if (argc == 1) { 1957c478bd9Sstevel@tonic-gate usage(argv[0]); 1967c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate 199*60fffc19Sjw149990 while ((opt = getopt(argc, argv, "udm:M:Ll:gp:D:n")) != EOF) { 2007c478bd9Sstevel@tonic-gate switch (opt) { 2017c478bd9Sstevel@tonic-gate case 'u': 2027c478bd9Sstevel@tonic-gate patch_vfstab = 1; 2037c478bd9Sstevel@tonic-gate n++; 2047c478bd9Sstevel@tonic-gate break; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate case 'd': 2077c478bd9Sstevel@tonic-gate debug = 1; 2087c478bd9Sstevel@tonic-gate break; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate case 'm': 2117c478bd9Sstevel@tonic-gate mapdev = s_strdup(optarg); 2127c478bd9Sstevel@tonic-gate n++; 2137c478bd9Sstevel@tonic-gate break; 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate case 'M': 2167c478bd9Sstevel@tonic-gate mapdev = s_strdup(optarg); 2177c478bd9Sstevel@tonic-gate cap_m_option = 1; 2187c478bd9Sstevel@tonic-gate n++; 2197c478bd9Sstevel@tonic-gate break; 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate case 'L': 2227c478bd9Sstevel@tonic-gate list_option = 1; 2237c478bd9Sstevel@tonic-gate n++; 2247c478bd9Sstevel@tonic-gate break; 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate case 'l': 2277c478bd9Sstevel@tonic-gate list_option = 1; 2287c478bd9Sstevel@tonic-gate list_controllernum = (int)atol(optarg); 2297c478bd9Sstevel@tonic-gate if (list_controllernum < 0) { 2307c478bd9Sstevel@tonic-gate logerr(gettext("controller number %d is " 2317c478bd9Sstevel@tonic-gate "invalid\n"), list_controllernum); 2327c478bd9Sstevel@tonic-gate clean_exit(1); 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate n++; 2357c478bd9Sstevel@tonic-gate break; 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate case 'g': 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * private option to display non-STMS device name 2407c478bd9Sstevel@tonic-gate * to GUID mappings. 2417c478bd9Sstevel@tonic-gate */ 2427c478bd9Sstevel@tonic-gate list_guid_mappings = 1; 2437c478bd9Sstevel@tonic-gate break; 244*60fffc19Sjw149990 2455a4c37c9Sqh201292 case 'p': 2465a4c37c9Sqh201292 /* 2475a4c37c9Sqh201292 * map openable vhci based name to phci base name 2485a4c37c9Sqh201292 */ 2495a4c37c9Sqh201292 map_vhciname = s_strdup(optarg); 2505a4c37c9Sqh201292 n++; 2515a4c37c9Sqh201292 break; 2527c478bd9Sstevel@tonic-gate 253*60fffc19Sjw149990 case 'D': 254*60fffc19Sjw149990 /* 255*60fffc19Sjw149990 * Grab the driver name we need to look for. Each 256*60fffc19Sjw149990 * time we add support for a new SAS or FC driver 257*60fffc19Sjw149990 * to this utility, make sure that its driver name 258*60fffc19Sjw149990 * is checked here. 259*60fffc19Sjw149990 */ 260*60fffc19Sjw149990 drvname = s_malloc(sizeof (optarg) + 1); 261*60fffc19Sjw149990 drvname = s_strdup(optarg); 262*60fffc19Sjw149990 if (strcmp(drvname, "fp") == 0) { 263*60fffc19Sjw149990 drvprop = s_malloc(sizeof (NODE_WWN_PROP)); 264*60fffc19Sjw149990 (void) snprintf(drvprop, sizeof (NODE_WWN_PROP), 265*60fffc19Sjw149990 NODE_WWN_PROP); 266*60fffc19Sjw149990 } else if (strcmp(drvname, "mpt") == 0) { 267*60fffc19Sjw149990 drvprop = s_malloc(sizeof (SASPROP) + 268*60fffc19Sjw149990 sizeof (drvname) + 1); 269*60fffc19Sjw149990 (void) snprintf(drvprop, sizeof (SASPROP) + 270*60fffc19Sjw149990 sizeof (drvname), "%s%s", 271*60fffc19Sjw149990 SASPROP, drvname); 272*60fffc19Sjw149990 } else { 273*60fffc19Sjw149990 logerr(gettext("Driver %s is not supported\n"), 274*60fffc19Sjw149990 drvname); 275*60fffc19Sjw149990 clean_exit(1); 276*60fffc19Sjw149990 } 277*60fffc19Sjw149990 278*60fffc19Sjw149990 break; 279*60fffc19Sjw149990 280*60fffc19Sjw149990 case 'n': 281*60fffc19Sjw149990 ++parent; 282*60fffc19Sjw149990 n++; 283*60fffc19Sjw149990 break; 284*60fffc19Sjw149990 2857c478bd9Sstevel@tonic-gate default: 2867c478bd9Sstevel@tonic-gate usage(argv[0]); 2877c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate 291*60fffc19Sjw149990 if (n != 1) { 2927c478bd9Sstevel@tonic-gate usage(argv[0]); 2937c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2947c478bd9Sstevel@tonic-gate } 295*60fffc19Sjw149990 } 2967c478bd9Sstevel@tonic-gate 29780ab886dSwesolows int 2987c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 2997c478bd9Sstevel@tonic-gate { 3007c478bd9Sstevel@tonic-gate char save_vfstab[SYS_FILENAME_LEN], tmp_vfstab[SYS_FILENAME_LEN]; 3017c478bd9Sstevel@tonic-gate int vfstab_updated; 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 3047c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate if (getuid() != 0) { 3077c478bd9Sstevel@tonic-gate logerr(gettext("must be super-user to run this program\n")); 3087c478bd9Sstevel@tonic-gate clean_exit(1); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate parse_args(argc, argv); 3127c478bd9Sstevel@tonic-gate (void) umask(022); 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* 3157c478bd9Sstevel@tonic-gate * NOTE: The mpxio boot-up script executes this program with the 3167c478bd9Sstevel@tonic-gate * mapping (-m) option before the /usr is even mounted and when the 3177c478bd9Sstevel@tonic-gate * root filesystem is still mounted read-only. 3187c478bd9Sstevel@tonic-gate */ 3197c478bd9Sstevel@tonic-gate if (*mapdev != '\0') { 3207c478bd9Sstevel@tonic-gate char newname[MAXPATHLEN]; 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate if (map_devname(mapdev, newname, sizeof (newname), 3237c478bd9Sstevel@tonic-gate cap_m_option) == 0) { 3247c478bd9Sstevel@tonic-gate (void) printf("%s\n", newname); 3257c478bd9Sstevel@tonic-gate clean_exit(0); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate clean_exit(1); 3287c478bd9Sstevel@tonic-gate } 3295a4c37c9Sqh201292 if (*map_vhciname != '\0') { 3305a4c37c9Sqh201292 char newname[MAXPATHLEN]; 3315a4c37c9Sqh201292 3325a4c37c9Sqh201292 if (map_openable_vhciname(map_vhciname, newname, 3335a4c37c9Sqh201292 sizeof (newname)) == 0) { 3345a4c37c9Sqh201292 (void) printf("%s\n", newname); 3355a4c37c9Sqh201292 clean_exit(0); 3365a4c37c9Sqh201292 } 3375a4c37c9Sqh201292 clean_exit(1); 3385a4c37c9Sqh201292 } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate if (list_option || list_guid_mappings) { 3417c478bd9Sstevel@tonic-gate if (list_mappings(list_controllernum, list_guid_mappings) == 0) 3427c478bd9Sstevel@tonic-gate clean_exit(0); 3437c478bd9Sstevel@tonic-gate clean_exit(1); 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate 346*60fffc19Sjw149990 if (parent > 0) { 347*60fffc19Sjw149990 if (strcmp(drvname, "") == 0) { 348*60fffc19Sjw149990 usage(argv[0]); 349*60fffc19Sjw149990 clean_exit(1); 350*60fffc19Sjw149990 } else { 351*60fffc19Sjw149990 list_nodes(drvname); 352*60fffc19Sjw149990 clean_exit(0); 353*60fffc19Sjw149990 } 354*60fffc19Sjw149990 } 355*60fffc19Sjw149990 3567c478bd9Sstevel@tonic-gate /* create a directory where a copy of the system files are saved */ 3577c478bd9Sstevel@tonic-gate if (patch_vfstab) { 3587c478bd9Sstevel@tonic-gate if (mkdirp(SAVE_DIR, 0755) != 0 && errno != EEXIST) { 3597c478bd9Sstevel@tonic-gate logerr(gettext("mkdirp: failed to create %1$s: %2$s\n"), 3607c478bd9Sstevel@tonic-gate SAVE_DIR, strerror(errno)); 3617c478bd9Sstevel@tonic-gate clean_exit(1); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate if (make_temp(VFSTAB, save_vfstab, tmp_vfstab, 3657c478bd9Sstevel@tonic-gate SYS_FILENAME_LEN) != 0) 3667c478bd9Sstevel@tonic-gate clean_exit(1); 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate /* build new vfstab without modifying the existing one */ 3697c478bd9Sstevel@tonic-gate if ((vfstab_updated = update_vfstab(VFSTAB, tmp_vfstab)) 3707c478bd9Sstevel@tonic-gate == -1) { 3717c478bd9Sstevel@tonic-gate logerr(gettext("failed to update %s\n"), VFSTAB); 3727c478bd9Sstevel@tonic-gate clean_exit(1); 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate commit_change(VFSTAB, save_vfstab, tmp_vfstab, vfstab_updated); 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate clean_exit(0); 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate /* 3827c478bd9Sstevel@tonic-gate * Make saved and temporary filenames in SAVE_DIR. 3837c478bd9Sstevel@tonic-gate * 3847c478bd9Sstevel@tonic-gate * ex: if the filename is /etc/vfstab then the save_filename and tmp_filename 3857c478bd9Sstevel@tonic-gate * would be SAVE_DIR/vfstab and SAVE_DIR/vfstab.tmp respectively. 3867c478bd9Sstevel@tonic-gate * 3877c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 3887c478bd9Sstevel@tonic-gate */ 3897c478bd9Sstevel@tonic-gate static int 3907c478bd9Sstevel@tonic-gate make_temp(char *filename, char *save_filename, char *tmp_filename, size_t len) 3917c478bd9Sstevel@tonic-gate { 3927c478bd9Sstevel@tonic-gate char *ptr; 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate if ((ptr = strrchr(filename, '/')) == NULL) { 3957c478bd9Sstevel@tonic-gate logdmsg("invalid file %s\n", filename); 3967c478bd9Sstevel@tonic-gate return (-1); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate (void) snprintf(save_filename, len, "%s%s", SAVE_DIR, ptr); 3997c478bd9Sstevel@tonic-gate (void) snprintf(tmp_filename, len, "%s%s.tmp", SAVE_DIR, ptr); 4007c478bd9Sstevel@tonic-gate logdmsg("make_temp: %s: save = %s, temp = %s\n", filename, 4017c478bd9Sstevel@tonic-gate save_filename, tmp_filename); 4027c478bd9Sstevel@tonic-gate return (0); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate /* 4067c478bd9Sstevel@tonic-gate * Commit the changes made to the system file 4077c478bd9Sstevel@tonic-gate */ 4087c478bd9Sstevel@tonic-gate static void 4097c478bd9Sstevel@tonic-gate commit_change(char *filename, char *save_filename, char *tmp_filename, 4107c478bd9Sstevel@tonic-gate int updated) 4117c478bd9Sstevel@tonic-gate { 4127c478bd9Sstevel@tonic-gate int x; 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate if (updated) { 4157c478bd9Sstevel@tonic-gate /* save the original */ 4167c478bd9Sstevel@tonic-gate if ((x = rename(filename, save_filename)) != 0) { 4177c478bd9Sstevel@tonic-gate logerr(gettext("rename %1$s to %2$s failed: %3$s\n"), 4187c478bd9Sstevel@tonic-gate filename, save_filename, strerror(errno)); 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* now rename the new file to the actual file */ 4227c478bd9Sstevel@tonic-gate if (rename(tmp_filename, filename) != 0) { 4237c478bd9Sstevel@tonic-gate logerr(gettext("rename %1$s to %2$s failed: %3$s\n"), 4247c478bd9Sstevel@tonic-gate tmp_filename, filename, strerror(errno)); 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate /* restore the original */ 4277c478bd9Sstevel@tonic-gate if (x == 0 && rename(save_filename, filename) != 0) { 4287c478bd9Sstevel@tonic-gate logerr( 4297c478bd9Sstevel@tonic-gate gettext("rename %1$s to %2$s failed: %3$s\n" 4307c478bd9Sstevel@tonic-gate "%4$s is a copy of the original %5$s file" 4317c478bd9Sstevel@tonic-gate "\n"), 4327c478bd9Sstevel@tonic-gate save_filename, filename, strerror(errno), 4337c478bd9Sstevel@tonic-gate save_filename, filename); 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate } else 4367c478bd9Sstevel@tonic-gate (void) printf(gettext("%1$s: %2$s has been updated.\n"), 4377c478bd9Sstevel@tonic-gate stmsboot, filename); 4387c478bd9Sstevel@tonic-gate } else { 4397c478bd9Sstevel@tonic-gate /* remove the temp file */ 4407c478bd9Sstevel@tonic-gate (void) unlink(tmp_filename); 4417c478bd9Sstevel@tonic-gate (void) printf(gettext("%1$s: %2$s was not modified as no " 4427c478bd9Sstevel@tonic-gate "changes were needed.\n"), stmsboot, filename); 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate /* 4477c478bd9Sstevel@tonic-gate * Get the GUID of the device. 4487c478bd9Sstevel@tonic-gate * 4497c478bd9Sstevel@tonic-gate * physpath /devices name without the /devices prefix and minor name 4507c478bd9Sstevel@tonic-gate * component. 4517c478bd9Sstevel@tonic-gate * guid caller supplied buffer where the GUID will be placed on return 4527c478bd9Sstevel@tonic-gate * guid_len length of the caller supplied guid buffer. 453*60fffc19Sjw149990 * no_delay_flag if set open the device with O_NDELAY 4547c478bd9Sstevel@tonic-gate * node di_node corresponding to physpath if already available, 4557c478bd9Sstevel@tonic-gate * otherwise pass DI_NODE_NIL. 4567c478bd9Sstevel@tonic-gate * 4577c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 4587c478bd9Sstevel@tonic-gate */ 4597c478bd9Sstevel@tonic-gate static int 4607c478bd9Sstevel@tonic-gate get_guid(char *physpath, char *guid, int guid_len, int no_delay_flag, 4617c478bd9Sstevel@tonic-gate di_node_t node) 4627c478bd9Sstevel@tonic-gate { 4637c478bd9Sstevel@tonic-gate int fd; 4647c478bd9Sstevel@tonic-gate ddi_devid_t devid; 4657c478bd9Sstevel@tonic-gate int rv = -1; 4667c478bd9Sstevel@tonic-gate char *i_guid = NULL; 4677c478bd9Sstevel@tonic-gate char physpath_raw[MAXPATHLEN]; 4687c478bd9Sstevel@tonic-gate uchar_t *wwnp; 4697c478bd9Sstevel@tonic-gate int i, n, snapshot_taken = 0; 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate logdmsg("get_guid: physpath = %s\n", physpath); 4727c478bd9Sstevel@tonic-gate 4735a4c37c9Sqh201292 #ifdef sparc 4747c478bd9Sstevel@tonic-gate (void) snprintf(physpath_raw, MAXPATHLEN, 4757c478bd9Sstevel@tonic-gate "/devices%s:a,raw", physpath); 4765a4c37c9Sqh201292 #else 4775a4c37c9Sqh201292 (void) snprintf(physpath_raw, MAXPATHLEN, 4785a4c37c9Sqh201292 "/devices%s:c,raw", physpath); 4795a4c37c9Sqh201292 #endif 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate *guid = '\0'; 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate if (no_delay_flag) 4847c478bd9Sstevel@tonic-gate no_delay_flag = O_NDELAY; 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate /* 4877c478bd9Sstevel@tonic-gate * Open the raw device 4887c478bd9Sstevel@tonic-gate * Without the O_DELAY flag, the open will fail on standby paths of 4897c478bd9Sstevel@tonic-gate * T3 if its mp_support mode is "mpxio". 4907c478bd9Sstevel@tonic-gate */ 4917c478bd9Sstevel@tonic-gate if ((fd = open(physpath_raw, O_RDONLY | no_delay_flag)) == -1) { 4927c478bd9Sstevel@tonic-gate logdmsg("get_guid: failed to open %s: %s\n", physpath_raw, 4937c478bd9Sstevel@tonic-gate strerror(errno)); 4947c478bd9Sstevel@tonic-gate return (-1); 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate if (devid_get(fd, &devid) == 0) { 4987c478bd9Sstevel@tonic-gate i_guid = devid_to_guid(devid); 4997c478bd9Sstevel@tonic-gate devid_free(devid); 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate if (i_guid != NULL) { 5027c478bd9Sstevel@tonic-gate s_strlcpy(guid, i_guid, guid_len); 5037c478bd9Sstevel@tonic-gate devid_free_guid(i_guid); 5047c478bd9Sstevel@tonic-gate rv = 0; 5057c478bd9Sstevel@tonic-gate goto out; 506*60fffc19Sjw149990 } else { 5077c478bd9Sstevel@tonic-gate logdmsg("get_guid: devid_to_guid() failed\n"); 508*60fffc19Sjw149990 logdmsg("Unable to get a GUID for device " 509*60fffc19Sjw149990 "%s\n", physpath_raw); 510*60fffc19Sjw149990 } 511*60fffc19Sjw149990 5127c478bd9Sstevel@tonic-gate } else 5137c478bd9Sstevel@tonic-gate logdmsg("get_guid: devid_get() failed: %s\n", strerror(errno)); 5147c478bd9Sstevel@tonic-gate 515*60fffc19Sjw149990 /* 516*60fffc19Sjw149990 * Unless we're looking at an fp-attached device, we now 517*60fffc19Sjw149990 * fallback to node name as the guid as this is what the 518*60fffc19Sjw149990 * fcp driver does. A sas-attached device will have the 519*60fffc19Sjw149990 * client-guid property set. 520*60fffc19Sjw149990 */ 5217c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 5227c478bd9Sstevel@tonic-gate if ((node = di_init(physpath, DINFOCPYALL | DINFOFORCE)) 5237c478bd9Sstevel@tonic-gate == DI_NODE_NIL) { 5247c478bd9Sstevel@tonic-gate logdmsg("get_guid: di_init on %s failed: %s\n", 5257c478bd9Sstevel@tonic-gate physpath, strerror(errno)); 5267c478bd9Sstevel@tonic-gate goto out; 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate snapshot_taken = 1; 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 531*60fffc19Sjw149990 /* non-fp fallout */ 532*60fffc19Sjw149990 if (strstr(physpath, "fp") == (char *)NULL) { 533*60fffc19Sjw149990 if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, 534*60fffc19Sjw149990 "client-guid", &guid) < 0) { 535*60fffc19Sjw149990 logdmsg("get_guid: non-fp-attached device, " 536*60fffc19Sjw149990 "bailing out\n"); 537*60fffc19Sjw149990 goto out; 538*60fffc19Sjw149990 } 539*60fffc19Sjw149990 } 540*60fffc19Sjw149990 5417c478bd9Sstevel@tonic-gate if ((n = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, NODE_WWN_PROP, 5427c478bd9Sstevel@tonic-gate &wwnp)) == -1) { 5437c478bd9Sstevel@tonic-gate logdmsg("get_guid: di_prop_lookup_bytes() failed to lookup " 5447c478bd9Sstevel@tonic-gate "%s: %s\n", NODE_WWN_PROP, strerror(errno)); 5457c478bd9Sstevel@tonic-gate goto out; 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate if (guid_len >= ((n * 2) + 1)) { 5497c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) { 5507c478bd9Sstevel@tonic-gate (void) sprintf(guid + (i * 2), "%02x", (uint_t)(*wwnp)); 5517c478bd9Sstevel@tonic-gate wwnp++; 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate rv = 0; 5547c478bd9Sstevel@tonic-gate } else 5557c478bd9Sstevel@tonic-gate logerr(gettext("insufficient buffer size: need %1$d " 5567c478bd9Sstevel@tonic-gate "bytes, passed %2$d bytes\n"), (n * 2) + 1, guid_len); 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate out: 5597c478bd9Sstevel@tonic-gate if (snapshot_taken) 5607c478bd9Sstevel@tonic-gate di_fini(node); 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate (void) close(fd); 5637c478bd9Sstevel@tonic-gate logdmsg("get_guid: GUID = %s\n", guid); 5647c478bd9Sstevel@tonic-gate return (rv); 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate /* 5687c478bd9Sstevel@tonic-gate * Given client_name return whether it is a phci or vhci based name. 5697c478bd9Sstevel@tonic-gate * client_name is /devices name of a client without the /devices prefix. 5707c478bd9Sstevel@tonic-gate * 5717c478bd9Sstevel@tonic-gate * client_name Return value 5725a4c37c9Sqh201292 * on sparc: 573*60fffc19Sjw149990 * .../fp@xxx/ssd@yyy CLIENT_TYPE_PHCI (fc) 574*60fffc19Sjw149990 * .../LSILogic,sas@xxx/sd@yyy CLIENT_TYPE_PHCI (sas) 575*60fffc19Sjw149990 * .../scsi_vhci/ssd@yyy CLIENT_TYPE_VHCI (fc) 576*60fffc19Sjw149990 * .../scsi_vhci/disk@yyy CLIENT_TYPE_VHCI (sas) 5777c478bd9Sstevel@tonic-gate * other CLIENT_TYPE_UNKNOWN 5785a4c37c9Sqh201292 * on x86: 579*60fffc19Sjw149990 * .../fp@xxx/disk@yyy CLIENT_TYPE_PHCI (fc) 580*60fffc19Sjw149990 * .../pci1000,????@xxx/sd@yyy CLIENT_TYPE_PHCI (sas) 5815a4c37c9Sqh201292 * .../scsi_vhci/disk@yyy CLIENT_TYPE_VHCI 5825a4c37c9Sqh201292 * other CLIENT_TYPE_UNKNOWN 5837c478bd9Sstevel@tonic-gate */ 5847c478bd9Sstevel@tonic-gate static client_type_t 5857c478bd9Sstevel@tonic-gate client_name_type(char *client_name) 5867c478bd9Sstevel@tonic-gate { 5877c478bd9Sstevel@tonic-gate client_type_t client_type = CLIENT_TYPE_UNKNOWN; 588*60fffc19Sjw149990 char *p1; 589*60fffc19Sjw149990 char *client_path; 590*60fffc19Sjw149990 591*60fffc19Sjw149990 client_path = s_strdup(client_name); 592*60fffc19Sjw149990 logdmsg("client_name_type: client is %s\n", client_path); 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate if (*client_name != '/') 5957c478bd9Sstevel@tonic-gate return (CLIENT_TYPE_UNKNOWN); 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate if ((p1 = strrchr(client_name, '/')) == NULL || 598*60fffc19Sjw149990 ((strncmp(p1, "/ssd@", sizeof ("/ssd@") - 1) != 0) && 599*60fffc19Sjw149990 (strncmp(p1, "/sd@", sizeof ("/sd@") - 1) != 0) && 600*60fffc19Sjw149990 (strncmp(p1, "/disk@", sizeof ("/disk@") - 1) != 0))) { 601*60fffc19Sjw149990 logdmsg("client_name_type: p1 = %s\n", p1); 6027c478bd9Sstevel@tonic-gate return (CLIENT_TYPE_UNKNOWN); 603*60fffc19Sjw149990 } 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate *p1 = '\0'; 6067c478bd9Sstevel@tonic-gate 607*60fffc19Sjw149990 /* 608*60fffc19Sjw149990 * Courtesy of the if (..) block above, we know that any 609*60fffc19Sjw149990 * device path we have now is either PHCI or VHCI 610*60fffc19Sjw149990 */ 611*60fffc19Sjw149990 client_type = client_by_props(client_path); 612*60fffc19Sjw149990 613*60fffc19Sjw149990 logdmsg("client_name_type: client_type = %d\n", client_type); 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate *p1 = '/'; 6167c478bd9Sstevel@tonic-gate return (client_type); 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate /* 620*60fffc19Sjw149990 * client_by_props() is called to determine what the client type 621*60fffc19Sjw149990 * is, based on properties in the device tree: 622*60fffc19Sjw149990 * 623*60fffc19Sjw149990 * drivername property type 624*60fffc19Sjw149990 * ------------------------------------- 625*60fffc19Sjw149990 * fp node-wwn CLIENT_TYPE_PHCI 626*60fffc19Sjw149990 * mpt sas-mpt CLIENT_TYPE_PHCI 627*60fffc19Sjw149990 * mpt client-guid CLIENT_TYPE_PHCI (corner case) 628*60fffc19Sjw149990 * 629*60fffc19Sjw149990 * Normally, the "client-guid" property only shows up for a node 630*60fffc19Sjw149990 * if we've enumerated that node under scsi_vhci. During testing 631*60fffc19Sjw149990 * of this function, one particular corner case was found which 632*60fffc19Sjw149990 * requires an exception handler. 633*60fffc19Sjw149990 */ 634*60fffc19Sjw149990 635*60fffc19Sjw149990 static client_type_t 636*60fffc19Sjw149990 client_by_props(char *path) { 637*60fffc19Sjw149990 638*60fffc19Sjw149990 di_node_t clientnode = DI_NODE_NIL; 639*60fffc19Sjw149990 di_node_t parentnode = DI_NODE_NIL; 640*60fffc19Sjw149990 unsigned int rval = CLIENT_TYPE_UNKNOWN; 641*60fffc19Sjw149990 uchar_t *byteprop[32]; 642*60fffc19Sjw149990 char *charprop = NULL; 643*60fffc19Sjw149990 char *physpath; 644*60fffc19Sjw149990 char *parentpath; 645*60fffc19Sjw149990 646*60fffc19Sjw149990 physpath = s_malloc(MAXPATHLEN); 647*60fffc19Sjw149990 bzero(physpath, MAXPATHLEN); 648*60fffc19Sjw149990 649*60fffc19Sjw149990 physpath = s_strdup(path); 650*60fffc19Sjw149990 651*60fffc19Sjw149990 logdmsg("client_by_props: physpath = (%s)\n", physpath); 652*60fffc19Sjw149990 653*60fffc19Sjw149990 /* easy short-circuits */ 654*60fffc19Sjw149990 if (strstr(physpath, "scsi_vhci") != (char *)NULL) { 655*60fffc19Sjw149990 logdmsg("client_by_props: found " 656*60fffc19Sjw149990 "'scsi_vhci' on path (%s)\n", physpath); 657*60fffc19Sjw149990 rval = CLIENT_TYPE_VHCI; 658*60fffc19Sjw149990 goto out; 659*60fffc19Sjw149990 } else if ((strstr(physpath, "ide") != (char *)NULL) || 660*60fffc19Sjw149990 (strstr(physpath, "storage") != (char *)NULL)) { 661*60fffc19Sjw149990 logdmsg("client_by_props: ignoring this device\n"); 662*60fffc19Sjw149990 goto out; 663*60fffc19Sjw149990 } 664*60fffc19Sjw149990 665*60fffc19Sjw149990 parentpath = s_malloc(MAXPATHLEN); 666*60fffc19Sjw149990 bzero(parentpath, MAXPATHLEN); 667*60fffc19Sjw149990 668*60fffc19Sjw149990 (void) strncpy(parentpath, physpath, strlen(physpath) - 669*60fffc19Sjw149990 strlen(strrchr(physpath, '/'))); 670*60fffc19Sjw149990 671*60fffc19Sjw149990 if ((parentnode = di_init(parentpath, DINFOCPYALL | 672*60fffc19Sjw149990 DINFOFORCE)) == DI_NODE_NIL) { 673*60fffc19Sjw149990 logdmsg("client_by_props: unable to di_init(%s)\n", 674*60fffc19Sjw149990 parentpath); 675*60fffc19Sjw149990 goto out; 676*60fffc19Sjw149990 } 677*60fffc19Sjw149990 678*60fffc19Sjw149990 if (strstr(physpath, "fp") != (char *)NULL) { 679*60fffc19Sjw149990 if (drvprop == (char *)NULL) { 680*60fffc19Sjw149990 drvprop = s_malloc(strlen(NODE_WWN_PROP) + 1); 681*60fffc19Sjw149990 } 682*60fffc19Sjw149990 logdmsg("NODE_WWN_PROP\n"); 683*60fffc19Sjw149990 (void) snprintf(drvprop, strlen(NODE_WWN_PROP) + 1, 684*60fffc19Sjw149990 NODE_WWN_PROP); 685*60fffc19Sjw149990 } else { 686*60fffc19Sjw149990 if (drvname == (char *)NULL) { 687*60fffc19Sjw149990 drvname = di_driver_name(parentnode); 688*60fffc19Sjw149990 logdmsg("client_by_props: drvname = %s\n", drvname); 689*60fffc19Sjw149990 } 690*60fffc19Sjw149990 691*60fffc19Sjw149990 if (drvprop == (char *)NULL) { 692*60fffc19Sjw149990 drvprop = s_malloc(sizeof (SASPROP) + 693*60fffc19Sjw149990 sizeof (drvname) + 1); 694*60fffc19Sjw149990 } 695*60fffc19Sjw149990 (void) snprintf(drvprop, sizeof (SASPROP) + 696*60fffc19Sjw149990 sizeof (drvname), "%s%s", SASPROP, drvname); 697*60fffc19Sjw149990 698*60fffc19Sjw149990 logdmsg("parentpath: %s\nphyspath: %s\n" 699*60fffc19Sjw149990 "length %d, strrchr: %d\n", 700*60fffc19Sjw149990 parentpath, physpath, strlen(physpath), 701*60fffc19Sjw149990 strlen(strrchr(physpath, '/'))); 702*60fffc19Sjw149990 } 703*60fffc19Sjw149990 704*60fffc19Sjw149990 logdmsg("client_by_props: searching for property '%s'\n", drvprop); 705*60fffc19Sjw149990 706*60fffc19Sjw149990 if ((clientnode = di_init(physpath, DINFOCPYALL | DINFOFORCE)) == 707*60fffc19Sjw149990 DI_NODE_NIL) { 708*60fffc19Sjw149990 logdmsg("client_by_props: unable to di_init(%s)\n", 709*60fffc19Sjw149990 physpath); 710*60fffc19Sjw149990 711*60fffc19Sjw149990 /* 712*60fffc19Sjw149990 * On x86/x64 systems, we won't be able to di_init() the 713*60fffc19Sjw149990 * node we want in the device tree, however the parent 714*60fffc19Sjw149990 * node will still have 'mpxio-disable' set, so we can 715*60fffc19Sjw149990 * check for that property and make our decision on type 716*60fffc19Sjw149990 */ 717*60fffc19Sjw149990 718*60fffc19Sjw149990 if (di_prop_lookup_strings(DDI_DEV_T_ANY, parentnode, 719*60fffc19Sjw149990 "mpxio-disable", &charprop) > -1) { 720*60fffc19Sjw149990 rval = CLIENT_TYPE_PHCI; 721*60fffc19Sjw149990 di_fini(parentnode); 722*60fffc19Sjw149990 logdmsg("client_by_props: device %s is PHCI\n", 723*60fffc19Sjw149990 physpath); 724*60fffc19Sjw149990 } 725*60fffc19Sjw149990 goto out; 726*60fffc19Sjw149990 } 727*60fffc19Sjw149990 728*60fffc19Sjw149990 if (di_prop_lookup_bytes(DDI_DEV_T_ANY, 729*60fffc19Sjw149990 clientnode, drvprop, byteprop) > -1) { 730*60fffc19Sjw149990 logdmsg("client_by_props: found prop %s on " 731*60fffc19Sjw149990 "path %s\n", drvprop, physpath); 732*60fffc19Sjw149990 rval = CLIENT_TYPE_PHCI; 733*60fffc19Sjw149990 } else if (di_prop_lookup_strings(DDI_DEV_T_ANY, 734*60fffc19Sjw149990 clientnode, "client-guid", &charprop) > -1) { 735*60fffc19Sjw149990 /* 736*60fffc19Sjw149990 * A corner case was seen during testing where 737*60fffc19Sjw149990 * scsi_vhci was loaded, but not all applicable 738*60fffc19Sjw149990 * devices were enumerated under it. That left 739*60fffc19Sjw149990 * the phci mapping along with the "client-guid" 740*60fffc19Sjw149990 * property. 741*60fffc19Sjw149990 */ 742*60fffc19Sjw149990 logdmsg("client_by_props: weird... \n"); 743*60fffc19Sjw149990 rval = CLIENT_TYPE_PHCI; 744*60fffc19Sjw149990 } else { 745*60fffc19Sjw149990 logdmsg("client_by_props: unable to find " 746*60fffc19Sjw149990 "property 'client-guid', 'mpxio-disable' " 747*60fffc19Sjw149990 "or '%s' anywhere on path (%s)\n", 748*60fffc19Sjw149990 drvprop, physpath); 749*60fffc19Sjw149990 logdmsg("client_by_props: this node is unknown\n"); 750*60fffc19Sjw149990 } 751*60fffc19Sjw149990 752*60fffc19Sjw149990 di_fini(parentnode); 753*60fffc19Sjw149990 di_fini(clientnode); 754*60fffc19Sjw149990 out: 755*60fffc19Sjw149990 free(physpath); 756*60fffc19Sjw149990 return (rval); 757*60fffc19Sjw149990 } 758*60fffc19Sjw149990 759*60fffc19Sjw149990 760*60fffc19Sjw149990 /* 7617c478bd9Sstevel@tonic-gate * Map phci based client name to vhci based client name. 7627c478bd9Sstevel@tonic-gate * 7637c478bd9Sstevel@tonic-gate * phci_name 7647c478bd9Sstevel@tonic-gate * phci based client /devices name without the /devices prefix and 7657c478bd9Sstevel@tonic-gate * minor name component. 7665a4c37c9Sqh201292 * ex: 767*60fffc19Sjw149990 * 768*60fffc19Sjw149990 * (FC) 7695a4c37c9Sqh201292 * for sparc: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0 7705a4c37c9Sqh201292 * for x86: /pci@8,600000/SUNW,qlc@4/fp@0,0/disk@w2100002037cd9f72,0 7717c478bd9Sstevel@tonic-gate * 772*60fffc19Sjw149990 * (SAS) 773*60fffc19Sjw149990 * for sparc: /pci@0,2/LSILogic,sas@1/disk@6,0 774*60fffc19Sjw149990 * for x86: /pci1000,3060@3/sd@0,0 775*60fffc19Sjw149990 * 7767c478bd9Sstevel@tonic-gate * vhci_name 7777c478bd9Sstevel@tonic-gate * Caller supplied buffer where vhci /devices name will be placed on 7787c478bd9Sstevel@tonic-gate * return (without the /devices prefix and minor name component). 7795a4c37c9Sqh201292 * ex: 780*60fffc19Sjw149990 * 781*60fffc19Sjw149990 * (FC) 7825a4c37c9Sqh201292 * for sparc: /scsi_vhci/ssd@g2000002037cd9f72 7835a4c37c9Sqh201292 * for x86: /scsi_vhci/disk@g2000002037cd9f72 7847c478bd9Sstevel@tonic-gate * 785*60fffc19Sjw149990 * (SAS) 786*60fffc19Sjw149990 * both: /scsi_vhci/disk@g600a0b8000254d3e00000284453ed8ac 787*60fffc19Sjw149990 * 7887c478bd9Sstevel@tonic-gate * vhci_name_len 7897c478bd9Sstevel@tonic-gate * Length of the caller supplied vhci_name buffer. 7907c478bd9Sstevel@tonic-gate * 7917c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 7927c478bd9Sstevel@tonic-gate */ 7937c478bd9Sstevel@tonic-gate static int 7947c478bd9Sstevel@tonic-gate phci_to_vhci(char *phci_name, char *vhci_name, size_t vhci_name_len) 7957c478bd9Sstevel@tonic-gate { 7967c478bd9Sstevel@tonic-gate sv_iocdata_t ioc; 797*60fffc19Sjw149990 char *slash, *at; 7987c478bd9Sstevel@tonic-gate char vhci_name_buf[MAXPATHLEN]; 7997c478bd9Sstevel@tonic-gate char phci_name_buf[MAXPATHLEN]; 8007c478bd9Sstevel@tonic-gate char addr_buf[MAXNAMELEN]; 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate logdmsg("phci_to_vhci: client = %s\n", phci_name); 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate s_strlcpy(phci_name_buf, phci_name, MAXPATHLEN); 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate if (client_name_type(phci_name_buf) != CLIENT_TYPE_PHCI || 8077c478bd9Sstevel@tonic-gate (slash = strrchr(phci_name_buf, '/')) == NULL || 808*60fffc19Sjw149990 ((strncmp(slash, "/ssd@", sizeof ("/ssd@") - 1) != 0) && 809*60fffc19Sjw149990 (strncmp(slash, "/sd@", sizeof ("/sd@") - 1) != 0) && 810*60fffc19Sjw149990 (strncmp(slash, "/disk@", sizeof ("/disk@") - 1) != 0))) { 8117c478bd9Sstevel@tonic-gate logdmsg("phci_to_vhci: %s is not of CLIENT_TYPE_PHCI\n", 8127c478bd9Sstevel@tonic-gate phci_name); 8137c478bd9Sstevel@tonic-gate return (-1); 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate if (vhci_fd < 0) { 8177c478bd9Sstevel@tonic-gate if ((vhci_fd = open(VHCI_CTL_NODE, O_RDWR)) < 0) 8187c478bd9Sstevel@tonic-gate return (-1); 8197c478bd9Sstevel@tonic-gate } 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate *slash = '\0'; 822*60fffc19Sjw149990 823*60fffc19Sjw149990 at = strchr(slash + 1, '@'); 824*60fffc19Sjw149990 s_strlcpy(addr_buf, at + 1, MAXNAMELEN); 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate bzero(&ioc, sizeof (sv_iocdata_t)); 8277c478bd9Sstevel@tonic-gate ioc.client = vhci_name_buf; 8287c478bd9Sstevel@tonic-gate ioc.phci = phci_name_buf; 8297c478bd9Sstevel@tonic-gate ioc.addr = addr_buf; 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate if (ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_NAME, &ioc) != 0) { 8327c478bd9Sstevel@tonic-gate logdmsg("SCSI_VHCI_GET_CLIENT_NAME on %s " 8337c478bd9Sstevel@tonic-gate "failed: %s\n", phci_name, strerror(errno)); 8347c478bd9Sstevel@tonic-gate return (-1); 8357c478bd9Sstevel@tonic-gate } 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate s_strlcpy(vhci_name, vhci_name_buf, vhci_name_len); 8387c478bd9Sstevel@tonic-gate logdmsg("phci_to_vhci: %s maps to %s\n", phci_name, vhci_name); 8397c478bd9Sstevel@tonic-gate return (0); 8407c478bd9Sstevel@tonic-gate } 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate /* 8437c478bd9Sstevel@tonic-gate * Map vhci based client name to phci based client name. 8447c478bd9Sstevel@tonic-gate * If the client has multiple paths, only one of the paths with which client 8457c478bd9Sstevel@tonic-gate * can be accessed is returned. This function does not use SCSI_VHCI ioctls 8467c478bd9Sstevel@tonic-gate * as it is called on mpxio disabled paths. 8477c478bd9Sstevel@tonic-gate * 8487c478bd9Sstevel@tonic-gate * vhci_name 8497c478bd9Sstevel@tonic-gate * vhci based client /devices name without the /devices prefix and 8507c478bd9Sstevel@tonic-gate * minor name component. 8515a4c37c9Sqh201292 * ex: 8525a4c37c9Sqh201292 * sparc: /scsi_vhci/ssd@g2000002037cd9f72 8535a4c37c9Sqh201292 * x86: /scsi_vhci/disk@g2000002037cd9f72 8547c478bd9Sstevel@tonic-gate * 8557c478bd9Sstevel@tonic-gate * phci_name 8567c478bd9Sstevel@tonic-gate * Caller supplied buffer where phci /devices name will be placed on 8577c478bd9Sstevel@tonic-gate * return (without the /devices prefix and minor name component). 8585a4c37c9Sqh201292 * ex: 8595a4c37c9Sqh201292 * sparc: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0 8605a4c37c9Sqh201292 * x86: /pci@8,600000/SUNW,qlc@4/fp@0,0/disk@w2100002037cd9f72,0 8617c478bd9Sstevel@tonic-gate * 8627c478bd9Sstevel@tonic-gate * phci_name_len 8637c478bd9Sstevel@tonic-gate * Length of the caller supplied phci_name buffer. 8647c478bd9Sstevel@tonic-gate * 8657c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 8667c478bd9Sstevel@tonic-gate */ 8677c478bd9Sstevel@tonic-gate static int 8687c478bd9Sstevel@tonic-gate vhci_to_phci(char *vhci_name, char *phci_name, size_t phci_name_len) 8697c478bd9Sstevel@tonic-gate { 870*60fffc19Sjw149990 di_node_t node = DI_NODE_NIL; 8717c478bd9Sstevel@tonic-gate char *vhci_guid, *devfspath; 8727c478bd9Sstevel@tonic-gate char phci_guid[MAXPATHLEN]; 873*60fffc19Sjw149990 char *node_name; 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: client = %s\n", vhci_name); 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate if (client_name_type(vhci_name) != CLIENT_TYPE_VHCI) { 8787c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: %s is not of CLIENT_TYPE_VHCI\n", 8797c478bd9Sstevel@tonic-gate vhci_name); 8807c478bd9Sstevel@tonic-gate return (-1); 8817c478bd9Sstevel@tonic-gate } 8827c478bd9Sstevel@tonic-gate 883*60fffc19Sjw149990 8847c478bd9Sstevel@tonic-gate if ((vhci_guid = strrchr(vhci_name, '@')) == NULL || 8857c478bd9Sstevel@tonic-gate *(++vhci_guid) != 'g') { 8867c478bd9Sstevel@tonic-gate logerr(gettext("couldn't get guid from %s\n"), vhci_name); 8877c478bd9Sstevel@tonic-gate return (-1); 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate /* point to guid */ 8917c478bd9Sstevel@tonic-gate ++vhci_guid; 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate /* 8947c478bd9Sstevel@tonic-gate * Get devinfo snapshot and walk all ssd nodes whose parent is fp. 8957c478bd9Sstevel@tonic-gate * For each node get the guid and match it with vhci_guid. 8967c478bd9Sstevel@tonic-gate */ 8977c478bd9Sstevel@tonic-gate if (devinfo_root == DI_NODE_NIL) { 8987c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: taking devinfo snapshot\n"); 8997c478bd9Sstevel@tonic-gate if ((devinfo_root = di_init("/", DINFOCPYALL | DINFOFORCE)) 9007c478bd9Sstevel@tonic-gate == DI_NODE_NIL) { 9017c478bd9Sstevel@tonic-gate logerr(gettext("di_init failed: %s\n"), 9027c478bd9Sstevel@tonic-gate strerror(errno)); 9037c478bd9Sstevel@tonic-gate return (-1); 9047c478bd9Sstevel@tonic-gate } 9057c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: done taking devinfo snapshot\n"); 9067c478bd9Sstevel@tonic-gate } 9077c478bd9Sstevel@tonic-gate 908*60fffc19Sjw149990 909*60fffc19Sjw149990 /* 910*60fffc19Sjw149990 * When we finally get a unified "sd" driver for all 911*60fffc19Sjw149990 * architectures that Solaris runs on, we can remove this 912*60fffc19Sjw149990 * first loop around for "ssd" 913*60fffc19Sjw149990 */ 914*60fffc19Sjw149990 for (node = di_drv_first_node("ssd", devinfo_root); 9157c478bd9Sstevel@tonic-gate node != DI_NODE_NIL; node = di_drv_next_node(node)) { 916*60fffc19Sjw149990 917*60fffc19Sjw149990 if ((node_name = di_node_name(node)) == NULL) 918*60fffc19Sjw149990 continue; 919*60fffc19Sjw149990 920*60fffc19Sjw149990 if ((strcmp(node_name, "disk") != 0) && 921*60fffc19Sjw149990 (strcmp(node_name, "sd") != 0) && 922*60fffc19Sjw149990 (strcmp(node_name, "ssd") != 0)) 923*60fffc19Sjw149990 continue; 924*60fffc19Sjw149990 925*60fffc19Sjw149990 if (di_parent_node(node) == DI_NODE_NIL) 926*60fffc19Sjw149990 continue; 927*60fffc19Sjw149990 928*60fffc19Sjw149990 if ((devfspath = di_devfs_path(node)) == NULL) 9297c478bd9Sstevel@tonic-gate continue; 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate /* 9327c478bd9Sstevel@tonic-gate * Don't set no_delay_flag to have get_guid() fail on 9337c478bd9Sstevel@tonic-gate * standby paths of T3. So we'll find the preferred paths. 9347c478bd9Sstevel@tonic-gate */ 9357c478bd9Sstevel@tonic-gate if (get_guid(devfspath, phci_guid, 936*60fffc19Sjw149990 sizeof (phci_guid), 0, node) != 0) 937*60fffc19Sjw149990 continue; 938*60fffc19Sjw149990 939*60fffc19Sjw149990 if (strcmp(phci_guid, vhci_guid) == 0) { 940*60fffc19Sjw149990 s_strlcpy(phci_name, devfspath, phci_name_len); 941*60fffc19Sjw149990 di_devfs_path_free(devfspath); 942*60fffc19Sjw149990 logdmsg("vhci_to_phci: %s maps to %s\n", vhci_name, 943*60fffc19Sjw149990 phci_name); 944*60fffc19Sjw149990 return (0); 945*60fffc19Sjw149990 } 946*60fffc19Sjw149990 947*60fffc19Sjw149990 di_devfs_path_free(devfspath); 948*60fffc19Sjw149990 } 949*60fffc19Sjw149990 950*60fffc19Sjw149990 for (node = di_drv_first_node("sd", devinfo_root); 951*60fffc19Sjw149990 node != DI_NODE_NIL; node = di_drv_next_node(node)) { 952*60fffc19Sjw149990 953*60fffc19Sjw149990 if ((node_name = di_node_name(node)) == NULL) 954*60fffc19Sjw149990 continue; 955*60fffc19Sjw149990 956*60fffc19Sjw149990 if ((strcmp(node_name, "disk") != 0) && 957*60fffc19Sjw149990 (strcmp(node_name, "sd") != 0) && 958*60fffc19Sjw149990 (strcmp(node_name, "ssd") != 0)) 959*60fffc19Sjw149990 continue; 960*60fffc19Sjw149990 961*60fffc19Sjw149990 if (di_parent_node(node) == DI_NODE_NIL) 962*60fffc19Sjw149990 continue; 963*60fffc19Sjw149990 964*60fffc19Sjw149990 if ((devfspath = di_devfs_path(node)) == NULL) 965*60fffc19Sjw149990 continue; 966*60fffc19Sjw149990 967*60fffc19Sjw149990 /* 968*60fffc19Sjw149990 * Don't set no_delay_flag to have get_guid() fail on 969*60fffc19Sjw149990 * standby paths of T3. So we'll find the preferred paths. 970*60fffc19Sjw149990 */ 971*60fffc19Sjw149990 if (get_guid(devfspath, phci_guid, 972*60fffc19Sjw149990 sizeof (phci_guid), 0, node) != 0) 973*60fffc19Sjw149990 continue; 974*60fffc19Sjw149990 975*60fffc19Sjw149990 if (strcmp(phci_guid, vhci_guid) == 0) { 9767c478bd9Sstevel@tonic-gate s_strlcpy(phci_name, devfspath, phci_name_len); 9777c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 9787c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: %s maps to %s\n", vhci_name, 9797c478bd9Sstevel@tonic-gate phci_name); 9807c478bd9Sstevel@tonic-gate return (0); 9817c478bd9Sstevel@tonic-gate } 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 9847c478bd9Sstevel@tonic-gate } 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: couldn't get phci name for %s\n", vhci_name); 9877c478bd9Sstevel@tonic-gate return (-1); 9887c478bd9Sstevel@tonic-gate } 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate /* 9915a4c37c9Sqh201292 * Map vhci based client name to phci based client name. 9925a4c37c9Sqh201292 * If the client has multiple paths, only one of the paths with which client 9935a4c37c9Sqh201292 * can be accessed is returned. 9945a4c37c9Sqh201292 * This function uses SCSI_VHCI ioctls to get the phci paths 9955a4c37c9Sqh201292 * 9965a4c37c9Sqh201292 * vhci_name 9975a4c37c9Sqh201292 * vhci based client /devices name without the /devices prefix and 9985a4c37c9Sqh201292 * minor name component. 9995a4c37c9Sqh201292 * ex: 10005a4c37c9Sqh201292 * sparc: /scsi_vhci/ssd@g2000002037cd9f72 10015a4c37c9Sqh201292 * x86: /scsi_vhci/disk@g2000002037cd9f72 10025a4c37c9Sqh201292 * 10035a4c37c9Sqh201292 * phci_name 10045a4c37c9Sqh201292 * Caller supplied buffer where phci /devices name will be placed on 10055a4c37c9Sqh201292 * return (without the /devices prefix and minor name component). 10065a4c37c9Sqh201292 * ex: 10075a4c37c9Sqh201292 * sparc: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0 10085a4c37c9Sqh201292 * x86: /pci@8,600000/SUNW,qlc@4/fp@0,0/disk@w2100002037cd9f72,0 10095a4c37c9Sqh201292 * 10105a4c37c9Sqh201292 * phci_name_len 10115a4c37c9Sqh201292 * Length of the caller supplied phci_name buffer. 10125a4c37c9Sqh201292 * 10135a4c37c9Sqh201292 * Returns 0 on success, -1 on failure. 10145a4c37c9Sqh201292 */ 10155a4c37c9Sqh201292 10165a4c37c9Sqh201292 static int 10175a4c37c9Sqh201292 vhci_to_phci_by_ioctl(char *vhci_name, char *phci_name, size_t phci_name_len) 10185a4c37c9Sqh201292 { 10195a4c37c9Sqh201292 sv_iocdata_t ioc; 10205a4c37c9Sqh201292 uint_t npaths; 10215a4c37c9Sqh201292 char *node_name, *at; 10225a4c37c9Sqh201292 char vhci_name_buf[MAXPATHLEN]; 10235a4c37c9Sqh201292 int ret; 10245a4c37c9Sqh201292 sv_path_info_t *pi; 10255a4c37c9Sqh201292 10265a4c37c9Sqh201292 logdmsg("vhci_to_phci_by_ioctl: client = %s\n", vhci_name); 10275a4c37c9Sqh201292 10285a4c37c9Sqh201292 if (vhci_fd < 0) { 10295a4c37c9Sqh201292 if ((vhci_fd = open(VHCI_CTL_NODE, O_RDWR)) < 0) 10305a4c37c9Sqh201292 return (-1); 10315a4c37c9Sqh201292 } 10325a4c37c9Sqh201292 10335a4c37c9Sqh201292 (void) strlcpy(vhci_name_buf, vhci_name, MAXPATHLEN); 10345a4c37c9Sqh201292 10355a4c37c9Sqh201292 /* first get the number paths */ 10365a4c37c9Sqh201292 bzero(&ioc, sizeof (sv_iocdata_t)); 10375a4c37c9Sqh201292 ioc.client = vhci_name_buf; 10385a4c37c9Sqh201292 ioc.ret_elem = &npaths; 10395a4c37c9Sqh201292 if ((ret = ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, 10405a4c37c9Sqh201292 &ioc)) != 0 || npaths == 0) { 10415a4c37c9Sqh201292 logdmsg("SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO on %s " 10425a4c37c9Sqh201292 "failed: %s\n", vhci_name, 10435a4c37c9Sqh201292 ret?strerror(errno):"got 0 paths"); 10445a4c37c9Sqh201292 return (-1); 10455a4c37c9Sqh201292 } 10465a4c37c9Sqh201292 10475a4c37c9Sqh201292 /* now allocate memory for the path information and get all paths */ 10485a4c37c9Sqh201292 bzero(&ioc, sizeof (sv_iocdata_t)); 10495a4c37c9Sqh201292 ioc.client = vhci_name_buf; 10505a4c37c9Sqh201292 ioc.buf_elem = npaths; 10515a4c37c9Sqh201292 ioc.ret_elem = &npaths; 10525a4c37c9Sqh201292 if ((ioc.ret_buf = (sv_path_info_t *)calloc(npaths, 10535a4c37c9Sqh201292 sizeof (sv_path_info_t))) == NULL) 10545a4c37c9Sqh201292 return (-1); 10555a4c37c9Sqh201292 if ((ret = ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, 10565a4c37c9Sqh201292 &ioc)) != 0 || npaths == 0) { 10575a4c37c9Sqh201292 logdmsg("SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO on %s " 10585a4c37c9Sqh201292 "failed: %s\n", vhci_name, 10595a4c37c9Sqh201292 ret?strerror(errno):"got 0 paths"); 10605a4c37c9Sqh201292 goto out; 10615a4c37c9Sqh201292 } 10625a4c37c9Sqh201292 10635a4c37c9Sqh201292 if (ioc.buf_elem < npaths) 10645a4c37c9Sqh201292 npaths = ioc.buf_elem; 10655a4c37c9Sqh201292 if ((node_name = strrchr(vhci_name_buf, '/')) == NULL || 10665a4c37c9Sqh201292 (at = strchr(node_name, '@')) == NULL) 10675a4c37c9Sqh201292 goto out; 10685a4c37c9Sqh201292 10695a4c37c9Sqh201292 node_name++; 10705a4c37c9Sqh201292 *at = '\0'; 10715a4c37c9Sqh201292 1072*60fffc19Sjw149990 logdmsg("vhci_to_phci_by_ioctl: node_name is %s\n", node_name); 1073*60fffc19Sjw149990 #ifndef sparc 1074*60fffc19Sjw149990 /* 1075*60fffc19Sjw149990 * We need to use a libdevinfo call to get this info 1076*60fffc19Sjw149990 * in an architecturally-neutral fashion. Phase-II for sure! 1077*60fffc19Sjw149990 */ 1078*60fffc19Sjw149990 node_name = "sd"; 1079*60fffc19Sjw149990 #endif 1080*60fffc19Sjw149990 10815a4c37c9Sqh201292 /* 10825a4c37c9Sqh201292 * return the first online paths as non-online paths may 10835a4c37c9Sqh201292 * not be accessible in the target environment. 10845a4c37c9Sqh201292 */ 10855a4c37c9Sqh201292 pi = (sv_path_info_t *)ioc.ret_buf; 10865a4c37c9Sqh201292 while (npaths--) { 10875a4c37c9Sqh201292 if (MDI_PATHINFO_STATE_ONLINE == pi->ret_state) { 10885a4c37c9Sqh201292 (void) snprintf(phci_name, phci_name_len, "%s/%s@%s", 10895a4c37c9Sqh201292 pi->device.ret_phci, node_name, 10905a4c37c9Sqh201292 pi->ret_addr); 10915a4c37c9Sqh201292 logdmsg("vhci_to_phci_by_ioctl: %s maps to %s\n", 10925a4c37c9Sqh201292 vhci_name, phci_name); 10935a4c37c9Sqh201292 free(ioc.ret_buf); 10945a4c37c9Sqh201292 return (0); 10955a4c37c9Sqh201292 } 10965a4c37c9Sqh201292 pi++; 10975a4c37c9Sqh201292 } 10985a4c37c9Sqh201292 10995a4c37c9Sqh201292 out: 11005a4c37c9Sqh201292 logdmsg("vhci_to_phci_by_ioctl: couldn't get phci name for %s\n", 11015a4c37c9Sqh201292 vhci_name); 11025a4c37c9Sqh201292 free(ioc.ret_buf); 11035a4c37c9Sqh201292 return (-1); 11045a4c37c9Sqh201292 11055a4c37c9Sqh201292 } 11065a4c37c9Sqh201292 11075a4c37c9Sqh201292 /* 11087c478bd9Sstevel@tonic-gate * Map physname from phci name space to vhci name space or vice-versa 11097c478bd9Sstevel@tonic-gate * 11107c478bd9Sstevel@tonic-gate * physname 11117c478bd9Sstevel@tonic-gate * phci or vhci based client /devices name without the /devices prefix and 11127c478bd9Sstevel@tonic-gate * minor name component. 11137c478bd9Sstevel@tonic-gate * 11147c478bd9Sstevel@tonic-gate * new_physname 11157c478bd9Sstevel@tonic-gate * Caller supplied buffer where the mapped physical name is stored on 11167c478bd9Sstevel@tonic-gate * return (without the /devices prefix and minor name component). 11177c478bd9Sstevel@tonic-gate * 11187c478bd9Sstevel@tonic-gate * len 11197c478bd9Sstevel@tonic-gate * Length of the caller supplied new_physname buffer. 11207c478bd9Sstevel@tonic-gate * 11217c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 11227c478bd9Sstevel@tonic-gate */ 11237c478bd9Sstevel@tonic-gate static int 11247c478bd9Sstevel@tonic-gate map_physname(char *physname, char *new_physname, size_t len) 11257c478bd9Sstevel@tonic-gate { 11267c478bd9Sstevel@tonic-gate int type; 11277c478bd9Sstevel@tonic-gate int rv; 11287c478bd9Sstevel@tonic-gate 1129*60fffc19Sjw149990 type = client_name_type(physname); 1130*60fffc19Sjw149990 logdmsg("map_physname: type (%d) physname = %s\n", 1131*60fffc19Sjw149990 type, physname); 1132*60fffc19Sjw149990 1133*60fffc19Sjw149990 if (type == CLIENT_TYPE_VHCI) 11347c478bd9Sstevel@tonic-gate rv = vhci_to_phci(physname, new_physname, len); 11357c478bd9Sstevel@tonic-gate else if (type == CLIENT_TYPE_PHCI) 11367c478bd9Sstevel@tonic-gate rv = phci_to_vhci(physname, new_physname, len); 11377c478bd9Sstevel@tonic-gate else 11387c478bd9Sstevel@tonic-gate rv = -1; 11397c478bd9Sstevel@tonic-gate 1140*60fffc19Sjw149990 logdmsg("map_physname: returning %d\n", rv); 11417c478bd9Sstevel@tonic-gate return (rv); 11427c478bd9Sstevel@tonic-gate } 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate /* 11457c478bd9Sstevel@tonic-gate * Given a phci or vhci devname which is either a /dev link or /devices name 11467c478bd9Sstevel@tonic-gate * get the corresponding physical node path (without the /devices prefix) 11477c478bd9Sstevel@tonic-gate * and minor name. 11487c478bd9Sstevel@tonic-gate * 11497c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 11507c478bd9Sstevel@tonic-gate */ 11517c478bd9Sstevel@tonic-gate static int 11527c478bd9Sstevel@tonic-gate get_physname_minor(char *devname, char *physname, int physname_len, 11537c478bd9Sstevel@tonic-gate char *minorname, int minorname_len) 11547c478bd9Sstevel@tonic-gate { 11557c478bd9Sstevel@tonic-gate int linksize; 11567c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 11577c478bd9Sstevel@tonic-gate char *p, *m; 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate if (strncmp(devname, DEV_DSK, sizeof (DEV_DSK) - 1) == 0 || 11607c478bd9Sstevel@tonic-gate strncmp(devname, DEV_RDSK, sizeof (DEV_RDSK) - 1) == 0) { 11617c478bd9Sstevel@tonic-gate if ((linksize = readlink(devname, buf, MAXPATHLEN)) 11627c478bd9Sstevel@tonic-gate > 0 && linksize <= (MAXPATHLEN - 1)) { 11637c478bd9Sstevel@tonic-gate buf[linksize] = '\0'; 11647c478bd9Sstevel@tonic-gate } else 11657c478bd9Sstevel@tonic-gate return (-1); 11667c478bd9Sstevel@tonic-gate } else 11677c478bd9Sstevel@tonic-gate s_strlcpy(buf, devname, MAXPATHLEN); 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate if ((p = strstr(buf, SLASH_DEVICES)) == NULL) 11707c478bd9Sstevel@tonic-gate return (-1); 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate /* point to '/' after /devices */ 11737c478bd9Sstevel@tonic-gate p += sizeof (SLASH_DEVICES) - 2; 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate if ((m = strrchr(p, ':')) == NULL) { 11767c478bd9Sstevel@tonic-gate logdmsg("get_physname_minor: no minor name component in %s\n", 11777c478bd9Sstevel@tonic-gate buf); 11787c478bd9Sstevel@tonic-gate return (-1); 11797c478bd9Sstevel@tonic-gate } 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate *m = '\0'; 11827c478bd9Sstevel@tonic-gate m++; 11837c478bd9Sstevel@tonic-gate 11847c478bd9Sstevel@tonic-gate if (client_name_type(p) == CLIENT_TYPE_UNKNOWN) 11857c478bd9Sstevel@tonic-gate return (-1); 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate s_strlcpy(physname, p, physname_len); 11887c478bd9Sstevel@tonic-gate s_strlcpy(minorname, m, minorname_len); 11897c478bd9Sstevel@tonic-gate logdmsg("get_physname_minor: %s: physname = %s, minor = %s\n", 11907c478bd9Sstevel@tonic-gate devname, physname, minorname); 11917c478bd9Sstevel@tonic-gate return (0); 11927c478bd9Sstevel@tonic-gate } 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate static int 11957c478bd9Sstevel@tonic-gate devlink_callback(di_devlink_t devlink, void *argptr) 11967c478bd9Sstevel@tonic-gate { 11977c478bd9Sstevel@tonic-gate const char *link; 11987c478bd9Sstevel@tonic-gate struct devlink_cbarg *argp = argptr; 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate if ((link = di_devlink_path(devlink)) != NULL) { 12017c478bd9Sstevel@tonic-gate s_strlcpy(argp->devlink, link, argp->len); 12027c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 12067c478bd9Sstevel@tonic-gate } 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate /* 12097c478bd9Sstevel@tonic-gate * Lookup the /dev link corresponding to physname and minorname. 12107c478bd9Sstevel@tonic-gate * 12117c478bd9Sstevel@tonic-gate * physname client /devices path without the /devices prefix and minor 12127c478bd9Sstevel@tonic-gate * name component. 12137c478bd9Sstevel@tonic-gate * minorname client minor name. 12147c478bd9Sstevel@tonic-gate * devlink caller supplied buffer where the /dev link is placed on return. 12157c478bd9Sstevel@tonic-gate * len caller supplied devlink buffer length 12167c478bd9Sstevel@tonic-gate * 12177c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 12187c478bd9Sstevel@tonic-gate */ 12197c478bd9Sstevel@tonic-gate static int 12207c478bd9Sstevel@tonic-gate lookup_devlink(char *physname, char *minorname, char *devlink, size_t len) 12217c478bd9Sstevel@tonic-gate { 12227c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 12237c478bd9Sstevel@tonic-gate struct devlink_cbarg arg; 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate if (devlink_hdl == NULL) { 12267c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: taking devlink snapshot\n"); 12277c478bd9Sstevel@tonic-gate if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 12287c478bd9Sstevel@tonic-gate logerr(gettext("di_devlink_init failed: %s\n"), 12297c478bd9Sstevel@tonic-gate strerror(errno)); 12307c478bd9Sstevel@tonic-gate clean_exit(1); 12317c478bd9Sstevel@tonic-gate } 12327c478bd9Sstevel@tonic-gate } 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate *devlink = '\0'; 12357c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, "%s:%s", physname, minorname); 12367c478bd9Sstevel@tonic-gate arg.devlink = devlink; 12377c478bd9Sstevel@tonic-gate arg.len = len; 12387c478bd9Sstevel@tonic-gate if (di_devlink_walk(devlink_hdl, NULL, buf, DI_PRIMARY_LINK, &arg, 12397c478bd9Sstevel@tonic-gate devlink_callback) != 0) { 12407c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: di_devlink_walk on %s failed: %s\n", 12417c478bd9Sstevel@tonic-gate buf, strerror(errno)); 12427c478bd9Sstevel@tonic-gate return (-1); 12437c478bd9Sstevel@tonic-gate } 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate if (*devlink == '\0') { 12467c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: failed to lookup devlink for %s\n", 12477c478bd9Sstevel@tonic-gate buf); 12487c478bd9Sstevel@tonic-gate return (-1); 12497c478bd9Sstevel@tonic-gate } 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: /dev link for %s:%s = %s\n", physname, 12527c478bd9Sstevel@tonic-gate minorname, devlink); 12537c478bd9Sstevel@tonic-gate return (0); 12547c478bd9Sstevel@tonic-gate } 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate /* 12577c478bd9Sstevel@tonic-gate * open infile for reading and return its file pointer in *fp_in. 12587c478bd9Sstevel@tonic-gate * open outfile for writing and return its file pointer in *fp_out. 12597c478bd9Sstevel@tonic-gate * 12607c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 12617c478bd9Sstevel@tonic-gate */ 12627c478bd9Sstevel@tonic-gate static int 12637c478bd9Sstevel@tonic-gate open_in_out_files(char *infile, char *outfile, FILE **fp_in, FILE **fp_out) 12647c478bd9Sstevel@tonic-gate { 12657c478bd9Sstevel@tonic-gate FILE *fin = NULL; 12667c478bd9Sstevel@tonic-gate FILE *fout = NULL; 12677c478bd9Sstevel@tonic-gate struct stat sbuf; 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate if ((fin = fopen(infile, "r")) == NULL) { 12707c478bd9Sstevel@tonic-gate logerr(gettext("failed to fopen %1$s: %2$s\n"), 12717c478bd9Sstevel@tonic-gate infile, strerror(errno)); 12727c478bd9Sstevel@tonic-gate goto out; 12737c478bd9Sstevel@tonic-gate } 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate if (fstat(fileno(fin), &sbuf) != 0) { 12767c478bd9Sstevel@tonic-gate logerr(gettext("fstat failed on %1$s: %2$s\n"), 12777c478bd9Sstevel@tonic-gate infile, strerror(errno)); 12787c478bd9Sstevel@tonic-gate goto out; 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate if ((fout = fopen(outfile, "w")) == NULL) { 12827c478bd9Sstevel@tonic-gate logerr(gettext("failed to fopen %1$s: %2$s\n"), 12837c478bd9Sstevel@tonic-gate outfile, strerror(errno)); 12847c478bd9Sstevel@tonic-gate goto out; 12857c478bd9Sstevel@tonic-gate } 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate if (fchmod(fileno(fout), (sbuf.st_mode & 0777)) != 0) { 12887c478bd9Sstevel@tonic-gate logerr(gettext("failed to fchmod %1$s to 0%2$o: %3$s\n"), 12897c478bd9Sstevel@tonic-gate outfile, sbuf.st_mode & 0777, strerror(errno)); 12907c478bd9Sstevel@tonic-gate goto out; 12917c478bd9Sstevel@tonic-gate } 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate if (fchown(fileno(fout), sbuf.st_uid, sbuf.st_gid) != 0) { 12947c478bd9Sstevel@tonic-gate logerr(gettext("failed to fchown %1$s to uid %2$d and " 12957c478bd9Sstevel@tonic-gate "gid %3$d: %4$s\n"), 12967c478bd9Sstevel@tonic-gate outfile, sbuf.st_uid, sbuf.st_gid, strerror(errno)); 12977c478bd9Sstevel@tonic-gate goto out; 12987c478bd9Sstevel@tonic-gate } 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate *fp_in = fin; 13017c478bd9Sstevel@tonic-gate *fp_out = fout; 13027c478bd9Sstevel@tonic-gate return (0); 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate out: 13057c478bd9Sstevel@tonic-gate if (fin != NULL) 13067c478bd9Sstevel@tonic-gate (void) fclose(fin); 13077c478bd9Sstevel@tonic-gate if (fout != NULL) 13087c478bd9Sstevel@tonic-gate (void) fclose(fout); 13097c478bd9Sstevel@tonic-gate return (-1); 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate 13127c478bd9Sstevel@tonic-gate /* 13137c478bd9Sstevel@tonic-gate * If the devname is a phci based name and not open-able, map it to vhci 13147c478bd9Sstevel@tonic-gate * based name. If the devname is a vhci based name and not open-able, map it 13157c478bd9Sstevel@tonic-gate * to phci based name. 13167c478bd9Sstevel@tonic-gate * 13177c478bd9Sstevel@tonic-gate * devname either a /dev link or /devices name to client device 13187c478bd9Sstevel@tonic-gate * new_devname caller supplied buffer where the mapped device name is 13197c478bd9Sstevel@tonic-gate * placed on return. 13207c478bd9Sstevel@tonic-gate * len caller supplied new_devname buffer length 13217c478bd9Sstevel@tonic-gate * devlink_flag pass 1 if requesting the /dev link to the mapped device. 13227c478bd9Sstevel@tonic-gate * pass 0 if requesting the /devices name of the mapped device. 13237c478bd9Sstevel@tonic-gate * 13247c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 13257c478bd9Sstevel@tonic-gate */ 13267c478bd9Sstevel@tonic-gate static int 13277c478bd9Sstevel@tonic-gate map_devname(char *devname, char *new_devname, size_t len, int devlink_flag) 13287c478bd9Sstevel@tonic-gate { 13297c478bd9Sstevel@tonic-gate char physname[MAXPATHLEN]; 13307c478bd9Sstevel@tonic-gate char minor[MAXNAMELEN]; 13315a4c37c9Sqh201292 char new_physname[MAXPATHLEN]; 13327c478bd9Sstevel@tonic-gate 1333*60fffc19Sjw149990 logdmsg("map_devname: checking devname %s\n", devname); 1334*60fffc19Sjw149990 if ((get_physname_minor(devname, physname, sizeof (physname), 1335*60fffc19Sjw149990 minor, sizeof (minor)) == 0) && 1336*60fffc19Sjw149990 (canopen(devname) == 0) && 1337*60fffc19Sjw149990 (map_physname(physname, new_physname, 1338*60fffc19Sjw149990 sizeof (new_physname)) == 0)) { 1339*60fffc19Sjw149990 1340*60fffc19Sjw149990 logdmsg("map_devname: now looking up devlink\n"); 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate if (devlink_flag) { 13437c478bd9Sstevel@tonic-gate if (lookup_devlink(new_physname, minor, new_devname, 13447c478bd9Sstevel@tonic-gate len) == 0) 13457c478bd9Sstevel@tonic-gate return (0); 13467c478bd9Sstevel@tonic-gate } else { 13477c478bd9Sstevel@tonic-gate (void) snprintf(new_devname, len, "/devices%s:%s", 13487c478bd9Sstevel@tonic-gate new_physname, minor); 13497c478bd9Sstevel@tonic-gate return (0); 13507c478bd9Sstevel@tonic-gate } 13517c478bd9Sstevel@tonic-gate } 13527c478bd9Sstevel@tonic-gate 1353*60fffc19Sjw149990 logdmsg("map_devname: failed to find mapping for %s\n", devname); 13547c478bd9Sstevel@tonic-gate return (-1); 13557c478bd9Sstevel@tonic-gate } 13567c478bd9Sstevel@tonic-gate 13577c478bd9Sstevel@tonic-gate /* 13585a4c37c9Sqh201292 * If the devname is a vhci based name and open-able, map it to phci 13595a4c37c9Sqh201292 * based name. 13605a4c37c9Sqh201292 * 13615a4c37c9Sqh201292 * devname either a /dev link or /devices name to client device 13625a4c37c9Sqh201292 * new_devname caller supplied buffer where the mapped device name without 13635a4c37c9Sqh201292 * /devices prefix is placed on return. 13645a4c37c9Sqh201292 * len caller supplied new_devname buffer length 13655a4c37c9Sqh201292 */ 13665a4c37c9Sqh201292 static int 13675a4c37c9Sqh201292 map_openable_vhciname(char *devname, char *new_devname, size_t len) 13685a4c37c9Sqh201292 { 13695a4c37c9Sqh201292 char physname[MAXPATHLEN]; 13705a4c37c9Sqh201292 char minor[MAXNAMELEN]; 13715a4c37c9Sqh201292 char new_physname[MAXPATHLEN]; 13725a4c37c9Sqh201292 13735a4c37c9Sqh201292 if (get_physname_minor(devname, physname, sizeof (physname), 13745a4c37c9Sqh201292 minor, sizeof (minor)) == 0 && 13755a4c37c9Sqh201292 canopen(devname) == 1 && 13765a4c37c9Sqh201292 client_name_type(physname) == CLIENT_TYPE_VHCI && 13775a4c37c9Sqh201292 vhci_to_phci_by_ioctl(physname, new_physname, 13785a4c37c9Sqh201292 sizeof (new_physname)) == 0) { 13795a4c37c9Sqh201292 (void) snprintf(new_devname, len, "%s:%s", 13805a4c37c9Sqh201292 new_physname, minor); 13815a4c37c9Sqh201292 return (0); 13825a4c37c9Sqh201292 } 13835a4c37c9Sqh201292 13845a4c37c9Sqh201292 return (-1); 13855a4c37c9Sqh201292 } 13865a4c37c9Sqh201292 /* 13877c478bd9Sstevel@tonic-gate * Make a new /etc/vfstab: 13887c478bd9Sstevel@tonic-gate * Read vfstab_in, convert the device name entries to appropriate vhci or phci 13897c478bd9Sstevel@tonic-gate * based names, and write to vfstab_out. Only device names whose physical 13907c478bd9Sstevel@tonic-gate * paths are either phci or vhci based names and not open-able are considered 13917c478bd9Sstevel@tonic-gate * for conversion. Open-able device name entries are not converted as it 13927c478bd9Sstevel@tonic-gate * means that the device is already accessible; hence no need to convert. 13937c478bd9Sstevel@tonic-gate * 13947c478bd9Sstevel@tonic-gate * Returns: 13957c478bd9Sstevel@tonic-gate * 0 successful but vfstab_out contents are the same as vfstab_in 13967c478bd9Sstevel@tonic-gate * 1 successful and vfstab_out changed from vfstab_in 13977c478bd9Sstevel@tonic-gate * -1 failed 13987c478bd9Sstevel@tonic-gate */ 13997c478bd9Sstevel@tonic-gate static int 14007c478bd9Sstevel@tonic-gate update_vfstab(char *vfstab_in, char *vfstab_out) 14017c478bd9Sstevel@tonic-gate { 14027c478bd9Sstevel@tonic-gate FILE *fp_in, *fp_out; 14037c478bd9Sstevel@tonic-gate char *buf, *tmpbuf; 14047c478bd9Sstevel@tonic-gate char *vfs_cache[2]; 14057c478bd9Sstevel@tonic-gate int idx = 0, count = 0; 14067c478bd9Sstevel@tonic-gate int rv = -1; 14077c478bd9Sstevel@tonic-gate int vfstab_updated = 0; 14087c478bd9Sstevel@tonic-gate int i; 14097c478bd9Sstevel@tonic-gate char cdev[MAXPATHLEN]; 14107c478bd9Sstevel@tonic-gate char bdev[MAXPATHLEN]; 14117c478bd9Sstevel@tonic-gate char mntpt[MAXPATHLEN]; 14127c478bd9Sstevel@tonic-gate char fstype[512]; 14137c478bd9Sstevel@tonic-gate char fsckpass[512]; 14147c478bd9Sstevel@tonic-gate char mntboot[512]; 14157c478bd9Sstevel@tonic-gate char mntopt[MAX_MNTOPT_STR]; 14167c478bd9Sstevel@tonic-gate char phys_bdev[MAXPATHLEN], phys_cdev[MAXPATHLEN]; 14177c478bd9Sstevel@tonic-gate char bdev_minor[MAXNAMELEN], cdev_minor[MAXNAMELEN]; 14187c478bd9Sstevel@tonic-gate char new_physname[MAXPATHLEN]; 14197c478bd9Sstevel@tonic-gate char new_bdevlink[MAXPATHLEN], new_cdevlink[MAXPATHLEN]; 14207c478bd9Sstevel@tonic-gate char fmt[80]; 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate if (open_in_out_files(vfstab_in, vfstab_out, &fp_in, &fp_out) != 0) 14237c478bd9Sstevel@tonic-gate return (-1); 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate /* 14267c478bd9Sstevel@tonic-gate * Read one line at time from vfstab_in. If no conversion is needed 14277c478bd9Sstevel@tonic-gate * for the line simply write the line to vfstab_out. If conversion is 14287c478bd9Sstevel@tonic-gate * needed, first write the existing line as a comment to vfstab_out 14297c478bd9Sstevel@tonic-gate * and then write the converted line. 14307c478bd9Sstevel@tonic-gate * 14317c478bd9Sstevel@tonic-gate * To avoid commented entries piling up in vfstab in case if the 14327c478bd9Sstevel@tonic-gate * user runs stmsboot multiple times to switch on and off from mpxio, 14337c478bd9Sstevel@tonic-gate * add the commented line only if not already there. To do this 14347c478bd9Sstevel@tonic-gate * cache the last two vfstab lines processed and add the commented 14357c478bd9Sstevel@tonic-gate * entry only if it is not found in the cache. We only need to cache 14367c478bd9Sstevel@tonic-gate * the last two lines because a device can have at most two names - 14377c478bd9Sstevel@tonic-gate * one mpxio and one non-mpxio name. Therefore for any device name 14387c478bd9Sstevel@tonic-gate * entry we at most add two comments - one with mpxio name and one 14397c478bd9Sstevel@tonic-gate * with non-mpxio name - no matter how many times stmsboot is run. 14407c478bd9Sstevel@tonic-gate */ 14417c478bd9Sstevel@tonic-gate buf = (char *)s_malloc(VFS_LINE_MAX); 14427c478bd9Sstevel@tonic-gate tmpbuf = (char *)s_malloc(VFS_LINE_MAX); 14437c478bd9Sstevel@tonic-gate vfs_cache[0] = (char *)s_malloc(VFS_LINE_MAX); 14447c478bd9Sstevel@tonic-gate vfs_cache[1] = (char *)s_malloc(VFS_LINE_MAX); 14457c478bd9Sstevel@tonic-gate 14467c478bd9Sstevel@tonic-gate (void) snprintf(fmt, sizeof (fmt), 14477c478bd9Sstevel@tonic-gate "%%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds", sizeof (bdev) - 1, 14487c478bd9Sstevel@tonic-gate sizeof (cdev) - 1, sizeof (mntpt) - 1, sizeof (fstype) - 1, 14497c478bd9Sstevel@tonic-gate sizeof (fsckpass) - 1, sizeof (mntboot) - 1, sizeof (mntopt) - 1); 14507c478bd9Sstevel@tonic-gate 14517c478bd9Sstevel@tonic-gate while (fgets(buf, VFS_LINE_MAX, fp_in) != NULL) { 14527c478bd9Sstevel@tonic-gate if (strlen(buf) == (VFS_LINE_MAX - 1) && 14537c478bd9Sstevel@tonic-gate buf[VFS_LINE_MAX-2] != '\n') { 14547c478bd9Sstevel@tonic-gate logerr(gettext("%1$s line size too long, " 14557c478bd9Sstevel@tonic-gate "exceeded %2$d: \"%3$s\"\n"), 14567c478bd9Sstevel@tonic-gate VFSTAB, VFS_LINE_MAX - 2, buf); 14577c478bd9Sstevel@tonic-gate goto out; 14587c478bd9Sstevel@tonic-gate } 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate /* LINTED - format specifier */ 14617c478bd9Sstevel@tonic-gate if ((sscanf(buf, fmt, bdev, cdev, mntpt, 14627c478bd9Sstevel@tonic-gate fstype, fsckpass, mntboot, mntopt) != 7) || 14637c478bd9Sstevel@tonic-gate (bdev[0] == '#') || 14647c478bd9Sstevel@tonic-gate (get_physname_minor(bdev, phys_bdev, sizeof (phys_bdev), 14657c478bd9Sstevel@tonic-gate bdev_minor, sizeof (bdev_minor)) != 0) || 14667c478bd9Sstevel@tonic-gate 14677c478bd9Sstevel@tonic-gate (strcmp(fstype, "swap") != 0 && 14687c478bd9Sstevel@tonic-gate ((get_physname_minor(cdev, phys_cdev, sizeof (phys_cdev), 14697c478bd9Sstevel@tonic-gate cdev_minor, sizeof (cdev_minor)) != 0) || 14707c478bd9Sstevel@tonic-gate (strcmp(phys_bdev, phys_cdev) != 0))) || 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate canopen(bdev) || 14737c478bd9Sstevel@tonic-gate (map_physname(phys_bdev, new_physname, 14747c478bd9Sstevel@tonic-gate sizeof (new_physname)) != 0) || 14757c478bd9Sstevel@tonic-gate (lookup_devlink(new_physname, bdev_minor, new_bdevlink, 14767c478bd9Sstevel@tonic-gate sizeof (new_bdevlink)) != 0) || 14777c478bd9Sstevel@tonic-gate 14787c478bd9Sstevel@tonic-gate (strcmp(fstype, "swap") != 0 && 14797c478bd9Sstevel@tonic-gate (lookup_devlink(new_physname, cdev_minor, new_cdevlink, 14807c478bd9Sstevel@tonic-gate sizeof (new_cdevlink)) != 0))) { 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate /* cache the last two entries */ 14837c478bd9Sstevel@tonic-gate (void) strlcpy(vfs_cache[idx], buf, VFS_LINE_MAX); 14847c478bd9Sstevel@tonic-gate idx = (idx == 0) ? 1 : 0; 14857c478bd9Sstevel@tonic-gate if (count < 2) 14867c478bd9Sstevel@tonic-gate count++; 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate if (fputs(buf, fp_out) == EOF) { 14897c478bd9Sstevel@tonic-gate logerr(gettext("fputs \"%1$s\" to %2$s " 14907c478bd9Sstevel@tonic-gate "failed: %3$s\n"), 14917c478bd9Sstevel@tonic-gate buf, vfstab_out, strerror(errno)); 14927c478bd9Sstevel@tonic-gate goto out; 14937c478bd9Sstevel@tonic-gate } 14947c478bd9Sstevel@tonic-gate 14957c478bd9Sstevel@tonic-gate } else { 14967c478bd9Sstevel@tonic-gate /* 14977c478bd9Sstevel@tonic-gate * comment the entry in vfstab only if it is not 14987c478bd9Sstevel@tonic-gate * already in the cache. 14997c478bd9Sstevel@tonic-gate */ 15007c478bd9Sstevel@tonic-gate if (client_name_type(phys_bdev) == CLIENT_TYPE_VHCI) 15017c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, VFS_LINE_MAX, 15027c478bd9Sstevel@tonic-gate "# mpxio: %s", buf); 15037c478bd9Sstevel@tonic-gate else 15047c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, VFS_LINE_MAX, 15057c478bd9Sstevel@tonic-gate "# non-mpxio: %s", buf); 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 15087c478bd9Sstevel@tonic-gate if (strcmp(vfs_cache[i], tmpbuf) == 0) 15097c478bd9Sstevel@tonic-gate break; 15107c478bd9Sstevel@tonic-gate } 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate if (i == count) { 15137c478bd9Sstevel@tonic-gate if (fputs(tmpbuf, fp_out) == EOF) { 15147c478bd9Sstevel@tonic-gate logerr(gettext("fputs \"%1$s\" to %2$s " 15157c478bd9Sstevel@tonic-gate "failed: %3$s\n"), tmpbuf, 15167c478bd9Sstevel@tonic-gate vfstab_out, strerror(errno)); 15177c478bd9Sstevel@tonic-gate goto out; 15187c478bd9Sstevel@tonic-gate } 15197c478bd9Sstevel@tonic-gate } 15207c478bd9Sstevel@tonic-gate 15217c478bd9Sstevel@tonic-gate count = 0; 15227c478bd9Sstevel@tonic-gate idx = 0; 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate if (fprintf(fp_out, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", 15257c478bd9Sstevel@tonic-gate new_bdevlink, 15267c478bd9Sstevel@tonic-gate (strcmp(fstype, "swap") != 0) ? new_cdevlink : cdev, 15277c478bd9Sstevel@tonic-gate mntpt, fstype, fsckpass, mntboot, mntopt) < 0) { 15287c478bd9Sstevel@tonic-gate logerr(gettext("fprintf failed to write to " 15297c478bd9Sstevel@tonic-gate "%1$s: %2$s\n"), 15307c478bd9Sstevel@tonic-gate vfstab_out, strerror(errno)); 15317c478bd9Sstevel@tonic-gate goto out; 15327c478bd9Sstevel@tonic-gate } 15337c478bd9Sstevel@tonic-gate vfstab_updated = 1; 15347c478bd9Sstevel@tonic-gate } 15357c478bd9Sstevel@tonic-gate } 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate rv = vfstab_updated; 15387c478bd9Sstevel@tonic-gate out: 15397c478bd9Sstevel@tonic-gate (void) fclose(fp_in); 15407c478bd9Sstevel@tonic-gate (void) fclose(fp_out); 15417c478bd9Sstevel@tonic-gate free(buf); 15427c478bd9Sstevel@tonic-gate free(tmpbuf); 15437c478bd9Sstevel@tonic-gate free(vfs_cache[0]); 15447c478bd9Sstevel@tonic-gate free(vfs_cache[1]); 15457c478bd9Sstevel@tonic-gate return (rv); 15467c478bd9Sstevel@tonic-gate } 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate /* 15497c478bd9Sstevel@tonic-gate * if guidmap is 0, list non-STMS to STMS device name mappings for the 15507c478bd9Sstevel@tonic-gate * specified controller. 15517c478bd9Sstevel@tonic-gate * if guidmap is 1, list non-STMS to GUID mappings for the specified controller. 15527c478bd9Sstevel@tonic-gate * If controller is -1 list mappings for all controllers. 15537c478bd9Sstevel@tonic-gate * 15547c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 15557c478bd9Sstevel@tonic-gate */ 15567c478bd9Sstevel@tonic-gate static int 15577c478bd9Sstevel@tonic-gate list_mappings(int controller, int guidmap) 15587c478bd9Sstevel@tonic-gate { 15597c478bd9Sstevel@tonic-gate int cnum, len, mapped; 15607c478bd9Sstevel@tonic-gate int header = 1; 15617c478bd9Sstevel@tonic-gate char *p1, *p2; 15627c478bd9Sstevel@tonic-gate DIR *dirp; 15637c478bd9Sstevel@tonic-gate struct dirent *direntry; 15647c478bd9Sstevel@tonic-gate char devname[MAXPATHLEN]; 15657c478bd9Sstevel@tonic-gate char physname[MAXPATHLEN]; 15667c478bd9Sstevel@tonic-gate char new_devname[MAXPATHLEN]; 15677c478bd9Sstevel@tonic-gate char new_physname[MAXPATHLEN]; 15687c478bd9Sstevel@tonic-gate char guid[MAXPATHLEN]; 15697c478bd9Sstevel@tonic-gate char minor[MAXNAMELEN]; 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate if ((dirp = opendir("/dev/rdsk")) == NULL) 15727c478bd9Sstevel@tonic-gate return (-1); 15737c478bd9Sstevel@tonic-gate 15747c478bd9Sstevel@tonic-gate while ((direntry = readdir(dirp)) != NULL) { 15757c478bd9Sstevel@tonic-gate if (strcmp(direntry->d_name, ".") == 0 || 15767c478bd9Sstevel@tonic-gate strcmp(direntry->d_name, "..") == 0 || 15777c478bd9Sstevel@tonic-gate (len = strlen(direntry->d_name)) < 2 || 15787c478bd9Sstevel@tonic-gate strcmp(direntry->d_name + len - 2, "s0") != 0 || 15797c478bd9Sstevel@tonic-gate sscanf(direntry->d_name, "c%dt", &cnum) != 1 || 15807c478bd9Sstevel@tonic-gate (controller != -1 && controller != cnum)) 15817c478bd9Sstevel@tonic-gate continue; 15827c478bd9Sstevel@tonic-gate 15837c478bd9Sstevel@tonic-gate (void) snprintf(devname, MAXPATHLEN, "/dev/rdsk/%s", 15847c478bd9Sstevel@tonic-gate direntry->d_name); 15857c478bd9Sstevel@tonic-gate 15867c478bd9Sstevel@tonic-gate if (get_physname_minor(devname, physname, sizeof (physname), 15877c478bd9Sstevel@tonic-gate minor, sizeof (minor)) != 0 || 1588*60fffc19Sjw149990 client_name_type(physname) != CLIENT_TYPE_PHCI) { 1589*60fffc19Sjw149990 logdmsg("list_mappings: continuing\n"); 15907c478bd9Sstevel@tonic-gate continue; 1591*60fffc19Sjw149990 } 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate /* 15947c478bd9Sstevel@tonic-gate * First try phci_to_vhci() mapping. It will work if the 15957c478bd9Sstevel@tonic-gate * device is under MPxIO control. If the device is not under 15967c478bd9Sstevel@tonic-gate * MPxIO, phci_to_vhci() will fail in which case try to lookup 15977c478bd9Sstevel@tonic-gate * if an old mapping exists using guid lookup. 15987c478bd9Sstevel@tonic-gate */ 15997c478bd9Sstevel@tonic-gate mapped = 1; 16007c478bd9Sstevel@tonic-gate if (phci_to_vhci(physname, new_physname, 16017c478bd9Sstevel@tonic-gate sizeof (new_physname)) != 0) { 16027c478bd9Sstevel@tonic-gate if (get_guid(physname, guid, sizeof (guid), 1, 16037c478bd9Sstevel@tonic-gate DI_NODE_NIL) == 0) 16047c478bd9Sstevel@tonic-gate (void) snprintf(new_physname, MAXPATHLEN, 16055a4c37c9Sqh201292 "/scsi_vhci/%s%s", DISK_AT_G, guid); 16067c478bd9Sstevel@tonic-gate else 16077c478bd9Sstevel@tonic-gate mapped = 0; 16087c478bd9Sstevel@tonic-gate } 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate if (mapped == 0) 16117c478bd9Sstevel@tonic-gate continue; 16127c478bd9Sstevel@tonic-gate 16137c478bd9Sstevel@tonic-gate /* strip the slice number part */ 16147c478bd9Sstevel@tonic-gate devname[strlen(devname) - 2] = '\0'; 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate if (guidmap == 0) { 16177c478bd9Sstevel@tonic-gate if (lookup_devlink(new_physname, minor, 16187c478bd9Sstevel@tonic-gate new_devname, sizeof (new_devname)) != 0) 16197c478bd9Sstevel@tonic-gate continue; 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate /* strip the slice number part */ 16227c478bd9Sstevel@tonic-gate new_devname[strlen(new_devname) - 2] = '\0'; 16237c478bd9Sstevel@tonic-gate 16247c478bd9Sstevel@tonic-gate if (header) { 16257c478bd9Sstevel@tonic-gate (void) printf( 16267c478bd9Sstevel@tonic-gate gettext("non-STMS device name\t\t\t" 16277c478bd9Sstevel@tonic-gate "STMS device name\n" 16287c478bd9Sstevel@tonic-gate "------------------------------------------" 16297c478bd9Sstevel@tonic-gate "------------------------\n")); 16307c478bd9Sstevel@tonic-gate header = 0; 16317c478bd9Sstevel@tonic-gate } 16327c478bd9Sstevel@tonic-gate (void) printf("%s\t\t%s\n", devname, new_devname); 16337c478bd9Sstevel@tonic-gate } else { 16347c478bd9Sstevel@tonic-gate /* extract guid part */ 1635*60fffc19Sjw149990 /* we should be using a getguid() call instead */ 1636*60fffc19Sjw149990 if ((p1 = strstr(new_physname, "@")) 1637*60fffc19Sjw149990 == NULL) { 16387c478bd9Sstevel@tonic-gate logdmsg("invalid vhci: %s\n", new_physname); 16397c478bd9Sstevel@tonic-gate continue; 16407c478bd9Sstevel@tonic-gate } 1641*60fffc19Sjw149990 1642*60fffc19Sjw149990 logdmsg("\tp1 = %s\n", p1); 1643*60fffc19Sjw149990 1644*60fffc19Sjw149990 p1 += 2; /* "@" + [nwg] */ 16457c478bd9Sstevel@tonic-gate if ((p2 = strrchr(p1, ':')) != NULL) 16467c478bd9Sstevel@tonic-gate *p2 = '\0'; 16477c478bd9Sstevel@tonic-gate 16487c478bd9Sstevel@tonic-gate if (header) { 16497c478bd9Sstevel@tonic-gate (void) printf( 16507c478bd9Sstevel@tonic-gate gettext("non-STMS device name\t\t\tGUID\n" 16517c478bd9Sstevel@tonic-gate "------------------------------------------" 16527c478bd9Sstevel@tonic-gate "------------------------\n")); 16537c478bd9Sstevel@tonic-gate header = 0; 16547c478bd9Sstevel@tonic-gate } 16557c478bd9Sstevel@tonic-gate (void) printf("%s\t\t%s\n", devname, p1); 16567c478bd9Sstevel@tonic-gate } 16577c478bd9Sstevel@tonic-gate } 16587c478bd9Sstevel@tonic-gate 16597c478bd9Sstevel@tonic-gate (void) closedir(dirp); 16607c478bd9Sstevel@tonic-gate return (0); 16617c478bd9Sstevel@tonic-gate } 16627c478bd9Sstevel@tonic-gate 16637c478bd9Sstevel@tonic-gate /* 16647c478bd9Sstevel@tonic-gate * Check if the file can be opened. 16657c478bd9Sstevel@tonic-gate * 16667c478bd9Sstevel@tonic-gate * Return 1 if the file can be opened, 0 otherwise. 16677c478bd9Sstevel@tonic-gate */ 16687c478bd9Sstevel@tonic-gate static int 16697c478bd9Sstevel@tonic-gate canopen(char *filename) 16707c478bd9Sstevel@tonic-gate { 16717c478bd9Sstevel@tonic-gate int fd; 16727c478bd9Sstevel@tonic-gate 16737c478bd9Sstevel@tonic-gate if ((fd = open(filename, O_RDONLY)) == -1) 16747c478bd9Sstevel@tonic-gate return (0); 16757c478bd9Sstevel@tonic-gate 1676*60fffc19Sjw149990 logdmsg("canopen: was able to open %s\n", filename); 16777c478bd9Sstevel@tonic-gate (void) close(fd); 16787c478bd9Sstevel@tonic-gate return (1); 16797c478bd9Sstevel@tonic-gate } 16807c478bd9Sstevel@tonic-gate 1681*60fffc19Sjw149990 1682*60fffc19Sjw149990 /* 1683*60fffc19Sjw149990 * This function traverses the device tree looking for nodes 1684*60fffc19Sjw149990 * which have "drivername" as a property. We return a list of 1685*60fffc19Sjw149990 * these nodes, with SLASH_DISK_AT appended. 1686*60fffc19Sjw149990 * Since there can be many different pci/pcie devices that all 1687*60fffc19Sjw149990 * share the same driver but which have different pci vid/did 1688*60fffc19Sjw149990 * combinations, we have to be smart about returning only those 1689*60fffc19Sjw149990 * pci vid/dids which have the "sas-*" property unless the 1690*60fffc19Sjw149990 * drivername is "fp", in which case we're searching for "node-wwn" 1691*60fffc19Sjw149990 */ 1692*60fffc19Sjw149990 static void 1693*60fffc19Sjw149990 list_nodes(char *drivername) 1694*60fffc19Sjw149990 { 1695*60fffc19Sjw149990 char *aliaslist; 1696*60fffc19Sjw149990 char *mpxprop = NULL; 1697*60fffc19Sjw149990 di_node_t devroot = DI_NODE_NIL; 1698*60fffc19Sjw149990 di_node_t thisnode = DI_NODE_NIL; 1699*60fffc19Sjw149990 int *intprop = NULL; 1700*60fffc19Sjw149990 int i = 1; /* fencepost */ 1701*60fffc19Sjw149990 1702*60fffc19Sjw149990 /* 1703*60fffc19Sjw149990 * Since the "fp" driver enumerates with its own name, 1704*60fffc19Sjw149990 * we can special-case its handling. 1705*60fffc19Sjw149990 */ 1706*60fffc19Sjw149990 if (strcmp(drvname, "fp") == 0) { 1707*60fffc19Sjw149990 (void) fprintf(stdout, "fp\n"); 1708*60fffc19Sjw149990 } else { 1709*60fffc19Sjw149990 1710*60fffc19Sjw149990 if ((devroot = di_init("/", DINFOCPYALL | DINFOFORCE)) 1711*60fffc19Sjw149990 == DI_NODE_NIL) { 1712*60fffc19Sjw149990 logerr(gettext("list_nodes: di_init failed: " 1713*60fffc19Sjw149990 "%s\n"), strerror(errno)); 1714*60fffc19Sjw149990 } 1715*60fffc19Sjw149990 1716*60fffc19Sjw149990 if ((thisnode = di_drv_first_node(drivername, devroot)) 1717*60fffc19Sjw149990 != NULL) { 1718*60fffc19Sjw149990 logdmsg("list_nodes: searching for property " 1719*60fffc19Sjw149990 "%s\n", drvprop); 1720*60fffc19Sjw149990 1721*60fffc19Sjw149990 aliaslist = s_malloc(1024 * sizeof (char)); 1722*60fffc19Sjw149990 bzero(aliaslist, 1024); 1723*60fffc19Sjw149990 while (thisnode != DI_NODE_NIL) { 1724*60fffc19Sjw149990 logdmsg("devfs-name %s driver-name %s " 1725*60fffc19Sjw149990 "node-name %s\n", 1726*60fffc19Sjw149990 di_devfs_path(thisnode), 1727*60fffc19Sjw149990 di_driver_name(thisnode), 1728*60fffc19Sjw149990 di_node_name(thisnode)); 1729*60fffc19Sjw149990 1730*60fffc19Sjw149990 /* We check the child node for drvprop */ 1731*60fffc19Sjw149990 if ((di_prop_lookup_ints(DDI_DEV_T_ANY, 1732*60fffc19Sjw149990 di_child_node(thisnode), drvprop, 1733*60fffc19Sjw149990 &intprop) > -1) || 1734*60fffc19Sjw149990 (((di_prop_lookup_strings(DDI_DEV_T_ANY, 1735*60fffc19Sjw149990 thisnode, "mpxio-disable", &mpxprop) > -1) && 1736*60fffc19Sjw149990 strcmp(di_driver_name(thisnode), 1737*60fffc19Sjw149990 drivername)) == 0)) { 1738*60fffc19Sjw149990 1739*60fffc19Sjw149990 if (strstr(aliaslist, 1740*60fffc19Sjw149990 di_node_name(thisnode)) 1741*60fffc19Sjw149990 == (char *)NULL) { 1742*60fffc19Sjw149990 char *nname; 1743*60fffc19Sjw149990 1744*60fffc19Sjw149990 nname = di_node_name(thisnode); 1745*60fffc19Sjw149990 1746*60fffc19Sjw149990 if (i) { 1747*60fffc19Sjw149990 (void) snprintf(aliaslist, 1748*60fffc19Sjw149990 strlen(nname), "%s", nname); 1749*60fffc19Sjw149990 --i; 1750*60fffc19Sjw149990 } else { 1751*60fffc19Sjw149990 if (strstr(aliaslist, 1752*60fffc19Sjw149990 di_node_name(thisnode)) == 1753*60fffc19Sjw149990 (char *)NULL) { 1754*60fffc19Sjw149990 (void) snprintf(aliaslist, 1755*60fffc19Sjw149990 strlen(nname) + 1756*60fffc19Sjw149990 strlen(aliaslist), 1757*60fffc19Sjw149990 "%s|%s", aliaslist, 1758*60fffc19Sjw149990 nname); 1759*60fffc19Sjw149990 } 1760*60fffc19Sjw149990 } 1761*60fffc19Sjw149990 } 1762*60fffc19Sjw149990 } else { 1763*60fffc19Sjw149990 logdmsg("unable to lookup property %s " 1764*60fffc19Sjw149990 "for node %s. Error %d: %s\n", 1765*60fffc19Sjw149990 drvprop, di_devfs_path(thisnode), 1766*60fffc19Sjw149990 errno, strerror(errno)); 1767*60fffc19Sjw149990 } 1768*60fffc19Sjw149990 thisnode = di_drv_next_node(thisnode); 1769*60fffc19Sjw149990 } 1770*60fffc19Sjw149990 (void) fprintf(stdout, "%s\n", aliaslist); 1771*60fffc19Sjw149990 } 1772*60fffc19Sjw149990 1773*60fffc19Sjw149990 di_fini(devroot); 1774*60fffc19Sjw149990 } 1775*60fffc19Sjw149990 } 1776*60fffc19Sjw149990 17777c478bd9Sstevel@tonic-gate static void 17787c478bd9Sstevel@tonic-gate logerr(char *msg, ...) 17797c478bd9Sstevel@tonic-gate { 17807c478bd9Sstevel@tonic-gate va_list ap; 17817c478bd9Sstevel@tonic-gate 17827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", stmsboot); 17837c478bd9Sstevel@tonic-gate va_start(ap, msg); 17847c478bd9Sstevel@tonic-gate /* LINTED - format specifier */ 17857c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, msg, ap); 17867c478bd9Sstevel@tonic-gate va_end(ap); 17877c478bd9Sstevel@tonic-gate } 17887c478bd9Sstevel@tonic-gate 17897c478bd9Sstevel@tonic-gate /* log debug message */ 17907c478bd9Sstevel@tonic-gate static void 17917c478bd9Sstevel@tonic-gate logdmsg(char *msg, ...) 17927c478bd9Sstevel@tonic-gate { 17937c478bd9Sstevel@tonic-gate va_list ap; 17947c478bd9Sstevel@tonic-gate 17957c478bd9Sstevel@tonic-gate if (debug) { 17967c478bd9Sstevel@tonic-gate va_start(ap, msg); 17977c478bd9Sstevel@tonic-gate /* LINTED - format specifier */ 17987c478bd9Sstevel@tonic-gate (void) vprintf(msg, ap); 17997c478bd9Sstevel@tonic-gate va_end(ap); 18007c478bd9Sstevel@tonic-gate } 18017c478bd9Sstevel@tonic-gate } 18027c478bd9Sstevel@tonic-gate 18037c478bd9Sstevel@tonic-gate static void * 18047c478bd9Sstevel@tonic-gate s_malloc(const size_t size) 18057c478bd9Sstevel@tonic-gate { 18067c478bd9Sstevel@tonic-gate void *rp; 18077c478bd9Sstevel@tonic-gate 18087c478bd9Sstevel@tonic-gate if ((rp = malloc(size)) == NULL) { 18097c478bd9Sstevel@tonic-gate logerr(gettext("malloc failed to allocate %d bytes\n"), size); 18107c478bd9Sstevel@tonic-gate clean_exit(1); 18117c478bd9Sstevel@tonic-gate } 18127c478bd9Sstevel@tonic-gate return (rp); 18137c478bd9Sstevel@tonic-gate } 18147c478bd9Sstevel@tonic-gate 18157c478bd9Sstevel@tonic-gate static char * 18167c478bd9Sstevel@tonic-gate s_strdup(const char *ptr) 18177c478bd9Sstevel@tonic-gate { 18187c478bd9Sstevel@tonic-gate void *rp; 18197c478bd9Sstevel@tonic-gate 18207c478bd9Sstevel@tonic-gate if ((rp = strdup(ptr)) == NULL) { 18217c478bd9Sstevel@tonic-gate logerr(gettext("strdup failed to dup %s\n"), ptr); 18227c478bd9Sstevel@tonic-gate clean_exit(1); 18237c478bd9Sstevel@tonic-gate } 18247c478bd9Sstevel@tonic-gate return (rp); 18257c478bd9Sstevel@tonic-gate } 18267c478bd9Sstevel@tonic-gate 18277c478bd9Sstevel@tonic-gate static void 18287c478bd9Sstevel@tonic-gate s_strlcpy(char *dst, const char *src, size_t dstsize) 18297c478bd9Sstevel@tonic-gate { 18307c478bd9Sstevel@tonic-gate int n; 18317c478bd9Sstevel@tonic-gate 18327c478bd9Sstevel@tonic-gate if ((n = strlcpy(dst, src, dstsize)) >= dstsize) { 18337c478bd9Sstevel@tonic-gate logerr(gettext("strlcpy: destination buffer size is %1$d " 18347c478bd9Sstevel@tonic-gate "bytes, need to at least %2$d bytes\n"), dstsize, n + 1); 18357c478bd9Sstevel@tonic-gate clean_exit(1); 18367c478bd9Sstevel@tonic-gate } 18377c478bd9Sstevel@tonic-gate } 18387c478bd9Sstevel@tonic-gate 18397c478bd9Sstevel@tonic-gate static void 18407c478bd9Sstevel@tonic-gate clean_exit(int status) 18417c478bd9Sstevel@tonic-gate { 18427c478bd9Sstevel@tonic-gate if (devinfo_root != DI_NODE_NIL) 18437c478bd9Sstevel@tonic-gate di_fini(devinfo_root); 18447c478bd9Sstevel@tonic-gate 18457c478bd9Sstevel@tonic-gate if (devlink_hdl != NULL) 18467c478bd9Sstevel@tonic-gate (void) di_devlink_fini(&devlink_hdl); 18477c478bd9Sstevel@tonic-gate 18487c478bd9Sstevel@tonic-gate if (vhci_fd != -1) 18497c478bd9Sstevel@tonic-gate (void) close(vhci_fd); 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate exit(status); 18527c478bd9Sstevel@tonic-gate } 1853