#include "version.h"
#include "cifsiostat.h"
-#include "common.h"
+#include "rd_stats.h"
+#include "count.h"
#ifdef USE_NLS
#include <locale.h>
#define _(string) (string)
#endif
+#ifdef USE_SCCSID
#define SCCSID "@(#)sysstat-" VERSION ": " __FILE__ " compiled " __DATE__ " " __TIME__
char *sccsid(void) { return (SCCSID); }
+#endif
+
+#ifdef TEST
+void int_handler(int n) { return; }
+#endif
-unsigned long long uptime[2] = {0, 0};
-unsigned long long uptime0[2] = {0, 0};
+unsigned long long uptime_cs[2] = {0, 0};
struct cifs_stats *st_cifs[2];
struct io_hdr_stats *st_hdr_cifs;
int cifs_nr = 0; /* Nb of CIFS mounted directories found */
int cpu_nr = 0; /* Nb of processors on the machine */
int flags = 0; /* Flag for common options and system state */
+int dplaces_nr = -1; /* Number of decimal places */
long interval = 0;
-char timestamp[64];
+char timestamp[TIMESTAMP_LEN];
+struct sigaction alrm_act;
/*
***************************************************************************
fprintf(stderr, _("Usage: %s [ options ] [ <interval> [ <count> ] ]\n"),
progname);
+#ifdef DEBUG
+ fprintf(stderr, _("Options are:\n"
+ "[ --dec={ 0 | 1 | 2 } ] [ --human ] [ -h ] [ -k | -m ] [ -t ] [ -V ] [ --debuginfo ]\n"));
+#else
fprintf(stderr, _("Options are:\n"
- "[ -h ] [ -k | -m ] [ -t ] [ -V ]\n"));
+ "[ --dec={ 0 | 1 | 2 } ] [ --human ] [ -h ] [ -k | -m ] [ -t ] [ -V ]\n"));
+#endif
exit(1);
}
* SIGALRM signal handler.
*
* IN:
- * @sig Signal number. Set to 0 for the first time, then to SIGALRM.
+ * @sig Signal number.
***************************************************************************
*/
void alarm_handler(int sig)
{
- signal(SIGALRM, alarm_handler);
alarm(interval);
}
/* File non-existent */
return 0;
- while (fgets(line, 128, fp) != NULL) {
-
+ while (fgets(line, sizeof(line), fp) != NULL) {
+
if (!strncmp(line, "Share (unique mount targets): ", 30)) {
sscanf(line + 30, "%d", &cifs);
break;
void io_sys_init(void)
{
int i;
-
+
/* How many processors on this machine? */
- cpu_nr = get_cpu_nr(~0);
+ cpu_nr = get_cpu_nr(~0, FALSE);
/* Get number of CIFS directories in /proc/fs/cifs/Stats */
if ((cifs_nr = get_cifs_nr()) > 0) {
cifs_nr += NR_CIFS_PREALLOC;
}
- st_hdr_cifs = (struct io_hdr_stats *) calloc(cifs_nr, IO_HDR_STATS_SIZE);
-
- /* Allocate structures for number of CIFS directories found */
- for (i = 0; i < 2; i++) {
- if ((st_cifs[i] =
- (struct cifs_stats *) calloc(cifs_nr, CIFS_STATS_SIZE)) == NULL) {
+
+ if (cifs_nr > 0) {
+ if ((st_hdr_cifs = (struct io_hdr_stats *) calloc(cifs_nr, IO_HDR_STATS_SIZE)) == NULL) {
perror("malloc");
exit(4);
}
+
+ /* Allocate structures for number of CIFS directories found */
+ for (i = 0; i < 2; i++) {
+ if ((st_cifs[i] =
+ (struct cifs_stats *) calloc(cifs_nr, CIFS_STATS_SIZE)) == NULL) {
+ perror("malloc");
+ exit(4);
+ }
+ }
+ }
+ else {
+ /*
+ * cifs_nr value is probably zero, but it can also be negative
+ * (possible overflow when adding NR_CIFS_PREALLOC above).
+ */
+ cifs_nr = 0;
}
}
/* Free CIFS directories structures */
for (i = 0; i < 2; i++) {
-
- if (st_cifs[i]) {
- free(st_cifs[i]);
- }
- }
-
- if (st_hdr_cifs) {
- free(st_hdr_cifs);
+ free(st_cifs[i]);
}
+
+ free(st_hdr_cifs);
}
/*
*/
void save_stats(char *name, int curr, struct cifs_stats *st_io)
{
- int i;
+ int i, j;
struct io_hdr_stats *st_hdr_cifs_i;
struct cifs_stats *st_cifs_i;
/* Look for CIFS directory in data table */
for (i = 0; i < cifs_nr; i++) {
st_hdr_cifs_i = st_hdr_cifs + i;
- if (!strcmp(st_hdr_cifs_i->name, name)) {
+ if ((st_hdr_cifs_i->used == TRUE) &&
+ (!strcmp(st_hdr_cifs_i->name, name))) {
break;
}
}
-
+
if (i == cifs_nr) {
/*
* This is a new filesystem: Look for an unused entry to store it.
if (!st_hdr_cifs_i->used) {
/* Unused entry found... */
st_hdr_cifs_i->used = TRUE; /* Indicate it is now used */
- strcpy(st_hdr_cifs_i->name, name);
- st_cifs_i = st_cifs[!curr] + i;
- memset(st_cifs_i, 0, CIFS_STATS_SIZE);
+ st_hdr_cifs_i->active = TRUE;
+ strncpy(st_hdr_cifs_i->name, name, MAX_NAME_LEN - 1);
+ st_hdr_cifs_i->name[MAX_NAME_LEN - 1] = '\0';
+ st_cifs_i = st_cifs[curr] + i;
+ *st_cifs_i = *((struct cifs_stats *) st_io);
break;
}
}
- }
- if (i < cifs_nr) {
+ if (i == cifs_nr) {
+ /*
+ * It is a new CIFS directory
+ * but there is no free structure to store it.
+ */
+
+ /* All entries are used: The number has to be increased */
+ cifs_nr = cifs_nr + 5;
+
+ /* Increase the size of st_hdr_ionfs buffer */
+ if ((st_hdr_cifs = (struct io_hdr_stats *)
+ realloc(st_hdr_cifs, cifs_nr * IO_HDR_STATS_SIZE)) == NULL) {
+ perror("malloc");
+ exit(4);
+ }
+
+ /* Set the new entries inactive */
+ for (j = 0; j < 5; j++) {
+ st_hdr_cifs_i = st_hdr_cifs + i + j;
+ st_hdr_cifs_i->used = FALSE;
+ st_hdr_cifs_i->active = FALSE;
+ }
+
+ /* Increase the size of st_hdr_ionfs buffer */
+ for (j = 0; j < 2; j++) {
+ if ((st_cifs[j] = (struct cifs_stats *)
+ realloc(st_cifs[j], cifs_nr * CIFS_STATS_SIZE)) == NULL) {
+ perror("malloc");
+ exit(4);
+ }
+ memset(st_cifs[j] + i, 0, 5 * CIFS_STATS_SIZE);
+ }
+ /* Now i shows the first unused entry of the new block */
+ st_hdr_cifs_i = st_hdr_cifs + i;
+ st_hdr_cifs_i->used = TRUE; /* Indicate it is now used */
+ st_hdr_cifs_i->active = TRUE;
+ strncpy(st_hdr_cifs_i->name, name, MAX_NAME_LEN - 1);
+ st_hdr_cifs_i->name[MAX_NAME_LEN - 1] = '\0';
+ st_cifs_i = st_cifs[curr] + i;
+ *st_cifs_i = *st_io;
+ }
+ } else {
st_hdr_cifs_i = st_hdr_cifs + i;
st_hdr_cifs_i->active = TRUE;
+ st_hdr_cifs_i->used = TRUE;
st_cifs_i = st_cifs[curr] + i;
*st_cifs_i = *st_io;
}
char line[256];
char aux[32];
int start = 0;
+ long long unsigned aux_open;
+ long long unsigned all_open = 0;
char cifs_name[MAX_NAME_LEN];
char name_tmp[MAX_NAME_LEN];
- struct cifs_stats scifs;
+ struct cifs_stats scifs = {0, 0, 0, 0, 0, 0, 0};
/* Every CIFS entry is potentially unregistered */
set_entries_inactive();
if ((fp = fopen(CIFSSTATS, "r")) == NULL)
return;
- sprintf(aux, "%%%ds %%10s %%10s",
- MAX_NAME_LEN < 200 ? MAX_NAME_LEN : 200);
+ sprintf(aux, "%%*d) %%%ds",
+ MAX_NAME_LEN < 200 ? MAX_NAME_LEN - 1 : 200);
- while (fgets(line, 256, fp) != NULL) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
/* Read CIFS directory name */
- if (isdigit((unsigned char) line[0]) && sscanf(line, "%*d) %s", name_tmp) == 1) {
+ if (isdigit((unsigned char) line[0]) && sscanf(line, aux , name_tmp) == 1) {
if (start) {
+ scifs.fopens = all_open;
save_stats(cifs_name, curr, &scifs);
+ all_open = 0;
}
else {
start = 1;
}
- strcpy(cifs_name, name_tmp);
+ strncpy(cifs_name, name_tmp, MAX_NAME_LEN);
+ cifs_name[MAX_NAME_LEN - 1] = '\0';
}
else {
if (!strncmp(line, "Reads:", 6)) {
}
if (!strncmp(line, "Opens:", 6)) {
sscanf(line, "Opens: %llu Closes:%llu Deletes: %llu",
- &scifs.fopens, &scifs.fcloses, &scifs.fdeletes);
+ &aux_open, &scifs.fcloses, &scifs.fdeletes);
+ all_open += aux_open;
+ }
+ if (!strncmp(line, "Posix Opens:", 12)) {
+ sscanf(line, "Posix Opens: %llu", &aux_open);
+ all_open += aux_open;
}
}
}
-
+
if (start) {
+ scifs.fopens = all_open;
save_stats(cifs_name, curr, &scifs);
}
*/
void write_cifs_stat_header(int *fctr)
{
- printf("Filesystem: ");
+ if (!DISPLAY_HUMAN_READ(flags)) {
+ printf("Filesystem ");
+ }
if (DISPLAY_KILOBYTES(flags)) {
printf(" rkB/s wkB/s");
*fctr = 1024;
printf(" rB/s wB/s");
*fctr = 1;
}
- printf(" rops/s wops/s fo/s fc/s fd/s\n");
+ printf(" rops/s wops/s fo/s fc/s fd/s");
+ if (DISPLAY_HUMAN_READ(flags)) {
+ printf(" Filesystem");
+ }
+ printf("\n");
}
/*
*
* IN:
* @curr Index in array for current sample statistics.
- * @itv Interval of time.
+ * @itv Interval of time (in 1/100th of a second).
* @fctr Conversion factor.
* @shi Structures describing the CIFS filesystems.
* @ioi Current sample statistics.
struct io_hdr_stats *shi, struct cifs_stats *ioni,
struct cifs_stats *ionj)
{
- if (DISPLAY_HUMAN_READ(flags)) {
- printf("%-22s\n%23s", shi->name, "");
- }
- else {
- printf("%-22s ", shi->name);
+ double rbytes, wbytes;
+
+ if (!DISPLAY_HUMAN_READ(flags)) {
+ cprintf_in(IS_STR, "%-22s", shi->name, 0);
}
+
/* rB/s wB/s fo/s fc/s fd/s*/
- printf("%12.2f %12.2f %9.2f %9.2f %12.2f %12.2f %12.2f \n",
- S_VALUE(ionj->rd_bytes, ioni->rd_bytes, itv) / fctr,
- S_VALUE(ionj->wr_bytes, ioni->wr_bytes, itv) / fctr,
- S_VALUE(ionj->rd_ops, ioni->rd_ops, itv),
- S_VALUE(ionj->wr_ops, ioni->wr_ops, itv),
- S_VALUE(ionj->fopens, ioni->fopens, itv),
- S_VALUE(ionj->fcloses, ioni->fcloses, itv),
- S_VALUE(ionj->fdeletes, ioni->fdeletes, itv));
+ rbytes = S_VALUE(ionj->rd_bytes, ioni->rd_bytes, itv);
+ wbytes = S_VALUE(ionj->wr_bytes, ioni->wr_bytes, itv);
+ if (!DISPLAY_UNIT(flags)) {
+ rbytes /= fctr;
+ wbytes /= fctr;
+ }
+ cprintf_f(DISPLAY_UNIT(flags) ? UNIT_BYTE : NO_UNIT, 2, 12, 2,
+ rbytes, wbytes);
+ cprintf_f(NO_UNIT, 2, 9, 2,
+ S_VALUE(ionj->rd_ops, ioni->rd_ops, itv),
+ S_VALUE(ionj->wr_ops, ioni->wr_ops, itv));
+ cprintf_f(NO_UNIT, 3, 12, 2,
+ S_VALUE(ionj->fopens, ioni->fopens, itv),
+ S_VALUE(ionj->fcloses, ioni->fcloses, itv),
+ S_VALUE(ionj->fdeletes, ioni->fdeletes, itv));
+ if (DISPLAY_HUMAN_READ(flags)) {
+ cprintf_in(IS_STR, " %s", shi->name, 0);
+ }
+ printf("\n");
}
/*
strftime(timestamp, sizeof(timestamp), "%x %X", rectime);
}
printf("%s\n", timestamp);
+#ifdef DEBUG
+ if (DISPLAY_DEBUG(flags)) {
+ fprintf(stderr, "%s\n", timestamp);
+ }
+#endif
}
- /* Interval is multiplied by the number of processors */
- itv = get_interval(uptime[!curr], uptime[curr]);
-
- if (cpu_nr > 1) {
- /* On SMP machines, reduce itv to one processor (see note above) */
- itv = get_interval(uptime0[!curr], uptime0[curr]);
- }
+ /* Interval of time, reduced to one processor */
+ itv = get_interval(uptime_cs[!curr], uptime_cs[curr]);
shi = st_hdr_cifs;
if (shi->used) {
ioni = st_cifs[curr] + i;
ionj = st_cifs[!curr] + i;
+#ifdef DEBUG
+ if (DISPLAY_DEBUG(flags)) {
+ /* Debug output */
+ fprintf(stderr, "name=%s itv=%llu fctr=%d ioni{ rd_bytes=%llu "
+ "wr_bytes=%llu rd_ops=%llu wr_ops=%llu fopens=%llu "
+ "fcloses=%llu fdeletes=%llu}\n",
+ shi->name, itv, fctr,
+ ioni->rd_bytes, ioni->wr_bytes,
+ ioni->rd_ops, ioni->wr_ops,
+ ioni->fopens, ioni->fcloses,
+ ioni->fdeletes);
+ }
+#endif
write_cifs_stat(curr, itv, fctr, shi, ioni, ionj);
}
}
/* Don't buffer data if redirected to a pipe */
setbuf(stdout, NULL);
-
+
do {
- if (cpu_nr > 1) {
- /*
- * Read system uptime (only for SMP machines).
- * Init uptime0. So if /proc/uptime cannot fill it,
- * this will be done by /proc/stat.
- */
- uptime0[curr] = 0;
- read_uptime(&(uptime0[curr]));
- }
+ /* Read system uptime in 1/100th of a second */
+ read_uptime(&(uptime_cs[curr]));
/* Read CIFS stats */
read_cifs_stat(curr);
/* Get time */
- get_localtime(rectime);
+ get_localtime(rectime, 0);
/* Print results */
write_stats(curr, rectime);
if (count > 0) {
count--;
}
+
if (count) {
curr ^= 1;
pause();
init_nls();
#endif
- /* Get HZ */
- get_HZ();
+ /* Init color strings */
+ init_colors();
/* Process args... */
while (opt < argc) {
- if (!strncmp(argv[opt], "-", 1)) {
+#ifdef DEBUG
+ if (!strcmp(argv[opt], "--debuginfo")) {
+ flags |= I_D_DEBUG;
+ opt++;
+ } else
+#endif
+
+ if (!strcmp(argv[opt], "--human")) {
+ flags |= I_D_UNIT;
+ opt++;
+ }
+
+ else if (!strncmp(argv[opt], "--dec=", 6) && (strlen(argv[opt]) == 7)) {
+ /* Get number of decimal places */
+ dplaces_nr = atoi(argv[opt] + 6);
+ if ((dplaces_nr < 0) || (dplaces_nr > 2)) {
+ usage(argv[0]);
+ }
+ opt++;
+ }
+
+ else if (!strncmp(argv[opt], "-", 1)) {
for (i = 1; *(argv[opt] + i); i++) {
switch (*(argv[opt] + i)) {
case 'h':
- /* Display an easy-to-read CIFS report */
- flags |= I_D_HUMAN_READ;
+ /* Display an easy-to-read CIFS report. Also imply --human */
+ flags |= I_D_HUMAN_READ + I_D_UNIT;
break;
-
+
case 'k':
if (DISPLAY_MEGABYTES(flags)) {
usage(argv[0]);
/* Print version number and exit */
print_version();
break;
-
+
default:
usage(argv[0]);
}
/* Init structures according to machine architecture */
io_sys_init();
- get_localtime(&rectime);
+ get_localtime(&rectime, 0);
/* Get system name, release number and hostname */
- uname(&header);
+ __uname(&header);
if (print_gal_header(&rectime, header.sysname, header.release,
- header.nodename, header.machine, cpu_nr)) {
+ header.nodename, header.machine, cpu_nr,
+ PLAIN_OUTPUT)) {
flags |= I_D_ISO;
}
printf("\n");
/* Set a handler for SIGALRM */
- alarm_handler(0);
+ memset(&alrm_act, 0, sizeof(alrm_act));
+ alrm_act.sa_handler = alarm_handler;
+ sigaction(SIGALRM, &alrm_act, NULL);
+ alarm(interval);
/* Main loop */
rw_io_stat_loop(count, &rectime);