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