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 */ 21*e373b6e4SYuri Pankov 227c478bd9Sstevel@tonic-gate /* 234e78ab0bScth * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*e373b6e4SYuri Pankov * Copyright 2016 Nexenta Systems, Inc. 267c478bd9Sstevel@tonic-gate */ 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> 5237fbbce5Scth #include <strings.h> 537c478bd9Sstevel@tonic-gate #include <unistd.h> 547c478bd9Sstevel@tonic-gate #include <errno.h> 557c478bd9Sstevel@tonic-gate #include <devid.h> 5637fbbce5Scth #include <sys/scsi/adapters/scsi_vhci.h> 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate #include "dsr.h" 597c478bd9Sstevel@tonic-gate #include "statcommon.h" 607c478bd9Sstevel@tonic-gate 6137fbbce5Scth /* where we get kstat name translation information from */ 6237fbbce5Scth static di_node_t di_root; /* from di_init: for devid */ 6337fbbce5Scth static di_dim_t di_dim; /* from di_dim_init: for /dev names */ 6437fbbce5Scth static int scsi_vhci_fd = -1; /* from scsi_vhci: for mpxio path */ 6537fbbce5Scth 6637fbbce5Scth /* disk/tape/misc info */ 67a08731ecScth typedef struct { 68a08731ecScth char *minor_name; 69a08731ecScth int minor_isdisk; 70a08731ecScth } minor_match_t; 71a08731ecScth static minor_match_t mm_disk = {"a", 1}; 72a08731ecScth static minor_match_t mm_tape = {"", 0}; 7337fbbce5Scth static minor_match_t mm_misc = {"0", 0}; 7437fbbce5Scth static minor_match_t *mma_disk_tape_misc[] = 7537fbbce5Scth {&mm_disk, &mm_tape, &mm_misc, NULL}; 76*e373b6e4SYuri Pankov #define DISKLIST_MOD 256 /* ^2 instance mod hash */ 77a08731ecScth static disk_list_t *disklist[DISKLIST_MOD]; 787c478bd9Sstevel@tonic-gate 7937fbbce5Scth 80a08731ecScth /* nfs info */ 81a08731ecScth extern kstat_ctl_t *kc; 82a08731ecScth extern mnt_t *nfs; 83a08731ecScth static int nfs_tried; 847c478bd9Sstevel@tonic-gate static char *get_nfs_by_minor(uint_t); 857c478bd9Sstevel@tonic-gate static char *cur_hostname(uint_t, kstat_ctl_t *); 867c478bd9Sstevel@tonic-gate static char *cur_special(char *, char *); 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate /* 89a08731ecScth * Clear the snapshot so a cache miss in lookup_ks_name() will cause a fresh 90*e373b6e4SYuri Pankov * snapshot in drvinstpart2dev(). 917c478bd9Sstevel@tonic-gate */ 92a08731ecScth void 93a08731ecScth cleanup_iodevs_snapshot() 947c478bd9Sstevel@tonic-gate { 95a08731ecScth if (di_dim) { 96a08731ecScth di_dim_fini(di_dim); 97a08731ecScth di_dim = NULL; 98a08731ecScth } 997c478bd9Sstevel@tonic-gate 100a08731ecScth if (di_root) { 101a08731ecScth di_fini(di_root); 102a08731ecScth di_root = DI_NODE_NIL; 103a08731ecScth } 104a08731ecScth 105a08731ecScth nfs_tried = 0; 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate /* 109*e373b6e4SYuri Pankov * Find information for (driver, instance) device: return zero on failure. 1107c478bd9Sstevel@tonic-gate * 111*e373b6e4SYuri Pankov * NOTE: Failure of drvinstpart2dev works out OK for the caller if the kstat 112a08731ecScth * name is the same as public name: the caller will just use kstat name. 1137c478bd9Sstevel@tonic-gate */ 1147c478bd9Sstevel@tonic-gate static int 115*e373b6e4SYuri Pankov drvinstpart2dev(char *driver, int instance, char *part, 11637fbbce5Scth char **devpathp, char **adevpathp, char **devidp) 1177c478bd9Sstevel@tonic-gate { 118*e373b6e4SYuri Pankov minor_match_t *mm, **mma = mma_disk_tape_misc; 119a08731ecScth char *devpath; 120a08731ecScth char *devid; 121a08731ecScth char *devicespath; 122a08731ecScth di_node_t node; 123a08731ecScth 124a08731ecScth /* setup "no result" return values */ 125*e373b6e4SYuri Pankov if (devpathp != NULL) 126a08731ecScth *devpathp = NULL; 127*e373b6e4SYuri Pankov if (adevpathp != NULL) 128a08731ecScth *adevpathp = NULL; 129*e373b6e4SYuri Pankov if (devidp != NULL) 130a08731ecScth *devidp = NULL; 131a08731ecScth 132*e373b6e4SYuri Pankov /* take <driver><instance><minor> snapshot if not established */ 133a08731ecScth if (di_dim == NULL) { 134a08731ecScth di_dim = di_dim_init(); 135a08731ecScth if (di_dim == NULL) 1367c478bd9Sstevel@tonic-gate return (0); 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate 139*e373b6e4SYuri Pankov if (part != NULL) { 14037fbbce5Scth devpath = di_dim_path_dev(di_dim, driver, instance, part); 14137fbbce5Scth } else { 142a08731ecScth /* Try to find a minor_match that works */ 143*e373b6e4SYuri Pankov for (mm = *mma++; mm != NULL; mm = *mma++) { 144a08731ecScth if ((devpath = di_dim_path_dev(di_dim, 145a08731ecScth driver, instance, mm->minor_name)) != NULL) 146a08731ecScth break; 147a08731ecScth } 14837fbbce5Scth } 149a08731ecScth if (devpath == NULL) 150a08731ecScth return (0); 151a08731ecScth 152a08731ecScth /* 153a08731ecScth * At this point we have a devpath result. Return the information about 154a08731ecScth * the result that the caller is asking for. 155a08731ecScth */ 156*e373b6e4SYuri Pankov if (devpathp != NULL) /* devpath */ 157a08731ecScth *devpathp = safe_strdup(devpath); 158a08731ecScth 159*e373b6e4SYuri Pankov if (adevpathp != NULL) { /* abbreviated devpath */ 160*e373b6e4SYuri Pankov char *a; 161*e373b6e4SYuri Pankov 162*e373b6e4SYuri Pankov a = strrchr(devpath, '/'); 163*e373b6e4SYuri Pankov if (a == NULL) { 164*e373b6e4SYuri Pankov free(devpath); 165*e373b6e4SYuri Pankov return (0); 166*e373b6e4SYuri Pankov } 167*e373b6e4SYuri Pankov a++; 168*e373b6e4SYuri Pankov if (part == NULL && mm->minor_isdisk) { 169a08731ecScth /* 17037fbbce5Scth * For disk kstats without a partition we return the 17137fbbce5Scth * last component with trailing "s#" or "p#" stripped 17237fbbce5Scth * off (i.e. partition/slice information is removed). 173a08731ecScth * For example for devpath of "/dev/dsk/c0t0d0s0" the 174a08731ecScth * abbreviated devpath would be "c0t0d0". 175a08731ecScth */ 176*e373b6e4SYuri Pankov char *s; 177*e373b6e4SYuri Pankov 178*e373b6e4SYuri Pankov if ((s = strrchr(a, 's')) == NULL && 179*e373b6e4SYuri Pankov (s = strrchr(a, 'p')) == NULL) { 180a08731ecScth free(devpath); 181a08731ecScth return (0); 182a08731ecScth } 183a08731ecScth /* don't include slice information in devpath */ 184a08731ecScth *s = '\0'; 1857c478bd9Sstevel@tonic-gate } 186a08731ecScth *adevpathp = safe_strdup(a); 187a08731ecScth } 188a08731ecScth 189*e373b6e4SYuri Pankov if (devidp != NULL) { /* lookup the devid */ 19037fbbce5Scth /* take snapshot if not established */ 191*e373b6e4SYuri Pankov if (di_root == DI_NODE_NIL) 192a08731ecScth di_root = di_init("/", DINFOCACHE); 193*e373b6e4SYuri Pankov if (di_root != NULL) { 194a08731ecScth /* get path to /devices devinfo node */ 195a08731ecScth devicespath = di_dim_path_devices(di_dim, 196a08731ecScth driver, instance, NULL); 197a08731ecScth if (devicespath) { 198a08731ecScth /* find the node in the snapshot */ 199a08731ecScth node = di_lookup_node(di_root, devicespath); 200a08731ecScth free(devicespath); 201a08731ecScth 202a08731ecScth /* and lookup devid property on the node */ 203a08731ecScth if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, 204a08731ecScth DEVID_PROP_NAME, &devid) != -1) 205a08731ecScth *devidp = devid; 206a08731ecScth } 207a08731ecScth } 208a08731ecScth } 209a08731ecScth 210a08731ecScth free(devpath); 211a08731ecScth return (1); /* success */ 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* 21537fbbce5Scth * Do <pid> to 'target-port' translation 21637fbbce5Scth */ 21737fbbce5Scth static int 21837fbbce5Scth drvpid2port(uint_t pid, char **target_portp) 21937fbbce5Scth { 22037fbbce5Scth sv_iocdata_t ioc; 22137fbbce5Scth char target_port[MAXNAMELEN]; 22237fbbce5Scth 22337fbbce5Scth /* setup "no result" return values */ 22437fbbce5Scth *target_portp = NULL; 22537fbbce5Scth 22637fbbce5Scth /* open scsi_vhci if not already done */ 22737fbbce5Scth if (scsi_vhci_fd == -1) { 22837fbbce5Scth scsi_vhci_fd = open("/devices/scsi_vhci:devctl", O_RDONLY); 22937fbbce5Scth if (scsi_vhci_fd == -1) 23037fbbce5Scth return (0); /* failure */ 23137fbbce5Scth } 23237fbbce5Scth 23337fbbce5Scth /* 23437fbbce5Scth * Perform ioctl for <pid> -> 'target-port' translation. 23537fbbce5Scth * 23637fbbce5Scth * NOTE: it is legimite for this ioctl to fail for transports 23737fbbce5Scth * that use mpxio, but don't set a 'target-port' pathinfo property. 23837fbbce5Scth * On failure we return the the "<pid>" as the target port string. 23937fbbce5Scth */ 24037fbbce5Scth bzero(&ioc, sizeof (sv_iocdata_t)); 24137fbbce5Scth ioc.buf_elem = pid; 24237fbbce5Scth ioc.addr = target_port; 24337fbbce5Scth if (ioctl(scsi_vhci_fd, SCSI_VHCI_GET_TARGET_LONGNAME, &ioc) < 0) { 24437fbbce5Scth (void) snprintf(target_port, sizeof (target_port), "%d", pid); 24537fbbce5Scth } 24637fbbce5Scth 24737fbbce5Scth *target_portp = safe_strdup(target_port); 24837fbbce5Scth return (1); /* success */ 24937fbbce5Scth } 25037fbbce5Scth 25137fbbce5Scth /* 252*e373b6e4SYuri Pankov * Find/create a disk_list entry for the given kstat name. 25337fbbce5Scth * The basic format of a kstat name is 25437fbbce5Scth * 255*e373b6e4SYuri Pankov * "<driver><instance>[.<pid>.<phci-driver><instance>][,<partition>]". 25637fbbce5Scth * 257*e373b6e4SYuri Pankov * The <instance> is a decimal number. The ".<pid>.<phci-driver><instance>", 25837fbbce5Scth * which describes mpxio path stat information, and ",<partition>" parts are 25937fbbce5Scth * optional. The <pid> consists of the letter 't' followed by a decimal number. 26037fbbce5Scth * When available, we use the <pid> to find the 'target-port' via ioctls to 26137fbbce5Scth * the scsi_vhci driver. 2627c478bd9Sstevel@tonic-gate */ 263a08731ecScth disk_list_t * 264a08731ecScth lookup_ks_name(char *ks_name, int want_devid) 2657c478bd9Sstevel@tonic-gate { 26637fbbce5Scth char *pidp; /* ".<pid>... */ 26737fbbce5Scth char *part; /* ",partition... */ 26837fbbce5Scth char *initiator; /* ".<phci-driver>... */ 269a08731ecScth char *p; 270a08731ecScth int len; 27137fbbce5Scth char driver[KSTAT_STRLEN]; 272*e373b6e4SYuri Pankov int instance; 273a08731ecScth disk_list_t **dlhp; /* disklist head */ 2747c478bd9Sstevel@tonic-gate disk_list_t *entry; 27537fbbce5Scth char *devpath = NULL; 276a08731ecScth char *adevpath = NULL; 277a08731ecScth char *devid = NULL; 27837fbbce5Scth int pid; 27937fbbce5Scth char *target_port = NULL; 28037fbbce5Scth char portform[MAXPATHLEN]; 2817c478bd9Sstevel@tonic-gate 282*e373b6e4SYuri Pankov /* Filter out illegal forms (like all digits) */ 283*e373b6e4SYuri Pankov if (ks_name == NULL || *ks_name == '\0' || 284*e373b6e4SYuri Pankov strspn(ks_name, "0123456789") == strlen(ks_name)) 28537fbbce5Scth goto fail; 28637fbbce5Scth 28737fbbce5Scth /* parse ks_name to create new entry */ 28837fbbce5Scth pidp = strchr(ks_name, '.'); /* start of ".<pid>" */ 28937fbbce5Scth initiator = strrchr(ks_name, '.'); /* start of ".<pHCI-driver>" */ 290*e373b6e4SYuri Pankov if (pidp != NULL && pidp == initiator) /* can't have same start */ 29137fbbce5Scth goto fail; 29237fbbce5Scth 29337fbbce5Scth part = strchr(ks_name, ','); /* start of ",<partition>" */ 29437fbbce5Scth p = strchr(ks_name, ':'); /* start of ":<partition>" */ 295*e373b6e4SYuri Pankov if (part != NULL && p != NULL) 29637fbbce5Scth goto fail; /* can't have both */ 297*e373b6e4SYuri Pankov if (p != NULL) 29837fbbce5Scth part = p; 299*e373b6e4SYuri Pankov if (part != NULL && pidp != NULL) 30037fbbce5Scth goto fail; /* <pid> and partition: bad */ 30137fbbce5Scth 302*e373b6e4SYuri Pankov p = (part != NULL) ? part : pidp; 303a08731ecScth if (p == NULL) 304a08731ecScth p = &ks_name[strlen(ks_name) - 1]; /* last char */ 305a08731ecScth else 30637fbbce5Scth p--; /* before ',' or '.' */ 307a08731ecScth 308a08731ecScth while ((p >= ks_name) && isdigit(*p)) 309a08731ecScth p--; /* backwards over digits */ 310*e373b6e4SYuri Pankov p++; /* start of instance */ 31137fbbce5Scth if ((*p == '\0') || (*p == ',') || (*p == '.') || (*p == ':')) 312*e373b6e4SYuri Pankov goto fail; /* no <instance> */ 313a08731ecScth len = p - ks_name; 314a08731ecScth (void) strncpy(driver, ks_name, len); 315a08731ecScth driver[len] = '\0'; 316*e373b6e4SYuri Pankov instance = atoi(p); 317*e373b6e4SYuri Pankov if (part != NULL) 31837fbbce5Scth part++; /* skip ',' */ 319a08731ecScth 320*e373b6e4SYuri Pankov /* hash by instance and search for existing entry */ 321*e373b6e4SYuri Pankov dlhp = &disklist[instance & (DISKLIST_MOD - 1)]; 322a08731ecScth for (entry = *dlhp; entry; entry = entry->next) { 323*e373b6e4SYuri Pankov if (strcmp(entry->ks_name, ks_name) == 0) 324a08731ecScth return (entry); 325a08731ecScth } 326a08731ecScth 32737fbbce5Scth /* not found, translate kstat_name components and create new entry */ 32837fbbce5Scth 32937fbbce5Scth /* translate kstat_name dev information */ 330*e373b6e4SYuri Pankov if (drvinstpart2dev(driver, instance, part, 331*e373b6e4SYuri Pankov &devpath, &adevpath, want_devid ? &devid : NULL) == 0) 33237fbbce5Scth goto fail; 333a08731ecScth 33437fbbce5Scth /* parse and translate path information */ 335*e373b6e4SYuri Pankov if (pidp != NULL) { 33637fbbce5Scth /* parse path information: ".t#.<phci-driver><instance>" */ 33737fbbce5Scth pidp++; /* skip '.' */ 33837fbbce5Scth initiator++; /* skip '.' */ 339*e373b6e4SYuri Pankov if (*pidp != 't' || !isdigit(pidp[1])) 34037fbbce5Scth goto fail; /* not ".t#" */ 34137fbbce5Scth pid = atoi(&pidp[1]); 34237fbbce5Scth 34337fbbce5Scth /* translate <pid> to 'target-port' */ 34437fbbce5Scth if (drvpid2port(pid, &target_port) == 0) 34537fbbce5Scth goto fail; 34637fbbce5Scth 34737fbbce5Scth /* Establish 'target-port' form. */ 34837fbbce5Scth (void) snprintf(portform, sizeof (portform), 34937fbbce5Scth "%s.t%s.%s", adevpath, target_port, initiator); 35037fbbce5Scth free(target_port); 35137fbbce5Scth free(adevpath); 35237fbbce5Scth adevpath = strdup(portform); 35337fbbce5Scth } 35437fbbce5Scth 35537fbbce5Scth /* make a new entry ... */ 3567c478bd9Sstevel@tonic-gate entry = safe_alloc(sizeof (disk_list_t)); 35737fbbce5Scth entry->ks_name = safe_strdup(ks_name); 358a08731ecScth entry->dname = devpath; 359a08731ecScth entry->dsk = adevpath; 360a08731ecScth entry->devidstr = devid; 361a08731ecScth 36237fbbce5Scth #ifdef DEBUG 36337fbbce5Scth (void) printf("lookup_ks_name: new: %s %s\n", 36437fbbce5Scth ks_name, entry->dsk ? entry->dsk : "NULL"); 36537fbbce5Scth #endif /* DEBUG */ 36637fbbce5Scth 36737fbbce5Scth /* add new entry to head of hashed list */ 368a08731ecScth entry->next = *dlhp; 369a08731ecScth *dlhp = entry; 3707c478bd9Sstevel@tonic-gate return (entry); 37137fbbce5Scth 37237fbbce5Scth fail: 37337fbbce5Scth free(devpath); 37437fbbce5Scth free(adevpath); 37537fbbce5Scth free(devid); 37637fbbce5Scth #ifdef DEBUG 37737fbbce5Scth (void) printf("lookup_ks_name: failed: %s\n", ks_name); 37837fbbce5Scth #endif /* DEBUG */ 37937fbbce5Scth return (NULL); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate char * 3837c478bd9Sstevel@tonic-gate lookup_nfs_name(char *ks, kstat_ctl_t *kc) 3847c478bd9Sstevel@tonic-gate { 3857c478bd9Sstevel@tonic-gate uint_t minor; 3867c478bd9Sstevel@tonic-gate char *host, *path; 3877c478bd9Sstevel@tonic-gate char *cp; 3887c478bd9Sstevel@tonic-gate char *rstr = 0; 3897c478bd9Sstevel@tonic-gate size_t len; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate if (sscanf(ks, "nfs%u", &minor) == 1) { 3927c478bd9Sstevel@tonic-gate retry: 3937c478bd9Sstevel@tonic-gate cp = get_nfs_by_minor(minor); 3947c478bd9Sstevel@tonic-gate if (cp) { 3957c478bd9Sstevel@tonic-gate if (strchr(cp, ',') == NULL) { 3967c478bd9Sstevel@tonic-gate rstr = safe_strdup(cp); 3977c478bd9Sstevel@tonic-gate return (rstr); 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate host = cur_hostname(minor, kc); 4007c478bd9Sstevel@tonic-gate if (host) { 4017c478bd9Sstevel@tonic-gate if (*host) { 4027c478bd9Sstevel@tonic-gate path = cur_special(host, cp); 4037c478bd9Sstevel@tonic-gate if (path) { 4047c478bd9Sstevel@tonic-gate len = strlen(host); 4057c478bd9Sstevel@tonic-gate len += strlen(path); 4067c478bd9Sstevel@tonic-gate len += 2; 4077c478bd9Sstevel@tonic-gate rstr = safe_alloc(len); 4087c478bd9Sstevel@tonic-gate (void) snprintf(rstr, len, 4097c478bd9Sstevel@tonic-gate "%s:%s", host, path); 4107c478bd9Sstevel@tonic-gate } else { 4117c478bd9Sstevel@tonic-gate rstr = safe_strdup(cp); 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate } else { 4147c478bd9Sstevel@tonic-gate rstr = safe_strdup(ks); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate free(host); 4177c478bd9Sstevel@tonic-gate } else { 4187c478bd9Sstevel@tonic-gate rstr = safe_strdup(cp); 4197c478bd9Sstevel@tonic-gate } 420a08731ecScth } else if (nfs_tried == 0) { 421a08731ecScth nfs_tried = 1; 4227c478bd9Sstevel@tonic-gate do_mnttab(); 4237c478bd9Sstevel@tonic-gate goto retry; 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate return (rstr); 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate static char * 4307c478bd9Sstevel@tonic-gate get_nfs_by_minor(uint_t minor) 4317c478bd9Sstevel@tonic-gate { 4327c478bd9Sstevel@tonic-gate mnt_t *localnfs; 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate localnfs = nfs; 4357c478bd9Sstevel@tonic-gate while (localnfs) { 4367c478bd9Sstevel@tonic-gate if (localnfs->minor == minor) { 4377c478bd9Sstevel@tonic-gate return (localnfs->device_name); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate localnfs = localnfs->next; 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate return (0); 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate /* 4457c478bd9Sstevel@tonic-gate * Read the cur_hostname from the mntinfo kstat 4467c478bd9Sstevel@tonic-gate */ 4477c478bd9Sstevel@tonic-gate static char * 4487c478bd9Sstevel@tonic-gate cur_hostname(uint_t minor, kstat_ctl_t *kc) 4497c478bd9Sstevel@tonic-gate { 4507c478bd9Sstevel@tonic-gate kstat_t *ksp; 4517c478bd9Sstevel@tonic-gate static struct mntinfo_kstat mik; 4527c478bd9Sstevel@tonic-gate char *rstr; 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 4557c478bd9Sstevel@tonic-gate if (ksp->ks_type != KSTAT_TYPE_RAW) 4567c478bd9Sstevel@tonic-gate continue; 4577c478bd9Sstevel@tonic-gate if (ksp->ks_instance != minor) 4587c478bd9Sstevel@tonic-gate continue; 4597c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_module, "nfs")) 4607c478bd9Sstevel@tonic-gate continue; 4617c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_name, "mntinfo")) 4627c478bd9Sstevel@tonic-gate continue; 4637c478bd9Sstevel@tonic-gate if (ksp->ks_flags & KSTAT_FLAG_INVALID) 4647c478bd9Sstevel@tonic-gate return (NULL); 4657c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, &mik) == -1) 4667c478bd9Sstevel@tonic-gate return (NULL); 4677c478bd9Sstevel@tonic-gate rstr = safe_strdup(mik.mik_curserver); 4687c478bd9Sstevel@tonic-gate return (rstr); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate return (NULL); 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate /* 4747c478bd9Sstevel@tonic-gate * Given the hostname of the mounted server, extract the server 4757c478bd9Sstevel@tonic-gate * mount point from the mnttab string. 4767c478bd9Sstevel@tonic-gate * 4777c478bd9Sstevel@tonic-gate * Common forms: 4787c478bd9Sstevel@tonic-gate * server1,server2,server3:/path 4797c478bd9Sstevel@tonic-gate * server1:/path,server2:/path 4807c478bd9Sstevel@tonic-gate * or a hybrid of the two 4817c478bd9Sstevel@tonic-gate */ 4827c478bd9Sstevel@tonic-gate static char * 4837c478bd9Sstevel@tonic-gate cur_special(char *hostname, char *special) 4847c478bd9Sstevel@tonic-gate { 4857c478bd9Sstevel@tonic-gate char *cp; 4867c478bd9Sstevel@tonic-gate char *path; 4877c478bd9Sstevel@tonic-gate size_t hlen = strlen(hostname); 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate /* 4907c478bd9Sstevel@tonic-gate * find hostname in string 4917c478bd9Sstevel@tonic-gate */ 4927c478bd9Sstevel@tonic-gate again: 4937c478bd9Sstevel@tonic-gate if ((cp = strstr(special, hostname)) == NULL) 4947c478bd9Sstevel@tonic-gate return (NULL); 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate /* 4977c478bd9Sstevel@tonic-gate * hostname must be followed by ',' or ':' 4987c478bd9Sstevel@tonic-gate */ 4997c478bd9Sstevel@tonic-gate if (cp[hlen] != ',' && cp[hlen] != ':') { 5007c478bd9Sstevel@tonic-gate special = &cp[hlen]; 5017c478bd9Sstevel@tonic-gate goto again; 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate /* 5057c478bd9Sstevel@tonic-gate * If hostname is followed by a ',' eat all characters until a ':' 5067c478bd9Sstevel@tonic-gate */ 5077c478bd9Sstevel@tonic-gate cp = &cp[hlen]; 5087c478bd9Sstevel@tonic-gate if (*cp == ',') { 5097c478bd9Sstevel@tonic-gate cp++; 5107c478bd9Sstevel@tonic-gate while (*cp != ':') { 5117c478bd9Sstevel@tonic-gate if (*cp == NULL) 5127c478bd9Sstevel@tonic-gate return (NULL); 5137c478bd9Sstevel@tonic-gate cp++; 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate path = ++cp; /* skip ':' */ 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate /* 5197c478bd9Sstevel@tonic-gate * path is terminated by either 0, or space or ',' 5207c478bd9Sstevel@tonic-gate */ 5217c478bd9Sstevel@tonic-gate while (*cp) { 5227c478bd9Sstevel@tonic-gate if (isspace(*cp) || *cp == ',') { 5237c478bd9Sstevel@tonic-gate *cp = NULL; 5247c478bd9Sstevel@tonic-gate return (path); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate cp++; 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate return (path); 5297c478bd9Sstevel@tonic-gate } 530