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 51aef0e11Sjg * Common Development and Distribution License (the "License"). 61aef0e11Sjg * 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*72916ffbSGangadhar Mylapuram * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate #ifdef lint 267c478bd9Sstevel@tonic-gate #define _REENTRANT /* for localtime_r */ 277c478bd9Sstevel@tonic-gate #endif 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <stdio.h> 307c478bd9Sstevel@tonic-gate #include <ctype.h> 317c478bd9Sstevel@tonic-gate #include <stdlib.h> 327c478bd9Sstevel@tonic-gate #include <sys/types.h> 337c478bd9Sstevel@tonic-gate #include <strings.h> 347c478bd9Sstevel@tonic-gate #include <stdarg.h> 357c478bd9Sstevel@tonic-gate #include <sys/stat.h> 367c478bd9Sstevel@tonic-gate #include <fcntl.h> 377c478bd9Sstevel@tonic-gate #include <errno.h> 387c478bd9Sstevel@tonic-gate #include <unistd.h> 397c478bd9Sstevel@tonic-gate #include <stropts.h> 407c478bd9Sstevel@tonic-gate #include <time.h> 417c478bd9Sstevel@tonic-gate #include <sys/param.h> 427c478bd9Sstevel@tonic-gate #include <sys/vfstab.h> 437c478bd9Sstevel@tonic-gate #include <dirent.h> 447c478bd9Sstevel@tonic-gate #ifdef __sparc 457c478bd9Sstevel@tonic-gate #include <sys/scsi/adapters/scsi_vhci.h> 467c478bd9Sstevel@tonic-gate #include <sys/sunmdi.h> 477c478bd9Sstevel@tonic-gate #endif /* __sparc */ 487c478bd9Sstevel@tonic-gate #include "libdevinfo.h" 497c478bd9Sstevel@tonic-gate #include "device_info.h" 501aef0e11Sjg #include <regex.h> 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #define isnewline(ch) ((ch) == '\n' || (ch) == '\r' || (ch) == '\f') 537c478bd9Sstevel@tonic-gate #define isnamechar(ch) (isalpha(ch) || isdigit(ch) || (ch) == '_' ||\ 547c478bd9Sstevel@tonic-gate (ch) == '-') 557c478bd9Sstevel@tonic-gate #define MAX_TOKEN_SIZE 1024 567c478bd9Sstevel@tonic-gate #define BUFSIZE 1024 577c478bd9Sstevel@tonic-gate #define STRVAL(s) ((s) ? (s) : "NULL") 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate #define SCSI_VHCI_CONF "/kernel/drv/scsi_vhci.conf" 607c478bd9Sstevel@tonic-gate #define QLC_CONF "/kernel/drv/qlc.conf" 617c478bd9Sstevel@tonic-gate #define FP_CONF "/kernel/drv/fp.conf" 627c478bd9Sstevel@tonic-gate #define DRIVER_CLASSES "/etc/driver_classes" 637c478bd9Sstevel@tonic-gate #define FP_AT "fp@" 647c478bd9Sstevel@tonic-gate #define VHCI_CTL_NODE "/devices/scsi_vhci:devctl" 657c478bd9Sstevel@tonic-gate #define SLASH_DEVICES "/devices" 667c478bd9Sstevel@tonic-gate #define SLASH_DEVICES_SLASH "/devices/" 677c478bd9Sstevel@tonic-gate #define SLASH_FP_AT "/fp@" 687c478bd9Sstevel@tonic-gate #define SLASH_SCSI_VHCI "/scsi_vhci" 697c478bd9Sstevel@tonic-gate #define META_DEV "/dev/md/dsk/" 707c478bd9Sstevel@tonic-gate #define SLASH_DEV_SLASH "/dev/" 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate /* 737c478bd9Sstevel@tonic-gate * Macros to produce a quoted string containing the value of a 747c478bd9Sstevel@tonic-gate * preprocessor macro. For example, if SIZE is defined to be 256, 757c478bd9Sstevel@tonic-gate * VAL2STR(SIZE) is "256". This is used to construct format 767c478bd9Sstevel@tonic-gate * strings for scanf-family functions below. 777c478bd9Sstevel@tonic-gate */ 787c478bd9Sstevel@tonic-gate #define QUOTE(x) #x 797c478bd9Sstevel@tonic-gate #define VAL2STR(x) QUOTE(x) 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate typedef enum { 827c478bd9Sstevel@tonic-gate CLIENT_TYPE_UNKNOWN, 837c478bd9Sstevel@tonic-gate CLIENT_TYPE_PHCI, 847c478bd9Sstevel@tonic-gate CLIENT_TYPE_VHCI 857c478bd9Sstevel@tonic-gate } client_type_t; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate typedef enum { 887c478bd9Sstevel@tonic-gate T_EQUALS, 897c478bd9Sstevel@tonic-gate T_AMPERSAND, 907c478bd9Sstevel@tonic-gate T_BIT_OR, 917c478bd9Sstevel@tonic-gate T_STAR, 927c478bd9Sstevel@tonic-gate T_POUND, 937c478bd9Sstevel@tonic-gate T_COLON, 947c478bd9Sstevel@tonic-gate T_SEMICOLON, 957c478bd9Sstevel@tonic-gate T_COMMA, 967c478bd9Sstevel@tonic-gate T_SLASH, 977c478bd9Sstevel@tonic-gate T_WHITE_SPACE, 987c478bd9Sstevel@tonic-gate T_NEWLINE, 997c478bd9Sstevel@tonic-gate T_EOF, 1007c478bd9Sstevel@tonic-gate T_STRING, 1017c478bd9Sstevel@tonic-gate T_HEXVAL, 1027c478bd9Sstevel@tonic-gate T_DECVAL, 1037c478bd9Sstevel@tonic-gate T_NAME 1047c478bd9Sstevel@tonic-gate } token_t; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate typedef enum { 1077c478bd9Sstevel@tonic-gate begin, parent, drvname, drvclass, prop, 1087c478bd9Sstevel@tonic-gate parent_equals, name_equals, drvclass_equals, 1097c478bd9Sstevel@tonic-gate parent_equals_string, name_equals_string, 1107c478bd9Sstevel@tonic-gate drvclass_equals_string, 1117c478bd9Sstevel@tonic-gate prop_equals, prop_equals_string, prop_equals_integer, 1127c478bd9Sstevel@tonic-gate prop_equals_string_comma, prop_equals_integer_comma 1137c478bd9Sstevel@tonic-gate } conf_state_t; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* structure to hold entries with mpxio-disable property in driver.conf file */ 1167c478bd9Sstevel@tonic-gate struct conf_entry { 1177c478bd9Sstevel@tonic-gate char *name; 1187c478bd9Sstevel@tonic-gate char *parent; 1197c478bd9Sstevel@tonic-gate char *class; 1207c478bd9Sstevel@tonic-gate char *unit_address; 1217c478bd9Sstevel@tonic-gate int port; 1227c478bd9Sstevel@tonic-gate int mpxio_disable; 1237c478bd9Sstevel@tonic-gate struct conf_entry *next; 1247c478bd9Sstevel@tonic-gate }; 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate struct conf_file { 1277c478bd9Sstevel@tonic-gate char *filename; 1287c478bd9Sstevel@tonic-gate FILE *fp; 1297c478bd9Sstevel@tonic-gate int linenum; 1307c478bd9Sstevel@tonic-gate }; 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate static char *tok_err = "Unexpected token '%s'\n"; 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate /* #define DEBUG */ 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate #ifdef DEBUG 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate int devfsmap_debug = 0; 1407c478bd9Sstevel@tonic-gate /* /var/run is not mounted at install time. Therefore use /tmp */ 1417c478bd9Sstevel@tonic-gate char *devfsmap_logfile = "/tmp/devfsmap.log"; 1427c478bd9Sstevel@tonic-gate static FILE *logfp; 1437c478bd9Sstevel@tonic-gate #define logdmsg(args) log_debug_msg args 1447c478bd9Sstevel@tonic-gate static void vlog_debug_msg(char *, va_list); 1457c478bd9Sstevel@tonic-gate static void log_debug_msg(char *, ...); 1467c478bd9Sstevel@tonic-gate #ifdef __sparc 1477c478bd9Sstevel@tonic-gate static void log_confent_list(char *, struct conf_entry *, int); 1487c478bd9Sstevel@tonic-gate static void log_pathlist(char **); 1497c478bd9Sstevel@tonic-gate #endif /* __sparc */ 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate #else /* DEBUG */ 1527c478bd9Sstevel@tonic-gate #define logdmsg(args) /* nothing */ 1537c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate /* 1577c478bd9Sstevel@tonic-gate * Leave NEWLINE as the next character. 1587c478bd9Sstevel@tonic-gate */ 1597c478bd9Sstevel@tonic-gate static void 1607c478bd9Sstevel@tonic-gate find_eol(FILE *fp) 1617c478bd9Sstevel@tonic-gate { 1627c478bd9Sstevel@tonic-gate int ch; 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate while ((ch = getc(fp)) != EOF) { 1657c478bd9Sstevel@tonic-gate if (isnewline(ch)) { 1667c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 1677c478bd9Sstevel@tonic-gate break; 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* ignore parsing errors */ 1737c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1747c478bd9Sstevel@tonic-gate static void 1757c478bd9Sstevel@tonic-gate file_err(struct conf_file *filep, char *fmt, ...) 1767c478bd9Sstevel@tonic-gate { 1777c478bd9Sstevel@tonic-gate #ifdef DEBUG 1787c478bd9Sstevel@tonic-gate va_list ap; 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate va_start(ap, fmt); 1817c478bd9Sstevel@tonic-gate log_debug_msg("WARNING: %s line # %d: ", 1827c478bd9Sstevel@tonic-gate filep->filename, filep->linenum); 1837c478bd9Sstevel@tonic-gate vlog_debug_msg(fmt, ap); 1847c478bd9Sstevel@tonic-gate va_end(ap); 1857c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* return the next token from the given driver.conf file, or -1 on error */ 1897c478bd9Sstevel@tonic-gate static token_t 1907c478bd9Sstevel@tonic-gate lex(struct conf_file *filep, char *val, size_t size) 1917c478bd9Sstevel@tonic-gate { 1927c478bd9Sstevel@tonic-gate char *cp; 1937c478bd9Sstevel@tonic-gate int ch, oval, badquote; 1947c478bd9Sstevel@tonic-gate size_t remain; 1957c478bd9Sstevel@tonic-gate token_t token; 1967c478bd9Sstevel@tonic-gate FILE *fp = filep->fp; 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate if (size < 2) 1997c478bd9Sstevel@tonic-gate return (-1); 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate cp = val; 2027c478bd9Sstevel@tonic-gate while ((ch = getc(fp)) == ' ' || ch == '\t') 2037c478bd9Sstevel@tonic-gate ; 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate remain = size - 1; 2067c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 2077c478bd9Sstevel@tonic-gate switch (ch) { 2087c478bd9Sstevel@tonic-gate case '=': 2097c478bd9Sstevel@tonic-gate token = T_EQUALS; 2107c478bd9Sstevel@tonic-gate break; 2117c478bd9Sstevel@tonic-gate case '&': 2127c478bd9Sstevel@tonic-gate token = T_AMPERSAND; 2137c478bd9Sstevel@tonic-gate break; 2147c478bd9Sstevel@tonic-gate case '|': 2157c478bd9Sstevel@tonic-gate token = T_BIT_OR; 2167c478bd9Sstevel@tonic-gate break; 2177c478bd9Sstevel@tonic-gate case '*': 2187c478bd9Sstevel@tonic-gate token = T_STAR; 2197c478bd9Sstevel@tonic-gate break; 2207c478bd9Sstevel@tonic-gate case '#': 2217c478bd9Sstevel@tonic-gate token = T_POUND; 2227c478bd9Sstevel@tonic-gate break; 2237c478bd9Sstevel@tonic-gate case ':': 2247c478bd9Sstevel@tonic-gate token = T_COLON; 2257c478bd9Sstevel@tonic-gate break; 2267c478bd9Sstevel@tonic-gate case ';': 2277c478bd9Sstevel@tonic-gate token = T_SEMICOLON; 2287c478bd9Sstevel@tonic-gate break; 2297c478bd9Sstevel@tonic-gate case ',': 2307c478bd9Sstevel@tonic-gate token = T_COMMA; 2317c478bd9Sstevel@tonic-gate break; 2327c478bd9Sstevel@tonic-gate case '/': 2337c478bd9Sstevel@tonic-gate token = T_SLASH; 2347c478bd9Sstevel@tonic-gate break; 2357c478bd9Sstevel@tonic-gate case ' ': 2367c478bd9Sstevel@tonic-gate case '\t': 2377c478bd9Sstevel@tonic-gate case '\f': 2387c478bd9Sstevel@tonic-gate while ((ch = getc(fp)) == ' ' || 2397c478bd9Sstevel@tonic-gate ch == '\t' || ch == '\f') { 2407c478bd9Sstevel@tonic-gate if (--remain == 0) { 2417c478bd9Sstevel@tonic-gate *cp = '\0'; 2427c478bd9Sstevel@tonic-gate return (-1); 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 2477c478bd9Sstevel@tonic-gate token = T_WHITE_SPACE; 2487c478bd9Sstevel@tonic-gate break; 2497c478bd9Sstevel@tonic-gate case '\n': 2507c478bd9Sstevel@tonic-gate case '\r': 2517c478bd9Sstevel@tonic-gate token = T_NEWLINE; 2527c478bd9Sstevel@tonic-gate break; 2537c478bd9Sstevel@tonic-gate case '"': 2547c478bd9Sstevel@tonic-gate remain++; 2557c478bd9Sstevel@tonic-gate cp--; 2567c478bd9Sstevel@tonic-gate badquote = 0; 2577c478bd9Sstevel@tonic-gate while (!badquote && (ch = getc(fp)) != '"') { 2587c478bd9Sstevel@tonic-gate switch (ch) { 2597c478bd9Sstevel@tonic-gate case '\n': 2607c478bd9Sstevel@tonic-gate case EOF: 2617c478bd9Sstevel@tonic-gate file_err(filep, "Missing \"\n"); 2627c478bd9Sstevel@tonic-gate remain = size - 1; 2637c478bd9Sstevel@tonic-gate cp = val; 2647c478bd9Sstevel@tonic-gate *cp++ = '\n'; 2657c478bd9Sstevel@tonic-gate badquote = 1; 2667c478bd9Sstevel@tonic-gate /* since we consumed the newline/EOF */ 2677c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 2687c478bd9Sstevel@tonic-gate break; 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate case '\\': 2717c478bd9Sstevel@tonic-gate if (--remain == 0) { 2727c478bd9Sstevel@tonic-gate *cp = '\0'; 2737c478bd9Sstevel@tonic-gate return (-1); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate ch = (char)getc(fp); 2767c478bd9Sstevel@tonic-gate if (!isdigit(ch)) { 2777c478bd9Sstevel@tonic-gate /* escape the character */ 2787c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 2797c478bd9Sstevel@tonic-gate break; 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate oval = 0; 2827c478bd9Sstevel@tonic-gate while (ch >= '0' && ch <= '7') { 2837c478bd9Sstevel@tonic-gate ch -= '0'; 2847c478bd9Sstevel@tonic-gate oval = (oval << 3) + ch; 2857c478bd9Sstevel@tonic-gate ch = (char)getc(fp); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 2887c478bd9Sstevel@tonic-gate /* check for character overflow? */ 2897c478bd9Sstevel@tonic-gate if (oval > 127) { 2907c478bd9Sstevel@tonic-gate file_err(filep, 2917c478bd9Sstevel@tonic-gate "Character " 2927c478bd9Sstevel@tonic-gate "overflow detected.\n"); 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate *cp++ = (char)oval; 2957c478bd9Sstevel@tonic-gate break; 2967c478bd9Sstevel@tonic-gate default: 2977c478bd9Sstevel@tonic-gate if (--remain == 0) { 2987c478bd9Sstevel@tonic-gate *cp = '\0'; 2997c478bd9Sstevel@tonic-gate return (-1); 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 3027c478bd9Sstevel@tonic-gate break; 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate token = T_STRING; 3067c478bd9Sstevel@tonic-gate break; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate case EOF: 3097c478bd9Sstevel@tonic-gate token = T_EOF; 3107c478bd9Sstevel@tonic-gate break; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate default: 3137c478bd9Sstevel@tonic-gate /* 3147c478bd9Sstevel@tonic-gate * detect a lone '-' (including at the end of a line), and 3157c478bd9Sstevel@tonic-gate * identify it as a 'name' 3167c478bd9Sstevel@tonic-gate */ 3177c478bd9Sstevel@tonic-gate if (ch == '-') { 3187c478bd9Sstevel@tonic-gate if (--remain == 0) { 3197c478bd9Sstevel@tonic-gate *cp = '\0'; 3207c478bd9Sstevel@tonic-gate return (-1); 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate *cp++ = (char)(ch = getc(fp)); 3237c478bd9Sstevel@tonic-gate if (ch == ' ' || ch == '\t' || ch == '\n') { 3247c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 3257c478bd9Sstevel@tonic-gate remain++; 3267c478bd9Sstevel@tonic-gate cp--; 3277c478bd9Sstevel@tonic-gate token = T_NAME; 3287c478bd9Sstevel@tonic-gate break; 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate } else if (ch == '~' || ch == '-') { 3317c478bd9Sstevel@tonic-gate if (--remain == 0) { 3327c478bd9Sstevel@tonic-gate *cp = '\0'; 3337c478bd9Sstevel@tonic-gate return (-1); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate *cp++ = (char)(ch = getc(fp)); 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate if (isdigit(ch)) { 3407c478bd9Sstevel@tonic-gate if (ch == '0') { 3417c478bd9Sstevel@tonic-gate if ((ch = getc(fp)) == 'x') { 3427c478bd9Sstevel@tonic-gate if (--remain == 0) { 3437c478bd9Sstevel@tonic-gate *cp = '\0'; 3447c478bd9Sstevel@tonic-gate return (-1); 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 3477c478bd9Sstevel@tonic-gate ch = getc(fp); 3487c478bd9Sstevel@tonic-gate while (isxdigit(ch)) { 3497c478bd9Sstevel@tonic-gate if (--remain == 0) { 3507c478bd9Sstevel@tonic-gate *cp = '\0'; 3517c478bd9Sstevel@tonic-gate return (-1); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 3547c478bd9Sstevel@tonic-gate ch = getc(fp); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 3577c478bd9Sstevel@tonic-gate token = T_HEXVAL; 3587c478bd9Sstevel@tonic-gate } else { 3597c478bd9Sstevel@tonic-gate goto digit; 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate } else { 3627c478bd9Sstevel@tonic-gate ch = getc(fp); 3637c478bd9Sstevel@tonic-gate digit: 3647c478bd9Sstevel@tonic-gate while (isdigit(ch)) { 3657c478bd9Sstevel@tonic-gate if (--remain == 0) { 3667c478bd9Sstevel@tonic-gate *cp = '\0'; 3677c478bd9Sstevel@tonic-gate return (-1); 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 3707c478bd9Sstevel@tonic-gate ch = getc(fp); 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 3737c478bd9Sstevel@tonic-gate token = T_DECVAL; 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate } else if (isalpha(ch) || ch == '\\') { 3767c478bd9Sstevel@tonic-gate if (ch != '\\') { 3777c478bd9Sstevel@tonic-gate ch = getc(fp); 3787c478bd9Sstevel@tonic-gate } else { 3797c478bd9Sstevel@tonic-gate /* 3807c478bd9Sstevel@tonic-gate * if the character was a backslash, 3817c478bd9Sstevel@tonic-gate * back up so we can overwrite it with 3827c478bd9Sstevel@tonic-gate * the next (i.e. escaped) character. 3837c478bd9Sstevel@tonic-gate */ 3847c478bd9Sstevel@tonic-gate remain++; 3857c478bd9Sstevel@tonic-gate cp--; 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate while (isnamechar(ch) || ch == '\\') { 3887c478bd9Sstevel@tonic-gate if (ch == '\\') 3897c478bd9Sstevel@tonic-gate ch = getc(fp); 3907c478bd9Sstevel@tonic-gate if (--remain == 0) { 3917c478bd9Sstevel@tonic-gate *cp = '\0'; 3927c478bd9Sstevel@tonic-gate return (-1); 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 3957c478bd9Sstevel@tonic-gate ch = getc(fp); 3967c478bd9Sstevel@tonic-gate } 3977c478bd9Sstevel@tonic-gate (void) ungetc(ch, fp); 3987c478bd9Sstevel@tonic-gate token = T_NAME; 3997c478bd9Sstevel@tonic-gate } else { 4007c478bd9Sstevel@tonic-gate return (-1); 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate break; 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate *cp = '\0'; 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate return (token); 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4101aef0e11Sjg #ifdef __sparc 4111aef0e11Sjg 4127c478bd9Sstevel@tonic-gate static void 4137c478bd9Sstevel@tonic-gate free_confent(struct conf_entry *confent) 4147c478bd9Sstevel@tonic-gate { 4157c478bd9Sstevel@tonic-gate if (confent->name) 4167c478bd9Sstevel@tonic-gate free(confent->name); 4177c478bd9Sstevel@tonic-gate if (confent->parent) 4187c478bd9Sstevel@tonic-gate free(confent->parent); 4197c478bd9Sstevel@tonic-gate if (confent->class) 4207c478bd9Sstevel@tonic-gate free(confent->class); 4217c478bd9Sstevel@tonic-gate if (confent->unit_address) 4227c478bd9Sstevel@tonic-gate free(confent->unit_address); 4237c478bd9Sstevel@tonic-gate free(confent); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate static void 4277c478bd9Sstevel@tonic-gate free_confent_list(struct conf_entry *confent_list) 4287c478bd9Sstevel@tonic-gate { 4297c478bd9Sstevel@tonic-gate struct conf_entry *confent, *next; 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate for (confent = confent_list; confent != NULL; confent = next) { 4327c478bd9Sstevel@tonic-gate next = confent->next; 4337c478bd9Sstevel@tonic-gate free_confent(confent); 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate /* 4387c478bd9Sstevel@tonic-gate * Parse the next entry from the driver.conf file and return in the form of 4397c478bd9Sstevel@tonic-gate * a pointer to the conf_entry. 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate static struct conf_entry * 4427c478bd9Sstevel@tonic-gate parse_conf_entry(struct conf_file *filep, char *tokbuf, size_t linesize) 4437c478bd9Sstevel@tonic-gate { 4447c478bd9Sstevel@tonic-gate char *prop_name, *string; 4457c478bd9Sstevel@tonic-gate token_t token; 4467c478bd9Sstevel@tonic-gate struct conf_entry *confent; 4477c478bd9Sstevel@tonic-gate conf_state_t state; 4487c478bd9Sstevel@tonic-gate int failed = 1; 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate if ((confent = calloc(1, sizeof (*confent))) == NULL) 4517c478bd9Sstevel@tonic-gate return (NULL); 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate confent->port = -1; 4547c478bd9Sstevel@tonic-gate confent->mpxio_disable = -1; 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate state = begin; 4577c478bd9Sstevel@tonic-gate token = T_NAME; 4587c478bd9Sstevel@tonic-gate prop_name = NULL; 4597c478bd9Sstevel@tonic-gate string = NULL; 4607c478bd9Sstevel@tonic-gate do { 4617c478bd9Sstevel@tonic-gate switch (token) { 4627c478bd9Sstevel@tonic-gate case T_NAME: 4637c478bd9Sstevel@tonic-gate switch (state) { 4647c478bd9Sstevel@tonic-gate case prop_equals_string: 4657c478bd9Sstevel@tonic-gate case prop_equals_integer: 4667c478bd9Sstevel@tonic-gate case begin: 4677c478bd9Sstevel@tonic-gate state = prop; 4687c478bd9Sstevel@tonic-gate if ((prop_name = strdup(tokbuf)) == NULL) 4697c478bd9Sstevel@tonic-gate goto bad; 4707c478bd9Sstevel@tonic-gate break; 4717c478bd9Sstevel@tonic-gate default: 4727c478bd9Sstevel@tonic-gate file_err(filep, tok_err, tokbuf); 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate break; 4757c478bd9Sstevel@tonic-gate case T_EQUALS: 4767c478bd9Sstevel@tonic-gate switch (state) { 4777c478bd9Sstevel@tonic-gate case prop: 4787c478bd9Sstevel@tonic-gate state = prop_equals; 4797c478bd9Sstevel@tonic-gate break; 4807c478bd9Sstevel@tonic-gate default: 4817c478bd9Sstevel@tonic-gate file_err(filep, tok_err, tokbuf); 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate break; 4847c478bd9Sstevel@tonic-gate case T_STRING: 4857c478bd9Sstevel@tonic-gate switch (state) { 4867c478bd9Sstevel@tonic-gate case prop_equals: 4877c478bd9Sstevel@tonic-gate if ((string = strdup(tokbuf)) == NULL) 4887c478bd9Sstevel@tonic-gate goto bad; 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate state = begin; 4917c478bd9Sstevel@tonic-gate if (strcmp(prop_name, "PARENT") == 0 || 4927c478bd9Sstevel@tonic-gate strcmp(prop_name, "parent") == 0) { 4937c478bd9Sstevel@tonic-gate if (confent->parent) { 4947c478bd9Sstevel@tonic-gate file_err(filep, 4957c478bd9Sstevel@tonic-gate "'parent' property already specified\n"); 4967c478bd9Sstevel@tonic-gate goto bad; 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate confent->parent = string; 4997c478bd9Sstevel@tonic-gate } else if (strcmp(prop_name, "NAME") == 0 || 5007c478bd9Sstevel@tonic-gate strcmp(prop_name, "name") == 0) { 5017c478bd9Sstevel@tonic-gate if (confent->name) { 5027c478bd9Sstevel@tonic-gate file_err(filep, 5037c478bd9Sstevel@tonic-gate "'name' property already specified\n"); 5047c478bd9Sstevel@tonic-gate goto bad; 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate confent->name = string; 5077c478bd9Sstevel@tonic-gate } else if (strcmp(prop_name, "CLASS") == 0 || 5087c478bd9Sstevel@tonic-gate strcmp(prop_name, "class") == 0) { 5097c478bd9Sstevel@tonic-gate if (confent->class) { 5107c478bd9Sstevel@tonic-gate file_err(filep, 5117c478bd9Sstevel@tonic-gate "'class' property already specified\n"); 5127c478bd9Sstevel@tonic-gate goto bad; 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate confent->class = string; 5157c478bd9Sstevel@tonic-gate } else if (strcmp(prop_name, "unit-address") 5167c478bd9Sstevel@tonic-gate == 0) { 5177c478bd9Sstevel@tonic-gate if (confent->unit_address) { 5187c478bd9Sstevel@tonic-gate file_err(filep, 5197c478bd9Sstevel@tonic-gate "'unit-address' property already specified\n"); 5207c478bd9Sstevel@tonic-gate goto bad; 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate confent->unit_address = string; 5237c478bd9Sstevel@tonic-gate } else if (strcmp(prop_name, "mpxio-disable") 5247c478bd9Sstevel@tonic-gate == 0) { 5257c478bd9Sstevel@tonic-gate if (confent->mpxio_disable != -1) { 5267c478bd9Sstevel@tonic-gate file_err(filep, 5277c478bd9Sstevel@tonic-gate "'mpxio-disable' property already specified\n"); 5287c478bd9Sstevel@tonic-gate goto bad; 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate if (strcmp(string, "yes") == 0) 5317c478bd9Sstevel@tonic-gate confent->mpxio_disable = 1; 5327c478bd9Sstevel@tonic-gate else if (strcmp(string, "no") == 0) 5337c478bd9Sstevel@tonic-gate confent->mpxio_disable = 0; 5347c478bd9Sstevel@tonic-gate else { 5357c478bd9Sstevel@tonic-gate file_err(filep, 5367c478bd9Sstevel@tonic-gate "'mpxio-disable' property setting is invalid. " 5377c478bd9Sstevel@tonic-gate "The value must be either \"yes\" or \"no\"\n"); 5387c478bd9Sstevel@tonic-gate goto bad; 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate free(string); 5417c478bd9Sstevel@tonic-gate } else { 5427c478bd9Sstevel@tonic-gate free(string); 5437c478bd9Sstevel@tonic-gate state = prop_equals_string; 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate string = NULL; 5467c478bd9Sstevel@tonic-gate free(prop_name); 5477c478bd9Sstevel@tonic-gate prop_name = NULL; 5487c478bd9Sstevel@tonic-gate break; 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate case prop_equals_string_comma: 5517c478bd9Sstevel@tonic-gate state = prop_equals_string; 5527c478bd9Sstevel@tonic-gate break; 5537c478bd9Sstevel@tonic-gate default: 5547c478bd9Sstevel@tonic-gate file_err(filep, tok_err, tokbuf); 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate break; 5577c478bd9Sstevel@tonic-gate case T_HEXVAL: 5587c478bd9Sstevel@tonic-gate case T_DECVAL: 5597c478bd9Sstevel@tonic-gate switch (state) { 5607c478bd9Sstevel@tonic-gate case prop_equals: 5617c478bd9Sstevel@tonic-gate if (strcmp(prop_name, "port") == 0) { 5627c478bd9Sstevel@tonic-gate if (confent->port != -1) { 5637c478bd9Sstevel@tonic-gate file_err(filep, 5647c478bd9Sstevel@tonic-gate "'port' property already specified\n"); 5657c478bd9Sstevel@tonic-gate goto bad; 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate confent->port = 5687c478bd9Sstevel@tonic-gate (int)strtol(tokbuf, NULL, 0); 5697c478bd9Sstevel@tonic-gate state = begin; 5707c478bd9Sstevel@tonic-gate } else 5717c478bd9Sstevel@tonic-gate state = prop_equals_integer; 5727c478bd9Sstevel@tonic-gate free(prop_name); 5737c478bd9Sstevel@tonic-gate prop_name = NULL; 5747c478bd9Sstevel@tonic-gate break; 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate case prop_equals_integer_comma: 5777c478bd9Sstevel@tonic-gate state = prop_equals_integer; 5787c478bd9Sstevel@tonic-gate break; 5797c478bd9Sstevel@tonic-gate default: 5807c478bd9Sstevel@tonic-gate file_err(filep, tok_err, tokbuf); 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate break; 5837c478bd9Sstevel@tonic-gate case T_COMMA: 5847c478bd9Sstevel@tonic-gate switch (state) { 5857c478bd9Sstevel@tonic-gate case prop_equals_string: 5867c478bd9Sstevel@tonic-gate state = prop_equals_string_comma; 5877c478bd9Sstevel@tonic-gate break; 5887c478bd9Sstevel@tonic-gate case prop_equals_integer: 5897c478bd9Sstevel@tonic-gate state = prop_equals_integer_comma; 5907c478bd9Sstevel@tonic-gate break; 5917c478bd9Sstevel@tonic-gate default: 5927c478bd9Sstevel@tonic-gate file_err(filep, tok_err, tokbuf); 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate break; 5957c478bd9Sstevel@tonic-gate case T_NEWLINE: 5967c478bd9Sstevel@tonic-gate filep->linenum++; 5977c478bd9Sstevel@tonic-gate break; 5987c478bd9Sstevel@tonic-gate case T_POUND: 5997c478bd9Sstevel@tonic-gate find_eol(filep->fp); 6007c478bd9Sstevel@tonic-gate break; 6017c478bd9Sstevel@tonic-gate case T_EOF: 6027c478bd9Sstevel@tonic-gate file_err(filep, "Unexpected EOF\n"); 6037c478bd9Sstevel@tonic-gate goto bad; 6047c478bd9Sstevel@tonic-gate default: 6057c478bd9Sstevel@tonic-gate file_err(filep, tok_err, tokbuf); 6067c478bd9Sstevel@tonic-gate goto bad; 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate } while ((token = lex(filep, tokbuf, linesize)) != T_SEMICOLON); 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate failed = 0; 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate bad: 6137c478bd9Sstevel@tonic-gate if (prop_name) 6147c478bd9Sstevel@tonic-gate free(prop_name); 6157c478bd9Sstevel@tonic-gate if (string) 6167c478bd9Sstevel@tonic-gate free(string); 6177c478bd9Sstevel@tonic-gate if (failed == 1) { 6187c478bd9Sstevel@tonic-gate free_confent(confent); 6197c478bd9Sstevel@tonic-gate return (NULL); 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate return (confent); 6227c478bd9Sstevel@tonic-gate } 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate /* 6257c478bd9Sstevel@tonic-gate * Parse all entries with mpxio-disable property in the given driver.conf 6267c478bd9Sstevel@tonic-gate * file. 6277c478bd9Sstevel@tonic-gate * 6287c478bd9Sstevel@tonic-gate * fname driver.conf file name 6297c478bd9Sstevel@tonic-gate * confent_list on return *confent_list will contain the list of 6307c478bd9Sstevel@tonic-gate * driver.conf file entries with mpxio-disable property. 6317c478bd9Sstevel@tonic-gate * mpxio_disable on return *mpxio_disable is set to the setting of the 6327c478bd9Sstevel@tonic-gate * driver global mpxio-dissable property as follows. 6337c478bd9Sstevel@tonic-gate * 0 if driver mpxio-disable="no" 6347c478bd9Sstevel@tonic-gate * 1 if driver mpxio-disable="yes" 6357c478bd9Sstevel@tonic-gate * -1 if driver mpxio-disable property isn't specified. 6367c478bd9Sstevel@tonic-gate */ 6377c478bd9Sstevel@tonic-gate static void 6387c478bd9Sstevel@tonic-gate parse_conf_file(char *fname, struct conf_entry **confent_list, 6397c478bd9Sstevel@tonic-gate int *mpxio_disable) 6407c478bd9Sstevel@tonic-gate { 6417c478bd9Sstevel@tonic-gate struct conf_entry *confent, *tail = NULL; 6427c478bd9Sstevel@tonic-gate token_t token; 6437c478bd9Sstevel@tonic-gate struct conf_file file; 6447c478bd9Sstevel@tonic-gate char tokval[MAX_TOKEN_SIZE]; 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate *confent_list = NULL; 6477c478bd9Sstevel@tonic-gate *mpxio_disable = -1; 6487c478bd9Sstevel@tonic-gate if ((file.fp = fopen(fname, "r")) == NULL) 6497c478bd9Sstevel@tonic-gate return; 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate file.filename = fname; 6527c478bd9Sstevel@tonic-gate file.linenum = 1; 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate while ((token = lex(&file, tokval, MAX_TOKEN_SIZE)) != T_EOF) { 6557c478bd9Sstevel@tonic-gate switch (token) { 6567c478bd9Sstevel@tonic-gate case T_POUND: 6577c478bd9Sstevel@tonic-gate /* 6587c478bd9Sstevel@tonic-gate * Skip comments. 6597c478bd9Sstevel@tonic-gate */ 6607c478bd9Sstevel@tonic-gate find_eol(file.fp); 6617c478bd9Sstevel@tonic-gate break; 6627c478bd9Sstevel@tonic-gate case T_NAME: 6637c478bd9Sstevel@tonic-gate if ((confent = parse_conf_entry(&file, tokval, 6647c478bd9Sstevel@tonic-gate MAX_TOKEN_SIZE)) == NULL) 6657c478bd9Sstevel@tonic-gate break; 6667c478bd9Sstevel@tonic-gate /* 6677c478bd9Sstevel@tonic-gate * No name indicates global property. 6687c478bd9Sstevel@tonic-gate * Make sure parent and class not NULL. 6697c478bd9Sstevel@tonic-gate */ 6707c478bd9Sstevel@tonic-gate if (confent->name == NULL) { 6717c478bd9Sstevel@tonic-gate if (confent->parent || 6727c478bd9Sstevel@tonic-gate confent->class) { 6737c478bd9Sstevel@tonic-gate file_err(&file, 6747c478bd9Sstevel@tonic-gate "missing name attribute\n"); 6757c478bd9Sstevel@tonic-gate } else if (confent->mpxio_disable != -1) { 6767c478bd9Sstevel@tonic-gate if (*mpxio_disable == -1) 6777c478bd9Sstevel@tonic-gate *mpxio_disable = 6787c478bd9Sstevel@tonic-gate confent->mpxio_disable; 6797c478bd9Sstevel@tonic-gate else 6807c478bd9Sstevel@tonic-gate file_err(&file, 6817c478bd9Sstevel@tonic-gate "'mpxio-disable' property already specified\n"); 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate free_confent(confent); 6847c478bd9Sstevel@tonic-gate break; 6857c478bd9Sstevel@tonic-gate } 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate /* 6887c478bd9Sstevel@tonic-gate * This is a node spec, either parent or class 6897c478bd9Sstevel@tonic-gate * must be specified. 6907c478bd9Sstevel@tonic-gate */ 6917c478bd9Sstevel@tonic-gate if (confent->parent == NULL && confent->class == NULL) { 6927c478bd9Sstevel@tonic-gate file_err(&file, 6937c478bd9Sstevel@tonic-gate "missing parent or class attribute\n"); 6947c478bd9Sstevel@tonic-gate free_confent(confent); 6957c478bd9Sstevel@tonic-gate break; 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate /* only need entries with mpxio_disable property */ 6997c478bd9Sstevel@tonic-gate if (confent->mpxio_disable == -1) { 7007c478bd9Sstevel@tonic-gate free_confent(confent); 7017c478bd9Sstevel@tonic-gate break; 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate if (tail) 7057c478bd9Sstevel@tonic-gate tail->next = confent; 7067c478bd9Sstevel@tonic-gate else 7077c478bd9Sstevel@tonic-gate *confent_list = confent; 7087c478bd9Sstevel@tonic-gate tail = confent; 7097c478bd9Sstevel@tonic-gate break; 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate case T_NEWLINE: 7127c478bd9Sstevel@tonic-gate file.linenum++; 7137c478bd9Sstevel@tonic-gate break; 7147c478bd9Sstevel@tonic-gate default: 7157c478bd9Sstevel@tonic-gate break; 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate (void) fclose(file.fp); 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate /* 7237c478bd9Sstevel@tonic-gate * Return the driver class of the given driver_name. 7247c478bd9Sstevel@tonic-gate * The memory for the driver class is allocated by this function and the 7257c478bd9Sstevel@tonic-gate * caller must free it. 7267c478bd9Sstevel@tonic-gate */ 7277c478bd9Sstevel@tonic-gate static char * 7287c478bd9Sstevel@tonic-gate get_driver_class(char *rootdir, char *driver_name) 7297c478bd9Sstevel@tonic-gate { 7307c478bd9Sstevel@tonic-gate FILE *fp; 7317c478bd9Sstevel@tonic-gate char buf[BUFSIZE]; 7327c478bd9Sstevel@tonic-gate char driver[BUFSIZE]; 7337c478bd9Sstevel@tonic-gate char class_name[BUFSIZE]; 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate logdmsg(("get_driver_class: rootdir = %s, driver name = %s\n", 7367c478bd9Sstevel@tonic-gate rootdir, driver_name)); 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s%s", rootdir, DRIVER_CLASSES); 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate if ((fp = fopen(buf, "r")) == NULL) { 7417c478bd9Sstevel@tonic-gate logdmsg(("get_driver_class: failed to open %s: %s\n", 7427c478bd9Sstevel@tonic-gate buf, strerror(errno))); 7437c478bd9Sstevel@tonic-gate return (NULL); 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate while (fgets(buf, sizeof (buf), fp) != NULL) { 7477c478bd9Sstevel@tonic-gate /* LINTED - unbounded string specifier */ 7487c478bd9Sstevel@tonic-gate if ((sscanf(buf, "%s %s", driver, class_name) == 2) && 7497c478bd9Sstevel@tonic-gate driver[0] != '#' && strcmp(driver, driver_name) == 0) { 7507c478bd9Sstevel@tonic-gate logdmsg(("get_driver_class: driver class = %s\n", 7517c478bd9Sstevel@tonic-gate class_name)); 7527c478bd9Sstevel@tonic-gate (void) fclose(fp); 7537c478bd9Sstevel@tonic-gate return (strdup(class_name)); 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate } 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate (void) fclose(fp); 7587c478bd9Sstevel@tonic-gate return (NULL); 7597c478bd9Sstevel@tonic-gate } 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate static int 7627c478bd9Sstevel@tonic-gate lookup_in_confent_list(struct conf_entry *confent_list, 7637c478bd9Sstevel@tonic-gate int match_class, char *parent, char *unit_addr, int port) 7647c478bd9Sstevel@tonic-gate { 7657c478bd9Sstevel@tonic-gate struct conf_entry *confent; 7667c478bd9Sstevel@tonic-gate char *par; 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate logdmsg(("lookup_in_confent_list: %s = \"%s\", unit_addr = \"%s\", " 7697c478bd9Sstevel@tonic-gate "port = %d\n", (match_class) ? "class" : "parent", parent, 7707c478bd9Sstevel@tonic-gate STRVAL(unit_addr), port)); 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate for (confent = confent_list; confent != NULL; confent = confent->next) { 7737c478bd9Sstevel@tonic-gate par = (match_class) ? confent->class : confent->parent; 7747c478bd9Sstevel@tonic-gate if (unit_addr) { 7757c478bd9Sstevel@tonic-gate if (confent->unit_address != NULL && 7767c478bd9Sstevel@tonic-gate strcmp(confent->unit_address, unit_addr) == 0 && 7777c478bd9Sstevel@tonic-gate par != NULL && strcmp(par, parent) == 0) 7787c478bd9Sstevel@tonic-gate return (confent->mpxio_disable); 7797c478bd9Sstevel@tonic-gate } else { 7807c478bd9Sstevel@tonic-gate if (confent->port == port && 7817c478bd9Sstevel@tonic-gate par != NULL && strcmp(par, parent) == 0) 7827c478bd9Sstevel@tonic-gate return (confent->mpxio_disable); 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate } 7857c478bd9Sstevel@tonic-gate return (-1); 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate /* 7897c478bd9Sstevel@tonic-gate * lookup mpxio-disabled property setting for the given path in the given 7907c478bd9Sstevel@tonic-gate * driver.conf file. Match the entries from most specific to least specific. 7917c478bd9Sstevel@tonic-gate * 7927c478bd9Sstevel@tonic-gate * conf_file the path name of either fp.conf, qlc.conf or scsi_vhci.conf 7937c478bd9Sstevel@tonic-gate * path /devices node path without the /devices prefix. 7947c478bd9Sstevel@tonic-gate * If the conf_file is fp.conf, path must be a fp node path 7957c478bd9Sstevel@tonic-gate * if the conf_file is qlc.conf, path must be a qlc node path. 7967c478bd9Sstevel@tonic-gate * if the conf_file is scsi_vhci.conf, path must be NULL. 7977c478bd9Sstevel@tonic-gate * ex: /pci@8,600000/SUNW,qlc@4/fp@0,0 7987c478bd9Sstevel@tonic-gate * /pci@8,600000/SUNW,qlc@4 7997c478bd9Sstevel@tonic-gate * 8007c478bd9Sstevel@tonic-gate * returns: 8017c478bd9Sstevel@tonic-gate * 0 if mpxio-disable="no" 8027c478bd9Sstevel@tonic-gate * 1 if mpxio-disable="yes" 8037c478bd9Sstevel@tonic-gate * -1 if mpxio-disable property isn't specified. 8047c478bd9Sstevel@tonic-gate */ 8057c478bd9Sstevel@tonic-gate static int 8067c478bd9Sstevel@tonic-gate lookup_in_conf_file(char *rootdir, char *conf_file, char *path) 8077c478bd9Sstevel@tonic-gate { 8087c478bd9Sstevel@tonic-gate struct conf_entry *confent_list = NULL; 8097c478bd9Sstevel@tonic-gate int mpxio_disable; 8107c478bd9Sstevel@tonic-gate di_node_t par_node = DI_NODE_NIL; 8117c478bd9Sstevel@tonic-gate char *node_name = NULL, *node_addr = NULL; 8127c478bd9Sstevel@tonic-gate char *unit_addr = NULL; 8137c478bd9Sstevel@tonic-gate int port = -1; 8147c478bd9Sstevel@tonic-gate char *par_node_name = NULL, *par_node_addr = NULL; 8157c478bd9Sstevel@tonic-gate char *par_binding_name = NULL, *par_driver_name = NULL; 8167c478bd9Sstevel@tonic-gate char *par_driver_class = NULL, *par_node_name_addr; 8177c478bd9Sstevel@tonic-gate int rv = -1; 8187c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate logdmsg(("lookup_in_conf_file: rootdir = \"%s\", conf_file = \"%s\", " 8217c478bd9Sstevel@tonic-gate "path = \"%s\"\n", rootdir, conf_file, STRVAL(path))); 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, "%s%s", rootdir, conf_file); 8247c478bd9Sstevel@tonic-gate parse_conf_file(buf, &confent_list, &mpxio_disable); 8257c478bd9Sstevel@tonic-gate #ifdef DEBUG 8267c478bd9Sstevel@tonic-gate log_confent_list(buf, confent_list, mpxio_disable); 8277c478bd9Sstevel@tonic-gate #endif 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate /* if path is NULL, return driver global mpxio-disable setting */ 8307c478bd9Sstevel@tonic-gate if (path == NULL) { 8317c478bd9Sstevel@tonic-gate rv = mpxio_disable; 8327c478bd9Sstevel@tonic-gate goto done; 8337c478bd9Sstevel@tonic-gate } 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate if ((node_name = strrchr(path, '/')) == NULL) 8367c478bd9Sstevel@tonic-gate goto done; 8377c478bd9Sstevel@tonic-gate 8387c478bd9Sstevel@tonic-gate *node_name = '\0'; 8397c478bd9Sstevel@tonic-gate node_name++; 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate if ((node_addr = strchr(node_name, '@')) == NULL) 8427c478bd9Sstevel@tonic-gate goto done; 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate *node_addr = '\0'; 8457c478bd9Sstevel@tonic-gate node_addr++; 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate if (strcmp(node_name, "fp") == 0) { 8487c478bd9Sstevel@tonic-gate /* get port number; encoded in the node addr as a hex number */ 8497c478bd9Sstevel@tonic-gate port = (int)strtol(node_addr, NULL, 16); 8507c478bd9Sstevel@tonic-gate } else 8517c478bd9Sstevel@tonic-gate unit_addr = node_addr; 8527c478bd9Sstevel@tonic-gate 8537c478bd9Sstevel@tonic-gate /* 8547c478bd9Sstevel@tonic-gate * Match from most specific to least specific; 8557c478bd9Sstevel@tonic-gate * first, start the lookup based on full path. 8567c478bd9Sstevel@tonic-gate */ 8577c478bd9Sstevel@tonic-gate if ((rv = lookup_in_confent_list(confent_list, 0, path, 8587c478bd9Sstevel@tonic-gate unit_addr, port)) != -1) 8597c478bd9Sstevel@tonic-gate goto done; 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate /* lookup nodename@address */ 8627c478bd9Sstevel@tonic-gate if ((par_node_name_addr = strrchr(path, '/')) != NULL) { 8637c478bd9Sstevel@tonic-gate par_node_name_addr++; 8647c478bd9Sstevel@tonic-gate if ((rv = lookup_in_confent_list(confent_list, 0, 8657c478bd9Sstevel@tonic-gate par_node_name_addr, unit_addr, port)) != -1) 8667c478bd9Sstevel@tonic-gate goto done; 8677c478bd9Sstevel@tonic-gate } 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate /* di_init() doesn't work when 0 is passed in flags */ 8707c478bd9Sstevel@tonic-gate par_node = di_init(path, DINFOMINOR); 8717c478bd9Sstevel@tonic-gate if (par_node != DI_NODE_NIL) { 8727c478bd9Sstevel@tonic-gate par_node_name = di_node_name(par_node); 8737c478bd9Sstevel@tonic-gate par_node_addr = di_bus_addr(par_node); 8747c478bd9Sstevel@tonic-gate par_binding_name = di_binding_name(par_node); 8757c478bd9Sstevel@tonic-gate par_driver_name = di_driver_name(par_node); 8767c478bd9Sstevel@tonic-gate } 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate logdmsg(("par_node_name = %s\n", STRVAL(par_node_name))); 8797c478bd9Sstevel@tonic-gate logdmsg(("par_node_addr = %s\n", STRVAL(par_node_addr))); 8807c478bd9Sstevel@tonic-gate logdmsg(("par_binding_name = %s\n", STRVAL(par_binding_name))); 8817c478bd9Sstevel@tonic-gate logdmsg(("par_driver_name = %s\n", STRVAL(par_driver_name))); 8827c478bd9Sstevel@tonic-gate 8837c478bd9Sstevel@tonic-gate /* lookup bindingname@address */ 8847c478bd9Sstevel@tonic-gate if (par_binding_name != NULL && par_binding_name != par_node_name && 8857c478bd9Sstevel@tonic-gate par_node_addr != NULL) { 8867c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s@%s", par_binding_name, 8877c478bd9Sstevel@tonic-gate par_node_addr); 8887c478bd9Sstevel@tonic-gate if ((rv = lookup_in_confent_list(confent_list, 0, 8897c478bd9Sstevel@tonic-gate buf, unit_addr, port)) != -1) 8907c478bd9Sstevel@tonic-gate goto done; 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate /* lookup binding name */ 8947c478bd9Sstevel@tonic-gate if (par_binding_name != NULL) { 8957c478bd9Sstevel@tonic-gate if ((rv = lookup_in_confent_list(confent_list, 0, 8967c478bd9Sstevel@tonic-gate par_binding_name, unit_addr, port)) != -1) 8977c478bd9Sstevel@tonic-gate goto done; 8987c478bd9Sstevel@tonic-gate } 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate if (par_driver_name != NULL) { 9017c478bd9Sstevel@tonic-gate /* lookup driver name */ 9027c478bd9Sstevel@tonic-gate if ((rv = lookup_in_confent_list(confent_list, 0, 9037c478bd9Sstevel@tonic-gate par_driver_name, unit_addr, port)) != -1) 9047c478bd9Sstevel@tonic-gate goto done; 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate /* finally, lookup class name */ 9077c478bd9Sstevel@tonic-gate par_driver_class = get_driver_class(rootdir, par_driver_name); 9087c478bd9Sstevel@tonic-gate if (par_driver_class != NULL) { 9097c478bd9Sstevel@tonic-gate if ((rv = lookup_in_confent_list(confent_list, 1, 9107c478bd9Sstevel@tonic-gate par_driver_class, unit_addr, port)) != -1) 9117c478bd9Sstevel@tonic-gate goto done; 9127c478bd9Sstevel@tonic-gate } 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate /* 9167c478bd9Sstevel@tonic-gate * no match so far; 9177c478bd9Sstevel@tonic-gate * use the driver global mpxio-disable setting if exists. 9187c478bd9Sstevel@tonic-gate */ 9197c478bd9Sstevel@tonic-gate rv = mpxio_disable; 9207c478bd9Sstevel@tonic-gate 9217c478bd9Sstevel@tonic-gate done: 9227c478bd9Sstevel@tonic-gate if (node_name != NULL) 9237c478bd9Sstevel@tonic-gate *(node_name - 1) = '/'; 9247c478bd9Sstevel@tonic-gate if (node_addr != NULL) 9257c478bd9Sstevel@tonic-gate *(node_addr - 1) = '@'; 9267c478bd9Sstevel@tonic-gate if (par_driver_class != NULL) 9277c478bd9Sstevel@tonic-gate free(par_driver_class); 9287c478bd9Sstevel@tonic-gate if (confent_list != NULL) 9297c478bd9Sstevel@tonic-gate free_confent_list(confent_list); 9307c478bd9Sstevel@tonic-gate if (par_node != DI_NODE_NIL) 9317c478bd9Sstevel@tonic-gate di_fini(par_node); 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate return (rv); 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate /* 9377c478bd9Sstevel@tonic-gate * Given client_name return whether it is a phci or vhci based name. 9387c478bd9Sstevel@tonic-gate * client_name is /devices name of a client without the /devices prefix. 9397c478bd9Sstevel@tonic-gate * 9407c478bd9Sstevel@tonic-gate * client_name Return value 9417c478bd9Sstevel@tonic-gate * .../fp@xxx/ssd@yyy CLIENT_TYPE_PHCI 9427c478bd9Sstevel@tonic-gate * .../scsi_vhci/ssd@yyy CLIENT_TYPE_VHCI 9437c478bd9Sstevel@tonic-gate * other CLIENT_TYPE_UNKNOWN 9447c478bd9Sstevel@tonic-gate */ 9457c478bd9Sstevel@tonic-gate static client_type_t 9467c478bd9Sstevel@tonic-gate client_name_type(char *client_name) 9477c478bd9Sstevel@tonic-gate { 9487c478bd9Sstevel@tonic-gate client_type_t client_type; 9497c478bd9Sstevel@tonic-gate char *p1, *p2; 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate logdmsg(("client_name_type: client_name = %s\n", client_name)); 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate if (strncmp(client_name, SLASH_SCSI_VHCI, 9547c478bd9Sstevel@tonic-gate sizeof (SLASH_SCSI_VHCI) - 1) == 0) 9557c478bd9Sstevel@tonic-gate return (CLIENT_TYPE_VHCI); 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate if (*client_name != '/') 9587c478bd9Sstevel@tonic-gate return (CLIENT_TYPE_UNKNOWN); 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate if ((p1 = strrchr(client_name, '/')) == NULL) 9617c478bd9Sstevel@tonic-gate return (CLIENT_TYPE_UNKNOWN); 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate *p1 = '\0'; 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate if ((p2 = strrchr(client_name, '/')) != NULL && 9667c478bd9Sstevel@tonic-gate strncmp(p2, SLASH_FP_AT, sizeof (SLASH_FP_AT) - 1) == 0) 9677c478bd9Sstevel@tonic-gate client_type = CLIENT_TYPE_PHCI; 9687c478bd9Sstevel@tonic-gate else 9697c478bd9Sstevel@tonic-gate client_type = CLIENT_TYPE_UNKNOWN; 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate *p1 = '/'; 9727c478bd9Sstevel@tonic-gate return (client_type); 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate /* 9767c478bd9Sstevel@tonic-gate * Compare controller name portion of dev1 and dev2. 9777c478bd9Sstevel@tonic-gate * 9787c478bd9Sstevel@tonic-gate * rootdir root directory of the target environment 9797c478bd9Sstevel@tonic-gate * dev1 can be either a /dev link or /devices name in the target 9807c478bd9Sstevel@tonic-gate * environemnt 9817c478bd9Sstevel@tonic-gate * dev2 /devices name of a device without the /devices prefix 9827c478bd9Sstevel@tonic-gate * 9837c478bd9Sstevel@tonic-gate * Returns: 9847c478bd9Sstevel@tonic-gate * 0 if controller names match 9857c478bd9Sstevel@tonic-gate * 1 if controller names don't match 9867c478bd9Sstevel@tonic-gate * -1 an error occurred. 9877c478bd9Sstevel@tonic-gate */ 9887c478bd9Sstevel@tonic-gate static int 9897c478bd9Sstevel@tonic-gate compare_controller(char *rootdir, char *dev1, char *dev2) 9907c478bd9Sstevel@tonic-gate { 9917c478bd9Sstevel@tonic-gate int linksize; 9927c478bd9Sstevel@tonic-gate char *p1, *p; 9937c478bd9Sstevel@tonic-gate char physdev1[MAXPATHLEN]; 9947c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate logdmsg(("compare_controller: rootdir = %s, dev1 = %s, dev2 = %s\n", 9977c478bd9Sstevel@tonic-gate rootdir, dev1, dev2)); 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate if (strncmp(dev1, SLASH_DEV_SLASH, sizeof (SLASH_DEV_SLASH) - 1) 10007c478bd9Sstevel@tonic-gate == 0) { 10017c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, "%s%s", rootdir, dev1); 10027c478bd9Sstevel@tonic-gate if ((linksize = readlink(buf, physdev1, MAXPATHLEN)) > 0 && 10037c478bd9Sstevel@tonic-gate linksize < (MAXPATHLEN - 1)) { 10047c478bd9Sstevel@tonic-gate physdev1[linksize] = '\0'; 10057c478bd9Sstevel@tonic-gate logdmsg(("compare_controller: physdev1 = %s\n", 10067c478bd9Sstevel@tonic-gate physdev1)); 10077c478bd9Sstevel@tonic-gate } else 10087c478bd9Sstevel@tonic-gate return (-1); 10097c478bd9Sstevel@tonic-gate } else 10107c478bd9Sstevel@tonic-gate (void) strlcpy(physdev1, dev1, MAXPATHLEN); 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate if ((p1 = strstr(physdev1, SLASH_DEVICES)) == NULL) 10137c478bd9Sstevel@tonic-gate return (-1); 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate p1 += sizeof (SLASH_DEVICES) - 1; 10167c478bd9Sstevel@tonic-gate /* strip the device portion */ 10177c478bd9Sstevel@tonic-gate if ((p = strrchr(p1, '/')) == NULL) 10187c478bd9Sstevel@tonic-gate return (-1); 10197c478bd9Sstevel@tonic-gate *p = '\0'; 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate if ((p = strrchr(dev2, '/')) == NULL) 10227c478bd9Sstevel@tonic-gate return (-1); 10237c478bd9Sstevel@tonic-gate *p = '\0'; 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate logdmsg(("compare_controller: path1 = %s, path2 = %s\n", 10267c478bd9Sstevel@tonic-gate p1, dev2)); 10277c478bd9Sstevel@tonic-gate if (strcmp(p1, dev2) == 0) { 10287c478bd9Sstevel@tonic-gate *p = '/'; 10297c478bd9Sstevel@tonic-gate return (0); 10307c478bd9Sstevel@tonic-gate } else { 10317c478bd9Sstevel@tonic-gate *p = '/'; 10327c478bd9Sstevel@tonic-gate return (1); 10337c478bd9Sstevel@tonic-gate } 10347c478bd9Sstevel@tonic-gate } 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate /* 10377c478bd9Sstevel@tonic-gate * Check if the specified device path is on the root controller. 10387c478bd9Sstevel@tonic-gate * 10397c478bd9Sstevel@tonic-gate * rootdir root directory of the target environment 10407c478bd9Sstevel@tonic-gate * path /devices name of a device without the /devices prefix 10417c478bd9Sstevel@tonic-gate * 10427c478bd9Sstevel@tonic-gate * Returns 10437c478bd9Sstevel@tonic-gate * 1 if the path is on the root controller 10447c478bd9Sstevel@tonic-gate * 0 if the path is not on the root controller 10457c478bd9Sstevel@tonic-gate * -1 if an error occurs 10467c478bd9Sstevel@tonic-gate */ 10477c478bd9Sstevel@tonic-gate static int 10487c478bd9Sstevel@tonic-gate is_root_controller(char *rootdir, char *path) 10497c478bd9Sstevel@tonic-gate { 10507c478bd9Sstevel@tonic-gate FILE *fp; 10517c478bd9Sstevel@tonic-gate char *tmpfile; 10527c478bd9Sstevel@tonic-gate int rv = -1; 10537c478bd9Sstevel@tonic-gate struct vfstab vfsent; 10547c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 10557c478bd9Sstevel@tonic-gate char ctd[MAXNAMELEN + 1]; 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate logdmsg(("is_root_controller: rootdir = %s, path = %s\n", rootdir, 10587c478bd9Sstevel@tonic-gate path)); 10597c478bd9Sstevel@tonic-gate 10607c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, "%s%s", rootdir, VFSTAB); 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate if ((fp = fopen(buf, "r")) == NULL) { 10637c478bd9Sstevel@tonic-gate logdmsg(("is_root_controller: failed to open %s: %s\n", 10647c478bd9Sstevel@tonic-gate buf, strerror(errno))); 10657c478bd9Sstevel@tonic-gate return (-1); 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate if (getvfsfile(fp, &vfsent, "/") != 0) { 10697c478bd9Sstevel@tonic-gate logdmsg(("is_root_controller: getvfsfile: failed to read " 10707c478bd9Sstevel@tonic-gate "vfstab entry for mount point \"/\": %s\n", 10717c478bd9Sstevel@tonic-gate strerror(errno))); 10727c478bd9Sstevel@tonic-gate (void) fclose(fp); 10737c478bd9Sstevel@tonic-gate return (-1); 10747c478bd9Sstevel@tonic-gate } 10757c478bd9Sstevel@tonic-gate (void) fclose(fp); 10767c478bd9Sstevel@tonic-gate 10777c478bd9Sstevel@tonic-gate /* check if the root is an svm metadisk */ 10787c478bd9Sstevel@tonic-gate if (strncmp(vfsent.vfs_special, META_DEV, sizeof (META_DEV) - 1) != 0) { 10797c478bd9Sstevel@tonic-gate if (compare_controller(rootdir, vfsent.vfs_special, path) == 0) 10807c478bd9Sstevel@tonic-gate return (1); 10817c478bd9Sstevel@tonic-gate else 10827c478bd9Sstevel@tonic-gate return (0); 10837c478bd9Sstevel@tonic-gate } 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate /* Don't use /var/run as it is not mounted in miniroot */ 10867c478bd9Sstevel@tonic-gate if ((tmpfile = tempnam("/tmp", "diirc")) == NULL) { 10877c478bd9Sstevel@tonic-gate logdmsg(("is_root_controller: tempnam: failed: %s\n", 10887c478bd9Sstevel@tonic-gate strerror(errno))); 10897c478bd9Sstevel@tonic-gate return (-1); 10907c478bd9Sstevel@tonic-gate } 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate /* get metadisk components using metastat command */ 10937c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, 10947c478bd9Sstevel@tonic-gate "/usr/sbin/metastat -p %s 2>/dev/null | " 10957c478bd9Sstevel@tonic-gate "/usr/bin/grep ' 1 1 ' | " 10967c478bd9Sstevel@tonic-gate "/usr/bin/sed -e 's/^.* 1 1 //' | " 10977c478bd9Sstevel@tonic-gate "/usr/bin/cut -f1 -d ' ' > %s", 10987c478bd9Sstevel@tonic-gate vfsent.vfs_special + sizeof (META_DEV) - 1, tmpfile); 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate logdmsg(("is_root_controller: command = %s\n", buf)); 11017c478bd9Sstevel@tonic-gate fp = NULL; 11027c478bd9Sstevel@tonic-gate if (system(buf) == 0 && (fp = fopen(tmpfile, "r")) != NULL) { 11037c478bd9Sstevel@tonic-gate while (fscanf(fp, "%" VAL2STR(MAXNAMELEN) "s", ctd) == 1) { 11047c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, "/dev/dsk/%s", ctd); 11057c478bd9Sstevel@tonic-gate if (compare_controller(rootdir, buf, path) == 0) { 11067c478bd9Sstevel@tonic-gate rv = 1; 11077c478bd9Sstevel@tonic-gate goto out; 11087c478bd9Sstevel@tonic-gate } 11097c478bd9Sstevel@tonic-gate } 11107c478bd9Sstevel@tonic-gate rv = 0; 11117c478bd9Sstevel@tonic-gate } 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate out: 11147c478bd9Sstevel@tonic-gate if (fp) 11157c478bd9Sstevel@tonic-gate (void) fclose(fp); 11167c478bd9Sstevel@tonic-gate (void) unlink(tmpfile); 11177c478bd9Sstevel@tonic-gate free(tmpfile); 11187c478bd9Sstevel@tonic-gate return (rv); 11197c478bd9Sstevel@tonic-gate } 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate static int 11227c478bd9Sstevel@tonic-gate file_exists(char *rootdir, char *path) 11237c478bd9Sstevel@tonic-gate { 11247c478bd9Sstevel@tonic-gate struct stat stbuf; 11257c478bd9Sstevel@tonic-gate char fullpath[MAXPATHLEN]; 11267c478bd9Sstevel@tonic-gate int x; 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate (void) snprintf(fullpath, MAXPATHLEN, "%s%s", rootdir, path); 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate x = stat(fullpath, &stbuf); 11317c478bd9Sstevel@tonic-gate logdmsg(("file_exists: %s: %s\n", fullpath, (x == 0) ? "yes" : "no")); 11327c478bd9Sstevel@tonic-gate if (x == 0) 11337c478bd9Sstevel@tonic-gate return (1); 11347c478bd9Sstevel@tonic-gate else 11357c478bd9Sstevel@tonic-gate return (0); 11367c478bd9Sstevel@tonic-gate } 11377c478bd9Sstevel@tonic-gate 11387c478bd9Sstevel@tonic-gate /* 11397c478bd9Sstevel@tonic-gate * Check if mpxio is enabled or disabled on the specified device path. 11407c478bd9Sstevel@tonic-gate * Looks through the .conf files to determine the mpxio setting. 11417c478bd9Sstevel@tonic-gate * 11427c478bd9Sstevel@tonic-gate * rootdir root directory of the target environment 11437c478bd9Sstevel@tonic-gate * path /devices name of a device without the /devices prefix and 11447c478bd9Sstevel@tonic-gate * minor name component. 11457c478bd9Sstevel@tonic-gate * 11467c478bd9Sstevel@tonic-gate * Returns 11477c478bd9Sstevel@tonic-gate * 1 if mpxio is disabled 11487c478bd9Sstevel@tonic-gate * 0 if mpxio is enabled 11497c478bd9Sstevel@tonic-gate * -1 if an error occurs 11507c478bd9Sstevel@tonic-gate */ 11517c478bd9Sstevel@tonic-gate static int 11527c478bd9Sstevel@tonic-gate is_mpxio_disabled(char *rootdir, char *path) 11537c478bd9Sstevel@tonic-gate { 11547c478bd9Sstevel@tonic-gate int mpxio_disable; 11557c478bd9Sstevel@tonic-gate char *p; 11567c478bd9Sstevel@tonic-gate int check_root_controller; 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate logdmsg(("is_mpxio_disabled: rootdir = %s, path = %s\n", 11597c478bd9Sstevel@tonic-gate rootdir, path)); 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate if (file_exists(rootdir, SCSI_VHCI_CONF) == 0) { 11627c478bd9Sstevel@tonic-gate /* 11637c478bd9Sstevel@tonic-gate * scsi_vhci.conf doesn't exist: 11647c478bd9Sstevel@tonic-gate * if upgrading from a pre solaris 9 release. or 11657c478bd9Sstevel@tonic-gate * if this function is called during fresh or flash install 11667c478bd9Sstevel@tonic-gate * prior to installing scsi_vhci.conf file. 11677c478bd9Sstevel@tonic-gate */ 11687c478bd9Sstevel@tonic-gate if (file_exists(rootdir, "/kernel/drv")) 11697c478bd9Sstevel@tonic-gate /* upgrading from pre solaris 9 */ 11707c478bd9Sstevel@tonic-gate return (1); 11717c478bd9Sstevel@tonic-gate else 11727c478bd9Sstevel@tonic-gate /* fresh or flash install */ 11737c478bd9Sstevel@tonic-gate return (0); 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate mpxio_disable = lookup_in_conf_file(rootdir, SCSI_VHCI_CONF, NULL); 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate /* 11797c478bd9Sstevel@tonic-gate * scsi_vhci.conf contains mpxio-disable property only in s9 and 11807c478bd9Sstevel@tonic-gate * s8+sfkpatch. This property is no longer present from s10 onwards. 11817c478bd9Sstevel@tonic-gate */ 11827c478bd9Sstevel@tonic-gate if (mpxio_disable == 1) { 11837c478bd9Sstevel@tonic-gate /* upgrading from s8 or s9 with mpxio globally disabled */ 11847c478bd9Sstevel@tonic-gate return (1); 11857c478bd9Sstevel@tonic-gate } else if (mpxio_disable == 0) { 11867c478bd9Sstevel@tonic-gate /* upgrading from s8 or s9 with mpxio globally enabled */ 11877c478bd9Sstevel@tonic-gate check_root_controller = 1; 11887c478bd9Sstevel@tonic-gate } else { 11897c478bd9Sstevel@tonic-gate /* 11907c478bd9Sstevel@tonic-gate * We are looking at the s10 version of the file. This is 11917c478bd9Sstevel@tonic-gate * the case if this function is called after installing the 11927c478bd9Sstevel@tonic-gate * new scsi_vhci.conf file. 11937c478bd9Sstevel@tonic-gate */ 11947c478bd9Sstevel@tonic-gate check_root_controller = 0; 11957c478bd9Sstevel@tonic-gate } 11967c478bd9Sstevel@tonic-gate 11977c478bd9Sstevel@tonic-gate if ((mpxio_disable = lookup_in_conf_file(rootdir, FP_CONF, path)) 11987c478bd9Sstevel@tonic-gate != -1) 11997c478bd9Sstevel@tonic-gate return (mpxio_disable); 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate if ((p = strrchr(path, '/')) == NULL) 12027c478bd9Sstevel@tonic-gate return (-1); 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate *p = '\0'; 12057c478bd9Sstevel@tonic-gate if ((mpxio_disable = lookup_in_conf_file(rootdir, QLC_CONF, path)) 12067c478bd9Sstevel@tonic-gate != -1) { 12077c478bd9Sstevel@tonic-gate *p = '/'; 12087c478bd9Sstevel@tonic-gate return (mpxio_disable); 12097c478bd9Sstevel@tonic-gate } 12107c478bd9Sstevel@tonic-gate *p = '/'; 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate /* 12137c478bd9Sstevel@tonic-gate * mpxio-disable setting is not found in the .conf files. 12147c478bd9Sstevel@tonic-gate * The default is to enable mpxio, except if the path is on the root 12157c478bd9Sstevel@tonic-gate * controller. 12167c478bd9Sstevel@tonic-gate * 12177c478bd9Sstevel@tonic-gate * In s8 and s9 mpxio is not supported on the root controller. 12187c478bd9Sstevel@tonic-gate * NWS supplies a patch to enable root controller support in s8 and s9. 12197c478bd9Sstevel@tonic-gate * If the system had the patch installed, the fp.conf file would have 12207c478bd9Sstevel@tonic-gate * explicit "mpxio-disable=no" for the root controller. So we would 12217c478bd9Sstevel@tonic-gate * have found the mpxio-disable setting when we looked up this property 12227c478bd9Sstevel@tonic-gate * in the fp.conf file. 12237c478bd9Sstevel@tonic-gate */ 12247c478bd9Sstevel@tonic-gate if (check_root_controller) { 12257c478bd9Sstevel@tonic-gate mpxio_disable = is_root_controller(rootdir, path); 12267c478bd9Sstevel@tonic-gate logdmsg(("is_mpxio_disabled: is_root_controller returned %d\n", 12277c478bd9Sstevel@tonic-gate mpxio_disable)); 12287c478bd9Sstevel@tonic-gate } else 12297c478bd9Sstevel@tonic-gate mpxio_disable = 0; 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate return (mpxio_disable); 12327c478bd9Sstevel@tonic-gate } 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate static int 12357c478bd9Sstevel@tonic-gate vhci_ctl(sv_iocdata_t *iocp, int cmd) 12367c478bd9Sstevel@tonic-gate { 12377c478bd9Sstevel@tonic-gate int fd, rv; 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate if ((fd = open(VHCI_CTL_NODE, O_RDWR)) < 0) 12407c478bd9Sstevel@tonic-gate return (-1); 12417c478bd9Sstevel@tonic-gate rv = ioctl(fd, cmd, iocp); 12427c478bd9Sstevel@tonic-gate (void) close(fd); 12437c478bd9Sstevel@tonic-gate return (rv); 12447c478bd9Sstevel@tonic-gate } 12457c478bd9Sstevel@tonic-gate 12467c478bd9Sstevel@tonic-gate /* 12477c478bd9Sstevel@tonic-gate * Convert a phci client name to vhci client name. 12487c478bd9Sstevel@tonic-gate * 12497c478bd9Sstevel@tonic-gate * phci_name phci client /devices name without the /devices prefix and 12507c478bd9Sstevel@tonic-gate * minor name component. 12517c478bd9Sstevel@tonic-gate * ex: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0 12527c478bd9Sstevel@tonic-gate * 12537c478bd9Sstevel@tonic-gate * Returns on success, vhci client name is returned. The memory for 12547c478bd9Sstevel@tonic-gate * the vhci name is allocated by this function and the caller 12557c478bd9Sstevel@tonic-gate * must free it. 12567c478bd9Sstevel@tonic-gate * on failure, NULL is returned. 12577c478bd9Sstevel@tonic-gate */ 12587c478bd9Sstevel@tonic-gate static char * 12597c478bd9Sstevel@tonic-gate phci_to_vhci(char *phci_name) 12607c478bd9Sstevel@tonic-gate { 12617c478bd9Sstevel@tonic-gate sv_iocdata_t ioc; 12627c478bd9Sstevel@tonic-gate char *slash, *addr, *retp; 12637c478bd9Sstevel@tonic-gate char vhci_name_buf[MAXPATHLEN]; 12647c478bd9Sstevel@tonic-gate char phci_name_buf[MAXPATHLEN]; 12657c478bd9Sstevel@tonic-gate char addr_buf[MAXNAMELEN]; 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate logdmsg(("phci_to_vhci: pchi_name = %s\n", phci_name)); 12687c478bd9Sstevel@tonic-gate (void) strlcpy(phci_name_buf, phci_name, MAXPATHLEN); 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate if ((slash = strrchr(phci_name_buf, '/')) == NULL || 12717c478bd9Sstevel@tonic-gate (addr = strchr(slash, '@')) == NULL) 12727c478bd9Sstevel@tonic-gate return (NULL); 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate *slash = '\0'; 12757c478bd9Sstevel@tonic-gate addr++; 12767c478bd9Sstevel@tonic-gate (void) strlcpy(addr_buf, addr, MAXNAMELEN); 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate bzero(&ioc, sizeof (sv_iocdata_t)); 12797c478bd9Sstevel@tonic-gate ioc.client = vhci_name_buf; 12807c478bd9Sstevel@tonic-gate ioc.phci = phci_name_buf; 12817c478bd9Sstevel@tonic-gate ioc.addr = addr_buf; 12827c478bd9Sstevel@tonic-gate if (vhci_ctl(&ioc, SCSI_VHCI_GET_CLIENT_NAME) != 0) { 12837c478bd9Sstevel@tonic-gate logdmsg(("phci_to_vhci: vhci_ctl failed: %s\n", 12847c478bd9Sstevel@tonic-gate strerror(errno))); 12857c478bd9Sstevel@tonic-gate return (NULL); 12867c478bd9Sstevel@tonic-gate } 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate retp = strdup(vhci_name_buf); 12897c478bd9Sstevel@tonic-gate logdmsg(("phci_to_vhci: vhci name = %s\n", STRVAL(retp))); 12907c478bd9Sstevel@tonic-gate return (retp); 12917c478bd9Sstevel@tonic-gate } 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate static int 12947c478bd9Sstevel@tonic-gate add_to_phci_list(char **phci_list, sv_path_info_t *pi, int npaths, int state, 12957c478bd9Sstevel@tonic-gate char *node_name) 12967c478bd9Sstevel@tonic-gate { 12977c478bd9Sstevel@tonic-gate int rv = 0; 12987c478bd9Sstevel@tonic-gate char name[MAXPATHLEN]; 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate while (npaths--) { 13017c478bd9Sstevel@tonic-gate if (state == pi->ret_state) { 130272a50065Scth (void) snprintf(name, MAXPATHLEN, "%s/%s@%s", 13037c478bd9Sstevel@tonic-gate pi->device.ret_phci, node_name, pi->ret_addr); 13047c478bd9Sstevel@tonic-gate if ((*phci_list = strdup(name)) == NULL) 13057c478bd9Sstevel@tonic-gate return (-1); 13067c478bd9Sstevel@tonic-gate phci_list++; 13077c478bd9Sstevel@tonic-gate rv++; 13087c478bd9Sstevel@tonic-gate } 13097c478bd9Sstevel@tonic-gate pi++; 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate 13127c478bd9Sstevel@tonic-gate return (rv); 13137c478bd9Sstevel@tonic-gate } 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate static void 13167c478bd9Sstevel@tonic-gate free_pathlist(char **pathlist) 13177c478bd9Sstevel@tonic-gate { 13187c478bd9Sstevel@tonic-gate char **p; 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate if (pathlist != NULL) { 13217c478bd9Sstevel@tonic-gate for (p = pathlist; *p != NULL; p++) 13227c478bd9Sstevel@tonic-gate free(*p); 13237c478bd9Sstevel@tonic-gate free(pathlist); 13247c478bd9Sstevel@tonic-gate } 13257c478bd9Sstevel@tonic-gate } 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate 13287c478bd9Sstevel@tonic-gate /* 13297c478bd9Sstevel@tonic-gate * Convert a vhci client name to phci client names. 13307c478bd9Sstevel@tonic-gate * 13317c478bd9Sstevel@tonic-gate * vhci_name vhci client /devices name without the /devices prefix and 13327c478bd9Sstevel@tonic-gate * minor name component. 13337c478bd9Sstevel@tonic-gate * num_paths On return, *num_paths is set to the number paths in the 13347c478bd9Sstevel@tonic-gate * returned path list. 13357c478bd9Sstevel@tonic-gate * 13367c478bd9Sstevel@tonic-gate * Returns NULL terminated path list containing phci client paths is 13377c478bd9Sstevel@tonic-gate * returned on success. The memory for the path list is 13387c478bd9Sstevel@tonic-gate * allocated by this function and the caller must free it by 13397c478bd9Sstevel@tonic-gate * calling free_pathlist(). 13407c478bd9Sstevel@tonic-gate * NULL is returned on failure. 13417c478bd9Sstevel@tonic-gate */ 13427c478bd9Sstevel@tonic-gate static char ** 13437c478bd9Sstevel@tonic-gate vhci_to_phci(char *vhci_name, int *num_paths) 13447c478bd9Sstevel@tonic-gate { 13457c478bd9Sstevel@tonic-gate sv_iocdata_t ioc; 13467c478bd9Sstevel@tonic-gate uint_t npaths; 13477c478bd9Sstevel@tonic-gate int n; 13487c478bd9Sstevel@tonic-gate char **phci_list = NULL; 13497c478bd9Sstevel@tonic-gate char *node_name, *at; 13507c478bd9Sstevel@tonic-gate char vhci_name_buf[MAXPATHLEN]; 13517c478bd9Sstevel@tonic-gate 13527c478bd9Sstevel@tonic-gate logdmsg(("vhci_to_phci: vchi_name = %s\n", vhci_name)); 13537c478bd9Sstevel@tonic-gate 13547c478bd9Sstevel@tonic-gate *num_paths = 0; 13557c478bd9Sstevel@tonic-gate (void) strlcpy(vhci_name_buf, vhci_name, MAXPATHLEN); 13567c478bd9Sstevel@tonic-gate 13577c478bd9Sstevel@tonic-gate /* first get the number paths */ 13587c478bd9Sstevel@tonic-gate bzero(&ioc, sizeof (sv_iocdata_t)); 13597c478bd9Sstevel@tonic-gate ioc.client = vhci_name_buf; 13607c478bd9Sstevel@tonic-gate ioc.ret_elem = &npaths; 13617c478bd9Sstevel@tonic-gate if (vhci_ctl(&ioc, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO) != 0 || 13627c478bd9Sstevel@tonic-gate npaths == 0) { 13637c478bd9Sstevel@tonic-gate logdmsg(("vhci_to_phci: vhci_ctl failed to get npaths: %s\n", 13647c478bd9Sstevel@tonic-gate strerror(errno))); 13657c478bd9Sstevel@tonic-gate return (NULL); 13667c478bd9Sstevel@tonic-gate } 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate /* now allocate memory for the path information and get all paths */ 13697c478bd9Sstevel@tonic-gate bzero(&ioc, sizeof (sv_iocdata_t)); 13707c478bd9Sstevel@tonic-gate ioc.client = vhci_name_buf; 13717c478bd9Sstevel@tonic-gate ioc.buf_elem = npaths; 13727c478bd9Sstevel@tonic-gate ioc.ret_elem = &npaths; 13737c478bd9Sstevel@tonic-gate if ((ioc.ret_buf = (sv_path_info_t *)calloc(npaths, 13747c478bd9Sstevel@tonic-gate sizeof (sv_path_info_t))) == NULL) 13757c478bd9Sstevel@tonic-gate return (NULL); 13767c478bd9Sstevel@tonic-gate if (vhci_ctl(&ioc, SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO) != 0 || 13777c478bd9Sstevel@tonic-gate npaths == 0) { 13787c478bd9Sstevel@tonic-gate logdmsg(("vhci_to_phci: vhci_ctl failed: %s\n", 13797c478bd9Sstevel@tonic-gate strerror(errno))); 13807c478bd9Sstevel@tonic-gate goto out; 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate 13837c478bd9Sstevel@tonic-gate if (ioc.buf_elem < npaths) 13847c478bd9Sstevel@tonic-gate npaths = ioc.buf_elem; 13857c478bd9Sstevel@tonic-gate 13867c478bd9Sstevel@tonic-gate if ((node_name = strrchr(vhci_name_buf, '/')) == NULL || 13877c478bd9Sstevel@tonic-gate (at = strchr(node_name, '@')) == NULL) 13887c478bd9Sstevel@tonic-gate goto out; 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate node_name++; 13917c478bd9Sstevel@tonic-gate *at = '\0'; 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate /* allocate one more (than npaths) for the terminating NULL pointer */ 13947c478bd9Sstevel@tonic-gate if ((phci_list = calloc(npaths + 1, sizeof (char *))) == NULL) 13957c478bd9Sstevel@tonic-gate goto out; 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate /* 13987c478bd9Sstevel@tonic-gate * add only online paths as non-online paths may not be accessible 13997c478bd9Sstevel@tonic-gate * in the target environment. 14007c478bd9Sstevel@tonic-gate */ 14017c478bd9Sstevel@tonic-gate if ((n = add_to_phci_list(phci_list, ioc.ret_buf, npaths, 14027c478bd9Sstevel@tonic-gate MDI_PATHINFO_STATE_ONLINE, node_name)) <= 0) 14037c478bd9Sstevel@tonic-gate goto out; 14047c478bd9Sstevel@tonic-gate 14057c478bd9Sstevel@tonic-gate free(ioc.ret_buf); 14067c478bd9Sstevel@tonic-gate *num_paths = n; 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate #ifdef DEBUG 14097c478bd9Sstevel@tonic-gate logdmsg(("vhci_to_phci: phci list:\n")); 14107c478bd9Sstevel@tonic-gate log_pathlist(phci_list); 14117c478bd9Sstevel@tonic-gate #endif 14127c478bd9Sstevel@tonic-gate return (phci_list); 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate out: 14157c478bd9Sstevel@tonic-gate free(ioc.ret_buf); 14167c478bd9Sstevel@tonic-gate if (phci_list) 14177c478bd9Sstevel@tonic-gate free_pathlist(phci_list); 14187c478bd9Sstevel@tonic-gate return (NULL); 14197c478bd9Sstevel@tonic-gate } 14207c478bd9Sstevel@tonic-gate 14217c478bd9Sstevel@tonic-gate /* 14227c478bd9Sstevel@tonic-gate * build list of paths accessible from the target environment 14237c478bd9Sstevel@tonic-gate */ 14247c478bd9Sstevel@tonic-gate static int 14257c478bd9Sstevel@tonic-gate build_pathlist(char *rootdir, char *vhcipath, char **pathlist, int npaths) 14267c478bd9Sstevel@tonic-gate { 14277c478bd9Sstevel@tonic-gate int mpxio_disabled; 14287c478bd9Sstevel@tonic-gate int i, j; 14297c478bd9Sstevel@tonic-gate char *vpath = NULL; 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate for (i = 0; i < npaths; i++) { 14327c478bd9Sstevel@tonic-gate mpxio_disabled = is_mpxio_disabled(rootdir, pathlist[i]); 14337c478bd9Sstevel@tonic-gate logdmsg(("build_pathlist: mpxio_disabled = %d " 14347c478bd9Sstevel@tonic-gate "on path %s\n", mpxio_disabled, pathlist[i])); 14357c478bd9Sstevel@tonic-gate if (mpxio_disabled == -1) 14367c478bd9Sstevel@tonic-gate return (-1); 14377c478bd9Sstevel@tonic-gate if (mpxio_disabled == 0) { 14387c478bd9Sstevel@tonic-gate /* 14397c478bd9Sstevel@tonic-gate * mpxio is enabled on this phci path. 14407c478bd9Sstevel@tonic-gate * So use vhci path instead of phci path. 14417c478bd9Sstevel@tonic-gate */ 14427c478bd9Sstevel@tonic-gate if (vpath == NULL) { 14437c478bd9Sstevel@tonic-gate if ((vpath = strdup(vhcipath)) == NULL) 14447c478bd9Sstevel@tonic-gate return (-1); 14457c478bd9Sstevel@tonic-gate free(pathlist[i]); 14467c478bd9Sstevel@tonic-gate /* keep vhci path at beginning of the list */ 14477c478bd9Sstevel@tonic-gate for (j = i; j > 0; j--) 14487c478bd9Sstevel@tonic-gate pathlist[j] = pathlist[j - 1]; 14497c478bd9Sstevel@tonic-gate pathlist[0] = vpath; 14507c478bd9Sstevel@tonic-gate } else { 14517c478bd9Sstevel@tonic-gate free(pathlist[i]); 14527c478bd9Sstevel@tonic-gate npaths--; 14537c478bd9Sstevel@tonic-gate for (j = i; j < npaths; j++) 14547c478bd9Sstevel@tonic-gate pathlist[j] = pathlist[j + 1]; 14557c478bd9Sstevel@tonic-gate pathlist[npaths] = NULL; 14567c478bd9Sstevel@tonic-gate /* compensate for i++ in the for loop */ 14577c478bd9Sstevel@tonic-gate i--; 14587c478bd9Sstevel@tonic-gate } 14597c478bd9Sstevel@tonic-gate } 14607c478bd9Sstevel@tonic-gate } 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate #ifdef DEBUG 14637c478bd9Sstevel@tonic-gate logdmsg(("build_pathlist: returning npaths = %d, pathlist:\n", npaths)); 14647c478bd9Sstevel@tonic-gate log_pathlist(pathlist); 14657c478bd9Sstevel@tonic-gate #endif 14667c478bd9Sstevel@tonic-gate return (npaths); 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate /* 14707c478bd9Sstevel@tonic-gate * Check if the specified device is refenced in the vfstab file. 14717c478bd9Sstevel@tonic-gate * Return 1 if referenced, 0 if not. 14727c478bd9Sstevel@tonic-gate * 14737c478bd9Sstevel@tonic-gate * rootdir root directory of the target environment 14747c478bd9Sstevel@tonic-gate * nodepath /devices path of a device in the target environment without 14757c478bd9Sstevel@tonic-gate * the /devices prefix and minor component. 14767c478bd9Sstevel@tonic-gate */ 14777c478bd9Sstevel@tonic-gate static int 14787c478bd9Sstevel@tonic-gate is_dev_in_vfstab(char *rootdir, char *nodepath) 14797c478bd9Sstevel@tonic-gate { 14807c478bd9Sstevel@tonic-gate FILE *fp; 14817c478bd9Sstevel@tonic-gate int linksize; 14827c478bd9Sstevel@tonic-gate struct vfstab vfsent; 14837c478bd9Sstevel@tonic-gate char *abspath, *minor; 14847c478bd9Sstevel@tonic-gate char physpath[MAXPATHLEN]; 14857c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 14867c478bd9Sstevel@tonic-gate 14877c478bd9Sstevel@tonic-gate logdmsg(("is_dev_in_vfstab: rootdir = %s, nodepath = %s\n", 14887c478bd9Sstevel@tonic-gate rootdir, nodepath)); 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s%s", rootdir, VFSTAB); 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate if ((fp = fopen(buf, "r")) == NULL) 14937c478bd9Sstevel@tonic-gate return (0); 14947c478bd9Sstevel@tonic-gate 14957c478bd9Sstevel@tonic-gate /* 14967c478bd9Sstevel@tonic-gate * read device specials from vfstab and compare names at physical 14977c478bd9Sstevel@tonic-gate * node path level. 14987c478bd9Sstevel@tonic-gate */ 14997c478bd9Sstevel@tonic-gate while (getvfsent(fp, &vfsent) == 0) { 15007c478bd9Sstevel@tonic-gate if (strncmp(vfsent.vfs_special, SLASH_DEV_SLASH, 15017c478bd9Sstevel@tonic-gate sizeof (SLASH_DEV_SLASH) - 1) == 0) { 15027c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN, "%s%s", 15037c478bd9Sstevel@tonic-gate rootdir, vfsent.vfs_special); 15047c478bd9Sstevel@tonic-gate if ((linksize = readlink(buf, physpath, 15057c478bd9Sstevel@tonic-gate MAXPATHLEN)) > 0 && linksize < (MAXPATHLEN - 1)) { 15067c478bd9Sstevel@tonic-gate physpath[linksize] = '\0'; 15077c478bd9Sstevel@tonic-gate if ((abspath = strstr(physpath, 15087c478bd9Sstevel@tonic-gate SLASH_DEVICES_SLASH)) == NULL) 15097c478bd9Sstevel@tonic-gate continue; 15107c478bd9Sstevel@tonic-gate } else 15117c478bd9Sstevel@tonic-gate continue; 15127c478bd9Sstevel@tonic-gate } else if (strncmp(vfsent.vfs_special, SLASH_DEVICES_SLASH, 15137c478bd9Sstevel@tonic-gate sizeof (SLASH_DEVICES_SLASH) - 1) == 0) { 15147c478bd9Sstevel@tonic-gate (void) strlcpy(physpath, vfsent.vfs_special, 15157c478bd9Sstevel@tonic-gate MAXPATHLEN); 15167c478bd9Sstevel@tonic-gate abspath = physpath; 15177c478bd9Sstevel@tonic-gate } else 15187c478bd9Sstevel@tonic-gate continue; 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate /* point to / after /devices */ 15217c478bd9Sstevel@tonic-gate abspath += sizeof (SLASH_DEVICES_SLASH) - 2; 15227c478bd9Sstevel@tonic-gate /* strip minor component */ 15237c478bd9Sstevel@tonic-gate if ((minor = strrchr(abspath, ':')) != NULL) 15247c478bd9Sstevel@tonic-gate *minor = '\0'; 15257c478bd9Sstevel@tonic-gate 15267c478bd9Sstevel@tonic-gate if (strcmp(nodepath, abspath) == 0) { 15277c478bd9Sstevel@tonic-gate (void) fclose(fp); 15287c478bd9Sstevel@tonic-gate logdmsg(("is_dev_in_vfstab: returning 1\n")); 15297c478bd9Sstevel@tonic-gate return (1); 15307c478bd9Sstevel@tonic-gate } 15317c478bd9Sstevel@tonic-gate } 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate (void) fclose(fp); 15347c478bd9Sstevel@tonic-gate return (0); 15357c478bd9Sstevel@tonic-gate } 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate #endif /* __sparc */ 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate static int 15407c478bd9Sstevel@tonic-gate devlink_callback(di_devlink_t devlink, void *argp) 15417c478bd9Sstevel@tonic-gate { 15427c478bd9Sstevel@tonic-gate const char *link; 15437c478bd9Sstevel@tonic-gate 15447c478bd9Sstevel@tonic-gate if ((link = di_devlink_path(devlink)) != NULL) 15457c478bd9Sstevel@tonic-gate (void) strlcpy((char *)argp, link, MAXPATHLEN); 15467c478bd9Sstevel@tonic-gate 15477c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 15487c478bd9Sstevel@tonic-gate } 15497c478bd9Sstevel@tonic-gate 15507c478bd9Sstevel@tonic-gate /* 15517c478bd9Sstevel@tonic-gate * Get the /dev name in the install environment corresponding to physpath. 15527c478bd9Sstevel@tonic-gate * 15537c478bd9Sstevel@tonic-gate * physpath /devices path in the install environment without the /devices 15547c478bd9Sstevel@tonic-gate * prefix. 15557c478bd9Sstevel@tonic-gate * buf caller supplied buffer where the /dev name is placed on return 15567c478bd9Sstevel@tonic-gate * bufsz length of the buffer 15577c478bd9Sstevel@tonic-gate * 15587c478bd9Sstevel@tonic-gate * Returns strlen of the /dev name on success, -1 on failure. 15597c478bd9Sstevel@tonic-gate */ 15607c478bd9Sstevel@tonic-gate static int 15617c478bd9Sstevel@tonic-gate get_install_devlink(char *physpath, char *buf, size_t bufsz) 15627c478bd9Sstevel@tonic-gate { 15637c478bd9Sstevel@tonic-gate di_devlink_handle_t devlink_hdl; 15647c478bd9Sstevel@tonic-gate char devname[MAXPATHLEN]; 1565*72916ffbSGangadhar Mylapuram int tries = 0; 1566*72916ffbSGangadhar Mylapuram int sleeptime = 2; /* number of seconds to sleep between retries */ 1567*72916ffbSGangadhar Mylapuram int maxtries = 10; /* maximum number of tries */ 15687c478bd9Sstevel@tonic-gate 15697c478bd9Sstevel@tonic-gate logdmsg(("get_install_devlink: physpath = %s\n", physpath)); 15707c478bd9Sstevel@tonic-gate 1571*72916ffbSGangadhar Mylapuram /* 1572*72916ffbSGangadhar Mylapuram * devlink_db sync happens after MINOR_FINI_TIMEOUT_DEFAULT secs 1573*72916ffbSGangadhar Mylapuram * after dev link creation. So wait for minimum that amout of time. 1574*72916ffbSGangadhar Mylapuram */ 1575*72916ffbSGangadhar Mylapuram 1576*72916ffbSGangadhar Mylapuram retry: 1577*72916ffbSGangadhar Mylapuram (void) sleep(sleeptime); 1578*72916ffbSGangadhar Mylapuram 15797c478bd9Sstevel@tonic-gate if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 15807c478bd9Sstevel@tonic-gate logdmsg(("get_install_devlink: di_devlink_init() failed: %s\n", 15817c478bd9Sstevel@tonic-gate strerror(errno))); 15827c478bd9Sstevel@tonic-gate return (-1); 15837c478bd9Sstevel@tonic-gate } 15847c478bd9Sstevel@tonic-gate 15857c478bd9Sstevel@tonic-gate devname[0] = '\0'; 15867c478bd9Sstevel@tonic-gate if (di_devlink_walk(devlink_hdl, NULL, physpath, DI_PRIMARY_LINK, 1587*72916ffbSGangadhar Mylapuram devname, devlink_callback) == 0) { 1588*72916ffbSGangadhar Mylapuram if (devname[0] == '\0' && tries < maxtries) { 1589*72916ffbSGangadhar Mylapuram tries++; 1590*72916ffbSGangadhar Mylapuram (void) di_devlink_fini(&devlink_hdl); 1591*72916ffbSGangadhar Mylapuram goto retry; 1592*72916ffbSGangadhar Mylapuram } else if (devname[0] == '\0') { 1593*72916ffbSGangadhar Mylapuram logdmsg(("get_install_devlink: di_devlink_walk" 1594*72916ffbSGangadhar Mylapuram " failed: %s\n", strerror(errno))); 1595*72916ffbSGangadhar Mylapuram (void) di_devlink_fini(&devlink_hdl); 1596*72916ffbSGangadhar Mylapuram return (-1); 1597*72916ffbSGangadhar Mylapuram } 1598*72916ffbSGangadhar Mylapuram } else { 15997c478bd9Sstevel@tonic-gate logdmsg(("get_install_devlink: di_devlink_walk failed: %s\n", 16007c478bd9Sstevel@tonic-gate strerror(errno))); 16017c478bd9Sstevel@tonic-gate (void) di_devlink_fini(&devlink_hdl); 16027c478bd9Sstevel@tonic-gate return (-1); 16037c478bd9Sstevel@tonic-gate } 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate (void) di_devlink_fini(&devlink_hdl); 16067c478bd9Sstevel@tonic-gate 16077c478bd9Sstevel@tonic-gate logdmsg(("get_install_devlink: devlink = %s\n", devname)); 16087c478bd9Sstevel@tonic-gate return (strlcpy(buf, devname, bufsz)); 16097c478bd9Sstevel@tonic-gate } 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate /* 16127c478bd9Sstevel@tonic-gate * Get the /dev name in the target environment corresponding to physpath. 16137c478bd9Sstevel@tonic-gate * 16147c478bd9Sstevel@tonic-gate * rootdir root directory of the target environment 16157c478bd9Sstevel@tonic-gate * physpath /devices path in the target environment without the /devices 16167c478bd9Sstevel@tonic-gate * prefix. 16177c478bd9Sstevel@tonic-gate * buf caller supplied buffer where the /dev name is placed on return 16187c478bd9Sstevel@tonic-gate * bufsz length of the buffer 16197c478bd9Sstevel@tonic-gate * 16207c478bd9Sstevel@tonic-gate * Returns strlen of the /dev name on success, -1 on failure. 16217c478bd9Sstevel@tonic-gate */ 16227c478bd9Sstevel@tonic-gate static int 16237c478bd9Sstevel@tonic-gate get_target_devlink(char *rootdir, char *physpath, char *buf, size_t bufsz) 16247c478bd9Sstevel@tonic-gate { 16257c478bd9Sstevel@tonic-gate char *p; 16267c478bd9Sstevel@tonic-gate int linksize; 16277c478bd9Sstevel@tonic-gate DIR *dirp; 16287c478bd9Sstevel@tonic-gate struct dirent *direntry; 16297c478bd9Sstevel@tonic-gate char dirpath[MAXPATHLEN]; 16307c478bd9Sstevel@tonic-gate char devname[MAXPATHLEN]; 16317c478bd9Sstevel@tonic-gate char physdev[MAXPATHLEN]; 16327c478bd9Sstevel@tonic-gate 16337c478bd9Sstevel@tonic-gate logdmsg(("get_target_devlink: rootdir = %s, physpath = %s\n", 16347c478bd9Sstevel@tonic-gate rootdir, physpath)); 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate if ((p = strrchr(physpath, '/')) == NULL) 16377c478bd9Sstevel@tonic-gate return (-1); 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate if (strstr(p, ",raw") != NULL) { 16407c478bd9Sstevel@tonic-gate (void) snprintf(dirpath, MAXPATHLEN, "%s/dev/rdsk", rootdir); 16417c478bd9Sstevel@tonic-gate } else { 16427c478bd9Sstevel@tonic-gate (void) snprintf(dirpath, MAXPATHLEN, "%s/dev/dsk", rootdir); 16437c478bd9Sstevel@tonic-gate } 16447c478bd9Sstevel@tonic-gate 16457c478bd9Sstevel@tonic-gate if ((dirp = opendir(dirpath)) == NULL) 16467c478bd9Sstevel@tonic-gate return (-1); 16477c478bd9Sstevel@tonic-gate 16487c478bd9Sstevel@tonic-gate while ((direntry = readdir(dirp)) != NULL) { 16497c478bd9Sstevel@tonic-gate if (strcmp(direntry->d_name, ".") == 0 || 16507c478bd9Sstevel@tonic-gate strcmp(direntry->d_name, "..") == 0) 16517c478bd9Sstevel@tonic-gate continue; 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate (void) snprintf(devname, MAXPATHLEN, "%s/%s", 16547c478bd9Sstevel@tonic-gate dirpath, direntry->d_name); 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate if ((linksize = readlink(devname, physdev, MAXPATHLEN)) > 0 && 16577c478bd9Sstevel@tonic-gate linksize < (MAXPATHLEN - 1)) { 16587c478bd9Sstevel@tonic-gate physdev[linksize] = '\0'; 16597c478bd9Sstevel@tonic-gate if ((p = strstr(physdev, SLASH_DEVICES_SLASH)) != 16607c478bd9Sstevel@tonic-gate NULL && strcmp(p + sizeof (SLASH_DEVICES) - 1, 16617c478bd9Sstevel@tonic-gate physpath) == 0) { 16627c478bd9Sstevel@tonic-gate (void) closedir(dirp); 16637c478bd9Sstevel@tonic-gate logdmsg(("get_target_devlink: devlink = %s\n", 16647c478bd9Sstevel@tonic-gate devname + strlen(rootdir))); 16657c478bd9Sstevel@tonic-gate return (strlcpy(buf, devname + strlen(rootdir), 16667c478bd9Sstevel@tonic-gate bufsz)); 16677c478bd9Sstevel@tonic-gate } 16687c478bd9Sstevel@tonic-gate } 16697c478bd9Sstevel@tonic-gate } 16707c478bd9Sstevel@tonic-gate 16717c478bd9Sstevel@tonic-gate (void) closedir(dirp); 16727c478bd9Sstevel@tonic-gate return (-1); 16737c478bd9Sstevel@tonic-gate } 16747c478bd9Sstevel@tonic-gate 16757c478bd9Sstevel@tonic-gate /* 16767c478bd9Sstevel@tonic-gate * Convert device name to physpath. 16777c478bd9Sstevel@tonic-gate * 16787c478bd9Sstevel@tonic-gate * rootdir root directory 16797c478bd9Sstevel@tonic-gate * devname a /dev name or /devices name under rootdir 16807c478bd9Sstevel@tonic-gate * physpath caller supplied buffer where the /devices path will be placed 16817c478bd9Sstevel@tonic-gate * on return (without the /devices prefix). 16827c478bd9Sstevel@tonic-gate * physpathlen length of the physpath buffer 16837c478bd9Sstevel@tonic-gate * 16847c478bd9Sstevel@tonic-gate * Returns 0 on success, -1 on failure. 16857c478bd9Sstevel@tonic-gate */ 16867c478bd9Sstevel@tonic-gate static int 16877c478bd9Sstevel@tonic-gate devname2physpath(char *rootdir, char *devname, char *physpath, int physpathlen) 16887c478bd9Sstevel@tonic-gate { 16897c478bd9Sstevel@tonic-gate int linksize; 16907c478bd9Sstevel@tonic-gate char *p; 16917c478bd9Sstevel@tonic-gate char devlink[MAXPATHLEN]; 16927c478bd9Sstevel@tonic-gate char tmpphyspath[MAXPATHLEN]; 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate logdmsg(("devname2physpath: rootdir = %s, devname = %s\n", 16957c478bd9Sstevel@tonic-gate rootdir, devname)); 16967c478bd9Sstevel@tonic-gate 16977c478bd9Sstevel@tonic-gate if (strncmp(devname, SLASH_DEVICES_SLASH, 16987c478bd9Sstevel@tonic-gate sizeof (SLASH_DEVICES_SLASH) - 1) != 0) { 16997c478bd9Sstevel@tonic-gate if (*rootdir == '\0') 17007c478bd9Sstevel@tonic-gate linksize = readlink(devname, tmpphyspath, MAXPATHLEN); 17017c478bd9Sstevel@tonic-gate else { 17027c478bd9Sstevel@tonic-gate (void) snprintf(devlink, MAXPATHLEN, "%s%s", 17037c478bd9Sstevel@tonic-gate rootdir, devname); 17047c478bd9Sstevel@tonic-gate linksize = readlink(devlink, tmpphyspath, MAXPATHLEN); 17057c478bd9Sstevel@tonic-gate } 17067c478bd9Sstevel@tonic-gate if (linksize > 0 && linksize < (MAXPATHLEN - 1)) { 17077c478bd9Sstevel@tonic-gate tmpphyspath[linksize] = '\0'; 17087c478bd9Sstevel@tonic-gate if ((p = strstr(tmpphyspath, SLASH_DEVICES_SLASH)) 17097c478bd9Sstevel@tonic-gate == NULL) 17107c478bd9Sstevel@tonic-gate return (-1); 17117c478bd9Sstevel@tonic-gate } else 17127c478bd9Sstevel@tonic-gate return (-1); 17137c478bd9Sstevel@tonic-gate } else 17147c478bd9Sstevel@tonic-gate p = devname; 17157c478bd9Sstevel@tonic-gate 17167c478bd9Sstevel@tonic-gate (void) strlcpy(physpath, p + sizeof (SLASH_DEVICES) - 1, physpathlen); 17177c478bd9Sstevel@tonic-gate logdmsg(("devname2physpath: physpath = %s\n", physpath)); 17187c478bd9Sstevel@tonic-gate return (0); 17197c478bd9Sstevel@tonic-gate } 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate /* 17227c478bd9Sstevel@tonic-gate * Map a device name (devname) from the target environment to the 17237c478bd9Sstevel@tonic-gate * install environment. 17247c478bd9Sstevel@tonic-gate * 17257c478bd9Sstevel@tonic-gate * rootdir root directory of the target environment 17267c478bd9Sstevel@tonic-gate * devname /dev or /devices name under the target environment 17277c478bd9Sstevel@tonic-gate * buf caller supplied buffer where the mapped /dev name is placed 17287c478bd9Sstevel@tonic-gate * on return 17297c478bd9Sstevel@tonic-gate * bufsz length of the buffer 17307c478bd9Sstevel@tonic-gate * 17317c478bd9Sstevel@tonic-gate * Returns strlen of the mapped /dev name on success, -1 on failure. 17327c478bd9Sstevel@tonic-gate */ 17337c478bd9Sstevel@tonic-gate int 17347c478bd9Sstevel@tonic-gate devfs_target2install(const char *rootdir, const char *devname, char *buf, 17357c478bd9Sstevel@tonic-gate size_t bufsz) 17367c478bd9Sstevel@tonic-gate { 17377c478bd9Sstevel@tonic-gate char physpath[MAXPATHLEN]; 17387c478bd9Sstevel@tonic-gate 17397c478bd9Sstevel@tonic-gate logdmsg(("devfs_target2install: rootdir = %s, devname = %s\n", 17407c478bd9Sstevel@tonic-gate STRVAL(rootdir), STRVAL(devname))); 17417c478bd9Sstevel@tonic-gate 17427c478bd9Sstevel@tonic-gate if (rootdir == NULL || devname == NULL || buf == NULL || bufsz == 0) 17437c478bd9Sstevel@tonic-gate return (-1); 17447c478bd9Sstevel@tonic-gate 17457c478bd9Sstevel@tonic-gate if (strcmp(rootdir, "/") == 0) 17467c478bd9Sstevel@tonic-gate rootdir = ""; 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate if (devname2physpath((char *)rootdir, (char *)devname, physpath, 17497c478bd9Sstevel@tonic-gate MAXPATHLEN) != 0) 17507c478bd9Sstevel@tonic-gate return (-1); 17517c478bd9Sstevel@tonic-gate 17527c478bd9Sstevel@tonic-gate #ifdef __sparc 17537c478bd9Sstevel@tonic-gate if (client_name_type(physpath) == CLIENT_TYPE_PHCI) { 17547c478bd9Sstevel@tonic-gate char *mapped_node_path, *minor; 17557c478bd9Sstevel@tonic-gate char minorbuf[MAXNAMELEN]; 17567c478bd9Sstevel@tonic-gate 17577c478bd9Sstevel@tonic-gate /* strip minor component if present */ 17587c478bd9Sstevel@tonic-gate if ((minor = strrchr(physpath, ':')) != NULL) { 17597c478bd9Sstevel@tonic-gate *minor = '\0'; 17607c478bd9Sstevel@tonic-gate minor++; 17617c478bd9Sstevel@tonic-gate (void) strlcpy(minorbuf, minor, MAXNAMELEN); 17627c478bd9Sstevel@tonic-gate } 17637c478bd9Sstevel@tonic-gate if ((mapped_node_path = phci_to_vhci(physpath)) != NULL) { 17647c478bd9Sstevel@tonic-gate if (minor) 17657c478bd9Sstevel@tonic-gate (void) snprintf(physpath, MAXPATHLEN, 17667c478bd9Sstevel@tonic-gate "%s:%s", mapped_node_path, minorbuf); 17677c478bd9Sstevel@tonic-gate else 17687c478bd9Sstevel@tonic-gate (void) strlcpy(physpath, mapped_node_path, 17697c478bd9Sstevel@tonic-gate MAXPATHLEN); 17707c478bd9Sstevel@tonic-gate free(mapped_node_path); 17717c478bd9Sstevel@tonic-gate logdmsg(("devfs_target2install: mapped physpath: %s\n", 17727c478bd9Sstevel@tonic-gate physpath)); 17737c478bd9Sstevel@tonic-gate 17747c478bd9Sstevel@tonic-gate } else if (minor) 17757c478bd9Sstevel@tonic-gate *(minor - 1) = ':'; 17767c478bd9Sstevel@tonic-gate } 17777c478bd9Sstevel@tonic-gate #endif /* __sparc */ 17787c478bd9Sstevel@tonic-gate 17797c478bd9Sstevel@tonic-gate return (get_install_devlink(physpath, buf, bufsz)); 17807c478bd9Sstevel@tonic-gate } 17817c478bd9Sstevel@tonic-gate 17827c478bd9Sstevel@tonic-gate /* 17837c478bd9Sstevel@tonic-gate * Map a device name (devname) from the install environment to the target 17847c478bd9Sstevel@tonic-gate * environment. 17857c478bd9Sstevel@tonic-gate * 17867c478bd9Sstevel@tonic-gate * rootdir root directory of the target environment 17877c478bd9Sstevel@tonic-gate * devname /dev or /devices name under the install environment 17887c478bd9Sstevel@tonic-gate * buf caller supplied buffer where the mapped /dev name is placed 17897c478bd9Sstevel@tonic-gate * on return 17907c478bd9Sstevel@tonic-gate * bufsz length of the buffer 17917c478bd9Sstevel@tonic-gate * 17927c478bd9Sstevel@tonic-gate * Returns strlen of the mapped /dev name on success, -1 on failure. 17937c478bd9Sstevel@tonic-gate */ 17947c478bd9Sstevel@tonic-gate int 17957c478bd9Sstevel@tonic-gate devfs_install2target(const char *rootdir, const char *devname, char *buf, 17967c478bd9Sstevel@tonic-gate size_t bufsz) 17977c478bd9Sstevel@tonic-gate { 17987c478bd9Sstevel@tonic-gate char physpath[MAXPATHLEN]; 17997c478bd9Sstevel@tonic-gate 18007c478bd9Sstevel@tonic-gate logdmsg(("devfs_install2target: rootdir = %s, devname = %s\n", 18017c478bd9Sstevel@tonic-gate STRVAL(rootdir), STRVAL(devname))); 18027c478bd9Sstevel@tonic-gate 18037c478bd9Sstevel@tonic-gate if (rootdir == NULL || devname == NULL || buf == NULL || bufsz == 0) 18047c478bd9Sstevel@tonic-gate return (-1); 18057c478bd9Sstevel@tonic-gate 18067c478bd9Sstevel@tonic-gate if (strcmp(rootdir, "/") == 0) 18077c478bd9Sstevel@tonic-gate rootdir = ""; 18087c478bd9Sstevel@tonic-gate 18097c478bd9Sstevel@tonic-gate if (devname2physpath("", (char *)devname, physpath, MAXPATHLEN) != 0) 18107c478bd9Sstevel@tonic-gate return (-1); 18117c478bd9Sstevel@tonic-gate 18127c478bd9Sstevel@tonic-gate #ifdef __sparc 18137c478bd9Sstevel@tonic-gate if (client_name_type(physpath) == CLIENT_TYPE_VHCI) { 18147c478bd9Sstevel@tonic-gate char **pathlist; 18157c478bd9Sstevel@tonic-gate int npaths, i, j; 18167c478bd9Sstevel@tonic-gate char *minor; 18177c478bd9Sstevel@tonic-gate char minorbuf[MAXNAMELEN]; 18187c478bd9Sstevel@tonic-gate 18197c478bd9Sstevel@tonic-gate /* strip minor component if present */ 18207c478bd9Sstevel@tonic-gate if ((minor = strrchr(physpath, ':')) != NULL) { 18217c478bd9Sstevel@tonic-gate *minor = '\0'; 18227c478bd9Sstevel@tonic-gate minor++; 18237c478bd9Sstevel@tonic-gate (void) strlcpy(minorbuf, minor, MAXNAMELEN); 18247c478bd9Sstevel@tonic-gate } 18257c478bd9Sstevel@tonic-gate 18267c478bd9Sstevel@tonic-gate if ((pathlist = vhci_to_phci(physpath, &npaths)) == NULL) 18277c478bd9Sstevel@tonic-gate return (-1); 18287c478bd9Sstevel@tonic-gate 18297c478bd9Sstevel@tonic-gate if ((npaths = build_pathlist((char *)rootdir, physpath, 18307c478bd9Sstevel@tonic-gate pathlist, npaths)) <= 0) { 18317c478bd9Sstevel@tonic-gate free_pathlist(pathlist); 18327c478bd9Sstevel@tonic-gate return (-1); 18337c478bd9Sstevel@tonic-gate } 18347c478bd9Sstevel@tonic-gate 18357c478bd9Sstevel@tonic-gate /* 18367c478bd9Sstevel@tonic-gate * in case of more than one path, try to use the path 18377c478bd9Sstevel@tonic-gate * referenced in the vfstab file, otherwise use the first path. 18387c478bd9Sstevel@tonic-gate */ 18397c478bd9Sstevel@tonic-gate j = 0; 18407c478bd9Sstevel@tonic-gate if (npaths > 1) { 18417c478bd9Sstevel@tonic-gate for (i = 0; i < npaths; i++) { 18427c478bd9Sstevel@tonic-gate if (is_dev_in_vfstab((char *)rootdir, 18437c478bd9Sstevel@tonic-gate pathlist[i])) { 18447c478bd9Sstevel@tonic-gate j = i; 18457c478bd9Sstevel@tonic-gate break; 18467c478bd9Sstevel@tonic-gate } 18477c478bd9Sstevel@tonic-gate } 18487c478bd9Sstevel@tonic-gate } 18497c478bd9Sstevel@tonic-gate 18507c478bd9Sstevel@tonic-gate if (minor) 18517c478bd9Sstevel@tonic-gate (void) snprintf(physpath, MAXPATHLEN, 18527c478bd9Sstevel@tonic-gate "%s:%s", pathlist[j], minorbuf); 18537c478bd9Sstevel@tonic-gate else 18547c478bd9Sstevel@tonic-gate (void) strlcpy(physpath, pathlist[j], MAXPATHLEN); 18557c478bd9Sstevel@tonic-gate free_pathlist(pathlist); 18567c478bd9Sstevel@tonic-gate } 18577c478bd9Sstevel@tonic-gate #endif /* __sparc */ 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate return (get_target_devlink((char *)rootdir, physpath, buf, bufsz)); 18607c478bd9Sstevel@tonic-gate } 18617c478bd9Sstevel@tonic-gate 18621aef0e11Sjg /* 18631aef0e11Sjg * A parser for /etc/path_to_inst. 18641aef0e11Sjg * The user-supplied callback is called once for each entry in the file. 18651aef0e11Sjg * Returns 0 on success, ENOMEM/ENOENT/EINVAL on error. 18661aef0e11Sjg * Callback may return DI_WALK_TERMINATE to terminate the walk, 18671aef0e11Sjg * otherwise DI_WALK_CONTINUE. 18681aef0e11Sjg */ 18691aef0e11Sjg int 18701aef0e11Sjg devfs_parse_binding_file(const char *binding_file, 18711aef0e11Sjg int (*callback)(void *, const char *, int, 18721aef0e11Sjg const char *), void *cb_arg) 18731aef0e11Sjg { 18741aef0e11Sjg token_t token; 18751aef0e11Sjg struct conf_file file; 18761aef0e11Sjg char tokval[MAX_TOKEN_SIZE]; 18771aef0e11Sjg enum { STATE_RESET, STATE_DEVPATH, STATE_INSTVAL } state; 18781aef0e11Sjg char *devpath; 18791aef0e11Sjg char *bindname; 18801aef0e11Sjg int instval = 0; 18811aef0e11Sjg int rv; 18821aef0e11Sjg 18831aef0e11Sjg if ((devpath = calloc(1, MAXPATHLEN)) == NULL) 18841aef0e11Sjg return (ENOMEM); 1885da3b42e9Sethindra if ((bindname = calloc(1, MAX_TOKEN_SIZE)) == NULL) { 1886da3b42e9Sethindra free(devpath); 18871aef0e11Sjg return (ENOMEM); 1888da3b42e9Sethindra } 18891aef0e11Sjg 18901aef0e11Sjg if ((file.fp = fopen(binding_file, "r")) == NULL) { 18911aef0e11Sjg free(devpath); 18921aef0e11Sjg free(bindname); 18931aef0e11Sjg return (errno); 18941aef0e11Sjg } 18951aef0e11Sjg 18961aef0e11Sjg file.filename = (char *)binding_file; 18971aef0e11Sjg file.linenum = 1; 18981aef0e11Sjg 18991aef0e11Sjg state = STATE_RESET; 19001aef0e11Sjg while ((token = lex(&file, tokval, MAX_TOKEN_SIZE)) != T_EOF) { 19011aef0e11Sjg switch (token) { 19021aef0e11Sjg case T_POUND: 19031aef0e11Sjg /* 19041aef0e11Sjg * Skip comments. 19051aef0e11Sjg */ 19061aef0e11Sjg find_eol(file.fp); 19071aef0e11Sjg break; 19081aef0e11Sjg case T_NAME: 19091aef0e11Sjg case T_STRING: 19101aef0e11Sjg switch (state) { 19111aef0e11Sjg case STATE_RESET: 19121aef0e11Sjg if (strlcpy(devpath, tokval, 19131aef0e11Sjg MAXPATHLEN) >= MAXPATHLEN) 19141aef0e11Sjg goto err; 19151aef0e11Sjg state = STATE_DEVPATH; 19161aef0e11Sjg break; 19171aef0e11Sjg case STATE_INSTVAL: 19181aef0e11Sjg if (strlcpy(bindname, tokval, 19191aef0e11Sjg MAX_TOKEN_SIZE) >= MAX_TOKEN_SIZE) 19201aef0e11Sjg goto err; 19211aef0e11Sjg rv = callback(cb_arg, 19221aef0e11Sjg devpath, instval, bindname); 19231aef0e11Sjg if (rv == DI_WALK_TERMINATE) 19241aef0e11Sjg goto done; 19251aef0e11Sjg if (rv != DI_WALK_CONTINUE) 19261aef0e11Sjg goto err; 19271aef0e11Sjg state = STATE_RESET; 19281aef0e11Sjg break; 19291aef0e11Sjg default: 19301aef0e11Sjg file_err(&file, tok_err, tokval); 19311aef0e11Sjg state = STATE_RESET; 19321aef0e11Sjg break; 19331aef0e11Sjg } 19341aef0e11Sjg break; 19351aef0e11Sjg case T_DECVAL: 19361aef0e11Sjg case T_HEXVAL: 19371aef0e11Sjg switch (state) { 19381aef0e11Sjg case STATE_DEVPATH: 19391aef0e11Sjg instval = (int)strtol(tokval, NULL, 0); 19401aef0e11Sjg state = STATE_INSTVAL; 19411aef0e11Sjg break; 19421aef0e11Sjg default: 19431aef0e11Sjg file_err(&file, tok_err, tokval); 19441aef0e11Sjg state = STATE_RESET; 19451aef0e11Sjg break; 19461aef0e11Sjg } 19471aef0e11Sjg break; 19481aef0e11Sjg case T_NEWLINE: 19491aef0e11Sjg file.linenum++; 19501aef0e11Sjg state = STATE_RESET; 19511aef0e11Sjg break; 19521aef0e11Sjg default: 19531aef0e11Sjg file_err(&file, tok_err, tokval); 19541aef0e11Sjg state = STATE_RESET; 19551aef0e11Sjg break; 19561aef0e11Sjg } 19571aef0e11Sjg } 19581aef0e11Sjg 19591aef0e11Sjg done: 19601aef0e11Sjg (void) fclose(file.fp); 19611aef0e11Sjg free(devpath); 19621aef0e11Sjg free(bindname); 19631aef0e11Sjg return (0); 19641aef0e11Sjg 19651aef0e11Sjg err: 19661aef0e11Sjg (void) fclose(file.fp); 19671aef0e11Sjg free(devpath); 19681aef0e11Sjg free(bindname); 19691aef0e11Sjg return (EINVAL); 19701aef0e11Sjg } 19711aef0e11Sjg 19721aef0e11Sjg /* 19731aef0e11Sjg * Walk the minor nodes of all children below the specified device 19741aef0e11Sjg * by calling the provided callback with the path to each minor. 19751aef0e11Sjg */ 19761aef0e11Sjg static int 19771aef0e11Sjg devfs_walk_children_minors(const char *device_path, struct stat *st, 19781aef0e11Sjg int (*callback)(void *, const char *), void *cb_arg, int *terminate) 19791aef0e11Sjg { 19801aef0e11Sjg DIR *dir; 19811aef0e11Sjg struct dirent *dp; 19821aef0e11Sjg char *minor_path = NULL; 19831aef0e11Sjg int need_close = 0; 19841aef0e11Sjg int rv; 19851aef0e11Sjg 19861aef0e11Sjg if ((minor_path = calloc(1, MAXPATHLEN)) == NULL) 19871aef0e11Sjg return (ENOMEM); 19881aef0e11Sjg 19891aef0e11Sjg if ((dir = opendir(device_path)) == NULL) { 19901aef0e11Sjg rv = ENOENT; 19911aef0e11Sjg goto err; 19921aef0e11Sjg } 19931aef0e11Sjg need_close = 1; 19941aef0e11Sjg 19951aef0e11Sjg while ((dp = readdir(dir)) != NULL) { 19961aef0e11Sjg if ((strcmp(dp->d_name, ".") == 0) || 19971aef0e11Sjg (strcmp(dp->d_name, "..") == 0)) 19981aef0e11Sjg continue; 19991aef0e11Sjg (void) snprintf(minor_path, MAXPATHLEN, 20001aef0e11Sjg "%s/%s", device_path, dp->d_name); 20011aef0e11Sjg if (stat(minor_path, st) == -1) 20021aef0e11Sjg continue; 20031aef0e11Sjg if (S_ISDIR(st->st_mode)) { 20041aef0e11Sjg rv = devfs_walk_children_minors( 20051aef0e11Sjg (const char *)minor_path, st, 20061aef0e11Sjg callback, cb_arg, terminate); 20071aef0e11Sjg if (rv != 0) 20081aef0e11Sjg goto err; 20091aef0e11Sjg if (*terminate) 20101aef0e11Sjg break; 20111aef0e11Sjg } else { 20121aef0e11Sjg rv = callback(cb_arg, minor_path); 20131aef0e11Sjg if (rv == DI_WALK_TERMINATE) { 20141aef0e11Sjg *terminate = 1; 20151aef0e11Sjg break; 20161aef0e11Sjg } 20171aef0e11Sjg if (rv != DI_WALK_CONTINUE) { 20181aef0e11Sjg rv = EINVAL; 20191aef0e11Sjg goto err; 20201aef0e11Sjg } 20211aef0e11Sjg } 20221aef0e11Sjg } 20231aef0e11Sjg 20241aef0e11Sjg rv = 0; 20251aef0e11Sjg err: 20261aef0e11Sjg if (need_close) 20271aef0e11Sjg (void) closedir(dir); 20281aef0e11Sjg if (minor_path) 20291aef0e11Sjg free(minor_path); 20301aef0e11Sjg return (rv); 20311aef0e11Sjg } 20321aef0e11Sjg 20331aef0e11Sjg /* 20341aef0e11Sjg * Return the path to each minor node for a device by 20351aef0e11Sjg * calling the provided callback. 20361aef0e11Sjg */ 20371aef0e11Sjg static int 20381aef0e11Sjg devfs_walk_device_minors(const char *device_path, struct stat *st, 20391aef0e11Sjg int (*callback)(void *, const char *), void *cb_arg, int *terminate) 20401aef0e11Sjg { 20411aef0e11Sjg char *minor_path; 20421aef0e11Sjg char *devpath; 20431aef0e11Sjg char *expr; 20441aef0e11Sjg regex_t regex; 20451aef0e11Sjg int need_regfree = 0; 20461aef0e11Sjg int need_close = 0; 20471aef0e11Sjg DIR *dir; 20481aef0e11Sjg struct dirent *dp; 20491aef0e11Sjg int rv; 20501aef0e11Sjg char *p; 20511aef0e11Sjg 20521aef0e11Sjg minor_path = calloc(1, MAXPATHLEN); 20531aef0e11Sjg devpath = calloc(1, MAXPATHLEN); 20541aef0e11Sjg expr = calloc(1, MAXNAMELEN); 20551aef0e11Sjg if (devpath == NULL || expr == NULL || minor_path == NULL) { 20561aef0e11Sjg rv = ENOMEM; 20571aef0e11Sjg goto err; 20581aef0e11Sjg } 20591aef0e11Sjg 20601aef0e11Sjg rv = EINVAL; 20611aef0e11Sjg if (strlcpy(devpath, device_path, MAXPATHLEN) >= MAXPATHLEN) 20621aef0e11Sjg goto err; 20631aef0e11Sjg if ((p = strrchr(devpath, '/')) == NULL) 20641aef0e11Sjg goto err; 20651aef0e11Sjg *p++ = 0; 20661aef0e11Sjg if (strlen(p) == 0) 20671aef0e11Sjg goto err; 20681aef0e11Sjg if (snprintf(expr, MAXNAMELEN, "%s:.*", p) >= MAXNAMELEN) 20691aef0e11Sjg goto err; 20701aef0e11Sjg if (regcomp(®ex, expr, REG_EXTENDED) != 0) 20711aef0e11Sjg goto err; 20721aef0e11Sjg need_regfree = 1; 20731aef0e11Sjg 20741aef0e11Sjg if ((dir = opendir(devpath)) == NULL) { 20751aef0e11Sjg rv = ENOENT; 20761aef0e11Sjg goto err; 20771aef0e11Sjg } 20781aef0e11Sjg need_close = 1; 20791aef0e11Sjg 20801aef0e11Sjg while ((dp = readdir(dir)) != NULL) { 20811aef0e11Sjg if ((strcmp(dp->d_name, ".") == 0) || 20821aef0e11Sjg (strcmp(dp->d_name, "..") == 0)) 20831aef0e11Sjg continue; 20841aef0e11Sjg (void) snprintf(minor_path, MAXPATHLEN, 20851aef0e11Sjg "%s/%s", devpath, dp->d_name); 20861aef0e11Sjg if (stat(minor_path, st) == -1) 20871aef0e11Sjg continue; 20881aef0e11Sjg if ((S_ISBLK(st->st_mode) || S_ISCHR(st->st_mode)) && 20891aef0e11Sjg regexec(®ex, dp->d_name, 0, NULL, 0) == 0) { 20901aef0e11Sjg rv = callback(cb_arg, minor_path); 20911aef0e11Sjg if (rv == DI_WALK_TERMINATE) { 20921aef0e11Sjg *terminate = 1; 20931aef0e11Sjg break; 20941aef0e11Sjg } 20951aef0e11Sjg if (rv != DI_WALK_CONTINUE) { 20961aef0e11Sjg rv = EINVAL; 20971aef0e11Sjg goto err; 20981aef0e11Sjg } 20991aef0e11Sjg } 21001aef0e11Sjg } 21011aef0e11Sjg 21021aef0e11Sjg rv = 0; 21031aef0e11Sjg err: 21041aef0e11Sjg if (need_close) 21051aef0e11Sjg (void) closedir(dir); 21061aef0e11Sjg if (need_regfree) 21071aef0e11Sjg regfree(®ex); 21081aef0e11Sjg if (devpath) 21091aef0e11Sjg free(devpath); 21101aef0e11Sjg if (minor_path) 21111aef0e11Sjg free(minor_path); 21121aef0e11Sjg if (expr) 21131aef0e11Sjg free(expr); 21141aef0e11Sjg return (rv); 21151aef0e11Sjg } 21161aef0e11Sjg 21171aef0e11Sjg /* 21181aef0e11Sjg * Perform a walk of all minor nodes for the specified device, 21191aef0e11Sjg * and minor nodes below the device. 21201aef0e11Sjg */ 21211aef0e11Sjg int 21221aef0e11Sjg devfs_walk_minor_nodes(const char *device_path, 21231aef0e11Sjg int (*callback)(void *, const char *), void *cb_arg) 21241aef0e11Sjg { 21251aef0e11Sjg struct stat stbuf; 21261aef0e11Sjg int rv; 21271aef0e11Sjg int terminate = 0; 21281aef0e11Sjg 21291aef0e11Sjg rv = devfs_walk_device_minors(device_path, 21301aef0e11Sjg &stbuf, callback, cb_arg, &terminate); 21311aef0e11Sjg if (rv == 0 && terminate == 0) { 21321aef0e11Sjg rv = devfs_walk_children_minors(device_path, 21331aef0e11Sjg &stbuf, callback, cb_arg, &terminate); 21341aef0e11Sjg } 21351aef0e11Sjg return (rv); 21361aef0e11Sjg } 21371aef0e11Sjg 21387c478bd9Sstevel@tonic-gate #ifdef DEBUG 21397c478bd9Sstevel@tonic-gate 21407c478bd9Sstevel@tonic-gate static void 21417c478bd9Sstevel@tonic-gate vlog_debug_msg(char *fmt, va_list ap) 21427c478bd9Sstevel@tonic-gate { 21437c478bd9Sstevel@tonic-gate time_t clock; 21447c478bd9Sstevel@tonic-gate struct tm t; 21457c478bd9Sstevel@tonic-gate 21467c478bd9Sstevel@tonic-gate if (!devfsmap_debug) 21477c478bd9Sstevel@tonic-gate return; 21487c478bd9Sstevel@tonic-gate 21497c478bd9Sstevel@tonic-gate if (logfp == NULL) { 21507c478bd9Sstevel@tonic-gate if (*devfsmap_logfile != '\0') { 21517c478bd9Sstevel@tonic-gate logfp = fopen(devfsmap_logfile, "a"); 21527c478bd9Sstevel@tonic-gate if (logfp) 21537c478bd9Sstevel@tonic-gate (void) fprintf(logfp, "\nNew Log:\n"); 21547c478bd9Sstevel@tonic-gate } 21557c478bd9Sstevel@tonic-gate 21567c478bd9Sstevel@tonic-gate if (logfp == NULL) 21577c478bd9Sstevel@tonic-gate logfp = stdout; 21587c478bd9Sstevel@tonic-gate } 21597c478bd9Sstevel@tonic-gate 21607c478bd9Sstevel@tonic-gate clock = time(NULL); 21617c478bd9Sstevel@tonic-gate (void) localtime_r(&clock, &t); 21627c478bd9Sstevel@tonic-gate (void) fprintf(logfp, "%02d:%02d:%02d ", t.tm_hour, t.tm_min, 21637c478bd9Sstevel@tonic-gate t.tm_sec); 21647c478bd9Sstevel@tonic-gate (void) vfprintf(logfp, fmt, ap); 21657c478bd9Sstevel@tonic-gate (void) fflush(logfp); 21667c478bd9Sstevel@tonic-gate } 21677c478bd9Sstevel@tonic-gate 21687c478bd9Sstevel@tonic-gate static void 21697c478bd9Sstevel@tonic-gate log_debug_msg(char *fmt, ...) 21707c478bd9Sstevel@tonic-gate { 21717c478bd9Sstevel@tonic-gate va_list ap; 21727c478bd9Sstevel@tonic-gate 21737c478bd9Sstevel@tonic-gate va_start(ap, fmt); 21747c478bd9Sstevel@tonic-gate vlog_debug_msg(fmt, ap); 21757c478bd9Sstevel@tonic-gate va_end(ap); 21767c478bd9Sstevel@tonic-gate } 21777c478bd9Sstevel@tonic-gate 21787c478bd9Sstevel@tonic-gate #ifdef __sparc 21797c478bd9Sstevel@tonic-gate 21807c478bd9Sstevel@tonic-gate static char * 21817c478bd9Sstevel@tonic-gate mpxio_disable_string(int mpxio_disable) 21827c478bd9Sstevel@tonic-gate { 21837c478bd9Sstevel@tonic-gate if (mpxio_disable == 0) 21847c478bd9Sstevel@tonic-gate return ("no"); 21857c478bd9Sstevel@tonic-gate else if (mpxio_disable == 1) 21867c478bd9Sstevel@tonic-gate return ("yes"); 21877c478bd9Sstevel@tonic-gate else 21887c478bd9Sstevel@tonic-gate return ("not specified"); 21897c478bd9Sstevel@tonic-gate } 21907c478bd9Sstevel@tonic-gate 21917c478bd9Sstevel@tonic-gate static void 21927c478bd9Sstevel@tonic-gate log_confent_list(char *filename, struct conf_entry *confent_list, 21937c478bd9Sstevel@tonic-gate int global_mpxio_disable) 21947c478bd9Sstevel@tonic-gate { 21957c478bd9Sstevel@tonic-gate struct conf_entry *confent; 21967c478bd9Sstevel@tonic-gate 21977c478bd9Sstevel@tonic-gate log_debug_msg("log_confent_list: filename = %s:\n", filename); 21987c478bd9Sstevel@tonic-gate if (global_mpxio_disable != -1) 21997c478bd9Sstevel@tonic-gate log_debug_msg("\tdriver global mpxio_disable = \"%s\"\n\n", 22007c478bd9Sstevel@tonic-gate mpxio_disable_string(global_mpxio_disable)); 22017c478bd9Sstevel@tonic-gate 22027c478bd9Sstevel@tonic-gate for (confent = confent_list; confent != NULL; confent = confent->next) { 22037c478bd9Sstevel@tonic-gate if (confent->name) 22047c478bd9Sstevel@tonic-gate log_debug_msg("\tname = %s\n", confent->name); 22057c478bd9Sstevel@tonic-gate if (confent->parent) 22067c478bd9Sstevel@tonic-gate log_debug_msg("\tparent = %s\n", confent->parent); 22077c478bd9Sstevel@tonic-gate if (confent->class) 22087c478bd9Sstevel@tonic-gate log_debug_msg("\tclass = %s\n", confent->class); 22097c478bd9Sstevel@tonic-gate if (confent->unit_address) 22107c478bd9Sstevel@tonic-gate log_debug_msg("\tunit_address = %s\n", 22117c478bd9Sstevel@tonic-gate confent->unit_address); 22127c478bd9Sstevel@tonic-gate if (confent->port != -1) 22137c478bd9Sstevel@tonic-gate log_debug_msg("\tport = %d\n", confent->port); 22147c478bd9Sstevel@tonic-gate log_debug_msg("\tmpxio_disable = \"%s\"\n\n", 22157c478bd9Sstevel@tonic-gate mpxio_disable_string(confent->mpxio_disable)); 22167c478bd9Sstevel@tonic-gate } 22177c478bd9Sstevel@tonic-gate } 22187c478bd9Sstevel@tonic-gate 22197c478bd9Sstevel@tonic-gate static void 22207c478bd9Sstevel@tonic-gate log_pathlist(char **pathlist) 22217c478bd9Sstevel@tonic-gate { 22227c478bd9Sstevel@tonic-gate char **p; 22237c478bd9Sstevel@tonic-gate 22247c478bd9Sstevel@tonic-gate for (p = pathlist; *p != NULL; p++) 22257c478bd9Sstevel@tonic-gate log_debug_msg("\t%s\n", *p); 22267c478bd9Sstevel@tonic-gate } 22277c478bd9Sstevel@tonic-gate 22287c478bd9Sstevel@tonic-gate #endif /* __sparc */ 22297c478bd9Sstevel@tonic-gate 22307c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 2231