diff options
-rw-r--r-- | usr/src/cmd/stat/common/acquire_iodevs.c | 17 | ||||
-rw-r--r-- | usr/src/cmd/stat/common/dsr.c | 992 | ||||
-rw-r--r-- | usr/src/cmd/stat/common/dsr.h | 73 | ||||
-rw-r--r-- | usr/src/cmd/stat/common/statcommon.h | 11 | ||||
-rw-r--r-- | usr/src/cmd/stat/iostat/iostat.c | 38 | ||||
-rw-r--r-- | usr/src/cmd/stat/mpstat/mpstat.c | 9 | ||||
-rw-r--r-- | usr/src/cmd/truss/print.c | 4 | ||||
-rw-r--r-- | usr/src/lib/libdevinfo/Makefile.com | 2 | ||||
-rw-r--r-- | usr/src/lib/libdevinfo/devinfo_devlink.c | 1 | ||||
-rw-r--r-- | usr/src/lib/libdevinfo/devinfo_dim.c | 149 | ||||
-rw-r--r-- | usr/src/lib/libdevinfo/libdevinfo.h | 16 | ||||
-rw-r--r-- | usr/src/lib/libdevinfo/mapfile-vers | 4 | ||||
-rw-r--r-- | usr/src/uts/common/os/kstat_fr.c | 18 | ||||
-rw-r--r-- | usr/src/uts/common/os/modctl.c | 82 | ||||
-rw-r--r-- | usr/src/uts/common/os/policy.c | 13 | ||||
-rw-r--r-- | usr/src/uts/common/sys/modctl.h | 2 |
16 files changed, 622 insertions, 809 deletions
diff --git a/usr/src/cmd/stat/common/acquire_iodevs.c b/usr/src/cmd/stat/common/acquire_iodevs.c index cd7d167c97..be29ff88ef 100644 --- a/usr/src/cmd/stat/common/acquire_iodevs.c +++ b/usr/src/cmd/stat/common/acquire_iodevs.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -543,7 +542,7 @@ get_pretty_name(enum snapshot_types types, struct iodev_snapshot *iodev, if (!*tmp) return; (void) strlcpy(buf, iodev->is_name, 1 + tmp - iodev->is_name); - dl = lookup_ks_name(buf); + dl = lookup_ks_name(buf, (types & SNAP_IODEV_DEVID) ? 1 : 0); if (dl == NULL || dl->dsk == NULL) return; len = strlen(dl->dsk) + strlen(tmp) + 1; @@ -553,7 +552,7 @@ get_pretty_name(enum snapshot_types types, struct iodev_snapshot *iodev, goto out; } - dl = lookup_ks_name(iodev->is_name); + dl = lookup_ks_name(iodev->is_name, (types & SNAP_IODEV_DEVID) ? 1 : 0); if (dl == NULL) return; @@ -655,6 +654,12 @@ acquire_iodevs(struct snapshot *ss, kstat_ctl_t *kc, struct iodev_filter *df) ss->s_nr_iodevs = 0; + /* + * Call cleanup_iodevs_snapshot() so that a cache miss in + * lookup_ks_name() will result in a fresh snapshot. + */ + cleanup_iodevs_snapshot(); + for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { enum iodev_type type; diff --git a/usr/src/cmd/stat/common/dsr.c b/usr/src/cmd/stat/common/dsr.c index f3c5a18fe4..b25637a73b 100644 --- a/usr/src/cmd/stat/common/dsr.c +++ b/usr/src/cmd/stat/common/dsr.c @@ -56,770 +56,362 @@ #include "dsr.h" #include "statcommon.h" -static void rummage_dev(ldinfo_t *); -static void do_snm(char *, char *); -static int look_up_name(const char *, disk_list_t *); -static disk_list_t *make_an_entry(char *, char *, - char *, dir_info_t *, int, ldinfo_t *); -static char *trim(char *, char *, int); -static ldinfo_t *rummage_devinfo(void); -static void pline(char *, int, char *, char *, ldinfo_t **); -static void insert_dlist_ent(disk_list_t *, disk_list_t **); -static int str_is_digit(char *); -static ldinfo_t *find_ldinfo_match(char *, ldinfo_t *); - -static void insert_into_dlist(dir_info_t *, disk_list_t *); -static void cleanup_dlist(dir_info_t *); -static void cleanup_ldinfo(ldinfo_t *); -static int devinfo_ident_disks(di_node_t, void *); -static int devinfo_ident_tapes(di_node_t, void *); -static void process_dir_ent(char *dent, int curr_type, - char *last_snm, dir_info_t *, ldinfo_t *); - -static char *get_nfs_by_minor(uint_t); -static char *cur_hostname(uint_t, kstat_ctl_t *); -static char *cur_special(char *, char *); - -extern kstat_ctl_t *kc; -extern mnt_t *nfs; +/* disk/tape info */ +static di_node_t di_root; /* for devid */ +static di_dim_t di_dim; /* for /dev names */ +typedef struct { + char *minor_name; + int minor_isdisk; +} minor_match_t; +static minor_match_t mm_disk = {"a", 1}; +static minor_match_t mm_tape = {"", 0}; +static char md_minor_name[MAXPATHLEN]; +static minor_match_t mm_md = {md_minor_name, 0}; +static minor_match_t *mma_disk_tape[] = {&mm_disk, &mm_tape, NULL}; +static minor_match_t *mma_md[] = {&mm_md, NULL}; +static char *mdsetno2name(int setno); +#define DISKLIST_MOD 256 /* ^2 instunit mod hash */ +static disk_list_t *disklist[DISKLIST_MOD]; + +/* nfs info */ +extern kstat_ctl_t *kc; +extern mnt_t *nfs; +static int nfs_tried; +static char *get_nfs_by_minor(uint_t); +static char *cur_hostname(uint_t, kstat_ctl_t *); +static char *cur_special(char *, char *); /* - * To do: add VXVM support: /dev/vx/dsk and ap support: /dev/ap/ - * - * Note: Adding support for VxVM is *not* as simple as adding another - * entry in the table and magically getting to see stuff related to - * VxVM. The structure is radically different *AND* they don't produce - * any IO kstats. + * Clear the snapshot so a cache miss in lookup_ks_name() will cause a fresh + * snapshot in drvinstunit2dev(). */ - -#define OSA_DISK 0 -#define DISK 1 -#define MD_DISK 2 -#define TAPE 3 - -#define MAX_TYPES 4 - -#define OSA_DISK_PATH "/dev/osa/dev/dsk" -#define MD_DISK_PATH "/dev/md/dsk" -#define DISK_PATH "/dev/dsk" -#define TAPE_PATH "/dev/rmt" - -#define BASE_TRIM "../../devices" -#define MD_TRIM "../../../devices" -#define COLON ':' -#define COMMA ',' - -#define NAME_BUFLEN 256 - -static dir_info_t dlist[MAX_TYPES] = { - OSA_DISK_PATH, 0, 0, 0, 0, "sd", BASE_TRIM, COLON, - DISK_PATH, 0, 0, 0, 0, "sd", BASE_TRIM, COLON, - MD_DISK_PATH, 0, 0, 0, 1, "md", MD_TRIM, COMMA, - TAPE_PATH, 0, 0, 0, 0, "st", BASE_TRIM, COLON, -}; - -/* - * Build a list of disks attached to the system. - */ -static void -build_disk_list(void) +void +cleanup_iodevs_snapshot() { - ldinfo_t *ptoi; - - /* - * Build the list of devices connected to the system. - */ - ptoi = rummage_devinfo(); - rummage_dev(ptoi); - cleanup_ldinfo(ptoi); -} + if (di_dim) { + di_dim_fini(di_dim); + di_dim = NULL; + } -/* - * Walk the /dev/dsk and /dev/rmt directories building a - * list of interesting devices. Interesting is everything in the - * /dev/dsk directory. We skip some of the stuff in the /dev/rmt - * directory. - * - * Note that not finding one or more of the directories is not an - * error. - */ -static void -rummage_dev(ldinfo_t *ptoi) -{ - DIR *dskp; - int i; - struct stat buf; - - for (i = 0; i < MAX_TYPES; i++) { - if (stat(dlist[i].name, &buf) == 0) { - if (dlist[i].mtime != buf.st_mtime) { - /* - * We've found a change. We need to cleanup - * old information and then rebuild the list - * for this device type. - */ - cleanup_dlist(&dlist[i]); - dlist[i].mtime = buf.st_mtime; - if ((dskp = opendir(dlist[i].name))) { - struct dirent *bpt; - char last_snm[NAME_BUFLEN]; - - last_snm[0] = NULL; - while ((bpt = readdir(dskp)) != NULL) { - if (bpt->d_name[0] != '.') { - process_dir_ent( - bpt->d_name, - i, last_snm, - &dlist[i], - ptoi); - } - } - } - (void) closedir(dskp); - } - } + if (di_root) { + di_fini(di_root); + di_root = DI_NODE_NIL; } + + nfs_tried = 0; } /* - * Walk the list of located devices and see if we've - * seen this device before. We look at the short name. + * Find information for (driver, instunit) device: return zero on failure. + * + * NOTE: Failure of drvinstunit2dev works out OK for the caller if the kstat + * name is the same as public name: the caller will just use kstat name. */ static int -look_up_name(const char *nm, disk_list_t *list) +drvinstunit2dev(char *driver, int instunit, + char **devpathp, char **adevpathp, char **devidp, int *isdiskp) { - while (list) { - if (strcmp(list->dsk, nm) != 0) - list = list->next; - else { - return (1); - } + int instance; + minor_match_t **mma; + minor_match_t *mm; + char *devpath; + char *devid; + char *a, *s; + int mdsetno; + char *mdsetname = NULL; + char amdsetname[MAXPATHLEN]; + char *devicespath; + di_node_t node; + + + /* setup "no result" return values */ + if (devpathp) + *devpathp = NULL; + if (adevpathp) + *adevpathp = NULL; + if (devidp) + *devidp = NULL; + if (isdiskp) + *isdiskp = 0; + + /* take <driver><instance><minor_name> snapshot if not established */ + if (di_dim == NULL) { + di_dim = di_dim_init(); + if (di_dim == NULL) + return (0); } - return (0); -} -/* - * Take a name of the form cNtNdNsN or cNtNdNpN - * or /dev/dsk/CNtNdNsN or /dev/dsk/cNtNdNpN - * remove the trailing sN or pN. Simply looking - * for the first 's' or 'p' doesn't cut it. - */ -static void -do_snm(char *orig, char *shortnm) -{ - char *tmp; - char *ptmp; - int done = 0; - char repl_char = 0; - - tmp = strrchr(orig, 's'); - if (tmp) { - ptmp = tmp; - ptmp++; - done = str_is_digit(ptmp); - } - if (done == 0) { + /* + * Determine if 'instunit' is an 'instance' or 'unit' based on the + * 'driver'. The current code only detects 'md' metadevice 'units', + * and defaults to 'instance' for everything else. + * + * For a metadevice, 'driver' is either "md" or "<setno>/md". + */ + s = strstr(driver, "/md"); + if ((strcmp(driver, "md") == 0) || + (s && isdigit(*driver) && (strcmp(s, "/md") == 0))) { /* - * The string either has no 's' in it - * or the stuff trailing the s has a - * non-numeric in it. Look to see if - * we have an ending 'p' followed by - * numerics. + * "md" unit: Special case translation of "md" kstat names. + * For the local set the kstat name is "md<unit>", and for + * a shared set the kstat name is "<setno>/md<unit>": we map + * these to the minor paths "/pseudo/md@0:<unit>,blk" and + * "/pseudo/md@0:<set>,<unit>,blk" respectively. */ - tmp = strrchr(orig, 'p'); - if (tmp) { - ptmp = tmp; - ptmp++; - if (str_is_digit(ptmp)) - repl_char = 'p'; - else - tmp = 0; - } - } else { - repl_char = 's'; - } - if (tmp) - *tmp = '\0'; - (void) strcpy(shortnm, orig); - if (repl_char) - *tmp = repl_char; -} - -/* - * Create and insert an entry into the device list. - */ -static disk_list_t * -make_an_entry(char *lname, char *shortnm, char *longnm, - dir_info_t *drent, int devtype, ldinfo_t *ptoi) -{ - disk_list_t *entry; - char *nlnm; - char snm[NAME_BUFLEN]; - ldinfo_t *p; + if (isdigit(*driver)) { + mdsetno = atoi(driver); - entry = safe_alloc(sizeof (disk_list_t)); + /* convert setno to setname */ + mdsetname = mdsetno2name(mdsetno); + } else + mdsetno = 0; - nlnm = trim(lname, drent->trimstr, drent->trimchr); - entry->dsk = safe_strdup(shortnm); - do_snm(longnm, snm); - entry->dname = safe_strdup(snm); - entry->devtype = devtype; - entry->devidstr = NULL; - if ((p = find_ldinfo_match(nlnm, ptoi))) { - entry->dnum = p->dnum; - entry->dtype = safe_strdup(p->dtype); - if (p->devidstr) - entry->devidstr = safe_strdup(p->devidstr); + driver = "md"; + instance = 0; + mma = mma_md; /* metadevice dynamic minor */ + (void) snprintf(md_minor_name, sizeof (md_minor_name), + "%d,%d,blk", mdsetno, instunit); } else { - entry->dtype = safe_strdup(drent->dtype); - entry->dnum = -1; - if (drent->dtype) { - if (strcmp(drent->dtype, "md") == 0) { - (void) sscanf(shortnm, "d%d", &entry->dnum); - } - } + instance = instunit; + mma = mma_disk_tape; /* disk/tape minors */ } - entry->seen = 0; - entry->next = 0; - insert_dlist_ent(entry, &drent->list); - return (entry); -} -/* - * slice stuff off beginning and end of /devices directory names derived from - * device links. - */ -static char * -trim(char *fnm, char *lname, int rchr) -{ - char *ptr; - - while (*lname == *fnm) { - lname++; - fnm++; + /* Try to find a minor_match that works */ + for (mm = *mma++; mm; mm = *mma++) { + if ((devpath = di_dim_path_dev(di_dim, + driver, instance, mm->minor_name)) != NULL) + break; } - if ((ptr = strrchr(fnm, rchr))) - *ptr = NULL; - return (fnm); -} + if (devpath == NULL) + return (0); -/* - * Find an entry matching the name passed in - */ -static ldinfo_t * -find_ldinfo_match(char *name, ldinfo_t *ptoi) -{ - if (name) { - while (ptoi) { - if (strcmp(ptoi->name, name)) - ptoi = ptoi->next; - else - return (ptoi); - } - } - return (NULL); -} + /* + * At this point we have a devpath result. Return the information about + * the result that the caller is asking for. + */ + if (devpathp) /* devpath */ + *devpathp = safe_strdup(devpath); -/* - * Determine if a name is already in the list of disks. If not, insert the - * name in the list. - */ -static void -insert_dlist_ent(disk_list_t *n, disk_list_t **hd) -{ - disk_list_t *tmp_ptr; - - if (n->dtype != NULL) { - tmp_ptr = *hd; - while (tmp_ptr) { - if (strcmp(n->dsk, tmp_ptr->dsk) != 0) - tmp_ptr = tmp_ptr->next; - else - break; - } - if (tmp_ptr == NULL) { + if (adevpathp) { /* abbreviated devpath */ + if (mm->minor_isdisk) { /* - * We don't do anything with MD_DISK types here - * since they don't have partitions. + * For disks we return the last component (with + * trailing "s#" or "p#" stripped off for disks). + * For example for devpath of "/dev/dsk/c0t0d0s0" the + * abbreviated devpath would be "c0t0d0". */ - if (n->devtype == DISK || n->devtype == OSA_DISK) { - n->flags = SLICES_OK; -#if defined(__i386) - n->flags |= PARTITIONS_OK; -#endif - } else { - n->flags = 0; + a = strrchr(devpath, '/'); + if (a == NULL) { + free(devpath); + return (0); } + a++; + s = strrchr(a, 's'); + if (s == NULL) { + s = strrchr(a, 'p'); + if (s == NULL) { + free(devpath); + return (0); + } + } + /* don't include slice information in devpath */ + *s = '\0'; + } else { /* - * Figure out where to insert the name. The list is - * ostensibly in sorted order. + * remove "/dev/", and "/dsk/", from 'devpath' (like + * "/dev/md/dsk/d0") to form the abbreviated devpath + * (like "md/d0"). */ - if (*hd) { - disk_list_t *follw; - int mv; - - tmp_ptr = *hd; - - /* - * Look through the list. While the strcmp - * value is less than the current value, - */ - while (tmp_ptr) { - if ((mv = strcmp(n->dtype, - tmp_ptr->dtype)) < 0) { - follw = tmp_ptr; - tmp_ptr = tmp_ptr->next; - } else - break; - } - if (mv == 0) { - /* - * We're now in the area where the - * leading chars of the kstat name - * match. We need to insert in numeric - * order after that. - */ - while (tmp_ptr) { - if (strcmp(n->dtype, - tmp_ptr->dtype) != 0) - break; - if (n->dnum > tmp_ptr->dnum) { - follw = tmp_ptr; - tmp_ptr = tmp_ptr->next; - } else - break; - } - } - /* - * We should now be ready to insert an - * entry... - */ - if (mv >= 0) { - if (tmp_ptr == *hd) { - n->next = tmp_ptr; - *hd = n; - } else { - n->next = follw->next; - follw->next = n; - } - } else { - /* - * insert at the end of the - * list - */ - follw->next = n; - n->next = 0; - } + if ((s = strstr(devpath, "/dev/")) != NULL) + (void) strcpy(s + 1, s + 5); + if ((s = strstr(devpath, "/dsk/")) != NULL) + (void) strcpy(s + 1, s + 5); + + /* + * If we have an mdsetname, convert abbreviated setno + * notation (like "md/shared/1/d0" to abbreviated + * setname notation (like "md/red/d0"). + */ + if (mdsetname) { + a = strrchr(devpath, '/'); + (void) snprintf(amdsetname, sizeof (amdsetname), + "md/%s%s", mdsetname, a); + free(mdsetname); + a = amdsetname; } else { - *hd = n; - n->next = 0; + if (*devpath == '/') + a = devpath + 1; + else + a = devpath; } } - } -} - -/* - * find an entry matching the given kstat name in the list - * of disks, tapes and metadevices. - */ -disk_list_t * -lookup_ks_name(char *dev_nm) -{ - int tried = 0; - int dv; - int len; - char cmpbuf[PATH_MAX + 1]; - struct list_of_disks *list; - char *nm; - dev_name_t *tmp; - uint_t i; - - /* - * extract the device type from the kstat name. We expect the - * name to be one or more alphabetics followed by the device - * numeric id. We do this solely for speed purposes . - */ - len = 0; - nm = dev_nm; - while (*nm) { - if (isalpha(*nm)) { - nm++; - len++; - } else - break; + *adevpathp = safe_strdup(a); } - if (!*nm) - return (NULL); - - /* - * For each of the elements in the dlist array we keep - * an array of pointers to chains for each of the kstat - * prefixes found within that directory. This is typically - * 'sd' and 'ssd'. We walk the list in the directory and - * match on that type. Since the same prefixes can be - * in multiple places we keep checking if we don't find - * it in the first place. - */ - - (void) strncpy(cmpbuf, dev_nm, len); - cmpbuf[len] = NULL; - dv = atoi(nm); - -retry: - for (i = 0; i < MAX_TYPES; i++) { - tmp = dlist[i].nf; - while (tmp) { - if (strcmp(tmp->name, cmpbuf) == 0) { - /* - * As an optimization we keep mins - * and maxes for the devices found. - * This helps chop the lists up and - * avoid some really long chains as - * we would get if we kept only prefix - * lists. - */ - if (dv >= tmp->min && dv <= tmp->max) { - list = tmp->list_start; - while (list) { - if (list->dnum < dv) - list = list->next; - else - break; - } - if (list && list->dnum == dv) { - return (list); - } - } + if (devidp) { /* lookup the devid */ + /* take snapshots if not established */ + if (di_root == DI_NODE_NIL) { + di_root = di_init("/", DINFOCACHE); + } + if (di_root) { + /* get path to /devices devinfo node */ + devicespath = di_dim_path_devices(di_dim, + driver, instance, NULL); + if (devicespath) { + /* find the node in the snapshot */ + node = di_lookup_node(di_root, devicespath); + free(devicespath); + + /* and lookup devid property on the node */ + if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, + DEVID_PROP_NAME, &devid) != -1) + *devidp = devid; } - tmp = tmp->next; } } - if (!tried) { - tried = 1; - build_disk_list(); - goto retry; - } + if (isdiskp) + *isdiskp = mm->minor_isdisk; - return (0); -} - -static int -str_is_digit(char *str) -{ - while (*str) { - if (isdigit(*str)) - str++; - else - return (0); - } - return (1); -} - -static void -insert_into_dlist(dir_info_t *d, disk_list_t *e) -{ - dev_name_t *tmp; - - tmp = d->nf; - while (tmp) { - if (strcmp(e->dtype, tmp->name) != 0) { - tmp = tmp->next; - } else { - if (e->dnum < tmp->min) { - tmp->min = e->dnum; - tmp->list_start = e; - } else if (e->dnum > tmp->max) { - tmp->max = e->dnum; - tmp->list_end = e; - } - break; - } - } - if (tmp == NULL) { - tmp = safe_alloc(sizeof (dev_name_t)); - tmp->name = e->dtype; - tmp->min = e->dnum; - tmp->max = e->dnum; - tmp->list_start = e; - tmp->list_end = e; - tmp->next = d->nf; - d->nf = tmp; - } + free(devpath); + return (1); /* success */ } /* - * devinfo_ident_disks() and devinfo_ident_tapes() are the callback functions we - * use while walking the device tree snapshot provided by devinfo. If - * devinfo_ident_disks() identifies that the device being considered has one or - * more minor nodes _and_ is a block device, then it is a potential disk. - * Similarly for devinfo_ident_tapes(), except that the second criterion is that - * the minor_node be a character device. (This is more inclusive than only - * tape devices, but will match any entries in /dev/rmt/.) + * Find/create a disk_list entry for "<driver><instunit>" given a kstat name. + * The basic format of a kstat name is "<driver><instunit>,<partition>". The + * <instunit> is a base10 number, and the ",<partition>" part is optional. * - * Note: if a driver was previously loaded but is now unloaded, the kstat may - * still be around (e.g., st) but no information will be found in the - * libdevinfo tree. + * NOTE: In the case of non-local metadevices, the format of "<driver>" in + * a kstat name is acutally "<setno>/md". */ - -static int -devinfo_ident_disks(di_node_t node, void *arg) +disk_list_t * +lookup_ks_name(char *ks_name, int want_devid) { - di_minor_t minor = DI_MINOR_NIL; - - if ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { - int spectype = di_minor_spectype(minor); - - if (S_ISBLK(spectype)) { - char *physical_path = di_devfs_path(node); - int instance = di_instance(node); - char *driver_name = di_driver_name(node); - char *devidstr; - - /* lookup the devid, devt specific first */ - if ((di_prop_lookup_strings(di_minor_devt(minor), node, - DEVID_PROP_NAME, &devidstr) == -1) && - (di_prop_lookup_strings(DDI_DEV_T_ANY, node, - DEVID_PROP_NAME, &devidstr) == -1)) - devidstr = NULL; - - if (driver_name == NULL) - driver_name = "<nil>"; - - pline(physical_path, instance, - driver_name, devidstr, arg); - di_devfs_path_free(physical_path); + char *p; + int len; + char driver[MAXNAMELEN]; + int instunit; + disk_list_t **dlhp; /* disklist head */ + disk_list_t *entry; + char *devpath; + char *adevpath = NULL; + char *devid = NULL; + int isdisk; + + /* + * Extract <driver> and <instunit> from kstat name. + * Filter out illegal forms (like all digits). + */ + if ((ks_name == NULL) || (*ks_name == 0) || + (strspn(ks_name, "0123456789") == strlen(ks_name))) + return (NULL); + p = strrchr(ks_name, ','); /* start of ",partition" */ + if (p == NULL) + p = &ks_name[strlen(ks_name) - 1]; /* last char */ + else + p--; /* before ",partition" */ + + while ((p >= ks_name) && isdigit(*p)) + p--; /* backwards over digits */ + p++; /* start of instunit */ + if ((*p == '\0') || (*p == ',')) + return (NULL); /* no <instunit> */ + len = p - ks_name; + (void) strncpy(driver, ks_name, len); + driver[len] = '\0'; + instunit = atoi(p); + + /* hash and search for existing disklist entry */ + dlhp = &disklist[instunit & (DISKLIST_MOD - 1)]; + for (entry = *dlhp; entry; entry = entry->next) { + if ((strcmp(entry->dtype, driver) == 0) && + (entry->dnum == instunit)) { + return (entry); } } - return (DI_WALK_CONTINUE); -} -static int -devinfo_ident_tapes(di_node_t node, void *arg) -{ - di_minor_t minor = DI_MINOR_NIL; - - if ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { - int spectype = di_minor_spectype(minor); - - if (S_ISCHR(spectype)) { - char *physical_path = di_devfs_path(node); - int instance = di_instance(node); - char *binding_name = di_binding_name(node); - - pline(physical_path, instance, - binding_name, NULL, arg); - di_devfs_path_free(physical_path); - } + /* not found, try to get dev information */ + if (drvinstunit2dev(driver, instunit, &devpath, &adevpath, + want_devid ? &devid : NULL, &isdisk) == 0) { + return (NULL); } - return (DI_WALK_CONTINUE); -} -/* - * rummage_devinfo() is the driver routine that walks the devinfo snapshot. - */ -static ldinfo_t * -rummage_devinfo(void) -{ - di_node_t root_node; - ldinfo_t *rv = NULL; - - if ((root_node = di_init("/", DINFOCACHE)) != DI_NODE_NIL) { - (void) di_walk_node(root_node, DI_WALK_CLDFIRST, (void *)&rv, - devinfo_ident_disks); - (void) di_walk_node(root_node, DI_WALK_CLDFIRST, (void *)&rv, - devinfo_ident_tapes); - di_fini(root_node); + /* and make a new disklist entry ... */ + entry = safe_alloc(sizeof (disk_list_t)); + entry->dtype = safe_strdup(driver); + entry->dnum = instunit; + entry->dname = devpath; + entry->dsk = adevpath; + entry->devidstr = devid; + entry->flags = 0; + if (isdisk) { + entry->flags |= SLICES_OK; +#if defined(__i386) + entry->flags |= PARTITIONS_OK; +#endif } - return (rv); -} + entry->seen = 0; -/* - * pline() performs the lookup of the device path in the current list of disks, - * and adds the appropriate information to the nms list in the case of a match. - */ -static void -pline(char *devfs_path, int instance, - char *driver_name, char *devidstr, ldinfo_t **list) -{ - ldinfo_t *entry; - - entry = safe_alloc(sizeof (ldinfo_t)); - entry->dnum = instance; - entry->name = safe_strdup(devfs_path); - entry->dtype = safe_strdup(driver_name); - entry->devidstr = safe_strdup(devidstr); - entry->next = *list; - *list = entry; + /* add new entry to head of instunit hashed list */ + entry->next = *dlhp; + *dlhp = entry; + return (entry); } /* - * Cleanup space allocated in dlist processing. - * We're only interested in cleaning up the list and nf - * fields in the structure. Everything else is static - * data. + * Convert metadevice setno to setname by looking in /dev/md for symlinks + * that point to "shared/setno" - the name of such a symlink is the setname. + * The caller is responsible for freeing the returned string. */ -static void -cleanup_dlist(dir_info_t *d) +static char * +mdsetno2name(int setno) { - dev_name_t *tmp; - dev_name_t *t1; - disk_list_t *t2; - disk_list_t *t3; + char setlink[MAXPATHLEN + 1]; + char link[MAXPATHLEN + 1]; + char path[MAXPATHLEN + 1]; + char *p; + DIR *dirp; + struct dirent *dp; + size_t len; + char *mdsetname = NULL; + + /* we are looking for a link to setlink */ + (void) snprintf(setlink, MAXPATHLEN, "shared/%d", setno); + + /* in the directory /dev/md */ + (void) strcpy(path, "/dev/md/"); + p = path + strlen(path); + dirp = opendir(path); + if (dirp == NULL) + return (NULL); - /* - * All of the entries in a dev_name_t use information - * from a disk_list_t structure that is freed later. - * All we need do here is free the dev_name_t - * structure itself. - */ - tmp = d->nf; - while (tmp) { - t1 = tmp->next; - free(tmp); - tmp = t1; - } - d->nf = 0; - /* - * "Later". Free the disk_list_t structures and their - * data attached to this portion of the dir_info - * structure. - */ - t2 = d->list; - while (t2) { - if (t2->dtype) { - free(t2->dtype); - t2->dtype = NULL; - } - if (t2->dsk) { - free(t2->dsk); - t2->dsk = NULL; - } - if (t2->dname) { - free(t2->dname); - t2->dname = NULL; - } - t3 = t2->next; - free(t2); - t2 = t3; - } - d->list = 0; -} + /* loop through /dev/md directory entries */ + while ((dp = readdir(dirp)) != NULL) { -static void -process_dir_ent(char *dent, int curr_type, char *last_snm, - dir_info_t *dp, ldinfo_t *ptoi) -{ - struct stat sbuf; - char dnmbuf[PATH_MAX + 1]; - char lnm[NAME_BUFLEN]; - char snm[NAME_BUFLEN]; - char *npt; - - snm[0] = NULL; - if (curr_type == DISK || curr_type == OSA_DISK) { - /* - * get the short name - omitting - * the trailing sN or PN - */ - (void) strcpy(lnm, dent); - do_snm(dent, snm); - } else if (curr_type == MD_DISK) { - (void) strcpy(lnm, dent); - (void) strcpy(snm, dent); - } else { - /* - * don't want all rewind/etc - * devices for a tape - */ - if (!str_is_digit(dent)) - return; - (void) snprintf(snm, sizeof (snm), "rmt/%s", dent); - (void) snprintf(lnm, sizeof (snm), "rmt/%s", dent); - } - /* - * See if we've already processed an entry for this device. - * If so, we're just another partition so we get another - * entry. - * - * last_snm is an optimization to avoid the function call - * and lookup since we'll often see partition records - * immediately after the disk record. - */ - if (dp->skip_lookup == 0) { - if (strcmp(snm, last_snm) != 0) { - /* - * a zero return means that - * no record was found. We'd - * return a pointer otherwise. - */ - if (look_up_name(snm, - dp->list) == 0) { - (void) strcpy(last_snm, snm); - } else - return; - } else - return; - } - /* - * Get the real device name for this beast - * by following the link into /devices. - */ - (void) snprintf(dnmbuf, sizeof (dnmbuf), "%s/%s", dp->name, dent); - if (lstat(dnmbuf, &sbuf) != -1) { - if ((sbuf.st_mode & S_IFMT) == S_IFLNK) { - /* - * It's a link. Get the real name. - */ - char nmbuf[PATH_MAX + 1]; - int nbyr; - - if ((nbyr = readlink(dnmbuf, nmbuf, - sizeof (nmbuf))) != 1) { - npt = nmbuf; - /* - * readlink does not terminate - * the string so we have to - * do it. - */ - nmbuf[nbyr] = NULL; - } else - npt = NULL; - } else - npt = lnm; - /* - * make an entry in the device list - */ - if (npt) { - disk_list_t *d; + /* doing a readlink of entry (fails for non-symlinks) */ + *p = '\0'; + (void) strcpy(p, dp->d_name); + if ((len = readlink(path, link, MAXPATHLEN)) == (size_t)-1) + continue; - d = make_an_entry(npt, snm, - dnmbuf, dp, - curr_type, ptoi); - insert_into_dlist(dp, d); - } - } -} -static void -cleanup_ldinfo(ldinfo_t *list) -{ - ldinfo_t *tmp; - while (list) { - tmp = list; - list = list->next; - free(tmp->name); - free(tmp->dtype); - if (tmp->devidstr) - free(tmp->devidstr); - free(tmp); + /* and looking for a link to setlink */ + link[len] = '\0'; + if (strcmp(setlink, link)) + continue; + + /* found- name of link is the setname */ + mdsetname = safe_strdup(dp->d_name); + break; } + + (void) closedir(dirp); + return (mdsetname); } char * lookup_nfs_name(char *ks, kstat_ctl_t *kc) { - int tried = 0; uint_t minor; char *host, *path; char *cp; @@ -855,8 +447,8 @@ retry: } else { rstr = safe_strdup(cp); } - } else if (!tried) { - tried = 1; + } else if (nfs_tried == 0) { + nfs_tried = 1; do_mnttab(); goto retry; } diff --git a/usr/src/cmd/stat/common/dsr.h b/usr/src/cmd/stat/common/dsr.h index dc14576efb..96757e68a8 100644 --- a/usr/src/cmd/stat/common/dsr.h +++ b/usr/src/cmd/stat/common/dsr.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -43,7 +42,6 @@ typedef struct list_of_disks { char *dname; /* in form of /dev/dsk/cNtNdN */ char *devidstr; /* in form of "id1,sd@XXXX" */ uint_t flags; /* see SLICES_OK and PARTITIONS_OK above */ - int devtype; /* disk, metadevice, tape */ uint_t seen; /* Used for diffing disk lists */ struct list_of_disks *next; /* link to next one */ } disk_list_t; @@ -60,68 +58,6 @@ typedef struct mnt_info { } mnt_t; /* - * A basic description of each device found - * on the system by walking the device tree. - * These entries are used to select the - * relevent entries from the actual /dev - * entries. - */ -typedef struct ldinfo { - char *name; - char *dtype; - char *devidstr; - int dnum; - struct ldinfo *next; -} ldinfo_t; - -/* - * Optimization for lookup of kstats. - * For each kstat prefix (e.g., 'sd') - * found in a directory one of these - * structures will be created. - * - * name: prefix of kstat name (e.g., 'ssd') - * min: smallest number seen from kstat - * name (e.g., 101 from 'sd101') - * max: largest number seen from kstat - * list_start: beginning of disk_list structures - * for this kstat type in the main list for - * this directory - * list_end: end of entries for this kstat type - * in this directory. - */ -typedef struct dev_name { - char *name; - uint_t min; - uint_t max; - disk_list_t *list_start; - disk_list_t *list_end; - struct dev_name *next; -} dev_name_t; - -/* - * Definition of a "type" of disk device. - * Tied to the directory containing entries - * for that device. Divides the list of - * devices into localized chunks and allows - * quick determination as to whether an entry - * exists or whether we need to look at the - * devices upon a state change. - */ -typedef struct dir_info { - char *name; /* directory name */ - time_t mtime; /* mod time */ - disk_list_t *list; /* master list of devices */ - dev_name_t *nf; /* lists per name */ - uint_t skip_lookup; /* skip lookup if device */ - /* does not have partitions */ - char *dtype; /* Type of device */ - char *trimstr; /* What do we prune */ - char trimchr; /* Char denoting end */ - /* of interesting data */ -} dir_info_t; - -/* * The following are used to control treatment of kstat names * which fall beyond the number of disk partitions allowed on * the particular ISA. PARTITIONS_OK is set only on an Intel @@ -132,8 +68,9 @@ typedef struct dir_info { void do_mnttab(void); mnt_t *lookup_mntent_byname(char *); -disk_list_t *lookup_ks_name(char *); +disk_list_t *lookup_ks_name(char *, int); char *lookup_nfs_name(char *, kstat_ctl_t *); +void cleanup_iodevs_snapshot(); #ifdef __cplusplus } diff --git a/usr/src/cmd/stat/common/statcommon.h b/usr/src/cmd/stat/common/statcommon.h index efc48e57ae..674148da6b 100644 --- a/usr/src/cmd/stat/common/statcommon.h +++ b/usr/src/cmd/stat/common/statcommon.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Common routines for acquiring snapshots of kstats for @@ -80,7 +79,9 @@ enum snapshot_types { /* disk error stats */ SNAP_IODEV_ERRORS = 1 << 8, /* pretty names for iodevs */ - SNAP_IODEV_PRETTY = 1 << 9 + SNAP_IODEV_PRETTY = 1 << 9, + /* devid for iodevs */ + SNAP_IODEV_DEVID = 1 << 10 }; struct cpu_snapshot { diff --git a/usr/src/cmd/stat/iostat/iostat.c b/usr/src/cmd/stat/iostat/iostat.c index 3499695347..1199870792 100644 --- a/usr/src/cmd/stat/iostat/iostat.c +++ b/usr/src/cmd/stat/iostat/iostat.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * rewritten from UCB 4.13 83/09/25 @@ -203,6 +202,7 @@ main(int argc, char **argv) enum snapshot_types types = SNAP_SYSTEM; kstat_ctl_t *kc; long hz; + int iiter; do_args(argc, argv); do_format(); @@ -228,6 +228,8 @@ main(int argc, char **argv) df.if_allowed_types |= IODEV_PARTITION; if (do_conversions) types |= SNAP_IODEV_PRETTY; + if (do_devid) + types |= SNAP_IODEV_DEVID; if (do_controller) { if (!(do_disk & PRINT_VERTICAL) || (do_disk & DISK_EXTENDED_ERRORS)) @@ -253,6 +255,7 @@ main(int argc, char **argv) kc = open_kstat(); newss = acquire_snapshot(kc, types, &df); + iiter = iter; do { if (do_tty || do_cpu) { kstat_t *oldks; @@ -277,6 +280,10 @@ main(int argc, char **argv) (void) fflush(stdout); } + /* only doing a single iteration, we are done */ + if (iiter == 1) + continue; + if (interval > 0 && iter != 1) (void) pause(); @@ -297,6 +304,8 @@ main(int argc, char **argv) free_snapshot(oldss); free_snapshot(newss); + (void) kstat_close(kc); + return (0); } @@ -345,7 +354,7 @@ show_disk_name(void *v1, void *v2, void *data) (void) snprintf(fbuf, sizeof (fbuf), "%*s", width, name); name = fbuf; - push_out("%-14.14s", name); + push_out("%-13.13s ", name); } else { push_out(name); } @@ -1242,7 +1251,10 @@ do_format(void) default: break; } - if (do_disk == DISK_ERRORS) { + + /* do DISK_ERRORS header (already added above for DISK_EXTENDED) */ + if ((do_disk & DISK_ERRORS) && + ((do_disk & DISK_IO_MASK) != DISK_EXTENDED)) { char *sep; if (!do_conversions) { @@ -1256,9 +1268,12 @@ do_format(void) if (do_raw == 0) { (void) snprintf(disk_header, sizeof (disk_header), - " %s", header); - } else - (void) strcpy(disk_header, header); + " %sdevice", header); + } else { + (void) snprintf(disk_header, + sizeof (disk_header), + "%s,device", header); + } } } else { /* @@ -1557,6 +1572,11 @@ print_err_hdr(void) { char obuf[SMALL_SCRATCH_BUFLEN]; + if (do_raw) { + push_out("errors"); + return; + } + if (do_conversions == 0) { if (!(do_disk & DISK_EXTENDED)) { (void) snprintf(obuf, sizeof (obuf), diff --git a/usr/src/cmd/stat/mpstat/mpstat.c b/usr/src/cmd/stat/mpstat/mpstat.c index b2c1793a8b..9ca510bf3d 100644 --- a/usr/src/cmd/stat/mpstat/mpstat.c +++ b/usr/src/cmd/stat/mpstat/mpstat.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -163,6 +162,8 @@ main(int argc, char **argv) (void) poll(NULL, 0, poll_interval); } + (void) kstat_close(kc); + return (0); } diff --git a/usr/src/cmd/truss/print.c b/usr/src/cmd/truss/print.c index ccaaf61485..f284539c1a 100644 --- a/usr/src/cmd/truss/print.c +++ b/usr/src/cmd/truss/print.c @@ -1102,6 +1102,10 @@ prt_mod(private_t *pri, int raw, long val) /* print modctl() code */ case MODDEVEXISTS: s = "MODDEVEXISTS"; break; case MODDEVREADDIR: s = "MODDEVREADDIR"; break; case MODDEVNAME: s = "MODDEVNAME"; break; + case MODGETDEVFSPATH_MI_LEN: + s = "MODGETDEVFSPATH_MI_LEN"; break; + case MODGETDEVFSPATH_MI: + s = "MODGETDEVFSPATH_MI"; break; } } diff --git a/usr/src/lib/libdevinfo/Makefile.com b/usr/src/lib/libdevinfo/Makefile.com index adcea87c26..42cf90b29d 100644 --- a/usr/src/lib/libdevinfo/Makefile.com +++ b/usr/src/lib/libdevinfo/Makefile.com @@ -30,7 +30,7 @@ VERS= .1 OBJECTS= devfsinfo.o devinfo.o devinfo_prop_decode.o devinfo_devlink.o \ devinfo_devperm.o devfsmap.o devinfo_devname.o \ - devinfo_finddev.o devinfo_dli.o + devinfo_finddev.o devinfo_dli.o devinfo_dim.o include ../../Makefile.lib include ../../Makefile.rootfs diff --git a/usr/src/lib/libdevinfo/devinfo_devlink.c b/usr/src/lib/libdevinfo/devinfo_devlink.c index 3bc5dadf6d..cd259eaee1 100644 --- a/usr/src/lib/libdevinfo/devinfo_devlink.c +++ b/usr/src/lib/libdevinfo/devinfo_devlink.c @@ -1032,6 +1032,7 @@ handle_free(struct di_devlink_handle **pp) assert(hdp->lock_fd == -1); free(hdp->dev_dir); + free(hdp->db_dir); free(hdp); } diff --git a/usr/src/lib/libdevinfo/devinfo_dim.c b/usr/src/lib/libdevinfo/devinfo_dim.c new file mode 100644 index 0000000000..141f5a9514 --- /dev/null +++ b/usr/src/lib/libdevinfo/devinfo_dim.c @@ -0,0 +1,149 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libdevinfo.h" +#include <strings.h> +#include <sys/modctl.h> + +/* + * + * This file contains interfaces to translate <driver><instance><minorname> + * information into /devices and /dev paths. It does this using interfaces to + * the kernel instance tree so that it can provide translations for devices + * which are no longer present. An example consumer of these interfaces is + * iostat(1M) - which shows, in its first iteration, activity since reboot. + * With persistant kstats, a device which was busy a long time ago can still + * have a decaying presence in iostat output, and that output, when '-n' is + * used, should show the public name. + */ + +typedef struct { + di_devlink_handle_t i_devlink_hdl; +} *idim_t; + +di_dim_t +di_dim_init() +{ + idim_t idim; + + if ((idim = (idim_t)malloc(sizeof (*idim))) == NULL) + return (NULL); + idim->i_devlink_hdl = di_devlink_init(NULL, 0); + if (idim->i_devlink_hdl == NULL) { + free(idim); + return (NULL); + } + return ((di_dim_t)idim); +} + +void +di_dim_fini(di_dim_t dim) +{ + idim_t idim = (idim_t)dim; + + if (idim->i_devlink_hdl) { + (void) di_devlink_fini(&idim->i_devlink_hdl); + } + free(idim); +} + +/*ARGSUSED*/ +char * +di_dim_path_devices(di_dim_t dim, char *drv_name, int instance, + char *minor_name) +{ + major_t major; + int len; + int mlen; + char *devices; + + /* convert drv_name to major_t */ + if (modctl(MODGETMAJBIND, drv_name, strlen(drv_name) + 1, &major) < 0) + return (NULL); + + /* find the length of the devices path given major,instance */ + if (modctl(MODGETDEVFSPATH_MI_LEN, major, instance, &len) != 0) + return (NULL); + + /* + * MODGETDEVFSPATH_MI_LEN result includes '\0' termination, but we + * may need to add space for ":<minor_name>" + */ + if (minor_name) + mlen = len + 1 + strlen(minor_name); + else + mlen = len; + if ((devices = (char *)malloc(mlen)) == NULL) + return (NULL); + + if (modctl(MODGETDEVFSPATH_MI, major, instance, len, devices) != 0) { + free(devices); + return (NULL); + } + + if (minor_name) { + /* add ':<minot_name>' to the end of /devices path */ + (void) strcat(devices, ":"); + (void) strcat(devices, minor_name); + } + return (devices); +} + +/* di_dim_path_dev di_devlink callback */ +static int +di_dim_path_dev_callback(di_devlink_t dl, void *arg) +{ + char **devp = (char **)arg; + char *devpath = (char *)di_devlink_path(dl); + + if (devpath) + *devp = strdup(devpath); + return (DI_WALK_TERMINATE); +} + +char * +di_dim_path_dev(di_dim_t dim, char *drv_name, int instance, char *minor_name) +{ + idim_t idim = (idim_t)dim; + char *devices; + char *dev = NULL; + + /* we must have a minor_name to resolve to a public name */ + if (minor_name == NULL) + return (NULL); + + /* convert <driver><instance><minor_name> to /devices path */ + devices = di_dim_path_devices(dim, drv_name, instance, minor_name); + if (devices == NULL) + return (NULL); + + /* convert /devices path to /dev path */ + (void) di_devlink_walk(idim->i_devlink_hdl, NULL, + devices, DI_PRIMARY_LINK, (void *)&dev, di_dim_path_dev_callback); + free(devices); + return (dev); +} diff --git a/usr/src/lib/libdevinfo/libdevinfo.h b/usr/src/lib/libdevinfo/libdevinfo.h index 0fac182582..56c4b4982c 100644 --- a/usr/src/lib/libdevinfo/libdevinfo.h +++ b/usr/src/lib/libdevinfo/libdevinfo.h @@ -431,6 +431,22 @@ extern int di_prof_add_exclude(di_prof_t, const char *); extern int di_prof_add_symlink(di_prof_t, const char *, const char *); extern int di_prof_add_map(di_prof_t, const char *, const char *); +/* + * Private interfaces for <driver><instance><minor> to path conversion. + * NOTE: These interfaces do not require or cause attach. The implementation + * uses the kernel instance-tree (/etc/path_to_inst) and the di_devlinks + * database information. + */ +typedef struct __di_dim *di_dim_t; + +extern di_dim_t di_dim_init(); +extern void di_dim_fini(di_dim_t); +extern char *di_dim_path_devices(di_dim_t, + char *drv_name, int instance, char *minor_name); +extern char *di_dim_path_dev(di_dim_t, + char *drv_name, int instance, char *minor_name); + + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/libdevinfo/mapfile-vers b/usr/src/lib/libdevinfo/mapfile-vers index 5a6310b03d..34251800bd 100644 --- a/usr/src/lib/libdevinfo/mapfile-vers +++ b/usr/src/lib/libdevinfo/mapfile-vers @@ -150,6 +150,10 @@ SUNWprivate_1.1 { di_devname_action_on_key; di_devname_print_mapinfo; di_driver_private_data; + di_dim_fini; + di_dim_init; + di_dim_path_dev; + di_dim_path_devices; di_init_driver; di_init_impl; di_lookup_node; diff --git a/usr/src/uts/common/os/kstat_fr.c b/usr/src/uts/common/os/kstat_fr.c index db3cf68ffd..1f4525fabb 100644 --- a/usr/src/uts/common/os/kstat_fr.c +++ b/usr/src/uts/common/os/kstat_fr.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -710,17 +709,20 @@ default_kstat_snapshot(kstat_t *ksp, void *buf, int rw) scalehrtime(&kiop->rlastupdate); if (kiop->wcnt != 0) { + /* like kstat_waitq_exit */ hrtime_t wfix = cur_time - kiop->wlastupdate; - kiop->wtime += wfix; + kiop->wlastupdate = cur_time; kiop->wlentime += kiop->wcnt * wfix; + kiop->wtime += wfix; } - kiop->wlastupdate = cur_time; + if (kiop->rcnt != 0) { + /* like kstat_runq_exit */ hrtime_t rfix = cur_time - kiop->rlastupdate; - kiop->rtime += rfix; + kiop->rlastupdate = cur_time; kiop->rlentime += kiop->rcnt * rfix; + kiop->rtime += rfix; } - kiop->rlastupdate = cur_time; break; case KSTAT_TYPE_NAMED: diff --git a/usr/src/uts/common/os/modctl.c b/usr/src/uts/common/os/modctl.c index 3509231ee2..4acbaae74f 100644 --- a/usr/src/uts/common/os/modctl.c +++ b/usr/src/uts/common/os/modctl.c @@ -1098,7 +1098,7 @@ modctl_get_minorname(dev_t dev, int spectype, uint_t len, char *uname) } /* - * Return the size of the devfspath name. + * Return the size of the (dev_t,spectype) devfspath name. */ static int modctl_devfspath_len(dev_t dev, int spectype, uint_t *len) @@ -1124,7 +1124,7 @@ modctl_devfspath_len(dev_t dev, int spectype, uint_t *len) } /* - * Return the devfspath name. + * Return the (dev_t,spectype) devfspath name. */ static int modctl_devfspath(dev_t dev, int spectype, uint_t len, char *uname) @@ -1155,6 +1155,66 @@ modctl_devfspath(dev_t dev, int spectype, uint_t len, char *uname) return (err); } +/* + * Return the size of the (major,instance) devfspath name. + */ +static int +modctl_devfspath_mi_len(major_t major, int instance, uint_t *len) +{ + uint_t sz; + char *name; + + /* get the path name */ + name = kmem_zalloc(MAXPATHLEN, KM_SLEEP); + if (e_ddi_majorinstance_to_path(major, instance, name) != DDI_SUCCESS) { + kmem_free(name, MAXPATHLEN); + return (EINVAL); + } + + sz = strlen(name) + 1; + kmem_free(name, MAXPATHLEN); + + /* copy out the size of the path name */ + if (copyout(&sz, len, sizeof (sz)) != 0) + return (EFAULT); + + return (0); +} + +/* + * Return the (major_instance) devfspath name. + * NOTE: e_ddi_majorinstance_to_path does not require the device to attach to + * return a path - it uses the instance tree. + */ +static int +modctl_devfspath_mi(major_t major, int instance, uint_t len, char *uname) +{ + uint_t sz; + char *name; + int err = 0; + + /* get the path name */ + name = kmem_zalloc(MAXPATHLEN, KM_SLEEP); + if (e_ddi_majorinstance_to_path(major, instance, name) != DDI_SUCCESS) { + kmem_free(name, MAXPATHLEN); + return (EINVAL); + } + + sz = strlen(name) + 1; + + /* Error if the path name is larger than the space allocated */ + if (sz > len) { + kmem_free(name, MAXPATHLEN); + return (ENOSPC); + } + + /* copy out the path name */ + if (copyout(name, uname, sz) != 0) + err = EFAULT; + kmem_free(name, MAXPATHLEN); + return (err); +} + static int modctl_get_fbname(char *path) { @@ -1874,7 +1934,7 @@ modctl(int cmd, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, error = modctl_get_devid(dev, (uint_t)a2, (ddi_devid_t)a3); break; - case MODSIZEOF_MINORNAME: /* sizeof minor nm of dev_t/spectype */ + case MODSIZEOF_MINORNAME: /* sizeof minor nm (dev_t,spectype) */ if (get_udatamodel() == DATAMODEL_NATIVE) { error = modctl_sizeof_minorname((dev_t)a1, (int)a2, (uint_t *)a3); @@ -1888,7 +1948,7 @@ modctl(int cmd, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, #endif break; - case MODGETMINORNAME: /* get minor name of dev_t and spec type */ + case MODGETMINORNAME: /* get minor name of (dev_t,spectype) */ if (get_udatamodel() == DATAMODEL_NATIVE) { error = modctl_get_minorname((dev_t)a1, (int)a2, (uint_t)a3, (char *)a4); @@ -1901,7 +1961,7 @@ modctl(int cmd, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, #endif break; - case MODGETDEVFSPATH_LEN: /* sizeof path nm of dev_t/spectype */ + case MODGETDEVFSPATH_LEN: /* sizeof path nm of (dev_t,spectype) */ if (get_udatamodel() == DATAMODEL_NATIVE) { error = modctl_devfspath_len((dev_t)a1, (int)a2, (uint_t *)a3); @@ -1915,7 +1975,7 @@ modctl(int cmd, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, #endif break; - case MODGETDEVFSPATH: /* get path name of dev_t and spec type */ + case MODGETDEVFSPATH: /* get path name of (dev_t,spec) type */ if (get_udatamodel() == DATAMODEL_NATIVE) { error = modctl_devfspath((dev_t)a1, (int)a2, (uint_t)a3, (char *)a4); @@ -1928,6 +1988,16 @@ modctl(int cmd, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, #endif break; + case MODGETDEVFSPATH_MI_LEN: /* sizeof path nm of (major,instance) */ + error = modctl_devfspath_mi_len((major_t)a1, (int)a2, + (uint_t *)a3); + break; + + case MODGETDEVFSPATH_MI: /* get path name of (major,instance) */ + error = modctl_devfspath_mi((major_t)a1, (int)a2, + (uint_t)a3, (char *)a4); + break; + case MODEVENTS: error = modctl_modevents((int)a1, a2, a3, a4, (uint_t)a5); diff --git a/usr/src/uts/common/os/policy.c b/usr/src/uts/common/os/policy.c index 592c6a97be..2f804b1d0e 100644 --- a/usr/src/uts/common/os/policy.c +++ b/usr/src/uts/common/os/policy.c @@ -1654,13 +1654,22 @@ secpolicy_modctl(const cred_t *cr, int cmd) { switch (cmd) { case MODINFO: + case MODGETMAJBIND: case MODGETPATH: case MODGETPATHLEN: - case MODGETFBNAME: case MODGETNAME: + case MODGETFBNAME: case MODGETDEVPOLICY: case MODGETDEVPOLICYBYNAME: - case MODGETMAJBIND: + case MODDEVT2INSTANCE: + case MODSIZEOF_DEVID: + case MODGETDEVID: + case MODSIZEOF_MINORNAME: + case MODGETMINORNAME: + case MODGETDEVFSPATH_LEN: + case MODGETDEVFSPATH: + case MODGETDEVFSPATH_MI_LEN: + case MODGETDEVFSPATH_MI: /* Unprivileged */ return (0); case MODLOAD: diff --git a/usr/src/uts/common/sys/modctl.h b/usr/src/uts/common/sys/modctl.h index 5e9450dde5..255d02d7b2 100644 --- a/usr/src/uts/common/sys/modctl.h +++ b/usr/src/uts/common/sys/modctl.h @@ -256,6 +256,8 @@ struct modlinkage { #define MODDEVEXISTS 35 #define MODDEVREADDIR 36 #define MODDEVNAME 37 +#define MODGETDEVFSPATH_MI_LEN 38 +#define MODGETDEVFSPATH_MI 39 /* * sub cmds for MODEVENTS |