/*-
* Copyright (c) 2003 Michael Reifenberger (Michael@Reifenberger.com)
* All rights reserved.
*
* since this software is derived from gstat(8) the following applies also:
*
* Copyright (c) 2003 Poul-Henning Kamp
* All rights reserved.
*
* 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. The names of the authors may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD: src/usr.sbin/gstat/gstat.c,v 1.5 2003/03/22 09:47:02 keramida Exp $
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <paths.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <err.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <libgeom.h>
#include <sys/resource.h>
#include <devstat.h>
#include <sys/devicestat.h>
static int time_I = 3600;
static void stop_da( const char *name );
static void stop_others( const char *name );
static void usage(void);
struct devs {
char name[7];
uint64_t lastt;
};
int
main(int argc, char **argv)
{
int error, i;
struct devstat *gsp, *gsq;
struct stat sb;
char path[32];
void *sp, *sq;
double dt;
struct timespec tp, tq;
struct gmesh gmp;
struct gprovider *pp;
struct gident *gid;
struct devs *devs, *devp;
char *p;
uint64_t u64;
time_t ltime;
while ((i = getopt( argc, argv, "I:" ) ) != -1 ) {
switch ( i ) {
case 'I':
p = NULL;
i = strtoul( optarg, &p, 0 );
if ( p == optarg || errno == EINVAL ||
errno == ERANGE ) {
errx( 1, "Invalid argument to -I" );
} else if ( !strcmp( p, "h" ) )
i *= 3600;
else if ( !strcmp( p, "m" ) )
i *= 60;
else if ( !strcmp( p, "s" ) )
i *= 1;
time_I = i;
break;
case '?':
default:
usage();
}
}
argc -= optind;
argv += optind;
if ( argc == 0 )
usage();
devs = calloc( argc, sizeof( struct devs ) );
devp = devs;
for( i = 0; i < argc; i++ ) {
sprintf( path, "/dev/%s", argv[i] );
error = stat( path, &sb );
if( error != 0 ) {
errx( 1, "Error %d accessing %s", errno, path );
}
snprintf( devs[i].name, 6, argv[i] );
devs[i].lastt = 1;
}
error = daemon( 0, 0 );
if( error != 0 )
errx( 1, "Error %d running as daemon", errno );
i = geom_gettree( &gmp );
if ( i != 0 )
err( 1, "geom_gettree = %d", i );
error = geom_stats_open();
if ( error )
err( 1, "geom_stats_open()" );
sq = NULL;
sq = geom_stats_snapshot_get();
if ( sq == NULL )
err( 1, "geom_stats_snapshot()" );
geom_stats_snapshot_timestamp( sq, &tq );
while ( 1 ) {
sleep( time_I );
sp = geom_stats_snapshot_get();
if ( sp == NULL )
err( 1, "geom_stats_snapshot()" );
geom_stats_snapshot_timestamp( sp, &tp );
dt = tp.tv_sec - tq.tv_sec;
dt += ( tp.tv_nsec - tq.tv_nsec ) * 1e-9;
tq = tp;
geom_stats_snapshot_reset( sp );
geom_stats_snapshot_reset( sq );
while( 1 ) {
gsp = geom_stats_snapshot_next( sp );
gsq = geom_stats_snapshot_next( sq );
if ( gsp == NULL || gsq == NULL )
break;
if ( gsp->id == NULL )
continue;
gid = geom_lookupid( &gmp, gsp->id );
if ( gid == NULL ) {
geom_deletetree( &gmp );
i = geom_gettree( &gmp );
if ( i != 0 )
err( 1, "geom_gettree = %d", i );
gid = geom_lookupid( &gmp, gsp->id );
}
if ( gid == NULL )
continue;
if ( gid != NULL && gid->lg_what == ISCONSUMER )
continue;
if ( gsp->sequence0 != gsp->sequence1 ) {
continue;
}
devstat_compute_statistics( gsp, gsq, dt,
DSM_TOTAL_TRANSFERS, &u64,
DSM_NONE );
*gsq = *gsp;
pp = gid->lg_ptr;
i = strlen( pp->lg_name );
ltime = time( NULL );
for( i = 0; i < argc; i++ ) {
if( ( strncmp( pp->lg_name, devs[i].name, 6 ) == 0 ) ) {
if( ( u64 == 0 ) &&( devs[i].lastt != 0 ) ) {
syslog( LOG_LOCAL0 | LOG_INFO,
"%s: %4ju@%s\n", pp->lg_name,
(uintmax_t)u64, ctime( <ime ) );
if( pp->lg_name[0] == 'd' && pp->lg_name[1] == 'a' ) {
stop_da( pp->lg_name );
// } else if ( pp->name[0] == 'a' && pp->name[1] == 'd' ) {
} else {
stop_others( pp->lg_name );
}
devs[i].lastt = 0;
} else if( u64 != 0 ) {
devs[i].lastt = u64;
}
}
}
}
geom_stats_snapshot_free( sp );
}
exit (0);
}
static void stop_da( const char *name ) {
char cmd[256];
snprintf( cmd, 256,
"/sbin/camcontrol stop %s"
"| /usr/bin/logger -p local0.info -t gstopd 2>&1", name );
system( cmd );
}
static void stop_others( const char *name ) {
char cmd[256];
snprintf( cmd, 256,
"/bin/echo 'would stop %s' if it where implemented"
"| /usr/bin/logger -p local0.info -t gstopd 2>&1", name );
system( cmd );
}
static void usage(void)
{
fprintf(stderr, "usage: gstopd [-I interval] daX ...\n");
exit(1);
/* NOTREACHED */
}
syntax highlighted by Code2HTML, v. 0.9.1