/*-
* Copyright (c) 1996, 1997, 1999, 2000, 2009 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
* NASA Ames Research Center.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1982, 1986, 1988, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94
*/
/*
* Function prototypes for sysctl nodes
*/
static int sysctl_hw_disknames(SYSCTLFN_PROTO);
static int sysctl_hw_iostatnames(SYSCTLFN_PROTO);
static int sysctl_hw_iostats(SYSCTLFN_PROTO);
/*
* A global list of all drives attached to the system. May grow or
* shrink over time.
*/
struct iostatlist_head iostatlist = TAILQ_HEAD_INITIALIZER(iostatlist);
int iostat_count; /* number of drives in global drivelist */
krwlock_t iostatlist_lock;
/*
* Searches the iostatlist for the iostat corresponding to the
* name provided.
*/
struct io_stats *
iostat_find(const char *name)
{
struct io_stats *iostatp;
/*
* Set the attached timestamp.
*/
getmicrouptime(&stats->io_attachtime);
/*
* Link into the drivelist.
*/
rw_enter(&iostatlist_lock, RW_WRITER);
TAILQ_INSERT_TAIL(&iostatlist, stats, io_link);
iostat_count++;
rw_exit(&iostatlist_lock);
/*
* multiply timeval by unsigned integer and add to result
*/
static void
timermac(struct timeval *a, uint64_t count, struct timeval *res)
{
struct timeval part = *a;
while (count) {
if (count & 1)
timeradd(res, &part, res);
timeradd(&part, &part, &part);
count >>= 1;
}
}
/*
* Increment the iostat wait counter.
* Accumulate wait time and timesum.
*
* Wait time is spent in the device bufq.
*/
void
iostat_wait(struct io_stats *stats)
{
struct timeval dv_time, diff_time;
int32_t count;
/*
* Decrement the iostat wait counter.
* Increment the iostat busy counter.
* Accumulate wait and busy times and timesums.
*
* Busy time is spent being processed by the device.
*
* Old devices do not yet measure wait time, so skip
* processing it if the counter is still zero.
*/
void
iostat_busy(struct io_stats *stats)
{
struct timeval dv_time, diff_time;
int32_t count;
KASSERT(stats->io_wait >= 0); /* > 0 when iostat_wait is used */
KASSERT(stats->io_busy >= 0);
if (where == NULL)
needed += strlen(stats->io_name) + 1;
else {
memset(bf, 0, sizeof(bf));
if (first) {
strncpy(bf, stats->io_name, sizeof(bf));
/* account for trailing NUL byte */
needed += 1;
first = 0;
} else {
bf[0] = ' ';
strncpy(bf + 1, stats->io_name,
sizeof(bf) - 1);
}
bf[IOSTATNAMELEN] = '\0';
slen = strlen(bf);
if (left < slen + 1)
break;
/* +1 to copy out the trailing NUL byte */
error = copyout(bf, where, slen + 1);
if (error)
break;
where += slen;
needed += slen;
left -= slen;
}
}
rw_exit(&iostatlist_lock);
*oldlenp = needed;
return (error);
}
static int
sysctl_hw_iostats(SYSCTLFN_ARGS)
{
struct io_sysctl sdrive;
struct io_stats *stats;
char *where = oldp;
size_t tocopy, left;
int error;
if (newp != NULL)
return (EPERM);
/*
* The original hw.diskstats call was broken and did not require
* the userland to pass in its size of struct disk_sysctl. This
* was fixed after NetBSD 1.6 was released.
*/
if (namelen == 0)
tocopy = offsetof(struct io_sysctl, busy);
else
tocopy = name[0];