17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*4e78ab0bScth * Common Development and Distribution License (the "License"). 6*4e78ab0bScth * 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*4e78ab0bScth * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <sys/stat.h> 297c478bd9Sstevel@tonic-gate #include <sys/types.h> 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate /* 327c478bd9Sstevel@tonic-gate * Dependent on types.h, but not including it... 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate #include <stdio.h> 357c478bd9Sstevel@tonic-gate #include <sys/types.h> 367c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 377c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h> 387c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 397c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 407c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 417c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 427c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 437c478bd9Sstevel@tonic-gate #include <nfs/nfs.h> 447c478bd9Sstevel@tonic-gate #include <nfs/nfs_clnt.h> 457c478bd9Sstevel@tonic-gate #include <kstat.h> 467c478bd9Sstevel@tonic-gate #include <ctype.h> 477c478bd9Sstevel@tonic-gate #include <dirent.h> 487c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 497c478bd9Sstevel@tonic-gate #include <limits.h> 507c478bd9Sstevel@tonic-gate #include <stdlib.h> 517c478bd9Sstevel@tonic-gate #include <string.h> 527c478bd9Sstevel@tonic-gate #include <unistd.h> 537c478bd9Sstevel@tonic-gate #include <errno.h> 547c478bd9Sstevel@tonic-gate #include <devid.h> 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate #include "dsr.h" 577c478bd9Sstevel@tonic-gate #include "statcommon.h" 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate static void rummage_dev(ldinfo_t *); 607c478bd9Sstevel@tonic-gate static void do_snm(char *, char *); 617c478bd9Sstevel@tonic-gate static int look_up_name(const char *, disk_list_t *); 627c478bd9Sstevel@tonic-gate static disk_list_t *make_an_entry(char *, char *, 637c478bd9Sstevel@tonic-gate char *, dir_info_t *, int, ldinfo_t *); 647c478bd9Sstevel@tonic-gate static char *trim(char *, char *, int); 657c478bd9Sstevel@tonic-gate static ldinfo_t *rummage_devinfo(void); 667c478bd9Sstevel@tonic-gate static void pline(char *, int, char *, char *, ldinfo_t **); 677c478bd9Sstevel@tonic-gate static void insert_dlist_ent(disk_list_t *, disk_list_t **); 687c478bd9Sstevel@tonic-gate static int str_is_digit(char *); 697c478bd9Sstevel@tonic-gate static ldinfo_t *find_ldinfo_match(char *, ldinfo_t *); 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate static void insert_into_dlist(dir_info_t *, disk_list_t *); 727c478bd9Sstevel@tonic-gate static void cleanup_dlist(dir_info_t *); 737c478bd9Sstevel@tonic-gate static void cleanup_ldinfo(ldinfo_t *); 747c478bd9Sstevel@tonic-gate static int devinfo_ident_disks(di_node_t, void *); 757c478bd9Sstevel@tonic-gate static int devinfo_ident_tapes(di_node_t, void *); 767c478bd9Sstevel@tonic-gate static void process_dir_ent(char *dent, int curr_type, 777c478bd9Sstevel@tonic-gate char *last_snm, dir_info_t *, ldinfo_t *); 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate static char *get_nfs_by_minor(uint_t); 807c478bd9Sstevel@tonic-gate static char *cur_hostname(uint_t, kstat_ctl_t *); 817c478bd9Sstevel@tonic-gate static char *cur_special(char *, char *); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate extern kstat_ctl_t *kc; 847c478bd9Sstevel@tonic-gate extern mnt_t *nfs; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate /* 877c478bd9Sstevel@tonic-gate * To do: add VXVM support: /dev/vx/dsk and ap support: /dev/ap/ 887c478bd9Sstevel@tonic-gate * 897c478bd9Sstevel@tonic-gate * Note: Adding support for VxVM is *not* as simple as adding another 907c478bd9Sstevel@tonic-gate * entry in the table and magically getting to see stuff related to 917c478bd9Sstevel@tonic-gate * VxVM. The structure is radically different *AND* they don't produce 927c478bd9Sstevel@tonic-gate * any IO kstats. 937c478bd9Sstevel@tonic-gate */ 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate #define OSA_DISK 0 967c478bd9Sstevel@tonic-gate #define DISK 1 977c478bd9Sstevel@tonic-gate #define MD_DISK 2 987c478bd9Sstevel@tonic-gate #define TAPE 3 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate #define MAX_TYPES 4 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate #define OSA_DISK_PATH "/dev/osa/dev/dsk" 1037c478bd9Sstevel@tonic-gate #define MD_DISK_PATH "/dev/md/dsk" 1047c478bd9Sstevel@tonic-gate #define DISK_PATH "/dev/dsk" 1057c478bd9Sstevel@tonic-gate #define TAPE_PATH "/dev/rmt" 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate #define BASE_TRIM "../../devices" 1087c478bd9Sstevel@tonic-gate #define MD_TRIM "../../../devices" 1097c478bd9Sstevel@tonic-gate #define COLON ':' 1107c478bd9Sstevel@tonic-gate #define COMMA ',' 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate #define NAME_BUFLEN 256 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate static dir_info_t dlist[MAX_TYPES] = { 1157c478bd9Sstevel@tonic-gate OSA_DISK_PATH, 0, 0, 0, 0, "sd", BASE_TRIM, COLON, 1167c478bd9Sstevel@tonic-gate DISK_PATH, 0, 0, 0, 0, "sd", BASE_TRIM, COLON, 1177c478bd9Sstevel@tonic-gate MD_DISK_PATH, 0, 0, 0, 1, "md", MD_TRIM, COMMA, 1187c478bd9Sstevel@tonic-gate TAPE_PATH, 0, 0, 0, 0, "st", BASE_TRIM, COLON, 1197c478bd9Sstevel@tonic-gate }; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate /* 1227c478bd9Sstevel@tonic-gate * Build a list of disks attached to the system. 1237c478bd9Sstevel@tonic-gate */ 1247c478bd9Sstevel@tonic-gate static void 1257c478bd9Sstevel@tonic-gate build_disk_list(void) 1267c478bd9Sstevel@tonic-gate { 1277c478bd9Sstevel@tonic-gate ldinfo_t *ptoi; 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate /* 1307c478bd9Sstevel@tonic-gate * Build the list of devices connected to the system. 1317c478bd9Sstevel@tonic-gate */ 1327c478bd9Sstevel@tonic-gate ptoi = rummage_devinfo(); 1337c478bd9Sstevel@tonic-gate rummage_dev(ptoi); 1347c478bd9Sstevel@tonic-gate cleanup_ldinfo(ptoi); 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate /* 1387c478bd9Sstevel@tonic-gate * Walk the /dev/dsk and /dev/rmt directories building a 1397c478bd9Sstevel@tonic-gate * list of interesting devices. Interesting is everything in the 1407c478bd9Sstevel@tonic-gate * /dev/dsk directory. We skip some of the stuff in the /dev/rmt 1417c478bd9Sstevel@tonic-gate * directory. 1427c478bd9Sstevel@tonic-gate * 1437c478bd9Sstevel@tonic-gate * Note that not finding one or more of the directories is not an 1447c478bd9Sstevel@tonic-gate * error. 1457c478bd9Sstevel@tonic-gate */ 1467c478bd9Sstevel@tonic-gate static void 1477c478bd9Sstevel@tonic-gate rummage_dev(ldinfo_t *ptoi) 1487c478bd9Sstevel@tonic-gate { 1497c478bd9Sstevel@tonic-gate DIR *dskp; 1507c478bd9Sstevel@tonic-gate int i; 1517c478bd9Sstevel@tonic-gate struct stat buf; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_TYPES; i++) { 1547c478bd9Sstevel@tonic-gate if (stat(dlist[i].name, &buf) == 0) { 1557c478bd9Sstevel@tonic-gate if (dlist[i].mtime != buf.st_mtime) { 1567c478bd9Sstevel@tonic-gate /* 1577c478bd9Sstevel@tonic-gate * We've found a change. We need to cleanup 1587c478bd9Sstevel@tonic-gate * old information and then rebuild the list 1597c478bd9Sstevel@tonic-gate * for this device type. 1607c478bd9Sstevel@tonic-gate */ 1617c478bd9Sstevel@tonic-gate cleanup_dlist(&dlist[i]); 1627c478bd9Sstevel@tonic-gate dlist[i].mtime = buf.st_mtime; 1637c478bd9Sstevel@tonic-gate if ((dskp = opendir(dlist[i].name))) { 1647c478bd9Sstevel@tonic-gate struct dirent *bpt; 1657c478bd9Sstevel@tonic-gate char last_snm[NAME_BUFLEN]; 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate last_snm[0] = NULL; 1687c478bd9Sstevel@tonic-gate while ((bpt = readdir(dskp)) != NULL) { 1697c478bd9Sstevel@tonic-gate if (bpt->d_name[0] != '.') { 1707c478bd9Sstevel@tonic-gate process_dir_ent( 1717c478bd9Sstevel@tonic-gate bpt->d_name, 1727c478bd9Sstevel@tonic-gate i, last_snm, 1737c478bd9Sstevel@tonic-gate &dlist[i], 1747c478bd9Sstevel@tonic-gate ptoi); 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate (void) closedir(dskp); 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate /* 1857c478bd9Sstevel@tonic-gate * Walk the list of located devices and see if we've 1867c478bd9Sstevel@tonic-gate * seen this device before. We look at the short name. 1877c478bd9Sstevel@tonic-gate */ 1887c478bd9Sstevel@tonic-gate static int 1897c478bd9Sstevel@tonic-gate look_up_name(const char *nm, disk_list_t *list) 1907c478bd9Sstevel@tonic-gate { 1917c478bd9Sstevel@tonic-gate while (list) { 1927c478bd9Sstevel@tonic-gate if (strcmp(list->dsk, nm) != 0) 1937c478bd9Sstevel@tonic-gate list = list->next; 1947c478bd9Sstevel@tonic-gate else { 1957c478bd9Sstevel@tonic-gate return (1); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate return (0); 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate /* 2027c478bd9Sstevel@tonic-gate * Take a name of the form cNtNdNsN or cNtNdNpN 2037c478bd9Sstevel@tonic-gate * or /dev/dsk/CNtNdNsN or /dev/dsk/cNtNdNpN 2047c478bd9Sstevel@tonic-gate * remove the trailing sN or pN. Simply looking 2057c478bd9Sstevel@tonic-gate * for the first 's' or 'p' doesn't cut it. 2067c478bd9Sstevel@tonic-gate */ 2077c478bd9Sstevel@tonic-gate static void 2087c478bd9Sstevel@tonic-gate do_snm(char *orig, char *shortnm) 2097c478bd9Sstevel@tonic-gate { 2107c478bd9Sstevel@tonic-gate char *tmp; 2117c478bd9Sstevel@tonic-gate char *ptmp; 2127c478bd9Sstevel@tonic-gate int done = 0; 2137c478bd9Sstevel@tonic-gate char repl_char = 0; 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate tmp = strrchr(orig, 's'); 2167c478bd9Sstevel@tonic-gate if (tmp) { 2177c478bd9Sstevel@tonic-gate ptmp = tmp; 2187c478bd9Sstevel@tonic-gate ptmp++; 2197c478bd9Sstevel@tonic-gate done = str_is_digit(ptmp); 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate if (done == 0) { 2227c478bd9Sstevel@tonic-gate /* 2237c478bd9Sstevel@tonic-gate * The string either has no 's' in it 2247c478bd9Sstevel@tonic-gate * or the stuff trailing the s has a 2257c478bd9Sstevel@tonic-gate * non-numeric in it. Look to see if 2267c478bd9Sstevel@tonic-gate * we have an ending 'p' followed by 2277c478bd9Sstevel@tonic-gate * numerics. 2287c478bd9Sstevel@tonic-gate */ 2297c478bd9Sstevel@tonic-gate tmp = strrchr(orig, 'p'); 2307c478bd9Sstevel@tonic-gate if (tmp) { 2317c478bd9Sstevel@tonic-gate ptmp = tmp; 2327c478bd9Sstevel@tonic-gate ptmp++; 2337c478bd9Sstevel@tonic-gate if (str_is_digit(ptmp)) 2347c478bd9Sstevel@tonic-gate repl_char = 'p'; 2357c478bd9Sstevel@tonic-gate else 2367c478bd9Sstevel@tonic-gate tmp = 0; 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate } else { 2397c478bd9Sstevel@tonic-gate repl_char = 's'; 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate if (tmp) 2427c478bd9Sstevel@tonic-gate *tmp = '\0'; 2437c478bd9Sstevel@tonic-gate (void) strcpy(shortnm, orig); 2447c478bd9Sstevel@tonic-gate if (repl_char) 2457c478bd9Sstevel@tonic-gate *tmp = repl_char; 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * Create and insert an entry into the device list. 2507c478bd9Sstevel@tonic-gate */ 2517c478bd9Sstevel@tonic-gate static disk_list_t * 2527c478bd9Sstevel@tonic-gate make_an_entry(char *lname, char *shortnm, char *longnm, 2537c478bd9Sstevel@tonic-gate dir_info_t *drent, int devtype, ldinfo_t *ptoi) 2547c478bd9Sstevel@tonic-gate { 2557c478bd9Sstevel@tonic-gate disk_list_t *entry; 2567c478bd9Sstevel@tonic-gate char *nlnm; 2577c478bd9Sstevel@tonic-gate char snm[NAME_BUFLEN]; 2587c478bd9Sstevel@tonic-gate ldinfo_t *p; 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate entry = safe_alloc(sizeof (disk_list_t)); 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate nlnm = trim(lname, drent->trimstr, drent->trimchr); 2637c478bd9Sstevel@tonic-gate entry->dsk = safe_strdup(shortnm); 2647c478bd9Sstevel@tonic-gate do_snm(longnm, snm); 2657c478bd9Sstevel@tonic-gate entry->dname = safe_strdup(snm); 2667c478bd9Sstevel@tonic-gate entry->devtype = devtype; 2677c478bd9Sstevel@tonic-gate entry->devidstr = NULL; 2687c478bd9Sstevel@tonic-gate if ((p = find_ldinfo_match(nlnm, ptoi))) { 2697c478bd9Sstevel@tonic-gate entry->dnum = p->dnum; 2707c478bd9Sstevel@tonic-gate entry->dtype = safe_strdup(p->dtype); 2717c478bd9Sstevel@tonic-gate if (p->devidstr) 2727c478bd9Sstevel@tonic-gate entry->devidstr = safe_strdup(p->devidstr); 2737c478bd9Sstevel@tonic-gate } else { 2747c478bd9Sstevel@tonic-gate entry->dtype = safe_strdup(drent->dtype); 2757c478bd9Sstevel@tonic-gate entry->dnum = -1; 2767c478bd9Sstevel@tonic-gate if (drent->dtype) { 2777c478bd9Sstevel@tonic-gate if (strcmp(drent->dtype, "md") == 0) { 2787c478bd9Sstevel@tonic-gate (void) sscanf(shortnm, "d%d", &entry->dnum); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate entry->seen = 0; 2837c478bd9Sstevel@tonic-gate entry->next = 0; 2847c478bd9Sstevel@tonic-gate insert_dlist_ent(entry, &drent->list); 2857c478bd9Sstevel@tonic-gate return (entry); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate /* 2897c478bd9Sstevel@tonic-gate * slice stuff off beginning and end of /devices directory names derived from 2907c478bd9Sstevel@tonic-gate * device links. 2917c478bd9Sstevel@tonic-gate */ 2927c478bd9Sstevel@tonic-gate static char * 2937c478bd9Sstevel@tonic-gate trim(char *fnm, char *lname, int rchr) 2947c478bd9Sstevel@tonic-gate { 2957c478bd9Sstevel@tonic-gate char *ptr; 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate while (*lname == *fnm) { 2987c478bd9Sstevel@tonic-gate lname++; 2997c478bd9Sstevel@tonic-gate fnm++; 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate if ((ptr = strrchr(fnm, rchr))) 3027c478bd9Sstevel@tonic-gate *ptr = NULL; 3037c478bd9Sstevel@tonic-gate return (fnm); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate /* 3077c478bd9Sstevel@tonic-gate * Find an entry matching the name passed in 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate static ldinfo_t * 3107c478bd9Sstevel@tonic-gate find_ldinfo_match(char *name, ldinfo_t *ptoi) 3117c478bd9Sstevel@tonic-gate { 3127c478bd9Sstevel@tonic-gate if (name) { 3137c478bd9Sstevel@tonic-gate while (ptoi) { 3147c478bd9Sstevel@tonic-gate if (strcmp(ptoi->name, name)) 3157c478bd9Sstevel@tonic-gate ptoi = ptoi->next; 3167c478bd9Sstevel@tonic-gate else 3177c478bd9Sstevel@tonic-gate return (ptoi); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate return (NULL); 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate /* 3247c478bd9Sstevel@tonic-gate * Determine if a name is already in the list of disks. If not, insert the 3257c478bd9Sstevel@tonic-gate * name in the list. 3267c478bd9Sstevel@tonic-gate */ 3277c478bd9Sstevel@tonic-gate static void 3287c478bd9Sstevel@tonic-gate insert_dlist_ent(disk_list_t *n, disk_list_t **hd) 3297c478bd9Sstevel@tonic-gate { 3307c478bd9Sstevel@tonic-gate disk_list_t *tmp_ptr; 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate if (n->dtype != NULL) { 3337c478bd9Sstevel@tonic-gate tmp_ptr = *hd; 3347c478bd9Sstevel@tonic-gate while (tmp_ptr) { 3357c478bd9Sstevel@tonic-gate if (strcmp(n->dsk, tmp_ptr->dsk) != 0) 3367c478bd9Sstevel@tonic-gate tmp_ptr = tmp_ptr->next; 3377c478bd9Sstevel@tonic-gate else 3387c478bd9Sstevel@tonic-gate break; 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate if (tmp_ptr == NULL) { 3417c478bd9Sstevel@tonic-gate /* 3427c478bd9Sstevel@tonic-gate * We don't do anything with MD_DISK types here 3437c478bd9Sstevel@tonic-gate * since they don't have partitions. 3447c478bd9Sstevel@tonic-gate */ 3457c478bd9Sstevel@tonic-gate if (n->devtype == DISK || n->devtype == OSA_DISK) { 3467c478bd9Sstevel@tonic-gate n->flags = SLICES_OK; 347c2e7b48dSkalai #if defined(__i386) 3487c478bd9Sstevel@tonic-gate n->flags |= PARTITIONS_OK; 3497c478bd9Sstevel@tonic-gate #endif 3507c478bd9Sstevel@tonic-gate } else { 3517c478bd9Sstevel@tonic-gate n->flags = 0; 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate /* 3547c478bd9Sstevel@tonic-gate * Figure out where to insert the name. The list is 3557c478bd9Sstevel@tonic-gate * ostensibly in sorted order. 3567c478bd9Sstevel@tonic-gate */ 3577c478bd9Sstevel@tonic-gate if (*hd) { 3587c478bd9Sstevel@tonic-gate disk_list_t *follw; 3597c478bd9Sstevel@tonic-gate int mv; 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate tmp_ptr = *hd; 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* 3647c478bd9Sstevel@tonic-gate * Look through the list. While the strcmp 3657c478bd9Sstevel@tonic-gate * value is less than the current value, 3667c478bd9Sstevel@tonic-gate */ 3677c478bd9Sstevel@tonic-gate while (tmp_ptr) { 3687c478bd9Sstevel@tonic-gate if ((mv = strcmp(n->dtype, 3697c478bd9Sstevel@tonic-gate tmp_ptr->dtype)) < 0) { 3707c478bd9Sstevel@tonic-gate follw = tmp_ptr; 3717c478bd9Sstevel@tonic-gate tmp_ptr = tmp_ptr->next; 3727c478bd9Sstevel@tonic-gate } else 3737c478bd9Sstevel@tonic-gate break; 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate if (mv == 0) { 3767c478bd9Sstevel@tonic-gate /* 3777c478bd9Sstevel@tonic-gate * We're now in the area where the 3787c478bd9Sstevel@tonic-gate * leading chars of the kstat name 3797c478bd9Sstevel@tonic-gate * match. We need to insert in numeric 3807c478bd9Sstevel@tonic-gate * order after that. 3817c478bd9Sstevel@tonic-gate */ 3827c478bd9Sstevel@tonic-gate while (tmp_ptr) { 3837c478bd9Sstevel@tonic-gate if (strcmp(n->dtype, 3847c478bd9Sstevel@tonic-gate tmp_ptr->dtype) != 0) 3857c478bd9Sstevel@tonic-gate break; 3867c478bd9Sstevel@tonic-gate if (n->dnum > tmp_ptr->dnum) { 3877c478bd9Sstevel@tonic-gate follw = tmp_ptr; 3887c478bd9Sstevel@tonic-gate tmp_ptr = tmp_ptr->next; 3897c478bd9Sstevel@tonic-gate } else 3907c478bd9Sstevel@tonic-gate break; 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate /* 3947c478bd9Sstevel@tonic-gate * We should now be ready to insert an 3957c478bd9Sstevel@tonic-gate * entry... 3967c478bd9Sstevel@tonic-gate */ 3977c478bd9Sstevel@tonic-gate if (mv >= 0) { 3987c478bd9Sstevel@tonic-gate if (tmp_ptr == *hd) { 3997c478bd9Sstevel@tonic-gate n->next = tmp_ptr; 4007c478bd9Sstevel@tonic-gate *hd = n; 4017c478bd9Sstevel@tonic-gate } else { 4027c478bd9Sstevel@tonic-gate n->next = follw->next; 4037c478bd9Sstevel@tonic-gate follw->next = n; 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate } else { 4067c478bd9Sstevel@tonic-gate /* 4077c478bd9Sstevel@tonic-gate * insert at the end of the 4087c478bd9Sstevel@tonic-gate * list 4097c478bd9Sstevel@tonic-gate */ 4107c478bd9Sstevel@tonic-gate follw->next = n; 4117c478bd9Sstevel@tonic-gate n->next = 0; 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate } else { 4147c478bd9Sstevel@tonic-gate *hd = n; 4157c478bd9Sstevel@tonic-gate n->next = 0; 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* 4227c478bd9Sstevel@tonic-gate * find an entry matching the given kstat name in the list 4237c478bd9Sstevel@tonic-gate * of disks, tapes and metadevices. 4247c478bd9Sstevel@tonic-gate */ 4257c478bd9Sstevel@tonic-gate disk_list_t * 4267c478bd9Sstevel@tonic-gate lookup_ks_name(char *dev_nm) 4277c478bd9Sstevel@tonic-gate { 4287c478bd9Sstevel@tonic-gate int tried = 0; 4297c478bd9Sstevel@tonic-gate int dv; 4307c478bd9Sstevel@tonic-gate int len; 4317c478bd9Sstevel@tonic-gate char cmpbuf[PATH_MAX + 1]; 4327c478bd9Sstevel@tonic-gate struct list_of_disks *list; 4337c478bd9Sstevel@tonic-gate char *nm; 4347c478bd9Sstevel@tonic-gate dev_name_t *tmp; 4357c478bd9Sstevel@tonic-gate uint_t i; 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate /* 4387c478bd9Sstevel@tonic-gate * extract the device type from the kstat name. We expect the 4397c478bd9Sstevel@tonic-gate * name to be one or more alphabetics followed by the device 4407c478bd9Sstevel@tonic-gate * numeric id. We do this solely for speed purposes . 4417c478bd9Sstevel@tonic-gate */ 4427c478bd9Sstevel@tonic-gate len = 0; 4437c478bd9Sstevel@tonic-gate nm = dev_nm; 4447c478bd9Sstevel@tonic-gate while (*nm) { 4457c478bd9Sstevel@tonic-gate if (isalpha(*nm)) { 4467c478bd9Sstevel@tonic-gate nm++; 4477c478bd9Sstevel@tonic-gate len++; 4487c478bd9Sstevel@tonic-gate } else 4497c478bd9Sstevel@tonic-gate break; 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate if (!*nm) 4537c478bd9Sstevel@tonic-gate return (NULL); 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate /* 4567c478bd9Sstevel@tonic-gate * For each of the elements in the dlist array we keep 4577c478bd9Sstevel@tonic-gate * an array of pointers to chains for each of the kstat 4587c478bd9Sstevel@tonic-gate * prefixes found within that directory. This is typically 4597c478bd9Sstevel@tonic-gate * 'sd' and 'ssd'. We walk the list in the directory and 4607c478bd9Sstevel@tonic-gate * match on that type. Since the same prefixes can be 4617c478bd9Sstevel@tonic-gate * in multiple places we keep checking if we don't find 4627c478bd9Sstevel@tonic-gate * it in the first place. 4637c478bd9Sstevel@tonic-gate */ 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate (void) strncpy(cmpbuf, dev_nm, len); 4667c478bd9Sstevel@tonic-gate cmpbuf[len] = NULL; 4677c478bd9Sstevel@tonic-gate dv = atoi(nm); 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate retry: 4707c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_TYPES; i++) { 4717c478bd9Sstevel@tonic-gate tmp = dlist[i].nf; 4727c478bd9Sstevel@tonic-gate while (tmp) { 4737c478bd9Sstevel@tonic-gate if (strcmp(tmp->name, cmpbuf) == 0) { 4747c478bd9Sstevel@tonic-gate /* 4757c478bd9Sstevel@tonic-gate * As an optimization we keep mins 4767c478bd9Sstevel@tonic-gate * and maxes for the devices found. 4777c478bd9Sstevel@tonic-gate * This helps chop the lists up and 4787c478bd9Sstevel@tonic-gate * avoid some really long chains as 4797c478bd9Sstevel@tonic-gate * we would get if we kept only prefix 4807c478bd9Sstevel@tonic-gate * lists. 4817c478bd9Sstevel@tonic-gate */ 4827c478bd9Sstevel@tonic-gate if (dv >= tmp->min && dv <= tmp->max) { 4837c478bd9Sstevel@tonic-gate list = tmp->list_start; 4847c478bd9Sstevel@tonic-gate while (list) { 4857c478bd9Sstevel@tonic-gate if (list->dnum < dv) 4867c478bd9Sstevel@tonic-gate list = list->next; 4877c478bd9Sstevel@tonic-gate else 4887c478bd9Sstevel@tonic-gate break; 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate if (list && list->dnum == dv) { 4917c478bd9Sstevel@tonic-gate return (list); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate tmp = tmp->next; 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate if (!tried) { 5007c478bd9Sstevel@tonic-gate tried = 1; 5017c478bd9Sstevel@tonic-gate build_disk_list(); 5027c478bd9Sstevel@tonic-gate goto retry; 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate return (0); 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate static int 5097c478bd9Sstevel@tonic-gate str_is_digit(char *str) 5107c478bd9Sstevel@tonic-gate { 5117c478bd9Sstevel@tonic-gate while (*str) { 5127c478bd9Sstevel@tonic-gate if (isdigit(*str)) 5137c478bd9Sstevel@tonic-gate str++; 5147c478bd9Sstevel@tonic-gate else 5157c478bd9Sstevel@tonic-gate return (0); 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate return (1); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate static void 5217c478bd9Sstevel@tonic-gate insert_into_dlist(dir_info_t *d, disk_list_t *e) 5227c478bd9Sstevel@tonic-gate { 5237c478bd9Sstevel@tonic-gate dev_name_t *tmp; 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate tmp = d->nf; 5267c478bd9Sstevel@tonic-gate while (tmp) { 5277c478bd9Sstevel@tonic-gate if (strcmp(e->dtype, tmp->name) != 0) { 5287c478bd9Sstevel@tonic-gate tmp = tmp->next; 5297c478bd9Sstevel@tonic-gate } else { 5307c478bd9Sstevel@tonic-gate if (e->dnum < tmp->min) { 5317c478bd9Sstevel@tonic-gate tmp->min = e->dnum; 5327c478bd9Sstevel@tonic-gate tmp->list_start = e; 5337c478bd9Sstevel@tonic-gate } else if (e->dnum > tmp->max) { 5347c478bd9Sstevel@tonic-gate tmp->max = e->dnum; 5357c478bd9Sstevel@tonic-gate tmp->list_end = e; 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate break; 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate if (tmp == NULL) { 5417c478bd9Sstevel@tonic-gate tmp = safe_alloc(sizeof (dev_name_t)); 5427c478bd9Sstevel@tonic-gate tmp->name = e->dtype; 5437c478bd9Sstevel@tonic-gate tmp->min = e->dnum; 5447c478bd9Sstevel@tonic-gate tmp->max = e->dnum; 5457c478bd9Sstevel@tonic-gate tmp->list_start = e; 5467c478bd9Sstevel@tonic-gate tmp->list_end = e; 5477c478bd9Sstevel@tonic-gate tmp->next = d->nf; 5487c478bd9Sstevel@tonic-gate d->nf = tmp; 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate /* 5537c478bd9Sstevel@tonic-gate * devinfo_ident_disks() and devinfo_ident_tapes() are the callback functions we 5547c478bd9Sstevel@tonic-gate * use while walking the device tree snapshot provided by devinfo. If 5557c478bd9Sstevel@tonic-gate * devinfo_ident_disks() identifies that the device being considered has one or 5567c478bd9Sstevel@tonic-gate * more minor nodes _and_ is a block device, then it is a potential disk. 5577c478bd9Sstevel@tonic-gate * Similarly for devinfo_ident_tapes(), except that the second criterion is that 5587c478bd9Sstevel@tonic-gate * the minor_node be a character device. (This is more inclusive than only 5597c478bd9Sstevel@tonic-gate * tape devices, but will match any entries in /dev/rmt/.) 5607c478bd9Sstevel@tonic-gate * 5617c478bd9Sstevel@tonic-gate * Note: if a driver was previously loaded but is now unloaded, the kstat may 5627c478bd9Sstevel@tonic-gate * still be around (e.g., st) but no information will be found in the 5637c478bd9Sstevel@tonic-gate * libdevinfo tree. 5647c478bd9Sstevel@tonic-gate */ 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate static int 5677c478bd9Sstevel@tonic-gate devinfo_ident_disks(di_node_t node, void *arg) 5687c478bd9Sstevel@tonic-gate { 5697c478bd9Sstevel@tonic-gate di_minor_t minor = DI_MINOR_NIL; 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate if ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 5727c478bd9Sstevel@tonic-gate int spectype = di_minor_spectype(minor); 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate if (S_ISBLK(spectype)) { 5757c478bd9Sstevel@tonic-gate char *physical_path = di_devfs_path(node); 5767c478bd9Sstevel@tonic-gate int instance = di_instance(node); 5777c478bd9Sstevel@tonic-gate char *driver_name = di_driver_name(node); 5787c478bd9Sstevel@tonic-gate char *devidstr; 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate /* lookup the devid, devt specific first */ 5817c478bd9Sstevel@tonic-gate if ((di_prop_lookup_strings(di_minor_devt(minor), node, 5827c478bd9Sstevel@tonic-gate DEVID_PROP_NAME, &devidstr) == -1) && 5837c478bd9Sstevel@tonic-gate (di_prop_lookup_strings(DDI_DEV_T_ANY, node, 5847c478bd9Sstevel@tonic-gate DEVID_PROP_NAME, &devidstr) == -1)) 5857c478bd9Sstevel@tonic-gate devidstr = NULL; 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate if (driver_name == NULL) 5887c478bd9Sstevel@tonic-gate driver_name = "<nil>"; 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate pline(physical_path, instance, 5917c478bd9Sstevel@tonic-gate driver_name, devidstr, arg); 5927c478bd9Sstevel@tonic-gate di_devfs_path_free(physical_path); 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate static int 5997c478bd9Sstevel@tonic-gate devinfo_ident_tapes(di_node_t node, void *arg) 6007c478bd9Sstevel@tonic-gate { 6017c478bd9Sstevel@tonic-gate di_minor_t minor = DI_MINOR_NIL; 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate if ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 6047c478bd9Sstevel@tonic-gate int spectype = di_minor_spectype(minor); 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate if (S_ISCHR(spectype)) { 6077c478bd9Sstevel@tonic-gate char *physical_path = di_devfs_path(node); 6087c478bd9Sstevel@tonic-gate int instance = di_instance(node); 6097c478bd9Sstevel@tonic-gate char *binding_name = di_binding_name(node); 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate pline(physical_path, instance, 6127c478bd9Sstevel@tonic-gate binding_name, NULL, arg); 6137c478bd9Sstevel@tonic-gate di_devfs_path_free(physical_path); 6147c478bd9Sstevel@tonic-gate } 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate /* 6207c478bd9Sstevel@tonic-gate * rummage_devinfo() is the driver routine that walks the devinfo snapshot. 6217c478bd9Sstevel@tonic-gate */ 6227c478bd9Sstevel@tonic-gate static ldinfo_t * 6237c478bd9Sstevel@tonic-gate rummage_devinfo(void) 6247c478bd9Sstevel@tonic-gate { 6257c478bd9Sstevel@tonic-gate di_node_t root_node; 6267c478bd9Sstevel@tonic-gate ldinfo_t *rv = NULL; 6277c478bd9Sstevel@tonic-gate 628*4e78ab0bScth if ((root_node = di_init("/", DINFOCACHE)) != DI_NODE_NIL) { 6297c478bd9Sstevel@tonic-gate (void) di_walk_node(root_node, DI_WALK_CLDFIRST, (void *)&rv, 6307c478bd9Sstevel@tonic-gate devinfo_ident_disks); 6317c478bd9Sstevel@tonic-gate (void) di_walk_node(root_node, DI_WALK_CLDFIRST, (void *)&rv, 6327c478bd9Sstevel@tonic-gate devinfo_ident_tapes); 6337c478bd9Sstevel@tonic-gate di_fini(root_node); 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate return (rv); 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate /* 6397c478bd9Sstevel@tonic-gate * pline() performs the lookup of the device path in the current list of disks, 6407c478bd9Sstevel@tonic-gate * and adds the appropriate information to the nms list in the case of a match. 6417c478bd9Sstevel@tonic-gate */ 6427c478bd9Sstevel@tonic-gate static void 6437c478bd9Sstevel@tonic-gate pline(char *devfs_path, int instance, 6447c478bd9Sstevel@tonic-gate char *driver_name, char *devidstr, ldinfo_t **list) 6457c478bd9Sstevel@tonic-gate { 6467c478bd9Sstevel@tonic-gate ldinfo_t *entry; 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate entry = safe_alloc(sizeof (ldinfo_t)); 6497c478bd9Sstevel@tonic-gate entry->dnum = instance; 6507c478bd9Sstevel@tonic-gate entry->name = safe_strdup(devfs_path); 6517c478bd9Sstevel@tonic-gate entry->dtype = safe_strdup(driver_name); 6527c478bd9Sstevel@tonic-gate entry->devidstr = safe_strdup(devidstr); 6537c478bd9Sstevel@tonic-gate entry->next = *list; 6547c478bd9Sstevel@tonic-gate *list = entry; 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate /* 6587c478bd9Sstevel@tonic-gate * Cleanup space allocated in dlist processing. 6597c478bd9Sstevel@tonic-gate * We're only interested in cleaning up the list and nf 6607c478bd9Sstevel@tonic-gate * fields in the structure. Everything else is static 6617c478bd9Sstevel@tonic-gate * data. 6627c478bd9Sstevel@tonic-gate */ 6637c478bd9Sstevel@tonic-gate static void 6647c478bd9Sstevel@tonic-gate cleanup_dlist(dir_info_t *d) 6657c478bd9Sstevel@tonic-gate { 6667c478bd9Sstevel@tonic-gate dev_name_t *tmp; 6677c478bd9Sstevel@tonic-gate dev_name_t *t1; 6687c478bd9Sstevel@tonic-gate disk_list_t *t2; 6697c478bd9Sstevel@tonic-gate disk_list_t *t3; 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate /* 6727c478bd9Sstevel@tonic-gate * All of the entries in a dev_name_t use information 6737c478bd9Sstevel@tonic-gate * from a disk_list_t structure that is freed later. 6747c478bd9Sstevel@tonic-gate * All we need do here is free the dev_name_t 6757c478bd9Sstevel@tonic-gate * structure itself. 6767c478bd9Sstevel@tonic-gate */ 6777c478bd9Sstevel@tonic-gate tmp = d->nf; 6787c478bd9Sstevel@tonic-gate while (tmp) { 6797c478bd9Sstevel@tonic-gate t1 = tmp->next; 6807c478bd9Sstevel@tonic-gate free(tmp); 6817c478bd9Sstevel@tonic-gate tmp = t1; 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate d->nf = 0; 6847c478bd9Sstevel@tonic-gate /* 6857c478bd9Sstevel@tonic-gate * "Later". Free the disk_list_t structures and their 6867c478bd9Sstevel@tonic-gate * data attached to this portion of the dir_info 6877c478bd9Sstevel@tonic-gate * structure. 6887c478bd9Sstevel@tonic-gate */ 6897c478bd9Sstevel@tonic-gate t2 = d->list; 6907c478bd9Sstevel@tonic-gate while (t2) { 6917c478bd9Sstevel@tonic-gate if (t2->dtype) { 6927c478bd9Sstevel@tonic-gate free(t2->dtype); 6937c478bd9Sstevel@tonic-gate t2->dtype = NULL; 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate if (t2->dsk) { 6967c478bd9Sstevel@tonic-gate free(t2->dsk); 6977c478bd9Sstevel@tonic-gate t2->dsk = NULL; 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate if (t2->dname) { 7007c478bd9Sstevel@tonic-gate free(t2->dname); 7017c478bd9Sstevel@tonic-gate t2->dname = NULL; 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate t3 = t2->next; 7047c478bd9Sstevel@tonic-gate free(t2); 7057c478bd9Sstevel@tonic-gate t2 = t3; 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate d->list = 0; 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate static void 7117c478bd9Sstevel@tonic-gate process_dir_ent(char *dent, int curr_type, char *last_snm, 7127c478bd9Sstevel@tonic-gate dir_info_t *dp, ldinfo_t *ptoi) 7137c478bd9Sstevel@tonic-gate { 7147c478bd9Sstevel@tonic-gate struct stat sbuf; 7157c478bd9Sstevel@tonic-gate char dnmbuf[PATH_MAX + 1]; 7167c478bd9Sstevel@tonic-gate char lnm[NAME_BUFLEN]; 7177c478bd9Sstevel@tonic-gate char snm[NAME_BUFLEN]; 7187c478bd9Sstevel@tonic-gate char *npt; 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate snm[0] = NULL; 7217c478bd9Sstevel@tonic-gate if (curr_type == DISK || curr_type == OSA_DISK) { 7227c478bd9Sstevel@tonic-gate /* 7237c478bd9Sstevel@tonic-gate * get the short name - omitting 7247c478bd9Sstevel@tonic-gate * the trailing sN or PN 7257c478bd9Sstevel@tonic-gate */ 7267c478bd9Sstevel@tonic-gate (void) strcpy(lnm, dent); 7277c478bd9Sstevel@tonic-gate do_snm(dent, snm); 7287c478bd9Sstevel@tonic-gate } else if (curr_type == MD_DISK) { 7297c478bd9Sstevel@tonic-gate (void) strcpy(lnm, dent); 7307c478bd9Sstevel@tonic-gate (void) strcpy(snm, dent); 7317c478bd9Sstevel@tonic-gate } else { 7327c478bd9Sstevel@tonic-gate /* 7337c478bd9Sstevel@tonic-gate * don't want all rewind/etc 7347c478bd9Sstevel@tonic-gate * devices for a tape 7357c478bd9Sstevel@tonic-gate */ 7367c478bd9Sstevel@tonic-gate if (!str_is_digit(dent)) 7377c478bd9Sstevel@tonic-gate return; 7387c478bd9Sstevel@tonic-gate (void) snprintf(snm, sizeof (snm), "rmt/%s", dent); 7397c478bd9Sstevel@tonic-gate (void) snprintf(lnm, sizeof (snm), "rmt/%s", dent); 7407c478bd9Sstevel@tonic-gate } 7417c478bd9Sstevel@tonic-gate /* 7427c478bd9Sstevel@tonic-gate * See if we've already processed an entry for this device. 7437c478bd9Sstevel@tonic-gate * If so, we're just another partition so we get another 7447c478bd9Sstevel@tonic-gate * entry. 7457c478bd9Sstevel@tonic-gate * 7467c478bd9Sstevel@tonic-gate * last_snm is an optimization to avoid the function call 7477c478bd9Sstevel@tonic-gate * and lookup since we'll often see partition records 7487c478bd9Sstevel@tonic-gate * immediately after the disk record. 7497c478bd9Sstevel@tonic-gate */ 7507c478bd9Sstevel@tonic-gate if (dp->skip_lookup == 0) { 7517c478bd9Sstevel@tonic-gate if (strcmp(snm, last_snm) != 0) { 7527c478bd9Sstevel@tonic-gate /* 7537c478bd9Sstevel@tonic-gate * a zero return means that 7547c478bd9Sstevel@tonic-gate * no record was found. We'd 7557c478bd9Sstevel@tonic-gate * return a pointer otherwise. 7567c478bd9Sstevel@tonic-gate */ 7577c478bd9Sstevel@tonic-gate if (look_up_name(snm, 7587c478bd9Sstevel@tonic-gate dp->list) == 0) { 7597c478bd9Sstevel@tonic-gate (void) strcpy(last_snm, snm); 7607c478bd9Sstevel@tonic-gate } else 7617c478bd9Sstevel@tonic-gate return; 7627c478bd9Sstevel@tonic-gate } else 7637c478bd9Sstevel@tonic-gate return; 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate /* 7667c478bd9Sstevel@tonic-gate * Get the real device name for this beast 7677c478bd9Sstevel@tonic-gate * by following the link into /devices. 7687c478bd9Sstevel@tonic-gate */ 7697c478bd9Sstevel@tonic-gate (void) snprintf(dnmbuf, sizeof (dnmbuf), "%s/%s", dp->name, dent); 7707c478bd9Sstevel@tonic-gate if (lstat(dnmbuf, &sbuf) != -1) { 7717c478bd9Sstevel@tonic-gate if ((sbuf.st_mode & S_IFMT) == S_IFLNK) { 7727c478bd9Sstevel@tonic-gate /* 7737c478bd9Sstevel@tonic-gate * It's a link. Get the real name. 7747c478bd9Sstevel@tonic-gate */ 7757c478bd9Sstevel@tonic-gate char nmbuf[PATH_MAX + 1]; 7767c478bd9Sstevel@tonic-gate int nbyr; 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate if ((nbyr = readlink(dnmbuf, nmbuf, 7797c478bd9Sstevel@tonic-gate sizeof (nmbuf))) != 1) { 7807c478bd9Sstevel@tonic-gate npt = nmbuf; 7817c478bd9Sstevel@tonic-gate /* 7827c478bd9Sstevel@tonic-gate * readlink does not terminate 7837c478bd9Sstevel@tonic-gate * the string so we have to 7847c478bd9Sstevel@tonic-gate * do it. 7857c478bd9Sstevel@tonic-gate */ 7867c478bd9Sstevel@tonic-gate nmbuf[nbyr] = NULL; 7877c478bd9Sstevel@tonic-gate } else 7887c478bd9Sstevel@tonic-gate npt = NULL; 7897c478bd9Sstevel@tonic-gate } else 7907c478bd9Sstevel@tonic-gate npt = lnm; 7917c478bd9Sstevel@tonic-gate /* 7927c478bd9Sstevel@tonic-gate * make an entry in the device list 7937c478bd9Sstevel@tonic-gate */ 7947c478bd9Sstevel@tonic-gate if (npt) { 7957c478bd9Sstevel@tonic-gate disk_list_t *d; 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate d = make_an_entry(npt, snm, 7987c478bd9Sstevel@tonic-gate dnmbuf, dp, 7997c478bd9Sstevel@tonic-gate curr_type, ptoi); 8007c478bd9Sstevel@tonic-gate insert_into_dlist(dp, d); 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate static void 8057c478bd9Sstevel@tonic-gate cleanup_ldinfo(ldinfo_t *list) 8067c478bd9Sstevel@tonic-gate { 8077c478bd9Sstevel@tonic-gate ldinfo_t *tmp; 8087c478bd9Sstevel@tonic-gate while (list) { 8097c478bd9Sstevel@tonic-gate tmp = list; 8107c478bd9Sstevel@tonic-gate list = list->next; 8117c478bd9Sstevel@tonic-gate free(tmp->name); 8127c478bd9Sstevel@tonic-gate free(tmp->dtype); 8137c478bd9Sstevel@tonic-gate if (tmp->devidstr) 8147c478bd9Sstevel@tonic-gate free(tmp->devidstr); 8157c478bd9Sstevel@tonic-gate free(tmp); 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate } 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate char * 8207c478bd9Sstevel@tonic-gate lookup_nfs_name(char *ks, kstat_ctl_t *kc) 8217c478bd9Sstevel@tonic-gate { 8227c478bd9Sstevel@tonic-gate int tried = 0; 8237c478bd9Sstevel@tonic-gate uint_t minor; 8247c478bd9Sstevel@tonic-gate char *host, *path; 8257c478bd9Sstevel@tonic-gate char *cp; 8267c478bd9Sstevel@tonic-gate char *rstr = 0; 8277c478bd9Sstevel@tonic-gate size_t len; 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate if (sscanf(ks, "nfs%u", &minor) == 1) { 8307c478bd9Sstevel@tonic-gate retry: 8317c478bd9Sstevel@tonic-gate cp = get_nfs_by_minor(minor); 8327c478bd9Sstevel@tonic-gate if (cp) { 8337c478bd9Sstevel@tonic-gate if (strchr(cp, ',') == NULL) { 8347c478bd9Sstevel@tonic-gate rstr = safe_strdup(cp); 8357c478bd9Sstevel@tonic-gate return (rstr); 8367c478bd9Sstevel@tonic-gate } 8377c478bd9Sstevel@tonic-gate host = cur_hostname(minor, kc); 8387c478bd9Sstevel@tonic-gate if (host) { 8397c478bd9Sstevel@tonic-gate if (*host) { 8407c478bd9Sstevel@tonic-gate path = cur_special(host, cp); 8417c478bd9Sstevel@tonic-gate if (path) { 8427c478bd9Sstevel@tonic-gate len = strlen(host); 8437c478bd9Sstevel@tonic-gate len += strlen(path); 8447c478bd9Sstevel@tonic-gate len += 2; 8457c478bd9Sstevel@tonic-gate rstr = safe_alloc(len); 8467c478bd9Sstevel@tonic-gate (void) snprintf(rstr, len, 8477c478bd9Sstevel@tonic-gate "%s:%s", host, path); 8487c478bd9Sstevel@tonic-gate } else { 8497c478bd9Sstevel@tonic-gate rstr = safe_strdup(cp); 8507c478bd9Sstevel@tonic-gate } 8517c478bd9Sstevel@tonic-gate } else { 8527c478bd9Sstevel@tonic-gate rstr = safe_strdup(ks); 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate free(host); 8557c478bd9Sstevel@tonic-gate } else { 8567c478bd9Sstevel@tonic-gate rstr = safe_strdup(cp); 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate } else if (!tried) { 8597c478bd9Sstevel@tonic-gate tried = 1; 8607c478bd9Sstevel@tonic-gate do_mnttab(); 8617c478bd9Sstevel@tonic-gate goto retry; 8627c478bd9Sstevel@tonic-gate } 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate return (rstr); 8657c478bd9Sstevel@tonic-gate } 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate static char * 8687c478bd9Sstevel@tonic-gate get_nfs_by_minor(uint_t minor) 8697c478bd9Sstevel@tonic-gate { 8707c478bd9Sstevel@tonic-gate mnt_t *localnfs; 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate localnfs = nfs; 8737c478bd9Sstevel@tonic-gate while (localnfs) { 8747c478bd9Sstevel@tonic-gate if (localnfs->minor == minor) { 8757c478bd9Sstevel@tonic-gate return (localnfs->device_name); 8767c478bd9Sstevel@tonic-gate } 8777c478bd9Sstevel@tonic-gate localnfs = localnfs->next; 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate return (0); 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate /* 8837c478bd9Sstevel@tonic-gate * Read the cur_hostname from the mntinfo kstat 8847c478bd9Sstevel@tonic-gate */ 8857c478bd9Sstevel@tonic-gate static char * 8867c478bd9Sstevel@tonic-gate cur_hostname(uint_t minor, kstat_ctl_t *kc) 8877c478bd9Sstevel@tonic-gate { 8887c478bd9Sstevel@tonic-gate kstat_t *ksp; 8897c478bd9Sstevel@tonic-gate static struct mntinfo_kstat mik; 8907c478bd9Sstevel@tonic-gate char *rstr; 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 8937c478bd9Sstevel@tonic-gate if (ksp->ks_type != KSTAT_TYPE_RAW) 8947c478bd9Sstevel@tonic-gate continue; 8957c478bd9Sstevel@tonic-gate if (ksp->ks_instance != minor) 8967c478bd9Sstevel@tonic-gate continue; 8977c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_module, "nfs")) 8987c478bd9Sstevel@tonic-gate continue; 8997c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_name, "mntinfo")) 9007c478bd9Sstevel@tonic-gate continue; 9017c478bd9Sstevel@tonic-gate if (ksp->ks_flags & KSTAT_FLAG_INVALID) 9027c478bd9Sstevel@tonic-gate return (NULL); 9037c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, &mik) == -1) 9047c478bd9Sstevel@tonic-gate return (NULL); 9057c478bd9Sstevel@tonic-gate rstr = safe_strdup(mik.mik_curserver); 9067c478bd9Sstevel@tonic-gate return (rstr); 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate return (NULL); 9097c478bd9Sstevel@tonic-gate } 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate /* 9127c478bd9Sstevel@tonic-gate * Given the hostname of the mounted server, extract the server 9137c478bd9Sstevel@tonic-gate * mount point from the mnttab string. 9147c478bd9Sstevel@tonic-gate * 9157c478bd9Sstevel@tonic-gate * Common forms: 9167c478bd9Sstevel@tonic-gate * server1,server2,server3:/path 9177c478bd9Sstevel@tonic-gate * server1:/path,server2:/path 9187c478bd9Sstevel@tonic-gate * or a hybrid of the two 9197c478bd9Sstevel@tonic-gate */ 9207c478bd9Sstevel@tonic-gate static char * 9217c478bd9Sstevel@tonic-gate cur_special(char *hostname, char *special) 9227c478bd9Sstevel@tonic-gate { 9237c478bd9Sstevel@tonic-gate char *cp; 9247c478bd9Sstevel@tonic-gate char *path; 9257c478bd9Sstevel@tonic-gate size_t hlen = strlen(hostname); 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate /* 9287c478bd9Sstevel@tonic-gate * find hostname in string 9297c478bd9Sstevel@tonic-gate */ 9307c478bd9Sstevel@tonic-gate again: 9317c478bd9Sstevel@tonic-gate if ((cp = strstr(special, hostname)) == NULL) 9327c478bd9Sstevel@tonic-gate return (NULL); 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate /* 9357c478bd9Sstevel@tonic-gate * hostname must be followed by ',' or ':' 9367c478bd9Sstevel@tonic-gate */ 9377c478bd9Sstevel@tonic-gate if (cp[hlen] != ',' && cp[hlen] != ':') { 9387c478bd9Sstevel@tonic-gate special = &cp[hlen]; 9397c478bd9Sstevel@tonic-gate goto again; 9407c478bd9Sstevel@tonic-gate } 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate /* 9437c478bd9Sstevel@tonic-gate * If hostname is followed by a ',' eat all characters until a ':' 9447c478bd9Sstevel@tonic-gate */ 9457c478bd9Sstevel@tonic-gate cp = &cp[hlen]; 9467c478bd9Sstevel@tonic-gate if (*cp == ',') { 9477c478bd9Sstevel@tonic-gate cp++; 9487c478bd9Sstevel@tonic-gate while (*cp != ':') { 9497c478bd9Sstevel@tonic-gate if (*cp == NULL) 9507c478bd9Sstevel@tonic-gate return (NULL); 9517c478bd9Sstevel@tonic-gate cp++; 9527c478bd9Sstevel@tonic-gate } 9537c478bd9Sstevel@tonic-gate } 9547c478bd9Sstevel@tonic-gate path = ++cp; /* skip ':' */ 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate /* 9577c478bd9Sstevel@tonic-gate * path is terminated by either 0, or space or ',' 9587c478bd9Sstevel@tonic-gate */ 9597c478bd9Sstevel@tonic-gate while (*cp) { 9607c478bd9Sstevel@tonic-gate if (isspace(*cp) || *cp == ',') { 9617c478bd9Sstevel@tonic-gate *cp = NULL; 9627c478bd9Sstevel@tonic-gate return (path); 9637c478bd9Sstevel@tonic-gate } 9647c478bd9Sstevel@tonic-gate cp++; 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate return (path); 9677c478bd9Sstevel@tonic-gate } 968