acquire_iodevs.c revision 4be70790cfe8d92fa6249ff02f1e5f1268ae2b8e
/*
* 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
* 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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "statcommon.h"
#include "dsr.h"
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <strings.h>
#include <errno.h>
#include <limits.h>
static struct iodev_snapshot *
make_controller(int cid)
{
struct iodev_snapshot *new;
return (new);
}
static struct iodev_snapshot *
{
struct iodev_snapshot *pos;
struct iodev_snapshot *pos2;
return (pos);
return (pos2);
}
return (NULL);
}
static enum iodev_type
{
switch (type) {
case IODEV_CONTROLLER: return (0);
case IODEV_IOPATH_LT: return (0);
case IODEV_IOPATH_LI: return (0);
case IODEV_NFS: return (0);
case IODEV_TAPE: return (0);
case IODEV_IOPATH_LTI: return (IODEV_DISK);
case IODEV_DISK: return (IODEV_CONTROLLER);
case IODEV_PARTITION: return (IODEV_DISK);
}
return (IODEV_UNKNOWN);
}
static int
{
}
static struct iodev_snapshot *
{
struct iodev_snapshot *pos;
struct iodev_snapshot *pos2;
return (NULL);
return (NULL);
if (parent_type == IODEV_CONTROLLER) {
continue;
continue;
return (pos);
}
return (NULL);
return (pos);
}
/* IODEV_DISK parent */
return (pos);
continue;
continue;
return (pos2);
}
}
return (NULL);
}
/*
* Introduce an index into the list to speed up insert_into looking for the
* right position in the list. This index is an AVL tree of all the
* iodev_snapshot in the list.
*/
static int
{
(struct iodev_snapshot *)is2);
if (c > 0)
return (1);
if (c < 0)
return (-1);
return (0);
}
static void
{
if (l == NULL)
return;
}
static void
{
if (l == NULL)
return;
avl_remove(l, elem);
if (avl_numnodes(l) == 0) {
avl_destroy(l);
free(l);
}
}
static void
{
if (l == NULL)
return;
}
static void
{
}
static void
struct iodev_snapshot *new)
{
return;
}
else
}
static void
struct iodev_snapshot *new)
{
return;
}
}
static void
{
avl_tree_t *l;
void *p;
return;
}
/*
* Optimize the search: instead of walking the entire list
* (which can contain thousands of nodes), search in the AVL
* tree the nearest node and reposition the startup point to
* this node rather than always starting from the beginning
* of the list.
*/
if (l != NULL) {
if (p == NULL) {
}
if (p != NULL) {
tmp = (struct iodev_snapshot *)p;
}
}
for (;;) {
return;
}
break;
}
}
static int
{
}
static int
{
type == IODEV_IOPATH_LTI);
}
static void
{
struct iodev_snapshot **list;
parent->is_nr_children++;
} else {
ss->s_nr_iodevs++;
}
}
/* return 1 if dev passes filter */
static int
{
char *path;
int ifnl;
size_t i;
/* no filter, pass */
return (1); /* pass */
/* no filtered names, pass if not floppy and skipped */
for (i = 0; i < df->if_nr_names; i++) {
return (1); /* pass */
/* if filter is a path allow partial match */
if (path &&
return (1); /* pass */
}
return (0); /* fail */
}
/* return 1 if path is an mpxio path associated with dev */
static int
{
int dnl;
return (1); /* yes */
return (0); /* no */
}
/* select which I/O devices to collect stats for */
static void
struct iodev_filter *df)
{
int nr_iodevs;
int nr_iodevs_orig;
if (nr_iodevs == UNLIMITED_IODEVS)
/* add the full matches */
continue; /* failed full match */
/*
* Add all mpxio paths associated with match above. Added
* paths don't count against nr_iodevs.
*/
while (ppos) {
continue; /* not an mpxio path */
}
}
nr_iodevs--;
}
/*
* If we had a filter, and *nothing* passed the filter then we
* don't want to fill the remaining slots - it is just confusing
* if we don that, it makes it look like the filter code is broken.
*/
/* now insert any iodevs into the remaining slots */
continue;
--nr_iodevs;
}
}
/* clear the unwanted ones */
while (pos) {
}
}
static int
struct iodev_snapshot *disk)
{
return (errno);
return (0);
}
static int
{
struct iodev_snapshot *pos;
int err = 0;
/* controllers don't have stats (yet) */
return (errno);
}
return (err);
return (err);
}
}
}
return (0);
}
static int
{
return (0);
char kstat_name[KSTAT_STRLEN];
char *dname = kstat_name;
struct iodev_snapshot *iodev;
continue;
continue;
/*
* Some drivers may not follow the naming convention
* for error kstats (i.e., drivername,err) so
* be sure we don't walk off the end.
*/
dname++;
ename++;
}
*dname = '\0';
continue;
return (errno);
return (errno);
}
return (0);
}
static void
{
char *target;
const char *p1;
const char *p2;
return;
return;
++p1;
if (!*p1)
return;
++p1;
++p2;
return;
} else if (ret == 1) {
}
}
}
static void
{
if (!(types & SNAP_IODEV_PRETTY))
return;
return;
}
return;
if (types & SNAP_IODEV_PRETTY) {
}
/*
* we fill in pretty name wether it is asked for or not because
* it could be used in a filter by match_iodevs.
*/
}
static enum iodev_type
{
return (IODEV_DISK);
return (IODEV_PARTITION);
return (IODEV_NFS);
return (IODEV_IOPATH_LTI);
return (IODEV_TAPE);
return (IODEV_UNKNOWN);
}
static int
get_lti(char *s,
{
int num = 0;
}
/* get the lun, target, and initiator name and instance */
static void
{
/*
* If it is iopath or ssd then pad the name with i/t/l so we can sort
* by alpha order and set type for IOPATH to DISK since we want to
* have it grouped with its ssd parent. The lun can be 5 digits,
* the target can be 4 digits, and the initiator can be 3 digits and
* the padding is done appropriately for string comparisons.
*/
} else {
/* set to disk so we sort with disks */
*type = IODEV_DISK;
}
} else {
}
}
int
{
if ((!disk_or_partition(type1)) ||
(!disk_or_partition(type2))) {
/* neutral sort order between disk and part */
return (-1);
}
return (1);
}
}
/* controller doesn't have ksp */
}
return (-1);
}
return (1);
}
} else {
return (-1);
}
return (1);
}
}
}
/* update the target reads and writes */
static void
{
/*
* Stash the t_delta in the crtime for use in show_disk
* NOTE: this can't be done in show_disk because the
* itl entry is removed for the old format
*/
}
/*
* Create a new synthetic device entry of the specified type. The supported
* synthetic types are IODEV_IOPATH_LT and IODEV_IOPATH_LI.
*/
static struct iodev_snapshot *
{
char *ptr;
char lun_name[KSTAT_STRLEN];
char tgt_name[KSTAT_STRLEN];
char initiator_name[KSTAT_STRLEN];
return (NULL);
return (NULL);
}
}
sizeof (old->is_parent_id));
if (type == IODEV_IOPATH_LT) {
/* make new synthetic entry that is the LT */
/* set the id to the target id */
if (ptr)
*ptr = '\0';
}
} else if (type == IODEV_IOPATH_LI) {
/* make new synthetic entry that is the LI */
/* set the id to the initiator number */
if (ptr)
}
}
return (tptr);
}
/*
* This is to get the original -X LI format (e.g. ssd1.fp0). When an LTI kstat
* is found - traverse the children looking for the same initiator and sum
* them up. Add an LI entry and delete all of the LTI entries with the same
* initiator.
*/
static int
{
char lun_name[KSTAT_STRLEN];
char tgt_name[KSTAT_STRLEN];
char initiator_name[KSTAT_STRLEN];
int err;
return (err);
return (1);
}
/* found the same initiator */
parent->is_nr_children--;
break;
}
}
if (!pos) {
/* make the first LI entry */
if (parent) {
} else {
pos);
}
}
}
}
return (0);
}
/*
* We have the LTI kstat, now add an entry for the LT that sums up all of
* the LTI's with the same target(t).
*/
static int
{
char lun_name[KSTAT_STRLEN];
char tgt_name[KSTAT_STRLEN];
char initiator_name[KSTAT_STRLEN];
int err;
return (err);
return (1);
}
/* found the same target */
break;
}
}
if (!pos) {
if (parent) {
parent->is_nr_children++;
} else {
}
}
}
}
return (0);
}
/* Find the longest is_name field to aid formatting of output */
static int
{
struct iodev_snapshot *entry;
}
return (max);
}
int
{
struct iodev_snapshot *pos;
int err = 0;
ss->s_nr_iodevs = 0;
ss->s_iodevs_is_name_maxlen = 0;
/*
* Call cleanup_iodevs_snapshot() so that a cache miss in
* lookup_ks_name() will result in a fresh snapshot.
*/
enum iodev_type type;
continue;
/* e.g. "usb_byte_count" is not handled */
continue;
continue;
goto out;
}
/*
* We must insert in sort order so e.g. vmstat -l
* chooses in order.
*/
}
/* before acquire_stats for collate_controller()'s benefit */
goto out;
}
goto out;
/*
* -Y: kstats are LTI, need to create a synthetic LT
* for -Y output.
*/
return (err);
}
}
/*
* -X: kstats are LTI, need to create a synthetic LI and
* delete the LTI for -X output
*/
return (err);
}
}
/* determine width of longest is_name */
err = 0;
out:
return (err);
}
void
{
while (iodev->is_children) {
}
}
}
}