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
find_eol(FILE * fp)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
file_err(struct conf_file * filep,char * fmt,...)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
lex(struct conf_file * filep,char * val,size_t size)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
free_confent(struct conf_entry * confent)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
free_confent_list(struct conf_entry * confent_list)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 *
parse_conf_entry(struct conf_file * filep,char * tokbuf,size_t linesize)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
parse_conf_file(char * fname,struct conf_entry ** confent_list,int * mpxio_disable)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 *
get_driver_class(char * rootdir,char * driver_name)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
lookup_in_confent_list(struct conf_entry * confent_list,int match_class,char * parent,char * unit_addr,int port)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
lookup_in_conf_file(char * rootdir,char * conf_file,char * path)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
client_name_type(char * client_name)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
compare_controller(char * rootdir,char * dev1,char * dev2)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
is_root_controller(char * rootdir,char * path)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
file_exists(char * rootdir,char * path)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
is_mpxio_disabled(char * rootdir,char * path)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
vhci_ctl(sv_iocdata_t * iocp,int cmd)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 *
phci_to_vhci(char * phci_name)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
add_to_phci_list(char ** phci_list,sv_path_info_t * pi,int npaths,int state,char * node_name)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
free_pathlist(char ** pathlist)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 **
vhci_to_phci(char * vhci_name,int * num_paths)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
build_pathlist(char * rootdir,char * vhcipath,char ** pathlist,int npaths)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
is_dev_in_vfstab(char * rootdir,char * nodepath)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
devlink_callback(di_devlink_t devlink,void * argp)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
get_install_devlink(char * physpath,char * buf,size_t bufsz)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
get_target_devlink(char * rootdir,char * physpath,char * buf,size_t bufsz)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
devname2physpath(char * rootdir,char * devname,char * physpath,int physpathlen)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
devfs_target2install(const char * rootdir,const char * devname,char * buf,size_t bufsz)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
devfs_install2target(const char * rootdir,const char * devname,char * buf,size_t bufsz)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
devfs_parse_binding_file(const char * binding_file,int (* callback)(void *,const char *,int,const char *),void * cb_arg)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
devfs_walk_children_minors(const char * device_path,struct stat * st,int (* callback)(void *,const char *),void * cb_arg,int * terminate)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
devfs_walk_device_minors(const char * device_path,struct stat * st,int (* callback)(void *,const char *),void * cb_arg,int * terminate)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
devfs_walk_minor_nodes(const char * device_path,int (* callback)(void *,const char *),void * cb_arg)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
vlog_debug_msg(char * fmt,va_list ap)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
log_debug_msg(char * fmt,...)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 *
mpxio_disable_string(int mpxio_disable)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
log_confent_list(char * filename,struct conf_entry * confent_list,int global_mpxio_disable)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
log_pathlist(char ** pathlist)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