1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate /* 33*7c478bd9Sstevel@tonic-gate * Dependent on types.h, but not including it... 34*7c478bd9Sstevel@tonic-gate */ 35*7c478bd9Sstevel@tonic-gate #include <stdio.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 44*7c478bd9Sstevel@tonic-gate #include <nfs/nfs.h> 45*7c478bd9Sstevel@tonic-gate #include <nfs/nfs_clnt.h> 46*7c478bd9Sstevel@tonic-gate #include <kstat.h> 47*7c478bd9Sstevel@tonic-gate #include <ctype.h> 48*7c478bd9Sstevel@tonic-gate #include <dirent.h> 49*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 50*7c478bd9Sstevel@tonic-gate #include <limits.h> 51*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 52*7c478bd9Sstevel@tonic-gate #include <string.h> 53*7c478bd9Sstevel@tonic-gate #include <unistd.h> 54*7c478bd9Sstevel@tonic-gate #include <errno.h> 55*7c478bd9Sstevel@tonic-gate #include <devid.h> 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate #include "dsr.h" 58*7c478bd9Sstevel@tonic-gate #include "statcommon.h" 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate static void rummage_dev(ldinfo_t *); 61*7c478bd9Sstevel@tonic-gate static void do_snm(char *, char *); 62*7c478bd9Sstevel@tonic-gate static int look_up_name(const char *, disk_list_t *); 63*7c478bd9Sstevel@tonic-gate static disk_list_t *make_an_entry(char *, char *, 64*7c478bd9Sstevel@tonic-gate char *, dir_info_t *, int, ldinfo_t *); 65*7c478bd9Sstevel@tonic-gate static char *trim(char *, char *, int); 66*7c478bd9Sstevel@tonic-gate static ldinfo_t *rummage_devinfo(void); 67*7c478bd9Sstevel@tonic-gate static void pline(char *, int, char *, char *, ldinfo_t **); 68*7c478bd9Sstevel@tonic-gate static void insert_dlist_ent(disk_list_t *, disk_list_t **); 69*7c478bd9Sstevel@tonic-gate static int str_is_digit(char *); 70*7c478bd9Sstevel@tonic-gate static ldinfo_t *find_ldinfo_match(char *, ldinfo_t *); 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate static void insert_into_dlist(dir_info_t *, disk_list_t *); 73*7c478bd9Sstevel@tonic-gate static void cleanup_dlist(dir_info_t *); 74*7c478bd9Sstevel@tonic-gate static void cleanup_ldinfo(ldinfo_t *); 75*7c478bd9Sstevel@tonic-gate static int devinfo_ident_disks(di_node_t, void *); 76*7c478bd9Sstevel@tonic-gate static int devinfo_ident_tapes(di_node_t, void *); 77*7c478bd9Sstevel@tonic-gate static void process_dir_ent(char *dent, int curr_type, 78*7c478bd9Sstevel@tonic-gate char *last_snm, dir_info_t *, ldinfo_t *); 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate static char *get_nfs_by_minor(uint_t); 81*7c478bd9Sstevel@tonic-gate static char *cur_hostname(uint_t, kstat_ctl_t *); 82*7c478bd9Sstevel@tonic-gate static char *cur_special(char *, char *); 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate extern kstat_ctl_t *kc; 85*7c478bd9Sstevel@tonic-gate extern mnt_t *nfs; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate /* 88*7c478bd9Sstevel@tonic-gate * To do: add VXVM support: /dev/vx/dsk and ap support: /dev/ap/ 89*7c478bd9Sstevel@tonic-gate * 90*7c478bd9Sstevel@tonic-gate * Note: Adding support for VxVM is *not* as simple as adding another 91*7c478bd9Sstevel@tonic-gate * entry in the table and magically getting to see stuff related to 92*7c478bd9Sstevel@tonic-gate * VxVM. The structure is radically different *AND* they don't produce 93*7c478bd9Sstevel@tonic-gate * any IO kstats. 94*7c478bd9Sstevel@tonic-gate */ 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate #define OSA_DISK 0 97*7c478bd9Sstevel@tonic-gate #define DISK 1 98*7c478bd9Sstevel@tonic-gate #define MD_DISK 2 99*7c478bd9Sstevel@tonic-gate #define TAPE 3 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate #define MAX_TYPES 4 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate #define OSA_DISK_PATH "/dev/osa/dev/dsk" 104*7c478bd9Sstevel@tonic-gate #define MD_DISK_PATH "/dev/md/dsk" 105*7c478bd9Sstevel@tonic-gate #define DISK_PATH "/dev/dsk" 106*7c478bd9Sstevel@tonic-gate #define TAPE_PATH "/dev/rmt" 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate #define BASE_TRIM "../../devices" 109*7c478bd9Sstevel@tonic-gate #define MD_TRIM "../../../devices" 110*7c478bd9Sstevel@tonic-gate #define COLON ':' 111*7c478bd9Sstevel@tonic-gate #define COMMA ',' 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate #define NAME_BUFLEN 256 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate static dir_info_t dlist[MAX_TYPES] = { 116*7c478bd9Sstevel@tonic-gate OSA_DISK_PATH, 0, 0, 0, 0, "sd", BASE_TRIM, COLON, 117*7c478bd9Sstevel@tonic-gate DISK_PATH, 0, 0, 0, 0, "sd", BASE_TRIM, COLON, 118*7c478bd9Sstevel@tonic-gate MD_DISK_PATH, 0, 0, 0, 1, "md", MD_TRIM, COMMA, 119*7c478bd9Sstevel@tonic-gate TAPE_PATH, 0, 0, 0, 0, "st", BASE_TRIM, COLON, 120*7c478bd9Sstevel@tonic-gate }; 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate /* 123*7c478bd9Sstevel@tonic-gate * Build a list of disks attached to the system. 124*7c478bd9Sstevel@tonic-gate */ 125*7c478bd9Sstevel@tonic-gate static void 126*7c478bd9Sstevel@tonic-gate build_disk_list(void) 127*7c478bd9Sstevel@tonic-gate { 128*7c478bd9Sstevel@tonic-gate ldinfo_t *ptoi; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * Build the list of devices connected to the system. 132*7c478bd9Sstevel@tonic-gate */ 133*7c478bd9Sstevel@tonic-gate ptoi = rummage_devinfo(); 134*7c478bd9Sstevel@tonic-gate rummage_dev(ptoi); 135*7c478bd9Sstevel@tonic-gate cleanup_ldinfo(ptoi); 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate /* 139*7c478bd9Sstevel@tonic-gate * Walk the /dev/dsk and /dev/rmt directories building a 140*7c478bd9Sstevel@tonic-gate * list of interesting devices. Interesting is everything in the 141*7c478bd9Sstevel@tonic-gate * /dev/dsk directory. We skip some of the stuff in the /dev/rmt 142*7c478bd9Sstevel@tonic-gate * directory. 143*7c478bd9Sstevel@tonic-gate * 144*7c478bd9Sstevel@tonic-gate * Note that not finding one or more of the directories is not an 145*7c478bd9Sstevel@tonic-gate * error. 146*7c478bd9Sstevel@tonic-gate */ 147*7c478bd9Sstevel@tonic-gate static void 148*7c478bd9Sstevel@tonic-gate rummage_dev(ldinfo_t *ptoi) 149*7c478bd9Sstevel@tonic-gate { 150*7c478bd9Sstevel@tonic-gate DIR *dskp; 151*7c478bd9Sstevel@tonic-gate int i; 152*7c478bd9Sstevel@tonic-gate struct stat buf; 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_TYPES; i++) { 155*7c478bd9Sstevel@tonic-gate if (stat(dlist[i].name, &buf) == 0) { 156*7c478bd9Sstevel@tonic-gate if (dlist[i].mtime != buf.st_mtime) { 157*7c478bd9Sstevel@tonic-gate /* 158*7c478bd9Sstevel@tonic-gate * We've found a change. We need to cleanup 159*7c478bd9Sstevel@tonic-gate * old information and then rebuild the list 160*7c478bd9Sstevel@tonic-gate * for this device type. 161*7c478bd9Sstevel@tonic-gate */ 162*7c478bd9Sstevel@tonic-gate cleanup_dlist(&dlist[i]); 163*7c478bd9Sstevel@tonic-gate dlist[i].mtime = buf.st_mtime; 164*7c478bd9Sstevel@tonic-gate if ((dskp = opendir(dlist[i].name))) { 165*7c478bd9Sstevel@tonic-gate struct dirent *bpt; 166*7c478bd9Sstevel@tonic-gate char last_snm[NAME_BUFLEN]; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate last_snm[0] = NULL; 169*7c478bd9Sstevel@tonic-gate while ((bpt = readdir(dskp)) != NULL) { 170*7c478bd9Sstevel@tonic-gate if (bpt->d_name[0] != '.') { 171*7c478bd9Sstevel@tonic-gate process_dir_ent( 172*7c478bd9Sstevel@tonic-gate bpt->d_name, 173*7c478bd9Sstevel@tonic-gate i, last_snm, 174*7c478bd9Sstevel@tonic-gate &dlist[i], 175*7c478bd9Sstevel@tonic-gate ptoi); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate (void) closedir(dskp); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* 186*7c478bd9Sstevel@tonic-gate * Walk the list of located devices and see if we've 187*7c478bd9Sstevel@tonic-gate * seen this device before. We look at the short name. 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate static int 190*7c478bd9Sstevel@tonic-gate look_up_name(const char *nm, disk_list_t *list) 191*7c478bd9Sstevel@tonic-gate { 192*7c478bd9Sstevel@tonic-gate while (list) { 193*7c478bd9Sstevel@tonic-gate if (strcmp(list->dsk, nm) != 0) 194*7c478bd9Sstevel@tonic-gate list = list->next; 195*7c478bd9Sstevel@tonic-gate else { 196*7c478bd9Sstevel@tonic-gate return (1); 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate return (0); 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate /* 203*7c478bd9Sstevel@tonic-gate * Take a name of the form cNtNdNsN or cNtNdNpN 204*7c478bd9Sstevel@tonic-gate * or /dev/dsk/CNtNdNsN or /dev/dsk/cNtNdNpN 205*7c478bd9Sstevel@tonic-gate * remove the trailing sN or pN. Simply looking 206*7c478bd9Sstevel@tonic-gate * for the first 's' or 'p' doesn't cut it. 207*7c478bd9Sstevel@tonic-gate */ 208*7c478bd9Sstevel@tonic-gate static void 209*7c478bd9Sstevel@tonic-gate do_snm(char *orig, char *shortnm) 210*7c478bd9Sstevel@tonic-gate { 211*7c478bd9Sstevel@tonic-gate char *tmp; 212*7c478bd9Sstevel@tonic-gate char *ptmp; 213*7c478bd9Sstevel@tonic-gate int done = 0; 214*7c478bd9Sstevel@tonic-gate char repl_char = 0; 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate tmp = strrchr(orig, 's'); 217*7c478bd9Sstevel@tonic-gate if (tmp) { 218*7c478bd9Sstevel@tonic-gate ptmp = tmp; 219*7c478bd9Sstevel@tonic-gate ptmp++; 220*7c478bd9Sstevel@tonic-gate done = str_is_digit(ptmp); 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate if (done == 0) { 223*7c478bd9Sstevel@tonic-gate /* 224*7c478bd9Sstevel@tonic-gate * The string either has no 's' in it 225*7c478bd9Sstevel@tonic-gate * or the stuff trailing the s has a 226*7c478bd9Sstevel@tonic-gate * non-numeric in it. Look to see if 227*7c478bd9Sstevel@tonic-gate * we have an ending 'p' followed by 228*7c478bd9Sstevel@tonic-gate * numerics. 229*7c478bd9Sstevel@tonic-gate */ 230*7c478bd9Sstevel@tonic-gate tmp = strrchr(orig, 'p'); 231*7c478bd9Sstevel@tonic-gate if (tmp) { 232*7c478bd9Sstevel@tonic-gate ptmp = tmp; 233*7c478bd9Sstevel@tonic-gate ptmp++; 234*7c478bd9Sstevel@tonic-gate if (str_is_digit(ptmp)) 235*7c478bd9Sstevel@tonic-gate repl_char = 'p'; 236*7c478bd9Sstevel@tonic-gate else 237*7c478bd9Sstevel@tonic-gate tmp = 0; 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate } else { 240*7c478bd9Sstevel@tonic-gate repl_char = 's'; 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate if (tmp) 243*7c478bd9Sstevel@tonic-gate *tmp = '\0'; 244*7c478bd9Sstevel@tonic-gate (void) strcpy(shortnm, orig); 245*7c478bd9Sstevel@tonic-gate if (repl_char) 246*7c478bd9Sstevel@tonic-gate *tmp = repl_char; 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate /* 250*7c478bd9Sstevel@tonic-gate * Create and insert an entry into the device list. 251*7c478bd9Sstevel@tonic-gate */ 252*7c478bd9Sstevel@tonic-gate static disk_list_t * 253*7c478bd9Sstevel@tonic-gate make_an_entry(char *lname, char *shortnm, char *longnm, 254*7c478bd9Sstevel@tonic-gate dir_info_t *drent, int devtype, ldinfo_t *ptoi) 255*7c478bd9Sstevel@tonic-gate { 256*7c478bd9Sstevel@tonic-gate disk_list_t *entry; 257*7c478bd9Sstevel@tonic-gate char *nlnm; 258*7c478bd9Sstevel@tonic-gate char snm[NAME_BUFLEN]; 259*7c478bd9Sstevel@tonic-gate ldinfo_t *p; 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate entry = safe_alloc(sizeof (disk_list_t)); 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate nlnm = trim(lname, drent->trimstr, drent->trimchr); 264*7c478bd9Sstevel@tonic-gate entry->dsk = safe_strdup(shortnm); 265*7c478bd9Sstevel@tonic-gate do_snm(longnm, snm); 266*7c478bd9Sstevel@tonic-gate entry->dname = safe_strdup(snm); 267*7c478bd9Sstevel@tonic-gate entry->devtype = devtype; 268*7c478bd9Sstevel@tonic-gate entry->devidstr = NULL; 269*7c478bd9Sstevel@tonic-gate if ((p = find_ldinfo_match(nlnm, ptoi))) { 270*7c478bd9Sstevel@tonic-gate entry->dnum = p->dnum; 271*7c478bd9Sstevel@tonic-gate entry->dtype = safe_strdup(p->dtype); 272*7c478bd9Sstevel@tonic-gate if (p->devidstr) 273*7c478bd9Sstevel@tonic-gate entry->devidstr = safe_strdup(p->devidstr); 274*7c478bd9Sstevel@tonic-gate } else { 275*7c478bd9Sstevel@tonic-gate entry->dtype = safe_strdup(drent->dtype); 276*7c478bd9Sstevel@tonic-gate entry->dnum = -1; 277*7c478bd9Sstevel@tonic-gate if (drent->dtype) { 278*7c478bd9Sstevel@tonic-gate if (strcmp(drent->dtype, "md") == 0) { 279*7c478bd9Sstevel@tonic-gate (void) sscanf(shortnm, "d%d", &entry->dnum); 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate entry->seen = 0; 284*7c478bd9Sstevel@tonic-gate entry->next = 0; 285*7c478bd9Sstevel@tonic-gate insert_dlist_ent(entry, &drent->list); 286*7c478bd9Sstevel@tonic-gate return (entry); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* 290*7c478bd9Sstevel@tonic-gate * slice stuff off beginning and end of /devices directory names derived from 291*7c478bd9Sstevel@tonic-gate * device links. 292*7c478bd9Sstevel@tonic-gate */ 293*7c478bd9Sstevel@tonic-gate static char * 294*7c478bd9Sstevel@tonic-gate trim(char *fnm, char *lname, int rchr) 295*7c478bd9Sstevel@tonic-gate { 296*7c478bd9Sstevel@tonic-gate char *ptr; 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate while (*lname == *fnm) { 299*7c478bd9Sstevel@tonic-gate lname++; 300*7c478bd9Sstevel@tonic-gate fnm++; 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate if ((ptr = strrchr(fnm, rchr))) 303*7c478bd9Sstevel@tonic-gate *ptr = NULL; 304*7c478bd9Sstevel@tonic-gate return (fnm); 305*7c478bd9Sstevel@tonic-gate } 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate /* 308*7c478bd9Sstevel@tonic-gate * Find an entry matching the name passed in 309*7c478bd9Sstevel@tonic-gate */ 310*7c478bd9Sstevel@tonic-gate static ldinfo_t * 311*7c478bd9Sstevel@tonic-gate find_ldinfo_match(char *name, ldinfo_t *ptoi) 312*7c478bd9Sstevel@tonic-gate { 313*7c478bd9Sstevel@tonic-gate if (name) { 314*7c478bd9Sstevel@tonic-gate while (ptoi) { 315*7c478bd9Sstevel@tonic-gate if (strcmp(ptoi->name, name)) 316*7c478bd9Sstevel@tonic-gate ptoi = ptoi->next; 317*7c478bd9Sstevel@tonic-gate else 318*7c478bd9Sstevel@tonic-gate return (ptoi); 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate } 321*7c478bd9Sstevel@tonic-gate return (NULL); 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate /* 325*7c478bd9Sstevel@tonic-gate * Determine if a name is already in the list of disks. If not, insert the 326*7c478bd9Sstevel@tonic-gate * name in the list. 327*7c478bd9Sstevel@tonic-gate */ 328*7c478bd9Sstevel@tonic-gate static void 329*7c478bd9Sstevel@tonic-gate insert_dlist_ent(disk_list_t *n, disk_list_t **hd) 330*7c478bd9Sstevel@tonic-gate { 331*7c478bd9Sstevel@tonic-gate disk_list_t *tmp_ptr; 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate if (n->dtype != NULL) { 334*7c478bd9Sstevel@tonic-gate tmp_ptr = *hd; 335*7c478bd9Sstevel@tonic-gate while (tmp_ptr) { 336*7c478bd9Sstevel@tonic-gate if (strcmp(n->dsk, tmp_ptr->dsk) != 0) 337*7c478bd9Sstevel@tonic-gate tmp_ptr = tmp_ptr->next; 338*7c478bd9Sstevel@tonic-gate else 339*7c478bd9Sstevel@tonic-gate break; 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate if (tmp_ptr == NULL) { 342*7c478bd9Sstevel@tonic-gate /* 343*7c478bd9Sstevel@tonic-gate * We don't do anything with MD_DISK types here 344*7c478bd9Sstevel@tonic-gate * since they don't have partitions. 345*7c478bd9Sstevel@tonic-gate */ 346*7c478bd9Sstevel@tonic-gate if (n->devtype == DISK || n->devtype == OSA_DISK) { 347*7c478bd9Sstevel@tonic-gate n->flags = SLICES_OK; 348*7c478bd9Sstevel@tonic-gate #if defined(i386) || defined(__ia64) 349*7c478bd9Sstevel@tonic-gate n->flags |= PARTITIONS_OK; 350*7c478bd9Sstevel@tonic-gate #endif 351*7c478bd9Sstevel@tonic-gate } else { 352*7c478bd9Sstevel@tonic-gate n->flags = 0; 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate /* 355*7c478bd9Sstevel@tonic-gate * Figure out where to insert the name. The list is 356*7c478bd9Sstevel@tonic-gate * ostensibly in sorted order. 357*7c478bd9Sstevel@tonic-gate */ 358*7c478bd9Sstevel@tonic-gate if (*hd) { 359*7c478bd9Sstevel@tonic-gate disk_list_t *follw; 360*7c478bd9Sstevel@tonic-gate int mv; 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate tmp_ptr = *hd; 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate /* 365*7c478bd9Sstevel@tonic-gate * Look through the list. While the strcmp 366*7c478bd9Sstevel@tonic-gate * value is less than the current value, 367*7c478bd9Sstevel@tonic-gate */ 368*7c478bd9Sstevel@tonic-gate while (tmp_ptr) { 369*7c478bd9Sstevel@tonic-gate if ((mv = strcmp(n->dtype, 370*7c478bd9Sstevel@tonic-gate tmp_ptr->dtype)) < 0) { 371*7c478bd9Sstevel@tonic-gate follw = tmp_ptr; 372*7c478bd9Sstevel@tonic-gate tmp_ptr = tmp_ptr->next; 373*7c478bd9Sstevel@tonic-gate } else 374*7c478bd9Sstevel@tonic-gate break; 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate if (mv == 0) { 377*7c478bd9Sstevel@tonic-gate /* 378*7c478bd9Sstevel@tonic-gate * We're now in the area where the 379*7c478bd9Sstevel@tonic-gate * leading chars of the kstat name 380*7c478bd9Sstevel@tonic-gate * match. We need to insert in numeric 381*7c478bd9Sstevel@tonic-gate * order after that. 382*7c478bd9Sstevel@tonic-gate */ 383*7c478bd9Sstevel@tonic-gate while (tmp_ptr) { 384*7c478bd9Sstevel@tonic-gate if (strcmp(n->dtype, 385*7c478bd9Sstevel@tonic-gate tmp_ptr->dtype) != 0) 386*7c478bd9Sstevel@tonic-gate break; 387*7c478bd9Sstevel@tonic-gate if (n->dnum > tmp_ptr->dnum) { 388*7c478bd9Sstevel@tonic-gate follw = tmp_ptr; 389*7c478bd9Sstevel@tonic-gate tmp_ptr = tmp_ptr->next; 390*7c478bd9Sstevel@tonic-gate } else 391*7c478bd9Sstevel@tonic-gate break; 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate /* 395*7c478bd9Sstevel@tonic-gate * We should now be ready to insert an 396*7c478bd9Sstevel@tonic-gate * entry... 397*7c478bd9Sstevel@tonic-gate */ 398*7c478bd9Sstevel@tonic-gate if (mv >= 0) { 399*7c478bd9Sstevel@tonic-gate if (tmp_ptr == *hd) { 400*7c478bd9Sstevel@tonic-gate n->next = tmp_ptr; 401*7c478bd9Sstevel@tonic-gate *hd = n; 402*7c478bd9Sstevel@tonic-gate } else { 403*7c478bd9Sstevel@tonic-gate n->next = follw->next; 404*7c478bd9Sstevel@tonic-gate follw->next = n; 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate } else { 407*7c478bd9Sstevel@tonic-gate /* 408*7c478bd9Sstevel@tonic-gate * insert at the end of the 409*7c478bd9Sstevel@tonic-gate * list 410*7c478bd9Sstevel@tonic-gate */ 411*7c478bd9Sstevel@tonic-gate follw->next = n; 412*7c478bd9Sstevel@tonic-gate n->next = 0; 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate } else { 415*7c478bd9Sstevel@tonic-gate *hd = n; 416*7c478bd9Sstevel@tonic-gate n->next = 0; 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate /* 423*7c478bd9Sstevel@tonic-gate * find an entry matching the given kstat name in the list 424*7c478bd9Sstevel@tonic-gate * of disks, tapes and metadevices. 425*7c478bd9Sstevel@tonic-gate */ 426*7c478bd9Sstevel@tonic-gate disk_list_t * 427*7c478bd9Sstevel@tonic-gate lookup_ks_name(char *dev_nm) 428*7c478bd9Sstevel@tonic-gate { 429*7c478bd9Sstevel@tonic-gate int tried = 0; 430*7c478bd9Sstevel@tonic-gate int dv; 431*7c478bd9Sstevel@tonic-gate int len; 432*7c478bd9Sstevel@tonic-gate char cmpbuf[PATH_MAX + 1]; 433*7c478bd9Sstevel@tonic-gate struct list_of_disks *list; 434*7c478bd9Sstevel@tonic-gate char *nm; 435*7c478bd9Sstevel@tonic-gate dev_name_t *tmp; 436*7c478bd9Sstevel@tonic-gate uint_t i; 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate /* 439*7c478bd9Sstevel@tonic-gate * extract the device type from the kstat name. We expect the 440*7c478bd9Sstevel@tonic-gate * name to be one or more alphabetics followed by the device 441*7c478bd9Sstevel@tonic-gate * numeric id. We do this solely for speed purposes . 442*7c478bd9Sstevel@tonic-gate */ 443*7c478bd9Sstevel@tonic-gate len = 0; 444*7c478bd9Sstevel@tonic-gate nm = dev_nm; 445*7c478bd9Sstevel@tonic-gate while (*nm) { 446*7c478bd9Sstevel@tonic-gate if (isalpha(*nm)) { 447*7c478bd9Sstevel@tonic-gate nm++; 448*7c478bd9Sstevel@tonic-gate len++; 449*7c478bd9Sstevel@tonic-gate } else 450*7c478bd9Sstevel@tonic-gate break; 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate if (!*nm) 454*7c478bd9Sstevel@tonic-gate return (NULL); 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate /* 457*7c478bd9Sstevel@tonic-gate * For each of the elements in the dlist array we keep 458*7c478bd9Sstevel@tonic-gate * an array of pointers to chains for each of the kstat 459*7c478bd9Sstevel@tonic-gate * prefixes found within that directory. This is typically 460*7c478bd9Sstevel@tonic-gate * 'sd' and 'ssd'. We walk the list in the directory and 461*7c478bd9Sstevel@tonic-gate * match on that type. Since the same prefixes can be 462*7c478bd9Sstevel@tonic-gate * in multiple places we keep checking if we don't find 463*7c478bd9Sstevel@tonic-gate * it in the first place. 464*7c478bd9Sstevel@tonic-gate */ 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate (void) strncpy(cmpbuf, dev_nm, len); 467*7c478bd9Sstevel@tonic-gate cmpbuf[len] = NULL; 468*7c478bd9Sstevel@tonic-gate dv = atoi(nm); 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate retry: 471*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_TYPES; i++) { 472*7c478bd9Sstevel@tonic-gate tmp = dlist[i].nf; 473*7c478bd9Sstevel@tonic-gate while (tmp) { 474*7c478bd9Sstevel@tonic-gate if (strcmp(tmp->name, cmpbuf) == 0) { 475*7c478bd9Sstevel@tonic-gate /* 476*7c478bd9Sstevel@tonic-gate * As an optimization we keep mins 477*7c478bd9Sstevel@tonic-gate * and maxes for the devices found. 478*7c478bd9Sstevel@tonic-gate * This helps chop the lists up and 479*7c478bd9Sstevel@tonic-gate * avoid some really long chains as 480*7c478bd9Sstevel@tonic-gate * we would get if we kept only prefix 481*7c478bd9Sstevel@tonic-gate * lists. 482*7c478bd9Sstevel@tonic-gate */ 483*7c478bd9Sstevel@tonic-gate if (dv >= tmp->min && dv <= tmp->max) { 484*7c478bd9Sstevel@tonic-gate list = tmp->list_start; 485*7c478bd9Sstevel@tonic-gate while (list) { 486*7c478bd9Sstevel@tonic-gate if (list->dnum < dv) 487*7c478bd9Sstevel@tonic-gate list = list->next; 488*7c478bd9Sstevel@tonic-gate else 489*7c478bd9Sstevel@tonic-gate break; 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate if (list && list->dnum == dv) { 492*7c478bd9Sstevel@tonic-gate return (list); 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate tmp = tmp->next; 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate } 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate if (!tried) { 501*7c478bd9Sstevel@tonic-gate tried = 1; 502*7c478bd9Sstevel@tonic-gate build_disk_list(); 503*7c478bd9Sstevel@tonic-gate goto retry; 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate return (0); 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate static int 510*7c478bd9Sstevel@tonic-gate str_is_digit(char *str) 511*7c478bd9Sstevel@tonic-gate { 512*7c478bd9Sstevel@tonic-gate while (*str) { 513*7c478bd9Sstevel@tonic-gate if (isdigit(*str)) 514*7c478bd9Sstevel@tonic-gate str++; 515*7c478bd9Sstevel@tonic-gate else 516*7c478bd9Sstevel@tonic-gate return (0); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate return (1); 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate static void 522*7c478bd9Sstevel@tonic-gate insert_into_dlist(dir_info_t *d, disk_list_t *e) 523*7c478bd9Sstevel@tonic-gate { 524*7c478bd9Sstevel@tonic-gate dev_name_t *tmp; 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate tmp = d->nf; 527*7c478bd9Sstevel@tonic-gate while (tmp) { 528*7c478bd9Sstevel@tonic-gate if (strcmp(e->dtype, tmp->name) != 0) { 529*7c478bd9Sstevel@tonic-gate tmp = tmp->next; 530*7c478bd9Sstevel@tonic-gate } else { 531*7c478bd9Sstevel@tonic-gate if (e->dnum < tmp->min) { 532*7c478bd9Sstevel@tonic-gate tmp->min = e->dnum; 533*7c478bd9Sstevel@tonic-gate tmp->list_start = e; 534*7c478bd9Sstevel@tonic-gate } else if (e->dnum > tmp->max) { 535*7c478bd9Sstevel@tonic-gate tmp->max = e->dnum; 536*7c478bd9Sstevel@tonic-gate tmp->list_end = e; 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate break; 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate } 541*7c478bd9Sstevel@tonic-gate if (tmp == NULL) { 542*7c478bd9Sstevel@tonic-gate tmp = safe_alloc(sizeof (dev_name_t)); 543*7c478bd9Sstevel@tonic-gate tmp->name = e->dtype; 544*7c478bd9Sstevel@tonic-gate tmp->min = e->dnum; 545*7c478bd9Sstevel@tonic-gate tmp->max = e->dnum; 546*7c478bd9Sstevel@tonic-gate tmp->list_start = e; 547*7c478bd9Sstevel@tonic-gate tmp->list_end = e; 548*7c478bd9Sstevel@tonic-gate tmp->next = d->nf; 549*7c478bd9Sstevel@tonic-gate d->nf = tmp; 550*7c478bd9Sstevel@tonic-gate } 551*7c478bd9Sstevel@tonic-gate } 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate /* 554*7c478bd9Sstevel@tonic-gate * devinfo_ident_disks() and devinfo_ident_tapes() are the callback functions we 555*7c478bd9Sstevel@tonic-gate * use while walking the device tree snapshot provided by devinfo. If 556*7c478bd9Sstevel@tonic-gate * devinfo_ident_disks() identifies that the device being considered has one or 557*7c478bd9Sstevel@tonic-gate * more minor nodes _and_ is a block device, then it is a potential disk. 558*7c478bd9Sstevel@tonic-gate * Similarly for devinfo_ident_tapes(), except that the second criterion is that 559*7c478bd9Sstevel@tonic-gate * the minor_node be a character device. (This is more inclusive than only 560*7c478bd9Sstevel@tonic-gate * tape devices, but will match any entries in /dev/rmt/.) 561*7c478bd9Sstevel@tonic-gate * 562*7c478bd9Sstevel@tonic-gate * Note: if a driver was previously loaded but is now unloaded, the kstat may 563*7c478bd9Sstevel@tonic-gate * still be around (e.g., st) but no information will be found in the 564*7c478bd9Sstevel@tonic-gate * libdevinfo tree. 565*7c478bd9Sstevel@tonic-gate */ 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate static int 568*7c478bd9Sstevel@tonic-gate devinfo_ident_disks(di_node_t node, void *arg) 569*7c478bd9Sstevel@tonic-gate { 570*7c478bd9Sstevel@tonic-gate di_minor_t minor = DI_MINOR_NIL; 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate if ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 573*7c478bd9Sstevel@tonic-gate int spectype = di_minor_spectype(minor); 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate if (S_ISBLK(spectype)) { 576*7c478bd9Sstevel@tonic-gate char *physical_path = di_devfs_path(node); 577*7c478bd9Sstevel@tonic-gate int instance = di_instance(node); 578*7c478bd9Sstevel@tonic-gate char *driver_name = di_driver_name(node); 579*7c478bd9Sstevel@tonic-gate char *devidstr; 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate /* lookup the devid, devt specific first */ 582*7c478bd9Sstevel@tonic-gate if ((di_prop_lookup_strings(di_minor_devt(minor), node, 583*7c478bd9Sstevel@tonic-gate DEVID_PROP_NAME, &devidstr) == -1) && 584*7c478bd9Sstevel@tonic-gate (di_prop_lookup_strings(DDI_DEV_T_ANY, node, 585*7c478bd9Sstevel@tonic-gate DEVID_PROP_NAME, &devidstr) == -1)) 586*7c478bd9Sstevel@tonic-gate devidstr = NULL; 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate if (driver_name == NULL) 589*7c478bd9Sstevel@tonic-gate driver_name = "<nil>"; 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate pline(physical_path, instance, 592*7c478bd9Sstevel@tonic-gate driver_name, devidstr, arg); 593*7c478bd9Sstevel@tonic-gate di_devfs_path_free(physical_path); 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate } 596*7c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate static int 600*7c478bd9Sstevel@tonic-gate devinfo_ident_tapes(di_node_t node, void *arg) 601*7c478bd9Sstevel@tonic-gate { 602*7c478bd9Sstevel@tonic-gate di_minor_t minor = DI_MINOR_NIL; 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate if ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 605*7c478bd9Sstevel@tonic-gate int spectype = di_minor_spectype(minor); 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate if (S_ISCHR(spectype)) { 608*7c478bd9Sstevel@tonic-gate char *physical_path = di_devfs_path(node); 609*7c478bd9Sstevel@tonic-gate int instance = di_instance(node); 610*7c478bd9Sstevel@tonic-gate char *binding_name = di_binding_name(node); 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate pline(physical_path, instance, 613*7c478bd9Sstevel@tonic-gate binding_name, NULL, arg); 614*7c478bd9Sstevel@tonic-gate di_devfs_path_free(physical_path); 615*7c478bd9Sstevel@tonic-gate } 616*7c478bd9Sstevel@tonic-gate } 617*7c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate /* 621*7c478bd9Sstevel@tonic-gate * rummage_devinfo() is the driver routine that walks the devinfo snapshot. 622*7c478bd9Sstevel@tonic-gate */ 623*7c478bd9Sstevel@tonic-gate static ldinfo_t * 624*7c478bd9Sstevel@tonic-gate rummage_devinfo(void) 625*7c478bd9Sstevel@tonic-gate { 626*7c478bd9Sstevel@tonic-gate di_node_t root_node; 627*7c478bd9Sstevel@tonic-gate ldinfo_t *rv = NULL; 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate if ((root_node = di_init("/", DINFOCPYALL)) != DI_NODE_NIL) { 630*7c478bd9Sstevel@tonic-gate (void) di_walk_node(root_node, DI_WALK_CLDFIRST, (void *)&rv, 631*7c478bd9Sstevel@tonic-gate devinfo_ident_disks); 632*7c478bd9Sstevel@tonic-gate (void) di_walk_node(root_node, DI_WALK_CLDFIRST, (void *)&rv, 633*7c478bd9Sstevel@tonic-gate devinfo_ident_tapes); 634*7c478bd9Sstevel@tonic-gate di_fini(root_node); 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate return (rv); 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate /* 640*7c478bd9Sstevel@tonic-gate * pline() performs the lookup of the device path in the current list of disks, 641*7c478bd9Sstevel@tonic-gate * and adds the appropriate information to the nms list in the case of a match. 642*7c478bd9Sstevel@tonic-gate */ 643*7c478bd9Sstevel@tonic-gate static void 644*7c478bd9Sstevel@tonic-gate pline(char *devfs_path, int instance, 645*7c478bd9Sstevel@tonic-gate char *driver_name, char *devidstr, ldinfo_t **list) 646*7c478bd9Sstevel@tonic-gate { 647*7c478bd9Sstevel@tonic-gate ldinfo_t *entry; 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate entry = safe_alloc(sizeof (ldinfo_t)); 650*7c478bd9Sstevel@tonic-gate entry->dnum = instance; 651*7c478bd9Sstevel@tonic-gate entry->name = safe_strdup(devfs_path); 652*7c478bd9Sstevel@tonic-gate entry->dtype = safe_strdup(driver_name); 653*7c478bd9Sstevel@tonic-gate entry->devidstr = safe_strdup(devidstr); 654*7c478bd9Sstevel@tonic-gate entry->next = *list; 655*7c478bd9Sstevel@tonic-gate *list = entry; 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate /* 659*7c478bd9Sstevel@tonic-gate * Cleanup space allocated in dlist processing. 660*7c478bd9Sstevel@tonic-gate * We're only interested in cleaning up the list and nf 661*7c478bd9Sstevel@tonic-gate * fields in the structure. Everything else is static 662*7c478bd9Sstevel@tonic-gate * data. 663*7c478bd9Sstevel@tonic-gate */ 664*7c478bd9Sstevel@tonic-gate static void 665*7c478bd9Sstevel@tonic-gate cleanup_dlist(dir_info_t *d) 666*7c478bd9Sstevel@tonic-gate { 667*7c478bd9Sstevel@tonic-gate dev_name_t *tmp; 668*7c478bd9Sstevel@tonic-gate dev_name_t *t1; 669*7c478bd9Sstevel@tonic-gate disk_list_t *t2; 670*7c478bd9Sstevel@tonic-gate disk_list_t *t3; 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate /* 673*7c478bd9Sstevel@tonic-gate * All of the entries in a dev_name_t use information 674*7c478bd9Sstevel@tonic-gate * from a disk_list_t structure that is freed later. 675*7c478bd9Sstevel@tonic-gate * All we need do here is free the dev_name_t 676*7c478bd9Sstevel@tonic-gate * structure itself. 677*7c478bd9Sstevel@tonic-gate */ 678*7c478bd9Sstevel@tonic-gate tmp = d->nf; 679*7c478bd9Sstevel@tonic-gate while (tmp) { 680*7c478bd9Sstevel@tonic-gate t1 = tmp->next; 681*7c478bd9Sstevel@tonic-gate free(tmp); 682*7c478bd9Sstevel@tonic-gate tmp = t1; 683*7c478bd9Sstevel@tonic-gate } 684*7c478bd9Sstevel@tonic-gate d->nf = 0; 685*7c478bd9Sstevel@tonic-gate /* 686*7c478bd9Sstevel@tonic-gate * "Later". Free the disk_list_t structures and their 687*7c478bd9Sstevel@tonic-gate * data attached to this portion of the dir_info 688*7c478bd9Sstevel@tonic-gate * structure. 689*7c478bd9Sstevel@tonic-gate */ 690*7c478bd9Sstevel@tonic-gate t2 = d->list; 691*7c478bd9Sstevel@tonic-gate while (t2) { 692*7c478bd9Sstevel@tonic-gate if (t2->dtype) { 693*7c478bd9Sstevel@tonic-gate free(t2->dtype); 694*7c478bd9Sstevel@tonic-gate t2->dtype = NULL; 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate if (t2->dsk) { 697*7c478bd9Sstevel@tonic-gate free(t2->dsk); 698*7c478bd9Sstevel@tonic-gate t2->dsk = NULL; 699*7c478bd9Sstevel@tonic-gate } 700*7c478bd9Sstevel@tonic-gate if (t2->dname) { 701*7c478bd9Sstevel@tonic-gate free(t2->dname); 702*7c478bd9Sstevel@tonic-gate t2->dname = NULL; 703*7c478bd9Sstevel@tonic-gate } 704*7c478bd9Sstevel@tonic-gate t3 = t2->next; 705*7c478bd9Sstevel@tonic-gate free(t2); 706*7c478bd9Sstevel@tonic-gate t2 = t3; 707*7c478bd9Sstevel@tonic-gate } 708*7c478bd9Sstevel@tonic-gate d->list = 0; 709*7c478bd9Sstevel@tonic-gate } 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate static void 712*7c478bd9Sstevel@tonic-gate process_dir_ent(char *dent, int curr_type, char *last_snm, 713*7c478bd9Sstevel@tonic-gate dir_info_t *dp, ldinfo_t *ptoi) 714*7c478bd9Sstevel@tonic-gate { 715*7c478bd9Sstevel@tonic-gate struct stat sbuf; 716*7c478bd9Sstevel@tonic-gate char dnmbuf[PATH_MAX + 1]; 717*7c478bd9Sstevel@tonic-gate char lnm[NAME_BUFLEN]; 718*7c478bd9Sstevel@tonic-gate char snm[NAME_BUFLEN]; 719*7c478bd9Sstevel@tonic-gate char *npt; 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate snm[0] = NULL; 722*7c478bd9Sstevel@tonic-gate if (curr_type == DISK || curr_type == OSA_DISK) { 723*7c478bd9Sstevel@tonic-gate /* 724*7c478bd9Sstevel@tonic-gate * get the short name - omitting 725*7c478bd9Sstevel@tonic-gate * the trailing sN or PN 726*7c478bd9Sstevel@tonic-gate */ 727*7c478bd9Sstevel@tonic-gate (void) strcpy(lnm, dent); 728*7c478bd9Sstevel@tonic-gate do_snm(dent, snm); 729*7c478bd9Sstevel@tonic-gate } else if (curr_type == MD_DISK) { 730*7c478bd9Sstevel@tonic-gate (void) strcpy(lnm, dent); 731*7c478bd9Sstevel@tonic-gate (void) strcpy(snm, dent); 732*7c478bd9Sstevel@tonic-gate } else { 733*7c478bd9Sstevel@tonic-gate /* 734*7c478bd9Sstevel@tonic-gate * don't want all rewind/etc 735*7c478bd9Sstevel@tonic-gate * devices for a tape 736*7c478bd9Sstevel@tonic-gate */ 737*7c478bd9Sstevel@tonic-gate if (!str_is_digit(dent)) 738*7c478bd9Sstevel@tonic-gate return; 739*7c478bd9Sstevel@tonic-gate (void) snprintf(snm, sizeof (snm), "rmt/%s", dent); 740*7c478bd9Sstevel@tonic-gate (void) snprintf(lnm, sizeof (snm), "rmt/%s", dent); 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate /* 743*7c478bd9Sstevel@tonic-gate * See if we've already processed an entry for this device. 744*7c478bd9Sstevel@tonic-gate * If so, we're just another partition so we get another 745*7c478bd9Sstevel@tonic-gate * entry. 746*7c478bd9Sstevel@tonic-gate * 747*7c478bd9Sstevel@tonic-gate * last_snm is an optimization to avoid the function call 748*7c478bd9Sstevel@tonic-gate * and lookup since we'll often see partition records 749*7c478bd9Sstevel@tonic-gate * immediately after the disk record. 750*7c478bd9Sstevel@tonic-gate */ 751*7c478bd9Sstevel@tonic-gate if (dp->skip_lookup == 0) { 752*7c478bd9Sstevel@tonic-gate if (strcmp(snm, last_snm) != 0) { 753*7c478bd9Sstevel@tonic-gate /* 754*7c478bd9Sstevel@tonic-gate * a zero return means that 755*7c478bd9Sstevel@tonic-gate * no record was found. We'd 756*7c478bd9Sstevel@tonic-gate * return a pointer otherwise. 757*7c478bd9Sstevel@tonic-gate */ 758*7c478bd9Sstevel@tonic-gate if (look_up_name(snm, 759*7c478bd9Sstevel@tonic-gate dp->list) == 0) { 760*7c478bd9Sstevel@tonic-gate (void) strcpy(last_snm, snm); 761*7c478bd9Sstevel@tonic-gate } else 762*7c478bd9Sstevel@tonic-gate return; 763*7c478bd9Sstevel@tonic-gate } else 764*7c478bd9Sstevel@tonic-gate return; 765*7c478bd9Sstevel@tonic-gate } 766*7c478bd9Sstevel@tonic-gate /* 767*7c478bd9Sstevel@tonic-gate * Get the real device name for this beast 768*7c478bd9Sstevel@tonic-gate * by following the link into /devices. 769*7c478bd9Sstevel@tonic-gate */ 770*7c478bd9Sstevel@tonic-gate (void) snprintf(dnmbuf, sizeof (dnmbuf), "%s/%s", dp->name, dent); 771*7c478bd9Sstevel@tonic-gate if (lstat(dnmbuf, &sbuf) != -1) { 772*7c478bd9Sstevel@tonic-gate if ((sbuf.st_mode & S_IFMT) == S_IFLNK) { 773*7c478bd9Sstevel@tonic-gate /* 774*7c478bd9Sstevel@tonic-gate * It's a link. Get the real name. 775*7c478bd9Sstevel@tonic-gate */ 776*7c478bd9Sstevel@tonic-gate char nmbuf[PATH_MAX + 1]; 777*7c478bd9Sstevel@tonic-gate int nbyr; 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate if ((nbyr = readlink(dnmbuf, nmbuf, 780*7c478bd9Sstevel@tonic-gate sizeof (nmbuf))) != 1) { 781*7c478bd9Sstevel@tonic-gate npt = nmbuf; 782*7c478bd9Sstevel@tonic-gate /* 783*7c478bd9Sstevel@tonic-gate * readlink does not terminate 784*7c478bd9Sstevel@tonic-gate * the string so we have to 785*7c478bd9Sstevel@tonic-gate * do it. 786*7c478bd9Sstevel@tonic-gate */ 787*7c478bd9Sstevel@tonic-gate nmbuf[nbyr] = NULL; 788*7c478bd9Sstevel@tonic-gate } else 789*7c478bd9Sstevel@tonic-gate npt = NULL; 790*7c478bd9Sstevel@tonic-gate } else 791*7c478bd9Sstevel@tonic-gate npt = lnm; 792*7c478bd9Sstevel@tonic-gate /* 793*7c478bd9Sstevel@tonic-gate * make an entry in the device list 794*7c478bd9Sstevel@tonic-gate */ 795*7c478bd9Sstevel@tonic-gate if (npt) { 796*7c478bd9Sstevel@tonic-gate disk_list_t *d; 797*7c478bd9Sstevel@tonic-gate 798*7c478bd9Sstevel@tonic-gate d = make_an_entry(npt, snm, 799*7c478bd9Sstevel@tonic-gate dnmbuf, dp, 800*7c478bd9Sstevel@tonic-gate curr_type, ptoi); 801*7c478bd9Sstevel@tonic-gate insert_into_dlist(dp, d); 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate } 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate static void 806*7c478bd9Sstevel@tonic-gate cleanup_ldinfo(ldinfo_t *list) 807*7c478bd9Sstevel@tonic-gate { 808*7c478bd9Sstevel@tonic-gate ldinfo_t *tmp; 809*7c478bd9Sstevel@tonic-gate while (list) { 810*7c478bd9Sstevel@tonic-gate tmp = list; 811*7c478bd9Sstevel@tonic-gate list = list->next; 812*7c478bd9Sstevel@tonic-gate free(tmp->name); 813*7c478bd9Sstevel@tonic-gate free(tmp->dtype); 814*7c478bd9Sstevel@tonic-gate if (tmp->devidstr) 815*7c478bd9Sstevel@tonic-gate free(tmp->devidstr); 816*7c478bd9Sstevel@tonic-gate free(tmp); 817*7c478bd9Sstevel@tonic-gate } 818*7c478bd9Sstevel@tonic-gate } 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate char * 821*7c478bd9Sstevel@tonic-gate lookup_nfs_name(char *ks, kstat_ctl_t *kc) 822*7c478bd9Sstevel@tonic-gate { 823*7c478bd9Sstevel@tonic-gate int tried = 0; 824*7c478bd9Sstevel@tonic-gate uint_t minor; 825*7c478bd9Sstevel@tonic-gate char *host, *path; 826*7c478bd9Sstevel@tonic-gate char *cp; 827*7c478bd9Sstevel@tonic-gate char *rstr = 0; 828*7c478bd9Sstevel@tonic-gate size_t len; 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate if (sscanf(ks, "nfs%u", &minor) == 1) { 831*7c478bd9Sstevel@tonic-gate retry: 832*7c478bd9Sstevel@tonic-gate cp = get_nfs_by_minor(minor); 833*7c478bd9Sstevel@tonic-gate if (cp) { 834*7c478bd9Sstevel@tonic-gate if (strchr(cp, ',') == NULL) { 835*7c478bd9Sstevel@tonic-gate rstr = safe_strdup(cp); 836*7c478bd9Sstevel@tonic-gate return (rstr); 837*7c478bd9Sstevel@tonic-gate } 838*7c478bd9Sstevel@tonic-gate host = cur_hostname(minor, kc); 839*7c478bd9Sstevel@tonic-gate if (host) { 840*7c478bd9Sstevel@tonic-gate if (*host) { 841*7c478bd9Sstevel@tonic-gate path = cur_special(host, cp); 842*7c478bd9Sstevel@tonic-gate if (path) { 843*7c478bd9Sstevel@tonic-gate len = strlen(host); 844*7c478bd9Sstevel@tonic-gate len += strlen(path); 845*7c478bd9Sstevel@tonic-gate len += 2; 846*7c478bd9Sstevel@tonic-gate rstr = safe_alloc(len); 847*7c478bd9Sstevel@tonic-gate (void) snprintf(rstr, len, 848*7c478bd9Sstevel@tonic-gate "%s:%s", host, path); 849*7c478bd9Sstevel@tonic-gate } else { 850*7c478bd9Sstevel@tonic-gate rstr = safe_strdup(cp); 851*7c478bd9Sstevel@tonic-gate } 852*7c478bd9Sstevel@tonic-gate } else { 853*7c478bd9Sstevel@tonic-gate rstr = safe_strdup(ks); 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate free(host); 856*7c478bd9Sstevel@tonic-gate } else { 857*7c478bd9Sstevel@tonic-gate rstr = safe_strdup(cp); 858*7c478bd9Sstevel@tonic-gate } 859*7c478bd9Sstevel@tonic-gate } else if (!tried) { 860*7c478bd9Sstevel@tonic-gate tried = 1; 861*7c478bd9Sstevel@tonic-gate do_mnttab(); 862*7c478bd9Sstevel@tonic-gate goto retry; 863*7c478bd9Sstevel@tonic-gate } 864*7c478bd9Sstevel@tonic-gate } 865*7c478bd9Sstevel@tonic-gate return (rstr); 866*7c478bd9Sstevel@tonic-gate } 867*7c478bd9Sstevel@tonic-gate 868*7c478bd9Sstevel@tonic-gate static char * 869*7c478bd9Sstevel@tonic-gate get_nfs_by_minor(uint_t minor) 870*7c478bd9Sstevel@tonic-gate { 871*7c478bd9Sstevel@tonic-gate mnt_t *localnfs; 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate localnfs = nfs; 874*7c478bd9Sstevel@tonic-gate while (localnfs) { 875*7c478bd9Sstevel@tonic-gate if (localnfs->minor == minor) { 876*7c478bd9Sstevel@tonic-gate return (localnfs->device_name); 877*7c478bd9Sstevel@tonic-gate } 878*7c478bd9Sstevel@tonic-gate localnfs = localnfs->next; 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate return (0); 881*7c478bd9Sstevel@tonic-gate } 882*7c478bd9Sstevel@tonic-gate 883*7c478bd9Sstevel@tonic-gate /* 884*7c478bd9Sstevel@tonic-gate * Read the cur_hostname from the mntinfo kstat 885*7c478bd9Sstevel@tonic-gate */ 886*7c478bd9Sstevel@tonic-gate static char * 887*7c478bd9Sstevel@tonic-gate cur_hostname(uint_t minor, kstat_ctl_t *kc) 888*7c478bd9Sstevel@tonic-gate { 889*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 890*7c478bd9Sstevel@tonic-gate static struct mntinfo_kstat mik; 891*7c478bd9Sstevel@tonic-gate char *rstr; 892*7c478bd9Sstevel@tonic-gate 893*7c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 894*7c478bd9Sstevel@tonic-gate if (ksp->ks_type != KSTAT_TYPE_RAW) 895*7c478bd9Sstevel@tonic-gate continue; 896*7c478bd9Sstevel@tonic-gate if (ksp->ks_instance != minor) 897*7c478bd9Sstevel@tonic-gate continue; 898*7c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_module, "nfs")) 899*7c478bd9Sstevel@tonic-gate continue; 900*7c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_name, "mntinfo")) 901*7c478bd9Sstevel@tonic-gate continue; 902*7c478bd9Sstevel@tonic-gate if (ksp->ks_flags & KSTAT_FLAG_INVALID) 903*7c478bd9Sstevel@tonic-gate return (NULL); 904*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, &mik) == -1) 905*7c478bd9Sstevel@tonic-gate return (NULL); 906*7c478bd9Sstevel@tonic-gate rstr = safe_strdup(mik.mik_curserver); 907*7c478bd9Sstevel@tonic-gate return (rstr); 908*7c478bd9Sstevel@tonic-gate } 909*7c478bd9Sstevel@tonic-gate return (NULL); 910*7c478bd9Sstevel@tonic-gate } 911*7c478bd9Sstevel@tonic-gate 912*7c478bd9Sstevel@tonic-gate /* 913*7c478bd9Sstevel@tonic-gate * Given the hostname of the mounted server, extract the server 914*7c478bd9Sstevel@tonic-gate * mount point from the mnttab string. 915*7c478bd9Sstevel@tonic-gate * 916*7c478bd9Sstevel@tonic-gate * Common forms: 917*7c478bd9Sstevel@tonic-gate * server1,server2,server3:/path 918*7c478bd9Sstevel@tonic-gate * server1:/path,server2:/path 919*7c478bd9Sstevel@tonic-gate * or a hybrid of the two 920*7c478bd9Sstevel@tonic-gate */ 921*7c478bd9Sstevel@tonic-gate static char * 922*7c478bd9Sstevel@tonic-gate cur_special(char *hostname, char *special) 923*7c478bd9Sstevel@tonic-gate { 924*7c478bd9Sstevel@tonic-gate char *cp; 925*7c478bd9Sstevel@tonic-gate char *path; 926*7c478bd9Sstevel@tonic-gate size_t hlen = strlen(hostname); 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate /* 929*7c478bd9Sstevel@tonic-gate * find hostname in string 930*7c478bd9Sstevel@tonic-gate */ 931*7c478bd9Sstevel@tonic-gate again: 932*7c478bd9Sstevel@tonic-gate if ((cp = strstr(special, hostname)) == NULL) 933*7c478bd9Sstevel@tonic-gate return (NULL); 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate /* 936*7c478bd9Sstevel@tonic-gate * hostname must be followed by ',' or ':' 937*7c478bd9Sstevel@tonic-gate */ 938*7c478bd9Sstevel@tonic-gate if (cp[hlen] != ',' && cp[hlen] != ':') { 939*7c478bd9Sstevel@tonic-gate special = &cp[hlen]; 940*7c478bd9Sstevel@tonic-gate goto again; 941*7c478bd9Sstevel@tonic-gate } 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate /* 944*7c478bd9Sstevel@tonic-gate * If hostname is followed by a ',' eat all characters until a ':' 945*7c478bd9Sstevel@tonic-gate */ 946*7c478bd9Sstevel@tonic-gate cp = &cp[hlen]; 947*7c478bd9Sstevel@tonic-gate if (*cp == ',') { 948*7c478bd9Sstevel@tonic-gate cp++; 949*7c478bd9Sstevel@tonic-gate while (*cp != ':') { 950*7c478bd9Sstevel@tonic-gate if (*cp == NULL) 951*7c478bd9Sstevel@tonic-gate return (NULL); 952*7c478bd9Sstevel@tonic-gate cp++; 953*7c478bd9Sstevel@tonic-gate } 954*7c478bd9Sstevel@tonic-gate } 955*7c478bd9Sstevel@tonic-gate path = ++cp; /* skip ':' */ 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate /* 958*7c478bd9Sstevel@tonic-gate * path is terminated by either 0, or space or ',' 959*7c478bd9Sstevel@tonic-gate */ 960*7c478bd9Sstevel@tonic-gate while (*cp) { 961*7c478bd9Sstevel@tonic-gate if (isspace(*cp) || *cp == ',') { 962*7c478bd9Sstevel@tonic-gate *cp = NULL; 963*7c478bd9Sstevel@tonic-gate return (path); 964*7c478bd9Sstevel@tonic-gate } 965*7c478bd9Sstevel@tonic-gate cp++; 966*7c478bd9Sstevel@tonic-gate } 967*7c478bd9Sstevel@tonic-gate return (path); 968*7c478bd9Sstevel@tonic-gate } 969