/*- * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 */ }