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> 49*8cecff49Sgp87344 #include <sys/mnttab.h> 507c478bd9Sstevel@tonic-gate #include <sys/vfstab.h> 517c478bd9Sstevel@tonic-gate #include <sys/mount.h> 527c478bd9Sstevel@tonic-gate #include <devid.h> 537c478bd9Sstevel@tonic-gate #include <sys/libdevid.h> 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate #define VHCI_CTL_NODE "/devices/scsi_vhci:devctl" 567c478bd9Sstevel@tonic-gate #define SLASH_DEVICES "/devices/" 575a4c37c9Sqh201292 585a4c37c9Sqh201292 #ifdef sparc 595a4c37c9Sqh201292 #define DISK_NODE_NAME "ssd" 605a4c37c9Sqh201292 #define DISK_DRV_NAME "ssd" 615a4c37c9Sqh201292 #else /* sparc */ 625a4c37c9Sqh201292 #define DISK_NODE_NAME "disk" 635a4c37c9Sqh201292 #define DISK_DRV_NAME "sd" 645a4c37c9Sqh201292 #endif 655a4c37c9Sqh201292 6660fffc19Sjw149990 #define DISK_AT_G "disk@g" 677c478bd9Sstevel@tonic-gate #define SLASH_FP_AT "/fp@" 687c478bd9Sstevel@tonic-gate #define SLASH_SCSI_VHCI "/scsi_vhci" 697c478bd9Sstevel@tonic-gate #define DEV_DSK "/dev/dsk/" 707c478bd9Sstevel@tonic-gate #define DEV_RDSK "/dev/rdsk/" 717c478bd9Sstevel@tonic-gate #define SYS_FILENAME_LEN 256 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /* 747c478bd9Sstevel@tonic-gate * Save directory is the directory in which system files are saved. 757c478bd9Sstevel@tonic-gate * Save directory must be under the root filesystem, as this program is 767c478bd9Sstevel@tonic-gate * typically run before any other filesystems are mounted. 777c478bd9Sstevel@tonic-gate */ 787c478bd9Sstevel@tonic-gate #define SAVE_DIR "/etc/mpxio" 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /* fcp driver publishes this property */ 817c478bd9Sstevel@tonic-gate #define NODE_WWN_PROP "node-wwn" 827c478bd9Sstevel@tonic-gate 8360fffc19Sjw149990 /* 8460fffc19Sjw149990 * For SAS, we look for "sas-$drivername", eg sas-mpt, but 8560fffc19Sjw149990 * we strncat the driver name later once we've parsed the 8660fffc19Sjw149990 * args passed in from the shell. 8760fffc19Sjw149990 */ 8860fffc19Sjw149990 #define SASPROP "sas-" 8960fffc19Sjw149990 9060fffc19Sjw149990 917c478bd9Sstevel@tonic-gate typedef enum { 927c478bd9Sstevel@tonic-gate CLIENT_TYPE_UNKNOWN, 937c478bd9Sstevel@tonic-gate CLIENT_TYPE_PHCI, 947c478bd9Sstevel@tonic-gate CLIENT_TYPE_VHCI 957c478bd9Sstevel@tonic-gate } client_type_t; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate struct devlink_cbarg { 987c478bd9Sstevel@tonic-gate char *devlink; 997c478bd9Sstevel@tonic-gate size_t len; 1007c478bd9Sstevel@tonic-gate }; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate static di_node_t devinfo_root = DI_NODE_NIL; 1037c478bd9Sstevel@tonic-gate static di_devlink_handle_t devlink_hdl = NULL; 1047c478bd9Sstevel@tonic-gate static int vhci_fd = -1; 1057c478bd9Sstevel@tonic-gate static int patch_vfstab, cap_m_option, debug; 1067c478bd9Sstevel@tonic-gate static int list_option, list_guid_mappings, list_controllernum = -1; 1077c478bd9Sstevel@tonic-gate static char *mapdev = ""; 1085a4c37c9Sqh201292 static char *map_vhciname = ""; 1097c478bd9Sstevel@tonic-gate static char *stmsboot = "stmsboot"; 1107c478bd9Sstevel@tonic-gate 11160fffc19Sjw149990 char *drvname = (char *)NULL; /* "fp" or "mpt" or ... */ 11260fffc19Sjw149990 /* "node-wwn" if drvname=fp, or "sas-$drivername" otherwise */ 11360fffc19Sjw149990 char *drvprop = (char *)NULL; 11460fffc19Sjw149990 static int parent = 0; /* for "-n" usage */ 11560fffc19Sjw149990 1167c478bd9Sstevel@tonic-gate static int make_temp(char *, char *, char *, size_t); 1177c478bd9Sstevel@tonic-gate static void commit_change(char *, char *, char *, int); 1187c478bd9Sstevel@tonic-gate static int map_devname(char *, char *, size_t, int); 1197c478bd9Sstevel@tonic-gate static int update_vfstab(char *, char *); 1207c478bd9Sstevel@tonic-gate static int list_mappings(int, int); 1217c478bd9Sstevel@tonic-gate static int canopen(char *); 12260fffc19Sjw149990 static client_type_t client_by_props(char *path); 12360fffc19Sjw149990 static void list_nodes(char *drivername); 124*8cecff49Sgp87344 static int canread(char *, char *); 12560fffc19Sjw149990 1267c478bd9Sstevel@tonic-gate static void logerr(char *, ...); 1277c478bd9Sstevel@tonic-gate static void logdmsg(char *, ...); 1287c478bd9Sstevel@tonic-gate static void *s_malloc(const size_t); 1297c478bd9Sstevel@tonic-gate static char *s_strdup(const char *); 1307c478bd9Sstevel@tonic-gate static void s_strlcpy(char *, const char *, size_t); 131cfcc3aa4Sqh201292 static int map_openable_vhciname(char *, char *, size_t); 132264d6c47Seota /* 133264d6c47Seota * Using an exit function not marked __NORETURN causes a warning with gcc. 134264d6c47Seota * To suppress the warning, use __NORETURN attribute. 135264d6c47Seota */ 136264d6c47Seota static void clean_exit(int)__NORETURN; 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * Print usage and exit. 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate static void 1427c478bd9Sstevel@tonic-gate usage(char *argv0) 1437c478bd9Sstevel@tonic-gate { 1447c478bd9Sstevel@tonic-gate char *progname; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate progname = strrchr(argv0, '/'); 1477c478bd9Sstevel@tonic-gate if (progname != NULL) 1487c478bd9Sstevel@tonic-gate progname++; 1497c478bd9Sstevel@tonic-gate else 1507c478bd9Sstevel@tonic-gate progname = argv0; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate /* 1537c478bd9Sstevel@tonic-gate * -u update /etc/vfstab 1547c478bd9Sstevel@tonic-gate * -m devname 1557c478bd9Sstevel@tonic-gate * if devname is phci based name and not open-able, map it to 1567c478bd9Sstevel@tonic-gate * vhci based /devices name. 1577c478bd9Sstevel@tonic-gate * if devname is vhci based name and not open-able, map it to 1587c478bd9Sstevel@tonic-gate * phci based /devices name. 1597c478bd9Sstevel@tonic-gate * -M devname 1607c478bd9Sstevel@tonic-gate * same as -m except that /dev link is printed instead of 1617c478bd9Sstevel@tonic-gate * /devices name. 1627c478bd9Sstevel@tonic-gate * -l controller 1637c478bd9Sstevel@tonic-gate * list non-STMS to STMS device name mappings for the specific 1647c478bd9Sstevel@tonic-gate * controller 1657c478bd9Sstevel@tonic-gate * -L list non-STMS to STMS device name mappings for all controllers 1665a4c37c9Sqh201292 * -p devname 1675a4c37c9Sqh201292 * if devname is vhci based name and open-able, get the first 1685a4c37c9Sqh201292 * onlined phci based name without /devices prefix. 1695a4c37c9Sqh201292 * Used in stmsboot to update the phci based bootpath. 17060fffc19Sjw149990 * -D drvname 17160fffc19Sjw149990 * if supplied, indicates that we're going to operate on 17260fffc19Sjw149990 * devices attached to this driver 17360fffc19Sjw149990 * -n 17460fffc19Sjw149990 * if supplied, returns name of the node containing "fp" or 17560fffc19Sjw149990 * "sas-$driver", appends "sd@" or "ssd@" or "disk@". Can only 17660fffc19Sjw149990 * be used if -D drv is specified as well 1777c478bd9Sstevel@tonic-gate */ 1787c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("usage: %s -u | -m devname | " 17960fffc19Sjw149990 "-M devname | -l controller | -L | \n" 18060fffc19Sjw149990 "\t\t-p devname | -D { fp | mpt } | -n\n"), progname); 1817c478bd9Sstevel@tonic-gate exit(2); 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate /* 1857c478bd9Sstevel@tonic-gate * Parse command line arguments. 1867c478bd9Sstevel@tonic-gate */ 1877c478bd9Sstevel@tonic-gate static void 1887c478bd9Sstevel@tonic-gate parse_args(int argc, char *argv[]) 1897c478bd9Sstevel@tonic-gate { 1907c478bd9Sstevel@tonic-gate char opt; 1917c478bd9Sstevel@tonic-gate int n = 0; 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate if (argc == 1) { 1947c478bd9Sstevel@tonic-gate usage(argv[0]); 1957c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 19860fffc19Sjw149990 while ((opt = getopt(argc, argv, "udm:M:Ll:gp:D:n")) != EOF) { 1997c478bd9Sstevel@tonic-gate switch (opt) { 2007c478bd9Sstevel@tonic-gate case 'u': 2017c478bd9Sstevel@tonic-gate patch_vfstab = 1; 2027c478bd9Sstevel@tonic-gate n++; 2037c478bd9Sstevel@tonic-gate break; 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate case 'd': 2067c478bd9Sstevel@tonic-gate debug = 1; 2077c478bd9Sstevel@tonic-gate break; 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate case 'm': 2107c478bd9Sstevel@tonic-gate mapdev = s_strdup(optarg); 2117c478bd9Sstevel@tonic-gate n++; 2127c478bd9Sstevel@tonic-gate break; 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate case 'M': 2157c478bd9Sstevel@tonic-gate mapdev = s_strdup(optarg); 2167c478bd9Sstevel@tonic-gate cap_m_option = 1; 2177c478bd9Sstevel@tonic-gate n++; 2187c478bd9Sstevel@tonic-gate break; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate case 'L': 2217c478bd9Sstevel@tonic-gate list_option = 1; 2227c478bd9Sstevel@tonic-gate n++; 2237c478bd9Sstevel@tonic-gate break; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate case 'l': 2267c478bd9Sstevel@tonic-gate list_option = 1; 2277c478bd9Sstevel@tonic-gate list_controllernum = (int)atol(optarg); 2287c478bd9Sstevel@tonic-gate if (list_controllernum < 0) { 2297c478bd9Sstevel@tonic-gate logerr(gettext("controller number %d is " 2307c478bd9Sstevel@tonic-gate "invalid\n"), list_controllernum); 2317c478bd9Sstevel@tonic-gate clean_exit(1); 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate n++; 2347c478bd9Sstevel@tonic-gate break; 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate case 'g': 2377c478bd9Sstevel@tonic-gate /* 2387c478bd9Sstevel@tonic-gate * private option to display non-STMS device name 2397c478bd9Sstevel@tonic-gate * to GUID mappings. 2407c478bd9Sstevel@tonic-gate */ 2417c478bd9Sstevel@tonic-gate list_guid_mappings = 1; 2427c478bd9Sstevel@tonic-gate break; 24360fffc19Sjw149990 2445a4c37c9Sqh201292 case 'p': 2455a4c37c9Sqh201292 /* 2465a4c37c9Sqh201292 * map openable vhci based name to phci base name 2475a4c37c9Sqh201292 */ 2485a4c37c9Sqh201292 map_vhciname = s_strdup(optarg); 2495a4c37c9Sqh201292 n++; 2505a4c37c9Sqh201292 break; 2517c478bd9Sstevel@tonic-gate 25260fffc19Sjw149990 case 'D': 25360fffc19Sjw149990 /* 25460fffc19Sjw149990 * Grab the driver name we need to look for. Each 25560fffc19Sjw149990 * time we add support for a new SAS or FC driver 25660fffc19Sjw149990 * to this utility, make sure that its driver name 25760fffc19Sjw149990 * is checked here. 25860fffc19Sjw149990 */ 25960fffc19Sjw149990 drvname = s_malloc(sizeof (optarg) + 1); 26060fffc19Sjw149990 drvname = s_strdup(optarg); 26160fffc19Sjw149990 if (strcmp(drvname, "fp") == 0) { 26260fffc19Sjw149990 drvprop = s_malloc(sizeof (NODE_WWN_PROP)); 26360fffc19Sjw149990 (void) snprintf(drvprop, sizeof (NODE_WWN_PROP), 26460fffc19Sjw149990 NODE_WWN_PROP); 26560fffc19Sjw149990 } else if (strcmp(drvname, "mpt") == 0) { 26660fffc19Sjw149990 drvprop = s_malloc(sizeof (SASPROP) + 26760fffc19Sjw149990 sizeof (drvname) + 1); 26860fffc19Sjw149990 (void) snprintf(drvprop, sizeof (SASPROP) + 26960fffc19Sjw149990 sizeof (drvname), "%s%s", 27060fffc19Sjw149990 SASPROP, drvname); 27160fffc19Sjw149990 } else { 27260fffc19Sjw149990 logerr(gettext("Driver %s is not supported\n"), 27360fffc19Sjw149990 drvname); 27460fffc19Sjw149990 clean_exit(1); 27560fffc19Sjw149990 } 27660fffc19Sjw149990 27760fffc19Sjw149990 break; 27860fffc19Sjw149990 27960fffc19Sjw149990 case 'n': 28060fffc19Sjw149990 ++parent; 28160fffc19Sjw149990 n++; 28260fffc19Sjw149990 break; 28360fffc19Sjw149990 2847c478bd9Sstevel@tonic-gate default: 2857c478bd9Sstevel@tonic-gate usage(argv[0]); 2867c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate 29060fffc19Sjw149990 if (n != 1) { 2917c478bd9Sstevel@tonic-gate usage(argv[0]); 2927c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2937c478bd9Sstevel@tonic-gate } 29460fffc19Sjw149990 } 2957c478bd9Sstevel@tonic-gate 29680ab886dSwesolows int 2977c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 2987c478bd9Sstevel@tonic-gate { 2997c478bd9Sstevel@tonic-gate char save_vfstab[SYS_FILENAME_LEN], tmp_vfstab[SYS_FILENAME_LEN]; 3007c478bd9Sstevel@tonic-gate int vfstab_updated; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 3037c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate if (getuid() != 0) { 3067c478bd9Sstevel@tonic-gate logerr(gettext("must be super-user to run this program\n")); 3077c478bd9Sstevel@tonic-gate clean_exit(1); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate parse_args(argc, argv); 3117c478bd9Sstevel@tonic-gate (void) umask(022); 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate /* 3147c478bd9Sstevel@tonic-gate * NOTE: The mpxio boot-up script executes this program with the 3157c478bd9Sstevel@tonic-gate * mapping (-m) option before the /usr is even mounted and when the 3167c478bd9Sstevel@tonic-gate * root filesystem is still mounted read-only. 3177c478bd9Sstevel@tonic-gate */ 3187c478bd9Sstevel@tonic-gate if (*mapdev != '\0') { 3197c478bd9Sstevel@tonic-gate char newname[MAXPATHLEN]; 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate if (map_devname(mapdev, newname, sizeof (newname), 3227c478bd9Sstevel@tonic-gate cap_m_option) == 0) { 3237c478bd9Sstevel@tonic-gate (void) printf("%s\n", newname); 3247c478bd9Sstevel@tonic-gate clean_exit(0); 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate clean_exit(1); 3277c478bd9Sstevel@tonic-gate } 3285a4c37c9Sqh201292 if (*map_vhciname != '\0') { 3295a4c37c9Sqh201292 char newname[MAXPATHLEN]; 3305a4c37c9Sqh201292 3315a4c37c9Sqh201292 if (map_openable_vhciname(map_vhciname, newname, 3325a4c37c9Sqh201292 sizeof (newname)) == 0) { 3335a4c37c9Sqh201292 (void) printf("%s\n", newname); 3345a4c37c9Sqh201292 clean_exit(0); 3355a4c37c9Sqh201292 } 3365a4c37c9Sqh201292 clean_exit(1); 3375a4c37c9Sqh201292 } 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate if (list_option || list_guid_mappings) { 3407c478bd9Sstevel@tonic-gate if (list_mappings(list_controllernum, list_guid_mappings) == 0) 3417c478bd9Sstevel@tonic-gate clean_exit(0); 3427c478bd9Sstevel@tonic-gate clean_exit(1); 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate 34560fffc19Sjw149990 if (parent > 0) { 34660fffc19Sjw149990 if (strcmp(drvname, "") == 0) { 34760fffc19Sjw149990 usage(argv[0]); 34860fffc19Sjw149990 clean_exit(1); 34960fffc19Sjw149990 } else { 35060fffc19Sjw149990 list_nodes(drvname); 35160fffc19Sjw149990 clean_exit(0); 35260fffc19Sjw149990 } 35360fffc19Sjw149990 } 35460fffc19Sjw149990 3557c478bd9Sstevel@tonic-gate /* create a directory where a copy of the system files are saved */ 3567c478bd9Sstevel@tonic-gate if (patch_vfstab) { 3577c478bd9Sstevel@tonic-gate if (mkdirp(SAVE_DIR, 0755) != 0 && errno != EEXIST) { 3587c478bd9Sstevel@tonic-gate logerr(gettext("mkdirp: failed to create %1$s: %2$s\n"), 3597c478bd9Sstevel@tonic-gate SAVE_DIR, strerror(errno)); 3607c478bd9Sstevel@tonic-gate clean_exit(1); 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate if (make_temp(VFSTAB, save_vfstab, tmp_vfstab, 3647c478bd9Sstevel@tonic-gate SYS_FILENAME_LEN) != 0) 3657c478bd9Sstevel@tonic-gate clean_exit(1); 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate /* build new vfstab without modifying the existing one */ 3687c478bd9Sstevel@tonic-gate if ((vfstab_updated = update_vfstab(VFSTAB, tmp_vfstab)) 3697c478bd9Sstevel@tonic-gate == -1) { 3707c478bd9Sstevel@tonic-gate logerr(gettext("failed to update %s\n"), VFSTAB); 3717c478bd9Sstevel@tonic-gate clean_exit(1); 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate commit_change(VFSTAB, save_vfstab, tmp_vfstab, vfstab_updated); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate clean_exit(0); 378815dd917Sjmcp /*NOTREACHED*/ 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. 45360fffc19Sjw149990 * 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; 50660fffc19Sjw149990 } else { 5077c478bd9Sstevel@tonic-gate logdmsg("get_guid: devid_to_guid() failed\n"); 50860fffc19Sjw149990 logdmsg("Unable to get a GUID for device " 50960fffc19Sjw149990 "%s\n", physpath_raw); 51060fffc19Sjw149990 } 51160fffc19Sjw149990 5127c478bd9Sstevel@tonic-gate } else 5137c478bd9Sstevel@tonic-gate logdmsg("get_guid: devid_get() failed: %s\n", strerror(errno)); 5147c478bd9Sstevel@tonic-gate 51560fffc19Sjw149990 /* 51660fffc19Sjw149990 * Unless we're looking at an fp-attached device, we now 51760fffc19Sjw149990 * fallback to node name as the guid as this is what the 51860fffc19Sjw149990 * fcp driver does. A sas-attached device will have the 51960fffc19Sjw149990 * client-guid property set. 52060fffc19Sjw149990 */ 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 53160fffc19Sjw149990 /* non-fp fallout */ 53260fffc19Sjw149990 if (strstr(physpath, "fp") == (char *)NULL) { 53360fffc19Sjw149990 if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, 53460fffc19Sjw149990 "client-guid", &guid) < 0) { 53560fffc19Sjw149990 logdmsg("get_guid: non-fp-attached device, " 53660fffc19Sjw149990 "bailing out\n"); 53760fffc19Sjw149990 goto out; 53860fffc19Sjw149990 } 53960fffc19Sjw149990 } 54060fffc19Sjw149990 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: 57360fffc19Sjw149990 * .../fp@xxx/ssd@yyy CLIENT_TYPE_PHCI (fc) 57460fffc19Sjw149990 * .../LSILogic,sas@xxx/sd@yyy CLIENT_TYPE_PHCI (sas) 57560fffc19Sjw149990 * .../scsi_vhci/ssd@yyy CLIENT_TYPE_VHCI (fc) 57660fffc19Sjw149990 * .../scsi_vhci/disk@yyy CLIENT_TYPE_VHCI (sas) 5777c478bd9Sstevel@tonic-gate * other CLIENT_TYPE_UNKNOWN 5785a4c37c9Sqh201292 * on x86: 57960fffc19Sjw149990 * .../fp@xxx/disk@yyy CLIENT_TYPE_PHCI (fc) 58060fffc19Sjw149990 * .../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; 58860fffc19Sjw149990 char *p1; 58960fffc19Sjw149990 char *client_path; 59060fffc19Sjw149990 59160fffc19Sjw149990 client_path = s_strdup(client_name); 59260fffc19Sjw149990 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 || 59860fffc19Sjw149990 ((strncmp(p1, "/ssd@", sizeof ("/ssd@") - 1) != 0) && 59960fffc19Sjw149990 (strncmp(p1, "/sd@", sizeof ("/sd@") - 1) != 0) && 60060fffc19Sjw149990 (strncmp(p1, "/disk@", sizeof ("/disk@") - 1) != 0))) { 60160fffc19Sjw149990 logdmsg("client_name_type: p1 = %s\n", p1); 6027c478bd9Sstevel@tonic-gate return (CLIENT_TYPE_UNKNOWN); 60360fffc19Sjw149990 } 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate *p1 = '\0'; 6067c478bd9Sstevel@tonic-gate 60760fffc19Sjw149990 /* 60860fffc19Sjw149990 * Courtesy of the if (..) block above, we know that any 60960fffc19Sjw149990 * device path we have now is either PHCI or VHCI 61060fffc19Sjw149990 */ 61160fffc19Sjw149990 client_type = client_by_props(client_path); 61260fffc19Sjw149990 61360fffc19Sjw149990 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 /* 62060fffc19Sjw149990 * client_by_props() is called to determine what the client type 62160fffc19Sjw149990 * is, based on properties in the device tree: 62260fffc19Sjw149990 * 62360fffc19Sjw149990 * drivername property type 62460fffc19Sjw149990 * ------------------------------------- 62560fffc19Sjw149990 * fp node-wwn CLIENT_TYPE_PHCI 62660fffc19Sjw149990 * mpt sas-mpt CLIENT_TYPE_PHCI 62760fffc19Sjw149990 * mpt client-guid CLIENT_TYPE_PHCI (corner case) 62860fffc19Sjw149990 * 62960fffc19Sjw149990 * Normally, the "client-guid" property only shows up for a node 63060fffc19Sjw149990 * if we've enumerated that node under scsi_vhci. During testing 63160fffc19Sjw149990 * of this function, one particular corner case was found which 63260fffc19Sjw149990 * requires an exception handler. 63360fffc19Sjw149990 */ 63460fffc19Sjw149990 63560fffc19Sjw149990 static client_type_t 63660fffc19Sjw149990 client_by_props(char *path) { 63760fffc19Sjw149990 63860fffc19Sjw149990 di_node_t clientnode = DI_NODE_NIL; 63960fffc19Sjw149990 di_node_t parentnode = DI_NODE_NIL; 64060fffc19Sjw149990 unsigned int rval = CLIENT_TYPE_UNKNOWN; 64160fffc19Sjw149990 uchar_t *byteprop[32]; 64260fffc19Sjw149990 char *charprop = NULL; 64360fffc19Sjw149990 char *physpath; 64460fffc19Sjw149990 char *parentpath; 64560fffc19Sjw149990 64660fffc19Sjw149990 physpath = s_malloc(MAXPATHLEN); 64760fffc19Sjw149990 bzero(physpath, MAXPATHLEN); 64860fffc19Sjw149990 64960fffc19Sjw149990 physpath = s_strdup(path); 65060fffc19Sjw149990 65160fffc19Sjw149990 logdmsg("client_by_props: physpath = (%s)\n", physpath); 65260fffc19Sjw149990 65360fffc19Sjw149990 /* easy short-circuits */ 65460fffc19Sjw149990 if (strstr(physpath, "scsi_vhci") != (char *)NULL) { 65560fffc19Sjw149990 logdmsg("client_by_props: found " 65660fffc19Sjw149990 "'scsi_vhci' on path (%s)\n", physpath); 65760fffc19Sjw149990 rval = CLIENT_TYPE_VHCI; 65860fffc19Sjw149990 goto out; 65960fffc19Sjw149990 } else if ((strstr(physpath, "ide") != (char *)NULL) || 66060fffc19Sjw149990 (strstr(physpath, "storage") != (char *)NULL)) { 66160fffc19Sjw149990 logdmsg("client_by_props: ignoring this device\n"); 66260fffc19Sjw149990 goto out; 66360fffc19Sjw149990 } 66460fffc19Sjw149990 66560fffc19Sjw149990 parentpath = s_malloc(MAXPATHLEN); 66660fffc19Sjw149990 bzero(parentpath, MAXPATHLEN); 66760fffc19Sjw149990 66860fffc19Sjw149990 (void) strncpy(parentpath, physpath, strlen(physpath) - 66960fffc19Sjw149990 strlen(strrchr(physpath, '/'))); 67060fffc19Sjw149990 67160fffc19Sjw149990 if ((parentnode = di_init(parentpath, DINFOCPYALL | 67260fffc19Sjw149990 DINFOFORCE)) == DI_NODE_NIL) { 67360fffc19Sjw149990 logdmsg("client_by_props: unable to di_init(%s)\n", 67460fffc19Sjw149990 parentpath); 67560fffc19Sjw149990 goto out; 67660fffc19Sjw149990 } 67760fffc19Sjw149990 67860fffc19Sjw149990 if (strstr(physpath, "fp") != (char *)NULL) { 67960fffc19Sjw149990 if (drvprop == (char *)NULL) { 68060fffc19Sjw149990 drvprop = s_malloc(strlen(NODE_WWN_PROP) + 1); 68160fffc19Sjw149990 } 68260fffc19Sjw149990 logdmsg("NODE_WWN_PROP\n"); 68360fffc19Sjw149990 (void) snprintf(drvprop, strlen(NODE_WWN_PROP) + 1, 68460fffc19Sjw149990 NODE_WWN_PROP); 68560fffc19Sjw149990 } else { 68660fffc19Sjw149990 if (drvname == (char *)NULL) { 68760fffc19Sjw149990 drvname = di_driver_name(parentnode); 68860fffc19Sjw149990 logdmsg("client_by_props: drvname = %s\n", drvname); 68960fffc19Sjw149990 } 69060fffc19Sjw149990 69160fffc19Sjw149990 if (drvprop == (char *)NULL) { 69260fffc19Sjw149990 drvprop = s_malloc(sizeof (SASPROP) + 69360fffc19Sjw149990 sizeof (drvname) + 1); 69460fffc19Sjw149990 } 69560fffc19Sjw149990 (void) snprintf(drvprop, sizeof (SASPROP) + 69660fffc19Sjw149990 sizeof (drvname), "%s%s", SASPROP, drvname); 69760fffc19Sjw149990 69860fffc19Sjw149990 logdmsg("parentpath: %s\nphyspath: %s\n" 69960fffc19Sjw149990 "length %d, strrchr: %d\n", 70060fffc19Sjw149990 parentpath, physpath, strlen(physpath), 70160fffc19Sjw149990 strlen(strrchr(physpath, '/'))); 70260fffc19Sjw149990 } 70360fffc19Sjw149990 70460fffc19Sjw149990 logdmsg("client_by_props: searching for property '%s'\n", drvprop); 70560fffc19Sjw149990 70660fffc19Sjw149990 if ((clientnode = di_init(physpath, DINFOCPYALL | DINFOFORCE)) == 70760fffc19Sjw149990 DI_NODE_NIL) { 70860fffc19Sjw149990 logdmsg("client_by_props: unable to di_init(%s)\n", 70960fffc19Sjw149990 physpath); 71060fffc19Sjw149990 71160fffc19Sjw149990 /* 71260fffc19Sjw149990 * On x86/x64 systems, we won't be able to di_init() the 71360fffc19Sjw149990 * node we want in the device tree, however the parent 71460fffc19Sjw149990 * node will still have 'mpxio-disable' set, so we can 71560fffc19Sjw149990 * check for that property and make our decision on type 71660fffc19Sjw149990 */ 71760fffc19Sjw149990 71860fffc19Sjw149990 if (di_prop_lookup_strings(DDI_DEV_T_ANY, parentnode, 71960fffc19Sjw149990 "mpxio-disable", &charprop) > -1) { 72060fffc19Sjw149990 rval = CLIENT_TYPE_PHCI; 72160fffc19Sjw149990 di_fini(parentnode); 72260fffc19Sjw149990 logdmsg("client_by_props: device %s is PHCI\n", 72360fffc19Sjw149990 physpath); 72460fffc19Sjw149990 } 72560fffc19Sjw149990 goto out; 72660fffc19Sjw149990 } 72760fffc19Sjw149990 72860fffc19Sjw149990 if (di_prop_lookup_bytes(DDI_DEV_T_ANY, 72960fffc19Sjw149990 clientnode, drvprop, byteprop) > -1) { 73060fffc19Sjw149990 logdmsg("client_by_props: found prop %s on " 73160fffc19Sjw149990 "path %s\n", drvprop, physpath); 73260fffc19Sjw149990 rval = CLIENT_TYPE_PHCI; 73360fffc19Sjw149990 } else if (di_prop_lookup_strings(DDI_DEV_T_ANY, 73460fffc19Sjw149990 clientnode, "client-guid", &charprop) > -1) { 73560fffc19Sjw149990 /* 73660fffc19Sjw149990 * A corner case was seen during testing where 73760fffc19Sjw149990 * scsi_vhci was loaded, but not all applicable 73860fffc19Sjw149990 * devices were enumerated under it. That left 73960fffc19Sjw149990 * the phci mapping along with the "client-guid" 74060fffc19Sjw149990 * property. 74160fffc19Sjw149990 */ 74260fffc19Sjw149990 logdmsg("client_by_props: weird... \n"); 74360fffc19Sjw149990 rval = CLIENT_TYPE_PHCI; 74460fffc19Sjw149990 } else { 74560fffc19Sjw149990 logdmsg("client_by_props: unable to find " 74660fffc19Sjw149990 "property 'client-guid', 'mpxio-disable' " 74760fffc19Sjw149990 "or '%s' anywhere on path (%s)\n", 74860fffc19Sjw149990 drvprop, physpath); 74960fffc19Sjw149990 logdmsg("client_by_props: this node is unknown\n"); 75060fffc19Sjw149990 } 75160fffc19Sjw149990 75260fffc19Sjw149990 di_fini(parentnode); 75360fffc19Sjw149990 di_fini(clientnode); 75460fffc19Sjw149990 out: 75560fffc19Sjw149990 free(physpath); 75660fffc19Sjw149990 return (rval); 75760fffc19Sjw149990 } 75860fffc19Sjw149990 75960fffc19Sjw149990 76060fffc19Sjw149990 /* 761*8cecff49Sgp87344 * Given a phci or vhci devname which is either a /dev link or /devices name 762*8cecff49Sgp87344 * get the corresponding physical node path (without the /devices prefix) 763*8cecff49Sgp87344 * and minor name. 764*8cecff49Sgp87344 * 765*8cecff49Sgp87344 * Returns 0 on success, -1 on failure. 766*8cecff49Sgp87344 */ 767*8cecff49Sgp87344 static int 768*8cecff49Sgp87344 get_physname_minor(char *devname, char *physname, int physname_len, 769*8cecff49Sgp87344 char *minorname, int minorname_len) 770*8cecff49Sgp87344 { 771*8cecff49Sgp87344 int linksize; 772*8cecff49Sgp87344 char buf[MAXPATHLEN]; 773*8cecff49Sgp87344 char *p, *m; 774*8cecff49Sgp87344 775*8cecff49Sgp87344 if (strncmp(devname, DEV_DSK, sizeof (DEV_DSK) - 1) == 0 || 776*8cecff49Sgp87344 strncmp(devname, DEV_RDSK, sizeof (DEV_RDSK) - 1) == 0) { 777*8cecff49Sgp87344 if ((linksize = readlink(devname, buf, MAXPATHLEN)) 778*8cecff49Sgp87344 > 0 && linksize <= (MAXPATHLEN - 1)) { 779*8cecff49Sgp87344 buf[linksize] = '\0'; 780*8cecff49Sgp87344 } else 781*8cecff49Sgp87344 return (-1); 782*8cecff49Sgp87344 } else 783*8cecff49Sgp87344 s_strlcpy(buf, devname, MAXPATHLEN); 784*8cecff49Sgp87344 785*8cecff49Sgp87344 if ((p = strstr(buf, SLASH_DEVICES)) == NULL) 786*8cecff49Sgp87344 return (-1); 787*8cecff49Sgp87344 788*8cecff49Sgp87344 /* point to '/' after /devices */ 789*8cecff49Sgp87344 p += sizeof (SLASH_DEVICES) - 2; 790*8cecff49Sgp87344 791*8cecff49Sgp87344 if ((m = strrchr(p, ':')) == NULL) { 792*8cecff49Sgp87344 logdmsg("get_physname_minor: no minor name component in %s\n", 793*8cecff49Sgp87344 buf); 794*8cecff49Sgp87344 return (-1); 795*8cecff49Sgp87344 } 796*8cecff49Sgp87344 797*8cecff49Sgp87344 *m = '\0'; 798*8cecff49Sgp87344 m++; 799*8cecff49Sgp87344 800*8cecff49Sgp87344 if (client_name_type(p) == CLIENT_TYPE_UNKNOWN) 801*8cecff49Sgp87344 return (-1); 802*8cecff49Sgp87344 803*8cecff49Sgp87344 s_strlcpy(physname, p, physname_len); 804*8cecff49Sgp87344 s_strlcpy(minorname, m, minorname_len); 805*8cecff49Sgp87344 logdmsg("get_physname_minor: %s: physname = %s, minor = %s\n", 806*8cecff49Sgp87344 devname, physname, minorname); 807*8cecff49Sgp87344 return (0); 808*8cecff49Sgp87344 } 809*8cecff49Sgp87344 810*8cecff49Sgp87344 811*8cecff49Sgp87344 /* 8127c478bd9Sstevel@tonic-gate * Map phci based client name to vhci based client name. 8137c478bd9Sstevel@tonic-gate * 8147c478bd9Sstevel@tonic-gate * phci_name 8157c478bd9Sstevel@tonic-gate * phci based client /devices name without the /devices prefix and 8167c478bd9Sstevel@tonic-gate * minor name component. 8175a4c37c9Sqh201292 * ex: 81860fffc19Sjw149990 * 81960fffc19Sjw149990 * (FC) 8205a4c37c9Sqh201292 * for sparc: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0 8215a4c37c9Sqh201292 * for x86: /pci@8,600000/SUNW,qlc@4/fp@0,0/disk@w2100002037cd9f72,0 8227c478bd9Sstevel@tonic-gate * 82360fffc19Sjw149990 * (SAS) 82460fffc19Sjw149990 * for sparc: /pci@0,2/LSILogic,sas@1/disk@6,0 82560fffc19Sjw149990 * for x86: /pci1000,3060@3/sd@0,0 82660fffc19Sjw149990 * 8277c478bd9Sstevel@tonic-gate * vhci_name 8287c478bd9Sstevel@tonic-gate * Caller supplied buffer where vhci /devices name will be placed on 8297c478bd9Sstevel@tonic-gate * return (without the /devices prefix and minor name component). 8305a4c37c9Sqh201292 * ex: 83160fffc19Sjw149990 * 83260fffc19Sjw149990 * (FC) 8335a4c37c9Sqh201292 * for sparc: /scsi_vhci/ssd@g2000002037cd9f72 8345a4c37c9Sqh201292 * for x86: /scsi_vhci/disk@g2000002037cd9f72 8357c478bd9Sstevel@tonic-gate * 83660fffc19Sjw149990 * (SAS) 83760fffc19Sjw149990 * both: /scsi_vhci/disk@g600a0b8000254d3e00000284453ed8ac 83860fffc19Sjw149990 * 8397c478bd9Sstevel@tonic-gate * vhci_name_len 8407c478bd9Sstevel@tonic-gate * Length of the caller supplied vhci_name buffer. 8417c478bd9Sstevel@tonic-gate * 8427c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 8437c478bd9Sstevel@tonic-gate */ 8447c478bd9Sstevel@tonic-gate static int 8457c478bd9Sstevel@tonic-gate phci_to_vhci(char *phci_name, char *vhci_name, size_t vhci_name_len) 8467c478bd9Sstevel@tonic-gate { 8477c478bd9Sstevel@tonic-gate sv_iocdata_t ioc; 84860fffc19Sjw149990 char *slash, *at; 8497c478bd9Sstevel@tonic-gate char vhci_name_buf[MAXPATHLEN]; 8507c478bd9Sstevel@tonic-gate char phci_name_buf[MAXPATHLEN]; 8517c478bd9Sstevel@tonic-gate char addr_buf[MAXNAMELEN]; 8527c478bd9Sstevel@tonic-gate 8537c478bd9Sstevel@tonic-gate logdmsg("phci_to_vhci: client = %s\n", phci_name); 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate s_strlcpy(phci_name_buf, phci_name, MAXPATHLEN); 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate if (client_name_type(phci_name_buf) != CLIENT_TYPE_PHCI || 8587c478bd9Sstevel@tonic-gate (slash = strrchr(phci_name_buf, '/')) == NULL || 85960fffc19Sjw149990 ((strncmp(slash, "/ssd@", sizeof ("/ssd@") - 1) != 0) && 86060fffc19Sjw149990 (strncmp(slash, "/sd@", sizeof ("/sd@") - 1) != 0) && 86160fffc19Sjw149990 (strncmp(slash, "/disk@", sizeof ("/disk@") - 1) != 0))) { 8627c478bd9Sstevel@tonic-gate logdmsg("phci_to_vhci: %s is not of CLIENT_TYPE_PHCI\n", 8637c478bd9Sstevel@tonic-gate phci_name); 8647c478bd9Sstevel@tonic-gate return (-1); 8657c478bd9Sstevel@tonic-gate } 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate if (vhci_fd < 0) { 8687c478bd9Sstevel@tonic-gate if ((vhci_fd = open(VHCI_CTL_NODE, O_RDWR)) < 0) 8697c478bd9Sstevel@tonic-gate return (-1); 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate *slash = '\0'; 87360fffc19Sjw149990 87460fffc19Sjw149990 at = strchr(slash + 1, '@'); 87560fffc19Sjw149990 s_strlcpy(addr_buf, at + 1, MAXNAMELEN); 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate bzero(&ioc, sizeof (sv_iocdata_t)); 8787c478bd9Sstevel@tonic-gate ioc.client = vhci_name_buf; 8797c478bd9Sstevel@tonic-gate ioc.phci = phci_name_buf; 8807c478bd9Sstevel@tonic-gate ioc.addr = addr_buf; 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate if (ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_NAME, &ioc) != 0) { 8837c478bd9Sstevel@tonic-gate logdmsg("SCSI_VHCI_GET_CLIENT_NAME on %s " 8847c478bd9Sstevel@tonic-gate "failed: %s\n", phci_name, strerror(errno)); 8857c478bd9Sstevel@tonic-gate return (-1); 8867c478bd9Sstevel@tonic-gate } 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate s_strlcpy(vhci_name, vhci_name_buf, vhci_name_len); 8897c478bd9Sstevel@tonic-gate logdmsg("phci_to_vhci: %s maps to %s\n", phci_name, vhci_name); 8907c478bd9Sstevel@tonic-gate return (0); 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate /* 8947c478bd9Sstevel@tonic-gate * Map vhci based client name to phci based client name. 8957c478bd9Sstevel@tonic-gate * If the client has multiple paths, only one of the paths with which client 8967c478bd9Sstevel@tonic-gate * can be accessed is returned. This function does not use SCSI_VHCI ioctls 8977c478bd9Sstevel@tonic-gate * as it is called on mpxio disabled paths. 8987c478bd9Sstevel@tonic-gate * 8997c478bd9Sstevel@tonic-gate * vhci_name 9007c478bd9Sstevel@tonic-gate * vhci based client /devices name without the /devices prefix and 9017c478bd9Sstevel@tonic-gate * minor name component. 9025a4c37c9Sqh201292 * ex: 9035a4c37c9Sqh201292 * sparc: /scsi_vhci/ssd@g2000002037cd9f72 9045a4c37c9Sqh201292 * x86: /scsi_vhci/disk@g2000002037cd9f72 9057c478bd9Sstevel@tonic-gate * 9067c478bd9Sstevel@tonic-gate * phci_name 9077c478bd9Sstevel@tonic-gate * Caller supplied buffer where phci /devices name will be placed on 9087c478bd9Sstevel@tonic-gate * return (without the /devices prefix and minor name component). 9095a4c37c9Sqh201292 * ex: 9105a4c37c9Sqh201292 * sparc: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0 9115a4c37c9Sqh201292 * x86: /pci@8,600000/SUNW,qlc@4/fp@0,0/disk@w2100002037cd9f72,0 9127c478bd9Sstevel@tonic-gate * 9137c478bd9Sstevel@tonic-gate * phci_name_len 9147c478bd9Sstevel@tonic-gate * Length of the caller supplied phci_name buffer. 9157c478bd9Sstevel@tonic-gate * 916*8cecff49Sgp87344 * minor 917*8cecff49Sgp87344 * The slice of the disk of interest. 918*8cecff49Sgp87344 * 9197c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 9207c478bd9Sstevel@tonic-gate */ 9217c478bd9Sstevel@tonic-gate static int 922*8cecff49Sgp87344 vhci_to_phci(char *vhci_name, char *phci_name, size_t phci_name_len, 923*8cecff49Sgp87344 char *minor) 9247c478bd9Sstevel@tonic-gate { 92560fffc19Sjw149990 di_node_t node = DI_NODE_NIL; 9267c478bd9Sstevel@tonic-gate char *vhci_guid, *devfspath; 9277c478bd9Sstevel@tonic-gate char phci_guid[MAXPATHLEN]; 928*8cecff49Sgp87344 char root_guid[MAXPATHLEN]; 929*8cecff49Sgp87344 char root_phys[MAXPATHLEN]; 930*8cecff49Sgp87344 char root_minor[MAXPATHLEN]; 931*8cecff49Sgp87344 char root_path[MAXPATHLEN]; 93260fffc19Sjw149990 char *node_name; 933*8cecff49Sgp87344 FILE *mntfp; 934*8cecff49Sgp87344 struct mnttab mntpref, rootmnt; 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: client = %s\n", vhci_name); 9377c478bd9Sstevel@tonic-gate 938*8cecff49Sgp87344 bzero(&mntpref, sizeof (mntpref)); 939*8cecff49Sgp87344 mntpref.mnt_mountp = "/"; 940*8cecff49Sgp87344 941*8cecff49Sgp87344 if (!(mntfp = fopen(MNTTAB, "r"))) { 942*8cecff49Sgp87344 logdmsg("vhci_to_phci: can't open %s\n", MNTTAB); 943*8cecff49Sgp87344 return (-1); 944*8cecff49Sgp87344 } 945*8cecff49Sgp87344 946*8cecff49Sgp87344 if (getmntany(mntfp, &rootmnt, &mntpref)) { 947*8cecff49Sgp87344 logdmsg("vhci_to_phci: can't find / in %s\n", MNTTAB); 948*8cecff49Sgp87344 return (-1); 949*8cecff49Sgp87344 } 950*8cecff49Sgp87344 951*8cecff49Sgp87344 (void) fclose(mntfp); 952*8cecff49Sgp87344 9537c478bd9Sstevel@tonic-gate if (client_name_type(vhci_name) != CLIENT_TYPE_VHCI) { 9547c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: %s is not of CLIENT_TYPE_VHCI\n", 9557c478bd9Sstevel@tonic-gate vhci_name); 9567c478bd9Sstevel@tonic-gate return (-1); 9577c478bd9Sstevel@tonic-gate } 9587c478bd9Sstevel@tonic-gate 95960fffc19Sjw149990 9607c478bd9Sstevel@tonic-gate if ((vhci_guid = strrchr(vhci_name, '@')) == NULL || 9617c478bd9Sstevel@tonic-gate *(++vhci_guid) != 'g') { 9627c478bd9Sstevel@tonic-gate logerr(gettext("couldn't get guid from %s\n"), vhci_name); 9637c478bd9Sstevel@tonic-gate return (-1); 9647c478bd9Sstevel@tonic-gate } 9657c478bd9Sstevel@tonic-gate 9667c478bd9Sstevel@tonic-gate /* point to guid */ 9677c478bd9Sstevel@tonic-gate ++vhci_guid; 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate /* 9707c478bd9Sstevel@tonic-gate * Get devinfo snapshot and walk all ssd nodes whose parent is fp. 9717c478bd9Sstevel@tonic-gate * For each node get the guid and match it with vhci_guid. 9727c478bd9Sstevel@tonic-gate */ 9737c478bd9Sstevel@tonic-gate if (devinfo_root == DI_NODE_NIL) { 9747c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: taking devinfo snapshot\n"); 9757c478bd9Sstevel@tonic-gate if ((devinfo_root = di_init("/", DINFOCPYALL | DINFOFORCE)) 9767c478bd9Sstevel@tonic-gate == DI_NODE_NIL) { 9777c478bd9Sstevel@tonic-gate logerr(gettext("di_init failed: %s\n"), 9787c478bd9Sstevel@tonic-gate strerror(errno)); 9797c478bd9Sstevel@tonic-gate return (-1); 9807c478bd9Sstevel@tonic-gate } 9817c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: done taking devinfo snapshot\n"); 9827c478bd9Sstevel@tonic-gate } 9837c478bd9Sstevel@tonic-gate 984*8cecff49Sgp87344 if (strncmp(rootmnt.mnt_special, SLASH_DEVICES, 985*8cecff49Sgp87344 sizeof (SLASH_DEVICES)-1)) 986*8cecff49Sgp87344 (void) snprintf(root_path, sizeof (root_path), "/devices%s", 987*8cecff49Sgp87344 rootmnt.mnt_special); 988*8cecff49Sgp87344 else 989*8cecff49Sgp87344 (void) strcpy(root_path, rootmnt.mnt_special); 990*8cecff49Sgp87344 991*8cecff49Sgp87344 /* 992*8cecff49Sgp87344 * remove the /devices and minor components to call get_guid() 993*8cecff49Sgp87344 * if we can't get the guid, drop through to the regular processing. 994*8cecff49Sgp87344 */ 995*8cecff49Sgp87344 if ((get_physname_minor(root_path, root_phys, sizeof (root_phys), 996*8cecff49Sgp87344 root_minor, sizeof (root_minor)) || 997*8cecff49Sgp87344 (get_guid(root_phys, root_guid, sizeof (root_guid), 0, 998*8cecff49Sgp87344 node) != 0))) { 999*8cecff49Sgp87344 logdmsg("vhci_to_phci: can't get_guid for / (%s)\n", 1000*8cecff49Sgp87344 rootmnt.mnt_special); 1001*8cecff49Sgp87344 (void) strcpy(root_guid, ""); 1002*8cecff49Sgp87344 } 1003*8cecff49Sgp87344 1004*8cecff49Sgp87344 /* 1005*8cecff49Sgp87344 * We check the guid of the root device against the vhci guid so we 1006*8cecff49Sgp87344 * can return a preferred path. 1007*8cecff49Sgp87344 */ 1008*8cecff49Sgp87344 if ((strcmp(root_guid, vhci_guid) == 0) && 1009*8cecff49Sgp87344 (canread(root_phys, minor))) { 1010*8cecff49Sgp87344 s_strlcpy(phci_name, root_phys, phci_name_len); 1011*8cecff49Sgp87344 logdmsg("vhci_to_phci: %s maps to %s preferred path\n", 1012*8cecff49Sgp87344 vhci_name, phci_name); 1013*8cecff49Sgp87344 return (0); 1014*8cecff49Sgp87344 } 101560fffc19Sjw149990 101660fffc19Sjw149990 /* 101760fffc19Sjw149990 * When we finally get a unified "sd" driver for all 101860fffc19Sjw149990 * architectures that Solaris runs on, we can remove this 101960fffc19Sjw149990 * first loop around for "ssd" 102060fffc19Sjw149990 */ 102160fffc19Sjw149990 for (node = di_drv_first_node("ssd", devinfo_root); 10227c478bd9Sstevel@tonic-gate node != DI_NODE_NIL; node = di_drv_next_node(node)) { 102360fffc19Sjw149990 102460fffc19Sjw149990 if ((node_name = di_node_name(node)) == NULL) 102560fffc19Sjw149990 continue; 102660fffc19Sjw149990 102760fffc19Sjw149990 if ((strcmp(node_name, "disk") != 0) && 102860fffc19Sjw149990 (strcmp(node_name, "sd") != 0) && 102960fffc19Sjw149990 (strcmp(node_name, "ssd") != 0)) 103060fffc19Sjw149990 continue; 103160fffc19Sjw149990 103260fffc19Sjw149990 if (di_parent_node(node) == DI_NODE_NIL) 103360fffc19Sjw149990 continue; 103460fffc19Sjw149990 103560fffc19Sjw149990 if ((devfspath = di_devfs_path(node)) == NULL) 10367c478bd9Sstevel@tonic-gate continue; 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate /* 10397c478bd9Sstevel@tonic-gate * Don't set no_delay_flag to have get_guid() fail on 10407c478bd9Sstevel@tonic-gate * standby paths of T3. So we'll find the preferred paths. 10417c478bd9Sstevel@tonic-gate */ 10427c478bd9Sstevel@tonic-gate if (get_guid(devfspath, phci_guid, 104360fffc19Sjw149990 sizeof (phci_guid), 0, node) != 0) 104460fffc19Sjw149990 continue; 104560fffc19Sjw149990 1046*8cecff49Sgp87344 /* 1047*8cecff49Sgp87344 * If the GUID's match, and we can read data from the path of 1048*8cecff49Sgp87344 * interest, we conclude we have the correct path to use. 1049*8cecff49Sgp87344 */ 1050*8cecff49Sgp87344 if ((strcmp(phci_guid, vhci_guid) == 0) && 1051*8cecff49Sgp87344 (canread(devfspath, minor))) { 105260fffc19Sjw149990 s_strlcpy(phci_name, devfspath, phci_name_len); 105360fffc19Sjw149990 di_devfs_path_free(devfspath); 105460fffc19Sjw149990 logdmsg("vhci_to_phci: %s maps to %s\n", vhci_name, 105560fffc19Sjw149990 phci_name); 105660fffc19Sjw149990 return (0); 105760fffc19Sjw149990 } 105860fffc19Sjw149990 105960fffc19Sjw149990 di_devfs_path_free(devfspath); 106060fffc19Sjw149990 } 106160fffc19Sjw149990 106260fffc19Sjw149990 for (node = di_drv_first_node("sd", devinfo_root); 106360fffc19Sjw149990 node != DI_NODE_NIL; node = di_drv_next_node(node)) { 106460fffc19Sjw149990 106560fffc19Sjw149990 if ((node_name = di_node_name(node)) == NULL) 106660fffc19Sjw149990 continue; 106760fffc19Sjw149990 106860fffc19Sjw149990 if ((strcmp(node_name, "disk") != 0) && 106960fffc19Sjw149990 (strcmp(node_name, "sd") != 0) && 107060fffc19Sjw149990 (strcmp(node_name, "ssd") != 0)) 107160fffc19Sjw149990 continue; 107260fffc19Sjw149990 107360fffc19Sjw149990 if (di_parent_node(node) == DI_NODE_NIL) 107460fffc19Sjw149990 continue; 107560fffc19Sjw149990 107660fffc19Sjw149990 if ((devfspath = di_devfs_path(node)) == NULL) 107760fffc19Sjw149990 continue; 107860fffc19Sjw149990 107960fffc19Sjw149990 /* 108060fffc19Sjw149990 * Don't set no_delay_flag to have get_guid() fail on 108160fffc19Sjw149990 * standby paths of T3. So we'll find the preferred paths. 108260fffc19Sjw149990 */ 108360fffc19Sjw149990 if (get_guid(devfspath, phci_guid, 108460fffc19Sjw149990 sizeof (phci_guid), 0, node) != 0) 108560fffc19Sjw149990 continue; 108660fffc19Sjw149990 1087*8cecff49Sgp87344 /* 1088*8cecff49Sgp87344 * If the GUID's match, and we can read data from the path of 1089*8cecff49Sgp87344 * interest, we conclude we have the correct path to use. 1090*8cecff49Sgp87344 */ 1091*8cecff49Sgp87344 if ((strcmp(phci_guid, vhci_guid) == 0) && 1092*8cecff49Sgp87344 (canread(devfspath, minor))) { 10937c478bd9Sstevel@tonic-gate s_strlcpy(phci_name, devfspath, phci_name_len); 10947c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 10957c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: %s maps to %s\n", vhci_name, 10967c478bd9Sstevel@tonic-gate phci_name); 10977c478bd9Sstevel@tonic-gate return (0); 10987c478bd9Sstevel@tonic-gate } 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 11017c478bd9Sstevel@tonic-gate } 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: couldn't get phci name for %s\n", vhci_name); 11047c478bd9Sstevel@tonic-gate return (-1); 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate /* 11085a4c37c9Sqh201292 * Map vhci based client name to phci based client name. 11095a4c37c9Sqh201292 * If the client has multiple paths, only one of the paths with which client 11105a4c37c9Sqh201292 * can be accessed is returned. 11115a4c37c9Sqh201292 * This function uses SCSI_VHCI ioctls to get the phci paths 11125a4c37c9Sqh201292 * 11135a4c37c9Sqh201292 * vhci_name 11145a4c37c9Sqh201292 * vhci based client /devices name without the /devices prefix and 11155a4c37c9Sqh201292 * minor name component. 11165a4c37c9Sqh201292 * ex: 11175a4c37c9Sqh201292 * sparc: /scsi_vhci/ssd@g2000002037cd9f72 11185a4c37c9Sqh201292 * x86: /scsi_vhci/disk@g2000002037cd9f72 11195a4c37c9Sqh201292 * 11205a4c37c9Sqh201292 * phci_name 11215a4c37c9Sqh201292 * Caller supplied buffer where phci /devices name will be placed on 11225a4c37c9Sqh201292 * return (without the /devices prefix and minor name component). 11235a4c37c9Sqh201292 * ex: 11245a4c37c9Sqh201292 * sparc: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0 11255a4c37c9Sqh201292 * x86: /pci@8,600000/SUNW,qlc@4/fp@0,0/disk@w2100002037cd9f72,0 11265a4c37c9Sqh201292 * 11275a4c37c9Sqh201292 * phci_name_len 11285a4c37c9Sqh201292 * Length of the caller supplied phci_name buffer. 11295a4c37c9Sqh201292 * 11305a4c37c9Sqh201292 * Returns 0 on success, -1 on failure. 11315a4c37c9Sqh201292 */ 11325a4c37c9Sqh201292 11335a4c37c9Sqh201292 static int 11345a4c37c9Sqh201292 vhci_to_phci_by_ioctl(char *vhci_name, char *phci_name, size_t phci_name_len) 11355a4c37c9Sqh201292 { 11365a4c37c9Sqh201292 sv_iocdata_t ioc; 11375a4c37c9Sqh201292 uint_t npaths; 11385a4c37c9Sqh201292 char *node_name, *at; 11395a4c37c9Sqh201292 char vhci_name_buf[MAXPATHLEN]; 11405a4c37c9Sqh201292 int ret; 11415a4c37c9Sqh201292 sv_path_info_t *pi; 11425a4c37c9Sqh201292 11435a4c37c9Sqh201292 logdmsg("vhci_to_phci_by_ioctl: client = %s\n", vhci_name); 11445a4c37c9Sqh201292 11455a4c37c9Sqh201292 if (vhci_fd < 0) { 11465a4c37c9Sqh201292 if ((vhci_fd = open(VHCI_CTL_NODE, O_RDWR)) < 0) 11475a4c37c9Sqh201292 return (-1); 11485a4c37c9Sqh201292 } 11495a4c37c9Sqh201292 11505a4c37c9Sqh201292 (void) strlcpy(vhci_name_buf, vhci_name, MAXPATHLEN); 11515a4c37c9Sqh201292 11525a4c37c9Sqh201292 /* first get the number paths */ 11535a4c37c9Sqh201292 bzero(&ioc, sizeof (sv_iocdata_t)); 11545a4c37c9Sqh201292 ioc.client = vhci_name_buf; 11555a4c37c9Sqh201292 ioc.ret_elem = &npaths; 11565a4c37c9Sqh201292 if ((ret = ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, 11575a4c37c9Sqh201292 &ioc)) != 0 || npaths == 0) { 11585a4c37c9Sqh201292 logdmsg("SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO on %s " 11595a4c37c9Sqh201292 "failed: %s\n", vhci_name, 11605a4c37c9Sqh201292 ret?strerror(errno):"got 0 paths"); 11615a4c37c9Sqh201292 return (-1); 11625a4c37c9Sqh201292 } 11635a4c37c9Sqh201292 11645a4c37c9Sqh201292 /* now allocate memory for the path information and get all paths */ 11655a4c37c9Sqh201292 bzero(&ioc, sizeof (sv_iocdata_t)); 11665a4c37c9Sqh201292 ioc.client = vhci_name_buf; 11675a4c37c9Sqh201292 ioc.buf_elem = npaths; 11685a4c37c9Sqh201292 ioc.ret_elem = &npaths; 11695a4c37c9Sqh201292 if ((ioc.ret_buf = (sv_path_info_t *)calloc(npaths, 11705a4c37c9Sqh201292 sizeof (sv_path_info_t))) == NULL) 11715a4c37c9Sqh201292 return (-1); 11725a4c37c9Sqh201292 if ((ret = ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO, 11735a4c37c9Sqh201292 &ioc)) != 0 || npaths == 0) { 11745a4c37c9Sqh201292 logdmsg("SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO on %s " 11755a4c37c9Sqh201292 "failed: %s\n", vhci_name, 11765a4c37c9Sqh201292 ret?strerror(errno):"got 0 paths"); 11775a4c37c9Sqh201292 goto out; 11785a4c37c9Sqh201292 } 11795a4c37c9Sqh201292 11805a4c37c9Sqh201292 if (ioc.buf_elem < npaths) 11815a4c37c9Sqh201292 npaths = ioc.buf_elem; 11825a4c37c9Sqh201292 if ((node_name = strrchr(vhci_name_buf, '/')) == NULL || 11835a4c37c9Sqh201292 (at = strchr(node_name, '@')) == NULL) 11845a4c37c9Sqh201292 goto out; 11855a4c37c9Sqh201292 11865a4c37c9Sqh201292 node_name++; 11875a4c37c9Sqh201292 *at = '\0'; 11885a4c37c9Sqh201292 118960fffc19Sjw149990 logdmsg("vhci_to_phci_by_ioctl: node_name is %s\n", node_name); 119060fffc19Sjw149990 #ifndef sparc 119160fffc19Sjw149990 /* 119260fffc19Sjw149990 * We need to use a libdevinfo call to get this info 119360fffc19Sjw149990 * in an architecturally-neutral fashion. Phase-II for sure! 119460fffc19Sjw149990 */ 119560fffc19Sjw149990 node_name = "sd"; 119660fffc19Sjw149990 #endif 119760fffc19Sjw149990 11985a4c37c9Sqh201292 /* 11995a4c37c9Sqh201292 * return the first online paths as non-online paths may 12005a4c37c9Sqh201292 * not be accessible in the target environment. 12015a4c37c9Sqh201292 */ 12025a4c37c9Sqh201292 pi = (sv_path_info_t *)ioc.ret_buf; 12035a4c37c9Sqh201292 while (npaths--) { 12045a4c37c9Sqh201292 if (MDI_PATHINFO_STATE_ONLINE == pi->ret_state) { 12055a4c37c9Sqh201292 (void) snprintf(phci_name, phci_name_len, "%s/%s@%s", 12065a4c37c9Sqh201292 pi->device.ret_phci, node_name, 12075a4c37c9Sqh201292 pi->ret_addr); 12085a4c37c9Sqh201292 logdmsg("vhci_to_phci_by_ioctl: %s maps to %s\n", 12095a4c37c9Sqh201292 vhci_name, phci_name); 12105a4c37c9Sqh201292 free(ioc.ret_buf); 12115a4c37c9Sqh201292 return (0); 12125a4c37c9Sqh201292 } 12135a4c37c9Sqh201292 pi++; 12145a4c37c9Sqh201292 } 12155a4c37c9Sqh201292 12165a4c37c9Sqh201292 out: 12175a4c37c9Sqh201292 logdmsg("vhci_to_phci_by_ioctl: couldn't get phci name for %s\n", 12185a4c37c9Sqh201292 vhci_name); 12195a4c37c9Sqh201292 free(ioc.ret_buf); 12205a4c37c9Sqh201292 return (-1); 12215a4c37c9Sqh201292 12225a4c37c9Sqh201292 } 12235a4c37c9Sqh201292 12245a4c37c9Sqh201292 /* 12257c478bd9Sstevel@tonic-gate * Map physname from phci name space to vhci name space or vice-versa 12267c478bd9Sstevel@tonic-gate * 12277c478bd9Sstevel@tonic-gate * physname 12287c478bd9Sstevel@tonic-gate * phci or vhci based client /devices name without the /devices prefix and 12297c478bd9Sstevel@tonic-gate * minor name component. 12307c478bd9Sstevel@tonic-gate * 12317c478bd9Sstevel@tonic-gate * new_physname 12327c478bd9Sstevel@tonic-gate * Caller supplied buffer where the mapped physical name is stored on 12337c478bd9Sstevel@tonic-gate * return (without the /devices prefix and minor name component). 12347c478bd9Sstevel@tonic-gate * 12357c478bd9Sstevel@tonic-gate * len 12367c478bd9Sstevel@tonic-gate * Length of the caller supplied new_physname buffer. 12377c478bd9Sstevel@tonic-gate * 1238*8cecff49Sgp87344 * minor 1239*8cecff49Sgp87344 * The slice of the disk of interest. 1240*8cecff49Sgp87344 * 12417c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 12427c478bd9Sstevel@tonic-gate */ 12437c478bd9Sstevel@tonic-gate static int 1244*8cecff49Sgp87344 map_physname(char *physname, char *new_physname, size_t len, char *minor) 12457c478bd9Sstevel@tonic-gate { 12467c478bd9Sstevel@tonic-gate int type; 12477c478bd9Sstevel@tonic-gate int rv; 12487c478bd9Sstevel@tonic-gate 124960fffc19Sjw149990 type = client_name_type(physname); 125060fffc19Sjw149990 logdmsg("map_physname: type (%d) physname = %s\n", 125160fffc19Sjw149990 type, physname); 125260fffc19Sjw149990 125360fffc19Sjw149990 if (type == CLIENT_TYPE_VHCI) 1254*8cecff49Sgp87344 rv = vhci_to_phci(physname, new_physname, len, minor); 12557c478bd9Sstevel@tonic-gate else if (type == CLIENT_TYPE_PHCI) 12567c478bd9Sstevel@tonic-gate rv = phci_to_vhci(physname, new_physname, len); 12577c478bd9Sstevel@tonic-gate else 12587c478bd9Sstevel@tonic-gate rv = -1; 12597c478bd9Sstevel@tonic-gate 126060fffc19Sjw149990 logdmsg("map_physname: returning %d\n", rv); 12617c478bd9Sstevel@tonic-gate return (rv); 12627c478bd9Sstevel@tonic-gate } 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate static int 12657c478bd9Sstevel@tonic-gate devlink_callback(di_devlink_t devlink, void *argptr) 12667c478bd9Sstevel@tonic-gate { 12677c478bd9Sstevel@tonic-gate const char *link; 12687c478bd9Sstevel@tonic-gate struct devlink_cbarg *argp = argptr; 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate if ((link = di_devlink_path(devlink)) != NULL) { 12717c478bd9Sstevel@tonic-gate s_strlcpy(argp->devlink, link, argp->len); 12727c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 12737c478bd9Sstevel@tonic-gate } 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 12767c478bd9Sstevel@tonic-gate } 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate /* 12797c478bd9Sstevel@tonic-gate * Lookup the /dev link corresponding to physname and minorname. 12807c478bd9Sstevel@tonic-gate * 12817c478bd9Sstevel@tonic-gate * physname client /devices path without the /devices prefix and minor 12827c478bd9Sstevel@tonic-gate * name component. 12837c478bd9Sstevel@tonic-gate * minorname client minor name. 12847c478bd9Sstevel@tonic-gate * devlink caller supplied buffer where the /dev link is placed on return. 12857c478bd9Sstevel@tonic-gate * len caller supplied devlink buffer length 12867c478bd9Sstevel@tonic-gate * 12877c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 12887c478bd9Sstevel@tonic-gate */ 12897c478bd9Sstevel@tonic-gate static int 12907c478bd9Sstevel@tonic-gate lookup_devlink(char *physname, char *minorname, char *devlink, size_t len) 12917c478bd9Sstevel@tonic-gate { 12927c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 12937c478bd9Sstevel@tonic-gate struct devlink_cbarg arg; 12947c478bd9Sstevel@tonic-gate 12957c478bd9Sstevel@tonic-gate if (devlink_hdl == NULL) { 12967c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: taking devlink snapshot\n"); 12977c478bd9Sstevel@tonic-gate if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 12987c478bd9Sstevel@tonic-gate logerr(gettext("di_devlink_init failed: %s\n"), 12997c478bd9Sstevel@tonic-gate strerror(errno)); 13007c478bd9Sstevel@tonic-gate clean_exit(1); 13017c478bd9Sstevel@tonic-gate } 13027c478bd9Sstevel@tonic-gate } 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate *devlink = '\0'; 13057c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, "%s:%s", physname, minorname); 13067c478bd9Sstevel@tonic-gate arg.devlink = devlink; 13077c478bd9Sstevel@tonic-gate arg.len = len; 13087c478bd9Sstevel@tonic-gate if (di_devlink_walk(devlink_hdl, NULL, buf, DI_PRIMARY_LINK, &arg, 13097c478bd9Sstevel@tonic-gate devlink_callback) != 0) { 13107c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: di_devlink_walk on %s failed: %s\n", 13117c478bd9Sstevel@tonic-gate buf, strerror(errno)); 13127c478bd9Sstevel@tonic-gate return (-1); 13137c478bd9Sstevel@tonic-gate } 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate if (*devlink == '\0') { 13167c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: failed to lookup devlink for %s\n", 13177c478bd9Sstevel@tonic-gate buf); 13187c478bd9Sstevel@tonic-gate return (-1); 13197c478bd9Sstevel@tonic-gate } 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: /dev link for %s:%s = %s\n", physname, 13227c478bd9Sstevel@tonic-gate minorname, devlink); 13237c478bd9Sstevel@tonic-gate return (0); 13247c478bd9Sstevel@tonic-gate } 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate /* 13277c478bd9Sstevel@tonic-gate * open infile for reading and return its file pointer in *fp_in. 13287c478bd9Sstevel@tonic-gate * open outfile for writing and return its file pointer in *fp_out. 13297c478bd9Sstevel@tonic-gate * 13307c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 13317c478bd9Sstevel@tonic-gate */ 13327c478bd9Sstevel@tonic-gate static int 13337c478bd9Sstevel@tonic-gate open_in_out_files(char *infile, char *outfile, FILE **fp_in, FILE **fp_out) 13347c478bd9Sstevel@tonic-gate { 13357c478bd9Sstevel@tonic-gate FILE *fin = NULL; 13367c478bd9Sstevel@tonic-gate FILE *fout = NULL; 13377c478bd9Sstevel@tonic-gate struct stat sbuf; 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate if ((fin = fopen(infile, "r")) == NULL) { 13407c478bd9Sstevel@tonic-gate logerr(gettext("failed to fopen %1$s: %2$s\n"), 13417c478bd9Sstevel@tonic-gate infile, strerror(errno)); 13427c478bd9Sstevel@tonic-gate goto out; 13437c478bd9Sstevel@tonic-gate } 13447c478bd9Sstevel@tonic-gate 13457c478bd9Sstevel@tonic-gate if (fstat(fileno(fin), &sbuf) != 0) { 13467c478bd9Sstevel@tonic-gate logerr(gettext("fstat failed on %1$s: %2$s\n"), 13477c478bd9Sstevel@tonic-gate infile, strerror(errno)); 13487c478bd9Sstevel@tonic-gate goto out; 13497c478bd9Sstevel@tonic-gate } 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate if ((fout = fopen(outfile, "w")) == NULL) { 13527c478bd9Sstevel@tonic-gate logerr(gettext("failed to fopen %1$s: %2$s\n"), 13537c478bd9Sstevel@tonic-gate outfile, strerror(errno)); 13547c478bd9Sstevel@tonic-gate goto out; 13557c478bd9Sstevel@tonic-gate } 13567c478bd9Sstevel@tonic-gate 13577c478bd9Sstevel@tonic-gate if (fchmod(fileno(fout), (sbuf.st_mode & 0777)) != 0) { 13587c478bd9Sstevel@tonic-gate logerr(gettext("failed to fchmod %1$s to 0%2$o: %3$s\n"), 13597c478bd9Sstevel@tonic-gate outfile, sbuf.st_mode & 0777, strerror(errno)); 13607c478bd9Sstevel@tonic-gate goto out; 13617c478bd9Sstevel@tonic-gate } 13627c478bd9Sstevel@tonic-gate 13637c478bd9Sstevel@tonic-gate if (fchown(fileno(fout), sbuf.st_uid, sbuf.st_gid) != 0) { 13647c478bd9Sstevel@tonic-gate logerr(gettext("failed to fchown %1$s to uid %2$d and " 13657c478bd9Sstevel@tonic-gate "gid %3$d: %4$s\n"), 13667c478bd9Sstevel@tonic-gate outfile, sbuf.st_uid, sbuf.st_gid, strerror(errno)); 13677c478bd9Sstevel@tonic-gate goto out; 13687c478bd9Sstevel@tonic-gate } 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate *fp_in = fin; 13717c478bd9Sstevel@tonic-gate *fp_out = fout; 13727c478bd9Sstevel@tonic-gate return (0); 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate out: 13757c478bd9Sstevel@tonic-gate if (fin != NULL) 13767c478bd9Sstevel@tonic-gate (void) fclose(fin); 13777c478bd9Sstevel@tonic-gate if (fout != NULL) 13787c478bd9Sstevel@tonic-gate (void) fclose(fout); 13797c478bd9Sstevel@tonic-gate return (-1); 13807c478bd9Sstevel@tonic-gate } 13817c478bd9Sstevel@tonic-gate 13827c478bd9Sstevel@tonic-gate /* 13837c478bd9Sstevel@tonic-gate * If the devname is a phci based name and not open-able, map it to vhci 13847c478bd9Sstevel@tonic-gate * based name. If the devname is a vhci based name and not open-able, map it 13857c478bd9Sstevel@tonic-gate * to phci based name. 13867c478bd9Sstevel@tonic-gate * 13877c478bd9Sstevel@tonic-gate * devname either a /dev link or /devices name to client device 13887c478bd9Sstevel@tonic-gate * new_devname caller supplied buffer where the mapped device name is 13897c478bd9Sstevel@tonic-gate * placed on return. 13907c478bd9Sstevel@tonic-gate * len caller supplied new_devname buffer length 13917c478bd9Sstevel@tonic-gate * devlink_flag pass 1 if requesting the /dev link to the mapped device. 13927c478bd9Sstevel@tonic-gate * pass 0 if requesting the /devices name of the mapped device. 13937c478bd9Sstevel@tonic-gate * 13947c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 13957c478bd9Sstevel@tonic-gate */ 13967c478bd9Sstevel@tonic-gate static int 13977c478bd9Sstevel@tonic-gate map_devname(char *devname, char *new_devname, size_t len, int devlink_flag) 13987c478bd9Sstevel@tonic-gate { 13997c478bd9Sstevel@tonic-gate char physname[MAXPATHLEN]; 14007c478bd9Sstevel@tonic-gate char minor[MAXNAMELEN]; 14015a4c37c9Sqh201292 char new_physname[MAXPATHLEN]; 14027c478bd9Sstevel@tonic-gate 140360fffc19Sjw149990 logdmsg("map_devname: checking devname %s\n", devname); 140460fffc19Sjw149990 if ((get_physname_minor(devname, physname, sizeof (physname), 140560fffc19Sjw149990 minor, sizeof (minor)) == 0) && 140660fffc19Sjw149990 (canopen(devname) == 0) && 140760fffc19Sjw149990 (map_physname(physname, new_physname, 1408*8cecff49Sgp87344 sizeof (new_physname), minor) == 0)) { 140960fffc19Sjw149990 141060fffc19Sjw149990 logdmsg("map_devname: now looking up devlink\n"); 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate if (devlink_flag) { 14137c478bd9Sstevel@tonic-gate if (lookup_devlink(new_physname, minor, new_devname, 14147c478bd9Sstevel@tonic-gate len) == 0) 14157c478bd9Sstevel@tonic-gate return (0); 14167c478bd9Sstevel@tonic-gate } else { 14177c478bd9Sstevel@tonic-gate (void) snprintf(new_devname, len, "/devices%s:%s", 14187c478bd9Sstevel@tonic-gate new_physname, minor); 14197c478bd9Sstevel@tonic-gate return (0); 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate } 14227c478bd9Sstevel@tonic-gate 142360fffc19Sjw149990 logdmsg("map_devname: failed to find mapping for %s\n", devname); 14247c478bd9Sstevel@tonic-gate return (-1); 14257c478bd9Sstevel@tonic-gate } 14267c478bd9Sstevel@tonic-gate 14277c478bd9Sstevel@tonic-gate /* 14285a4c37c9Sqh201292 * If the devname is a vhci based name and open-able, map it to phci 14295a4c37c9Sqh201292 * based name. 14305a4c37c9Sqh201292 * 14315a4c37c9Sqh201292 * devname either a /dev link or /devices name to client device 14325a4c37c9Sqh201292 * new_devname caller supplied buffer where the mapped device name without 14335a4c37c9Sqh201292 * /devices prefix is placed on return. 14345a4c37c9Sqh201292 * len caller supplied new_devname buffer length 14355a4c37c9Sqh201292 */ 14365a4c37c9Sqh201292 static int 14375a4c37c9Sqh201292 map_openable_vhciname(char *devname, char *new_devname, size_t len) 14385a4c37c9Sqh201292 { 14395a4c37c9Sqh201292 char physname[MAXPATHLEN]; 14405a4c37c9Sqh201292 char minor[MAXNAMELEN]; 14415a4c37c9Sqh201292 char new_physname[MAXPATHLEN]; 14425a4c37c9Sqh201292 14435a4c37c9Sqh201292 if (get_physname_minor(devname, physname, sizeof (physname), 14445a4c37c9Sqh201292 minor, sizeof (minor)) == 0 && 14455a4c37c9Sqh201292 canopen(devname) == 1 && 14465a4c37c9Sqh201292 client_name_type(physname) == CLIENT_TYPE_VHCI && 14475a4c37c9Sqh201292 vhci_to_phci_by_ioctl(physname, new_physname, 14485a4c37c9Sqh201292 sizeof (new_physname)) == 0) { 14495a4c37c9Sqh201292 (void) snprintf(new_devname, len, "%s:%s", 14505a4c37c9Sqh201292 new_physname, minor); 14515a4c37c9Sqh201292 return (0); 14525a4c37c9Sqh201292 } 14535a4c37c9Sqh201292 14545a4c37c9Sqh201292 return (-1); 14555a4c37c9Sqh201292 } 14565a4c37c9Sqh201292 /* 14577c478bd9Sstevel@tonic-gate * Make a new /etc/vfstab: 14587c478bd9Sstevel@tonic-gate * Read vfstab_in, convert the device name entries to appropriate vhci or phci 14597c478bd9Sstevel@tonic-gate * based names, and write to vfstab_out. Only device names whose physical 14607c478bd9Sstevel@tonic-gate * paths are either phci or vhci based names and not open-able are considered 14617c478bd9Sstevel@tonic-gate * for conversion. Open-able device name entries are not converted as it 14627c478bd9Sstevel@tonic-gate * means that the device is already accessible; hence no need to convert. 14637c478bd9Sstevel@tonic-gate * 14647c478bd9Sstevel@tonic-gate * Returns: 14657c478bd9Sstevel@tonic-gate * 0 successful but vfstab_out contents are the same as vfstab_in 14667c478bd9Sstevel@tonic-gate * 1 successful and vfstab_out changed from vfstab_in 14677c478bd9Sstevel@tonic-gate * -1 failed 14687c478bd9Sstevel@tonic-gate */ 14697c478bd9Sstevel@tonic-gate static int 14707c478bd9Sstevel@tonic-gate update_vfstab(char *vfstab_in, char *vfstab_out) 14717c478bd9Sstevel@tonic-gate { 14727c478bd9Sstevel@tonic-gate FILE *fp_in, *fp_out; 14737c478bd9Sstevel@tonic-gate char *buf, *tmpbuf; 14747c478bd9Sstevel@tonic-gate char *vfs_cache[2]; 14757c478bd9Sstevel@tonic-gate int idx = 0, count = 0; 14767c478bd9Sstevel@tonic-gate int rv = -1; 14777c478bd9Sstevel@tonic-gate int vfstab_updated = 0; 14787c478bd9Sstevel@tonic-gate int i; 14797c478bd9Sstevel@tonic-gate char cdev[MAXPATHLEN]; 14807c478bd9Sstevel@tonic-gate char bdev[MAXPATHLEN]; 14817c478bd9Sstevel@tonic-gate char mntpt[MAXPATHLEN]; 14827c478bd9Sstevel@tonic-gate char fstype[512]; 14837c478bd9Sstevel@tonic-gate char fsckpass[512]; 14847c478bd9Sstevel@tonic-gate char mntboot[512]; 14857c478bd9Sstevel@tonic-gate char mntopt[MAX_MNTOPT_STR]; 14867c478bd9Sstevel@tonic-gate char phys_bdev[MAXPATHLEN], phys_cdev[MAXPATHLEN]; 14877c478bd9Sstevel@tonic-gate char bdev_minor[MAXNAMELEN], cdev_minor[MAXNAMELEN]; 14887c478bd9Sstevel@tonic-gate char new_physname[MAXPATHLEN]; 14897c478bd9Sstevel@tonic-gate char new_bdevlink[MAXPATHLEN], new_cdevlink[MAXPATHLEN]; 14907c478bd9Sstevel@tonic-gate char fmt[80]; 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate if (open_in_out_files(vfstab_in, vfstab_out, &fp_in, &fp_out) != 0) 14937c478bd9Sstevel@tonic-gate return (-1); 14947c478bd9Sstevel@tonic-gate 14957c478bd9Sstevel@tonic-gate /* 14967c478bd9Sstevel@tonic-gate * Read one line at time from vfstab_in. If no conversion is needed 14977c478bd9Sstevel@tonic-gate * for the line simply write the line to vfstab_out. If conversion is 14987c478bd9Sstevel@tonic-gate * needed, first write the existing line as a comment to vfstab_out 14997c478bd9Sstevel@tonic-gate * and then write the converted line. 15007c478bd9Sstevel@tonic-gate * 15017c478bd9Sstevel@tonic-gate * To avoid commented entries piling up in vfstab in case if the 15027c478bd9Sstevel@tonic-gate * user runs stmsboot multiple times to switch on and off from mpxio, 15037c478bd9Sstevel@tonic-gate * add the commented line only if not already there. To do this 15047c478bd9Sstevel@tonic-gate * cache the last two vfstab lines processed and add the commented 15057c478bd9Sstevel@tonic-gate * entry only if it is not found in the cache. We only need to cache 15067c478bd9Sstevel@tonic-gate * the last two lines because a device can have at most two names - 15077c478bd9Sstevel@tonic-gate * one mpxio and one non-mpxio name. Therefore for any device name 15087c478bd9Sstevel@tonic-gate * entry we at most add two comments - one with mpxio name and one 15097c478bd9Sstevel@tonic-gate * with non-mpxio name - no matter how many times stmsboot is run. 15107c478bd9Sstevel@tonic-gate */ 15117c478bd9Sstevel@tonic-gate buf = (char *)s_malloc(VFS_LINE_MAX); 15127c478bd9Sstevel@tonic-gate tmpbuf = (char *)s_malloc(VFS_LINE_MAX); 15137c478bd9Sstevel@tonic-gate vfs_cache[0] = (char *)s_malloc(VFS_LINE_MAX); 15147c478bd9Sstevel@tonic-gate vfs_cache[1] = (char *)s_malloc(VFS_LINE_MAX); 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate (void) snprintf(fmt, sizeof (fmt), 15177c478bd9Sstevel@tonic-gate "%%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds", sizeof (bdev) - 1, 15187c478bd9Sstevel@tonic-gate sizeof (cdev) - 1, sizeof (mntpt) - 1, sizeof (fstype) - 1, 15197c478bd9Sstevel@tonic-gate sizeof (fsckpass) - 1, sizeof (mntboot) - 1, sizeof (mntopt) - 1); 15207c478bd9Sstevel@tonic-gate 15217c478bd9Sstevel@tonic-gate while (fgets(buf, VFS_LINE_MAX, fp_in) != NULL) { 15227c478bd9Sstevel@tonic-gate if (strlen(buf) == (VFS_LINE_MAX - 1) && 15237c478bd9Sstevel@tonic-gate buf[VFS_LINE_MAX-2] != '\n') { 15247c478bd9Sstevel@tonic-gate logerr(gettext("%1$s line size too long, " 15257c478bd9Sstevel@tonic-gate "exceeded %2$d: \"%3$s\"\n"), 15267c478bd9Sstevel@tonic-gate VFSTAB, VFS_LINE_MAX - 2, buf); 15277c478bd9Sstevel@tonic-gate goto out; 15287c478bd9Sstevel@tonic-gate } 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate /* LINTED - format specifier */ 15317c478bd9Sstevel@tonic-gate if ((sscanf(buf, fmt, bdev, cdev, mntpt, 15327c478bd9Sstevel@tonic-gate fstype, fsckpass, mntboot, mntopt) != 7) || 15337c478bd9Sstevel@tonic-gate (bdev[0] == '#') || 15347c478bd9Sstevel@tonic-gate (get_physname_minor(bdev, phys_bdev, sizeof (phys_bdev), 15357c478bd9Sstevel@tonic-gate bdev_minor, sizeof (bdev_minor)) != 0) || 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate (strcmp(fstype, "swap") != 0 && 15387c478bd9Sstevel@tonic-gate ((get_physname_minor(cdev, phys_cdev, sizeof (phys_cdev), 15397c478bd9Sstevel@tonic-gate cdev_minor, sizeof (cdev_minor)) != 0) || 15407c478bd9Sstevel@tonic-gate (strcmp(phys_bdev, phys_cdev) != 0))) || 15417c478bd9Sstevel@tonic-gate 15427c478bd9Sstevel@tonic-gate canopen(bdev) || 15437c478bd9Sstevel@tonic-gate (map_physname(phys_bdev, new_physname, 1544*8cecff49Sgp87344 sizeof (new_physname), bdev_minor) != 0) || 15457c478bd9Sstevel@tonic-gate (lookup_devlink(new_physname, bdev_minor, new_bdevlink, 15467c478bd9Sstevel@tonic-gate sizeof (new_bdevlink)) != 0) || 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate (strcmp(fstype, "swap") != 0 && 15497c478bd9Sstevel@tonic-gate (lookup_devlink(new_physname, cdev_minor, new_cdevlink, 15507c478bd9Sstevel@tonic-gate sizeof (new_cdevlink)) != 0))) { 15517c478bd9Sstevel@tonic-gate 15527c478bd9Sstevel@tonic-gate /* cache the last two entries */ 15537c478bd9Sstevel@tonic-gate (void) strlcpy(vfs_cache[idx], buf, VFS_LINE_MAX); 15547c478bd9Sstevel@tonic-gate idx = (idx == 0) ? 1 : 0; 15557c478bd9Sstevel@tonic-gate if (count < 2) 15567c478bd9Sstevel@tonic-gate count++; 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate if (fputs(buf, fp_out) == EOF) { 15597c478bd9Sstevel@tonic-gate logerr(gettext("fputs \"%1$s\" to %2$s " 15607c478bd9Sstevel@tonic-gate "failed: %3$s\n"), 15617c478bd9Sstevel@tonic-gate buf, vfstab_out, strerror(errno)); 15627c478bd9Sstevel@tonic-gate goto out; 15637c478bd9Sstevel@tonic-gate } 15647c478bd9Sstevel@tonic-gate 15657c478bd9Sstevel@tonic-gate } else { 15667c478bd9Sstevel@tonic-gate /* 15677c478bd9Sstevel@tonic-gate * comment the entry in vfstab only if it is not 15687c478bd9Sstevel@tonic-gate * already in the cache. 15697c478bd9Sstevel@tonic-gate */ 15707c478bd9Sstevel@tonic-gate if (client_name_type(phys_bdev) == CLIENT_TYPE_VHCI) 15717c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, VFS_LINE_MAX, 15727c478bd9Sstevel@tonic-gate "# mpxio: %s", buf); 15737c478bd9Sstevel@tonic-gate else 15747c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, VFS_LINE_MAX, 15757c478bd9Sstevel@tonic-gate "# non-mpxio: %s", buf); 15767c478bd9Sstevel@tonic-gate 15777c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 15787c478bd9Sstevel@tonic-gate if (strcmp(vfs_cache[i], tmpbuf) == 0) 15797c478bd9Sstevel@tonic-gate break; 15807c478bd9Sstevel@tonic-gate } 15817c478bd9Sstevel@tonic-gate 15827c478bd9Sstevel@tonic-gate if (i == count) { 15837c478bd9Sstevel@tonic-gate if (fputs(tmpbuf, fp_out) == EOF) { 15847c478bd9Sstevel@tonic-gate logerr(gettext("fputs \"%1$s\" to %2$s " 15857c478bd9Sstevel@tonic-gate "failed: %3$s\n"), tmpbuf, 15867c478bd9Sstevel@tonic-gate vfstab_out, strerror(errno)); 15877c478bd9Sstevel@tonic-gate goto out; 15887c478bd9Sstevel@tonic-gate } 15897c478bd9Sstevel@tonic-gate } 15907c478bd9Sstevel@tonic-gate 15917c478bd9Sstevel@tonic-gate count = 0; 15927c478bd9Sstevel@tonic-gate idx = 0; 15937c478bd9Sstevel@tonic-gate 15947c478bd9Sstevel@tonic-gate if (fprintf(fp_out, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", 15957c478bd9Sstevel@tonic-gate new_bdevlink, 15967c478bd9Sstevel@tonic-gate (strcmp(fstype, "swap") != 0) ? new_cdevlink : cdev, 15977c478bd9Sstevel@tonic-gate mntpt, fstype, fsckpass, mntboot, mntopt) < 0) { 15987c478bd9Sstevel@tonic-gate logerr(gettext("fprintf failed to write to " 15997c478bd9Sstevel@tonic-gate "%1$s: %2$s\n"), 16007c478bd9Sstevel@tonic-gate vfstab_out, strerror(errno)); 16017c478bd9Sstevel@tonic-gate goto out; 16027c478bd9Sstevel@tonic-gate } 16037c478bd9Sstevel@tonic-gate vfstab_updated = 1; 16047c478bd9Sstevel@tonic-gate } 16057c478bd9Sstevel@tonic-gate } 16067c478bd9Sstevel@tonic-gate 16077c478bd9Sstevel@tonic-gate rv = vfstab_updated; 16087c478bd9Sstevel@tonic-gate out: 16097c478bd9Sstevel@tonic-gate (void) fclose(fp_in); 16107c478bd9Sstevel@tonic-gate (void) fclose(fp_out); 16117c478bd9Sstevel@tonic-gate free(buf); 16127c478bd9Sstevel@tonic-gate free(tmpbuf); 16137c478bd9Sstevel@tonic-gate free(vfs_cache[0]); 16147c478bd9Sstevel@tonic-gate free(vfs_cache[1]); 16157c478bd9Sstevel@tonic-gate return (rv); 16167c478bd9Sstevel@tonic-gate } 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate /* 16197c478bd9Sstevel@tonic-gate * if guidmap is 0, list non-STMS to STMS device name mappings for the 16207c478bd9Sstevel@tonic-gate * specified controller. 16217c478bd9Sstevel@tonic-gate * if guidmap is 1, list non-STMS to GUID mappings for the specified controller. 16227c478bd9Sstevel@tonic-gate * If controller is -1 list mappings for all controllers. 16237c478bd9Sstevel@tonic-gate * 16247c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 16257c478bd9Sstevel@tonic-gate */ 16267c478bd9Sstevel@tonic-gate static int 16277c478bd9Sstevel@tonic-gate list_mappings(int controller, int guidmap) 16287c478bd9Sstevel@tonic-gate { 16297c478bd9Sstevel@tonic-gate int cnum, len, mapped; 16307c478bd9Sstevel@tonic-gate int header = 1; 16317c478bd9Sstevel@tonic-gate char *p1, *p2; 16327c478bd9Sstevel@tonic-gate DIR *dirp; 16337c478bd9Sstevel@tonic-gate struct dirent *direntry; 16347c478bd9Sstevel@tonic-gate char devname[MAXPATHLEN]; 16357c478bd9Sstevel@tonic-gate char physname[MAXPATHLEN]; 16367c478bd9Sstevel@tonic-gate char new_devname[MAXPATHLEN]; 16377c478bd9Sstevel@tonic-gate char new_physname[MAXPATHLEN]; 16387c478bd9Sstevel@tonic-gate char guid[MAXPATHLEN]; 16397c478bd9Sstevel@tonic-gate char minor[MAXNAMELEN]; 16407c478bd9Sstevel@tonic-gate 16417c478bd9Sstevel@tonic-gate if ((dirp = opendir("/dev/rdsk")) == NULL) 16427c478bd9Sstevel@tonic-gate return (-1); 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate while ((direntry = readdir(dirp)) != NULL) { 16457c478bd9Sstevel@tonic-gate if (strcmp(direntry->d_name, ".") == 0 || 16467c478bd9Sstevel@tonic-gate strcmp(direntry->d_name, "..") == 0 || 16477c478bd9Sstevel@tonic-gate (len = strlen(direntry->d_name)) < 2 || 16487c478bd9Sstevel@tonic-gate strcmp(direntry->d_name + len - 2, "s0") != 0 || 16497c478bd9Sstevel@tonic-gate sscanf(direntry->d_name, "c%dt", &cnum) != 1 || 16507c478bd9Sstevel@tonic-gate (controller != -1 && controller != cnum)) 16517c478bd9Sstevel@tonic-gate continue; 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate (void) snprintf(devname, MAXPATHLEN, "/dev/rdsk/%s", 16547c478bd9Sstevel@tonic-gate direntry->d_name); 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate if (get_physname_minor(devname, physname, sizeof (physname), 16577c478bd9Sstevel@tonic-gate minor, sizeof (minor)) != 0 || 165860fffc19Sjw149990 client_name_type(physname) != CLIENT_TYPE_PHCI) { 165960fffc19Sjw149990 logdmsg("list_mappings: continuing\n"); 16607c478bd9Sstevel@tonic-gate continue; 166160fffc19Sjw149990 } 16627c478bd9Sstevel@tonic-gate 16637c478bd9Sstevel@tonic-gate /* 16647c478bd9Sstevel@tonic-gate * First try phci_to_vhci() mapping. It will work if the 16657c478bd9Sstevel@tonic-gate * device is under MPxIO control. If the device is not under 16667c478bd9Sstevel@tonic-gate * MPxIO, phci_to_vhci() will fail in which case try to lookup 16677c478bd9Sstevel@tonic-gate * if an old mapping exists using guid lookup. 16687c478bd9Sstevel@tonic-gate */ 16697c478bd9Sstevel@tonic-gate mapped = 1; 16707c478bd9Sstevel@tonic-gate if (phci_to_vhci(physname, new_physname, 16717c478bd9Sstevel@tonic-gate sizeof (new_physname)) != 0) { 16727c478bd9Sstevel@tonic-gate if (get_guid(physname, guid, sizeof (guid), 1, 16737c478bd9Sstevel@tonic-gate DI_NODE_NIL) == 0) 16747c478bd9Sstevel@tonic-gate (void) snprintf(new_physname, MAXPATHLEN, 16755a4c37c9Sqh201292 "/scsi_vhci/%s%s", DISK_AT_G, guid); 16767c478bd9Sstevel@tonic-gate else 16777c478bd9Sstevel@tonic-gate mapped = 0; 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate if (mapped == 0) 16817c478bd9Sstevel@tonic-gate continue; 16827c478bd9Sstevel@tonic-gate 16837c478bd9Sstevel@tonic-gate /* strip the slice number part */ 16847c478bd9Sstevel@tonic-gate devname[strlen(devname) - 2] = '\0'; 16857c478bd9Sstevel@tonic-gate 16867c478bd9Sstevel@tonic-gate if (guidmap == 0) { 16877c478bd9Sstevel@tonic-gate if (lookup_devlink(new_physname, minor, 16887c478bd9Sstevel@tonic-gate new_devname, sizeof (new_devname)) != 0) 16897c478bd9Sstevel@tonic-gate continue; 16907c478bd9Sstevel@tonic-gate 16917c478bd9Sstevel@tonic-gate /* strip the slice number part */ 16927c478bd9Sstevel@tonic-gate new_devname[strlen(new_devname) - 2] = '\0'; 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate if (header) { 16957c478bd9Sstevel@tonic-gate (void) printf( 16967c478bd9Sstevel@tonic-gate gettext("non-STMS device name\t\t\t" 16977c478bd9Sstevel@tonic-gate "STMS device name\n" 16987c478bd9Sstevel@tonic-gate "------------------------------------------" 16997c478bd9Sstevel@tonic-gate "------------------------\n")); 17007c478bd9Sstevel@tonic-gate header = 0; 17017c478bd9Sstevel@tonic-gate } 17027c478bd9Sstevel@tonic-gate (void) printf("%s\t\t%s\n", devname, new_devname); 17037c478bd9Sstevel@tonic-gate } else { 17047c478bd9Sstevel@tonic-gate /* extract guid part */ 170560fffc19Sjw149990 /* we should be using a getguid() call instead */ 170660fffc19Sjw149990 if ((p1 = strstr(new_physname, "@")) 170760fffc19Sjw149990 == NULL) { 17087c478bd9Sstevel@tonic-gate logdmsg("invalid vhci: %s\n", new_physname); 17097c478bd9Sstevel@tonic-gate continue; 17107c478bd9Sstevel@tonic-gate } 171160fffc19Sjw149990 171260fffc19Sjw149990 logdmsg("\tp1 = %s\n", p1); 171360fffc19Sjw149990 171460fffc19Sjw149990 p1 += 2; /* "@" + [nwg] */ 17157c478bd9Sstevel@tonic-gate if ((p2 = strrchr(p1, ':')) != NULL) 17167c478bd9Sstevel@tonic-gate *p2 = '\0'; 17177c478bd9Sstevel@tonic-gate 17187c478bd9Sstevel@tonic-gate if (header) { 17197c478bd9Sstevel@tonic-gate (void) printf( 17207c478bd9Sstevel@tonic-gate gettext("non-STMS device name\t\t\tGUID\n" 17217c478bd9Sstevel@tonic-gate "------------------------------------------" 17227c478bd9Sstevel@tonic-gate "------------------------\n")); 17237c478bd9Sstevel@tonic-gate header = 0; 17247c478bd9Sstevel@tonic-gate } 17257c478bd9Sstevel@tonic-gate (void) printf("%s\t\t%s\n", devname, p1); 17267c478bd9Sstevel@tonic-gate } 17277c478bd9Sstevel@tonic-gate } 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate (void) closedir(dirp); 17307c478bd9Sstevel@tonic-gate return (0); 17317c478bd9Sstevel@tonic-gate } 17327c478bd9Sstevel@tonic-gate 17337c478bd9Sstevel@tonic-gate /* 17347c478bd9Sstevel@tonic-gate * Check if the file can be opened. 17357c478bd9Sstevel@tonic-gate * 17367c478bd9Sstevel@tonic-gate * Return 1 if the file can be opened, 0 otherwise. 17377c478bd9Sstevel@tonic-gate */ 17387c478bd9Sstevel@tonic-gate static int 17397c478bd9Sstevel@tonic-gate canopen(char *filename) 17407c478bd9Sstevel@tonic-gate { 17417c478bd9Sstevel@tonic-gate int fd; 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate if ((fd = open(filename, O_RDONLY)) == -1) 17447c478bd9Sstevel@tonic-gate return (0); 17457c478bd9Sstevel@tonic-gate 174660fffc19Sjw149990 logdmsg("canopen: was able to open %s\n", filename); 17477c478bd9Sstevel@tonic-gate (void) close(fd); 17487c478bd9Sstevel@tonic-gate return (1); 17497c478bd9Sstevel@tonic-gate } 17507c478bd9Sstevel@tonic-gate 175160fffc19Sjw149990 175260fffc19Sjw149990 /* 175360fffc19Sjw149990 * This function traverses the device tree looking for nodes 175460fffc19Sjw149990 * which have "drivername" as a property. We return a list of 1755815dd917Sjmcp * these nodes, without duplicate entries. 175660fffc19Sjw149990 * Since there can be many different pci/pcie devices that all 175760fffc19Sjw149990 * share the same driver but which have different pci vid/did 175860fffc19Sjw149990 * combinations, we have to be smart about returning only those 175960fffc19Sjw149990 * pci vid/dids which have the "sas-*" property unless the 176060fffc19Sjw149990 * drivername is "fp", in which case we're searching for "node-wwn" 176160fffc19Sjw149990 */ 176260fffc19Sjw149990 static void 176360fffc19Sjw149990 list_nodes(char *drivername) 176460fffc19Sjw149990 { 176560fffc19Sjw149990 di_node_t devroot = DI_NODE_NIL; 176660fffc19Sjw149990 di_node_t thisnode = DI_NODE_NIL; 1767815dd917Sjmcp char *aliaslist; 1768815dd917Sjmcp char *iitype = NULL; /* the "initiator-interconnect-type" property */ 176960fffc19Sjw149990 int *intprop = NULL; 177060fffc19Sjw149990 int i = 1; /* fencepost */ 1771815dd917Sjmcp int irval = 0; 1772815dd917Sjmcp int crval = 0; 177360fffc19Sjw149990 177460fffc19Sjw149990 /* 177560fffc19Sjw149990 * Since the "fp" driver enumerates with its own name, 177660fffc19Sjw149990 * we can special-case its handling. 177760fffc19Sjw149990 */ 177860fffc19Sjw149990 if (strcmp(drvname, "fp") == 0) { 177960fffc19Sjw149990 (void) fprintf(stdout, "fp\n"); 178060fffc19Sjw149990 } else { 178160fffc19Sjw149990 178260fffc19Sjw149990 if ((devroot = di_init("/", DINFOCPYALL | DINFOFORCE)) 178360fffc19Sjw149990 == DI_NODE_NIL) { 178460fffc19Sjw149990 logerr(gettext("list_nodes: di_init failed: " 178560fffc19Sjw149990 "%s\n"), strerror(errno)); 178660fffc19Sjw149990 } 178760fffc19Sjw149990 178860fffc19Sjw149990 if ((thisnode = di_drv_first_node(drivername, devroot)) 178960fffc19Sjw149990 != NULL) { 179060fffc19Sjw149990 logdmsg("list_nodes: searching for property " 179160fffc19Sjw149990 "%s\n", drvprop); 179260fffc19Sjw149990 179360fffc19Sjw149990 aliaslist = s_malloc(1024 * sizeof (char)); 179460fffc19Sjw149990 bzero(aliaslist, 1024); 179560fffc19Sjw149990 while (thisnode != DI_NODE_NIL) { 179660fffc19Sjw149990 logdmsg("devfs-name %s driver-name %s " 179760fffc19Sjw149990 "node-name %s\n", 179860fffc19Sjw149990 di_devfs_path(thisnode), 179960fffc19Sjw149990 di_driver_name(thisnode), 180060fffc19Sjw149990 di_node_name(thisnode)); 180160fffc19Sjw149990 180260fffc19Sjw149990 /* We check the child node for drvprop */ 1803815dd917Sjmcp irval = di_prop_lookup_ints(DDI_DEV_T_ANY, 1804815dd917Sjmcp di_child_node(thisnode), drvprop, &intprop); 1805815dd917Sjmcp /* and this node for the correct initiator type */ 1806815dd917Sjmcp crval = di_prop_lookup_strings(DDI_DEV_T_ANY, 1807815dd917Sjmcp thisnode, "initiator-interconnect-type", &iitype); 1808815dd917Sjmcp 1809815dd917Sjmcp /* 1810815dd917Sjmcp * examine the return codes from di_prop_lookup*() 1811815dd917Sjmcp * functions to guard against library errors 1812815dd917Sjmcp */ 1813815dd917Sjmcp if ((irval > -1) || ((crval > -1) && 1814815dd917Sjmcp (strncmp(iitype, "SATA", 4) == 0))) { 181560fffc19Sjw149990 181660fffc19Sjw149990 if (strstr(aliaslist, 1817815dd917Sjmcp di_node_name(thisnode)) == (char *)NULL) { 181860fffc19Sjw149990 char *nname; 181960fffc19Sjw149990 182060fffc19Sjw149990 nname = di_node_name(thisnode); 182160fffc19Sjw149990 182260fffc19Sjw149990 if (i) { 182360fffc19Sjw149990 (void) snprintf(aliaslist, 1824815dd917Sjmcp strlen(nname) + 1, "%s", nname); 182560fffc19Sjw149990 --i; 182660fffc19Sjw149990 } else { 182760fffc19Sjw149990 if (strstr(aliaslist, 182860fffc19Sjw149990 di_node_name(thisnode)) == 182960fffc19Sjw149990 (char *)NULL) { 1830815dd917Sjmcp /* add 2 for the n-1 + "|" */ 183160fffc19Sjw149990 (void) snprintf(aliaslist, 1832815dd917Sjmcp strlen(nname) + 2 + 183360fffc19Sjw149990 strlen(aliaslist), 183460fffc19Sjw149990 "%s|%s", aliaslist, 183560fffc19Sjw149990 nname); 183660fffc19Sjw149990 } 183760fffc19Sjw149990 } 183860fffc19Sjw149990 } 183960fffc19Sjw149990 } else { 184060fffc19Sjw149990 logdmsg("unable to lookup property %s " 184160fffc19Sjw149990 "for node %s. Error %d: %s\n", 184260fffc19Sjw149990 drvprop, di_devfs_path(thisnode), 184360fffc19Sjw149990 errno, strerror(errno)); 184460fffc19Sjw149990 } 184560fffc19Sjw149990 thisnode = di_drv_next_node(thisnode); 184660fffc19Sjw149990 } 184760fffc19Sjw149990 (void) fprintf(stdout, "%s\n", aliaslist); 184860fffc19Sjw149990 } 184960fffc19Sjw149990 185060fffc19Sjw149990 di_fini(devroot); 185160fffc19Sjw149990 } 185260fffc19Sjw149990 } 185360fffc19Sjw149990 18547c478bd9Sstevel@tonic-gate static void 18557c478bd9Sstevel@tonic-gate logerr(char *msg, ...) 18567c478bd9Sstevel@tonic-gate { 18577c478bd9Sstevel@tonic-gate va_list ap; 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", stmsboot); 18607c478bd9Sstevel@tonic-gate va_start(ap, msg); 18617c478bd9Sstevel@tonic-gate /* LINTED - format specifier */ 18627c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, msg, ap); 18637c478bd9Sstevel@tonic-gate va_end(ap); 18647c478bd9Sstevel@tonic-gate } 18657c478bd9Sstevel@tonic-gate 18667c478bd9Sstevel@tonic-gate /* log debug message */ 18677c478bd9Sstevel@tonic-gate static void 18687c478bd9Sstevel@tonic-gate logdmsg(char *msg, ...) 18697c478bd9Sstevel@tonic-gate { 18707c478bd9Sstevel@tonic-gate va_list ap; 18717c478bd9Sstevel@tonic-gate 18727c478bd9Sstevel@tonic-gate if (debug) { 18737c478bd9Sstevel@tonic-gate va_start(ap, msg); 18747c478bd9Sstevel@tonic-gate /* LINTED - format specifier */ 18757c478bd9Sstevel@tonic-gate (void) vprintf(msg, ap); 18767c478bd9Sstevel@tonic-gate va_end(ap); 18777c478bd9Sstevel@tonic-gate } 18787c478bd9Sstevel@tonic-gate } 18797c478bd9Sstevel@tonic-gate 18807c478bd9Sstevel@tonic-gate static void * 18817c478bd9Sstevel@tonic-gate s_malloc(const size_t size) 18827c478bd9Sstevel@tonic-gate { 18837c478bd9Sstevel@tonic-gate void *rp; 18847c478bd9Sstevel@tonic-gate 18857c478bd9Sstevel@tonic-gate if ((rp = malloc(size)) == NULL) { 18867c478bd9Sstevel@tonic-gate logerr(gettext("malloc failed to allocate %d bytes\n"), size); 18877c478bd9Sstevel@tonic-gate clean_exit(1); 18887c478bd9Sstevel@tonic-gate } 18897c478bd9Sstevel@tonic-gate return (rp); 18907c478bd9Sstevel@tonic-gate } 18917c478bd9Sstevel@tonic-gate 18927c478bd9Sstevel@tonic-gate static char * 18937c478bd9Sstevel@tonic-gate s_strdup(const char *ptr) 18947c478bd9Sstevel@tonic-gate { 18957c478bd9Sstevel@tonic-gate void *rp; 18967c478bd9Sstevel@tonic-gate 18977c478bd9Sstevel@tonic-gate if ((rp = strdup(ptr)) == NULL) { 18987c478bd9Sstevel@tonic-gate logerr(gettext("strdup failed to dup %s\n"), ptr); 18997c478bd9Sstevel@tonic-gate clean_exit(1); 19007c478bd9Sstevel@tonic-gate } 19017c478bd9Sstevel@tonic-gate return (rp); 19027c478bd9Sstevel@tonic-gate } 19037c478bd9Sstevel@tonic-gate 19047c478bd9Sstevel@tonic-gate static void 19057c478bd9Sstevel@tonic-gate s_strlcpy(char *dst, const char *src, size_t dstsize) 19067c478bd9Sstevel@tonic-gate { 19077c478bd9Sstevel@tonic-gate int n; 19087c478bd9Sstevel@tonic-gate 19097c478bd9Sstevel@tonic-gate if ((n = strlcpy(dst, src, dstsize)) >= dstsize) { 19107c478bd9Sstevel@tonic-gate logerr(gettext("strlcpy: destination buffer size is %1$d " 19117c478bd9Sstevel@tonic-gate "bytes, need to at least %2$d bytes\n"), dstsize, n + 1); 19127c478bd9Sstevel@tonic-gate clean_exit(1); 19137c478bd9Sstevel@tonic-gate } 19147c478bd9Sstevel@tonic-gate } 19157c478bd9Sstevel@tonic-gate 19167c478bd9Sstevel@tonic-gate static void 19177c478bd9Sstevel@tonic-gate clean_exit(int status) 19187c478bd9Sstevel@tonic-gate { 19197c478bd9Sstevel@tonic-gate if (devinfo_root != DI_NODE_NIL) 19207c478bd9Sstevel@tonic-gate di_fini(devinfo_root); 19217c478bd9Sstevel@tonic-gate 19227c478bd9Sstevel@tonic-gate if (devlink_hdl != NULL) 19237c478bd9Sstevel@tonic-gate (void) di_devlink_fini(&devlink_hdl); 19247c478bd9Sstevel@tonic-gate 19257c478bd9Sstevel@tonic-gate if (vhci_fd != -1) 19267c478bd9Sstevel@tonic-gate (void) close(vhci_fd); 19277c478bd9Sstevel@tonic-gate 19287c478bd9Sstevel@tonic-gate exit(status); 19297c478bd9Sstevel@tonic-gate } 1930*8cecff49Sgp87344 1931*8cecff49Sgp87344 /* 1932*8cecff49Sgp87344 * Attempt to read some data from the specified slice from the device. 1933*8cecff49Sgp87344 */ 1934*8cecff49Sgp87344 static int 1935*8cecff49Sgp87344 canread(char *physname, char *minor) 1936*8cecff49Sgp87344 { 1937*8cecff49Sgp87344 char devname[MAXPATHLEN]; 1938*8cecff49Sgp87344 int fd, rv = 0; 1939*8cecff49Sgp87344 char tbuf[512]; 1940*8cecff49Sgp87344 1941*8cecff49Sgp87344 (void) snprintf(devname, MAXPATHLEN, "/devices%s:%s", physname, minor); 1942*8cecff49Sgp87344 if ((fd = open(devname, O_RDONLY)) == -1) { 1943*8cecff49Sgp87344 logdmsg("canread: failed to open %s: %s\n", devname, 1944*8cecff49Sgp87344 strerror(errno)); 1945*8cecff49Sgp87344 return (rv); 1946*8cecff49Sgp87344 } 1947*8cecff49Sgp87344 1948*8cecff49Sgp87344 if (read(fd, tbuf, sizeof (tbuf)) < 0) 1949*8cecff49Sgp87344 logdmsg("canread: failed to read %s: %s\n", devname, 1950*8cecff49Sgp87344 strerror(errno)); 1951*8cecff49Sgp87344 else 1952*8cecff49Sgp87344 rv = 1; 1953*8cecff49Sgp87344 1954*8cecff49Sgp87344 (void) close(fd); 1955*8cecff49Sgp87344 return (rv); 1956*8cecff49Sgp87344 } 1957