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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*72a50065Scth * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #ifdef lint 297c478bd9Sstevel@tonic-gate #define _REENTRANT /* for localtime_r */ 307c478bd9Sstevel@tonic-gate #endif 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <stdio.h> 337c478bd9Sstevel@tonic-gate #include <ctype.h> 347c478bd9Sstevel@tonic-gate #include <stdlib.h> 357c478bd9Sstevel@tonic-gate #include <sys/types.h> 367c478bd9Sstevel@tonic-gate #include <strings.h> 377c478bd9Sstevel@tonic-gate #include <stdarg.h> 387c478bd9Sstevel@tonic-gate #include <sys/stat.h> 397c478bd9Sstevel@tonic-gate #include <fcntl.h> 407c478bd9Sstevel@tonic-gate #include <errno.h> 417c478bd9Sstevel@tonic-gate #include <unistd.h> 427c478bd9Sstevel@tonic-gate #include <stropts.h> 437c478bd9Sstevel@tonic-gate #include <time.h> 447c478bd9Sstevel@tonic-gate #include <sys/param.h> 457c478bd9Sstevel@tonic-gate #include <sys/vfstab.h> 467c478bd9Sstevel@tonic-gate #include <dirent.h> 477c478bd9Sstevel@tonic-gate #ifdef __sparc 487c478bd9Sstevel@tonic-gate #include <sys/scsi/adapters/scsi_vhci.h> 497c478bd9Sstevel@tonic-gate #include <sys/sunmdi.h> 507c478bd9Sstevel@tonic-gate #endif /* __sparc */ 517c478bd9Sstevel@tonic-gate #include "libdevinfo.h" 527c478bd9Sstevel@tonic-gate #include "device_info.h" 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #define isnewline(ch) ((ch) == '\n' || (ch) == '\r' || (ch) == '\f') 557c478bd9Sstevel@tonic-gate #define isnamechar(ch) (isalpha(ch) || isdigit(ch) || (ch) == '_' ||\ 567c478bd9Sstevel@tonic-gate (ch) == '-') 577c478bd9Sstevel@tonic-gate #define MAX_TOKEN_SIZE 1024 587c478bd9Sstevel@tonic-gate #define BUFSIZE 1024 597c478bd9Sstevel@tonic-gate #define STRVAL(s) ((s) ? (s) : "NULL") 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate #define SCSI_VHCI_CONF "/kernel/drv/scsi_vhci.conf" 627c478bd9Sstevel@tonic-gate #define QLC_CONF "/kernel/drv/qlc.conf" 637c478bd9Sstevel@tonic-gate #define FP_CONF "/kernel/drv/fp.conf" 647c478bd9Sstevel@tonic-gate #define DRIVER_CLASSES "/etc/driver_classes" 657c478bd9Sstevel@tonic-gate #define FP_AT "fp@" 667c478bd9Sstevel@tonic-gate #define VHCI_CTL_NODE "/devices/scsi_vhci:devctl" 677c478bd9Sstevel@tonic-gate #define SLASH_DEVICES "/devices" 687c478bd9Sstevel@tonic-gate #define SLASH_DEVICES_SLASH "/devices/" 697c478bd9Sstevel@tonic-gate #define SLASH_FP_AT "/fp@" 707c478bd9Sstevel@tonic-gate #define SLASH_SCSI_VHCI "/scsi_vhci" 717c478bd9Sstevel@tonic-gate #define META_DEV "/dev/md/dsk/" 727c478bd9Sstevel@tonic-gate #define SLASH_DEV_SLASH "/dev/" 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate /* 757c478bd9Sstevel@tonic-gate * Macros to produce a quoted string containing the value of a 767c478bd9Sstevel@tonic-gate * preprocessor macro. For example, if SIZE is defined to be 256, 777c478bd9Sstevel@tonic-gate * VAL2STR(SIZE) is "256". This is used to construct format 787c478bd9Sstevel@tonic-gate * strings for scanf-family functions below. 797c478bd9Sstevel@tonic-gate */ 807c478bd9Sstevel@tonic-gate #define QUOTE(x) #x 817c478bd9Sstevel@tonic-gate #define VAL2STR(x) QUOTE(x) 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate #ifdef __sparc 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate typedef enum { 867c478bd9Sstevel@tonic-gate CLIENT_TYPE_UNKNOWN, 877c478bd9Sstevel@tonic-gate CLIENT_TYPE_PHCI, 887c478bd9Sstevel@tonic-gate CLIENT_TYPE_VHCI 897c478bd9Sstevel@tonic-gate } client_type_t; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate typedef enum { 927c478bd9Sstevel@tonic-gate T_EQUALS, 937c478bd9Sstevel@tonic-gate T_AMPERSAND, 947c478bd9Sstevel@tonic-gate T_BIT_OR, 957c478bd9Sstevel@tonic-gate T_STAR, 967c478bd9Sstevel@tonic-gate T_POUND, 977c478bd9Sstevel@tonic-gate T_COLON, 987c478bd9Sstevel@tonic-gate T_SEMICOLON, 997c478bd9Sstevel@tonic-gate T_COMMA, 1007c478bd9Sstevel@tonic-gate T_SLASH, 1017c478bd9Sstevel@tonic-gate T_WHITE_SPACE, 1027c478bd9Sstevel@tonic-gate T_NEWLINE, 1037c478bd9Sstevel@tonic-gate T_EOF, 1047c478bd9Sstevel@tonic-gate T_STRING, 1057c478bd9Sstevel@tonic-gate T_HEXVAL, 1067c478bd9Sstevel@tonic-gate T_DECVAL, 1077c478bd9Sstevel@tonic-gate T_NAME 1087c478bd9Sstevel@tonic-gate } token_t; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate typedef enum { 1117c478bd9Sstevel@tonic-gate begin, parent, drvname, drvclass, prop, 1127c478bd9Sstevel@tonic-gate parent_equals, name_equals, drvclass_equals, 1137c478bd9Sstevel@tonic-gate parent_equals_string, name_equals_string, 1147c478bd9Sstevel@tonic-gate drvclass_equals_string, 1157c478bd9Sstevel@tonic-gate prop_equals, prop_equals_string, prop_equals_integer, 1167c478bd9Sstevel@tonic-gate prop_equals_string_comma, prop_equals_integer_comma 1177c478bd9Sstevel@tonic-gate } conf_state_t; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* structure to hold entries with mpxio-disable property in driver.conf file */ 1207c478bd9Sstevel@tonic-gate struct conf_entry { 1217c478bd9Sstevel@tonic-gate char *name; 1227c478bd9Sstevel@tonic-gate char *parent; 1237c478bd9Sstevel@tonic-gate char *class; 1247c478bd9Sstevel@tonic-gate char *unit_address; 1257c478bd9Sstevel@tonic-gate int port; 1267c478bd9Sstevel@tonic-gate int mpxio_disable; 1277c478bd9Sstevel@tonic-gate struct conf_entry *next; 1287c478bd9Sstevel@tonic-gate }; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate struct conf_file { 1317c478bd9Sstevel@tonic-gate char *filename; 1327c478bd9Sstevel@tonic-gate FILE *fp; 1337c478bd9Sstevel@tonic-gate int linenum; 1347c478bd9Sstevel@tonic-gate }; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate static char *tok_err = "Unexpected token '%s'\n"; 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate #endif /* __sparc */ 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /* #define DEBUG */ 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate #ifdef DEBUG 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate int devfsmap_debug = 0; 1457c478bd9Sstevel@tonic-gate /* /var/run is not mounted at install time. Therefore use /tmp */ 1467c478bd9Sstevel@tonic-gate char *devfsmap_logfile = "/tmp/devfsmap.log"; 1477c478bd9Sstevel@tonic-gate static FILE *logfp; 1487c478bd9Sstevel@tonic-gate #define logdmsg(args) log_debug_msg args 1497c478bd9Sstevel@tonic-gate static void vlog_debug_msg(char *, va_list); 1507c478bd9Sstevel@tonic-gate static void log_debug_msg(char *, ...); 1517c478bd9Sstevel@tonic-gate #ifdef __sparc 1527c478bd9Sstevel@tonic-gate static void log_confent_list(char *, struct conf_entry *, int); 1537c478bd9Sstevel@tonic-gate static void log_pathlist(char **); 1547c478bd9Sstevel@tonic-gate #endif /* __sparc */ 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate #else /* DEBUG */ 1577c478bd9Sstevel@tonic-gate #define logdmsg(args) /* nothing */ 1587c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate #ifdef __sparc 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate /* 1637c478bd9Sstevel@tonic-gate * Leave NEWLINE as the next character. 1647c478bd9Sstevel@tonic-gate */ 1657c478bd9Sstevel@tonic-gate static void 1667c478bd9Sstevel@tonic-gate find_eol(FILE *fp) 1677c478bd9Sstevel@tonic-gate { 1687c478bd9Sstevel@tonic-gate int ch; 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate while ((ch = getc(fp)) != EOF) { 1717c478bd9Sstevel@tonic-gate if (isnewline(ch)) { 1727c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 1737c478bd9Sstevel@tonic-gate break; 1747c478bd9Sstevel@tonic-gate } 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate /* ignore parsing errors */ 1797c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1807c478bd9Sstevel@tonic-gate static void 1817c478bd9Sstevel@tonic-gate file_err(struct conf_file *filep, char *fmt, ...) 1827c478bd9Sstevel@tonic-gate { 1837c478bd9Sstevel@tonic-gate #ifdef DEBUG 1847c478bd9Sstevel@tonic-gate va_list ap; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate va_start(ap, fmt); 1877c478bd9Sstevel@tonic-gate log_debug_msg("WARNING: %s line # %d: ", 1887c478bd9Sstevel@tonic-gate filep->filename, filep->linenum); 1897c478bd9Sstevel@tonic-gate vlog_debug_msg(fmt, ap); 1907c478bd9Sstevel@tonic-gate va_end(ap); 1917c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* return the next token from the given driver.conf file, or -1 on error */ 1957c478bd9Sstevel@tonic-gate static token_t 1967c478bd9Sstevel@tonic-gate lex(struct conf_file *filep, char *val, size_t size) 1977c478bd9Sstevel@tonic-gate { 1987c478bd9Sstevel@tonic-gate char *cp; 1997c478bd9Sstevel@tonic-gate int ch, oval, badquote; 2007c478bd9Sstevel@tonic-gate size_t remain; 2017c478bd9Sstevel@tonic-gate token_t token; 2027c478bd9Sstevel@tonic-gate FILE *fp = filep->fp; 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate if (size < 2) 2057c478bd9Sstevel@tonic-gate return (-1); 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate cp = val; 2087c478bd9Sstevel@tonic-gate while ((ch = getc(fp)) == ' ' || ch == '\t') 2097c478bd9Sstevel@tonic-gate ; 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate remain = size - 1; 2127c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 2137c478bd9Sstevel@tonic-gate switch (ch) { 2147c478bd9Sstevel@tonic-gate case '=': 2157c478bd9Sstevel@tonic-gate token = T_EQUALS; 2167c478bd9Sstevel@tonic-gate break; 2177c478bd9Sstevel@tonic-gate case '&': 2187c478bd9Sstevel@tonic-gate token = T_AMPERSAND; 2197c478bd9Sstevel@tonic-gate break; 2207c478bd9Sstevel@tonic-gate case '|': 2217c478bd9Sstevel@tonic-gate token = T_BIT_OR; 2227c478bd9Sstevel@tonic-gate break; 2237c478bd9Sstevel@tonic-gate case '*': 2247c478bd9Sstevel@tonic-gate token = T_STAR; 2257c478bd9Sstevel@tonic-gate break; 2267c478bd9Sstevel@tonic-gate case '#': 2277c478bd9Sstevel@tonic-gate token = T_POUND; 2287c478bd9Sstevel@tonic-gate break; 2297c478bd9Sstevel@tonic-gate case ':': 2307c478bd9Sstevel@tonic-gate token = T_COLON; 2317c478bd9Sstevel@tonic-gate break; 2327c478bd9Sstevel@tonic-gate case ';': 2337c478bd9Sstevel@tonic-gate token = T_SEMICOLON; 2347c478bd9Sstevel@tonic-gate break; 2357c478bd9Sstevel@tonic-gate case ',': 2367c478bd9Sstevel@tonic-gate token = T_COMMA; 2377c478bd9Sstevel@tonic-gate break; 2387c478bd9Sstevel@tonic-gate case '/': 2397c478bd9Sstevel@tonic-gate token = T_SLASH; 2407c478bd9Sstevel@tonic-gate break; 2417c478bd9Sstevel@tonic-gate case ' ': 2427c478bd9Sstevel@tonic-gate case '\t': 2437c478bd9Sstevel@tonic-gate case '\f': 2447c478bd9Sstevel@tonic-gate while ((ch = getc(fp)) == ' ' || 2457c478bd9Sstevel@tonic-gate ch == '\t' || ch == '\f') { 2467c478bd9Sstevel@tonic-gate if (--remain == 0) { 2477c478bd9Sstevel@tonic-gate *cp = '\0'; 2487c478bd9Sstevel@tonic-gate return (-1); 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 2537c478bd9Sstevel@tonic-gate token = T_WHITE_SPACE; 2547c478bd9Sstevel@tonic-gate break; 2557c478bd9Sstevel@tonic-gate case '\n': 2567c478bd9Sstevel@tonic-gate case '\r': 2577c478bd9Sstevel@tonic-gate token = T_NEWLINE; 2587c478bd9Sstevel@tonic-gate break; 2597c478bd9Sstevel@tonic-gate case '"': 2607c478bd9Sstevel@tonic-gate remain++; 2617c478bd9Sstevel@tonic-gate cp--; 2627c478bd9Sstevel@tonic-gate badquote = 0; 2637c478bd9Sstevel@tonic-gate while (!badquote && (ch = getc(fp)) != '"') { 2647c478bd9Sstevel@tonic-gate switch (ch) { 2657c478bd9Sstevel@tonic-gate case '\n': 2667c478bd9Sstevel@tonic-gate case EOF: 2677c478bd9Sstevel@tonic-gate file_err(filep, "Missing \"\n"); 2687c478bd9Sstevel@tonic-gate remain = size - 1; 2697c478bd9Sstevel@tonic-gate cp = val; 2707c478bd9Sstevel@tonic-gate *cp++ = '\n'; 2717c478bd9Sstevel@tonic-gate badquote = 1; 2727c478bd9Sstevel@tonic-gate /* since we consumed the newline/EOF */ 2737c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 2747c478bd9Sstevel@tonic-gate break; 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate case '\\': 2777c478bd9Sstevel@tonic-gate if (--remain == 0) { 2787c478bd9Sstevel@tonic-gate *cp = '\0'; 2797c478bd9Sstevel@tonic-gate return (-1); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate ch = (char)getc(fp); 2827c478bd9Sstevel@tonic-gate if (!isdigit(ch)) { 2837c478bd9Sstevel@tonic-gate /* escape the character */ 2847c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 2857c478bd9Sstevel@tonic-gate break; 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate oval = 0; 2887c478bd9Sstevel@tonic-gate while (ch >= '0' && ch <= '7') { 2897c478bd9Sstevel@tonic-gate ch -= '0'; 2907c478bd9Sstevel@tonic-gate oval = (oval << 3) + ch; 2917c478bd9Sstevel@tonic-gate ch = (char)getc(fp); 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 2947c478bd9Sstevel@tonic-gate /* check for character overflow? */ 2957c478bd9Sstevel@tonic-gate if (oval > 127) { 2967c478bd9Sstevel@tonic-gate file_err(filep, 2977c478bd9Sstevel@tonic-gate "Character " 2987c478bd9Sstevel@tonic-gate "overflow detected.\n"); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate *cp++ = (char)oval; 3017c478bd9Sstevel@tonic-gate break; 3027c478bd9Sstevel@tonic-gate default: 3037c478bd9Sstevel@tonic-gate if (--remain == 0) { 3047c478bd9Sstevel@tonic-gate *cp = '\0'; 3057c478bd9Sstevel@tonic-gate return (-1); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 3087c478bd9Sstevel@tonic-gate break; 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate token = T_STRING; 3127c478bd9Sstevel@tonic-gate break; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate case EOF: 3157c478bd9Sstevel@tonic-gate token = T_EOF; 3167c478bd9Sstevel@tonic-gate break; 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate default: 3197c478bd9Sstevel@tonic-gate /* 3207c478bd9Sstevel@tonic-gate * detect a lone '-' (including at the end of a line), and 3217c478bd9Sstevel@tonic-gate * identify it as a 'name' 3227c478bd9Sstevel@tonic-gate */ 3237c478bd9Sstevel@tonic-gate if (ch == '-') { 3247c478bd9Sstevel@tonic-gate if (--remain == 0) { 3257c478bd9Sstevel@tonic-gate *cp = '\0'; 3267c478bd9Sstevel@tonic-gate return (-1); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate *cp++ = (char)(ch = getc(fp)); 3297c478bd9Sstevel@tonic-gate if (ch == ' ' || ch == '\t' || ch == '\n') { 3307c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 3317c478bd9Sstevel@tonic-gate remain++; 3327c478bd9Sstevel@tonic-gate cp--; 3337c478bd9Sstevel@tonic-gate token = T_NAME; 3347c478bd9Sstevel@tonic-gate break; 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate } else if (ch == '~' || ch == '-') { 3377c478bd9Sstevel@tonic-gate if (--remain == 0) { 3387c478bd9Sstevel@tonic-gate *cp = '\0'; 3397c478bd9Sstevel@tonic-gate return (-1); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate *cp++ = (char)(ch = getc(fp)); 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate if (isdigit(ch)) { 3467c478bd9Sstevel@tonic-gate if (ch == '0') { 3477c478bd9Sstevel@tonic-gate if ((ch = getc(fp)) == 'x') { 3487c478bd9Sstevel@tonic-gate if (--remain == 0) { 3497c478bd9Sstevel@tonic-gate *cp = '\0'; 3507c478bd9Sstevel@tonic-gate return (-1); 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 3537c478bd9Sstevel@tonic-gate ch = getc(fp); 3547c478bd9Sstevel@tonic-gate while (isxdigit(ch)) { 3557c478bd9Sstevel@tonic-gate if (--remain == 0) { 3567c478bd9Sstevel@tonic-gate *cp = '\0'; 3577c478bd9Sstevel@tonic-gate return (-1); 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 3607c478bd9Sstevel@tonic-gate ch = getc(fp); 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 3637c478bd9Sstevel@tonic-gate token = T_HEXVAL; 3647c478bd9Sstevel@tonic-gate } else { 3657c478bd9Sstevel@tonic-gate goto digit; 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate } else { 3687c478bd9Sstevel@tonic-gate ch = getc(fp); 3697c478bd9Sstevel@tonic-gate digit: 3707c478bd9Sstevel@tonic-gate while (isdigit(ch)) { 3717c478bd9Sstevel@tonic-gate if (--remain == 0) { 3727c478bd9Sstevel@tonic-gate *cp = '\0'; 3737c478bd9Sstevel@tonic-gate return (-1); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 3767c478bd9Sstevel@tonic-gate ch = getc(fp); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 3797c478bd9Sstevel@tonic-gate token = T_DECVAL; 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate } else if (isalpha(ch) || ch == '\\') { 3827c478bd9Sstevel@tonic-gate if (ch != '\\') { 3837c478bd9Sstevel@tonic-gate ch = getc(fp); 3847c478bd9Sstevel@tonic-gate } else { 3857c478bd9Sstevel@tonic-gate /* 3867c478bd9Sstevel@tonic-gate * if the character was a backslash, 3877c478bd9Sstevel@tonic-gate * back up so we can overwrite it with 3887c478bd9Sstevel@tonic-gate * the next (i.e. escaped) character. 3897c478bd9Sstevel@tonic-gate */ 3907c478bd9Sstevel@tonic-gate remain++; 3917c478bd9Sstevel@tonic-gate cp--; 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate while (isnamechar(ch) || ch == '\\') { 3947c478bd9Sstevel@tonic-gate if (ch == '\\') 3957c478bd9Sstevel@tonic-gate ch = getc(fp); 3967c478bd9Sstevel@tonic-gate if (--remain == 0) { 3977c478bd9Sstevel@tonic-gate *cp = '\0'; 3987c478bd9Sstevel@tonic-gate return (-1); 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 4017c478bd9Sstevel@tonic-gate ch = getc(fp); 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 4047c478bd9Sstevel@tonic-gate token = T_NAME; 4057c478bd9Sstevel@tonic-gate } else { 4067c478bd9Sstevel@tonic-gate return (-1); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate break; 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate *cp = '\0'; 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate return (token); 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate static void 4177c478bd9Sstevel@tonic-gate free_confent(struct conf_entry *confent) 4187c478bd9Sstevel@tonic-gate { 4197c478bd9Sstevel@tonic-gate if (confent->name) 4207c478bd9Sstevel@tonic-gate free(confent->name); 4217c478bd9Sstevel@tonic-gate if (confent->parent) 4227c478bd9Sstevel@tonic-gate free(confent->parent); 4237c478bd9Sstevel@tonic-gate if (confent->class) 4247c478bd9Sstevel@tonic-gate free(confent->class); 4257c478bd9Sstevel@tonic-gate if (confent->unit_address) 4267c478bd9Sstevel@tonic-gate free(confent->unit_address); 4277c478bd9Sstevel@tonic-gate free(confent); 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate static void 4317c478bd9Sstevel@tonic-gate free_confent_list(struct conf_entry *confent_list) 4327c478bd9Sstevel@tonic-gate { 4337c478bd9Sstevel@tonic-gate struct conf_entry *confent, *next; 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate for (confent = confent_list; confent != NULL; confent = next) { 4367c478bd9Sstevel@tonic-gate next = confent->next; 4377c478bd9Sstevel@tonic-gate free_confent(confent); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate /* 4427c478bd9Sstevel@tonic-gate * Parse the next entry from the driver.conf file and return in the form of 4437c478bd9Sstevel@tonic-gate * a pointer to the conf_entry. 4447c478bd9Sstevel@tonic-gate */ 4457c478bd9Sstevel@tonic-gate static struct conf_entry * 4467c478bd9Sstevel@tonic-gate parse_conf_entry(struct conf_file *filep, char *tokbuf, size_t linesize) 4477c478bd9Sstevel@tonic-gate { 4487c478bd9Sstevel@tonic-gate char *prop_name, *string; 4497c478bd9Sstevel@tonic-gate token_t token; 4507c478bd9Sstevel@tonic-gate struct conf_entry *confent; 4517c478bd9Sstevel@tonic-gate conf_state_t state; 4527c478bd9Sstevel@tonic-gate int failed = 1; 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate if ((confent = calloc(1, sizeof (*confent))) == NULL) 4557c478bd9Sstevel@tonic-gate return (NULL); 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate confent->port = -1; 4587c478bd9Sstevel@tonic-gate confent->mpxio_disable = -1; 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate state = begin; 4617c478bd9Sstevel@tonic-gate token = T_NAME; 4627c478bd9Sstevel@tonic-gate prop_name = NULL; 4637c478bd9Sstevel@tonic-gate string = NULL; 4647c478bd9Sstevel@tonic-gate do { 4657c478bd9Sstevel@tonic-gate switch (token) { 4667c478bd9Sstevel@tonic-gate case T_NAME: 4677c478bd9Sstevel@tonic-gate switch (state) { 4687c478bd9Sstevel@tonic-gate case prop_equals_string: 4697c478bd9Sstevel@tonic-gate case prop_equals_integer: 4707c478bd9Sstevel@tonic-gate case begin: 4717c478bd9Sstevel@tonic-gate state = prop; 4727c478bd9Sstevel@tonic-gate if ((prop_name = strdup(tokbuf)) == NULL) 4737c478bd9Sstevel@tonic-gate goto bad; 4747c478bd9Sstevel@tonic-gate break; 4757c478bd9Sstevel@tonic-gate default: 4767c478bd9Sstevel@tonic-gate file_err(filep, tok_err, tokbuf); 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate break; 4797c478bd9Sstevel@tonic-gate case T_EQUALS: 4807c478bd9Sstevel@tonic-gate switch (state) { 4817c478bd9Sstevel@tonic-gate case prop: 4827c478bd9Sstevel@tonic-gate state = prop_equals; 4837c478bd9Sstevel@tonic-gate break; 4847c478bd9Sstevel@tonic-gate default: 4857c478bd9Sstevel@tonic-gate file_err(filep, tok_err, tokbuf); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate break; 4887c478bd9Sstevel@tonic-gate case T_STRING: 4897c478bd9Sstevel@tonic-gate switch (state) { 4907c478bd9Sstevel@tonic-gate case prop_equals: 4917c478bd9Sstevel@tonic-gate if ((string = strdup(tokbuf)) == NULL) 4927c478bd9Sstevel@tonic-gate goto bad; 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate state = begin; 4957c478bd9Sstevel@tonic-gate if (strcmp(prop_name, "PARENT") == 0 || 4967c478bd9Sstevel@tonic-gate strcmp(prop_name, "parent") == 0) { 4977c478bd9Sstevel@tonic-gate if (confent->parent) { 4987c478bd9Sstevel@tonic-gate file_err(filep, 4997c478bd9Sstevel@tonic-gate "'parent' property already specified\n"); 5007c478bd9Sstevel@tonic-gate goto bad; 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate confent->parent = string; 5037c478bd9Sstevel@tonic-gate } else if (strcmp(prop_name, "NAME") == 0 || 5047c478bd9Sstevel@tonic-gate strcmp(prop_name, "name") == 0) { 5057c478bd9Sstevel@tonic-gate if (confent->name) { 5067c478bd9Sstevel@tonic-gate file_err(filep, 5077c478bd9Sstevel@tonic-gate "'name' property already specified\n"); 5087c478bd9Sstevel@tonic-gate goto bad; 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate confent->name = string; 5117c478bd9Sstevel@tonic-gate } else if (strcmp(prop_name, "CLASS") == 0 || 5127c478bd9Sstevel@tonic-gate strcmp(prop_name, "class") == 0) { 5137c478bd9Sstevel@tonic-gate if (confent->class) { 5147c478bd9Sstevel@tonic-gate file_err(filep, 5157c478bd9Sstevel@tonic-gate "'class' property already specified\n"); 5167c478bd9Sstevel@tonic-gate goto bad; 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate confent->class = string; 5197c478bd9Sstevel@tonic-gate } else if (strcmp(prop_name, "unit-address") 5207c478bd9Sstevel@tonic-gate == 0) { 5217c478bd9Sstevel@tonic-gate if (confent->unit_address) { 5227c478bd9Sstevel@tonic-gate file_err(filep, 5237c478bd9Sstevel@tonic-gate "'unit-address' property already specified\n"); 5247c478bd9Sstevel@tonic-gate goto bad; 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate confent->unit_address = string; 5277c478bd9Sstevel@tonic-gate } else if (strcmp(prop_name, "mpxio-disable") 5287c478bd9Sstevel@tonic-gate == 0) { 5297c478bd9Sstevel@tonic-gate if (confent->mpxio_disable != -1) { 5307c478bd9Sstevel@tonic-gate file_err(filep, 5317c478bd9Sstevel@tonic-gate "'mpxio-disable' property already specified\n"); 5327c478bd9Sstevel@tonic-gate goto bad; 5337c478bd9Sstevel@tonic-gate } 5347c478bd9Sstevel@tonic-gate if (strcmp(string, "yes") == 0) 5357c478bd9Sstevel@tonic-gate confent->mpxio_disable = 1; 5367c478bd9Sstevel@tonic-gate else if (strcmp(string, "no") == 0) 5377c478bd9Sstevel@tonic-gate confent->mpxio_disable = 0; 5387c478bd9Sstevel@tonic-gate else { 5397c478bd9Sstevel@tonic-gate file_err(filep, 5407c478bd9Sstevel@tonic-gate "'mpxio-disable' property setting is invalid. " 5417c478bd9Sstevel@tonic-gate "The value must be either \"yes\" or \"no\"\n"); 5427c478bd9Sstevel@tonic-gate goto bad; 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate free(string); 5457c478bd9Sstevel@tonic-gate } else { 5467c478bd9Sstevel@tonic-gate free(string); 5477c478bd9Sstevel@tonic-gate state = prop_equals_string; 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate string = NULL; 5507c478bd9Sstevel@tonic-gate free(prop_name); 5517c478bd9Sstevel@tonic-gate prop_name = NULL; 5527c478bd9Sstevel@tonic-gate break; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate case prop_equals_string_comma: 5557c478bd9Sstevel@tonic-gate state = prop_equals_string; 5567c478bd9Sstevel@tonic-gate break; 5577c478bd9Sstevel@tonic-gate default: 5587c478bd9Sstevel@tonic-gate file_err(filep, tok_err, tokbuf); 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate break; 5617c478bd9Sstevel@tonic-gate case T_HEXVAL: 5627c478bd9Sstevel@tonic-gate case T_DECVAL: 5637c478bd9Sstevel@tonic-gate switch (state) { 5647c478bd9Sstevel@tonic-gate case prop_equals: 5657c478bd9Sstevel@tonic-gate if (strcmp(prop_name, "port") == 0) { 5667c478bd9Sstevel@tonic-gate if (confent->port != -1) { 5677c478bd9Sstevel@tonic-gate file_err(filep, 5687c478bd9Sstevel@tonic-gate "'port' property already specified\n"); 5697c478bd9Sstevel@tonic-gate goto bad; 5707c478bd9Sstevel@tonic-gate } 5717c478bd9Sstevel@tonic-gate confent->port = 5727c478bd9Sstevel@tonic-gate (int)strtol(tokbuf, NULL, 0); 5737c478bd9Sstevel@tonic-gate state = begin; 5747c478bd9Sstevel@tonic-gate } else 5757c478bd9Sstevel@tonic-gate state = prop_equals_integer; 5767c478bd9Sstevel@tonic-gate free(prop_name); 5777c478bd9Sstevel@tonic-gate prop_name = NULL; 5787c478bd9Sstevel@tonic-gate break; 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate case prop_equals_integer_comma: 5817c478bd9Sstevel@tonic-gate state = prop_equals_integer; 5827c478bd9Sstevel@tonic-gate break; 5837c478bd9Sstevel@tonic-gate default: 5847c478bd9Sstevel@tonic-gate file_err(filep, tok_err, tokbuf); 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate break; 5877c478bd9Sstevel@tonic-gate case T_COMMA: 5887c478bd9Sstevel@tonic-gate switch (state) { 5897c478bd9Sstevel@tonic-gate case prop_equals_string: 5907c478bd9Sstevel@tonic-gate state = prop_equals_string_comma; 5917c478bd9Sstevel@tonic-gate break; 5927c478bd9Sstevel@tonic-gate case prop_equals_integer: 5937c478bd9Sstevel@tonic-gate state = prop_equals_integer_comma; 5947c478bd9Sstevel@tonic-gate break; 5957c478bd9Sstevel@tonic-gate default: 5967c478bd9Sstevel@tonic-gate file_err(filep, tok_err, tokbuf); 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate break; 5997c478bd9Sstevel@tonic-gate case T_NEWLINE: 6007c478bd9Sstevel@tonic-gate filep->linenum++; 6017c478bd9Sstevel@tonic-gate break; 6027c478bd9Sstevel@tonic-gate case T_POUND: 6037c478bd9Sstevel@tonic-gate find_eol(filep->fp); 6047c478bd9Sstevel@tonic-gate break; 6057c478bd9Sstevel@tonic-gate case T_EOF: 6067c478bd9Sstevel@tonic-gate file_err(filep, "Unexpected EOF\n"); 6077c478bd9Sstevel@tonic-gate goto bad; 6087c478bd9Sstevel@tonic-gate default: 6097c478bd9Sstevel@tonic-gate file_err(filep, tok_err, tokbuf); 6107c478bd9Sstevel@tonic-gate goto bad; 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate } while ((token = lex(filep, tokbuf, linesize)) != T_SEMICOLON); 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate failed = 0; 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate bad: 6177c478bd9Sstevel@tonic-gate if (prop_name) 6187c478bd9Sstevel@tonic-gate free(prop_name); 6197c478bd9Sstevel@tonic-gate if (string) 6207c478bd9Sstevel@tonic-gate free(string); 6217c478bd9Sstevel@tonic-gate if (failed == 1) { 6227c478bd9Sstevel@tonic-gate free_confent(confent); 6237c478bd9Sstevel@tonic-gate return (NULL); 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate return (confent); 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate /* 6297c478bd9Sstevel@tonic-gate * Parse all entries with mpxio-disable property in the given driver.conf 6307c478bd9Sstevel@tonic-gate * file. 6317c478bd9Sstevel@tonic-gate * 6327c478bd9Sstevel@tonic-gate * fname driver.conf file name 6337c478bd9Sstevel@tonic-gate * confent_list on return *confent_list will contain the list of 6347c478bd9Sstevel@tonic-gate * driver.conf file entries with mpxio-disable property. 6357c478bd9Sstevel@tonic-gate * mpxio_disable on return *mpxio_disable is set to the setting of the 6367c478bd9Sstevel@tonic-gate * driver global mpxio-dissable property as follows. 6377c478bd9Sstevel@tonic-gate * 0 if driver mpxio-disable="no" 6387c478bd9Sstevel@tonic-gate * 1 if driver mpxio-disable="yes" 6397c478bd9Sstevel@tonic-gate * -1 if driver mpxio-disable property isn't specified. 6407c478bd9Sstevel@tonic-gate */ 6417c478bd9Sstevel@tonic-gate static void 6427c478bd9Sstevel@tonic-gate parse_conf_file(char *fname, struct conf_entry **confent_list, 6437c478bd9Sstevel@tonic-gate int *mpxio_disable) 6447c478bd9Sstevel@tonic-gate { 6457c478bd9Sstevel@tonic-gate struct conf_entry *confent, *tail = NULL; 6467c478bd9Sstevel@tonic-gate token_t token; 6477c478bd9Sstevel@tonic-gate struct conf_file file; 6487c478bd9Sstevel@tonic-gate char tokval[MAX_TOKEN_SIZE]; 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate *confent_list = NULL; 6517c478bd9Sstevel@tonic-gate *mpxio_disable = -1; 6527c478bd9Sstevel@tonic-gate if ((file.fp = fopen(fname, "r")) == NULL) 6537c478bd9Sstevel@tonic-gate return; 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate file.filename = fname; 6567c478bd9Sstevel@tonic-gate file.linenum = 1; 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate while ((token = lex(&file, tokval, MAX_TOKEN_SIZE)) != T_EOF) { 6597c478bd9Sstevel@tonic-gate switch (token) { 6607c478bd9Sstevel@tonic-gate case T_POUND: 6617c478bd9Sstevel@tonic-gate /* 6627c478bd9Sstevel@tonic-gate * Skip comments. 6637c478bd9Sstevel@tonic-gate */ 6647c478bd9Sstevel@tonic-gate find_eol(file.fp); 6657c478bd9Sstevel@tonic-gate break; 6667c478bd9Sstevel@tonic-gate case T_NAME: 6677c478bd9Sstevel@tonic-gate if ((confent = parse_conf_entry(&file, tokval, 6687c478bd9Sstevel@tonic-gate MAX_TOKEN_SIZE)) == NULL) 6697c478bd9Sstevel@tonic-gate break; 6707c478bd9Sstevel@tonic-gate /* 6717c478bd9Sstevel@tonic-gate * No name indicates global property. 6727c478bd9Sstevel@tonic-gate * Make sure parent and class not NULL. 6737c478bd9Sstevel@tonic-gate */ 6747c478bd9Sstevel@tonic-gate if (confent->name == NULL) { 6757c478bd9Sstevel@tonic-gate if (confent->parent || 6767c478bd9Sstevel@tonic-gate confent->class) { 6777c478bd9Sstevel@tonic-gate file_err(&file, 6787c478bd9Sstevel@tonic-gate "missing name attribute\n"); 6797c478bd9Sstevel@tonic-gate } else if (confent->mpxio_disable != -1) { 6807c478bd9Sstevel@tonic-gate if (*mpxio_disable == -1) 6817c478bd9Sstevel@tonic-gate *mpxio_disable = 6827c478bd9Sstevel@tonic-gate confent->mpxio_disable; 6837c478bd9Sstevel@tonic-gate else 6847c478bd9Sstevel@tonic-gate file_err(&file, 6857c478bd9Sstevel@tonic-gate "'mpxio-disable' property already specified\n"); 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate free_confent(confent); 6887c478bd9Sstevel@tonic-gate break; 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate /* 6927c478bd9Sstevel@tonic-gate * This is a node spec, either parent or class 6937c478bd9Sstevel@tonic-gate * must be specified. 6947c478bd9Sstevel@tonic-gate */ 6957c478bd9Sstevel@tonic-gate if (confent->parent == NULL && confent->class == NULL) { 6967c478bd9Sstevel@tonic-gate file_err(&file, 6977c478bd9Sstevel@tonic-gate "missing parent or class attribute\n"); 6987c478bd9Sstevel@tonic-gate free_confent(confent); 6997c478bd9Sstevel@tonic-gate break; 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate /* only need entries with mpxio_disable property */ 7037c478bd9Sstevel@tonic-gate if (confent->mpxio_disable == -1) { 7047c478bd9Sstevel@tonic-gate free_confent(confent); 7057c478bd9Sstevel@tonic-gate break; 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate if (tail) 7097c478bd9Sstevel@tonic-gate tail->next = confent; 7107c478bd9Sstevel@tonic-gate else 7117c478bd9Sstevel@tonic-gate *confent_list = confent; 7127c478bd9Sstevel@tonic-gate tail = confent; 7137c478bd9Sstevel@tonic-gate break; 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate case T_NEWLINE: 7167c478bd9Sstevel@tonic-gate file.linenum++; 7177c478bd9Sstevel@tonic-gate break; 7187c478bd9Sstevel@tonic-gate default: 7197c478bd9Sstevel@tonic-gate break; 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate (void) fclose(file.fp); 7247c478bd9Sstevel@tonic-gate } 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate /* 7277c478bd9Sstevel@tonic-gate * Return the driver class of the given driver_name. 7287c478bd9Sstevel@tonic-gate * The memory for the driver class is allocated by this function and the 7297c478bd9Sstevel@tonic-gate * caller must free it. 7307c478bd9Sstevel@tonic-gate */ 7317c478bd9Sstevel@tonic-gate static char * 7327c478bd9Sstevel@tonic-gate get_driver_class(char *rootdir, char *driver_name) 7337c478bd9Sstevel@tonic-gate { 7347c478bd9Sstevel@tonic-gate FILE *fp; 7357c478bd9Sstevel@tonic-gate char buf[BUFSIZE]; 7367c478bd9Sstevel@tonic-gate char driver[BUFSIZE]; 7377c478bd9Sstevel@tonic-gate char class_name[BUFSIZE]; 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate logdmsg(("get_driver_class: rootdir = %s, driver name = %s\n", 7407c478bd9Sstevel@tonic-gate rootdir, driver_name)); 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s%s", rootdir, DRIVER_CLASSES); 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate if ((fp = fopen(buf, "r")) == NULL) { 7457c478bd9Sstevel@tonic-gate logdmsg(("get_driver_class: failed to open %s: %s\n", 7467c478bd9Sstevel@tonic-gate buf, strerror(errno))); 7477c478bd9Sstevel@tonic-gate return (NULL); 7487c478bd9Sstevel@tonic-gate } 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate while (fgets(buf, sizeof (buf), fp) != NULL) { 7517c478bd9Sstevel@tonic-gate /* LINTED - unbounded string specifier */ 7527c478bd9Sstevel@tonic-gate if ((sscanf(buf, "%s %s", driver, class_name) == 2) && 7537c478bd9Sstevel@tonic-gate driver[0] != '#' && strcmp(driver, driver_name) == 0) { 7547c478bd9Sstevel@tonic-gate logdmsg(("get_driver_class: driver class = %s\n", 7557c478bd9Sstevel@tonic-gate class_name)); 7567c478bd9Sstevel@tonic-gate (void) fclose(fp); 7577c478bd9Sstevel@tonic-gate return (strdup(class_name)); 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate } 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate (void) fclose(fp); 7627c478bd9Sstevel@tonic-gate return (NULL); 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate static int 7667c478bd9Sstevel@tonic-gate lookup_in_confent_list(struct conf_entry *confent_list, 7677c478bd9Sstevel@tonic-gate int match_class, char *parent, char *unit_addr, int port) 7687c478bd9Sstevel@tonic-gate { 7697c478bd9Sstevel@tonic-gate struct conf_entry *confent; 7707c478bd9Sstevel@tonic-gate char *par; 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate logdmsg(("lookup_in_confent_list: %s = \"%s\", unit_addr = \"%s\", " 7737c478bd9Sstevel@tonic-gate "port = %d\n", (match_class) ? "class" : "parent", parent, 7747c478bd9Sstevel@tonic-gate STRVAL(unit_addr), port)); 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate for (confent = confent_list; confent != NULL; confent = confent->next) { 7777c478bd9Sstevel@tonic-gate par = (match_class) ? confent->class : confent->parent; 7787c478bd9Sstevel@tonic-gate if (unit_addr) { 7797c478bd9Sstevel@tonic-gate if (confent->unit_address != NULL && 7807c478bd9Sstevel@tonic-gate strcmp(confent->unit_address, unit_addr) == 0 && 7817c478bd9Sstevel@tonic-gate par != NULL && strcmp(par, parent) == 0) 7827c478bd9Sstevel@tonic-gate return (confent->mpxio_disable); 7837c478bd9Sstevel@tonic-gate } else { 7847c478bd9Sstevel@tonic-gate if (confent->port == port && 7857c478bd9Sstevel@tonic-gate par != NULL && strcmp(par, parent) == 0) 7867c478bd9Sstevel@tonic-gate return (confent->mpxio_disable); 7877c478bd9Sstevel@tonic-gate } 7887c478bd9Sstevel@tonic-gate } 7897c478bd9Sstevel@tonic-gate return (-1); 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate /* 7937c478bd9Sstevel@tonic-gate * lookup mpxio-disabled property setting for the given path in the given 7947c478bd9Sstevel@tonic-gate * driver.conf file. Match the entries from most specific to least specific. 7957c478bd9Sstevel@tonic-gate * 7967c478bd9Sstevel@tonic-gate * conf_file the path name of either fp.conf, qlc.conf or scsi_vhci.conf 7977c478bd9Sstevel@tonic-gate * path /devices node path without the /devices prefix. 7987c478bd9Sstevel@tonic-gate * If the conf_file is fp.conf, path must be a fp node path 7997c478bd9Sstevel@tonic-gate * if the conf_file is qlc.conf, path must be a qlc node path. 8007c478bd9Sstevel@tonic-gate * if the conf_file is scsi_vhci.conf, path must be NULL. 8017c478bd9Sstevel@tonic-gate * ex: /pci@8,600000/SUNW,qlc@4/fp@0,0 8027c478bd9Sstevel@tonic-gate * /pci@8,600000/SUNW,qlc@4 8037c478bd9Sstevel@tonic-gate * 8047c478bd9Sstevel@tonic-gate * returns: 8057c478bd9Sstevel@tonic-gate * 0 if mpxio-disable="no" 8067c478bd9Sstevel@tonic-gate * 1 if mpxio-disable="yes" 8077c478bd9Sstevel@tonic-gate * -1 if mpxio-disable property isn't specified. 8087c478bd9Sstevel@tonic-gate */ 8097c478bd9Sstevel@tonic-gate static int 8107c478bd9Sstevel@tonic-gate lookup_in_conf_file(char *rootdir, char *conf_file, char *path) 8117c478bd9Sstevel@tonic-gate { 8127c478bd9Sstevel@tonic-gate struct conf_entry *confent_list = NULL; 8137c478bd9Sstevel@tonic-gate int mpxio_disable; 8147c478bd9Sstevel@tonic-gate di_node_t par_node = DI_NODE_NIL; 8157c478bd9Sstevel@tonic-gate char *node_name = NULL, *node_addr = NULL; 8167c478bd9Sstevel@tonic-gate char *unit_addr = NULL; 8177c478bd9Sstevel@tonic-gate int port = -1; 8187c478bd9Sstevel@tonic-gate char *par_node_name = NULL, *par_node_addr = NULL; 8197c478bd9Sstevel@tonic-gate char *par_binding_name = NULL, *par_driver_name = NULL; 8207c478bd9Sstevel@tonic-gate char *par_driver_class = NULL, *par_node_name_addr; 8217c478bd9Sstevel@tonic-gate int rv = -1; 8227c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate logdmsg(("lookup_in_conf_file: rootdir = \"%s\", conf_file = \"%s\", " 8257c478bd9Sstevel@tonic-gate "path = \"%s\"\n", rootdir, conf_file, STRVAL(path))); 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, "%s%s", rootdir, conf_file); 8287c478bd9Sstevel@tonic-gate parse_conf_file(buf, &confent_list, &mpxio_disable); 8297c478bd9Sstevel@tonic-gate #ifdef DEBUG 8307c478bd9Sstevel@tonic-gate log_confent_list(buf, confent_list, mpxio_disable); 8317c478bd9Sstevel@tonic-gate #endif 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate /* if path is NULL, return driver global mpxio-disable setting */ 8347c478bd9Sstevel@tonic-gate if (path == NULL) { 8357c478bd9Sstevel@tonic-gate rv = mpxio_disable; 8367c478bd9Sstevel@tonic-gate goto done; 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate if ((node_name = strrchr(path, '/')) == NULL) 8407c478bd9Sstevel@tonic-gate goto done; 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate *node_name = '\0'; 8437c478bd9Sstevel@tonic-gate node_name++; 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate if ((node_addr = strchr(node_name, '@')) == NULL) 8467c478bd9Sstevel@tonic-gate goto done; 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate *node_addr = '\0'; 8497c478bd9Sstevel@tonic-gate node_addr++; 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate if (strcmp(node_name, "fp") == 0) { 8527c478bd9Sstevel@tonic-gate /* get port number; encoded in the node addr as a hex number */ 8537c478bd9Sstevel@tonic-gate port = (int)strtol(node_addr, NULL, 16); 8547c478bd9Sstevel@tonic-gate } else 8557c478bd9Sstevel@tonic-gate unit_addr = node_addr; 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate /* 8587c478bd9Sstevel@tonic-gate * Match from most specific to least specific; 8597c478bd9Sstevel@tonic-gate * first, start the lookup based on full path. 8607c478bd9Sstevel@tonic-gate */ 8617c478bd9Sstevel@tonic-gate if ((rv = lookup_in_confent_list(confent_list, 0, path, 8627c478bd9Sstevel@tonic-gate unit_addr, port)) != -1) 8637c478bd9Sstevel@tonic-gate goto done; 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate /* lookup nodename@address */ 8667c478bd9Sstevel@tonic-gate if ((par_node_name_addr = strrchr(path, '/')) != NULL) { 8677c478bd9Sstevel@tonic-gate par_node_name_addr++; 8687c478bd9Sstevel@tonic-gate if ((rv = lookup_in_confent_list(confent_list, 0, 8697c478bd9Sstevel@tonic-gate par_node_name_addr, unit_addr, port)) != -1) 8707c478bd9Sstevel@tonic-gate goto done; 8717c478bd9Sstevel@tonic-gate } 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate /* di_init() doesn't work when 0 is passed in flags */ 8747c478bd9Sstevel@tonic-gate par_node = di_init(path, DINFOMINOR); 8757c478bd9Sstevel@tonic-gate if (par_node != DI_NODE_NIL) { 8767c478bd9Sstevel@tonic-gate par_node_name = di_node_name(par_node); 8777c478bd9Sstevel@tonic-gate par_node_addr = di_bus_addr(par_node); 8787c478bd9Sstevel@tonic-gate par_binding_name = di_binding_name(par_node); 8797c478bd9Sstevel@tonic-gate par_driver_name = di_driver_name(par_node); 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate logdmsg(("par_node_name = %s\n", STRVAL(par_node_name))); 8837c478bd9Sstevel@tonic-gate logdmsg(("par_node_addr = %s\n", STRVAL(par_node_addr))); 8847c478bd9Sstevel@tonic-gate logdmsg(("par_binding_name = %s\n", STRVAL(par_binding_name))); 8857c478bd9Sstevel@tonic-gate logdmsg(("par_driver_name = %s\n", STRVAL(par_driver_name))); 8867c478bd9Sstevel@tonic-gate 8877c478bd9Sstevel@tonic-gate /* lookup bindingname@address */ 8887c478bd9Sstevel@tonic-gate if (par_binding_name != NULL && par_binding_name != par_node_name && 8897c478bd9Sstevel@tonic-gate par_node_addr != NULL) { 8907c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s@%s", par_binding_name, 8917c478bd9Sstevel@tonic-gate par_node_addr); 8927c478bd9Sstevel@tonic-gate if ((rv = lookup_in_confent_list(confent_list, 0, 8937c478bd9Sstevel@tonic-gate buf, unit_addr, port)) != -1) 8947c478bd9Sstevel@tonic-gate goto done; 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate /* lookup binding name */ 8987c478bd9Sstevel@tonic-gate if (par_binding_name != NULL) { 8997c478bd9Sstevel@tonic-gate if ((rv = lookup_in_confent_list(confent_list, 0, 9007c478bd9Sstevel@tonic-gate par_binding_name, unit_addr, port)) != -1) 9017c478bd9Sstevel@tonic-gate goto done; 9027c478bd9Sstevel@tonic-gate } 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate if (par_driver_name != NULL) { 9057c478bd9Sstevel@tonic-gate /* lookup driver name */ 9067c478bd9Sstevel@tonic-gate if ((rv = lookup_in_confent_list(confent_list, 0, 9077c478bd9Sstevel@tonic-gate par_driver_name, unit_addr, port)) != -1) 9087c478bd9Sstevel@tonic-gate goto done; 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate /* finally, lookup class name */ 9117c478bd9Sstevel@tonic-gate par_driver_class = get_driver_class(rootdir, par_driver_name); 9127c478bd9Sstevel@tonic-gate if (par_driver_class != NULL) { 9137c478bd9Sstevel@tonic-gate if ((rv = lookup_in_confent_list(confent_list, 1, 9147c478bd9Sstevel@tonic-gate par_driver_class, unit_addr, port)) != -1) 9157c478bd9Sstevel@tonic-gate goto done; 9167c478bd9Sstevel@tonic-gate } 9177c478bd9Sstevel@tonic-gate } 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate /* 9207c478bd9Sstevel@tonic-gate * no match so far; 9217c478bd9Sstevel@tonic-gate * use the driver global mpxio-disable setting if exists. 9227c478bd9Sstevel@tonic-gate */ 9237c478bd9Sstevel@tonic-gate rv = mpxio_disable; 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate done: 9267c478bd9Sstevel@tonic-gate if (node_name != NULL) 9277c478bd9Sstevel@tonic-gate *(node_name - 1) = '/'; 9287c478bd9Sstevel@tonic-gate if (node_addr != NULL) 9297c478bd9Sstevel@tonic-gate *(node_addr - 1) = '@'; 9307c478bd9Sstevel@tonic-gate if (par_driver_class != NULL) 9317c478bd9Sstevel@tonic-gate free(par_driver_class); 9327c478bd9Sstevel@tonic-gate if (confent_list != NULL) 9337c478bd9Sstevel@tonic-gate free_confent_list(confent_list); 9347c478bd9Sstevel@tonic-gate if (par_node != DI_NODE_NIL) 9357c478bd9Sstevel@tonic-gate di_fini(par_node); 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate return (rv); 9387c478bd9Sstevel@tonic-gate } 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate /* 9417c478bd9Sstevel@tonic-gate * Given client_name return whether it is a phci or vhci based name. 9427c478bd9Sstevel@tonic-gate * client_name is /devices name of a client without the /devices prefix. 9437c478bd9Sstevel@tonic-gate * 9447c478bd9Sstevel@tonic-gate * client_name Return value 9457c478bd9Sstevel@tonic-gate * .../fp@xxx/ssd@yyy CLIENT_TYPE_PHCI 9467c478bd9Sstevel@tonic-gate * .../scsi_vhci/ssd@yyy CLIENT_TYPE_VHCI 9477c478bd9Sstevel@tonic-gate * other CLIENT_TYPE_UNKNOWN 9487c478bd9Sstevel@tonic-gate */ 9497c478bd9Sstevel@tonic-gate static client_type_t 9507c478bd9Sstevel@tonic-gate client_name_type(char *client_name) 9517c478bd9Sstevel@tonic-gate { 9527c478bd9Sstevel@tonic-gate client_type_t client_type; 9537c478bd9Sstevel@tonic-gate char *p1, *p2; 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate logdmsg(("client_name_type: client_name = %s\n", client_name)); 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate if (strncmp(client_name, SLASH_SCSI_VHCI, 9587c478bd9Sstevel@tonic-gate sizeof (SLASH_SCSI_VHCI) - 1) == 0) 9597c478bd9Sstevel@tonic-gate return (CLIENT_TYPE_VHCI); 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate if (*client_name != '/') 9627c478bd9Sstevel@tonic-gate return (CLIENT_TYPE_UNKNOWN); 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate if ((p1 = strrchr(client_name, '/')) == NULL) 9657c478bd9Sstevel@tonic-gate return (CLIENT_TYPE_UNKNOWN); 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate *p1 = '\0'; 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate if ((p2 = strrchr(client_name, '/')) != NULL && 9707c478bd9Sstevel@tonic-gate strncmp(p2, SLASH_FP_AT, sizeof (SLASH_FP_AT) - 1) == 0) 9717c478bd9Sstevel@tonic-gate client_type = CLIENT_TYPE_PHCI; 9727c478bd9Sstevel@tonic-gate else 9737c478bd9Sstevel@tonic-gate client_type = CLIENT_TYPE_UNKNOWN; 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate *p1 = '/'; 9767c478bd9Sstevel@tonic-gate return (client_type); 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate /* 9807c478bd9Sstevel@tonic-gate * Compare controller name portion of dev1 and dev2. 9817c478bd9Sstevel@tonic-gate * 9827c478bd9Sstevel@tonic-gate * rootdir root directory of the target environment 9837c478bd9Sstevel@tonic-gate * dev1 can be either a /dev link or /devices name in the target 9847c478bd9Sstevel@tonic-gate * environemnt 9857c478bd9Sstevel@tonic-gate * dev2 /devices name of a device without the /devices prefix 9867c478bd9Sstevel@tonic-gate * 9877c478bd9Sstevel@tonic-gate * Returns: 9887c478bd9Sstevel@tonic-gate * 0 if controller names match 9897c478bd9Sstevel@tonic-gate * 1 if controller names don't match 9907c478bd9Sstevel@tonic-gate * -1 an error occurred. 9917c478bd9Sstevel@tonic-gate */ 9927c478bd9Sstevel@tonic-gate static int 9937c478bd9Sstevel@tonic-gate compare_controller(char *rootdir, char *dev1, char *dev2) 9947c478bd9Sstevel@tonic-gate { 9957c478bd9Sstevel@tonic-gate int linksize; 9967c478bd9Sstevel@tonic-gate char *p1, *p; 9977c478bd9Sstevel@tonic-gate char physdev1[MAXPATHLEN]; 9987c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate logdmsg(("compare_controller: rootdir = %s, dev1 = %s, dev2 = %s\n", 10017c478bd9Sstevel@tonic-gate rootdir, dev1, dev2)); 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate if (strncmp(dev1, SLASH_DEV_SLASH, sizeof (SLASH_DEV_SLASH) - 1) 10047c478bd9Sstevel@tonic-gate == 0) { 10057c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, "%s%s", rootdir, dev1); 10067c478bd9Sstevel@tonic-gate if ((linksize = readlink(buf, physdev1, MAXPATHLEN)) > 0 && 10077c478bd9Sstevel@tonic-gate linksize < (MAXPATHLEN - 1)) { 10087c478bd9Sstevel@tonic-gate physdev1[linksize] = '\0'; 10097c478bd9Sstevel@tonic-gate logdmsg(("compare_controller: physdev1 = %s\n", 10107c478bd9Sstevel@tonic-gate physdev1)); 10117c478bd9Sstevel@tonic-gate } else 10127c478bd9Sstevel@tonic-gate return (-1); 10137c478bd9Sstevel@tonic-gate } else 10147c478bd9Sstevel@tonic-gate (void) strlcpy(physdev1, dev1, MAXPATHLEN); 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate if ((p1 = strstr(physdev1, SLASH_DEVICES)) == NULL) 10177c478bd9Sstevel@tonic-gate return (-1); 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate p1 += sizeof (SLASH_DEVICES) - 1; 10207c478bd9Sstevel@tonic-gate /* strip the device portion */ 10217c478bd9Sstevel@tonic-gate if ((p = strrchr(p1, '/')) == NULL) 10227c478bd9Sstevel@tonic-gate return (-1); 10237c478bd9Sstevel@tonic-gate *p = '\0'; 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate if ((p = strrchr(dev2, '/')) == NULL) 10267c478bd9Sstevel@tonic-gate return (-1); 10277c478bd9Sstevel@tonic-gate *p = '\0'; 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate logdmsg(("compare_controller: path1 = %s, path2 = %s\n", 10307c478bd9Sstevel@tonic-gate p1, dev2)); 10317c478bd9Sstevel@tonic-gate if (strcmp(p1, dev2) == 0) { 10327c478bd9Sstevel@tonic-gate *p = '/'; 10337c478bd9Sstevel@tonic-gate return (0); 10347c478bd9Sstevel@tonic-gate } else { 10357c478bd9Sstevel@tonic-gate *p = '/'; 10367c478bd9Sstevel@tonic-gate return (1); 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate /* 10417c478bd9Sstevel@tonic-gate * Check if the specified device path is on the root controller. 10427c478bd9Sstevel@tonic-gate * 10437c478bd9Sstevel@tonic-gate * rootdir root directory of the target environment 10447c478bd9Sstevel@tonic-gate * path /devices name of a device without the /devices prefix 10457c478bd9Sstevel@tonic-gate * 10467c478bd9Sstevel@tonic-gate * Returns 10477c478bd9Sstevel@tonic-gate * 1 if the path is on the root controller 10487c478bd9Sstevel@tonic-gate * 0 if the path is not on the root controller 10497c478bd9Sstevel@tonic-gate * -1 if an error occurs 10507c478bd9Sstevel@tonic-gate */ 10517c478bd9Sstevel@tonic-gate static int 10527c478bd9Sstevel@tonic-gate is_root_controller(char *rootdir, char *path) 10537c478bd9Sstevel@tonic-gate { 10547c478bd9Sstevel@tonic-gate FILE *fp; 10557c478bd9Sstevel@tonic-gate char *tmpfile; 10567c478bd9Sstevel@tonic-gate int rv = -1; 10577c478bd9Sstevel@tonic-gate struct vfstab vfsent; 10587c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 10597c478bd9Sstevel@tonic-gate char ctd[MAXNAMELEN + 1]; 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate logdmsg(("is_root_controller: rootdir = %s, path = %s\n", rootdir, 10627c478bd9Sstevel@tonic-gate path)); 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, "%s%s", rootdir, VFSTAB); 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate if ((fp = fopen(buf, "r")) == NULL) { 10677c478bd9Sstevel@tonic-gate logdmsg(("is_root_controller: failed to open %s: %s\n", 10687c478bd9Sstevel@tonic-gate buf, strerror(errno))); 10697c478bd9Sstevel@tonic-gate return (-1); 10707c478bd9Sstevel@tonic-gate } 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate if (getvfsfile(fp, &vfsent, "/") != 0) { 10737c478bd9Sstevel@tonic-gate logdmsg(("is_root_controller: getvfsfile: failed to read " 10747c478bd9Sstevel@tonic-gate "vfstab entry for mount point \"/\": %s\n", 10757c478bd9Sstevel@tonic-gate strerror(errno))); 10767c478bd9Sstevel@tonic-gate (void) fclose(fp); 10777c478bd9Sstevel@tonic-gate return (-1); 10787c478bd9Sstevel@tonic-gate } 10797c478bd9Sstevel@tonic-gate (void) fclose(fp); 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate /* check if the root is an svm metadisk */ 10827c478bd9Sstevel@tonic-gate if (strncmp(vfsent.vfs_special, META_DEV, sizeof (META_DEV) - 1) != 0) { 10837c478bd9Sstevel@tonic-gate if (compare_controller(rootdir, vfsent.vfs_special, path) == 0) 10847c478bd9Sstevel@tonic-gate return (1); 10857c478bd9Sstevel@tonic-gate else 10867c478bd9Sstevel@tonic-gate return (0); 10877c478bd9Sstevel@tonic-gate } 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate /* Don't use /var/run as it is not mounted in miniroot */ 10907c478bd9Sstevel@tonic-gate if ((tmpfile = tempnam("/tmp", "diirc")) == NULL) { 10917c478bd9Sstevel@tonic-gate logdmsg(("is_root_controller: tempnam: failed: %s\n", 10927c478bd9Sstevel@tonic-gate strerror(errno))); 10937c478bd9Sstevel@tonic-gate return (-1); 10947c478bd9Sstevel@tonic-gate } 10957c478bd9Sstevel@tonic-gate 10967c478bd9Sstevel@tonic-gate /* get metadisk components using metastat command */ 10977c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, 10987c478bd9Sstevel@tonic-gate "/usr/sbin/metastat -p %s 2>/dev/null | " 10997c478bd9Sstevel@tonic-gate "/usr/bin/grep ' 1 1 ' | " 11007c478bd9Sstevel@tonic-gate "/usr/bin/sed -e 's/^.* 1 1 //' | " 11017c478bd9Sstevel@tonic-gate "/usr/bin/cut -f1 -d ' ' > %s", 11027c478bd9Sstevel@tonic-gate vfsent.vfs_special + sizeof (META_DEV) - 1, tmpfile); 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate logdmsg(("is_root_controller: command = %s\n", buf)); 11057c478bd9Sstevel@tonic-gate fp = NULL; 11067c478bd9Sstevel@tonic-gate if (system(buf) == 0 && (fp = fopen(tmpfile, "r")) != NULL) { 11077c478bd9Sstevel@tonic-gate while (fscanf(fp, "%" VAL2STR(MAXNAMELEN) "s", ctd) == 1) { 11087c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, "/dev/dsk/%s", ctd); 11097c478bd9Sstevel@tonic-gate if (compare_controller(rootdir, buf, path) == 0) { 11107c478bd9Sstevel@tonic-gate rv = 1; 11117c478bd9Sstevel@tonic-gate goto out; 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate rv = 0; 11157c478bd9Sstevel@tonic-gate } 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate out: 11187c478bd9Sstevel@tonic-gate if (fp) 11197c478bd9Sstevel@tonic-gate (void) fclose(fp); 11207c478bd9Sstevel@tonic-gate (void) unlink(tmpfile); 11217c478bd9Sstevel@tonic-gate free(tmpfile); 11227c478bd9Sstevel@tonic-gate return (rv); 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate static int 11267c478bd9Sstevel@tonic-gate file_exists(char *rootdir, char *path) 11277c478bd9Sstevel@tonic-gate { 11287c478bd9Sstevel@tonic-gate struct stat stbuf; 11297c478bd9Sstevel@tonic-gate char fullpath[MAXPATHLEN]; 11307c478bd9Sstevel@tonic-gate int x; 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate (void) snprintf(fullpath, MAXPATHLEN, "%s%s", rootdir, path); 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate x = stat(fullpath, &stbuf); 11357c478bd9Sstevel@tonic-gate logdmsg(("file_exists: %s: %s\n", fullpath, (x == 0) ? "yes" : "no")); 11367c478bd9Sstevel@tonic-gate if (x == 0) 11377c478bd9Sstevel@tonic-gate return (1); 11387c478bd9Sstevel@tonic-gate else 11397c478bd9Sstevel@tonic-gate return (0); 11407c478bd9Sstevel@tonic-gate } 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate /* 11437c478bd9Sstevel@tonic-gate * Check if mpxio is enabled or disabled on the specified device path. 11447c478bd9Sstevel@tonic-gate * Looks through the .conf files to determine the mpxio setting. 11457c478bd9Sstevel@tonic-gate * 11467c478bd9Sstevel@tonic-gate * rootdir root directory of the target environment 11477c478bd9Sstevel@tonic-gate * path /devices name of a device without the /devices prefix and 11487c478bd9Sstevel@tonic-gate * minor name component. 11497c478bd9Sstevel@tonic-gate * 11507c478bd9Sstevel@tonic-gate * Returns 11517c478bd9Sstevel@tonic-gate * 1 if mpxio is disabled 11527c478bd9Sstevel@tonic-gate * 0 if mpxio is enabled 11537c478bd9Sstevel@tonic-gate * -1 if an error occurs 11547c478bd9Sstevel@tonic-gate */ 11557c478bd9Sstevel@tonic-gate static int 11567c478bd9Sstevel@tonic-gate is_mpxio_disabled(char *rootdir, char *path) 11577c478bd9Sstevel@tonic-gate { 11587c478bd9Sstevel@tonic-gate int mpxio_disable; 11597c478bd9Sstevel@tonic-gate char *p; 11607c478bd9Sstevel@tonic-gate int check_root_controller; 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate logdmsg(("is_mpxio_disabled: rootdir = %s, path = %s\n", 11637c478bd9Sstevel@tonic-gate rootdir, path)); 11647c478bd9Sstevel@tonic-gate 11657c478bd9Sstevel@tonic-gate if (file_exists(rootdir, SCSI_VHCI_CONF) == 0) { 11667c478bd9Sstevel@tonic-gate /* 11677c478bd9Sstevel@tonic-gate * scsi_vhci.conf doesn't exist: 11687c478bd9Sstevel@tonic-gate * if upgrading from a pre solaris 9 release. or 11697c478bd9Sstevel@tonic-gate * if this function is called during fresh or flash install 11707c478bd9Sstevel@tonic-gate * prior to installing scsi_vhci.conf file. 11717c478bd9Sstevel@tonic-gate */ 11727c478bd9Sstevel@tonic-gate if (file_exists(rootdir, "/kernel/drv")) 11737c478bd9Sstevel@tonic-gate /* upgrading from pre solaris 9 */ 11747c478bd9Sstevel@tonic-gate return (1); 11757c478bd9Sstevel@tonic-gate else 11767c478bd9Sstevel@tonic-gate /* fresh or flash install */ 11777c478bd9Sstevel@tonic-gate return (0); 11787c478bd9Sstevel@tonic-gate } 11797c478bd9Sstevel@tonic-gate 11807c478bd9Sstevel@tonic-gate mpxio_disable = lookup_in_conf_file(rootdir, SCSI_VHCI_CONF, NULL); 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate /* 11837c478bd9Sstevel@tonic-gate * scsi_vhci.conf contains mpxio-disable property only in s9 and 11847c478bd9Sstevel@tonic-gate * s8+sfkpatch. This property is no longer present from s10 onwards. 11857c478bd9Sstevel@tonic-gate */ 11867c478bd9Sstevel@tonic-gate if (mpxio_disable == 1) { 11877c478bd9Sstevel@tonic-gate /* upgrading from s8 or s9 with mpxio globally disabled */ 11887c478bd9Sstevel@tonic-gate return (1); 11897c478bd9Sstevel@tonic-gate } else if (mpxio_disable == 0) { 11907c478bd9Sstevel@tonic-gate /* upgrading from s8 or s9 with mpxio globally enabled */ 11917c478bd9Sstevel@tonic-gate check_root_controller = 1; 11927c478bd9Sstevel@tonic-gate } else { 11937c478bd9Sstevel@tonic-gate /* 11947c478bd9Sstevel@tonic-gate * We are looking at the s10 version of the file. This is 11957c478bd9Sstevel@tonic-gate * the case if this function is called after installing the 11967c478bd9Sstevel@tonic-gate * new scsi_vhci.conf file. 11977c478bd9Sstevel@tonic-gate */ 11987c478bd9Sstevel@tonic-gate check_root_controller = 0; 11997c478bd9Sstevel@tonic-gate } 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate if ((mpxio_disable = lookup_in_conf_file(rootdir, FP_CONF, path)) 12027c478bd9Sstevel@tonic-gate != -1) 12037c478bd9Sstevel@tonic-gate return (mpxio_disable); 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate if ((p = strrchr(path, '/')) == NULL) 12067c478bd9Sstevel@tonic-gate return (-1); 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate *p = '\0'; 12097c478bd9Sstevel@tonic-gate if ((mpxio_disable = lookup_in_conf_file(rootdir, QLC_CONF, path)) 12107c478bd9Sstevel@tonic-gate != -1) { 12117c478bd9Sstevel@tonic-gate *p = '/'; 12127c478bd9Sstevel@tonic-gate return (mpxio_disable); 12137c478bd9Sstevel@tonic-gate } 12147c478bd9Sstevel@tonic-gate *p = '/'; 12157c478bd9Sstevel@tonic-gate 12167c478bd9Sstevel@tonic-gate /* 12177c478bd9Sstevel@tonic-gate * mpxio-disable setting is not found in the .conf files. 12187c478bd9Sstevel@tonic-gate * The default is to enable mpxio, except if the path is on the root 12197c478bd9Sstevel@tonic-gate * controller. 12207c478bd9Sstevel@tonic-gate * 12217c478bd9Sstevel@tonic-gate * In s8 and s9 mpxio is not supported on the root controller. 12227c478bd9Sstevel@tonic-gate * NWS supplies a patch to enable root controller support in s8 and s9. 12237c478bd9Sstevel@tonic-gate * If the system had the patch installed, the fp.conf file would have 12247c478bd9Sstevel@tonic-gate * explicit "mpxio-disable=no" for the root controller. So we would 12257c478bd9Sstevel@tonic-gate * have found the mpxio-disable setting when we looked up this property 12267c478bd9Sstevel@tonic-gate * in the fp.conf file. 12277c478bd9Sstevel@tonic-gate */ 12287c478bd9Sstevel@tonic-gate if (check_root_controller) { 12297c478bd9Sstevel@tonic-gate mpxio_disable = is_root_controller(rootdir, path); 12307c478bd9Sstevel@tonic-gate logdmsg(("is_mpxio_disabled: is_root_controller returned %d\n", 12317c478bd9Sstevel@tonic-gate mpxio_disable)); 12327c478bd9Sstevel@tonic-gate } else 12337c478bd9Sstevel@tonic-gate mpxio_disable = 0; 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate return (mpxio_disable); 12367c478bd9Sstevel@tonic-gate } 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate static int 12397c478bd9Sstevel@tonic-gate vhci_ctl(sv_iocdata_t *iocp, int cmd) 12407c478bd9Sstevel@tonic-gate { 12417c478bd9Sstevel@tonic-gate int fd, rv; 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate if ((fd = open(VHCI_CTL_NODE, O_RDWR)) < 0) 12447c478bd9Sstevel@tonic-gate return (-1); 12457c478bd9Sstevel@tonic-gate rv = ioctl(fd, cmd, iocp); 12467c478bd9Sstevel@tonic-gate (void) close(fd); 12477c478bd9Sstevel@tonic-gate return (rv); 12487c478bd9Sstevel@tonic-gate } 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate /* 12517c478bd9Sstevel@tonic-gate * Convert a phci client name to vhci client name. 12527c478bd9Sstevel@tonic-gate * 12537c478bd9Sstevel@tonic-gate * phci_name phci client /devices name without the /devices prefix and 12547c478bd9Sstevel@tonic-gate * minor name component. 12557c478bd9Sstevel@tonic-gate * ex: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0 12567c478bd9Sstevel@tonic-gate * 12577c478bd9Sstevel@tonic-gate * Returns on success, vhci client name is returned. The memory for 12587c478bd9Sstevel@tonic-gate * the vhci name is allocated by this function and the caller 12597c478bd9Sstevel@tonic-gate * must free it. 12607c478bd9Sstevel@tonic-gate * on failure, NULL is returned. 12617c478bd9Sstevel@tonic-gate */ 12627c478bd9Sstevel@tonic-gate static char * 12637c478bd9Sstevel@tonic-gate phci_to_vhci(char *phci_name) 12647c478bd9Sstevel@tonic-gate { 12657c478bd9Sstevel@tonic-gate sv_iocdata_t ioc; 12667c478bd9Sstevel@tonic-gate char *slash, *addr, *retp; 12677c478bd9Sstevel@tonic-gate char vhci_name_buf[MAXPATHLEN]; 12687c478bd9Sstevel@tonic-gate char phci_name_buf[MAXPATHLEN]; 12697c478bd9Sstevel@tonic-gate char addr_buf[MAXNAMELEN]; 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate logdmsg(("phci_to_vhci: pchi_name = %s\n", phci_name)); 12727c478bd9Sstevel@tonic-gate (void) strlcpy(phci_name_buf, phci_name, MAXPATHLEN); 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate if ((slash = strrchr(phci_name_buf, '/')) == NULL || 12757c478bd9Sstevel@tonic-gate (addr = strchr(slash, '@')) == NULL) 12767c478bd9Sstevel@tonic-gate return (NULL); 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate *slash = '\0'; 12797c478bd9Sstevel@tonic-gate addr++; 12807c478bd9Sstevel@tonic-gate (void) strlcpy(addr_buf, addr, MAXNAMELEN); 12817c478bd9Sstevel@tonic-gate 12827c478bd9Sstevel@tonic-gate bzero(&ioc, sizeof (sv_iocdata_t)); 12837c478bd9Sstevel@tonic-gate ioc.client = vhci_name_buf; 12847c478bd9Sstevel@tonic-gate ioc.phci = phci_name_buf; 12857c478bd9Sstevel@tonic-gate ioc.addr = addr_buf; 12867c478bd9Sstevel@tonic-gate if (vhci_ctl(&ioc, SCSI_VHCI_GET_CLIENT_NAME) != 0) { 12877c478bd9Sstevel@tonic-gate logdmsg(("phci_to_vhci: vhci_ctl failed: %s\n", 12887c478bd9Sstevel@tonic-gate strerror(errno))); 12897c478bd9Sstevel@tonic-gate return (NULL); 12907c478bd9Sstevel@tonic-gate } 12917c478bd9Sstevel@tonic-gate 12927c478bd9Sstevel@tonic-gate retp = strdup(vhci_name_buf); 12937c478bd9Sstevel@tonic-gate logdmsg(("phci_to_vhci: vhci name = %s\n", STRVAL(retp))); 12947c478bd9Sstevel@tonic-gate return (retp); 12957c478bd9Sstevel@tonic-gate } 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate static int 12987c478bd9Sstevel@tonic-gate add_to_phci_list(char **phci_list, sv_path_info_t *pi, int npaths, int state, 12997c478bd9Sstevel@tonic-gate char *node_name) 13007c478bd9Sstevel@tonic-gate { 13017c478bd9Sstevel@tonic-gate int rv = 0; 13027c478bd9Sstevel@tonic-gate char name[MAXPATHLEN]; 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate while (npaths--) { 13057c478bd9Sstevel@tonic-gate if (state == pi->ret_state) { 1306*72a50065Scth (void) snprintf(name, MAXPATHLEN, "%s/%s@%s", 13077c478bd9Sstevel@tonic-gate pi->device.ret_phci, node_name, pi->ret_addr); 13087c478bd9Sstevel@tonic-gate if ((*phci_list = strdup(name)) == NULL) 13097c478bd9Sstevel@tonic-gate return (-1); 13107c478bd9Sstevel@tonic-gate phci_list++; 13117c478bd9Sstevel@tonic-gate rv++; 13127c478bd9Sstevel@tonic-gate } 13137c478bd9Sstevel@tonic-gate pi++; 13147c478bd9Sstevel@tonic-gate } 13157c478bd9Sstevel@tonic-gate 13167c478bd9Sstevel@tonic-gate return (rv); 13177c478bd9Sstevel@tonic-gate } 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate static void 13207c478bd9Sstevel@tonic-gate free_pathlist(char **pathlist) 13217c478bd9Sstevel@tonic-gate { 13227c478bd9Sstevel@tonic-gate char **p; 13237c478bd9Sstevel@tonic-gate 13247c478bd9Sstevel@tonic-gate if (pathlist != NULL) { 13257c478bd9Sstevel@tonic-gate for (p = pathlist; *p != NULL; p++) 13267c478bd9Sstevel@tonic-gate free(*p); 13277c478bd9Sstevel@tonic-gate free(pathlist); 13287c478bd9Sstevel@tonic-gate } 13297c478bd9Sstevel@tonic-gate } 13307c478bd9Sstevel@tonic-gate 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate /* 13337c478bd9Sstevel@tonic-gate * Convert a vhci client name to phci client names. 13347c478bd9Sstevel@tonic-gate * 13357c478bd9Sstevel@tonic-gate * vhci_name vhci client /devices name without the /devices prefix and 13367c478bd9Sstevel@tonic-gate * minor name component. 13377c478bd9Sstevel@tonic-gate * num_paths On return, *num_paths is set to the number paths in the 13387c478bd9Sstevel@tonic-gate * returned path list. 13397c478bd9Sstevel@tonic-gate * 13407c478bd9Sstevel@tonic-gate * Returns NULL terminated path list containing phci client paths is 13417c478bd9Sstevel@tonic-gate * returned on success. The memory for the path list is 13427c478bd9Sstevel@tonic-gate * allocated by this function and the caller must free it by 13437c478bd9Sstevel@tonic-gate * calling free_pathlist(). 13447c478bd9Sstevel@tonic-gate * NULL is returned on failure. 13457c478bd9Sstevel@tonic-gate */ 13467c478bd9Sstevel@tonic-gate static char ** 13477c478bd9Sstevel@tonic-gate vhci_to_phci(char *vhci_name, int *num_paths) 13487c478bd9Sstevel@tonic-gate { 13497c478bd9Sstevel@tonic-gate sv_iocdata_t ioc; 13507c478bd9Sstevel@tonic-gate uint_t npaths; 13517c478bd9Sstevel@tonic-gate int n; 13527c478bd9Sstevel@tonic-gate char **phci_list = NULL; 13537c478bd9Sstevel@tonic-gate char *node_name, *at; 13547c478bd9Sstevel@tonic-gate char vhci_name_buf[MAXPATHLEN]; 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate logdmsg(("vhci_to_phci: vchi_name = %s\n", vhci_name)); 13577c478bd9Sstevel@tonic-gate 13587c478bd9Sstevel@tonic-gate *num_paths = 0; 13597c478bd9Sstevel@tonic-gate (void) strlcpy(vhci_name_buf, vhci_name, MAXPATHLEN); 13607c478bd9Sstevel@tonic-gate 13617c478bd9Sstevel@tonic-gate /* first get the number paths */ 13627c478bd9Sstevel@tonic-gate bzero(&ioc, sizeof (sv_iocdata_t)); 13637c478bd9Sstevel@tonic-gate ioc.client = vhci_name_buf; 13647c478bd9Sstevel@tonic-gate ioc.ret_elem = &npaths; 13657c478bd9Sstevel@tonic-gate if (vhci_ctl(&ioc, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO) != 0 || 13667c478bd9Sstevel@tonic-gate npaths == 0) { 13677c478bd9Sstevel@tonic-gate logdmsg(("vhci_to_phci: vhci_ctl failed to get npaths: %s\n", 13687c478bd9Sstevel@tonic-gate strerror(errno))); 13697c478bd9Sstevel@tonic-gate return (NULL); 13707c478bd9Sstevel@tonic-gate } 13717c478bd9Sstevel@tonic-gate 13727c478bd9Sstevel@tonic-gate /* now allocate memory for the path information and get all paths */ 13737c478bd9Sstevel@tonic-gate bzero(&ioc, sizeof (sv_iocdata_t)); 13747c478bd9Sstevel@tonic-gate ioc.client = vhci_name_buf; 13757c478bd9Sstevel@tonic-gate ioc.buf_elem = npaths; 13767c478bd9Sstevel@tonic-gate ioc.ret_elem = &npaths; 13777c478bd9Sstevel@tonic-gate if ((ioc.ret_buf = (sv_path_info_t *)calloc(npaths, 13787c478bd9Sstevel@tonic-gate sizeof (sv_path_info_t))) == NULL) 13797c478bd9Sstevel@tonic-gate return (NULL); 13807c478bd9Sstevel@tonic-gate if (vhci_ctl(&ioc, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO) != 0 || 13817c478bd9Sstevel@tonic-gate npaths == 0) { 13827c478bd9Sstevel@tonic-gate logdmsg(("vhci_to_phci: vhci_ctl failed: %s\n", 13837c478bd9Sstevel@tonic-gate strerror(errno))); 13847c478bd9Sstevel@tonic-gate goto out; 13857c478bd9Sstevel@tonic-gate } 13867c478bd9Sstevel@tonic-gate 13877c478bd9Sstevel@tonic-gate if (ioc.buf_elem < npaths) 13887c478bd9Sstevel@tonic-gate npaths = ioc.buf_elem; 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate if ((node_name = strrchr(vhci_name_buf, '/')) == NULL || 13917c478bd9Sstevel@tonic-gate (at = strchr(node_name, '@')) == NULL) 13927c478bd9Sstevel@tonic-gate goto out; 13937c478bd9Sstevel@tonic-gate 13947c478bd9Sstevel@tonic-gate node_name++; 13957c478bd9Sstevel@tonic-gate *at = '\0'; 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate /* allocate one more (than npaths) for the terminating NULL pointer */ 13987c478bd9Sstevel@tonic-gate if ((phci_list = calloc(npaths + 1, sizeof (char *))) == NULL) 13997c478bd9Sstevel@tonic-gate goto out; 14007c478bd9Sstevel@tonic-gate 14017c478bd9Sstevel@tonic-gate /* 14027c478bd9Sstevel@tonic-gate * add only online paths as non-online paths may not be accessible 14037c478bd9Sstevel@tonic-gate * in the target environment. 14047c478bd9Sstevel@tonic-gate */ 14057c478bd9Sstevel@tonic-gate if ((n = add_to_phci_list(phci_list, ioc.ret_buf, npaths, 14067c478bd9Sstevel@tonic-gate MDI_PATHINFO_STATE_ONLINE, node_name)) <= 0) 14077c478bd9Sstevel@tonic-gate goto out; 14087c478bd9Sstevel@tonic-gate 14097c478bd9Sstevel@tonic-gate free(ioc.ret_buf); 14107c478bd9Sstevel@tonic-gate *num_paths = n; 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate #ifdef DEBUG 14137c478bd9Sstevel@tonic-gate logdmsg(("vhci_to_phci: phci list:\n")); 14147c478bd9Sstevel@tonic-gate log_pathlist(phci_list); 14157c478bd9Sstevel@tonic-gate #endif 14167c478bd9Sstevel@tonic-gate return (phci_list); 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate out: 14197c478bd9Sstevel@tonic-gate free(ioc.ret_buf); 14207c478bd9Sstevel@tonic-gate if (phci_list) 14217c478bd9Sstevel@tonic-gate free_pathlist(phci_list); 14227c478bd9Sstevel@tonic-gate return (NULL); 14237c478bd9Sstevel@tonic-gate } 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate /* 14267c478bd9Sstevel@tonic-gate * build list of paths accessible from the target environment 14277c478bd9Sstevel@tonic-gate */ 14287c478bd9Sstevel@tonic-gate static int 14297c478bd9Sstevel@tonic-gate build_pathlist(char *rootdir, char *vhcipath, char **pathlist, int npaths) 14307c478bd9Sstevel@tonic-gate { 14317c478bd9Sstevel@tonic-gate int mpxio_disabled; 14327c478bd9Sstevel@tonic-gate int i, j; 14337c478bd9Sstevel@tonic-gate char *vpath = NULL; 14347c478bd9Sstevel@tonic-gate 14357c478bd9Sstevel@tonic-gate for (i = 0; i < npaths; i++) { 14367c478bd9Sstevel@tonic-gate mpxio_disabled = is_mpxio_disabled(rootdir, pathlist[i]); 14377c478bd9Sstevel@tonic-gate logdmsg(("build_pathlist: mpxio_disabled = %d " 14387c478bd9Sstevel@tonic-gate "on path %s\n", mpxio_disabled, pathlist[i])); 14397c478bd9Sstevel@tonic-gate if (mpxio_disabled == -1) 14407c478bd9Sstevel@tonic-gate return (-1); 14417c478bd9Sstevel@tonic-gate if (mpxio_disabled == 0) { 14427c478bd9Sstevel@tonic-gate /* 14437c478bd9Sstevel@tonic-gate * mpxio is enabled on this phci path. 14447c478bd9Sstevel@tonic-gate * So use vhci path instead of phci path. 14457c478bd9Sstevel@tonic-gate */ 14467c478bd9Sstevel@tonic-gate if (vpath == NULL) { 14477c478bd9Sstevel@tonic-gate if ((vpath = strdup(vhcipath)) == NULL) 14487c478bd9Sstevel@tonic-gate return (-1); 14497c478bd9Sstevel@tonic-gate free(pathlist[i]); 14507c478bd9Sstevel@tonic-gate /* keep vhci path at beginning of the list */ 14517c478bd9Sstevel@tonic-gate for (j = i; j > 0; j--) 14527c478bd9Sstevel@tonic-gate pathlist[j] = pathlist[j - 1]; 14537c478bd9Sstevel@tonic-gate pathlist[0] = vpath; 14547c478bd9Sstevel@tonic-gate } else { 14557c478bd9Sstevel@tonic-gate free(pathlist[i]); 14567c478bd9Sstevel@tonic-gate npaths--; 14577c478bd9Sstevel@tonic-gate for (j = i; j < npaths; j++) 14587c478bd9Sstevel@tonic-gate pathlist[j] = pathlist[j + 1]; 14597c478bd9Sstevel@tonic-gate pathlist[npaths] = NULL; 14607c478bd9Sstevel@tonic-gate /* compensate for i++ in the for loop */ 14617c478bd9Sstevel@tonic-gate i--; 14627c478bd9Sstevel@tonic-gate } 14637c478bd9Sstevel@tonic-gate } 14647c478bd9Sstevel@tonic-gate } 14657c478bd9Sstevel@tonic-gate 14667c478bd9Sstevel@tonic-gate #ifdef DEBUG 14677c478bd9Sstevel@tonic-gate logdmsg(("build_pathlist: returning npaths = %d, pathlist:\n", npaths)); 14687c478bd9Sstevel@tonic-gate log_pathlist(pathlist); 14697c478bd9Sstevel@tonic-gate #endif 14707c478bd9Sstevel@tonic-gate return (npaths); 14717c478bd9Sstevel@tonic-gate } 14727c478bd9Sstevel@tonic-gate 14737c478bd9Sstevel@tonic-gate /* 14747c478bd9Sstevel@tonic-gate * Check if the specified device is refenced in the vfstab file. 14757c478bd9Sstevel@tonic-gate * Return 1 if referenced, 0 if not. 14767c478bd9Sstevel@tonic-gate * 14777c478bd9Sstevel@tonic-gate * rootdir root directory of the target environment 14787c478bd9Sstevel@tonic-gate * nodepath /devices path of a device in the target environment without 14797c478bd9Sstevel@tonic-gate * the /devices prefix and minor component. 14807c478bd9Sstevel@tonic-gate */ 14817c478bd9Sstevel@tonic-gate static int 14827c478bd9Sstevel@tonic-gate is_dev_in_vfstab(char *rootdir, char *nodepath) 14837c478bd9Sstevel@tonic-gate { 14847c478bd9Sstevel@tonic-gate FILE *fp; 14857c478bd9Sstevel@tonic-gate int linksize; 14867c478bd9Sstevel@tonic-gate struct vfstab vfsent; 14877c478bd9Sstevel@tonic-gate char *abspath, *minor; 14887c478bd9Sstevel@tonic-gate char physpath[MAXPATHLEN]; 14897c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate logdmsg(("is_dev_in_vfstab: rootdir = %s, nodepath = %s\n", 14927c478bd9Sstevel@tonic-gate rootdir, nodepath)); 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s%s", rootdir, VFSTAB); 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate if ((fp = fopen(buf, "r")) == NULL) 14977c478bd9Sstevel@tonic-gate return (0); 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate /* 15007c478bd9Sstevel@tonic-gate * read device specials from vfstab and compare names at physical 15017c478bd9Sstevel@tonic-gate * node path level. 15027c478bd9Sstevel@tonic-gate */ 15037c478bd9Sstevel@tonic-gate while (getvfsent(fp, &vfsent) == 0) { 15047c478bd9Sstevel@tonic-gate if (strncmp(vfsent.vfs_special, SLASH_DEV_SLASH, 15057c478bd9Sstevel@tonic-gate sizeof (SLASH_DEV_SLASH) - 1) == 0) { 15067c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, "%s%s", 15077c478bd9Sstevel@tonic-gate rootdir, vfsent.vfs_special); 15087c478bd9Sstevel@tonic-gate if ((linksize = readlink(buf, physpath, 15097c478bd9Sstevel@tonic-gate MAXPATHLEN)) > 0 && linksize < (MAXPATHLEN - 1)) { 15107c478bd9Sstevel@tonic-gate physpath[linksize] = '\0'; 15117c478bd9Sstevel@tonic-gate if ((abspath = strstr(physpath, 15127c478bd9Sstevel@tonic-gate SLASH_DEVICES_SLASH)) == NULL) 15137c478bd9Sstevel@tonic-gate continue; 15147c478bd9Sstevel@tonic-gate } else 15157c478bd9Sstevel@tonic-gate continue; 15167c478bd9Sstevel@tonic-gate } else if (strncmp(vfsent.vfs_special, SLASH_DEVICES_SLASH, 15177c478bd9Sstevel@tonic-gate sizeof (SLASH_DEVICES_SLASH) - 1) == 0) { 15187c478bd9Sstevel@tonic-gate (void) strlcpy(physpath, vfsent.vfs_special, 15197c478bd9Sstevel@tonic-gate MAXPATHLEN); 15207c478bd9Sstevel@tonic-gate abspath = physpath; 15217c478bd9Sstevel@tonic-gate } else 15227c478bd9Sstevel@tonic-gate continue; 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate /* point to / after /devices */ 15257c478bd9Sstevel@tonic-gate abspath += sizeof (SLASH_DEVICES_SLASH) - 2; 15267c478bd9Sstevel@tonic-gate /* strip minor component */ 15277c478bd9Sstevel@tonic-gate if ((minor = strrchr(abspath, ':')) != NULL) 15287c478bd9Sstevel@tonic-gate *minor = '\0'; 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate if (strcmp(nodepath, abspath) == 0) { 15317c478bd9Sstevel@tonic-gate (void) fclose(fp); 15327c478bd9Sstevel@tonic-gate logdmsg(("is_dev_in_vfstab: returning 1\n")); 15337c478bd9Sstevel@tonic-gate return (1); 15347c478bd9Sstevel@tonic-gate } 15357c478bd9Sstevel@tonic-gate } 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate (void) fclose(fp); 15387c478bd9Sstevel@tonic-gate return (0); 15397c478bd9Sstevel@tonic-gate } 15407c478bd9Sstevel@tonic-gate 15417c478bd9Sstevel@tonic-gate #endif /* __sparc */ 15427c478bd9Sstevel@tonic-gate 15437c478bd9Sstevel@tonic-gate static int 15447c478bd9Sstevel@tonic-gate devlink_callback(di_devlink_t devlink, void *argp) 15457c478bd9Sstevel@tonic-gate { 15467c478bd9Sstevel@tonic-gate const char *link; 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate if ((link = di_devlink_path(devlink)) != NULL) 15497c478bd9Sstevel@tonic-gate (void) strlcpy((char *)argp, link, MAXPATHLEN); 15507c478bd9Sstevel@tonic-gate 15517c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 15527c478bd9Sstevel@tonic-gate } 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate /* 15557c478bd9Sstevel@tonic-gate * Get the /dev name in the install environment corresponding to physpath. 15567c478bd9Sstevel@tonic-gate * 15577c478bd9Sstevel@tonic-gate * physpath /devices path in the install environment without the /devices 15587c478bd9Sstevel@tonic-gate * prefix. 15597c478bd9Sstevel@tonic-gate * buf caller supplied buffer where the /dev name is placed on return 15607c478bd9Sstevel@tonic-gate * bufsz length of the buffer 15617c478bd9Sstevel@tonic-gate * 15627c478bd9Sstevel@tonic-gate * Returns strlen of the /dev name on success, -1 on failure. 15637c478bd9Sstevel@tonic-gate */ 15647c478bd9Sstevel@tonic-gate static int 15657c478bd9Sstevel@tonic-gate get_install_devlink(char *physpath, char *buf, size_t bufsz) 15667c478bd9Sstevel@tonic-gate { 15677c478bd9Sstevel@tonic-gate di_devlink_handle_t devlink_hdl; 15687c478bd9Sstevel@tonic-gate char devname[MAXPATHLEN]; 15697c478bd9Sstevel@tonic-gate 15707c478bd9Sstevel@tonic-gate logdmsg(("get_install_devlink: physpath = %s\n", physpath)); 15717c478bd9Sstevel@tonic-gate 15727c478bd9Sstevel@tonic-gate if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 15737c478bd9Sstevel@tonic-gate logdmsg(("get_install_devlink: di_devlink_init() failed: %s\n", 15747c478bd9Sstevel@tonic-gate strerror(errno))); 15757c478bd9Sstevel@tonic-gate return (-1); 15767c478bd9Sstevel@tonic-gate } 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate devname[0] = '\0'; 15797c478bd9Sstevel@tonic-gate if (di_devlink_walk(devlink_hdl, NULL, physpath, DI_PRIMARY_LINK, 15807c478bd9Sstevel@tonic-gate devname, devlink_callback) != 0 || devname[0] == '\0') { 15817c478bd9Sstevel@tonic-gate logdmsg(("get_install_devlink: di_devlink_walk failed: %s\n", 15827c478bd9Sstevel@tonic-gate strerror(errno))); 15837c478bd9Sstevel@tonic-gate (void) di_devlink_fini(&devlink_hdl); 15847c478bd9Sstevel@tonic-gate return (-1); 15857c478bd9Sstevel@tonic-gate } 15867c478bd9Sstevel@tonic-gate 15877c478bd9Sstevel@tonic-gate (void) di_devlink_fini(&devlink_hdl); 15887c478bd9Sstevel@tonic-gate 15897c478bd9Sstevel@tonic-gate logdmsg(("get_install_devlink: devlink = %s\n", devname)); 15907c478bd9Sstevel@tonic-gate return (strlcpy(buf, devname, bufsz)); 15917c478bd9Sstevel@tonic-gate } 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate /* 15947c478bd9Sstevel@tonic-gate * Get the /dev name in the target environment corresponding to physpath. 15957c478bd9Sstevel@tonic-gate * 15967c478bd9Sstevel@tonic-gate * rootdir root directory of the target environment 15977c478bd9Sstevel@tonic-gate * physpath /devices path in the target environment without the /devices 15987c478bd9Sstevel@tonic-gate * prefix. 15997c478bd9Sstevel@tonic-gate * buf caller supplied buffer where the /dev name is placed on return 16007c478bd9Sstevel@tonic-gate * bufsz length of the buffer 16017c478bd9Sstevel@tonic-gate * 16027c478bd9Sstevel@tonic-gate * Returns strlen of the /dev name on success, -1 on failure. 16037c478bd9Sstevel@tonic-gate */ 16047c478bd9Sstevel@tonic-gate static int 16057c478bd9Sstevel@tonic-gate get_target_devlink(char *rootdir, char *physpath, char *buf, size_t bufsz) 16067c478bd9Sstevel@tonic-gate { 16077c478bd9Sstevel@tonic-gate char *p; 16087c478bd9Sstevel@tonic-gate int linksize; 16097c478bd9Sstevel@tonic-gate DIR *dirp; 16107c478bd9Sstevel@tonic-gate struct dirent *direntry; 16117c478bd9Sstevel@tonic-gate char dirpath[MAXPATHLEN]; 16127c478bd9Sstevel@tonic-gate char devname[MAXPATHLEN]; 16137c478bd9Sstevel@tonic-gate char physdev[MAXPATHLEN]; 16147c478bd9Sstevel@tonic-gate 16157c478bd9Sstevel@tonic-gate logdmsg(("get_target_devlink: rootdir = %s, physpath = %s\n", 16167c478bd9Sstevel@tonic-gate rootdir, physpath)); 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate if ((p = strrchr(physpath, '/')) == NULL) 16197c478bd9Sstevel@tonic-gate return (-1); 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate if (strstr(p, ",raw") != NULL) { 16227c478bd9Sstevel@tonic-gate (void) snprintf(dirpath, MAXPATHLEN, "%s/dev/rdsk", rootdir); 16237c478bd9Sstevel@tonic-gate } else { 16247c478bd9Sstevel@tonic-gate (void) snprintf(dirpath, MAXPATHLEN, "%s/dev/dsk", rootdir); 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate 16277c478bd9Sstevel@tonic-gate if ((dirp = opendir(dirpath)) == NULL) 16287c478bd9Sstevel@tonic-gate return (-1); 16297c478bd9Sstevel@tonic-gate 16307c478bd9Sstevel@tonic-gate while ((direntry = readdir(dirp)) != NULL) { 16317c478bd9Sstevel@tonic-gate if (strcmp(direntry->d_name, ".") == 0 || 16327c478bd9Sstevel@tonic-gate strcmp(direntry->d_name, "..") == 0) 16337c478bd9Sstevel@tonic-gate continue; 16347c478bd9Sstevel@tonic-gate 16357c478bd9Sstevel@tonic-gate (void) snprintf(devname, MAXPATHLEN, "%s/%s", 16367c478bd9Sstevel@tonic-gate dirpath, direntry->d_name); 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate if ((linksize = readlink(devname, physdev, MAXPATHLEN)) > 0 && 16397c478bd9Sstevel@tonic-gate linksize < (MAXPATHLEN - 1)) { 16407c478bd9Sstevel@tonic-gate physdev[linksize] = '\0'; 16417c478bd9Sstevel@tonic-gate if ((p = strstr(physdev, SLASH_DEVICES_SLASH)) != 16427c478bd9Sstevel@tonic-gate NULL && strcmp(p + sizeof (SLASH_DEVICES) - 1, 16437c478bd9Sstevel@tonic-gate physpath) == 0) { 16447c478bd9Sstevel@tonic-gate (void) closedir(dirp); 16457c478bd9Sstevel@tonic-gate logdmsg(("get_target_devlink: devlink = %s\n", 16467c478bd9Sstevel@tonic-gate devname + strlen(rootdir))); 16477c478bd9Sstevel@tonic-gate return (strlcpy(buf, devname + strlen(rootdir), 16487c478bd9Sstevel@tonic-gate bufsz)); 16497c478bd9Sstevel@tonic-gate } 16507c478bd9Sstevel@tonic-gate } 16517c478bd9Sstevel@tonic-gate } 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate (void) closedir(dirp); 16547c478bd9Sstevel@tonic-gate return (-1); 16557c478bd9Sstevel@tonic-gate } 16567c478bd9Sstevel@tonic-gate 16577c478bd9Sstevel@tonic-gate /* 16587c478bd9Sstevel@tonic-gate * Convert device name to physpath. 16597c478bd9Sstevel@tonic-gate * 16607c478bd9Sstevel@tonic-gate * rootdir root directory 16617c478bd9Sstevel@tonic-gate * devname a /dev name or /devices name under rootdir 16627c478bd9Sstevel@tonic-gate * physpath caller supplied buffer where the /devices path will be placed 16637c478bd9Sstevel@tonic-gate * on return (without the /devices prefix). 16647c478bd9Sstevel@tonic-gate * physpathlen length of the physpath buffer 16657c478bd9Sstevel@tonic-gate * 16667c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 16677c478bd9Sstevel@tonic-gate */ 16687c478bd9Sstevel@tonic-gate static int 16697c478bd9Sstevel@tonic-gate devname2physpath(char *rootdir, char *devname, char *physpath, int physpathlen) 16707c478bd9Sstevel@tonic-gate { 16717c478bd9Sstevel@tonic-gate int linksize; 16727c478bd9Sstevel@tonic-gate char *p; 16737c478bd9Sstevel@tonic-gate char devlink[MAXPATHLEN]; 16747c478bd9Sstevel@tonic-gate char tmpphyspath[MAXPATHLEN]; 16757c478bd9Sstevel@tonic-gate 16767c478bd9Sstevel@tonic-gate logdmsg(("devname2physpath: rootdir = %s, devname = %s\n", 16777c478bd9Sstevel@tonic-gate rootdir, devname)); 16787c478bd9Sstevel@tonic-gate 16797c478bd9Sstevel@tonic-gate if (strncmp(devname, SLASH_DEVICES_SLASH, 16807c478bd9Sstevel@tonic-gate sizeof (SLASH_DEVICES_SLASH) - 1) != 0) { 16817c478bd9Sstevel@tonic-gate if (*rootdir == '\0') 16827c478bd9Sstevel@tonic-gate linksize = readlink(devname, tmpphyspath, MAXPATHLEN); 16837c478bd9Sstevel@tonic-gate else { 16847c478bd9Sstevel@tonic-gate (void) snprintf(devlink, MAXPATHLEN, "%s%s", 16857c478bd9Sstevel@tonic-gate rootdir, devname); 16867c478bd9Sstevel@tonic-gate linksize = readlink(devlink, tmpphyspath, MAXPATHLEN); 16877c478bd9Sstevel@tonic-gate } 16887c478bd9Sstevel@tonic-gate if (linksize > 0 && linksize < (MAXPATHLEN - 1)) { 16897c478bd9Sstevel@tonic-gate tmpphyspath[linksize] = '\0'; 16907c478bd9Sstevel@tonic-gate if ((p = strstr(tmpphyspath, SLASH_DEVICES_SLASH)) 16917c478bd9Sstevel@tonic-gate == NULL) 16927c478bd9Sstevel@tonic-gate return (-1); 16937c478bd9Sstevel@tonic-gate } else 16947c478bd9Sstevel@tonic-gate return (-1); 16957c478bd9Sstevel@tonic-gate } else 16967c478bd9Sstevel@tonic-gate p = devname; 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate (void) strlcpy(physpath, p + sizeof (SLASH_DEVICES) - 1, physpathlen); 16997c478bd9Sstevel@tonic-gate logdmsg(("devname2physpath: physpath = %s\n", physpath)); 17007c478bd9Sstevel@tonic-gate return (0); 17017c478bd9Sstevel@tonic-gate } 17027c478bd9Sstevel@tonic-gate 17037c478bd9Sstevel@tonic-gate /* 17047c478bd9Sstevel@tonic-gate * Map a device name (devname) from the target environment to the 17057c478bd9Sstevel@tonic-gate * install environment. 17067c478bd9Sstevel@tonic-gate * 17077c478bd9Sstevel@tonic-gate * rootdir root directory of the target environment 17087c478bd9Sstevel@tonic-gate * devname /dev or /devices name under the target environment 17097c478bd9Sstevel@tonic-gate * buf caller supplied buffer where the mapped /dev name is placed 17107c478bd9Sstevel@tonic-gate * on return 17117c478bd9Sstevel@tonic-gate * bufsz length of the buffer 17127c478bd9Sstevel@tonic-gate * 17137c478bd9Sstevel@tonic-gate * Returns strlen of the mapped /dev name on success, -1 on failure. 17147c478bd9Sstevel@tonic-gate */ 17157c478bd9Sstevel@tonic-gate int 17167c478bd9Sstevel@tonic-gate devfs_target2install(const char *rootdir, const char *devname, char *buf, 17177c478bd9Sstevel@tonic-gate size_t bufsz) 17187c478bd9Sstevel@tonic-gate { 17197c478bd9Sstevel@tonic-gate char physpath[MAXPATHLEN]; 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate logdmsg(("devfs_target2install: rootdir = %s, devname = %s\n", 17227c478bd9Sstevel@tonic-gate STRVAL(rootdir), STRVAL(devname))); 17237c478bd9Sstevel@tonic-gate 17247c478bd9Sstevel@tonic-gate if (rootdir == NULL || devname == NULL || buf == NULL || bufsz == 0) 17257c478bd9Sstevel@tonic-gate return (-1); 17267c478bd9Sstevel@tonic-gate 17277c478bd9Sstevel@tonic-gate if (strcmp(rootdir, "/") == 0) 17287c478bd9Sstevel@tonic-gate rootdir = ""; 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate if (devname2physpath((char *)rootdir, (char *)devname, physpath, 17317c478bd9Sstevel@tonic-gate MAXPATHLEN) != 0) 17327c478bd9Sstevel@tonic-gate return (-1); 17337c478bd9Sstevel@tonic-gate 17347c478bd9Sstevel@tonic-gate #ifdef __sparc 17357c478bd9Sstevel@tonic-gate if (client_name_type(physpath) == CLIENT_TYPE_PHCI) { 17367c478bd9Sstevel@tonic-gate char *mapped_node_path, *minor; 17377c478bd9Sstevel@tonic-gate char minorbuf[MAXNAMELEN]; 17387c478bd9Sstevel@tonic-gate 17397c478bd9Sstevel@tonic-gate /* strip minor component if present */ 17407c478bd9Sstevel@tonic-gate if ((minor = strrchr(physpath, ':')) != NULL) { 17417c478bd9Sstevel@tonic-gate *minor = '\0'; 17427c478bd9Sstevel@tonic-gate minor++; 17437c478bd9Sstevel@tonic-gate (void) strlcpy(minorbuf, minor, MAXNAMELEN); 17447c478bd9Sstevel@tonic-gate } 17457c478bd9Sstevel@tonic-gate if ((mapped_node_path = phci_to_vhci(physpath)) != NULL) { 17467c478bd9Sstevel@tonic-gate if (minor) 17477c478bd9Sstevel@tonic-gate (void) snprintf(physpath, MAXPATHLEN, 17487c478bd9Sstevel@tonic-gate "%s:%s", mapped_node_path, minorbuf); 17497c478bd9Sstevel@tonic-gate else 17507c478bd9Sstevel@tonic-gate (void) strlcpy(physpath, mapped_node_path, 17517c478bd9Sstevel@tonic-gate MAXPATHLEN); 17527c478bd9Sstevel@tonic-gate free(mapped_node_path); 17537c478bd9Sstevel@tonic-gate logdmsg(("devfs_target2install: mapped physpath: %s\n", 17547c478bd9Sstevel@tonic-gate physpath)); 17557c478bd9Sstevel@tonic-gate 17567c478bd9Sstevel@tonic-gate } else if (minor) 17577c478bd9Sstevel@tonic-gate *(minor - 1) = ':'; 17587c478bd9Sstevel@tonic-gate } 17597c478bd9Sstevel@tonic-gate #endif /* __sparc */ 17607c478bd9Sstevel@tonic-gate 17617c478bd9Sstevel@tonic-gate return (get_install_devlink(physpath, buf, bufsz)); 17627c478bd9Sstevel@tonic-gate } 17637c478bd9Sstevel@tonic-gate 17647c478bd9Sstevel@tonic-gate /* 17657c478bd9Sstevel@tonic-gate * Map a device name (devname) from the install environment to the target 17667c478bd9Sstevel@tonic-gate * environment. 17677c478bd9Sstevel@tonic-gate * 17687c478bd9Sstevel@tonic-gate * rootdir root directory of the target environment 17697c478bd9Sstevel@tonic-gate * devname /dev or /devices name under the install environment 17707c478bd9Sstevel@tonic-gate * buf caller supplied buffer where the mapped /dev name is placed 17717c478bd9Sstevel@tonic-gate * on return 17727c478bd9Sstevel@tonic-gate * bufsz length of the buffer 17737c478bd9Sstevel@tonic-gate * 17747c478bd9Sstevel@tonic-gate * Returns strlen of the mapped /dev name on success, -1 on failure. 17757c478bd9Sstevel@tonic-gate */ 17767c478bd9Sstevel@tonic-gate int 17777c478bd9Sstevel@tonic-gate devfs_install2target(const char *rootdir, const char *devname, char *buf, 17787c478bd9Sstevel@tonic-gate size_t bufsz) 17797c478bd9Sstevel@tonic-gate { 17807c478bd9Sstevel@tonic-gate char physpath[MAXPATHLEN]; 17817c478bd9Sstevel@tonic-gate 17827c478bd9Sstevel@tonic-gate logdmsg(("devfs_install2target: rootdir = %s, devname = %s\n", 17837c478bd9Sstevel@tonic-gate STRVAL(rootdir), STRVAL(devname))); 17847c478bd9Sstevel@tonic-gate 17857c478bd9Sstevel@tonic-gate if (rootdir == NULL || devname == NULL || buf == NULL || bufsz == 0) 17867c478bd9Sstevel@tonic-gate return (-1); 17877c478bd9Sstevel@tonic-gate 17887c478bd9Sstevel@tonic-gate if (strcmp(rootdir, "/") == 0) 17897c478bd9Sstevel@tonic-gate rootdir = ""; 17907c478bd9Sstevel@tonic-gate 17917c478bd9Sstevel@tonic-gate if (devname2physpath("", (char *)devname, physpath, MAXPATHLEN) != 0) 17927c478bd9Sstevel@tonic-gate return (-1); 17937c478bd9Sstevel@tonic-gate 17947c478bd9Sstevel@tonic-gate #ifdef __sparc 17957c478bd9Sstevel@tonic-gate if (client_name_type(physpath) == CLIENT_TYPE_VHCI) { 17967c478bd9Sstevel@tonic-gate char **pathlist; 17977c478bd9Sstevel@tonic-gate int npaths, i, j; 17987c478bd9Sstevel@tonic-gate char *minor; 17997c478bd9Sstevel@tonic-gate char minorbuf[MAXNAMELEN]; 18007c478bd9Sstevel@tonic-gate 18017c478bd9Sstevel@tonic-gate /* strip minor component if present */ 18027c478bd9Sstevel@tonic-gate if ((minor = strrchr(physpath, ':')) != NULL) { 18037c478bd9Sstevel@tonic-gate *minor = '\0'; 18047c478bd9Sstevel@tonic-gate minor++; 18057c478bd9Sstevel@tonic-gate (void) strlcpy(minorbuf, minor, MAXNAMELEN); 18067c478bd9Sstevel@tonic-gate } 18077c478bd9Sstevel@tonic-gate 18087c478bd9Sstevel@tonic-gate if ((pathlist = vhci_to_phci(physpath, &npaths)) == NULL) 18097c478bd9Sstevel@tonic-gate return (-1); 18107c478bd9Sstevel@tonic-gate 18117c478bd9Sstevel@tonic-gate if ((npaths = build_pathlist((char *)rootdir, physpath, 18127c478bd9Sstevel@tonic-gate pathlist, npaths)) <= 0) { 18137c478bd9Sstevel@tonic-gate free_pathlist(pathlist); 18147c478bd9Sstevel@tonic-gate return (-1); 18157c478bd9Sstevel@tonic-gate } 18167c478bd9Sstevel@tonic-gate 18177c478bd9Sstevel@tonic-gate /* 18187c478bd9Sstevel@tonic-gate * in case of more than one path, try to use the path 18197c478bd9Sstevel@tonic-gate * referenced in the vfstab file, otherwise use the first path. 18207c478bd9Sstevel@tonic-gate */ 18217c478bd9Sstevel@tonic-gate j = 0; 18227c478bd9Sstevel@tonic-gate if (npaths > 1) { 18237c478bd9Sstevel@tonic-gate for (i = 0; i < npaths; i++) { 18247c478bd9Sstevel@tonic-gate if (is_dev_in_vfstab((char *)rootdir, 18257c478bd9Sstevel@tonic-gate pathlist[i])) { 18267c478bd9Sstevel@tonic-gate j = i; 18277c478bd9Sstevel@tonic-gate break; 18287c478bd9Sstevel@tonic-gate } 18297c478bd9Sstevel@tonic-gate } 18307c478bd9Sstevel@tonic-gate } 18317c478bd9Sstevel@tonic-gate 18327c478bd9Sstevel@tonic-gate if (minor) 18337c478bd9Sstevel@tonic-gate (void) snprintf(physpath, MAXPATHLEN, 18347c478bd9Sstevel@tonic-gate "%s:%s", pathlist[j], minorbuf); 18357c478bd9Sstevel@tonic-gate else 18367c478bd9Sstevel@tonic-gate (void) strlcpy(physpath, pathlist[j], MAXPATHLEN); 18377c478bd9Sstevel@tonic-gate free_pathlist(pathlist); 18387c478bd9Sstevel@tonic-gate } 18397c478bd9Sstevel@tonic-gate #endif /* __sparc */ 18407c478bd9Sstevel@tonic-gate 18417c478bd9Sstevel@tonic-gate return (get_target_devlink((char *)rootdir, physpath, buf, bufsz)); 18427c478bd9Sstevel@tonic-gate } 18437c478bd9Sstevel@tonic-gate 18447c478bd9Sstevel@tonic-gate #ifdef DEBUG 18457c478bd9Sstevel@tonic-gate 18467c478bd9Sstevel@tonic-gate static void 18477c478bd9Sstevel@tonic-gate vlog_debug_msg(char *fmt, va_list ap) 18487c478bd9Sstevel@tonic-gate { 18497c478bd9Sstevel@tonic-gate time_t clock; 18507c478bd9Sstevel@tonic-gate struct tm t; 18517c478bd9Sstevel@tonic-gate 18527c478bd9Sstevel@tonic-gate if (!devfsmap_debug) 18537c478bd9Sstevel@tonic-gate return; 18547c478bd9Sstevel@tonic-gate 18557c478bd9Sstevel@tonic-gate if (logfp == NULL) { 18567c478bd9Sstevel@tonic-gate if (*devfsmap_logfile != '\0') { 18577c478bd9Sstevel@tonic-gate logfp = fopen(devfsmap_logfile, "a"); 18587c478bd9Sstevel@tonic-gate if (logfp) 18597c478bd9Sstevel@tonic-gate (void) fprintf(logfp, "\nNew Log:\n"); 18607c478bd9Sstevel@tonic-gate } 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate if (logfp == NULL) 18637c478bd9Sstevel@tonic-gate logfp = stdout; 18647c478bd9Sstevel@tonic-gate } 18657c478bd9Sstevel@tonic-gate 18667c478bd9Sstevel@tonic-gate clock = time(NULL); 18677c478bd9Sstevel@tonic-gate (void) localtime_r(&clock, &t); 18687c478bd9Sstevel@tonic-gate (void) fprintf(logfp, "%02d:%02d:%02d ", t.tm_hour, t.tm_min, 18697c478bd9Sstevel@tonic-gate t.tm_sec); 18707c478bd9Sstevel@tonic-gate (void) vfprintf(logfp, fmt, ap); 18717c478bd9Sstevel@tonic-gate (void) fflush(logfp); 18727c478bd9Sstevel@tonic-gate } 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate static void 18757c478bd9Sstevel@tonic-gate log_debug_msg(char *fmt, ...) 18767c478bd9Sstevel@tonic-gate { 18777c478bd9Sstevel@tonic-gate va_list ap; 18787c478bd9Sstevel@tonic-gate 18797c478bd9Sstevel@tonic-gate va_start(ap, fmt); 18807c478bd9Sstevel@tonic-gate vlog_debug_msg(fmt, ap); 18817c478bd9Sstevel@tonic-gate va_end(ap); 18827c478bd9Sstevel@tonic-gate } 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate #ifdef __sparc 18857c478bd9Sstevel@tonic-gate 18867c478bd9Sstevel@tonic-gate static char * 18877c478bd9Sstevel@tonic-gate mpxio_disable_string(int mpxio_disable) 18887c478bd9Sstevel@tonic-gate { 18897c478bd9Sstevel@tonic-gate if (mpxio_disable == 0) 18907c478bd9Sstevel@tonic-gate return ("no"); 18917c478bd9Sstevel@tonic-gate else if (mpxio_disable == 1) 18927c478bd9Sstevel@tonic-gate return ("yes"); 18937c478bd9Sstevel@tonic-gate else 18947c478bd9Sstevel@tonic-gate return ("not specified"); 18957c478bd9Sstevel@tonic-gate } 18967c478bd9Sstevel@tonic-gate 18977c478bd9Sstevel@tonic-gate static void 18987c478bd9Sstevel@tonic-gate log_confent_list(char *filename, struct conf_entry *confent_list, 18997c478bd9Sstevel@tonic-gate int global_mpxio_disable) 19007c478bd9Sstevel@tonic-gate { 19017c478bd9Sstevel@tonic-gate struct conf_entry *confent; 19027c478bd9Sstevel@tonic-gate 19037c478bd9Sstevel@tonic-gate log_debug_msg("log_confent_list: filename = %s:\n", filename); 19047c478bd9Sstevel@tonic-gate if (global_mpxio_disable != -1) 19057c478bd9Sstevel@tonic-gate log_debug_msg("\tdriver global mpxio_disable = \"%s\"\n\n", 19067c478bd9Sstevel@tonic-gate mpxio_disable_string(global_mpxio_disable)); 19077c478bd9Sstevel@tonic-gate 19087c478bd9Sstevel@tonic-gate for (confent = confent_list; confent != NULL; confent = confent->next) { 19097c478bd9Sstevel@tonic-gate if (confent->name) 19107c478bd9Sstevel@tonic-gate log_debug_msg("\tname = %s\n", confent->name); 19117c478bd9Sstevel@tonic-gate if (confent->parent) 19127c478bd9Sstevel@tonic-gate log_debug_msg("\tparent = %s\n", confent->parent); 19137c478bd9Sstevel@tonic-gate if (confent->class) 19147c478bd9Sstevel@tonic-gate log_debug_msg("\tclass = %s\n", confent->class); 19157c478bd9Sstevel@tonic-gate if (confent->unit_address) 19167c478bd9Sstevel@tonic-gate log_debug_msg("\tunit_address = %s\n", 19177c478bd9Sstevel@tonic-gate confent->unit_address); 19187c478bd9Sstevel@tonic-gate if (confent->port != -1) 19197c478bd9Sstevel@tonic-gate log_debug_msg("\tport = %d\n", confent->port); 19207c478bd9Sstevel@tonic-gate log_debug_msg("\tmpxio_disable = \"%s\"\n\n", 19217c478bd9Sstevel@tonic-gate mpxio_disable_string(confent->mpxio_disable)); 19227c478bd9Sstevel@tonic-gate } 19237c478bd9Sstevel@tonic-gate } 19247c478bd9Sstevel@tonic-gate 19257c478bd9Sstevel@tonic-gate static void 19267c478bd9Sstevel@tonic-gate log_pathlist(char **pathlist) 19277c478bd9Sstevel@tonic-gate { 19287c478bd9Sstevel@tonic-gate char **p; 19297c478bd9Sstevel@tonic-gate 19307c478bd9Sstevel@tonic-gate for (p = pathlist; *p != NULL; p++) 19317c478bd9Sstevel@tonic-gate log_debug_msg("\t%s\n", *p); 19327c478bd9Sstevel@tonic-gate } 19337c478bd9Sstevel@tonic-gate 19347c478bd9Sstevel@tonic-gate #endif /* __sparc */ 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1937