/* *************************************************************************** * Write basic stats, read from /proc/diskstats or from sysfs. * * IN: * @curr Index in array for current sample statistics. * @itv Interval of time. * @fctr Conversion factor. * @shi Structures describing the devices and partitions. * @ioi Current sample statistics. * @ioj Previous sample statistics. *************************************************************************** */ void write_basic_stat(int curr, unsigned long long itv, int fctr, struct io_hdr_stats *shi, struct io_stats *ioi, struct io_stats *ioj) { char *devname = NULL; unsigned long long rd_sec, wr_sec; /* Print device name */ if (DISPLAY_PERSIST_NAME_I(flags)) { devname = get_persistent_name_from_pretty(shi->name); } if (!devname) { devname = shi->name; } if (DISPLAY_HUMAN_READ(flags)) { printf("%s\n%13s", devname, ""); } else { printf("%-13s", devname); } /* Print stats coming from /sys or /proc/diskstats */ rd_sec = ioi->rd_sectors - ioj->rd_sectors; if ((ioi->rd_sectors < ioj->rd_sectors) && (ioj->rd_sectors <= 0xffffffff)) { rd_sec &= 0xffffffff; } wr_sec = ioi->wr_sectors - ioj->wr_sectors; if ((ioi->wr_sectors < ioj->wr_sectors) && (ioj->wr_sectors <= 0xffffffff)) { wr_sec &= 0xffffffff; } printf(" %8.2f %12.2f %12.2f %10llu %10llu\n", S_VALUE(ioj->rd_ios + ioj->wr_ios, ioi->rd_ios + ioi->wr_ios, itv), ll_s_value(ioj->rd_sectors, ioi->rd_sectors, itv) / fctr, ll_s_value(ioj->wr_sectors, ioi->wr_sectors, itv) / fctr, (unsigned long long) rd_sec / fctr, (unsigned long long) wr_sec / fctr); }
/* *************************************************************************** * Display extended stats, read from /proc/{diskstats,partitions} or /sys *************************************************************************** */ void write_ext_stat(int curr, unsigned long long itv, int flags, int fctr, struct io_hdr_stats *shi, struct io_stats *ioi, struct io_stats *ioj, int scan_type, int first_time ) { unsigned long long rd_sec, wr_sec; double tput, util, await, svctm, arqsz, nr_ios; int size, year, mon, day, hour, min, sec; /* * Counters overflows are possible, but don't need to be handled in * a special way: the difference is still properly calculated if the * result is of the same type as the two values. * Exception is field rq_ticks which is incremented by the number of * I/O in progress times the number of milliseconds spent doing I/O. * But the number of I/O in progress (field ios_pgr) happens to be * sometimes negative... */ nr_ios = (ioi->rd_ios - ioj->rd_ios) + (ioi->wr_ios - ioj->wr_ios); tput = ((double) nr_ios) * HZ / itv; util = S_VALUE(ioj->tot_ticks, ioi->tot_ticks, itv); svctm = tput ? util / tput : 0.0; /* * kernel gives ticks already in milliseconds for all platforms * => no need for further scaling. */ await = nr_ios ? ((ioi->rd_ticks - ioj->rd_ticks) + (ioi->wr_ticks - ioj->wr_ticks)) / nr_ios : 0.0; rd_sec = ioi->rd_sectors - ioj->rd_sectors; if ((ioi->rd_sectors < ioj->rd_sectors) && (ioj->rd_sectors <= 0xffffffff)) rd_sec &= 0xffffffff; wr_sec = ioi->wr_sectors - ioj->wr_sectors; if ((ioi->wr_sectors < ioj->wr_sectors) && (ioj->wr_sectors <= 0xffffffff)) wr_sec &= 0xffffffff; arqsz = nr_ios ? (rd_sec + wr_sec) / nr_ios : 0.0; /* printf("%-13s", shi->name); if (strlen(shi->name) > 10) printf("\n "); */ memcpy( &Disk_usage.device, shi->name, strlen(shi->name) ); /* rrq/s wrq/s r/s w/s rsec wsec rqsz qusz await svctm %util */ /* printf(" %8.2f %8.2f %5.2f %5.2f %8.2f %8.2f %8.2f %8.2f %7.2f %6.2f %6.2f\n", S_VALUE(ioj->rd_merges, ioi->rd_merges, itv), S_VALUE(ioj->wr_merges, ioi->wr_merges, itv), S_VALUE(ioj->rd_ios, ioi->rd_ios, itv), S_VALUE(ioj->wr_ios, ioi->wr_ios, itv), ll_s_value(ioj->rd_sectors, ioi->rd_sectors, itv) / fctr, ll_s_value(ioj->wr_sectors, ioi->wr_sectors, itv) / fctr, arqsz, S_VALUE(ioj->rq_ticks, ioi->rq_ticks, itv) / 1000.0, await, */ /* The ticks output is biased to output 1000 ticks per second */ /* svctm, */ /* Again: ticks in milliseconds */ /* util / 10.0); */ Disk_usage.read_requests = S_VALUE(ioj->rd_ios, ioi->rd_ios, itv); Disk_usage.write_requests = S_VALUE(ioj->wr_ios, ioi->wr_ios, itv); Disk_usage.kb_read = ll_s_value(ioj->rd_sectors, ioi->rd_sectors, itv) / fctr; Disk_usage.kb_write = ll_s_value(ioj->wr_sectors, ioi->wr_sectors, itv) / fctr; Disk_usage.await = await; Disk_usage.svctm = svctm; Disk_usage.util = util / 10.0; Total_kb_read += Disk_usage.kb_read; Total_kb_write += Disk_usage.kb_write; Total_await += await; Total_svctm += svctm; Total_util += Disk_usage.util; Total_reports++; /* If the gnuplot file is open, write Disk stats to file. */ if( Disk_fd < 0 ) return; /* Did a start of volume event occur? */ if( VOLUME_EVENT == scan_type ){ unix_time( &Scan_info.scan_time, &year, &mon, &day, &hour, &min, &sec ); if( year >= 2000 ) year -= 2000; else year -= 1900; /* Do only the first time through. */ if( first_time ){ memset( Buffer, 0, sizeof(Buffer) ); sprintf( Buffer, "#===========================================================\ ==========================================\n" ); size = strlen( Buffer ); if( write( Disk_fd, Buffer, size ) != size ) fprintf( stderr, "Write to Disk_fd Failed\n" ); memset( Buffer, 0, sizeof(Buffer) ); sprintf( Buffer, "# %02d/%02d/%02d %02d:%02d:%02d VOLUME #: %4d VCP: %3d\n", mon, day, year, hour, min, sec, Volume_num, Scan_info.vcp ); size = strlen( Buffer ); if( write( Disk_fd, Buffer, size ) != size ) fprintf( stderr, "Write to Disk_fd Failed\n" ); memset( Buffer, 0, sizeof(Buffer) ); sprintf( Buffer,"# Cut Time (s) Total (s) Read (KB) Write (KB) Await (ms) \ SvcTime (ms) Util (%%)\n" ); size = strlen( Buffer ); if( write( Disk_fd, Buffer, size ) != size ) fprintf( stderr, "Write to Disk_fd Failed\n" ); } }
/* *************************************************************************** * Display extended stats, read from /proc/{diskstats,partitions} or /sys. * * IN: * @curr Index in array for current sample statistics. * @itv Interval of time. * @fctr Conversion factor. * @shi Structures describing the devices and partitions. * @ioi Current sample statistics. * @ioj Previous sample statistics. *************************************************************************** */ void write_ext_stat(int curr, unsigned long long itv, int fctr, struct io_hdr_stats *shi, struct io_stats *ioi, struct io_stats *ioj) { char *devname = NULL; struct stats_disk sdc, sdp; struct ext_disk_stats xds; double r_await, w_await; /* * Counters overflows are possible, but don't need to be handled in * a special way: The difference is still properly calculated if the * result is of the same type as the two values. * Exception is field rq_ticks which is incremented by the number of * I/O in progress times the number of milliseconds spent doing I/O. * But the number of I/O in progress (field ios_pgr) happens to be * sometimes negative... */ sdc.nr_ios = ioi->rd_ios + ioi->wr_ios; sdp.nr_ios = ioj->rd_ios + ioj->wr_ios; sdc.tot_ticks = ioi->tot_ticks; sdp.tot_ticks = ioj->tot_ticks; sdc.rd_ticks = ioi->rd_ticks; sdp.rd_ticks = ioj->rd_ticks; sdc.wr_ticks = ioi->wr_ticks; sdp.wr_ticks = ioj->wr_ticks; sdc.rd_sect = ioi->rd_sectors; sdp.rd_sect = ioj->rd_sectors; sdc.wr_sect = ioi->wr_sectors; sdp.wr_sect = ioj->wr_sectors; compute_ext_disk_stats(&sdc, &sdp, itv, &xds); r_await = (ioi->rd_ios - ioj->rd_ios) ? (ioi->rd_ticks - ioj->rd_ticks) / ((double) (ioi->rd_ios - ioj->rd_ios)) : 0.0; w_await = (ioi->wr_ios - ioj->wr_ios) ? (ioi->wr_ticks - ioj->wr_ticks) / ((double) (ioi->wr_ios - ioj->wr_ios)) : 0.0; /* Print device name */ if (DISPLAY_PERSIST_NAME_I(flags)) { devname = get_persistent_name_from_pretty(shi->name); } if (!devname) { devname = shi->name; } if (DISPLAY_HUMAN_READ(flags)) { printf("%s\n%13s", devname, ""); } else { printf("%-13s", devname); } /* rrq/s wrq/s r/s w/s rsec wsec rqsz qusz await r_await w_await svctm %util */ printf(" %8.2f %8.2f %7.2f %7.2f %8.2f %8.2f %8.2f %8.2f %7.2f %7.2f %7.2f %6.2f %6.2f\n", S_VALUE(ioj->rd_merges, ioi->rd_merges, itv), S_VALUE(ioj->wr_merges, ioi->wr_merges, itv), S_VALUE(ioj->rd_ios, ioi->rd_ios, itv), S_VALUE(ioj->wr_ios, ioi->wr_ios, itv), ll_s_value(ioj->rd_sectors, ioi->rd_sectors, itv) / fctr, ll_s_value(ioj->wr_sectors, ioi->wr_sectors, itv) / fctr, xds.arqsz, S_VALUE(ioj->rq_ticks, ioi->rq_ticks, itv) / 1000.0, xds.await, r_await, w_await, /* The ticks output is biased to output 1000 ticks per second */ xds.svctm, /* * Again: Ticks in milliseconds. * In the case of a device group (option -g), shi->used is the number of * devices in the group. Else shi->used equals 1. */ shi->used ? xds.util / 10.0 / (double) shi->used : xds.util / 10.0); /* shi->used should never be null here */ }