1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 34*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 35*7c478bd9Sstevel@tonic-gate #include <errno.h> 36*7c478bd9Sstevel@tonic-gate #include <unistd.h> 37*7c478bd9Sstevel@tonic-gate #include <stropts.h> 38*7c478bd9Sstevel@tonic-gate #include <strings.h> 39*7c478bd9Sstevel@tonic-gate #include <dirent.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/scsi/adapters/scsi_vhci.h> 42*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 43*7c478bd9Sstevel@tonic-gate #include <libgen.h> 44*7c478bd9Sstevel@tonic-gate #include <dlfcn.h> 45*7c478bd9Sstevel@tonic-gate #include <link.h> 46*7c478bd9Sstevel@tonic-gate #include <locale.h> 47*7c478bd9Sstevel@tonic-gate #include <libintl.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/syscall.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/vfstab.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/mount.h> 51*7c478bd9Sstevel@tonic-gate #include <devid.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/libdevid.h> 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #define VHCI_CTL_NODE "/devices/scsi_vhci:devctl" 55*7c478bd9Sstevel@tonic-gate #define SLASH_DEVICES "/devices/" 56*7c478bd9Sstevel@tonic-gate #define SLASH_SSD_AT "/ssd@" 57*7c478bd9Sstevel@tonic-gate #define SLASH_FP_AT "/fp@" 58*7c478bd9Sstevel@tonic-gate #define SLASH_SCSI_VHCI "/scsi_vhci" 59*7c478bd9Sstevel@tonic-gate #define DEV_DSK "/dev/dsk/" 60*7c478bd9Sstevel@tonic-gate #define DEV_RDSK "/dev/rdsk/" 61*7c478bd9Sstevel@tonic-gate #define SYS_FILENAME_LEN 256 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate /* 64*7c478bd9Sstevel@tonic-gate * Save directory is the directory in which system files are saved. 65*7c478bd9Sstevel@tonic-gate * Save directory must be under the root filesystem, as this program is 66*7c478bd9Sstevel@tonic-gate * typically run before any other filesystems are mounted. 67*7c478bd9Sstevel@tonic-gate */ 68*7c478bd9Sstevel@tonic-gate #define SAVE_DIR "/etc/mpxio" 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate /* fcp driver publishes this property */ 71*7c478bd9Sstevel@tonic-gate #define NODE_WWN_PROP "node-wwn" 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate typedef enum { 74*7c478bd9Sstevel@tonic-gate CLIENT_TYPE_UNKNOWN, 75*7c478bd9Sstevel@tonic-gate CLIENT_TYPE_PHCI, 76*7c478bd9Sstevel@tonic-gate CLIENT_TYPE_VHCI 77*7c478bd9Sstevel@tonic-gate } client_type_t; 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate struct devlink_cbarg { 80*7c478bd9Sstevel@tonic-gate char *devlink; 81*7c478bd9Sstevel@tonic-gate size_t len; 82*7c478bd9Sstevel@tonic-gate }; 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate static di_node_t devinfo_root = DI_NODE_NIL; 85*7c478bd9Sstevel@tonic-gate static di_devlink_handle_t devlink_hdl = NULL; 86*7c478bd9Sstevel@tonic-gate static int vhci_fd = -1; 87*7c478bd9Sstevel@tonic-gate static int patch_vfstab, cap_m_option, debug; 88*7c478bd9Sstevel@tonic-gate static int list_option, list_guid_mappings, list_controllernum = -1; 89*7c478bd9Sstevel@tonic-gate static char *mapdev = ""; 90*7c478bd9Sstevel@tonic-gate static char *stmsboot = "stmsboot"; 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate static int make_temp(char *, char *, char *, size_t); 93*7c478bd9Sstevel@tonic-gate static void commit_change(char *, char *, char *, int); 94*7c478bd9Sstevel@tonic-gate static int map_devname(char *, char *, size_t, int); 95*7c478bd9Sstevel@tonic-gate static int update_vfstab(char *, char *); 96*7c478bd9Sstevel@tonic-gate static int list_mappings(int, int); 97*7c478bd9Sstevel@tonic-gate static int canopen(char *); 98*7c478bd9Sstevel@tonic-gate static void logerr(char *, ...); 99*7c478bd9Sstevel@tonic-gate static void logdmsg(char *, ...); 100*7c478bd9Sstevel@tonic-gate static void *s_malloc(const size_t); 101*7c478bd9Sstevel@tonic-gate static char *s_strdup(const char *); 102*7c478bd9Sstevel@tonic-gate static void s_strlcpy(char *, const char *, size_t); 103*7c478bd9Sstevel@tonic-gate static void clean_exit(int); 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate /* 106*7c478bd9Sstevel@tonic-gate * Print usage and exit. 107*7c478bd9Sstevel@tonic-gate */ 108*7c478bd9Sstevel@tonic-gate static void 109*7c478bd9Sstevel@tonic-gate usage(char *argv0) 110*7c478bd9Sstevel@tonic-gate { 111*7c478bd9Sstevel@tonic-gate char *progname; 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate progname = strrchr(argv0, '/'); 114*7c478bd9Sstevel@tonic-gate if (progname != NULL) 115*7c478bd9Sstevel@tonic-gate progname++; 116*7c478bd9Sstevel@tonic-gate else 117*7c478bd9Sstevel@tonic-gate progname = argv0; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate /* 120*7c478bd9Sstevel@tonic-gate * -u update /etc/vfstab 121*7c478bd9Sstevel@tonic-gate * -m devname 122*7c478bd9Sstevel@tonic-gate * if devname is phci based name and not open-able, map it to 123*7c478bd9Sstevel@tonic-gate * vhci based /devices name. 124*7c478bd9Sstevel@tonic-gate * if devname is vhci based name and not open-able, map it to 125*7c478bd9Sstevel@tonic-gate * phci based /devices name. 126*7c478bd9Sstevel@tonic-gate * -M devname 127*7c478bd9Sstevel@tonic-gate * same as -m except that /dev link is printed instead of 128*7c478bd9Sstevel@tonic-gate * /devices name. 129*7c478bd9Sstevel@tonic-gate * -l controller 130*7c478bd9Sstevel@tonic-gate * list non-STMS to STMS device name mappings for the specific 131*7c478bd9Sstevel@tonic-gate * controller 132*7c478bd9Sstevel@tonic-gate * -L list non-STMS to STMS device name mappings for all controllers 133*7c478bd9Sstevel@tonic-gate */ 134*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("usage: %s -u | -m devname | " 135*7c478bd9Sstevel@tonic-gate "-M devname | -l controller | -L\n"), progname); 136*7c478bd9Sstevel@tonic-gate exit(2); 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate /* 140*7c478bd9Sstevel@tonic-gate * Parse command line arguments. 141*7c478bd9Sstevel@tonic-gate */ 142*7c478bd9Sstevel@tonic-gate static void 143*7c478bd9Sstevel@tonic-gate parse_args(int argc, char *argv[]) 144*7c478bd9Sstevel@tonic-gate { 145*7c478bd9Sstevel@tonic-gate char opt; 146*7c478bd9Sstevel@tonic-gate int n = 0; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate if (argc == 1) { 149*7c478bd9Sstevel@tonic-gate usage(argv[0]); 150*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, "udm:M:Ll:g")) != EOF) { 154*7c478bd9Sstevel@tonic-gate switch (opt) { 155*7c478bd9Sstevel@tonic-gate case 'u': 156*7c478bd9Sstevel@tonic-gate patch_vfstab = 1; 157*7c478bd9Sstevel@tonic-gate n++; 158*7c478bd9Sstevel@tonic-gate break; 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate case 'd': 161*7c478bd9Sstevel@tonic-gate debug = 1; 162*7c478bd9Sstevel@tonic-gate break; 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate case 'm': 165*7c478bd9Sstevel@tonic-gate mapdev = s_strdup(optarg); 166*7c478bd9Sstevel@tonic-gate n++; 167*7c478bd9Sstevel@tonic-gate break; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate case 'M': 170*7c478bd9Sstevel@tonic-gate mapdev = s_strdup(optarg); 171*7c478bd9Sstevel@tonic-gate cap_m_option = 1; 172*7c478bd9Sstevel@tonic-gate n++; 173*7c478bd9Sstevel@tonic-gate break; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate case 'L': 176*7c478bd9Sstevel@tonic-gate list_option = 1; 177*7c478bd9Sstevel@tonic-gate n++; 178*7c478bd9Sstevel@tonic-gate break; 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate case 'l': 181*7c478bd9Sstevel@tonic-gate list_option = 1; 182*7c478bd9Sstevel@tonic-gate list_controllernum = (int)atol(optarg); 183*7c478bd9Sstevel@tonic-gate if (list_controllernum < 0) { 184*7c478bd9Sstevel@tonic-gate logerr(gettext("controller number %d is " 185*7c478bd9Sstevel@tonic-gate "invalid\n"), list_controllernum); 186*7c478bd9Sstevel@tonic-gate clean_exit(1); 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate n++; 189*7c478bd9Sstevel@tonic-gate break; 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate case 'g': 192*7c478bd9Sstevel@tonic-gate /* 193*7c478bd9Sstevel@tonic-gate * private option to display non-STMS device name 194*7c478bd9Sstevel@tonic-gate * to GUID mappings. 195*7c478bd9Sstevel@tonic-gate */ 196*7c478bd9Sstevel@tonic-gate list_guid_mappings = 1; 197*7c478bd9Sstevel@tonic-gate n++; 198*7c478bd9Sstevel@tonic-gate break; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate default: 201*7c478bd9Sstevel@tonic-gate usage(argv[0]); 202*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate if (n != 1) 207*7c478bd9Sstevel@tonic-gate usage(argv[0]); 208*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate void 212*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 213*7c478bd9Sstevel@tonic-gate { 214*7c478bd9Sstevel@tonic-gate char save_vfstab[SYS_FILENAME_LEN], tmp_vfstab[SYS_FILENAME_LEN]; 215*7c478bd9Sstevel@tonic-gate int vfstab_updated; 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 218*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate if (getuid() != 0) { 221*7c478bd9Sstevel@tonic-gate logerr(gettext("must be super-user to run this program\n")); 222*7c478bd9Sstevel@tonic-gate clean_exit(1); 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate parse_args(argc, argv); 226*7c478bd9Sstevel@tonic-gate (void) umask(022); 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate /* 229*7c478bd9Sstevel@tonic-gate * NOTE: The mpxio boot-up script executes this program with the 230*7c478bd9Sstevel@tonic-gate * mapping (-m) option before the /usr is even mounted and when the 231*7c478bd9Sstevel@tonic-gate * root filesystem is still mounted read-only. 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate if (*mapdev != '\0') { 234*7c478bd9Sstevel@tonic-gate char newname[MAXPATHLEN]; 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate if (map_devname(mapdev, newname, sizeof (newname), 237*7c478bd9Sstevel@tonic-gate cap_m_option) == 0) { 238*7c478bd9Sstevel@tonic-gate (void) printf("%s\n", newname); 239*7c478bd9Sstevel@tonic-gate clean_exit(0); 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate clean_exit(1); 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate if (list_option || list_guid_mappings) { 245*7c478bd9Sstevel@tonic-gate if (list_mappings(list_controllernum, list_guid_mappings) == 0) 246*7c478bd9Sstevel@tonic-gate clean_exit(0); 247*7c478bd9Sstevel@tonic-gate clean_exit(1); 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate /* create a directory where a copy of the system files are saved */ 251*7c478bd9Sstevel@tonic-gate if (patch_vfstab) { 252*7c478bd9Sstevel@tonic-gate if (mkdirp(SAVE_DIR, 0755) != 0 && errno != EEXIST) { 253*7c478bd9Sstevel@tonic-gate logerr(gettext("mkdirp: failed to create %1$s: %2$s\n"), 254*7c478bd9Sstevel@tonic-gate SAVE_DIR, strerror(errno)); 255*7c478bd9Sstevel@tonic-gate clean_exit(1); 256*7c478bd9Sstevel@tonic-gate } 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate if (make_temp(VFSTAB, save_vfstab, tmp_vfstab, 259*7c478bd9Sstevel@tonic-gate SYS_FILENAME_LEN) != 0) 260*7c478bd9Sstevel@tonic-gate clean_exit(1); 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate /* build new vfstab without modifying the existing one */ 263*7c478bd9Sstevel@tonic-gate if ((vfstab_updated = update_vfstab(VFSTAB, tmp_vfstab)) 264*7c478bd9Sstevel@tonic-gate == -1) { 265*7c478bd9Sstevel@tonic-gate logerr(gettext("failed to update %s\n"), VFSTAB); 266*7c478bd9Sstevel@tonic-gate clean_exit(1); 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate commit_change(VFSTAB, save_vfstab, tmp_vfstab, vfstab_updated); 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate clean_exit(0); 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate /* 276*7c478bd9Sstevel@tonic-gate * Make saved and temporary filenames in SAVE_DIR. 277*7c478bd9Sstevel@tonic-gate * 278*7c478bd9Sstevel@tonic-gate * ex: if the filename is /etc/vfstab then the save_filename and tmp_filename 279*7c478bd9Sstevel@tonic-gate * would be SAVE_DIR/vfstab and SAVE_DIR/vfstab.tmp respectively. 280*7c478bd9Sstevel@tonic-gate * 281*7c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 282*7c478bd9Sstevel@tonic-gate */ 283*7c478bd9Sstevel@tonic-gate static int 284*7c478bd9Sstevel@tonic-gate make_temp(char *filename, char *save_filename, char *tmp_filename, size_t len) 285*7c478bd9Sstevel@tonic-gate { 286*7c478bd9Sstevel@tonic-gate char *ptr; 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate if ((ptr = strrchr(filename, '/')) == NULL) { 289*7c478bd9Sstevel@tonic-gate logdmsg("invalid file %s\n", filename); 290*7c478bd9Sstevel@tonic-gate return (-1); 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate (void) snprintf(save_filename, len, "%s%s", SAVE_DIR, ptr); 293*7c478bd9Sstevel@tonic-gate (void) snprintf(tmp_filename, len, "%s%s.tmp", SAVE_DIR, ptr); 294*7c478bd9Sstevel@tonic-gate logdmsg("make_temp: %s: save = %s, temp = %s\n", filename, 295*7c478bd9Sstevel@tonic-gate save_filename, tmp_filename); 296*7c478bd9Sstevel@tonic-gate return (0); 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate /* 300*7c478bd9Sstevel@tonic-gate * Commit the changes made to the system file 301*7c478bd9Sstevel@tonic-gate */ 302*7c478bd9Sstevel@tonic-gate static void 303*7c478bd9Sstevel@tonic-gate commit_change(char *filename, char *save_filename, char *tmp_filename, 304*7c478bd9Sstevel@tonic-gate int updated) 305*7c478bd9Sstevel@tonic-gate { 306*7c478bd9Sstevel@tonic-gate int x; 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate if (updated) { 309*7c478bd9Sstevel@tonic-gate /* save the original */ 310*7c478bd9Sstevel@tonic-gate if ((x = rename(filename, save_filename)) != 0) { 311*7c478bd9Sstevel@tonic-gate logerr(gettext("rename %1$s to %2$s failed: %3$s\n"), 312*7c478bd9Sstevel@tonic-gate filename, save_filename, strerror(errno)); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate /* now rename the new file to the actual file */ 316*7c478bd9Sstevel@tonic-gate if (rename(tmp_filename, filename) != 0) { 317*7c478bd9Sstevel@tonic-gate logerr(gettext("rename %1$s to %2$s failed: %3$s\n"), 318*7c478bd9Sstevel@tonic-gate tmp_filename, filename, strerror(errno)); 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate /* restore the original */ 321*7c478bd9Sstevel@tonic-gate if (x == 0 && rename(save_filename, filename) != 0) { 322*7c478bd9Sstevel@tonic-gate logerr( 323*7c478bd9Sstevel@tonic-gate gettext("rename %1$s to %2$s failed: %3$s\n" 324*7c478bd9Sstevel@tonic-gate "%4$s is a copy of the original %5$s file" 325*7c478bd9Sstevel@tonic-gate "\n"), 326*7c478bd9Sstevel@tonic-gate save_filename, filename, strerror(errno), 327*7c478bd9Sstevel@tonic-gate save_filename, filename); 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate } else 330*7c478bd9Sstevel@tonic-gate (void) printf(gettext("%1$s: %2$s has been updated.\n"), 331*7c478bd9Sstevel@tonic-gate stmsboot, filename); 332*7c478bd9Sstevel@tonic-gate } else { 333*7c478bd9Sstevel@tonic-gate /* remove the temp file */ 334*7c478bd9Sstevel@tonic-gate (void) unlink(tmp_filename); 335*7c478bd9Sstevel@tonic-gate (void) printf(gettext("%1$s: %2$s was not modified as no " 336*7c478bd9Sstevel@tonic-gate "changes were needed.\n"), stmsboot, filename); 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate /* 341*7c478bd9Sstevel@tonic-gate * Get the GUID of the device. 342*7c478bd9Sstevel@tonic-gate * 343*7c478bd9Sstevel@tonic-gate * physpath /devices name without the /devices prefix and minor name 344*7c478bd9Sstevel@tonic-gate * component. 345*7c478bd9Sstevel@tonic-gate * guid caller supplied buffer where the GUID will be placed on return 346*7c478bd9Sstevel@tonic-gate * guid_len length of the caller supplied guid buffer. 347*7c478bd9Sstevel@tonic-gate * no_dealy_flag if set open the device with O_NDELAY 348*7c478bd9Sstevel@tonic-gate * node di_node corresponding to physpath if already available, 349*7c478bd9Sstevel@tonic-gate * otherwise pass DI_NODE_NIL. 350*7c478bd9Sstevel@tonic-gate * 351*7c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 352*7c478bd9Sstevel@tonic-gate */ 353*7c478bd9Sstevel@tonic-gate static int 354*7c478bd9Sstevel@tonic-gate get_guid(char *physpath, char *guid, int guid_len, int no_delay_flag, 355*7c478bd9Sstevel@tonic-gate di_node_t node) 356*7c478bd9Sstevel@tonic-gate { 357*7c478bd9Sstevel@tonic-gate int fd; 358*7c478bd9Sstevel@tonic-gate ddi_devid_t devid; 359*7c478bd9Sstevel@tonic-gate int rv = -1; 360*7c478bd9Sstevel@tonic-gate char *i_guid = NULL; 361*7c478bd9Sstevel@tonic-gate char physpath_raw[MAXPATHLEN]; 362*7c478bd9Sstevel@tonic-gate uchar_t *wwnp; 363*7c478bd9Sstevel@tonic-gate int i, n, snapshot_taken = 0; 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate logdmsg("get_guid: physpath = %s\n", physpath); 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate (void) snprintf(physpath_raw, MAXPATHLEN, 368*7c478bd9Sstevel@tonic-gate "/devices%s:a,raw", physpath); 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate *guid = '\0'; 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate if (no_delay_flag) 373*7c478bd9Sstevel@tonic-gate no_delay_flag = O_NDELAY; 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate /* 376*7c478bd9Sstevel@tonic-gate * Open the raw device 377*7c478bd9Sstevel@tonic-gate * Without the O_DELAY flag, the open will fail on standby paths of 378*7c478bd9Sstevel@tonic-gate * T3 if its mp_support mode is "mpxio". 379*7c478bd9Sstevel@tonic-gate */ 380*7c478bd9Sstevel@tonic-gate if ((fd = open(physpath_raw, O_RDONLY | no_delay_flag)) == -1) { 381*7c478bd9Sstevel@tonic-gate logdmsg("get_guid: failed to open %s: %s\n", physpath_raw, 382*7c478bd9Sstevel@tonic-gate strerror(errno)); 383*7c478bd9Sstevel@tonic-gate return (-1); 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate if (devid_get(fd, &devid) == 0) { 387*7c478bd9Sstevel@tonic-gate i_guid = devid_to_guid(devid); 388*7c478bd9Sstevel@tonic-gate devid_free(devid); 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate if (i_guid != NULL) { 391*7c478bd9Sstevel@tonic-gate s_strlcpy(guid, i_guid, guid_len); 392*7c478bd9Sstevel@tonic-gate devid_free_guid(i_guid); 393*7c478bd9Sstevel@tonic-gate rv = 0; 394*7c478bd9Sstevel@tonic-gate goto out; 395*7c478bd9Sstevel@tonic-gate } else 396*7c478bd9Sstevel@tonic-gate logdmsg("get_guid: devid_to_guid() failed\n"); 397*7c478bd9Sstevel@tonic-gate } else 398*7c478bd9Sstevel@tonic-gate logdmsg("get_guid: devid_get() failed: %s\n", strerror(errno)); 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate /* fallback to node name as the guid as this is what fcp driver does */ 401*7c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 402*7c478bd9Sstevel@tonic-gate if ((node = di_init(physpath, DINFOCPYALL | DINFOFORCE)) 403*7c478bd9Sstevel@tonic-gate == DI_NODE_NIL) { 404*7c478bd9Sstevel@tonic-gate logdmsg("get_guid: di_init on %s failed: %s\n", 405*7c478bd9Sstevel@tonic-gate physpath, strerror(errno)); 406*7c478bd9Sstevel@tonic-gate goto out; 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate snapshot_taken = 1; 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate if ((n = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, NODE_WWN_PROP, 412*7c478bd9Sstevel@tonic-gate &wwnp)) == -1) { 413*7c478bd9Sstevel@tonic-gate logdmsg("get_guid: di_prop_lookup_bytes() failed to lookup " 414*7c478bd9Sstevel@tonic-gate "%s: %s\n", NODE_WWN_PROP, strerror(errno)); 415*7c478bd9Sstevel@tonic-gate goto out; 416*7c478bd9Sstevel@tonic-gate } 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate if (guid_len >= ((n * 2) + 1)) { 419*7c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) { 420*7c478bd9Sstevel@tonic-gate (void) sprintf(guid + (i * 2), "%02x", (uint_t)(*wwnp)); 421*7c478bd9Sstevel@tonic-gate wwnp++; 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate rv = 0; 424*7c478bd9Sstevel@tonic-gate } else 425*7c478bd9Sstevel@tonic-gate logerr(gettext("insufficient buffer size: need %1$d " 426*7c478bd9Sstevel@tonic-gate "bytes, passed %2$d bytes\n"), (n * 2) + 1, guid_len); 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate out: 429*7c478bd9Sstevel@tonic-gate if (snapshot_taken) 430*7c478bd9Sstevel@tonic-gate di_fini(node); 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate (void) close(fd); 433*7c478bd9Sstevel@tonic-gate logdmsg("get_guid: GUID = %s\n", guid); 434*7c478bd9Sstevel@tonic-gate return (rv); 435*7c478bd9Sstevel@tonic-gate } 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate /* 438*7c478bd9Sstevel@tonic-gate * Given client_name return whether it is a phci or vhci based name. 439*7c478bd9Sstevel@tonic-gate * client_name is /devices name of a client without the /devices prefix. 440*7c478bd9Sstevel@tonic-gate * 441*7c478bd9Sstevel@tonic-gate * client_name Return value 442*7c478bd9Sstevel@tonic-gate * .../fp@xxx/ssd@yyy CLIENT_TYPE_PHCI 443*7c478bd9Sstevel@tonic-gate * .../scsi_vhci/ssd@yyy CLIENT_TYPE_VHCI 444*7c478bd9Sstevel@tonic-gate * other CLIENT_TYPE_UNKNOWN 445*7c478bd9Sstevel@tonic-gate */ 446*7c478bd9Sstevel@tonic-gate static client_type_t 447*7c478bd9Sstevel@tonic-gate client_name_type(char *client_name) 448*7c478bd9Sstevel@tonic-gate { 449*7c478bd9Sstevel@tonic-gate client_type_t client_type = CLIENT_TYPE_UNKNOWN; 450*7c478bd9Sstevel@tonic-gate char *p1, *p2; 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate if (*client_name != '/') 453*7c478bd9Sstevel@tonic-gate return (CLIENT_TYPE_UNKNOWN); 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate /* we only care for ssd devices */ 456*7c478bd9Sstevel@tonic-gate if ((p1 = strrchr(client_name, '/')) == NULL || 457*7c478bd9Sstevel@tonic-gate strncmp(p1, SLASH_SSD_AT, sizeof (SLASH_SSD_AT) - 1) != 0) 458*7c478bd9Sstevel@tonic-gate return (CLIENT_TYPE_UNKNOWN); 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate *p1 = '\0'; 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate if ((p2 = strrchr(client_name, '/')) != NULL) { 463*7c478bd9Sstevel@tonic-gate if (strncmp(p2, SLASH_FP_AT, sizeof (SLASH_FP_AT) - 1) == 0) 464*7c478bd9Sstevel@tonic-gate client_type = CLIENT_TYPE_PHCI; 465*7c478bd9Sstevel@tonic-gate else if (strncmp(p2, SLASH_SCSI_VHCI, 466*7c478bd9Sstevel@tonic-gate sizeof (SLASH_SCSI_VHCI) - 1) == 0) 467*7c478bd9Sstevel@tonic-gate client_type = CLIENT_TYPE_VHCI; 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate *p1 = '/'; 471*7c478bd9Sstevel@tonic-gate return (client_type); 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate /* 475*7c478bd9Sstevel@tonic-gate * Map phci based client name to vhci based client name. 476*7c478bd9Sstevel@tonic-gate * 477*7c478bd9Sstevel@tonic-gate * phci_name 478*7c478bd9Sstevel@tonic-gate * phci based client /devices name without the /devices prefix and 479*7c478bd9Sstevel@tonic-gate * minor name component. 480*7c478bd9Sstevel@tonic-gate * ex: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0 481*7c478bd9Sstevel@tonic-gate * 482*7c478bd9Sstevel@tonic-gate * vhci_name 483*7c478bd9Sstevel@tonic-gate * Caller supplied buffer where vhci /devices name will be placed on 484*7c478bd9Sstevel@tonic-gate * return (without the /devices prefix and minor name component). 485*7c478bd9Sstevel@tonic-gate * ex: /scsi_vhci/ssd@g2000002037cd9f72 486*7c478bd9Sstevel@tonic-gate * 487*7c478bd9Sstevel@tonic-gate * vhci_name_len 488*7c478bd9Sstevel@tonic-gate * Length of the caller supplied vhci_name buffer. 489*7c478bd9Sstevel@tonic-gate * 490*7c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 491*7c478bd9Sstevel@tonic-gate */ 492*7c478bd9Sstevel@tonic-gate static int 493*7c478bd9Sstevel@tonic-gate phci_to_vhci(char *phci_name, char *vhci_name, size_t vhci_name_len) 494*7c478bd9Sstevel@tonic-gate { 495*7c478bd9Sstevel@tonic-gate sv_iocdata_t ioc; 496*7c478bd9Sstevel@tonic-gate char *slash; 497*7c478bd9Sstevel@tonic-gate char vhci_name_buf[MAXPATHLEN]; 498*7c478bd9Sstevel@tonic-gate char phci_name_buf[MAXPATHLEN]; 499*7c478bd9Sstevel@tonic-gate char addr_buf[MAXNAMELEN]; 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate logdmsg("phci_to_vhci: client = %s\n", phci_name); 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate s_strlcpy(phci_name_buf, phci_name, MAXPATHLEN); 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate if (client_name_type(phci_name_buf) != CLIENT_TYPE_PHCI || 506*7c478bd9Sstevel@tonic-gate (slash = strrchr(phci_name_buf, '/')) == NULL || 507*7c478bd9Sstevel@tonic-gate strncmp(slash, SLASH_SSD_AT, sizeof (SLASH_SSD_AT) - 1) != 0) { 508*7c478bd9Sstevel@tonic-gate logdmsg("phci_to_vhci: %s is not of CLIENT_TYPE_PHCI\n", 509*7c478bd9Sstevel@tonic-gate phci_name); 510*7c478bd9Sstevel@tonic-gate return (-1); 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate if (vhci_fd < 0) { 514*7c478bd9Sstevel@tonic-gate if ((vhci_fd = open(VHCI_CTL_NODE, O_RDWR)) < 0) 515*7c478bd9Sstevel@tonic-gate return (-1); 516*7c478bd9Sstevel@tonic-gate } 517*7c478bd9Sstevel@tonic-gate 518*7c478bd9Sstevel@tonic-gate *slash = '\0'; 519*7c478bd9Sstevel@tonic-gate s_strlcpy(addr_buf, slash + sizeof (SLASH_SSD_AT) - 1, MAXNAMELEN); 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate bzero(&ioc, sizeof (sv_iocdata_t)); 522*7c478bd9Sstevel@tonic-gate ioc.client = vhci_name_buf; 523*7c478bd9Sstevel@tonic-gate ioc.phci = phci_name_buf; 524*7c478bd9Sstevel@tonic-gate ioc.addr = addr_buf; 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate if (ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_NAME, &ioc) != 0) { 527*7c478bd9Sstevel@tonic-gate logdmsg("SCSI_VHCI_GET_CLIENT_NAME on %s " 528*7c478bd9Sstevel@tonic-gate "failed: %s\n", phci_name, strerror(errno)); 529*7c478bd9Sstevel@tonic-gate return (-1); 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate s_strlcpy(vhci_name, vhci_name_buf, vhci_name_len); 533*7c478bd9Sstevel@tonic-gate logdmsg("phci_to_vhci: %s maps to %s\n", phci_name, vhci_name); 534*7c478bd9Sstevel@tonic-gate return (0); 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate /* 538*7c478bd9Sstevel@tonic-gate * Map vhci based client name to phci based client name. 539*7c478bd9Sstevel@tonic-gate * If the client has multiple paths, only one of the paths with which client 540*7c478bd9Sstevel@tonic-gate * can be accessed is returned. This function does not use SCSI_VHCI ioctls 541*7c478bd9Sstevel@tonic-gate * as it is called on mpxio disabled paths. 542*7c478bd9Sstevel@tonic-gate * 543*7c478bd9Sstevel@tonic-gate * vhci_name 544*7c478bd9Sstevel@tonic-gate * vhci based client /devices name without the /devices prefix and 545*7c478bd9Sstevel@tonic-gate * minor name component. 546*7c478bd9Sstevel@tonic-gate * ex: /scsi_vhci/ssd@g2000002037cd9f72 547*7c478bd9Sstevel@tonic-gate * 548*7c478bd9Sstevel@tonic-gate * phci_name 549*7c478bd9Sstevel@tonic-gate * Caller supplied buffer where phci /devices name will be placed on 550*7c478bd9Sstevel@tonic-gate * return (without the /devices prefix and minor name component). 551*7c478bd9Sstevel@tonic-gate * ex: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0 552*7c478bd9Sstevel@tonic-gate * 553*7c478bd9Sstevel@tonic-gate * phci_name_len 554*7c478bd9Sstevel@tonic-gate * Length of the caller supplied phci_name buffer. 555*7c478bd9Sstevel@tonic-gate * 556*7c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 557*7c478bd9Sstevel@tonic-gate */ 558*7c478bd9Sstevel@tonic-gate static int 559*7c478bd9Sstevel@tonic-gate vhci_to_phci(char *vhci_name, char *phci_name, size_t phci_name_len) 560*7c478bd9Sstevel@tonic-gate { 561*7c478bd9Sstevel@tonic-gate di_node_t node, parent; 562*7c478bd9Sstevel@tonic-gate char *vhci_guid, *devfspath; 563*7c478bd9Sstevel@tonic-gate char phci_guid[MAXPATHLEN]; 564*7c478bd9Sstevel@tonic-gate char *parent_name, *node_name; 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: client = %s\n", vhci_name); 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate if (client_name_type(vhci_name) != CLIENT_TYPE_VHCI) { 569*7c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: %s is not of CLIENT_TYPE_VHCI\n", 570*7c478bd9Sstevel@tonic-gate vhci_name); 571*7c478bd9Sstevel@tonic-gate return (-1); 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate if ((vhci_guid = strrchr(vhci_name, '@')) == NULL || 575*7c478bd9Sstevel@tonic-gate *(++vhci_guid) != 'g') { 576*7c478bd9Sstevel@tonic-gate logerr(gettext("couldn't get guid from %s\n"), vhci_name); 577*7c478bd9Sstevel@tonic-gate return (-1); 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate /* point to guid */ 581*7c478bd9Sstevel@tonic-gate ++vhci_guid; 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate /* 584*7c478bd9Sstevel@tonic-gate * Get devinfo snapshot and walk all ssd nodes whose parent is fp. 585*7c478bd9Sstevel@tonic-gate * For each node get the guid and match it with vhci_guid. 586*7c478bd9Sstevel@tonic-gate */ 587*7c478bd9Sstevel@tonic-gate if (devinfo_root == DI_NODE_NIL) { 588*7c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: taking devinfo snapshot\n"); 589*7c478bd9Sstevel@tonic-gate if ((devinfo_root = di_init("/", DINFOCPYALL | DINFOFORCE)) 590*7c478bd9Sstevel@tonic-gate == DI_NODE_NIL) { 591*7c478bd9Sstevel@tonic-gate logerr(gettext("di_init failed: %s\n"), 592*7c478bd9Sstevel@tonic-gate strerror(errno)); 593*7c478bd9Sstevel@tonic-gate return (-1); 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: done taking devinfo snapshot\n"); 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate for (node = di_drv_first_node("ssd", devinfo_root); 599*7c478bd9Sstevel@tonic-gate node != DI_NODE_NIL; node = di_drv_next_node(node)) { 600*7c478bd9Sstevel@tonic-gate if ((node_name = di_node_name(node)) == NULL || 601*7c478bd9Sstevel@tonic-gate strcmp(node_name, "ssd") != 0 || 602*7c478bd9Sstevel@tonic-gate (parent = di_parent_node(node)) == DI_NODE_NIL || 603*7c478bd9Sstevel@tonic-gate (parent_name = di_node_name(parent)) == NULL || 604*7c478bd9Sstevel@tonic-gate strcmp(parent_name, "fp") != 0 || 605*7c478bd9Sstevel@tonic-gate (devfspath = di_devfs_path(node)) == NULL) 606*7c478bd9Sstevel@tonic-gate continue; 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate /* 609*7c478bd9Sstevel@tonic-gate * Don't set no_delay_flag to have get_guid() fail on 610*7c478bd9Sstevel@tonic-gate * standby paths of T3. So we'll find the preferred paths. 611*7c478bd9Sstevel@tonic-gate */ 612*7c478bd9Sstevel@tonic-gate if (get_guid(devfspath, phci_guid, 613*7c478bd9Sstevel@tonic-gate sizeof (phci_guid), 0, node) == 0 && 614*7c478bd9Sstevel@tonic-gate strcmp(phci_guid, vhci_guid) == 0) { 615*7c478bd9Sstevel@tonic-gate s_strlcpy(phci_name, devfspath, phci_name_len); 616*7c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 617*7c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: %s maps to %s\n", vhci_name, 618*7c478bd9Sstevel@tonic-gate phci_name); 619*7c478bd9Sstevel@tonic-gate return (0); 620*7c478bd9Sstevel@tonic-gate } 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 623*7c478bd9Sstevel@tonic-gate } 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate logdmsg("vhci_to_phci: couldn't get phci name for %s\n", vhci_name); 626*7c478bd9Sstevel@tonic-gate return (-1); 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate /* 630*7c478bd9Sstevel@tonic-gate * Map physname from phci name space to vhci name space or vice-versa 631*7c478bd9Sstevel@tonic-gate * 632*7c478bd9Sstevel@tonic-gate * physname 633*7c478bd9Sstevel@tonic-gate * phci or vhci based client /devices name without the /devices prefix and 634*7c478bd9Sstevel@tonic-gate * minor name component. 635*7c478bd9Sstevel@tonic-gate * 636*7c478bd9Sstevel@tonic-gate * new_physname 637*7c478bd9Sstevel@tonic-gate * Caller supplied buffer where the mapped physical name is stored on 638*7c478bd9Sstevel@tonic-gate * return (without the /devices prefix and minor name component). 639*7c478bd9Sstevel@tonic-gate * 640*7c478bd9Sstevel@tonic-gate * len 641*7c478bd9Sstevel@tonic-gate * Length of the caller supplied new_physname buffer. 642*7c478bd9Sstevel@tonic-gate * 643*7c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 644*7c478bd9Sstevel@tonic-gate */ 645*7c478bd9Sstevel@tonic-gate static int 646*7c478bd9Sstevel@tonic-gate map_physname(char *physname, char *new_physname, size_t len) 647*7c478bd9Sstevel@tonic-gate { 648*7c478bd9Sstevel@tonic-gate int type; 649*7c478bd9Sstevel@tonic-gate int rv; 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate if ((type = client_name_type(physname)) == CLIENT_TYPE_VHCI) 652*7c478bd9Sstevel@tonic-gate rv = vhci_to_phci(physname, new_physname, len); 653*7c478bd9Sstevel@tonic-gate else if (type == CLIENT_TYPE_PHCI) 654*7c478bd9Sstevel@tonic-gate rv = phci_to_vhci(physname, new_physname, len); 655*7c478bd9Sstevel@tonic-gate else 656*7c478bd9Sstevel@tonic-gate rv = -1; 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate return (rv); 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate /* 662*7c478bd9Sstevel@tonic-gate * Given a phci or vhci devname which is either a /dev link or /devices name 663*7c478bd9Sstevel@tonic-gate * get the corresponding physical node path (without the /devices prefix) 664*7c478bd9Sstevel@tonic-gate * and minor name. 665*7c478bd9Sstevel@tonic-gate * 666*7c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 667*7c478bd9Sstevel@tonic-gate */ 668*7c478bd9Sstevel@tonic-gate static int 669*7c478bd9Sstevel@tonic-gate get_physname_minor(char *devname, char *physname, int physname_len, 670*7c478bd9Sstevel@tonic-gate char *minorname, int minorname_len) 671*7c478bd9Sstevel@tonic-gate { 672*7c478bd9Sstevel@tonic-gate int linksize; 673*7c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 674*7c478bd9Sstevel@tonic-gate char *p, *m; 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate if (strncmp(devname, DEV_DSK, sizeof (DEV_DSK) - 1) == 0 || 677*7c478bd9Sstevel@tonic-gate strncmp(devname, DEV_RDSK, sizeof (DEV_RDSK) - 1) == 0) { 678*7c478bd9Sstevel@tonic-gate if ((linksize = readlink(devname, buf, MAXPATHLEN)) 679*7c478bd9Sstevel@tonic-gate > 0 && linksize <= (MAXPATHLEN - 1)) { 680*7c478bd9Sstevel@tonic-gate buf[linksize] = '\0'; 681*7c478bd9Sstevel@tonic-gate } else 682*7c478bd9Sstevel@tonic-gate return (-1); 683*7c478bd9Sstevel@tonic-gate } else 684*7c478bd9Sstevel@tonic-gate s_strlcpy(buf, devname, MAXPATHLEN); 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate if ((p = strstr(buf, SLASH_DEVICES)) == NULL) 687*7c478bd9Sstevel@tonic-gate return (-1); 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate /* point to '/' after /devices */ 690*7c478bd9Sstevel@tonic-gate p += sizeof (SLASH_DEVICES) - 2; 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate if ((m = strrchr(p, ':')) == NULL) { 693*7c478bd9Sstevel@tonic-gate logdmsg("get_physname_minor: no minor name component in %s\n", 694*7c478bd9Sstevel@tonic-gate buf); 695*7c478bd9Sstevel@tonic-gate return (-1); 696*7c478bd9Sstevel@tonic-gate } 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate *m = '\0'; 699*7c478bd9Sstevel@tonic-gate m++; 700*7c478bd9Sstevel@tonic-gate 701*7c478bd9Sstevel@tonic-gate if (client_name_type(p) == CLIENT_TYPE_UNKNOWN) 702*7c478bd9Sstevel@tonic-gate return (-1); 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate s_strlcpy(physname, p, physname_len); 705*7c478bd9Sstevel@tonic-gate s_strlcpy(minorname, m, minorname_len); 706*7c478bd9Sstevel@tonic-gate logdmsg("get_physname_minor: %s: physname = %s, minor = %s\n", 707*7c478bd9Sstevel@tonic-gate devname, physname, minorname); 708*7c478bd9Sstevel@tonic-gate return (0); 709*7c478bd9Sstevel@tonic-gate } 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate static int 712*7c478bd9Sstevel@tonic-gate devlink_callback(di_devlink_t devlink, void *argptr) 713*7c478bd9Sstevel@tonic-gate { 714*7c478bd9Sstevel@tonic-gate const char *link; 715*7c478bd9Sstevel@tonic-gate struct devlink_cbarg *argp = argptr; 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate if ((link = di_devlink_path(devlink)) != NULL) { 718*7c478bd9Sstevel@tonic-gate s_strlcpy(argp->devlink, link, argp->len); 719*7c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 723*7c478bd9Sstevel@tonic-gate } 724*7c478bd9Sstevel@tonic-gate 725*7c478bd9Sstevel@tonic-gate /* 726*7c478bd9Sstevel@tonic-gate * Lookup the /dev link corresponding to physname and minorname. 727*7c478bd9Sstevel@tonic-gate * 728*7c478bd9Sstevel@tonic-gate * physname client /devices path without the /devices prefix and minor 729*7c478bd9Sstevel@tonic-gate * name component. 730*7c478bd9Sstevel@tonic-gate * minorname client minor name. 731*7c478bd9Sstevel@tonic-gate * devlink caller supplied buffer where the /dev link is placed on return. 732*7c478bd9Sstevel@tonic-gate * len caller supplied devlink buffer length 733*7c478bd9Sstevel@tonic-gate * 734*7c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 735*7c478bd9Sstevel@tonic-gate */ 736*7c478bd9Sstevel@tonic-gate static int 737*7c478bd9Sstevel@tonic-gate lookup_devlink(char *physname, char *minorname, char *devlink, size_t len) 738*7c478bd9Sstevel@tonic-gate { 739*7c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 740*7c478bd9Sstevel@tonic-gate struct devlink_cbarg arg; 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate if (devlink_hdl == NULL) { 743*7c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: taking devlink snapshot\n"); 744*7c478bd9Sstevel@tonic-gate if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 745*7c478bd9Sstevel@tonic-gate logerr(gettext("di_devlink_init failed: %s\n"), 746*7c478bd9Sstevel@tonic-gate strerror(errno)); 747*7c478bd9Sstevel@tonic-gate clean_exit(1); 748*7c478bd9Sstevel@tonic-gate } 749*7c478bd9Sstevel@tonic-gate } 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate *devlink = '\0'; 752*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, "%s:%s", physname, minorname); 753*7c478bd9Sstevel@tonic-gate arg.devlink = devlink; 754*7c478bd9Sstevel@tonic-gate arg.len = len; 755*7c478bd9Sstevel@tonic-gate if (di_devlink_walk(devlink_hdl, NULL, buf, DI_PRIMARY_LINK, &arg, 756*7c478bd9Sstevel@tonic-gate devlink_callback) != 0) { 757*7c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: di_devlink_walk on %s failed: %s\n", 758*7c478bd9Sstevel@tonic-gate buf, strerror(errno)); 759*7c478bd9Sstevel@tonic-gate return (-1); 760*7c478bd9Sstevel@tonic-gate } 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate if (*devlink == '\0') { 763*7c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: failed to lookup devlink for %s\n", 764*7c478bd9Sstevel@tonic-gate buf); 765*7c478bd9Sstevel@tonic-gate return (-1); 766*7c478bd9Sstevel@tonic-gate } 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate logdmsg("lookup_devlink: /dev link for %s:%s = %s\n", physname, 769*7c478bd9Sstevel@tonic-gate minorname, devlink); 770*7c478bd9Sstevel@tonic-gate return (0); 771*7c478bd9Sstevel@tonic-gate } 772*7c478bd9Sstevel@tonic-gate 773*7c478bd9Sstevel@tonic-gate /* 774*7c478bd9Sstevel@tonic-gate * open infile for reading and return its file pointer in *fp_in. 775*7c478bd9Sstevel@tonic-gate * open outfile for writing and return its file pointer in *fp_out. 776*7c478bd9Sstevel@tonic-gate * 777*7c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 778*7c478bd9Sstevel@tonic-gate */ 779*7c478bd9Sstevel@tonic-gate static int 780*7c478bd9Sstevel@tonic-gate open_in_out_files(char *infile, char *outfile, FILE **fp_in, FILE **fp_out) 781*7c478bd9Sstevel@tonic-gate { 782*7c478bd9Sstevel@tonic-gate FILE *fin = NULL; 783*7c478bd9Sstevel@tonic-gate FILE *fout = NULL; 784*7c478bd9Sstevel@tonic-gate struct stat sbuf; 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate if ((fin = fopen(infile, "r")) == NULL) { 787*7c478bd9Sstevel@tonic-gate logerr(gettext("failed to fopen %1$s: %2$s\n"), 788*7c478bd9Sstevel@tonic-gate infile, strerror(errno)); 789*7c478bd9Sstevel@tonic-gate goto out; 790*7c478bd9Sstevel@tonic-gate } 791*7c478bd9Sstevel@tonic-gate 792*7c478bd9Sstevel@tonic-gate if (fstat(fileno(fin), &sbuf) != 0) { 793*7c478bd9Sstevel@tonic-gate logerr(gettext("fstat failed on %1$s: %2$s\n"), 794*7c478bd9Sstevel@tonic-gate infile, strerror(errno)); 795*7c478bd9Sstevel@tonic-gate goto out; 796*7c478bd9Sstevel@tonic-gate } 797*7c478bd9Sstevel@tonic-gate 798*7c478bd9Sstevel@tonic-gate if ((fout = fopen(outfile, "w")) == NULL) { 799*7c478bd9Sstevel@tonic-gate logerr(gettext("failed to fopen %1$s: %2$s\n"), 800*7c478bd9Sstevel@tonic-gate outfile, strerror(errno)); 801*7c478bd9Sstevel@tonic-gate goto out; 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate if (fchmod(fileno(fout), (sbuf.st_mode & 0777)) != 0) { 805*7c478bd9Sstevel@tonic-gate logerr(gettext("failed to fchmod %1$s to 0%2$o: %3$s\n"), 806*7c478bd9Sstevel@tonic-gate outfile, sbuf.st_mode & 0777, strerror(errno)); 807*7c478bd9Sstevel@tonic-gate goto out; 808*7c478bd9Sstevel@tonic-gate } 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate if (fchown(fileno(fout), sbuf.st_uid, sbuf.st_gid) != 0) { 811*7c478bd9Sstevel@tonic-gate logerr(gettext("failed to fchown %1$s to uid %2$d and " 812*7c478bd9Sstevel@tonic-gate "gid %3$d: %4$s\n"), 813*7c478bd9Sstevel@tonic-gate outfile, sbuf.st_uid, sbuf.st_gid, strerror(errno)); 814*7c478bd9Sstevel@tonic-gate goto out; 815*7c478bd9Sstevel@tonic-gate } 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate *fp_in = fin; 818*7c478bd9Sstevel@tonic-gate *fp_out = fout; 819*7c478bd9Sstevel@tonic-gate return (0); 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate out: 822*7c478bd9Sstevel@tonic-gate if (fin != NULL) 823*7c478bd9Sstevel@tonic-gate (void) fclose(fin); 824*7c478bd9Sstevel@tonic-gate if (fout != NULL) 825*7c478bd9Sstevel@tonic-gate (void) fclose(fout); 826*7c478bd9Sstevel@tonic-gate return (-1); 827*7c478bd9Sstevel@tonic-gate } 828*7c478bd9Sstevel@tonic-gate 829*7c478bd9Sstevel@tonic-gate /* 830*7c478bd9Sstevel@tonic-gate * If the devname is a phci based name and not open-able, map it to vhci 831*7c478bd9Sstevel@tonic-gate * based name. If the devname is a vhci based name and not open-able, map it 832*7c478bd9Sstevel@tonic-gate * to phci based name. 833*7c478bd9Sstevel@tonic-gate * 834*7c478bd9Sstevel@tonic-gate * devname either a /dev link or /devices name to client device 835*7c478bd9Sstevel@tonic-gate * new_devname caller supplied buffer where the mapped device name is 836*7c478bd9Sstevel@tonic-gate * placed on return. 837*7c478bd9Sstevel@tonic-gate * len caller supplied new_devname buffer length 838*7c478bd9Sstevel@tonic-gate * devlink_flag pass 1 if requesting the /dev link to the mapped device. 839*7c478bd9Sstevel@tonic-gate * pass 0 if requesting the /devices name of the mapped device. 840*7c478bd9Sstevel@tonic-gate * 841*7c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 842*7c478bd9Sstevel@tonic-gate */ 843*7c478bd9Sstevel@tonic-gate static int 844*7c478bd9Sstevel@tonic-gate map_devname(char *devname, char *new_devname, size_t len, int devlink_flag) 845*7c478bd9Sstevel@tonic-gate { 846*7c478bd9Sstevel@tonic-gate char physname[MAXPATHLEN]; 847*7c478bd9Sstevel@tonic-gate char minor[MAXNAMELEN]; 848*7c478bd9Sstevel@tonic-gate char new_physname[MAXNAMELEN]; 849*7c478bd9Sstevel@tonic-gate 850*7c478bd9Sstevel@tonic-gate if (get_physname_minor(devname, physname, sizeof (physname), 851*7c478bd9Sstevel@tonic-gate minor, sizeof (minor)) == 0 && 852*7c478bd9Sstevel@tonic-gate canopen(devname) == 0 && 853*7c478bd9Sstevel@tonic-gate map_physname(physname, new_physname, sizeof (new_physname)) == 0) { 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate if (devlink_flag) { 856*7c478bd9Sstevel@tonic-gate if (lookup_devlink(new_physname, minor, new_devname, 857*7c478bd9Sstevel@tonic-gate len) == 0) 858*7c478bd9Sstevel@tonic-gate return (0); 859*7c478bd9Sstevel@tonic-gate } else { 860*7c478bd9Sstevel@tonic-gate (void) snprintf(new_devname, len, "/devices%s:%s", 861*7c478bd9Sstevel@tonic-gate new_physname, minor); 862*7c478bd9Sstevel@tonic-gate return (0); 863*7c478bd9Sstevel@tonic-gate } 864*7c478bd9Sstevel@tonic-gate } 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate return (-1); 867*7c478bd9Sstevel@tonic-gate } 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate /* 870*7c478bd9Sstevel@tonic-gate * Make a new /etc/vfstab: 871*7c478bd9Sstevel@tonic-gate * Read vfstab_in, convert the device name entries to appropriate vhci or phci 872*7c478bd9Sstevel@tonic-gate * based names, and write to vfstab_out. Only device names whose physical 873*7c478bd9Sstevel@tonic-gate * paths are either phci or vhci based names and not open-able are considered 874*7c478bd9Sstevel@tonic-gate * for conversion. Open-able device name entries are not converted as it 875*7c478bd9Sstevel@tonic-gate * means that the device is already accessible; hence no need to convert. 876*7c478bd9Sstevel@tonic-gate * 877*7c478bd9Sstevel@tonic-gate * Returns: 878*7c478bd9Sstevel@tonic-gate * 0 successful but vfstab_out contents are the same as vfstab_in 879*7c478bd9Sstevel@tonic-gate * 1 successful and vfstab_out changed from vfstab_in 880*7c478bd9Sstevel@tonic-gate * -1 failed 881*7c478bd9Sstevel@tonic-gate */ 882*7c478bd9Sstevel@tonic-gate static int 883*7c478bd9Sstevel@tonic-gate update_vfstab(char *vfstab_in, char *vfstab_out) 884*7c478bd9Sstevel@tonic-gate { 885*7c478bd9Sstevel@tonic-gate FILE *fp_in, *fp_out; 886*7c478bd9Sstevel@tonic-gate char *buf, *tmpbuf; 887*7c478bd9Sstevel@tonic-gate char *vfs_cache[2]; 888*7c478bd9Sstevel@tonic-gate int idx = 0, count = 0; 889*7c478bd9Sstevel@tonic-gate int rv = -1; 890*7c478bd9Sstevel@tonic-gate int vfstab_updated = 0; 891*7c478bd9Sstevel@tonic-gate int i; 892*7c478bd9Sstevel@tonic-gate char cdev[MAXPATHLEN]; 893*7c478bd9Sstevel@tonic-gate char bdev[MAXPATHLEN]; 894*7c478bd9Sstevel@tonic-gate char mntpt[MAXPATHLEN]; 895*7c478bd9Sstevel@tonic-gate char fstype[512]; 896*7c478bd9Sstevel@tonic-gate char fsckpass[512]; 897*7c478bd9Sstevel@tonic-gate char mntboot[512]; 898*7c478bd9Sstevel@tonic-gate char mntopt[MAX_MNTOPT_STR]; 899*7c478bd9Sstevel@tonic-gate char phys_bdev[MAXPATHLEN], phys_cdev[MAXPATHLEN]; 900*7c478bd9Sstevel@tonic-gate char bdev_minor[MAXNAMELEN], cdev_minor[MAXNAMELEN]; 901*7c478bd9Sstevel@tonic-gate char new_physname[MAXPATHLEN]; 902*7c478bd9Sstevel@tonic-gate char new_bdevlink[MAXPATHLEN], new_cdevlink[MAXPATHLEN]; 903*7c478bd9Sstevel@tonic-gate char fmt[80]; 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate if (open_in_out_files(vfstab_in, vfstab_out, &fp_in, &fp_out) != 0) 906*7c478bd9Sstevel@tonic-gate return (-1); 907*7c478bd9Sstevel@tonic-gate 908*7c478bd9Sstevel@tonic-gate /* 909*7c478bd9Sstevel@tonic-gate * Read one line at time from vfstab_in. If no conversion is needed 910*7c478bd9Sstevel@tonic-gate * for the line simply write the line to vfstab_out. If conversion is 911*7c478bd9Sstevel@tonic-gate * needed, first write the existing line as a comment to vfstab_out 912*7c478bd9Sstevel@tonic-gate * and then write the converted line. 913*7c478bd9Sstevel@tonic-gate * 914*7c478bd9Sstevel@tonic-gate * To avoid commented entries piling up in vfstab in case if the 915*7c478bd9Sstevel@tonic-gate * user runs stmsboot multiple times to switch on and off from mpxio, 916*7c478bd9Sstevel@tonic-gate * add the commented line only if not already there. To do this 917*7c478bd9Sstevel@tonic-gate * cache the last two vfstab lines processed and add the commented 918*7c478bd9Sstevel@tonic-gate * entry only if it is not found in the cache. We only need to cache 919*7c478bd9Sstevel@tonic-gate * the last two lines because a device can have at most two names - 920*7c478bd9Sstevel@tonic-gate * one mpxio and one non-mpxio name. Therefore for any device name 921*7c478bd9Sstevel@tonic-gate * entry we at most add two comments - one with mpxio name and one 922*7c478bd9Sstevel@tonic-gate * with non-mpxio name - no matter how many times stmsboot is run. 923*7c478bd9Sstevel@tonic-gate */ 924*7c478bd9Sstevel@tonic-gate buf = (char *)s_malloc(VFS_LINE_MAX); 925*7c478bd9Sstevel@tonic-gate tmpbuf = (char *)s_malloc(VFS_LINE_MAX); 926*7c478bd9Sstevel@tonic-gate vfs_cache[0] = (char *)s_malloc(VFS_LINE_MAX); 927*7c478bd9Sstevel@tonic-gate vfs_cache[1] = (char *)s_malloc(VFS_LINE_MAX); 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate (void) snprintf(fmt, sizeof (fmt), 930*7c478bd9Sstevel@tonic-gate "%%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds", sizeof (bdev) - 1, 931*7c478bd9Sstevel@tonic-gate sizeof (cdev) - 1, sizeof (mntpt) - 1, sizeof (fstype) - 1, 932*7c478bd9Sstevel@tonic-gate sizeof (fsckpass) - 1, sizeof (mntboot) - 1, sizeof (mntopt) - 1); 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate while (fgets(buf, VFS_LINE_MAX, fp_in) != NULL) { 935*7c478bd9Sstevel@tonic-gate if (strlen(buf) == (VFS_LINE_MAX - 1) && 936*7c478bd9Sstevel@tonic-gate buf[VFS_LINE_MAX-2] != '\n') { 937*7c478bd9Sstevel@tonic-gate logerr(gettext("%1$s line size too long, " 938*7c478bd9Sstevel@tonic-gate "exceeded %2$d: \"%3$s\"\n"), 939*7c478bd9Sstevel@tonic-gate VFSTAB, VFS_LINE_MAX - 2, buf); 940*7c478bd9Sstevel@tonic-gate goto out; 941*7c478bd9Sstevel@tonic-gate } 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate /* LINTED - format specifier */ 944*7c478bd9Sstevel@tonic-gate if ((sscanf(buf, fmt, bdev, cdev, mntpt, 945*7c478bd9Sstevel@tonic-gate fstype, fsckpass, mntboot, mntopt) != 7) || 946*7c478bd9Sstevel@tonic-gate (bdev[0] == '#') || 947*7c478bd9Sstevel@tonic-gate (get_physname_minor(bdev, phys_bdev, sizeof (phys_bdev), 948*7c478bd9Sstevel@tonic-gate bdev_minor, sizeof (bdev_minor)) != 0) || 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate (strcmp(fstype, "swap") != 0 && 951*7c478bd9Sstevel@tonic-gate ((get_physname_minor(cdev, phys_cdev, sizeof (phys_cdev), 952*7c478bd9Sstevel@tonic-gate cdev_minor, sizeof (cdev_minor)) != 0) || 953*7c478bd9Sstevel@tonic-gate (strcmp(phys_bdev, phys_cdev) != 0))) || 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate canopen(bdev) || 956*7c478bd9Sstevel@tonic-gate (map_physname(phys_bdev, new_physname, 957*7c478bd9Sstevel@tonic-gate sizeof (new_physname)) != 0) || 958*7c478bd9Sstevel@tonic-gate (lookup_devlink(new_physname, bdev_minor, new_bdevlink, 959*7c478bd9Sstevel@tonic-gate sizeof (new_bdevlink)) != 0) || 960*7c478bd9Sstevel@tonic-gate 961*7c478bd9Sstevel@tonic-gate (strcmp(fstype, "swap") != 0 && 962*7c478bd9Sstevel@tonic-gate (lookup_devlink(new_physname, cdev_minor, new_cdevlink, 963*7c478bd9Sstevel@tonic-gate sizeof (new_cdevlink)) != 0))) { 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate /* cache the last two entries */ 966*7c478bd9Sstevel@tonic-gate (void) strlcpy(vfs_cache[idx], buf, VFS_LINE_MAX); 967*7c478bd9Sstevel@tonic-gate idx = (idx == 0) ? 1 : 0; 968*7c478bd9Sstevel@tonic-gate if (count < 2) 969*7c478bd9Sstevel@tonic-gate count++; 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate if (fputs(buf, fp_out) == EOF) { 972*7c478bd9Sstevel@tonic-gate logerr(gettext("fputs \"%1$s\" to %2$s " 973*7c478bd9Sstevel@tonic-gate "failed: %3$s\n"), 974*7c478bd9Sstevel@tonic-gate buf, vfstab_out, strerror(errno)); 975*7c478bd9Sstevel@tonic-gate goto out; 976*7c478bd9Sstevel@tonic-gate } 977*7c478bd9Sstevel@tonic-gate 978*7c478bd9Sstevel@tonic-gate } else { 979*7c478bd9Sstevel@tonic-gate /* 980*7c478bd9Sstevel@tonic-gate * comment the entry in vfstab only if it is not 981*7c478bd9Sstevel@tonic-gate * already in the cache. 982*7c478bd9Sstevel@tonic-gate */ 983*7c478bd9Sstevel@tonic-gate if (client_name_type(phys_bdev) == CLIENT_TYPE_VHCI) 984*7c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, VFS_LINE_MAX, 985*7c478bd9Sstevel@tonic-gate "# mpxio: %s", buf); 986*7c478bd9Sstevel@tonic-gate else 987*7c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, VFS_LINE_MAX, 988*7c478bd9Sstevel@tonic-gate "# non-mpxio: %s", buf); 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 991*7c478bd9Sstevel@tonic-gate if (strcmp(vfs_cache[i], tmpbuf) == 0) 992*7c478bd9Sstevel@tonic-gate break; 993*7c478bd9Sstevel@tonic-gate } 994*7c478bd9Sstevel@tonic-gate 995*7c478bd9Sstevel@tonic-gate if (i == count) { 996*7c478bd9Sstevel@tonic-gate if (fputs(tmpbuf, fp_out) == EOF) { 997*7c478bd9Sstevel@tonic-gate logerr(gettext("fputs \"%1$s\" to %2$s " 998*7c478bd9Sstevel@tonic-gate "failed: %3$s\n"), tmpbuf, 999*7c478bd9Sstevel@tonic-gate vfstab_out, strerror(errno)); 1000*7c478bd9Sstevel@tonic-gate goto out; 1001*7c478bd9Sstevel@tonic-gate } 1002*7c478bd9Sstevel@tonic-gate } 1003*7c478bd9Sstevel@tonic-gate 1004*7c478bd9Sstevel@tonic-gate count = 0; 1005*7c478bd9Sstevel@tonic-gate idx = 0; 1006*7c478bd9Sstevel@tonic-gate 1007*7c478bd9Sstevel@tonic-gate if (fprintf(fp_out, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", 1008*7c478bd9Sstevel@tonic-gate new_bdevlink, 1009*7c478bd9Sstevel@tonic-gate (strcmp(fstype, "swap") != 0) ? new_cdevlink : cdev, 1010*7c478bd9Sstevel@tonic-gate mntpt, fstype, fsckpass, mntboot, mntopt) < 0) { 1011*7c478bd9Sstevel@tonic-gate logerr(gettext("fprintf failed to write to " 1012*7c478bd9Sstevel@tonic-gate "%1$s: %2$s\n"), 1013*7c478bd9Sstevel@tonic-gate vfstab_out, strerror(errno)); 1014*7c478bd9Sstevel@tonic-gate goto out; 1015*7c478bd9Sstevel@tonic-gate } 1016*7c478bd9Sstevel@tonic-gate vfstab_updated = 1; 1017*7c478bd9Sstevel@tonic-gate } 1018*7c478bd9Sstevel@tonic-gate } 1019*7c478bd9Sstevel@tonic-gate 1020*7c478bd9Sstevel@tonic-gate rv = vfstab_updated; 1021*7c478bd9Sstevel@tonic-gate out: 1022*7c478bd9Sstevel@tonic-gate (void) fclose(fp_in); 1023*7c478bd9Sstevel@tonic-gate (void) fclose(fp_out); 1024*7c478bd9Sstevel@tonic-gate free(buf); 1025*7c478bd9Sstevel@tonic-gate free(tmpbuf); 1026*7c478bd9Sstevel@tonic-gate free(vfs_cache[0]); 1027*7c478bd9Sstevel@tonic-gate free(vfs_cache[1]); 1028*7c478bd9Sstevel@tonic-gate return (rv); 1029*7c478bd9Sstevel@tonic-gate } 1030*7c478bd9Sstevel@tonic-gate 1031*7c478bd9Sstevel@tonic-gate /* 1032*7c478bd9Sstevel@tonic-gate * if guidmap is 0, list non-STMS to STMS device name mappings for the 1033*7c478bd9Sstevel@tonic-gate * specified controller. 1034*7c478bd9Sstevel@tonic-gate * if guidmap is 1, list non-STMS to GUID mappings for the specified controller. 1035*7c478bd9Sstevel@tonic-gate * If controller is -1 list mappings for all controllers. 1036*7c478bd9Sstevel@tonic-gate * 1037*7c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 1038*7c478bd9Sstevel@tonic-gate */ 1039*7c478bd9Sstevel@tonic-gate static int 1040*7c478bd9Sstevel@tonic-gate list_mappings(int controller, int guidmap) 1041*7c478bd9Sstevel@tonic-gate { 1042*7c478bd9Sstevel@tonic-gate int cnum, len, mapped; 1043*7c478bd9Sstevel@tonic-gate int header = 1; 1044*7c478bd9Sstevel@tonic-gate char *p1, *p2; 1045*7c478bd9Sstevel@tonic-gate DIR *dirp; 1046*7c478bd9Sstevel@tonic-gate struct dirent *direntry; 1047*7c478bd9Sstevel@tonic-gate char devname[MAXPATHLEN]; 1048*7c478bd9Sstevel@tonic-gate char physname[MAXPATHLEN]; 1049*7c478bd9Sstevel@tonic-gate char new_devname[MAXPATHLEN]; 1050*7c478bd9Sstevel@tonic-gate char new_physname[MAXPATHLEN]; 1051*7c478bd9Sstevel@tonic-gate char guid[MAXPATHLEN]; 1052*7c478bd9Sstevel@tonic-gate char minor[MAXNAMELEN]; 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate if ((dirp = opendir("/dev/rdsk")) == NULL) 1055*7c478bd9Sstevel@tonic-gate return (-1); 1056*7c478bd9Sstevel@tonic-gate 1057*7c478bd9Sstevel@tonic-gate while ((direntry = readdir(dirp)) != NULL) { 1058*7c478bd9Sstevel@tonic-gate if (strcmp(direntry->d_name, ".") == 0 || 1059*7c478bd9Sstevel@tonic-gate strcmp(direntry->d_name, "..") == 0 || 1060*7c478bd9Sstevel@tonic-gate (len = strlen(direntry->d_name)) < 2 || 1061*7c478bd9Sstevel@tonic-gate strcmp(direntry->d_name + len - 2, "s0") != 0 || 1062*7c478bd9Sstevel@tonic-gate sscanf(direntry->d_name, "c%dt", &cnum) != 1 || 1063*7c478bd9Sstevel@tonic-gate (controller != -1 && controller != cnum)) 1064*7c478bd9Sstevel@tonic-gate continue; 1065*7c478bd9Sstevel@tonic-gate 1066*7c478bd9Sstevel@tonic-gate (void) snprintf(devname, MAXPATHLEN, "/dev/rdsk/%s", 1067*7c478bd9Sstevel@tonic-gate direntry->d_name); 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate if (get_physname_minor(devname, physname, sizeof (physname), 1070*7c478bd9Sstevel@tonic-gate minor, sizeof (minor)) != 0 || 1071*7c478bd9Sstevel@tonic-gate client_name_type(physname) != CLIENT_TYPE_PHCI) 1072*7c478bd9Sstevel@tonic-gate continue; 1073*7c478bd9Sstevel@tonic-gate 1074*7c478bd9Sstevel@tonic-gate /* 1075*7c478bd9Sstevel@tonic-gate * First try phci_to_vhci() mapping. It will work if the 1076*7c478bd9Sstevel@tonic-gate * device is under MPxIO control. If the device is not under 1077*7c478bd9Sstevel@tonic-gate * MPxIO, phci_to_vhci() will fail in which case try to lookup 1078*7c478bd9Sstevel@tonic-gate * if an old mapping exists using guid lookup. 1079*7c478bd9Sstevel@tonic-gate */ 1080*7c478bd9Sstevel@tonic-gate mapped = 1; 1081*7c478bd9Sstevel@tonic-gate if (phci_to_vhci(physname, new_physname, 1082*7c478bd9Sstevel@tonic-gate sizeof (new_physname)) != 0) { 1083*7c478bd9Sstevel@tonic-gate if (get_guid(physname, guid, sizeof (guid), 1, 1084*7c478bd9Sstevel@tonic-gate DI_NODE_NIL) == 0) 1085*7c478bd9Sstevel@tonic-gate (void) snprintf(new_physname, MAXPATHLEN, 1086*7c478bd9Sstevel@tonic-gate "/scsi_vhci/ssd@g%s", guid); 1087*7c478bd9Sstevel@tonic-gate else 1088*7c478bd9Sstevel@tonic-gate mapped = 0; 1089*7c478bd9Sstevel@tonic-gate } 1090*7c478bd9Sstevel@tonic-gate 1091*7c478bd9Sstevel@tonic-gate if (mapped == 0) 1092*7c478bd9Sstevel@tonic-gate continue; 1093*7c478bd9Sstevel@tonic-gate 1094*7c478bd9Sstevel@tonic-gate /* strip the slice number part */ 1095*7c478bd9Sstevel@tonic-gate devname[strlen(devname) - 2] = '\0'; 1096*7c478bd9Sstevel@tonic-gate 1097*7c478bd9Sstevel@tonic-gate if (guidmap == 0) { 1098*7c478bd9Sstevel@tonic-gate if (lookup_devlink(new_physname, minor, 1099*7c478bd9Sstevel@tonic-gate new_devname, sizeof (new_devname)) != 0) 1100*7c478bd9Sstevel@tonic-gate continue; 1101*7c478bd9Sstevel@tonic-gate 1102*7c478bd9Sstevel@tonic-gate /* strip the slice number part */ 1103*7c478bd9Sstevel@tonic-gate new_devname[strlen(new_devname) - 2] = '\0'; 1104*7c478bd9Sstevel@tonic-gate 1105*7c478bd9Sstevel@tonic-gate if (header) { 1106*7c478bd9Sstevel@tonic-gate (void) printf( 1107*7c478bd9Sstevel@tonic-gate gettext("non-STMS device name\t\t\t" 1108*7c478bd9Sstevel@tonic-gate "STMS device name\n" 1109*7c478bd9Sstevel@tonic-gate "------------------------------------------" 1110*7c478bd9Sstevel@tonic-gate "------------------------\n")); 1111*7c478bd9Sstevel@tonic-gate header = 0; 1112*7c478bd9Sstevel@tonic-gate } 1113*7c478bd9Sstevel@tonic-gate (void) printf("%s\t\t%s\n", devname, new_devname); 1114*7c478bd9Sstevel@tonic-gate } else { 1115*7c478bd9Sstevel@tonic-gate /* extract guid part */ 1116*7c478bd9Sstevel@tonic-gate if ((p1 = strstr(new_physname, "ssd@g")) == NULL) { 1117*7c478bd9Sstevel@tonic-gate logdmsg("invalid vhci: %s\n", new_physname); 1118*7c478bd9Sstevel@tonic-gate continue; 1119*7c478bd9Sstevel@tonic-gate } 1120*7c478bd9Sstevel@tonic-gate p1 += sizeof ("ssd@g") - 1; 1121*7c478bd9Sstevel@tonic-gate if ((p2 = strrchr(p1, ':')) != NULL) 1122*7c478bd9Sstevel@tonic-gate *p2 = '\0'; 1123*7c478bd9Sstevel@tonic-gate 1124*7c478bd9Sstevel@tonic-gate if (header) { 1125*7c478bd9Sstevel@tonic-gate (void) printf( 1126*7c478bd9Sstevel@tonic-gate gettext("non-STMS device name\t\t\tGUID\n" 1127*7c478bd9Sstevel@tonic-gate "------------------------------------------" 1128*7c478bd9Sstevel@tonic-gate "------------------------\n")); 1129*7c478bd9Sstevel@tonic-gate header = 0; 1130*7c478bd9Sstevel@tonic-gate } 1131*7c478bd9Sstevel@tonic-gate (void) printf("%s\t\t%s\n", devname, p1); 1132*7c478bd9Sstevel@tonic-gate } 1133*7c478bd9Sstevel@tonic-gate } 1134*7c478bd9Sstevel@tonic-gate 1135*7c478bd9Sstevel@tonic-gate (void) closedir(dirp); 1136*7c478bd9Sstevel@tonic-gate return (0); 1137*7c478bd9Sstevel@tonic-gate } 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate /* 1140*7c478bd9Sstevel@tonic-gate * Check if the file can be opened. 1141*7c478bd9Sstevel@tonic-gate * 1142*7c478bd9Sstevel@tonic-gate * Return 1 if the file can be opened, 0 otherwise. 1143*7c478bd9Sstevel@tonic-gate */ 1144*7c478bd9Sstevel@tonic-gate static int 1145*7c478bd9Sstevel@tonic-gate canopen(char *filename) 1146*7c478bd9Sstevel@tonic-gate { 1147*7c478bd9Sstevel@tonic-gate int fd; 1148*7c478bd9Sstevel@tonic-gate 1149*7c478bd9Sstevel@tonic-gate if ((fd = open(filename, O_RDONLY)) == -1) 1150*7c478bd9Sstevel@tonic-gate return (0); 1151*7c478bd9Sstevel@tonic-gate 1152*7c478bd9Sstevel@tonic-gate (void) close(fd); 1153*7c478bd9Sstevel@tonic-gate return (1); 1154*7c478bd9Sstevel@tonic-gate } 1155*7c478bd9Sstevel@tonic-gate 1156*7c478bd9Sstevel@tonic-gate static void 1157*7c478bd9Sstevel@tonic-gate logerr(char *msg, ...) 1158*7c478bd9Sstevel@tonic-gate { 1159*7c478bd9Sstevel@tonic-gate va_list ap; 1160*7c478bd9Sstevel@tonic-gate 1161*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", stmsboot); 1162*7c478bd9Sstevel@tonic-gate va_start(ap, msg); 1163*7c478bd9Sstevel@tonic-gate /* LINTED - format specifier */ 1164*7c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, msg, ap); 1165*7c478bd9Sstevel@tonic-gate va_end(ap); 1166*7c478bd9Sstevel@tonic-gate } 1167*7c478bd9Sstevel@tonic-gate 1168*7c478bd9Sstevel@tonic-gate /* log debug message */ 1169*7c478bd9Sstevel@tonic-gate static void 1170*7c478bd9Sstevel@tonic-gate logdmsg(char *msg, ...) 1171*7c478bd9Sstevel@tonic-gate { 1172*7c478bd9Sstevel@tonic-gate va_list ap; 1173*7c478bd9Sstevel@tonic-gate 1174*7c478bd9Sstevel@tonic-gate if (debug) { 1175*7c478bd9Sstevel@tonic-gate va_start(ap, msg); 1176*7c478bd9Sstevel@tonic-gate /* LINTED - format specifier */ 1177*7c478bd9Sstevel@tonic-gate (void) vprintf(msg, ap); 1178*7c478bd9Sstevel@tonic-gate va_end(ap); 1179*7c478bd9Sstevel@tonic-gate } 1180*7c478bd9Sstevel@tonic-gate } 1181*7c478bd9Sstevel@tonic-gate 1182*7c478bd9Sstevel@tonic-gate static void * 1183*7c478bd9Sstevel@tonic-gate s_malloc(const size_t size) 1184*7c478bd9Sstevel@tonic-gate { 1185*7c478bd9Sstevel@tonic-gate void *rp; 1186*7c478bd9Sstevel@tonic-gate 1187*7c478bd9Sstevel@tonic-gate if ((rp = malloc(size)) == NULL) { 1188*7c478bd9Sstevel@tonic-gate logerr(gettext("malloc failed to allocate %d bytes\n"), size); 1189*7c478bd9Sstevel@tonic-gate clean_exit(1); 1190*7c478bd9Sstevel@tonic-gate } 1191*7c478bd9Sstevel@tonic-gate return (rp); 1192*7c478bd9Sstevel@tonic-gate } 1193*7c478bd9Sstevel@tonic-gate 1194*7c478bd9Sstevel@tonic-gate static char * 1195*7c478bd9Sstevel@tonic-gate s_strdup(const char *ptr) 1196*7c478bd9Sstevel@tonic-gate { 1197*7c478bd9Sstevel@tonic-gate void *rp; 1198*7c478bd9Sstevel@tonic-gate 1199*7c478bd9Sstevel@tonic-gate if ((rp = strdup(ptr)) == NULL) { 1200*7c478bd9Sstevel@tonic-gate logerr(gettext("strdup failed to dup %s\n"), ptr); 1201*7c478bd9Sstevel@tonic-gate clean_exit(1); 1202*7c478bd9Sstevel@tonic-gate } 1203*7c478bd9Sstevel@tonic-gate return (rp); 1204*7c478bd9Sstevel@tonic-gate } 1205*7c478bd9Sstevel@tonic-gate 1206*7c478bd9Sstevel@tonic-gate static void 1207*7c478bd9Sstevel@tonic-gate s_strlcpy(char *dst, const char *src, size_t dstsize) 1208*7c478bd9Sstevel@tonic-gate { 1209*7c478bd9Sstevel@tonic-gate int n; 1210*7c478bd9Sstevel@tonic-gate 1211*7c478bd9Sstevel@tonic-gate if ((n = strlcpy(dst, src, dstsize)) >= dstsize) { 1212*7c478bd9Sstevel@tonic-gate logerr(gettext("strlcpy: destination buffer size is %1$d " 1213*7c478bd9Sstevel@tonic-gate "bytes, need to at least %2$d bytes\n"), dstsize, n + 1); 1214*7c478bd9Sstevel@tonic-gate clean_exit(1); 1215*7c478bd9Sstevel@tonic-gate } 1216*7c478bd9Sstevel@tonic-gate } 1217*7c478bd9Sstevel@tonic-gate 1218*7c478bd9Sstevel@tonic-gate static void 1219*7c478bd9Sstevel@tonic-gate clean_exit(int status) 1220*7c478bd9Sstevel@tonic-gate { 1221*7c478bd9Sstevel@tonic-gate if (devinfo_root != DI_NODE_NIL) 1222*7c478bd9Sstevel@tonic-gate di_fini(devinfo_root); 1223*7c478bd9Sstevel@tonic-gate 1224*7c478bd9Sstevel@tonic-gate if (devlink_hdl != NULL) 1225*7c478bd9Sstevel@tonic-gate (void) di_devlink_fini(&devlink_hdl); 1226*7c478bd9Sstevel@tonic-gate 1227*7c478bd9Sstevel@tonic-gate if (vhci_fd != -1) 1228*7c478bd9Sstevel@tonic-gate (void) close(vhci_fd); 1229*7c478bd9Sstevel@tonic-gate 1230*7c478bd9Sstevel@tonic-gate exit(status); 1231*7c478bd9Sstevel@tonic-gate } 1232