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 54e78ab0bScth * Common Development and Distribution License (the "License"). 64e78ab0bScth * 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 /* 224e78ab0bScth * 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 59*a08731ecScth /* disk/tape info */ 60*a08731ecScth static di_node_t di_root; /* for devid */ 61*a08731ecScth static di_dim_t di_dim; /* for /dev names */ 62*a08731ecScth typedef struct { 63*a08731ecScth char *minor_name; 64*a08731ecScth int minor_isdisk; 65*a08731ecScth } minor_match_t; 66*a08731ecScth static minor_match_t mm_disk = {"a", 1}; 67*a08731ecScth static minor_match_t mm_tape = {"", 0}; 68*a08731ecScth static char md_minor_name[MAXPATHLEN]; 69*a08731ecScth static minor_match_t mm_md = {md_minor_name, 0}; 70*a08731ecScth static minor_match_t *mma_disk_tape[] = {&mm_disk, &mm_tape, NULL}; 71*a08731ecScth static minor_match_t *mma_md[] = {&mm_md, NULL}; 72*a08731ecScth static char *mdsetno2name(int setno); 73*a08731ecScth #define DISKLIST_MOD 256 /* ^2 instunit mod hash */ 74*a08731ecScth static disk_list_t *disklist[DISKLIST_MOD]; 757c478bd9Sstevel@tonic-gate 76*a08731ecScth /* nfs info */ 77*a08731ecScth extern kstat_ctl_t *kc; 78*a08731ecScth extern mnt_t *nfs; 79*a08731ecScth static int nfs_tried; 807c478bd9Sstevel@tonic-gate static char *get_nfs_by_minor(uint_t); 817c478bd9Sstevel@tonic-gate static char *cur_hostname(uint_t, kstat_ctl_t *); 827c478bd9Sstevel@tonic-gate static char *cur_special(char *, char *); 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* 85*a08731ecScth * Clear the snapshot so a cache miss in lookup_ks_name() will cause a fresh 86*a08731ecScth * snapshot in drvinstunit2dev(). 877c478bd9Sstevel@tonic-gate */ 88*a08731ecScth void 89*a08731ecScth cleanup_iodevs_snapshot() 907c478bd9Sstevel@tonic-gate { 91*a08731ecScth if (di_dim) { 92*a08731ecScth di_dim_fini(di_dim); 93*a08731ecScth di_dim = NULL; 94*a08731ecScth } 957c478bd9Sstevel@tonic-gate 96*a08731ecScth if (di_root) { 97*a08731ecScth di_fini(di_root); 98*a08731ecScth di_root = DI_NODE_NIL; 99*a08731ecScth } 100*a08731ecScth 101*a08731ecScth nfs_tried = 0; 1027c478bd9Sstevel@tonic-gate } 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* 105*a08731ecScth * Find information for (driver, instunit) device: return zero on failure. 1067c478bd9Sstevel@tonic-gate * 107*a08731ecScth * NOTE: Failure of drvinstunit2dev works out OK for the caller if the kstat 108*a08731ecScth * name is the same as public name: the caller will just use kstat name. 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate static int 111*a08731ecScth drvinstunit2dev(char *driver, int instunit, 112*a08731ecScth char **devpathp, char **adevpathp, char **devidp, int *isdiskp) 1137c478bd9Sstevel@tonic-gate { 114*a08731ecScth int instance; 115*a08731ecScth minor_match_t **mma; 116*a08731ecScth minor_match_t *mm; 117*a08731ecScth char *devpath; 118*a08731ecScth char *devid; 119*a08731ecScth char *a, *s; 120*a08731ecScth int mdsetno; 121*a08731ecScth char *mdsetname = NULL; 122*a08731ecScth char amdsetname[MAXPATHLEN]; 123*a08731ecScth char *devicespath; 124*a08731ecScth di_node_t node; 125*a08731ecScth 126*a08731ecScth 127*a08731ecScth /* setup "no result" return values */ 128*a08731ecScth if (devpathp) 129*a08731ecScth *devpathp = NULL; 130*a08731ecScth if (adevpathp) 131*a08731ecScth *adevpathp = NULL; 132*a08731ecScth if (devidp) 133*a08731ecScth *devidp = NULL; 134*a08731ecScth if (isdiskp) 135*a08731ecScth *isdiskp = 0; 136*a08731ecScth 137*a08731ecScth /* take <driver><instance><minor_name> snapshot if not established */ 138*a08731ecScth if (di_dim == NULL) { 139*a08731ecScth di_dim = di_dim_init(); 140*a08731ecScth if (di_dim == NULL) 1417c478bd9Sstevel@tonic-gate return (0); 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* 145*a08731ecScth * Determine if 'instunit' is an 'instance' or 'unit' based on the 146*a08731ecScth * 'driver'. The current code only detects 'md' metadevice 'units', 147*a08731ecScth * and defaults to 'instance' for everything else. 148*a08731ecScth * 149*a08731ecScth * For a metadevice, 'driver' is either "md" or "<setno>/md". 1507c478bd9Sstevel@tonic-gate */ 151*a08731ecScth s = strstr(driver, "/md"); 152*a08731ecScth if ((strcmp(driver, "md") == 0) || 153*a08731ecScth (s && isdigit(*driver) && (strcmp(s, "/md") == 0))) { 1547c478bd9Sstevel@tonic-gate /* 155*a08731ecScth * "md" unit: Special case translation of "md" kstat names. 156*a08731ecScth * For the local set the kstat name is "md<unit>", and for 157*a08731ecScth * a shared set the kstat name is "<setno>/md<unit>": we map 158*a08731ecScth * these to the minor paths "/pseudo/md@0:<unit>,blk" and 159*a08731ecScth * "/pseudo/md@0:<set>,<unit>,blk" respectively. 1607c478bd9Sstevel@tonic-gate */ 161*a08731ecScth if (isdigit(*driver)) { 162*a08731ecScth mdsetno = atoi(driver); 163*a08731ecScth 164*a08731ecScth /* convert setno to setname */ 165*a08731ecScth mdsetname = mdsetno2name(mdsetno); 166*a08731ecScth } else 167*a08731ecScth mdsetno = 0; 168*a08731ecScth 169*a08731ecScth driver = "md"; 170*a08731ecScth instance = 0; 171*a08731ecScth mma = mma_md; /* metadevice dynamic minor */ 172*a08731ecScth (void) snprintf(md_minor_name, sizeof (md_minor_name), 173*a08731ecScth "%d,%d,blk", mdsetno, instunit); 174*a08731ecScth } else { 175*a08731ecScth instance = instunit; 176*a08731ecScth mma = mma_disk_tape; /* disk/tape minors */ 177*a08731ecScth } 178*a08731ecScth 179*a08731ecScth /* Try to find a minor_match that works */ 180*a08731ecScth for (mm = *mma++; mm; mm = *mma++) { 181*a08731ecScth if ((devpath = di_dim_path_dev(di_dim, 182*a08731ecScth driver, instance, mm->minor_name)) != NULL) 183*a08731ecScth break; 184*a08731ecScth } 185*a08731ecScth if (devpath == NULL) 186*a08731ecScth return (0); 187*a08731ecScth 188*a08731ecScth /* 189*a08731ecScth * At this point we have a devpath result. Return the information about 190*a08731ecScth * the result that the caller is asking for. 191*a08731ecScth */ 192*a08731ecScth if (devpathp) /* devpath */ 193*a08731ecScth *devpathp = safe_strdup(devpath); 194*a08731ecScth 195*a08731ecScth if (adevpathp) { /* abbreviated devpath */ 196*a08731ecScth if (mm->minor_isdisk) { 197*a08731ecScth /* 198*a08731ecScth * For disks we return the last component (with 199*a08731ecScth * trailing "s#" or "p#" stripped off for disks). 200*a08731ecScth * For example for devpath of "/dev/dsk/c0t0d0s0" the 201*a08731ecScth * abbreviated devpath would be "c0t0d0". 202*a08731ecScth */ 203*a08731ecScth a = strrchr(devpath, '/'); 204*a08731ecScth if (a == NULL) { 205*a08731ecScth free(devpath); 206*a08731ecScth return (0); 207*a08731ecScth } 208*a08731ecScth a++; 209*a08731ecScth s = strrchr(a, 's'); 210*a08731ecScth if (s == NULL) { 211*a08731ecScth s = strrchr(a, 'p'); 212*a08731ecScth if (s == NULL) { 213*a08731ecScth free(devpath); 214*a08731ecScth return (0); 215*a08731ecScth } 216*a08731ecScth } 217*a08731ecScth /* don't include slice information in devpath */ 218*a08731ecScth *s = '\0'; 219*a08731ecScth } else { 220*a08731ecScth /* 221*a08731ecScth * remove "/dev/", and "/dsk/", from 'devpath' (like 222*a08731ecScth * "/dev/md/dsk/d0") to form the abbreviated devpath 223*a08731ecScth * (like "md/d0"). 224*a08731ecScth */ 225*a08731ecScth if ((s = strstr(devpath, "/dev/")) != NULL) 226*a08731ecScth (void) strcpy(s + 1, s + 5); 227*a08731ecScth if ((s = strstr(devpath, "/dsk/")) != NULL) 228*a08731ecScth (void) strcpy(s + 1, s + 5); 229*a08731ecScth 230*a08731ecScth /* 231*a08731ecScth * If we have an mdsetname, convert abbreviated setno 232*a08731ecScth * notation (like "md/shared/1/d0" to abbreviated 233*a08731ecScth * setname notation (like "md/red/d0"). 234*a08731ecScth */ 235*a08731ecScth if (mdsetname) { 236*a08731ecScth a = strrchr(devpath, '/'); 237*a08731ecScth (void) snprintf(amdsetname, sizeof (amdsetname), 238*a08731ecScth "md/%s%s", mdsetname, a); 239*a08731ecScth free(mdsetname); 240*a08731ecScth a = amdsetname; 241*a08731ecScth } else { 242*a08731ecScth if (*devpath == '/') 243*a08731ecScth a = devpath + 1; 2447c478bd9Sstevel@tonic-gate else 245*a08731ecScth a = devpath; 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate } 248*a08731ecScth *adevpathp = safe_strdup(a); 249*a08731ecScth } 250*a08731ecScth 251*a08731ecScth if (devidp) { /* lookup the devid */ 252*a08731ecScth /* take snapshots if not established */ 253*a08731ecScth if (di_root == DI_NODE_NIL) { 254*a08731ecScth di_root = di_init("/", DINFOCACHE); 255*a08731ecScth } 256*a08731ecScth if (di_root) { 257*a08731ecScth /* get path to /devices devinfo node */ 258*a08731ecScth devicespath = di_dim_path_devices(di_dim, 259*a08731ecScth driver, instance, NULL); 260*a08731ecScth if (devicespath) { 261*a08731ecScth /* find the node in the snapshot */ 262*a08731ecScth node = di_lookup_node(di_root, devicespath); 263*a08731ecScth free(devicespath); 264*a08731ecScth 265*a08731ecScth /* and lookup devid property on the node */ 266*a08731ecScth if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, 267*a08731ecScth DEVID_PROP_NAME, &devid) != -1) 268*a08731ecScth *devidp = devid; 269*a08731ecScth } 270*a08731ecScth } 271*a08731ecScth } 272*a08731ecScth 273*a08731ecScth if (isdiskp) 274*a08731ecScth *isdiskp = mm->minor_isdisk; 275*a08731ecScth 276*a08731ecScth free(devpath); 277*a08731ecScth return (1); /* success */ 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate /* 281*a08731ecScth * Find/create a disk_list entry for "<driver><instunit>" given a kstat name. 282*a08731ecScth * The basic format of a kstat name is "<driver><instunit>,<partition>". The 283*a08731ecScth * <instunit> is a base10 number, and the ",<partition>" part is optional. 284*a08731ecScth * 285*a08731ecScth * NOTE: In the case of non-local metadevices, the format of "<driver>" in 286*a08731ecScth * a kstat name is acutally "<setno>/md". 2877c478bd9Sstevel@tonic-gate */ 288*a08731ecScth disk_list_t * 289*a08731ecScth lookup_ks_name(char *ks_name, int want_devid) 2907c478bd9Sstevel@tonic-gate { 291*a08731ecScth char *p; 292*a08731ecScth int len; 293*a08731ecScth char driver[MAXNAMELEN]; 294*a08731ecScth int instunit; 295*a08731ecScth disk_list_t **dlhp; /* disklist head */ 2967c478bd9Sstevel@tonic-gate disk_list_t *entry; 297*a08731ecScth char *devpath; 298*a08731ecScth char *adevpath = NULL; 299*a08731ecScth char *devid = NULL; 300*a08731ecScth int isdisk; 3017c478bd9Sstevel@tonic-gate 302*a08731ecScth /* 303*a08731ecScth * Extract <driver> and <instunit> from kstat name. 304*a08731ecScth * Filter out illegal forms (like all digits). 305*a08731ecScth */ 306*a08731ecScth if ((ks_name == NULL) || (*ks_name == 0) || 307*a08731ecScth (strspn(ks_name, "0123456789") == strlen(ks_name))) 308*a08731ecScth return (NULL); 309*a08731ecScth p = strrchr(ks_name, ','); /* start of ",partition" */ 310*a08731ecScth if (p == NULL) 311*a08731ecScth p = &ks_name[strlen(ks_name) - 1]; /* last char */ 312*a08731ecScth else 313*a08731ecScth p--; /* before ",partition" */ 314*a08731ecScth 315*a08731ecScth while ((p >= ks_name) && isdigit(*p)) 316*a08731ecScth p--; /* backwards over digits */ 317*a08731ecScth p++; /* start of instunit */ 318*a08731ecScth if ((*p == '\0') || (*p == ',')) 319*a08731ecScth return (NULL); /* no <instunit> */ 320*a08731ecScth len = p - ks_name; 321*a08731ecScth (void) strncpy(driver, ks_name, len); 322*a08731ecScth driver[len] = '\0'; 323*a08731ecScth instunit = atoi(p); 324*a08731ecScth 325*a08731ecScth /* hash and search for existing disklist entry */ 326*a08731ecScth dlhp = &disklist[instunit & (DISKLIST_MOD - 1)]; 327*a08731ecScth for (entry = *dlhp; entry; entry = entry->next) { 328*a08731ecScth if ((strcmp(entry->dtype, driver) == 0) && 329*a08731ecScth (entry->dnum == instunit)) { 330*a08731ecScth return (entry); 331*a08731ecScth } 332*a08731ecScth } 333*a08731ecScth 334*a08731ecScth /* not found, try to get dev information */ 335*a08731ecScth if (drvinstunit2dev(driver, instunit, &devpath, &adevpath, 336*a08731ecScth want_devid ? &devid : NULL, &isdisk) == 0) { 337*a08731ecScth return (NULL); 338*a08731ecScth } 339*a08731ecScth 340*a08731ecScth /* and make a new disklist entry ... */ 3417c478bd9Sstevel@tonic-gate entry = safe_alloc(sizeof (disk_list_t)); 342*a08731ecScth entry->dtype = safe_strdup(driver); 343*a08731ecScth entry->dnum = instunit; 344*a08731ecScth entry->dname = devpath; 345*a08731ecScth entry->dsk = adevpath; 346*a08731ecScth entry->devidstr = devid; 347*a08731ecScth entry->flags = 0; 348*a08731ecScth if (isdisk) { 349*a08731ecScth entry->flags |= SLICES_OK; 350*a08731ecScth #if defined(__i386) 351*a08731ecScth entry->flags |= PARTITIONS_OK; 352*a08731ecScth #endif 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate entry->seen = 0; 355*a08731ecScth 356*a08731ecScth /* add new entry to head of instunit hashed list */ 357*a08731ecScth entry->next = *dlhp; 358*a08731ecScth *dlhp = entry; 3597c478bd9Sstevel@tonic-gate return (entry); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate /* 363*a08731ecScth * Convert metadevice setno to setname by looking in /dev/md for symlinks 364*a08731ecScth * that point to "shared/setno" - the name of such a symlink is the setname. 365*a08731ecScth * The caller is responsible for freeing the returned string. 3667c478bd9Sstevel@tonic-gate */ 3677c478bd9Sstevel@tonic-gate static char * 368*a08731ecScth mdsetno2name(int setno) 3697c478bd9Sstevel@tonic-gate { 370*a08731ecScth char setlink[MAXPATHLEN + 1]; 371*a08731ecScth char link[MAXPATHLEN + 1]; 372*a08731ecScth char path[MAXPATHLEN + 1]; 373*a08731ecScth char *p; 374*a08731ecScth DIR *dirp; 375*a08731ecScth struct dirent *dp; 376*a08731ecScth size_t len; 377*a08731ecScth char *mdsetname = NULL; 3787c478bd9Sstevel@tonic-gate 379*a08731ecScth /* we are looking for a link to setlink */ 380*a08731ecScth (void) snprintf(setlink, MAXPATHLEN, "shared/%d", setno); 3817c478bd9Sstevel@tonic-gate 382*a08731ecScth /* in the directory /dev/md */ 383*a08731ecScth (void) strcpy(path, "/dev/md/"); 384*a08731ecScth p = path + strlen(path); 385*a08731ecScth dirp = opendir(path); 386*a08731ecScth if (dirp == NULL) 3877c478bd9Sstevel@tonic-gate return (NULL); 3887c478bd9Sstevel@tonic-gate 389*a08731ecScth /* loop through /dev/md directory entries */ 390*a08731ecScth while ((dp = readdir(dirp)) != NULL) { 3917c478bd9Sstevel@tonic-gate 392*a08731ecScth /* doing a readlink of entry (fails for non-symlinks) */ 393*a08731ecScth *p = '\0'; 394*a08731ecScth (void) strcpy(p, dp->d_name); 395*a08731ecScth if ((len = readlink(path, link, MAXPATHLEN)) == (size_t)-1) 396*a08731ecScth continue; 3977c478bd9Sstevel@tonic-gate 398*a08731ecScth /* and looking for a link to setlink */ 399*a08731ecScth link[len] = '\0'; 400*a08731ecScth if (strcmp(setlink, link)) 401*a08731ecScth continue; 402*a08731ecScth 403*a08731ecScth /* found- name of link is the setname */ 404*a08731ecScth mdsetname = safe_strdup(dp->d_name); 4057c478bd9Sstevel@tonic-gate break; 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate 408*a08731ecScth (void) closedir(dirp); 409*a08731ecScth return (mdsetname); 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate char * 4137c478bd9Sstevel@tonic-gate lookup_nfs_name(char *ks, kstat_ctl_t *kc) 4147c478bd9Sstevel@tonic-gate { 4157c478bd9Sstevel@tonic-gate uint_t minor; 4167c478bd9Sstevel@tonic-gate char *host, *path; 4177c478bd9Sstevel@tonic-gate char *cp; 4187c478bd9Sstevel@tonic-gate char *rstr = 0; 4197c478bd9Sstevel@tonic-gate size_t len; 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate if (sscanf(ks, "nfs%u", &minor) == 1) { 4227c478bd9Sstevel@tonic-gate retry: 4237c478bd9Sstevel@tonic-gate cp = get_nfs_by_minor(minor); 4247c478bd9Sstevel@tonic-gate if (cp) { 4257c478bd9Sstevel@tonic-gate if (strchr(cp, ',') == NULL) { 4267c478bd9Sstevel@tonic-gate rstr = safe_strdup(cp); 4277c478bd9Sstevel@tonic-gate return (rstr); 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate host = cur_hostname(minor, kc); 4307c478bd9Sstevel@tonic-gate if (host) { 4317c478bd9Sstevel@tonic-gate if (*host) { 4327c478bd9Sstevel@tonic-gate path = cur_special(host, cp); 4337c478bd9Sstevel@tonic-gate if (path) { 4347c478bd9Sstevel@tonic-gate len = strlen(host); 4357c478bd9Sstevel@tonic-gate len += strlen(path); 4367c478bd9Sstevel@tonic-gate len += 2; 4377c478bd9Sstevel@tonic-gate rstr = safe_alloc(len); 4387c478bd9Sstevel@tonic-gate (void) snprintf(rstr, len, 4397c478bd9Sstevel@tonic-gate "%s:%s", host, path); 4407c478bd9Sstevel@tonic-gate } else { 4417c478bd9Sstevel@tonic-gate rstr = safe_strdup(cp); 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate } else { 4447c478bd9Sstevel@tonic-gate rstr = safe_strdup(ks); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate free(host); 4477c478bd9Sstevel@tonic-gate } else { 4487c478bd9Sstevel@tonic-gate rstr = safe_strdup(cp); 4497c478bd9Sstevel@tonic-gate } 450*a08731ecScth } else if (nfs_tried == 0) { 451*a08731ecScth nfs_tried = 1; 4527c478bd9Sstevel@tonic-gate do_mnttab(); 4537c478bd9Sstevel@tonic-gate goto retry; 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate return (rstr); 4577c478bd9Sstevel@tonic-gate } 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate static char * 4607c478bd9Sstevel@tonic-gate get_nfs_by_minor(uint_t minor) 4617c478bd9Sstevel@tonic-gate { 4627c478bd9Sstevel@tonic-gate mnt_t *localnfs; 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate localnfs = nfs; 4657c478bd9Sstevel@tonic-gate while (localnfs) { 4667c478bd9Sstevel@tonic-gate if (localnfs->minor == minor) { 4677c478bd9Sstevel@tonic-gate return (localnfs->device_name); 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate localnfs = localnfs->next; 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate return (0); 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate /* 4757c478bd9Sstevel@tonic-gate * Read the cur_hostname from the mntinfo kstat 4767c478bd9Sstevel@tonic-gate */ 4777c478bd9Sstevel@tonic-gate static char * 4787c478bd9Sstevel@tonic-gate cur_hostname(uint_t minor, kstat_ctl_t *kc) 4797c478bd9Sstevel@tonic-gate { 4807c478bd9Sstevel@tonic-gate kstat_t *ksp; 4817c478bd9Sstevel@tonic-gate static struct mntinfo_kstat mik; 4827c478bd9Sstevel@tonic-gate char *rstr; 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 4857c478bd9Sstevel@tonic-gate if (ksp->ks_type != KSTAT_TYPE_RAW) 4867c478bd9Sstevel@tonic-gate continue; 4877c478bd9Sstevel@tonic-gate if (ksp->ks_instance != minor) 4887c478bd9Sstevel@tonic-gate continue; 4897c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_module, "nfs")) 4907c478bd9Sstevel@tonic-gate continue; 4917c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_name, "mntinfo")) 4927c478bd9Sstevel@tonic-gate continue; 4937c478bd9Sstevel@tonic-gate if (ksp->ks_flags & KSTAT_FLAG_INVALID) 4947c478bd9Sstevel@tonic-gate return (NULL); 4957c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, &mik) == -1) 4967c478bd9Sstevel@tonic-gate return (NULL); 4977c478bd9Sstevel@tonic-gate rstr = safe_strdup(mik.mik_curserver); 4987c478bd9Sstevel@tonic-gate return (rstr); 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate return (NULL); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate /* 5047c478bd9Sstevel@tonic-gate * Given the hostname of the mounted server, extract the server 5057c478bd9Sstevel@tonic-gate * mount point from the mnttab string. 5067c478bd9Sstevel@tonic-gate * 5077c478bd9Sstevel@tonic-gate * Common forms: 5087c478bd9Sstevel@tonic-gate * server1,server2,server3:/path 5097c478bd9Sstevel@tonic-gate * server1:/path,server2:/path 5107c478bd9Sstevel@tonic-gate * or a hybrid of the two 5117c478bd9Sstevel@tonic-gate */ 5127c478bd9Sstevel@tonic-gate static char * 5137c478bd9Sstevel@tonic-gate cur_special(char *hostname, char *special) 5147c478bd9Sstevel@tonic-gate { 5157c478bd9Sstevel@tonic-gate char *cp; 5167c478bd9Sstevel@tonic-gate char *path; 5177c478bd9Sstevel@tonic-gate size_t hlen = strlen(hostname); 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate /* 5207c478bd9Sstevel@tonic-gate * find hostname in string 5217c478bd9Sstevel@tonic-gate */ 5227c478bd9Sstevel@tonic-gate again: 5237c478bd9Sstevel@tonic-gate if ((cp = strstr(special, hostname)) == NULL) 5247c478bd9Sstevel@tonic-gate return (NULL); 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate /* 5277c478bd9Sstevel@tonic-gate * hostname must be followed by ',' or ':' 5287c478bd9Sstevel@tonic-gate */ 5297c478bd9Sstevel@tonic-gate if (cp[hlen] != ',' && cp[hlen] != ':') { 5307c478bd9Sstevel@tonic-gate special = &cp[hlen]; 5317c478bd9Sstevel@tonic-gate goto again; 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate /* 5357c478bd9Sstevel@tonic-gate * If hostname is followed by a ',' eat all characters until a ':' 5367c478bd9Sstevel@tonic-gate */ 5377c478bd9Sstevel@tonic-gate cp = &cp[hlen]; 5387c478bd9Sstevel@tonic-gate if (*cp == ',') { 5397c478bd9Sstevel@tonic-gate cp++; 5407c478bd9Sstevel@tonic-gate while (*cp != ':') { 5417c478bd9Sstevel@tonic-gate if (*cp == NULL) 5427c478bd9Sstevel@tonic-gate return (NULL); 5437c478bd9Sstevel@tonic-gate cp++; 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate path = ++cp; /* skip ':' */ 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate /* 5497c478bd9Sstevel@tonic-gate * path is terminated by either 0, or space or ',' 5507c478bd9Sstevel@tonic-gate */ 5517c478bd9Sstevel@tonic-gate while (*cp) { 5527c478bd9Sstevel@tonic-gate if (isspace(*cp) || *cp == ',') { 5537c478bd9Sstevel@tonic-gate *cp = NULL; 5547c478bd9Sstevel@tonic-gate return (path); 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate cp++; 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate return (path); 5597c478bd9Sstevel@tonic-gate } 560