/*
* rd_stats.c: Read system statistics
- * (C) 1999-2012 by Sebastien GODARD (sysstat <at> orange.fr)
+ * (C) 1999-2019 by Sebastien GODARD (sysstat <at> orange.fr)
*
***************************************************************************
* This program is free software; you can redistribute it and/or modify it *
* *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA *
***************************************************************************
*/
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/statvfs.h>
#include <unistd.h>
#include "common.h"
#include "rd_stats.h"
-#include "ioconf.h"
#ifdef USE_NLS
#include <locale.h>
/*
***************************************************************************
- * Read CPU statistics and machine uptime.
+ * Read CPU statistics.
+ * Remember that this function is used by several sysstat commands!
*
* IN:
- * @st_cpu Structure where stats will be saved.
- * @nbr Total number of CPU (including cpu "all").
+ * @st_cpu Buffer where structures containing stats will be saved.
+ * @nr_alloc Total number of structures allocated. Value is >= 1.
*
* OUT:
- * @st_cpu Structure with statistics.
- * @uptime Machine uptime multiplied by the number of processors.
- * @uptime0 Machine uptime. Filled only if previously set to zero.
+ * @st_cpu Buffer with statistics.
+ *
+ * RETURNS:
+ * Highest CPU number(*) for which statistics have been read.
+ * 1 means CPU "all", 2 means CPU 0, 3 means CPU 1, etc.
+ * Or -1 if the buffer was too small and needs to be reallocated.
+ *
+ * (*)This doesn't account for all processors in the machine in the case
+ * where some CPU are offline and located at the end of the list.
***************************************************************************
*/
-void read_stat_cpu(struct stats_cpu *st_cpu, int nbr,
- unsigned long long *uptime, unsigned long long *uptime0)
+__nr_t read_stat_cpu(struct stats_cpu *st_cpu, __nr_t nr_alloc)
{
FILE *fp;
struct stats_cpu *st_cpu_i;
struct stats_cpu sc;
char line[8192];
- int proc_nb;
+ int proc_nr;
+ __nr_t cpu_read = 0;
if ((fp = fopen(STAT, "r")) == NULL) {
fprintf(stderr, _("Cannot open %s: %s\n"), STAT, strerror(errno));
exit(2);
}
- while (fgets(line, 8192, fp) != NULL) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "cpu ", 4)) {
&st_cpu->cpu_guest,
&st_cpu->cpu_guest_nice);
- /*
- * Compute the uptime of the system in jiffies (1/100ths of a second
- * if HZ=100).
- * Machine uptime is multiplied by the number of processors here.
- *
- * NB: Don't add cpu_guest/cpu_guest_nice because cpu_user/cpu_nice
- * already include them.
- */
- *uptime = st_cpu->cpu_user + st_cpu->cpu_nice +
- st_cpu->cpu_sys + st_cpu->cpu_idle +
- st_cpu->cpu_iowait + st_cpu->cpu_hardirq +
- st_cpu->cpu_steal + st_cpu->cpu_softirq;
+ if (!cpu_read) {
+ cpu_read = 1;
+ }
+
+ if (nr_alloc == 1)
+ /* We just want to read stats for CPU "all" */
+ break;
}
else if (!strncmp(line, "cpu", 3)) {
- if (nbr > 1) {
- /* All the fields don't necessarily exist */
- memset(&sc, 0, STATS_CPU_SIZE);
- /*
- * Read the number of jiffies spent in the different modes
- * (user, nice, etc) for current proc.
- * This is done only on SMP machines.
- */
- sscanf(line + 3, "%d %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
- &proc_nb,
- &sc.cpu_user,
- &sc.cpu_nice,
- &sc.cpu_sys,
- &sc.cpu_idle,
- &sc.cpu_iowait,
- &sc.cpu_hardirq,
- &sc.cpu_softirq,
- &sc.cpu_steal,
- &sc.cpu_guest,
- &sc.cpu_guest_nice);
-
- if (proc_nb < (nbr - 1)) {
- st_cpu_i = st_cpu + proc_nb + 1;
- *st_cpu_i = sc;
- }
- /*
- * else additional CPUs have been dynamically registered
- * in /proc/stat.
- */
-
- if (!proc_nb && !*uptime0) {
- /*
- * Compute uptime reduced to one proc using proc#0.
- * Done if /proc/uptime was unavailable.
- *
- * NB: Don't add cpu_guest/cpu_guest_nice because cpu_user/cpu_nice
- * already include them.
- */
- *uptime0 = sc.cpu_user + sc.cpu_nice +
- sc.cpu_sys + sc.cpu_idle +
- sc.cpu_iowait + sc.cpu_steal +
- sc.cpu_hardirq + sc.cpu_softirq;
- }
+ /* All the fields don't necessarily exist */
+ memset(&sc, 0, STATS_CPU_SIZE);
+ /*
+ * Read the number of jiffies spent in the different modes
+ * (user, nice, etc) for current proc.
+ * This is done only on SMP machines.
+ */
+ sscanf(line + 3, "%d %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
+ &proc_nr,
+ &sc.cpu_user,
+ &sc.cpu_nice,
+ &sc.cpu_sys,
+ &sc.cpu_idle,
+ &sc.cpu_iowait,
+ &sc.cpu_hardirq,
+ &sc.cpu_softirq,
+ &sc.cpu_steal,
+ &sc.cpu_guest,
+ &sc.cpu_guest_nice);
+
+ if (proc_nr + 2 > nr_alloc) {
+ cpu_read = -1;
+ break;
}
- }
- }
-
- fclose(fp);
-}
-
-/*
- ***************************************************************************
- * Read processes (tasks) creation and context switches statistics
- * from /proc/stat.
- *
- * IN:
- * @st_pcsw Structure where stats will be saved.
- *
- * OUT:
- * @st_pcsw Structure with statistics.
- ***************************************************************************
- */
-void read_stat_pcsw(struct stats_pcsw *st_pcsw)
-{
- FILE *fp;
- char line[8192];
- if ((fp = fopen(STAT, "r")) == NULL)
- return;
-
- while (fgets(line, 8192, fp) != NULL) {
-
- if (!strncmp(line, "ctxt ", 5)) {
- /* Read number of context switches */
- sscanf(line + 5, "%llu", &st_pcsw->context_switch);
- }
+ st_cpu_i = st_cpu + proc_nr + 1;
+ *st_cpu_i = sc;
- else if (!strncmp(line, "processes ", 10)) {
- /* Read number of processes created since system boot */
- sscanf(line + 10, "%lu", &st_pcsw->processes);
+ if (proc_nr + 2 > cpu_read) {
+ cpu_read = proc_nr + 2;
+ }
}
}
fclose(fp);
+ return cpu_read;
}
/*
***************************************************************************
* Read interrupts statistics from /proc/stat.
+ * Remember that this function is used by several sysstat commands!
*
* IN:
* @st_irq Structure where stats will be saved.
- * @nbr Number of interrupts to read, including the total number
- * of interrupts.
+ * @nr_alloc Number of structures allocated. Value is >= 1.
*
* OUT:
* @st_irq Structure with statistics.
+ *
+ * RETURNS:
+ * Number of interrupts read, or -1 if the buffer was too small and
+ * needs to be reallocated.
***************************************************************************
*/
-void read_stat_irq(struct stats_irq *st_irq, int nbr)
+__nr_t read_stat_irq(struct stats_irq *st_irq, __nr_t nr_alloc)
{
FILE *fp;
struct stats_irq *st_irq_i;
char line[8192];
int i, pos;
+ unsigned long long irq_nr;
+ __nr_t irq_read = 0;
if ((fp = fopen(STAT, "r")) == NULL)
- return;
-
- while (fgets(line, 8192, fp) != NULL) {
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "intr ", 5)) {
/* Read total number of interrupts received since system boot */
sscanf(line + 5, "%llu", &st_irq->irq_nr);
pos = strcspn(line + 5, " ") + 5;
- for (i = 1; i < nbr; i++) {
- st_irq_i = st_irq + i;
- sscanf(line + pos, " %llu", &st_irq_i->irq_nr);
- pos += strcspn(line + pos + 1, " ") + 1;
- }
- }
- }
-
- fclose(fp);
-}
-
-/*
- ***************************************************************************
- * Read queue and load statistics from /proc/loadavg and /proc/stat.
- *
- * IN:
- * @st_queue Structure where stats will be saved.
- *
- * OUT:
- * @st_queue Structure with statistics.
- ***************************************************************************
- */
-void read_loadavg(struct stats_queue *st_queue)
-{
- FILE *fp;
- char line[8192];
- int load_tmp[3];
-
- if ((fp = fopen(LOADAVG, "r")) == NULL)
- return;
-
- /* Read load averages and queue length */
- fscanf(fp, "%d.%d %d.%d %d.%d %ld/%d %*d\n",
- &load_tmp[0], &st_queue->load_avg_1,
- &load_tmp[1], &st_queue->load_avg_5,
- &load_tmp[2], &st_queue->load_avg_15,
- &st_queue->nr_running,
- &st_queue->nr_threads);
-
- fclose(fp);
-
- st_queue->load_avg_1 += load_tmp[0] * 100;
- st_queue->load_avg_5 += load_tmp[1] * 100;
- st_queue->load_avg_15 += load_tmp[2] * 100;
+ irq_read++;
+ if (nr_alloc == 1)
+ /* We just want to read the total number of interrupts */
+ break;
- if (st_queue->nr_running) {
- /* Do not take current process into account */
- st_queue->nr_running--;
- }
+ do {
+ i = sscanf(line + pos, " %llu", &irq_nr);
+ if (i < 1)
+ break;
- /* Read nr of tasks blocked from /proc/stat */
- if ((fp = fopen(STAT, "r")) == NULL)
- return;
+ if (irq_read + 1 > nr_alloc) {
+ irq_read = -1;
+ break;
+ }
+ st_irq_i = st_irq + irq_read++;
+ st_irq_i->irq_nr = irq_nr;
- while (fgets(line, 8192, fp) != NULL) {
+ i = strcspn(line + pos + 1, " ");
+ pos += i + 1;
+ }
+ while ((i > 0) && (pos < (sizeof(line) - 1)));
- if (!strncmp(line, "procs_blocked ", 14)) {
- /* Read number of processes blocked */
- sscanf(line + 14, "%lu", &st_queue->procs_blocked);
break;
}
}
fclose(fp);
+ return irq_read;
}
/*
*
* OUT:
* @st_memory Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_meminfo(struct stats_memory *st_memory)
+__nr_t read_meminfo(struct stats_memory *st_memory)
{
FILE *fp;
char line[128];
-
+
if ((fp = fopen(MEMINFO, "r")) == NULL)
- return;
+ return 0;
- while (fgets(line, 128, fp) != NULL) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "MemTotal:", 9)) {
/* Read the total amount of memory in kB */
- sscanf(line + 9, "%lu", &st_memory->tlmkb);
+ sscanf(line + 9, "%llu", &st_memory->tlmkb);
}
else if (!strncmp(line, "MemFree:", 8)) {
/* Read the amount of free memory in kB */
- sscanf(line + 8, "%lu", &st_memory->frmkb);
+ sscanf(line + 8, "%llu", &st_memory->frmkb);
+ }
+ else if (!strncmp(line, "MemAvailable:", 13)) {
+ /* Read the amount of available memory in kB */
+ sscanf(line + 13, "%llu", &st_memory->availablekb);
}
else if (!strncmp(line, "Buffers:", 8)) {
/* Read the amount of buffered memory in kB */
- sscanf(line + 8, "%lu", &st_memory->bufkb);
+ sscanf(line + 8, "%llu", &st_memory->bufkb);
}
else if (!strncmp(line, "Cached:", 7)) {
/* Read the amount of cached memory in kB */
- sscanf(line + 7, "%lu", &st_memory->camkb);
+ sscanf(line + 7, "%llu", &st_memory->camkb);
}
else if (!strncmp(line, "SwapCached:", 11)) {
/* Read the amount of cached swap in kB */
- sscanf(line + 11, "%lu", &st_memory->caskb);
+ sscanf(line + 11, "%llu", &st_memory->caskb);
}
else if (!strncmp(line, "Active:", 7)) {
/* Read the amount of active memory in kB */
- sscanf(line + 7, "%lu", &st_memory->activekb);
+ sscanf(line + 7, "%llu", &st_memory->activekb);
}
else if (!strncmp(line, "Inactive:", 9)) {
/* Read the amount of inactive memory in kB */
- sscanf(line + 9, "%lu", &st_memory->inactkb);
+ sscanf(line + 9, "%llu", &st_memory->inactkb);
}
else if (!strncmp(line, "SwapTotal:", 10)) {
/* Read the total amount of swap memory in kB */
- sscanf(line + 10, "%lu", &st_memory->tlskb);
+ sscanf(line + 10, "%llu", &st_memory->tlskb);
}
else if (!strncmp(line, "SwapFree:", 9)) {
/* Read the amount of free swap memory in kB */
- sscanf(line + 9, "%lu", &st_memory->frskb);
+ sscanf(line + 9, "%llu", &st_memory->frskb);
}
else if (!strncmp(line, "Dirty:", 6)) {
/* Read the amount of dirty memory in kB */
- sscanf(line + 6, "%lu", &st_memory->dirtykb);
+ sscanf(line + 6, "%llu", &st_memory->dirtykb);
}
else if (!strncmp(line, "Committed_AS:", 13)) {
/* Read the amount of commited memory in kB */
- sscanf(line + 13, "%lu", &st_memory->comkb);
+ sscanf(line + 13, "%llu", &st_memory->comkb);
+ }
+ else if (!strncmp(line, "AnonPages:", 10)) {
+ /* Read the amount of pages mapped into userspace page tables in kB */
+ sscanf(line + 10, "%llu", &st_memory->anonpgkb);
+ }
+ else if (!strncmp(line, "Slab:", 5)) {
+ /* Read the amount of in-kernel data structures cache in kB */
+ sscanf(line + 5, "%llu", &st_memory->slabkb);
+ }
+ else if (!strncmp(line, "KernelStack:", 12)) {
+ /* Read the kernel stack utilization in kB */
+ sscanf(line + 12, "%llu", &st_memory->kstackkb);
+ }
+ else if (!strncmp(line, "PageTables:", 11)) {
+ /* Read the amount of memory dedicated to the lowest level of page tables in kB */
+ sscanf(line + 11, "%llu", &st_memory->pgtblkb);
+ }
+ else if (!strncmp(line, "VmallocUsed:", 12)) {
+ /* Read the amount of vmalloc area which is used in kB */
+ sscanf(line + 12, "%llu", &st_memory->vmusedkb);
}
}
fclose(fp);
+ return 1;
}
/*
***************************************************************************
- * Read swapping statistics from /proc/vmstat.
- *
- * IN:
- * @st_swap Structure where stats will be saved.
+ * Read machine uptime, independently of the number of processors.
*
* OUT:
- * @st_swap Structure with statistics.
+ * @uptime Uptime value in hundredths of a second.
***************************************************************************
*/
-void read_vmstat_swap(struct stats_swap *st_swap)
+void read_uptime(unsigned long long *uptime)
{
- FILE *fp;
+ FILE *fp = NULL;
char line[128];
+ unsigned long up_sec, up_cent;
+ int err = FALSE;
- if ((fp = fopen(VMSTAT, "r")) == NULL)
- return;
-
- while (fgets(line, 128, fp) != NULL) {
+ if ((fp = fopen(UPTIME, "r")) == NULL) {
+ err = TRUE;
+ }
+ else if (fgets(line, sizeof(line), fp) == NULL) {
+ err = TRUE;
+ }
+ else if (sscanf(line, "%lu.%lu", &up_sec, &up_cent) == 2) {
+ *uptime = (unsigned long long) up_sec * 100 +
+ (unsigned long long) up_cent;
+ }
+ else {
+ err = TRUE;
+ }
- if (!strncmp(line, "pswpin ", 7)) {
- /* Read number of swap pages brought in */
- sscanf(line + 7, "%lu", &st_swap->pswpin);
- }
- else if (!strncmp(line, "pswpout ", 8)) {
- /* Read number of swap pages brought out */
- sscanf(line + 8, "%lu", &st_swap->pswpout);
- }
+ if (fp != NULL) {
+ fclose(fp);
+ }
+ if (err) {
+ fprintf(stderr, _("Cannot read %s\n"), UPTIME);
+ exit(2);
}
-
- fclose(fp);
}
/*
***************************************************************************
- * Read paging statistics from /proc/vmstat.
+ * Compute "extended" device statistics (service time, etc.).
*
* IN:
- * @st_paging Structure where stats will be saved.
+ * @sdc Structure with current device statistics.
+ * @sdp Structure with previous device statistics.
+ * @itv Interval of time in 1/100th of a second.
*
* OUT:
- * @st_paging Structure with statistics.
+ * @xds Structure with extended statistics.
***************************************************************************
- */
-void read_vmstat_paging(struct stats_paging *st_paging)
+*/
+void compute_ext_disk_stats(struct stats_disk *sdc, struct stats_disk *sdp,
+ unsigned long long itv, struct ext_disk_stats *xds)
{
- FILE *fp;
- char line[128];
- unsigned long pgtmp;
-
- if ((fp = fopen(VMSTAT, "r")) == NULL)
- return;
-
- st_paging->pgsteal = 0;
- st_paging->pgscan_kswapd = st_paging->pgscan_direct = 0;
-
- while (fgets(line, 128, fp) != NULL) {
-
- if (!strncmp(line, "pgpgin ", 7)) {
- /* Read number of pages the system paged in */
- sscanf(line + 7, "%lu", &st_paging->pgpgin);
- }
- else if (!strncmp(line, "pgpgout ", 8)) {
- /* Read number of pages the system paged out */
- sscanf(line + 8, "%lu", &st_paging->pgpgout);
- }
- else if (!strncmp(line, "pgfault ", 8)) {
- /* Read number of faults (major+minor) made by the system */
- sscanf(line + 8, "%lu", &st_paging->pgfault);
- }
- else if (!strncmp(line, "pgmajfault ", 11)) {
- /* Read number of faults (major only) made by the system */
- sscanf(line + 11, "%lu", &st_paging->pgmajfault);
- }
- else if (!strncmp(line, "pgfree ", 7)) {
- /* Read number of pages freed by the system */
- sscanf(line + 7, "%lu", &st_paging->pgfree);
- }
- else if (!strncmp(line, "pgsteal_", 8)) {
- /* Read number of pages stolen by the system */
- sscanf(strchr(line, ' '), "%lu", &pgtmp);
- st_paging->pgsteal += pgtmp;
- }
- else if (!strncmp(line, "pgscan_kswapd_", 14)) {
- /* Read number of pages scanned by the kswapd daemon */
- sscanf(strchr(line, ' '), "%lu", &pgtmp);
- st_paging->pgscan_kswapd += pgtmp;
- }
- else if (!strncmp(line, "pgscan_direct_", 14)) {
- /* Read number of pages scanned directly */
- sscanf(strchr(line, ' '), "%lu", &pgtmp);
- st_paging->pgscan_direct += pgtmp;
- }
- }
-
- fclose(fp);
+ xds->util = S_VALUE(sdp->tot_ticks, sdc->tot_ticks, itv);
+ /*
+ * Kernel gives ticks already in milliseconds for all platforms
+ * => no need for further scaling.
+ */
+ xds->await = (sdc->nr_ios - sdp->nr_ios) ?
+ ((sdc->rd_ticks - sdp->rd_ticks) + (sdc->wr_ticks - sdp->wr_ticks) + (sdc->dc_ticks - sdp->dc_ticks)) /
+ ((double) (sdc->nr_ios - sdp->nr_ios)) : 0.0;
+ xds->arqsz = (sdc->nr_ios - sdp->nr_ios) ?
+ ((sdc->rd_sect - sdp->rd_sect) + (sdc->wr_sect - sdp->wr_sect) + (sdc->dc_sect - sdp->dc_sect)) /
+ ((double) (sdc->nr_ios - sdp->nr_ios)) : 0.0;
}
/*
***************************************************************************
- * Read I/O and transfer rates statistics from /proc/diskstats.
+ * Since ticks may vary slightly from CPU to CPU, we'll want
+ * to recalculate itv based on this CPU's tick count, rather
+ * than that reported by the "cpu" line. Otherwise we
+ * occasionally end up with slightly skewed figures, with
+ * the skew being greater as the time interval grows shorter.
*
* IN:
- * @st_io Structure where stats will be saved.
+ * @scc Current sample statistics for current CPU.
+ * @scp Previous sample statistics for current CPU.
*
- * OUT:
- * @st_io Structure with statistics.
+ * RETURNS:
+ * Interval of time based on current CPU, expressed in jiffies.
***************************************************************************
*/
-void read_diskstats_io(struct stats_io *st_io)
+unsigned long long get_per_cpu_interval(struct stats_cpu *scc,
+ struct stats_cpu *scp)
{
- FILE *fp;
- char line[256];
- char dev_name[MAX_NAME_LEN];
- unsigned int major, minor;
- unsigned long rd_ios, wr_ios, rd_sec, wr_sec;
-
- if ((fp = fopen(DISKSTATS, "r")) == NULL)
- return;
+ unsigned long long ishift = 0LL;
- while (fgets(line, 256, fp) != NULL) {
+ if ((scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest)) {
+ /*
+ * Sometimes the nr of jiffies spent in guest mode given by the guest
+ * counter in /proc/stat is slightly higher than that included in
+ * the user counter. Update the interval value accordingly.
+ */
+ ishift += (scp->cpu_user - scp->cpu_guest) -
+ (scc->cpu_user - scc->cpu_guest);
+ }
+ if ((scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice)) {
+ /*
+ * Idem for nr of jiffies spent in guest_nice mode.
+ */
+ ishift += (scp->cpu_nice - scp->cpu_guest_nice) -
+ (scc->cpu_nice - scc->cpu_guest_nice);
+ }
- if (sscanf(line, "%u %u %s %lu %*u %lu %*u %lu %*u %lu",
- &major, &minor, dev_name,
- &rd_ios, &rd_sec, &wr_ios, &wr_sec) == 7) {
-
- if (is_device(dev_name, IGNORE_VIRTUAL_DEVICES)) {
- /*
- * OK: It's a (real) device and not a partition.
- * Note: Structure should have been initialized first!
- */
- st_io->dk_drive += rd_ios + wr_ios;
- st_io->dk_drive_rio += rd_ios;
- st_io->dk_drive_rblk += rd_sec;
- st_io->dk_drive_wio += wr_ios;
- st_io->dk_drive_wblk += wr_sec;
- }
- }
+ /*
+ * Workaround for CPU coming back online: With recent kernels
+ * some fields (user, nice, system) restart from their previous value,
+ * whereas others (idle, iowait) restart from zero.
+ * For the latter we need to set their previous value to zero to
+ * avoid getting an interval value < 0.
+ * (I don't know how the other fields like hardirq, steal... behave).
+ * Don't assume the CPU has come back from offline state if previous
+ * value was greater than ULLONG_MAX - 0x7ffff (the counter probably
+ * overflew).
+ */
+ if ((scc->cpu_idle < scp->cpu_idle) && (scp->cpu_idle < (ULLONG_MAX - 0x7ffff))) {
+ scp->cpu_idle = 0;
}
-
- fclose(fp);
+ if ((scc->cpu_iowait < scp->cpu_iowait) && (scp->cpu_iowait < (ULLONG_MAX - 0x7ffff))) {
+ scp->cpu_iowait = 0;
+ }
+
+ /*
+ * Don't take cpu_guest and cpu_guest_nice into account
+ * because cpu_user and cpu_nice already include them.
+ */
+ return ((scc->cpu_user + scc->cpu_nice +
+ scc->cpu_sys + scc->cpu_iowait +
+ scc->cpu_idle + scc->cpu_steal +
+ scc->cpu_hardirq + scc->cpu_softirq) -
+ (scp->cpu_user + scp->cpu_nice +
+ scp->cpu_sys + scp->cpu_iowait +
+ scp->cpu_idle + scp->cpu_steal +
+ scp->cpu_hardirq + scp->cpu_softirq) +
+ ishift);
}
+#ifdef SOURCE_SADC
+/*---------------- BEGIN: FUNCTIONS USED BY SADC ONLY ---------------------*/
+
/*
***************************************************************************
- * Read block devices statistics from /proc/diskstats.
+ * Replace octal codes in string with their corresponding characters.
*
* IN:
- * @st_disk Structure where stats will be saved.
- * @nbr Maximum number of block devices.
- * @read_part True if disks *and* partitions should be read; False if only
- * disks are read.
+ * @str String to parse.
*
* OUT:
- * @st_disk Structure with statistics.
+ * @str String with octal codes replaced with characters.
***************************************************************************
*/
-void read_diskstats_disk(struct stats_disk *st_disk, int nbr, int read_part)
+void oct2chr(char *str)
{
- FILE *fp;
- char line[256];
- char dev_name[MAX_NAME_LEN];
- int dsk = 0;
- struct stats_disk *st_disk_i;
- unsigned int major, minor, rd_ticks, wr_ticks, tot_ticks, rq_ticks;
- unsigned long rd_ios, wr_ios, rd_sec, wr_sec;
-
- if ((fp = fopen(DISKSTATS, "r")) == NULL)
- return;
-
- while ((fgets(line, 256, fp) != NULL) && (dsk < nbr)) {
-
- if (sscanf(line, "%u %u %s %lu %*u %lu %u %lu %*u %lu"
- " %u %*u %u %u",
- &major, &minor, dev_name,
- &rd_ios, &rd_sec, &rd_ticks, &wr_ios, &wr_sec, &wr_ticks,
- &tot_ticks, &rq_ticks) == 11) {
-
- if (!rd_ios && !wr_ios)
- /* Unused device: Ignore it */
- continue;
- if (read_part || is_device(dev_name, ACCEPT_VIRTUAL_DEVICES)) {
- st_disk_i = st_disk + dsk++;
- st_disk_i->major = major;
- st_disk_i->minor = minor;
- st_disk_i->nr_ios = rd_ios + wr_ios;
- st_disk_i->rd_sect = rd_sec;
- st_disk_i->wr_sect = wr_sec;
- st_disk_i->rd_ticks = rd_ticks;
- st_disk_i->wr_ticks = wr_ticks;
- st_disk_i->tot_ticks = tot_ticks;
- st_disk_i->rq_ticks = rq_ticks;
+ int i = 0;
+ int j, len;
+
+ len = strlen(str);
+
+ while (i < len - 3) {
+ if ((str[i] == '\\') &&
+ (str[i + 1] >= '0') && (str[i + 1] <= '3') &&
+ (str[i + 2] >= '0') && (str[i + 2] <= '7') &&
+ (str[i + 3] >= '0') && (str[i + 3] <= '7')) {
+ /* Octal code found */
+ str[i] = (str[i + 1] - 48) * 64 +
+ (str[i + 2] - 48) * 8 +
+ (str[i + 3] - 48);
+ for (j = i + 4; j <= len; j++) {
+ str[j - 3] = str[j];
}
+ len -= 3;
}
+ i++;
}
-
- fclose(fp);
}
/*
***************************************************************************
- * Read serial lines statistics from /proc/tty/driver/serial.
+ * Read processes (tasks) creation and context switches statistics
+ * from /proc/stat.
*
* IN:
- * @st_serial Structure where stats will be saved.
- * @nbr Maximum number of serial lines.
+ * @st_pcsw Structure where stats will be saved.
*
* OUT:
- * @st_serial Structure with statistics.
- ***************************************************************************
- */
-void read_tty_driver_serial(struct stats_serial *st_serial, int nbr)
+ * @st_pcsw Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
+ ***************************************************************************
+ */
+__nr_t read_stat_pcsw(struct stats_pcsw *st_pcsw)
+{
+ FILE *fp;
+ char line[8192];
+
+ if ((fp = fopen(STAT, "r")) == NULL)
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+
+ if (!strncmp(line, "ctxt ", 5)) {
+ /* Read number of context switches */
+ sscanf(line + 5, "%llu", &st_pcsw->context_switch);
+ }
+
+ else if (!strncmp(line, "processes ", 10)) {
+ /* Read number of processes created since system boot */
+ sscanf(line + 10, "%lu", &st_pcsw->processes);
+ }
+ }
+
+ fclose(fp);
+ return 1;
+}
+
+/*
+ ***************************************************************************
+ * Read queue and load statistics from /proc/loadavg and /proc/stat.
+ *
+ * IN:
+ * @st_queue Structure where stats will be saved.
+ *
+ * OUT:
+ * @st_queue Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
+ ***************************************************************************
+ */
+__nr_t read_loadavg(struct stats_queue *st_queue)
+{
+ FILE *fp;
+ char line[8192];
+ unsigned int load_tmp[3];
+ int rc;
+
+ if ((fp = fopen(LOADAVG, "r")) == NULL)
+ return 0;
+
+ /* Read load averages and queue length */
+ rc = fscanf(fp, "%u.%u %u.%u %u.%u %llu/%llu %*d\n",
+ &load_tmp[0], &st_queue->load_avg_1,
+ &load_tmp[1], &st_queue->load_avg_5,
+ &load_tmp[2], &st_queue->load_avg_15,
+ &st_queue->nr_running,
+ &st_queue->nr_threads);
+
+ fclose(fp);
+
+ if (rc < 8)
+ return 0;
+
+ st_queue->load_avg_1 += load_tmp[0] * 100;
+ st_queue->load_avg_5 += load_tmp[1] * 100;
+ st_queue->load_avg_15 += load_tmp[2] * 100;
+
+ if (st_queue->nr_running) {
+ /* Do not take current process into account */
+ st_queue->nr_running--;
+ }
+
+ /* Read nr of tasks blocked from /proc/stat */
+ if ((fp = fopen(STAT, "r")) == NULL)
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+
+ if (!strncmp(line, "procs_blocked ", 14)) {
+ /* Read number of processes blocked */
+ sscanf(line + 14, "%llu", &st_queue->procs_blocked);
+ break;
+ }
+ }
+
+ fclose(fp);
+ return 1;
+}
+
+/*
+ ***************************************************************************
+ * Read swapping statistics from /proc/vmstat.
+ *
+ * IN:
+ * @st_swap Structure where stats will be saved.
+ *
+ * OUT:
+ * @st_swap Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
+ ***************************************************************************
+ */
+__nr_t read_vmstat_swap(struct stats_swap *st_swap)
+{
+ FILE *fp;
+ char line[128];
+
+ if ((fp = fopen(VMSTAT, "r")) == NULL)
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+
+ if (!strncmp(line, "pswpin ", 7)) {
+ /* Read number of swap pages brought in */
+ sscanf(line + 7, "%lu", &st_swap->pswpin);
+ }
+ else if (!strncmp(line, "pswpout ", 8)) {
+ /* Read number of swap pages brought out */
+ sscanf(line + 8, "%lu", &st_swap->pswpout);
+ }
+ }
+
+ fclose(fp);
+ return 1;
+}
+
+/*
+ ***************************************************************************
+ * Read paging statistics from /proc/vmstat.
+ *
+ * IN:
+ * @st_paging Structure where stats will be saved.
+ *
+ * OUT:
+ * @st_paging Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
+ ***************************************************************************
+ */
+__nr_t read_vmstat_paging(struct stats_paging *st_paging)
+{
+ FILE *fp;
+ char line[128];
+ unsigned long pgtmp;
+
+ if ((fp = fopen(VMSTAT, "r")) == NULL)
+ return 0;
+
+ st_paging->pgsteal = 0;
+ st_paging->pgscan_kswapd = st_paging->pgscan_direct = 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+
+ if (!strncmp(line, "pgpgin ", 7)) {
+ /* Read number of pages the system paged in */
+ sscanf(line + 7, "%lu", &st_paging->pgpgin);
+ }
+ else if (!strncmp(line, "pgpgout ", 8)) {
+ /* Read number of pages the system paged out */
+ sscanf(line + 8, "%lu", &st_paging->pgpgout);
+ }
+ else if (!strncmp(line, "pgfault ", 8)) {
+ /* Read number of faults (major+minor) made by the system */
+ sscanf(line + 8, "%lu", &st_paging->pgfault);
+ }
+ else if (!strncmp(line, "pgmajfault ", 11)) {
+ /* Read number of faults (major only) made by the system */
+ sscanf(line + 11, "%lu", &st_paging->pgmajfault);
+ }
+ else if (!strncmp(line, "pgfree ", 7)) {
+ /* Read number of pages freed by the system */
+ sscanf(line + 7, "%lu", &st_paging->pgfree);
+ }
+ else if (!strncmp(line, "pgsteal_", 8)) {
+ /* Read number of pages stolen by the system */
+ sscanf(strchr(line, ' '), "%lu", &pgtmp);
+ st_paging->pgsteal += pgtmp;
+ }
+ else if (!strncmp(line, "pgscan_kswapd", 13)) {
+ /* Read number of pages scanned by the kswapd daemon */
+ sscanf(strchr(line, ' '), "%lu", &pgtmp);
+ st_paging->pgscan_kswapd += pgtmp;
+ }
+ else if (!strncmp(line, "pgscan_direct", 13)) {
+ /* Read number of pages scanned directly */
+ sscanf(strchr(line, ' '), "%lu", &pgtmp);
+ st_paging->pgscan_direct += pgtmp;
+ }
+ }
+
+ fclose(fp);
+ return 1;
+}
+
+/*
+ ***************************************************************************
+ * Read I/O and transfer rates statistics from /proc/diskstats.
+ *
+ * IN:
+ * @st_io Structure where stats will be saved.
+ *
+ * OUT:
+ * @st_io Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
+ ***************************************************************************
+ */
+__nr_t read_diskstats_io(struct stats_io *st_io)
+{
+ FILE *fp;
+ char line[1024];
+ char dev_name[MAX_NAME_LEN];
+ unsigned int major, minor;
+ unsigned long rd_ios, wr_ios, dc_ios;
+ unsigned long rd_sec, wr_sec, dc_sec;
+
+ if ((fp = fopen(DISKSTATS, "r")) == NULL)
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+
+ /* Discard I/O stats may be not available */
+ dc_ios = dc_sec = 0;
+
+ if (sscanf(line,
+ "%u %u %s "
+ "%lu %*u %lu %*u "
+ "%lu %*u %lu %*u "
+ "%*u %*u %*u "
+ "%lu %*u %lu",
+ &major, &minor, dev_name,
+ &rd_ios, &rd_sec,
+ &wr_ios, &wr_sec,
+ &dc_ios, &dc_sec) >= 7) {
+
+ if (is_device(dev_name, IGNORE_VIRTUAL_DEVICES)) {
+ /*
+ * OK: It's a (real) device and not a partition.
+ * Note: Structure should have been initialized first!
+ */
+ st_io->dk_drive += (unsigned long long) rd_ios +
+ (unsigned long long) wr_ios +
+ (unsigned long long) dc_ios;
+ st_io->dk_drive_rio += rd_ios;
+ st_io->dk_drive_rblk += rd_sec;
+ st_io->dk_drive_wio += wr_ios;
+ st_io->dk_drive_wblk += wr_sec;
+ st_io->dk_drive_dio += dc_ios;
+ st_io->dk_drive_dblk += dc_sec;
+ }
+ }
+ }
+
+ fclose(fp);
+ return 1;
+}
+
+/*
+ ***************************************************************************
+ * Read block devices statistics from /proc/diskstats.
+ *
+ * IN:
+ * @st_disk Structure where stats will be saved.
+ * @nr_alloc Total number of structures allocated. Value is >= 1.
+ * @read_part True if disks *and* partitions should be read; False if only
+ * disks are read.
+ *
+ * OUT:
+ * @st_disk Structure with statistics.
+ *
+ * RETURNS:
+ * Number of block devices read, or -1 if the buffer was too small and
+ * needs to be reallocated.
+ ***************************************************************************
+ */
+__nr_t read_diskstats_disk(struct stats_disk *st_disk, __nr_t nr_alloc,
+ int read_part)
+{
+ FILE *fp;
+ char line[1024];
+ char dev_name[MAX_NAME_LEN];
+ struct stats_disk *st_disk_i;
+ unsigned int major, minor, rd_ticks, wr_ticks, dc_ticks, tot_ticks, rq_ticks, part_nr;
+ unsigned long rd_ios, wr_ios, dc_ios, rd_sec, wr_sec, dc_sec;
+ unsigned long long wwn[2];
+ __nr_t dsk_read = 0;
+
+ if ((fp = fopen(DISKSTATS, "r")) == NULL)
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+
+ /* Discard I/O stats may be not available */
+ dc_ios = dc_sec = dc_ticks = 0;
+
+ if (sscanf(line,
+ "%u %u %s "
+ "%lu %*u %lu %u "
+ "%lu %*u %lu %u "
+ "%*u %u %u "
+ "%lu %*u %lu %u",
+ &major, &minor, dev_name,
+ &rd_ios, &rd_sec, &rd_ticks,
+ &wr_ios, &wr_sec, &wr_ticks,
+ &tot_ticks, &rq_ticks,
+ &dc_ios, &dc_sec, &dc_ticks) >= 11) {
+
+ if (!rd_ios && !wr_ios && !dc_ios)
+ /* Unused device: Ignore it */
+ continue;
+ if (read_part || is_device(dev_name, ACCEPT_VIRTUAL_DEVICES)) {
+
+ if (dsk_read + 1 > nr_alloc) {
+ dsk_read = -1;
+ break;
+ }
+
+ st_disk_i = st_disk + dsk_read++;
+ st_disk_i->major = major;
+ st_disk_i->minor = minor;
+ st_disk_i->nr_ios = (unsigned long long) rd_ios +
+ (unsigned long long) wr_ios +
+ (unsigned long long) dc_ios;
+ st_disk_i->rd_sect = rd_sec;
+ st_disk_i->wr_sect = wr_sec;
+ st_disk_i->dc_sect = dc_sec;
+ st_disk_i->rd_ticks = rd_ticks;
+ st_disk_i->wr_ticks = wr_ticks;
+ st_disk_i->dc_ticks = dc_ticks;
+ st_disk_i->tot_ticks = tot_ticks;
+ st_disk_i->rq_ticks = rq_ticks;
+
+ if (get_wwnid_from_pretty(dev_name, wwn, &part_nr) < 0) {
+ st_disk_i->wwn[0] = 0ULL;
+ }
+ else {
+ st_disk_i->wwn[0] = wwn[0];
+ st_disk_i->wwn[1] = wwn[1];
+ st_disk_i->part_nr = part_nr;
+ }
+ }
+ }
+ }
+
+ fclose(fp);
+ return dsk_read;
+}
+
+/*
+ ***************************************************************************
+ * Read serial lines statistics from /proc/tty/driver/serial.
+ *
+ * IN:
+ * @st_serial Structure where stats will be saved.
+ * @nr_alloc Total number of structures allocated. Value is >= 1.
+ *
+ * OUT:
+ * @st_serial Structure with statistics.
+ *
+ * RETURNS:
+ * Number of serial lines read, or -1 if the buffer was too small and
+ * needs to be reallocated.
+ ***************************************************************************
+ */
+__nr_t read_tty_driver_serial(struct stats_serial *st_serial, __nr_t nr_alloc)
{
FILE *fp;
struct stats_serial *st_serial_i;
- int sl = 0;
char line[256];
char *p;
+ __nr_t sl_read = 0;
if ((fp = fopen(SERIAL, "r")) == NULL)
- return;
+ return 0;
- while ((fgets(line, 256, fp) != NULL) && (sl < nbr)) {
+ while (fgets(line, sizeof(line), fp) != NULL ) {
if ((p = strstr(line, "tx:")) != NULL) {
- st_serial_i = st_serial + sl;
+
+ if (sl_read + 1 > nr_alloc) {
+ sl_read = -1;
+ break;
+ }
+
+ st_serial_i = st_serial + sl_read++;
+ /* Read serial line number */
sscanf(line, "%u", &st_serial_i->line);
- /*
- * A value of 0 means an unused structure.
- * So increment it to make sure it is not null.
- */
- (st_serial_i->line)++;
/*
* Read the number of chars transmitted and received by
* current serial line.
if ((p = strstr(line, "oe:")) != NULL) {
sscanf(p + 3, "%u", &st_serial_i->overrun);
}
-
- sl++;
}
}
fclose(fp);
+ return sl_read;
}
/*
*
* OUT:
* @st_ktables Structure with statistics.
+ *
+ * RETURNS:
+ * 1 (always success).
***************************************************************************
*/
-void read_kernel_tables(struct stats_ktables *st_ktables)
+__nr_t read_kernel_tables(struct stats_ktables *st_ktables)
{
FILE *fp;
- unsigned int parm;
-
+ unsigned long long parm;
+ int rc = 0;
+
/* Open /proc/sys/fs/dentry-state file */
if ((fp = fopen(FDENTRY_STATE, "r")) != NULL) {
- fscanf(fp, "%*d %u",
- &st_ktables->dentry_stat);
+ rc = fscanf(fp, "%*d %llu",
+ &st_ktables->dentry_stat);
fclose(fp);
+ if (rc == 0) {
+ st_ktables->dentry_stat = 0;
+ }
}
/* Open /proc/sys/fs/file-nr file */
if ((fp = fopen(FFILE_NR, "r")) != NULL) {
- fscanf(fp, "%u %u",
- &st_ktables->file_used, &parm);
+ rc = fscanf(fp, "%llu %llu",
+ &st_ktables->file_used, &parm);
fclose(fp);
/*
* The number of used handles is the number of allocated ones
* minus the number of free ones.
*/
- st_ktables->file_used -= parm;
+ if (rc == 2) {
+ st_ktables->file_used -= parm;
+ }
+ else {
+ st_ktables->file_used = 0;
+ }
}
/* Open /proc/sys/fs/inode-state file */
if ((fp = fopen(FINODE_STATE, "r")) != NULL) {
- fscanf(fp, "%u %u",
- &st_ktables->inode_used, &parm);
+ rc = fscanf(fp, "%llu %llu",
+ &st_ktables->inode_used, &parm);
fclose(fp);
/*
* The number of inuse inodes is the number of allocated ones
* minus the number of free ones.
*/
- st_ktables->inode_used -= parm;
+ if (rc == 2) {
+ st_ktables->inode_used -= parm;
+ }
+ else {
+ st_ktables->inode_used = 0;
+ }
}
/* Open /proc/sys/kernel/pty/nr file */
if ((fp = fopen(PTY_NR, "r")) != NULL) {
- fscanf(fp, "%u",
- &st_ktables->pty_nr);
+ rc = fscanf(fp, "%llu",
+ &st_ktables->pty_nr);
fclose(fp);
+ if (rc == 0) {
+ st_ktables->pty_nr = 0;
+ }
}
+
+ return 1;
}
/*
*
* IN:
* @st_net_dev Structure where stats will be saved.
- * @nbr Maximum number of network interfaces.
+ * @nr_alloc Total number of structures allocated. Value is >= 1.
*
* OUT:
* @st_net_dev Structure with statistics.
+ *
+ * RETURNS:
+ * Number of interfaces read, or -1 if the buffer was too small and
+ * needs to be reallocated.
***************************************************************************
*/
-void read_net_dev(struct stats_net_dev *st_net_dev, int nbr)
+__nr_t read_net_dev(struct stats_net_dev *st_net_dev, __nr_t nr_alloc)
{
FILE *fp;
struct stats_net_dev *st_net_dev_i;
char line[256];
char iface[MAX_IFACE_LEN];
- int dev = 0;
+ __nr_t dev_read = 0;
int pos;
if ((fp = fopen(NET_DEV, "r")) == NULL)
- return;
-
- while ((fgets(line, 256, fp) != NULL) && (dev < nbr)) {
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
pos = strcspn(line, ":");
if (pos < strlen(line)) {
- st_net_dev_i = st_net_dev + dev;
+
+ if (dev_read + 1 > nr_alloc) {
+ dev_read = -1;
+ break;
+ }
+
+ st_net_dev_i = st_net_dev + dev_read++;
strncpy(iface, line, MINIMUM(pos, MAX_IFACE_LEN - 1));
iface[MINIMUM(pos, MAX_IFACE_LEN - 1)] = '\0';
sscanf(iface, "%s", st_net_dev_i->interface); /* Skip heading spaces */
&st_net_dev_i->tx_bytes,
&st_net_dev_i->tx_packets,
&st_net_dev_i->tx_compressed);
- dev++;
}
}
fclose(fp);
+ return dev_read;
}
+/*
+ ***************************************************************************
+ * Read duplex and speed data for network interface cards.
+ *
+ * IN:
+ * @st_net_dev Structure where stats will be saved.
+ * @nbr Number of network interfaces to read.
+ *
+ * OUT:
+ * @st_net_dev Structure with statistics.
+ ***************************************************************************
+ */
+void read_if_info(struct stats_net_dev *st_net_dev, int nbr)
+{
+ FILE *fp;
+ struct stats_net_dev *st_net_dev_i;
+ char filename[128], duplex[32];
+ int dev, n;
+
+ for (dev = 0; dev < nbr; dev++) {
+
+ st_net_dev_i = st_net_dev + dev;
+
+ /* Read speed info */
+ sprintf(filename, IF_DUPLEX, st_net_dev_i->interface);
+
+ if ((fp = fopen(filename, "r")) == NULL)
+ /* Cannot read NIC duplex */
+ continue;
+
+ n = fscanf(fp, "%31s", duplex);
+
+ fclose(fp);
+
+ if (n != 1)
+ /* Cannot read NIC duplex */
+ continue;
+
+ if (!strcmp(duplex, K_DUPLEX_FULL)) {
+ st_net_dev_i->duplex = C_DUPLEX_FULL;
+ }
+ else if (!strcmp(duplex, K_DUPLEX_HALF)) {
+ st_net_dev_i->duplex = C_DUPLEX_HALF;
+ }
+ else
+ continue;
+
+ /* Read speed info */
+ sprintf(filename, IF_SPEED, st_net_dev_i->interface);
+
+ if ((fp = fopen(filename, "r")) == NULL)
+ /* Cannot read NIC speed */
+ continue;
+
+ n = fscanf(fp, "%u", &st_net_dev_i->speed);
+
+ fclose(fp);
+
+ if (n != 1) {
+ st_net_dev_i->speed = 0;
+ }
+ }
+}
+
+
/*
***************************************************************************
* Read network interfaces errors statistics from /proc/net/dev.
*
* IN:
* @st_net_edev Structure where stats will be saved.
- * @nbr Maximum number of network interfaces.
+ * @nr_alloc Total number of structures allocated. Value is >= 1.
*
* OUT:
* @st_net_edev Structure with statistics.
+ *
+ * RETURNS:
+ * Number of interfaces read, or -1 if the buffer was too small and
+ * needs to be reallocated.
***************************************************************************
*/
-void read_net_edev(struct stats_net_edev *st_net_edev, int nbr)
+__nr_t read_net_edev(struct stats_net_edev *st_net_edev, __nr_t nr_alloc)
{
FILE *fp;
struct stats_net_edev *st_net_edev_i;
static char line[256];
char iface[MAX_IFACE_LEN];
- int dev = 0;
+ __nr_t dev_read = 0;
int pos;
if ((fp = fopen(NET_DEV, "r")) == NULL)
- return;
+ return 0;
- while ((fgets(line, 256, fp) != NULL) && (dev < nbr)) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
pos = strcspn(line, ":");
if (pos < strlen(line)) {
- st_net_edev_i = st_net_edev + dev;
+
+ if (dev_read + 1 > nr_alloc) {
+ dev_read = -1;
+ break;
+ }
+
+ st_net_edev_i = st_net_edev + dev_read++;
strncpy(iface, line, MINIMUM(pos, MAX_IFACE_LEN - 1));
iface[MINIMUM(pos, MAX_IFACE_LEN - 1)] = '\0';
sscanf(iface, "%s", st_net_edev_i->interface); /* Skip heading spaces */
&st_net_edev_i->tx_fifo_errors,
&st_net_edev_i->collisions,
&st_net_edev_i->tx_carrier_errors);
- dev++;
}
}
fclose(fp);
+ return dev_read;
}
/*
*
* OUT:
* @st_net_nfs Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_nfs(struct stats_net_nfs *st_net_nfs)
+__nr_t read_net_nfs(struct stats_net_nfs *st_net_nfs)
{
FILE *fp;
char line[256];
unsigned int getattcnt = 0, accesscnt = 0, readcnt = 0, writecnt = 0;
if ((fp = fopen(NET_RPC_NFS, "r")) == NULL)
- return;
+ return 0;
memset(st_net_nfs, 0, STATS_NET_NFS_SIZE);
-
- while (fgets(line, 256, fp) != NULL) {
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "rpc ", 4)) {
sscanf(line + 4, "%u %u",
else if (!strncmp(line, "proc3 ", 6)) {
sscanf(line + 6, "%*u %*u %u %*u %*u %u %*u %u %u",
&getattcnt, &accesscnt, &readcnt, &writecnt);
-
+
st_net_nfs->nfs_getattcnt += getattcnt;
st_net_nfs->nfs_accesscnt += accesscnt;
st_net_nfs->nfs_readcnt += readcnt;
sscanf(line + 6, "%*u %*u %u %u "
"%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %u %u",
&readcnt, &writecnt, &accesscnt, &getattcnt);
-
+
st_net_nfs->nfs_getattcnt += getattcnt;
st_net_nfs->nfs_accesscnt += accesscnt;
st_net_nfs->nfs_readcnt += readcnt;
}
fclose(fp);
+ return 1;
}
/*
*
* OUT:
* @st_net_nfsd Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_nfsd(struct stats_net_nfsd *st_net_nfsd)
+__nr_t read_net_nfsd(struct stats_net_nfsd *st_net_nfsd)
{
FILE *fp;
char line[256];
unsigned int getattcnt = 0, accesscnt = 0, readcnt = 0, writecnt = 0;
if ((fp = fopen(NET_RPC_NFSD, "r")) == NULL)
- return;
-
+ return 0;
+
memset(st_net_nfsd, 0, STATS_NET_NFSD_SIZE);
- while (fgets(line, 256, fp) != NULL) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "rc ", 3)) {
sscanf(line + 3, "%u %u",
st_net_nfsd->nfsd_accesscnt += accesscnt;
st_net_nfsd->nfsd_readcnt += readcnt;
st_net_nfsd->nfsd_writecnt += writecnt;
-
+
}
else if (!strncmp(line, "proc4ops ", 9)) {
sscanf(line + 9, "%*u %*u %*u %*u %u "
"%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %u "
"%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %u",
&accesscnt, &getattcnt, &readcnt, &writecnt);
-
+
st_net_nfsd->nfsd_getattcnt += getattcnt;
st_net_nfsd->nfsd_accesscnt += accesscnt;
st_net_nfsd->nfsd_readcnt += readcnt;
}
fclose(fp);
+ return 1;
}
/*
*
* OUT:
* @st_net_sock Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_sock(struct stats_net_sock *st_net_sock)
+__nr_t read_net_sock(struct stats_net_sock *st_net_sock)
{
FILE *fp;
char line[96];
char *p;
if ((fp = fopen(NET_SOCKSTAT, "r")) == NULL)
- return;
-
- while (fgets(line, 96, fp) != NULL) {
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "sockets:", 8)) {
/* Sockets */
}
fclose(fp);
+ return 1;
}
/*
*
* OUT:
* @st_net_ip Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_ip(struct stats_net_ip *st_net_ip)
+__nr_t read_net_ip(struct stats_net_ip *st_net_ip)
{
FILE *fp;
char line[1024];
int sw = FALSE;
if ((fp = fopen(NET_SNMP, "r")) == NULL)
- return;
-
- while (fgets(line, 1024, fp) != NULL) {
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "Ip:", 3)) {
if (sw) {
&st_net_ip->ReasmOKs,
&st_net_ip->FragOKs,
&st_net_ip->FragCreates);
-
+
break;
}
else {
}
fclose(fp);
+ return 1;
}
/*
***************************************************************************
- * Read IP network error statistics from /proc/net/snmp.
+ * Read IP network errors statistics from /proc/net/snmp.
*
* IN:
* @st_net_eip Structure where stats will be saved.
*
* OUT:
* @st_net_eip Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_eip(struct stats_net_eip *st_net_eip)
+__nr_t read_net_eip(struct stats_net_eip *st_net_eip)
{
FILE *fp;
char line[1024];
int sw = FALSE;
if ((fp = fopen(NET_SNMP, "r")) == NULL)
- return;
-
- while (fgets(line, 1024, fp) != NULL) {
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "Ip:", 3)) {
if (sw) {
&st_net_eip->OutNoRoutes,
&st_net_eip->ReasmFails,
&st_net_eip->FragFails);
-
+
break;
}
else {
}
fclose(fp);
+ return 1;
}
/*
*
* OUT:
* @st_net_icmp Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_icmp(struct stats_net_icmp *st_net_icmp)
+__nr_t read_net_icmp(struct stats_net_icmp *st_net_icmp)
{
FILE *fp;
char line[1024];
+ static char format[256] = "";
int sw = FALSE;
if ((fp = fopen(NET_SNMP, "r")) == NULL)
- return;
-
- while (fgets(line, 1024, fp) != NULL) {
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "Icmp:", 5)) {
if (sw) {
- sscanf(line + 5, "%lu %*u %*u %*u %*u %*u %*u "
- "%lu %lu %lu %lu %lu %lu %lu %*u %*u %*u %*u "
- "%*u %*u %lu %lu %lu %lu %lu %lu",
+ sscanf(line + 5, format,
&st_net_icmp->InMsgs,
&st_net_icmp->InEchos,
&st_net_icmp->InEchoReps,
break;
}
else {
+ if (!strlen(format)) {
+ if (strstr(line, "InCsumErrors")) {
+ /*
+ * New format: InCsumErrors field exists at position #3.
+ * Capture: 1,9,10,11,12,13,14,15,22,23,24,25,26,27.
+ */
+ strcpy(format, "%lu %*u %*u %*u %*u %*u %*u %*u "
+ "%lu %lu %lu %lu %lu %lu %lu %*u %*u %*u %*u "
+ "%*u %*u %lu %lu %lu %lu %lu %lu");
+ }
+ else {
+ /*
+ * Old format: InCsumErrors field doesn't exist.
+ * Capture: 1,8,9,10,11,12,13,14,21,22,23,24,25,26.
+ */
+ strcpy(format, "%lu %*u %*u %*u %*u %*u %*u "
+ "%lu %lu %lu %lu %lu %lu %lu %*u %*u %*u %*u "
+ "%*u %*u %lu %lu %lu %lu %lu %lu");
+ }
+ }
sw = TRUE;
}
}
}
fclose(fp);
+ return 1;
}
/*
***************************************************************************
- * Read ICMP network error statistics from /proc/net/snmp.
+ * Read ICMP network errors statistics from /proc/net/snmp.
*
* IN:
* @st_net_eicmp Structure where stats will be saved.
*
* OUT:
* @st_net_eicmp Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_eicmp(struct stats_net_eicmp *st_net_eicmp)
+__nr_t read_net_eicmp(struct stats_net_eicmp *st_net_eicmp)
{
FILE *fp;
char line[1024];
+ static char format[256] = "";
int sw = FALSE;
if ((fp = fopen(NET_SNMP, "r")) == NULL)
- return;
-
- while (fgets(line, 1024, fp) != NULL) {
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "Icmp:", 5)) {
if (sw) {
- sscanf(line + 5, "%*u %lu %lu %lu %lu %lu %lu %*u %*u "
- "%*u %*u %*u %*u %*u %lu %lu %lu %lu %lu %lu",
+ sscanf(line + 5, format,
&st_net_eicmp->InErrors,
&st_net_eicmp->InDestUnreachs,
&st_net_eicmp->InTimeExcds,
break;
}
else {
+ if (!strlen(format)) {
+ if (strstr(line, "InCsumErrors")) {
+ /*
+ * New format: InCsumErrors field exists at position #3.
+ * Capture: 2,4,5,6,7,8,16,17,18,19,20,21
+ */
+ strcpy(format, "%*u %lu %*u %lu %lu %lu %lu %lu %*u %*u "
+ "%*u %*u %*u %*u %*u %lu %lu %lu %lu %lu %lu");
+ }
+ else {
+ /*
+ * Old format: InCsumErrors field doesn't exist.
+ * Capture: 2,3,4,5,6,7,15,16,17,18,19,20
+ */
+ strcpy(format, "%*u %lu %lu %lu %lu %lu %lu %*u %*u "
+ "%*u %*u %*u %*u %*u %lu %lu %lu %lu %lu %lu");
+
+ }
+ }
sw = TRUE;
}
}
}
fclose(fp);
+ return 1;
}
/*
*
* OUT:
* @st_net_tcp Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_tcp(struct stats_net_tcp *st_net_tcp)
+__nr_t read_net_tcp(struct stats_net_tcp *st_net_tcp)
{
FILE *fp;
char line[1024];
int sw = FALSE;
if ((fp = fopen(NET_SNMP, "r")) == NULL)
- return;
-
- while (fgets(line, 1024, fp) != NULL) {
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "Tcp:", 4)) {
if (sw) {
}
fclose(fp);
+ return 1;
}
/*
***************************************************************************
- * Read TCP network error statistics from /proc/net/snmp.
+ * Read TCP network errors statistics from /proc/net/snmp.
*
* IN:
* @st_net_etcp Structure where stats will be saved.
*
* OUT:
* @st_net_etcp Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_etcp(struct stats_net_etcp *st_net_etcp)
+__nr_t read_net_etcp(struct stats_net_etcp *st_net_etcp)
{
FILE *fp;
char line[1024];
int sw = FALSE;
if ((fp = fopen(NET_SNMP, "r")) == NULL)
- return;
-
- while (fgets(line, 1024, fp) != NULL) {
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "Tcp:", 4)) {
if (sw) {
}
fclose(fp);
+ return 1;
}
/*
*
* OUT:
* @st_net_udp Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_udp(struct stats_net_udp *st_net_udp)
+__nr_t read_net_udp(struct stats_net_udp *st_net_udp)
{
FILE *fp;
char line[1024];
int sw = FALSE;
if ((fp = fopen(NET_SNMP, "r")) == NULL)
- return;
-
- while (fgets(line, 1024, fp) != NULL) {
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "Udp:", 4)) {
if (sw) {
}
fclose(fp);
+ return 1;
}
/*
*
* OUT:
* @st_net_sock6 Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_sock6(struct stats_net_sock6 *st_net_sock6)
+__nr_t read_net_sock6(struct stats_net_sock6 *st_net_sock6)
{
FILE *fp;
char line[96];
if ((fp = fopen(NET_SOCKSTAT6, "r")) == NULL)
- return;
-
- while (fgets(line, 96, fp) != NULL) {
+ return 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "TCP6:", 5)) {
/* TCPv6 sockets */
}
fclose(fp);
+ return 1;
}
/*
*
* OUT:
* @st_net_ip6 Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_ip6(struct stats_net_ip6 *st_net_ip6)
+__nr_t read_net_ip6(struct stats_net_ip6 *st_net_ip6)
{
FILE *fp;
char line[128];
if ((fp = fopen(NET_SNMP6, "r")) == NULL)
- return;
+ return 0;
- while (fgets(line, 128, fp) != NULL) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "Ip6InReceives ", 14)) {
sscanf(line + 14, "%llu", &st_net_ip6->InReceives6);
sscanf(line + 15, "%llu", &st_net_ip6->FragCreates6);
}
}
-
+
fclose(fp);
+ return 1;
}
/*
***************************************************************************
- * Read IPv6 network error statistics from /proc/net/snmp6.
+ * Read IPv6 network errors statistics from /proc/net/snmp6.
*
* IN:
* @st_net_eip6 Structure where stats will be saved.
*
* OUT:
* @st_net_eip6 Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_eip6(struct stats_net_eip6 *st_net_eip6)
+__nr_t read_net_eip6(struct stats_net_eip6 *st_net_eip6)
{
FILE *fp;
char line[128];
if ((fp = fopen(NET_SNMP6, "r")) == NULL)
- return;
+ return 0;
- while (fgets(line, 128, fp) != NULL) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "Ip6InHdrErrors ", 15)) {
sscanf(line + 15, "%llu", &st_net_eip6->InHdrErrors6);
sscanf(line + 19, "%llu", &st_net_eip6->InTruncatedPkts6);
}
}
-
+
fclose(fp);
+ return 1;
}
/*
*
* OUT:
* @st_net_icmp6 Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_icmp6(struct stats_net_icmp6 *st_net_icmp6)
+__nr_t read_net_icmp6(struct stats_net_icmp6 *st_net_icmp6)
{
FILE *fp;
char line[128];
if ((fp = fopen(NET_SNMP6, "r")) == NULL)
- return;
+ return 0;
- while (fgets(line, 128, fp) != NULL) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "Icmp6InMsgs ", 12)) {
sscanf(line + 12, "%lu", &st_net_icmp6->InMsgs6);
sscanf(line + 31, "%lu", &st_net_icmp6->OutNeighborAdvertisements6);
}
}
-
+
fclose(fp);
+ return 1;
}
/*
***************************************************************************
- * Read ICMPv6 network error statistics from /proc/net/snmp6.
+ * Read ICMPv6 network errors statistics from /proc/net/snmp6.
*
* IN:
* @st_net_eicmp6 Structure where stats will be saved.
*
* OUT:
* @st_net_eicmp6 Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_eicmp6(struct stats_net_eicmp6 *st_net_eicmp6)
+__nr_t read_net_eicmp6(struct stats_net_eicmp6 *st_net_eicmp6)
{
FILE *fp;
char line[128];
if ((fp = fopen(NET_SNMP6, "r")) == NULL)
- return;
+ return 0;
- while (fgets(line, 128, fp) != NULL) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "Icmp6InErrors ", 14)) {
sscanf(line + 14, "%lu", &st_net_eicmp6->InErrors6);
sscanf(line + 19, "%lu", &st_net_eicmp6->OutPktTooBigs6);
}
}
-
+
fclose(fp);
+ return 1;
}
/*
*
* OUT:
* @st_net_udp6 Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_net_udp6(struct stats_net_udp6 *st_net_udp6)
+__nr_t read_net_udp6(struct stats_net_udp6 *st_net_udp6)
{
FILE *fp;
char line[128];
if ((fp = fopen(NET_SNMP6, "r")) == NULL)
- return;
+ return 0;
- while (fgets(line, 128, fp) != NULL) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "Udp6InDatagrams ", 16)) {
sscanf(line + 16, "%lu", &st_net_udp6->InDatagrams6);
sscanf(line + 13, "%lu", &st_net_udp6->InErrors6);
}
}
-
+
fclose(fp);
+ return 1;
}
/*
*
* IN:
* @st_pwr_cpufreq Structure where stats will be saved.
- * @nbr Total number of CPU (including cpu "all").
+ * @nr_alloc Total number of structures allocated. Value is >= 1.
*
* OUT:
* @st_pwr_cpufreq Structure with statistics.
+ *
+ * RETURNS:
+ * Highest CPU number for which statistics have been read.
+ * 1 means CPU "all", 2 means CPU 0, 3 means CPU 1, etc.
+ * Or -1 if the buffer was too small and needs to be reallocated.
***************************************************************************
*/
-void read_cpuinfo(struct stats_pwr_cpufreq *st_pwr_cpufreq, int nbr)
+__nr_t read_cpuinfo(struct stats_pwr_cpufreq *st_pwr_cpufreq, __nr_t nr_alloc)
{
FILE *fp;
struct stats_pwr_cpufreq *st_pwr_cpufreq_i;
char line[1024];
- int proc_nb = 0, nr = 0;
- unsigned int ifreq, dfreq;
-
+ int nr = 0;
+ __nr_t cpu_read = 1; /* For CPU "all" */
+ unsigned int proc_nr = 0, ifreq, dfreq;
+
if ((fp = fopen(CPUINFO, "r")) == NULL)
- return;
-
+ return 0;
+
st_pwr_cpufreq->cpufreq = 0;
-
- while (fgets(line, 1024, fp) != NULL) {
-
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+
if (!strncmp(line, "processor\t", 10)) {
- sscanf(strchr(line, ':') + 1, "%d", &proc_nb);
+ sscanf(strchr(line, ':') + 1, "%u", &proc_nr);
+
+ if (proc_nr + 2 > nr_alloc) {
+ cpu_read = -1;
+ break;
+ }
}
-
- else if (!strncmp(line, "cpu MHz\t", 8)) {
+
+ /* Entry in /proc/cpuinfo is different between Intel and Power architectures */
+ else if (!strncmp(line, "cpu MHz\t", 8) ||
+ !strncmp(line, "clock\t", 6)) {
sscanf(strchr(line, ':') + 1, "%u.%u", &ifreq, &dfreq);
-
- if (proc_nb < (nbr - 1)) {
- /* Save current CPU frequency */
- st_pwr_cpufreq_i = st_pwr_cpufreq + proc_nb + 1;
- st_pwr_cpufreq_i->cpufreq = ifreq * 100 + dfreq / 10;
-
- /* Also save it to compute an average CPU frequency */
- st_pwr_cpufreq->cpufreq += st_pwr_cpufreq_i->cpufreq;
- nr++;
- }
- else if (!proc_nb && (nbr == 1)) {
- /*
- * We are reading freq for "Processor 0" and we have a machine
- * with only one processor and not an SMP kernel, with /sys not mounted
- * (the nr of proc has been counted using /proc/stat and there was
- * only one line with global CPU stats here).
- * This is a very specific case, I must admit...
- */
- st_pwr_cpufreq->cpufreq = ifreq * 100 + dfreq / 10;
+
+ /* Save current CPU frequency */
+ st_pwr_cpufreq_i = st_pwr_cpufreq + proc_nr + 1;
+ st_pwr_cpufreq_i->cpufreq = ifreq * 100 + dfreq / 10;
+
+ /* Also save it to compute an average CPU frequency */
+ st_pwr_cpufreq->cpufreq += st_pwr_cpufreq_i->cpufreq;
+ nr++;
+
+ if (proc_nr + 2 > cpu_read) {
+ cpu_read = proc_nr + 2;
}
}
}
-
+
fclose(fp);
-
+
if (nr) {
/* Compute average CPU frequency for this machine */
st_pwr_cpufreq->cpufreq /= nr;
}
+ return cpu_read;
}
/*
*
* OUT:
* @st_huge Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_meminfo_huge(struct stats_huge *st_huge)
+__nr_t read_meminfo_huge(struct stats_huge *st_huge)
{
FILE *fp;
char line[128];
unsigned long szhkb = 0;
if ((fp = fopen(MEMINFO, "r")) == NULL)
- return;
+ return 0;
- while (fgets(line, 128, fp) != NULL) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
if (!strncmp(line, "HugePages_Total:", 16)) {
/* Read the total number of huge pages */
- sscanf(line + 16, "%lu", &st_huge->tlhkb);
+ sscanf(line + 16, "%llu", &st_huge->tlhkb);
}
else if (!strncmp(line, "HugePages_Free:", 15)) {
/* Read the number of free huge pages */
- sscanf(line + 15, "%lu", &st_huge->frhkb);
+ sscanf(line + 15, "%llu", &st_huge->frhkb);
+ }
+ else if (!strncmp(line, "HugePages_Rsvd:", 15)) {
+ /* Read the number of reserved huge pages */
+ sscanf(line + 15, "%llu", &st_huge->rsvdhkb);
+ }
+ else if (!strncmp(line, "HugePages_Surp:", 15)) {
+ /* Read the number of surplus huge pages */
+ sscanf(line + 15, "%llu", &st_huge->surphkb);
}
else if (!strncmp(line, "Hugepagesize:", 13)) {
/* Read the default size of a huge page in kB */
/* We want huge pages stats in kB and not expressed in a number of pages */
st_huge->tlhkb *= szhkb;
st_huge->frhkb *= szhkb;
+ st_huge->rsvdhkb *= szhkb;
+ st_huge->surphkb *= szhkb;
+
+ return 1;
}
/*
*
* OUT:
* @st_pwr_wghfreq Structure with statistics.
+ *
+ * RETURNS:
+ * 1 on success, 0 otherwise.
***************************************************************************
*/
-void read_time_in_state(struct stats_pwr_wghfreq *st_pwr_wghfreq, int cpu_nr, int nbr)
+int read_time_in_state(struct stats_pwr_wghfreq *st_pwr_wghfreq, int cpu_nr, int nbr)
{
FILE *fp;
struct stats_pwr_wghfreq *st_pwr_wghfreq_j;
snprintf(filename, MAX_PF_NAME, "%s/cpu%d/%s",
SYSFS_DEVCPU, cpu_nr, SYSFS_TIME_IN_STATE);
if ((fp = fopen(filename, "r")) == NULL)
- return;
+ return 0;
- while (fgets(line, 128, fp) != NULL) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
sscanf(line, "%lu %llu", &freq, &time_in_state);
}
fclose(fp);
+ return 1;
+}
+
+/*
+ ***************************************************************************
+ * Read weighted CPU frequency statistics.
+ *
+ * IN:
+ * @st_pwr_wghfreq Structure where stats will be saved.
+ * @nr_alloc Total number of structures allocated. Value is >= 0.
+ * @nr2 Number of sub-items allocated per structure.
+ *
+ * OUT:
+ * @st_pwr_wghfreq Structure with statistics.
+ *
+ * RETURNS:
+ * Number of CPU for which statistics have been read.
+ * 1 means CPU "all", 2 means CPU "all" and 0, etc.
+ * Or -1 if the buffer was to small and needs to be reallocated.
+ ***************************************************************************
+ */
+__nr_t read_cpu_wghfreq(struct stats_pwr_wghfreq *st_pwr_wghfreq, __nr_t nr_alloc,
+ __nr_t nr2)
+{
+ __nr_t cpu_read = 0;
+ int j;
+ struct stats_pwr_wghfreq *st_pwr_wghfreq_i, *st_pwr_wghfreq_j, *st_pwr_wghfreq_all_j;
+
+ do {
+ if (cpu_read + 2 > nr_alloc)
+ return -1;
+
+ /* Read current CPU time-in-state data */
+ st_pwr_wghfreq_i = st_pwr_wghfreq + (cpu_read + 1) * nr2;
+ if (!read_time_in_state(st_pwr_wghfreq_i, cpu_read, nr2))
+ break;
+
+ /* Also save data for CPU 'all' */
+ for (j = 0; j < nr2; j++) {
+ st_pwr_wghfreq_j = st_pwr_wghfreq_i + j; /* CPU #cpu, state #j */
+ st_pwr_wghfreq_all_j = st_pwr_wghfreq + j; /* CPU #all, state #j */
+ if (!cpu_read) {
+ /* Assume that possible frequencies are the same for all CPUs */
+ st_pwr_wghfreq_all_j->freq = st_pwr_wghfreq_j->freq;
+ }
+ st_pwr_wghfreq_all_j->time_in_state += st_pwr_wghfreq_j->time_in_state;
+ }
+ cpu_read++;
+ }
+ while (1);
+
+ if (cpu_read > 0) {
+ for (j = 0; j < nr2; j++) {
+ st_pwr_wghfreq_all_j = st_pwr_wghfreq + j; /* CPU #all, state #j */
+ st_pwr_wghfreq_all_j->time_in_state /= cpu_read;
+ }
+
+ return cpu_read + 1; /* For CPU "all" */
+ }
+
+ return 0;
}
/*
*/
void read_usb_stats(struct stats_pwr_usb *st_pwr_usb, char *usb_device)
{
- int l;
+ int l, rc;
FILE *fp;
+ char * rs;
char filename[MAX_PF_NAME];
/* Get USB device bus number */
snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
SYSFS_USBDEV, usb_device, SYSFS_IDVENDOR);
if ((fp = fopen(filename, "r")) != NULL) {
- fscanf(fp, "%x",
- &st_pwr_usb->vendor_id);
+ rc = fscanf(fp, "%x",
+ &st_pwr_usb->vendor_id);
fclose(fp);
+ if (rc == 0) {
+ st_pwr_usb->vendor_id = 0;
+ }
}
/* Read USB device product ID */
snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
SYSFS_USBDEV, usb_device, SYSFS_IDPRODUCT);
if ((fp = fopen(filename, "r")) != NULL) {
- fscanf(fp, "%x",
- &st_pwr_usb->product_id);
+ rc = fscanf(fp, "%x",
+ &st_pwr_usb->product_id);
fclose(fp);
+ if (rc == 0) {
+ st_pwr_usb->product_id = 0;
+ }
}
-
+
/* Read USB device max power consumption */
snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
SYSFS_USBDEV, usb_device, SYSFS_BMAXPOWER);
if ((fp = fopen(filename, "r")) != NULL) {
- fscanf(fp, "%u",
- &st_pwr_usb->bmaxpower);
+ rc = fscanf(fp, "%u",
+ &st_pwr_usb->bmaxpower);
fclose(fp);
+ if (rc == 0) {
+ st_pwr_usb->bmaxpower = 0;
+ }
}
/* Read USB device manufacturer */
snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
SYSFS_USBDEV, usb_device, SYSFS_MANUFACTURER);
if ((fp = fopen(filename, "r")) != NULL) {
- fgets(st_pwr_usb->manufacturer, MAX_MANUF_LEN - 1, fp);
+ rs = fgets(st_pwr_usb->manufacturer,
+ MAX_MANUF_LEN - 1, fp);
fclose(fp);
- if ((l = strlen(st_pwr_usb->manufacturer)) > 0) {
+ if ((rs != NULL) &&
+ (l = strlen(st_pwr_usb->manufacturer)) > 0) {
/* Remove trailing CR */
st_pwr_usb->manufacturer[l - 1] = '\0';
}
snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
SYSFS_USBDEV, usb_device, SYSFS_PRODUCT);
if ((fp = fopen(filename, "r")) != NULL) {
- fgets(st_pwr_usb->product, MAX_PROD_LEN - 1, fp);
+ rs = fgets(st_pwr_usb->product,
+ MAX_PROD_LEN - 1, fp);
fclose(fp);
- if ((l = strlen(st_pwr_usb->product)) > 0) {
+ if ((rs != NULL) &&
+ (l = strlen(st_pwr_usb->product)) > 0) {
/* Remove trailing CR */
st_pwr_usb->product[l - 1] = '\0';
}
*
* IN:
* @st_pwr_usb Structure where stats will be saved.
- * @nbr Total number of USB devices.
+ * @nr_alloc Total number of structures allocated. Value is >= 0.
*
* OUT:
* @st_pwr_usb Structure with statistics.
+ *
+ * RETURNS:
+ * Number of USB devices read, or -1 if the buffer was too small and
+ * needs to be reallocated.
***************************************************************************
*/
-void read_bus_usb_dev(struct stats_pwr_usb *st_pwr_usb, int nbr)
+__nr_t read_bus_usb_dev(struct stats_pwr_usb *st_pwr_usb, __nr_t nr_alloc)
{
DIR *dir;
struct dirent *drd;
- struct stats_pwr_usb *st_pwr_usb_j;
- int j = 0;
+ struct stats_pwr_usb *st_pwr_usb_i;
+ __nr_t usb_read = 0;
/* Open relevant /sys directory */
if ((dir = opendir(SYSFS_USBDEV)) == NULL)
- return;
+ return 0;
/* Get current file entry */
while ((drd = readdir(dir)) != NULL) {
if (isdigit(drd->d_name[0]) && !strchr(drd->d_name, ':')) {
- if (j < nbr) {
- /* Read current USB device data */
- st_pwr_usb_j = st_pwr_usb + j;
- read_usb_stats(st_pwr_usb_j, drd->d_name);
- j++;
- }
- else
+
+ if (usb_read + 1 > nr_alloc) {
+ usb_read = -1;
break;
+ }
+
+ /* Read current USB device data */
+ st_pwr_usb_i = st_pwr_usb + usb_read++;
+ read_usb_stats(st_pwr_usb_i, drd->d_name);
}
}
/* Close directory */
closedir(dir);
+ return usb_read;
}
/*
***************************************************************************
- * Read machine uptime, independently of the number of processors.
+ * Read filesystems statistics.
+ *
+ * IN:
+ * @st_filesystem Structure where stats will be saved.
+ * @nr_alloc Total number of structures allocated. Value is >= 0.
*
* OUT:
- * @uptime Uptime value in jiffies.
- ***************************************************************************
- */
-void read_uptime(unsigned long long *uptime)
-{
- FILE *fp;
- char line[128];
- unsigned long up_sec, up_cent;
-
- if ((fp = fopen(UPTIME, "r")) == NULL)
- return;
-
- if (fgets(line, 128, fp) == NULL) {
- fclose(fp);
- return;
- }
-
- sscanf(line, "%lu.%lu", &up_sec, &up_cent);
- *uptime = (unsigned long long) up_sec * HZ +
- (unsigned long long) up_cent * HZ / 100;
-
- fclose(fp);
-
-}
-
-/*
- ***************************************************************************
- * Count number of interrupts that are in /proc/stat file.
+ * @st_filesystem Structure with statistics.
*
* RETURNS:
- * Number of interrupts, including total number of interrupts.
+ * Number of filesystems read, or -1 if the buffer was too small and
+ * needs to be reallocated.
***************************************************************************
*/
-int get_irq_nr(void)
+__nr_t read_filesystem(struct stats_filesystem *st_filesystem, __nr_t nr_alloc)
{
FILE *fp;
- char line[8192];
- int in = 0;
- int pos = 4;
-
- if ((fp = fopen(STAT, "r")) == NULL)
+ char line[512], fs_name[MAX_FS_LEN], mountp[256], type[128];
+ int skip = 0, skip_next = 0;
+ char *pos = 0, *pos2 = 0;
+ __nr_t fs_read = 0;
+ struct stats_filesystem *st_filesystem_i;
+ struct statvfs buf;
+
+ if ((fp = fopen(MTAB, "r")) == NULL)
return 0;
- while (fgets(line, 8192, fp) != NULL) {
-
- if (!strncmp(line, "intr ", 5)) {
-
- while (pos < strlen(line)) {
- in++;
- pos += strcspn(line + pos + 1, " ") + 1;
- }
- }
- }
-
- fclose(fp);
-
- return in;
-}
-
-/*
- ***************************************************************************
- * Find number of serial lines that support tx/rx accounting
- * in /proc/tty/driver/serial file.
- *
- * RETURNS:
- * Number of serial lines supporting tx/rx accouting.
- ***************************************************************************
- */
-int get_serial_nr(void)
-{
- FILE *fp;
- char line[256];
- int sl = 0;
-
- if ((fp = fopen(SERIAL, "r")) == NULL)
- return 0; /* No SERIAL file */
-
- while (fgets(line, 256, fp) != NULL) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
/*
- * tx/rx statistics are always present,
- * except when serial line is unknown.
+ * Ignore line if the preceding line did not contain '\n'.
+ * (Some very long lines may be found for instance when
+ * overlay2 filesystem with docker is used).
*/
- if (strstr(line, "tx:") != NULL) {
- sl++;
- }
- }
-
- fclose(fp);
-
- return sl;
-}
-
-/*
- ***************************************************************************
- * Find number of interfaces (network devices) that are in /proc/net/dev
- * file.
- *
- * RETURNS:
- * Number of network interfaces.
- ***************************************************************************
- */
-int get_iface_nr(void)
-{
- FILE *fp;
- char line[128];
- int iface = 0;
+ skip = skip_next;
+ skip_next = (strchr(line, '\n') == NULL);
+ if (skip)
+ continue;
+
+ if (line[0] == '/') {
+ /* Find field separator position */
+ pos = strchr(line, ' ');
+ if (pos == NULL)
+ continue;
- if ((fp = fopen(NET_DEV, "r")) == NULL)
- return 0; /* No network device file */
+ /*
+ * Find second field separator position,
+ * read filesystem type,
+ * if filesystem type is autofs, skip it
+ */
+ pos2 = strchr(pos + 1, ' ');
+ if (pos2 == NULL)
+ continue;
- while (fgets(line, 128, fp) != NULL) {
- if (strchr(line, ':')) {
- iface++;
- }
- }
+ sscanf(pos2 + 1, "%127s", type);
+ if(strcmp(type, "autofs") == 0)
+ continue;
- fclose(fp);
+ /* Read current filesystem name */
+ sscanf(line, "%127s", fs_name);
+ /*
+ * And now read the corresponding mount point.
+ * Read fs name and mount point in two distinct operations.
+ * Indeed, if fs name length is greater than 127 chars,
+ * previous scanf() will read only the first 127 chars, and
+ * mount point name will be read using the remaining chars
+ * from the fs name. This will result in a bogus name
+ * and following statvfs() function will always fail.
+ */
+ sscanf(pos + 1, "%255s", mountp);
- return iface;
-}
+ /* Replace octal codes */
+ oct2chr(mountp);
-/*
- ***************************************************************************
- * Find number of devices and partitions available in /proc/diskstats.
- *
- * IN:
- * @count_part Set to TRUE if devices _and_ partitions are to be
- * counted.
- * @only_used_dev When counting devices, set to TRUE if only devices
- * with non zero stats must be counted.
- *
- * RETURNS:
- * Number of devices (and partitions).
- ***************************************************************************
- */
-int get_diskstats_dev_nr(int count_part, int only_used_dev)
-{
- FILE *fp;
- char line[256];
- char dev_name[MAX_NAME_LEN];
- int dev = 0, i;
- unsigned long rd_ios, wr_ios;
+ /*
+ * It's important to have read the whole mount point name
+ * for statvfs() to work properly (see above).
+ */
+ if ((__statvfs(mountp, &buf) < 0) || (!buf.f_blocks))
+ continue;
- if ((fp = fopen(DISKSTATS, "r")) == NULL)
- /* File non-existent */
- return 0;
+ if (fs_read + 1 > nr_alloc) {
+ fs_read = -1;
+ break;
+ }
- /*
- * Counting devices and partitions is simply a matter of counting
- * the number of lines...
- */
- while (fgets(line, 256, fp) != NULL) {
- if (!count_part) {
- i = sscanf(line, "%*d %*d %s %lu %*u %*u %*u %lu",
- dev_name, &rd_ios, &wr_ios);
- if ((i == 2) || !is_device(dev_name, ACCEPT_VIRTUAL_DEVICES))
- /* It was a partition and not a device */
- continue;
- if (only_used_dev && !rd_ios && !wr_ios)
- /* Unused device */
- continue;
+ st_filesystem_i = st_filesystem + fs_read++;
+ st_filesystem_i->f_blocks = (unsigned long long) buf.f_blocks * (unsigned long long) buf.f_frsize;
+ st_filesystem_i->f_bfree = (unsigned long long) buf.f_bfree * (unsigned long long) buf.f_frsize;
+ st_filesystem_i->f_bavail = (unsigned long long) buf.f_bavail * (unsigned long long) buf.f_frsize;
+ st_filesystem_i->f_files = (unsigned long long) buf.f_files;
+ st_filesystem_i->f_ffree = (unsigned long long) buf.f_ffree;
+ strncpy(st_filesystem_i->fs_name, fs_name, MAX_FS_LEN);
+ st_filesystem_i->fs_name[MAX_FS_LEN - 1] = '\0';
+ strncpy(st_filesystem_i->mountp, mountp, MAX_FS_LEN);
+ st_filesystem_i->mountp[MAX_FS_LEN - 1] = '\0';
}
- dev++;
}
fclose(fp);
-
- return dev;
+ return fs_read;
}
/*
***************************************************************************
- * Get number of devices in /proc/diskstats.
+ * Read Fibre Channel HBA statistics.
*
* IN:
- * @f Non zero (true) if disks *and* partitions should be counted, and
- * zero (false) if only disks must be counted.
+ * @st_fc Structure where stats will be saved.
+ * @nr_alloc Total number of structures allocated. Value is >= 0.
*
- * RETURNS:
- * Number of devices.
- ***************************************************************************
- */
-int get_disk_nr(unsigned int f)
-{
- int disk_nr;
-
- /*
- * Partitions are taken into account by sar -d only with
- * kernels 2.6.25 and later.
- */
- disk_nr = get_diskstats_dev_nr(f, CNT_USED_DEV);
-
- return disk_nr;
-}
-
-/*
- ***************************************************************************
- * Count number of processors in /sys.
+ * OUT:
+ * @st_fc Structure with statistics.
*
* RETURNS:
- * Number of processors (online and offline).
- * A value of 0 means that /sys was not mounted.
- * A value of N (!=0) means N processor(s) (cpu0 .. cpu(N-1)).
+ * Number of FC hosts read, or -1 if the buffer was too small and needs to
+ * be reallocated.
***************************************************************************
*/
-int get_sys_cpu_nr(void)
+__nr_t read_fchost(struct stats_fchost *st_fc, __nr_t nr_alloc)
{
DIR *dir;
+ FILE *fp;
struct dirent *drd;
- struct stat buf;
- char line[MAX_PF_NAME];
- int proc_nr = 0;
-
- /* Open relevant /sys directory */
- if ((dir = opendir(SYSFS_DEVCPU)) == NULL)
- return 0;
+ struct stats_fchost *st_fc_i;
+ __nr_t fch_read = 0;
+ char fcstat_filename[MAX_PF_NAME];
+ char line[256];
+ unsigned long rx_frames, tx_frames, rx_words, tx_words;
- /* Get current file entry */
- while ((drd = readdir(dir)) != NULL) {
+ /* Each host, if present, will have its own hostX entry within SYSFS_FCHOST */
+ if ((dir = __opendir(SYSFS_FCHOST)) == NULL)
+ return 0; /* No FC hosts */
- if (!strncmp(drd->d_name, "cpu", 3) && isdigit(drd->d_name[3])) {
- snprintf(line, MAX_PF_NAME, "%s/%s", SYSFS_DEVCPU, drd->d_name);
- line[MAX_PF_NAME - 1] = '\0';
- if (stat(line, &buf) < 0)
- continue;
- if (S_ISDIR(buf.st_mode)) {
- proc_nr++;
- }
- }
- }
+ /*
+ * Read each of the counters via sysfs, where they are
+ * returned as hex values (e.g. 0x72400).
+ */
+ while ((drd = __readdir(dir)) != NULL) {
+ rx_frames = tx_frames = rx_words = tx_words = 0;
- /* Close directory */
- closedir(dir);
+ if (!strncmp(drd->d_name, "host", 4)) {
- return proc_nr;
-}
+ if (fch_read + 1 > nr_alloc) {
+ fch_read = -1;
+ break;
+ }
-/*
- ***************************************************************************
- * Count number of processors in /proc/stat.
- *
- * RETURNS:
- * Number of processors. The returned value is greater than or equal to the
- * number of online processors.
- * A value of 0 means one processor and non SMP kernel.
- * A value of N (!=0) means N processor(s) (0 .. N-1) with SMP kernel.
- ***************************************************************************
- */
-int get_proc_cpu_nr(void)
-{
- FILE *fp;
- char line[16];
- int num_proc, proc_nr = -1;
+ snprintf(fcstat_filename, MAX_PF_NAME, FC_RX_FRAMES,
+ SYSFS_FCHOST, drd->d_name);
+ if ((fp = fopen(fcstat_filename, "r"))) {
+ if (fgets(line, sizeof(line), fp)) {
+ sscanf(line, "%lx", &rx_frames);
+ }
+ fclose(fp);
+ }
- if ((fp = fopen(STAT, "r")) == NULL) {
- fprintf(stderr, _("Cannot open %s: %s\n"), STAT, strerror(errno));
- exit(1);
- }
+ snprintf(fcstat_filename, MAX_PF_NAME, FC_TX_FRAMES,
+ SYSFS_FCHOST, drd->d_name);
+ if ((fp = fopen(fcstat_filename, "r"))) {
+ if (fgets(line, sizeof(line), fp)) {
+ sscanf(line, "%lx", &tx_frames);
+ }
+ fclose(fp);
+ }
- while (fgets(line, 16, fp) != NULL) {
+ snprintf(fcstat_filename, MAX_PF_NAME, FC_RX_WORDS,
+ SYSFS_FCHOST, drd->d_name);
+ if ((fp = fopen(fcstat_filename, "r"))) {
+ if (fgets(line, sizeof(line), fp)) {
+ sscanf(line, "%lx", &rx_words);
+ }
+ fclose(fp);
+ }
- if (strncmp(line, "cpu ", 4) && !strncmp(line, "cpu", 3)) {
- sscanf(line + 3, "%d", &num_proc);
- if (num_proc > proc_nr) {
- proc_nr = num_proc;
+ snprintf(fcstat_filename, MAX_PF_NAME, FC_TX_WORDS,
+ SYSFS_FCHOST, drd->d_name);
+ if ((fp = fopen(fcstat_filename, "r"))) {
+ if (fgets(line, sizeof(line), fp)) {
+ sscanf(line, "%lx", &tx_words);
+ }
+ fclose(fp);
}
+
+ st_fc_i = st_fc + fch_read++;
+ st_fc_i->f_rxframes = rx_frames;
+ st_fc_i->f_txframes = tx_frames;
+ st_fc_i->f_rxwords = rx_words;
+ st_fc_i->f_txwords = tx_words;
+ memcpy(st_fc_i->fchost_name, drd->d_name, MAX_FCH_LEN);
+ st_fc_i->fchost_name[MAX_FCH_LEN - 1] = '\0';
}
}
- fclose(fp);
-
- return (proc_nr + 1);
+ __closedir(dir);
+ return fch_read;
}
/*
***************************************************************************
- * Count the number of processors on the machine.
- * Try to use /sys for that, or /proc/stat if /sys doesn't exist.
+ * Read softnet statistics.
*
* IN:
- * @max_nr_cpus Maximum number of proc that sysstat can handle.
- *
- * RETURNS:
- * Number of processors.
- * 0: one proc and non SMP kernel.
- * 1: one proc and SMP kernel (NB: On SMP machines where all the CPUs but
- * one have been disabled, we get the total number of proc since we use
- * /sys to count them).
- * 2: two proc...
- ***************************************************************************
- */
-int get_cpu_nr(unsigned int max_nr_cpus)
-{
- int cpu_nr;
-
- if ((cpu_nr = get_sys_cpu_nr()) == 0) {
- /* /sys may be not mounted. Use /proc/stat instead */
- cpu_nr = get_proc_cpu_nr();
- }
-
- if (cpu_nr > max_nr_cpus) {
- fprintf(stderr, _("Cannot handle so many processors!\n"));
- exit(1);
- }
-
- return cpu_nr;
-}
-
-/*
- ***************************************************************************
- * Find number of interrupts available per processor (use
- * /proc/interrupts file or /proc/softirqs).
+ * @st_softnet Structure where stats will be saved.
+ * @nr_alloc Total number of structures allocated. Value is >= 0.
+ * @online_cpu_bitmap
+ * Bitmap listing online CPU.
*
- * IN:
- * @file /proc file to read (interrupts or softirqs).
- * @max_nr_irqcpu Maximum number of interrupts per processor that
- * sadc can handle.
- * @cpu_nr Number of processors.
+ * OUT:
+ * @st_softnet Structure with statistics.
*
* RETURNS:
- * Number of interrupts per processor + a pre-allocation constant.
+ * 1 if stats have been sucessfully read, or 0 otherwise.
***************************************************************************
*/
-int get_irqcpu_nr(char *file, int max_nr_irqcpu, int cpu_nr)
+int read_softnet(struct stats_softnet *st_softnet, __nr_t nr_alloc,
+ unsigned char online_cpu_bitmap[])
{
FILE *fp;
- char *line = NULL;
- unsigned int irq = 0;
- int p;
-
- if ((fp = fopen(file, "r")) == NULL)
- return 0; /* No interrupts file */
-
- SREALLOC(line, char, INTERRUPTS_LINE + 11 * cpu_nr);
-
- while ((fgets(line, INTERRUPTS_LINE + 11 * cpu_nr , fp) != NULL) &&
- (irq < max_nr_irqcpu)) {
- p = strcspn(line, ":");
- if ((p > 0) && (p < 16)) {
- irq++;
- }
- }
-
- fclose(fp);
-
- if (line) {
- free(line);
- }
+ struct stats_softnet *st_softnet_i;
+ char line[1024];
+ int cpu;
- return irq;
-}
+ /* Open /proc/net/softnet_stat file */
+ if ((fp = fopen(NET_SOFTNET, "r")) == NULL)
+ return 0;
-/*
- ***************************************************************************
- * Count number of possible frequencies for CPU#0.
- *
- * RETURNS:
- * Number of frequencies.
- ***************************************************************************
- */
-int get_freq_nr(void)
-{
- FILE *fp;
- char filename[MAX_PF_NAME];
- char line[128];
- int freq = 0;
+ for (cpu = 1; cpu < nr_alloc; cpu++) {
+ if (!(online_cpu_bitmap[(cpu - 1) >> 3] & (1 << ((cpu - 1) & 0x07))))
+ /* CPU is offline */
+ continue;
- snprintf(filename, MAX_PF_NAME, "%s/cpu0/%s",
- SYSFS_DEVCPU, SYSFS_TIME_IN_STATE);
- if ((fp = fopen(filename, "r")) == NULL)
- return 0; /* No time_in_state file for CPU#0 */
+ if (fgets(line, sizeof(line), fp) == NULL)
+ break;
- while (fgets(line, 128, fp) != NULL) {
- freq++;
+ st_softnet_i = st_softnet + cpu;
+ sscanf(line, "%x %x %x %*x %*x %*x %*x %*x %*x %x %x",
+ &st_softnet_i->processed,
+ &st_softnet_i->dropped,
+ &st_softnet_i->time_squeeze,
+ &st_softnet_i->received_rps,
+ &st_softnet_i->flow_limit);
}
fclose(fp);
-
- return freq;
+ return 1;
}
-/*
- ***************************************************************************
- * Count number of USB devices in /sys/bus/usb/devices.
- *
- * RETURNS:
- * Number of USB devices plugged into the system.
- * Don't count USB root hubs.
- * Return -1 if directory doesn't exist in sysfs.
- ***************************************************************************
- */
-int get_usb_nr(void)
-{
- DIR *dir;
- struct dirent *drd;
- int usb = 0;
-
- /* Open relevant /sys directory */
- if ((dir = opendir(SYSFS_USBDEV)) == NULL)
- return -1;
-
- /* Get current file entry */
- while ((drd = readdir(dir)) != NULL) {
-
- if (isdigit(drd->d_name[0]) && !strchr(drd->d_name, ':')) {
- usb++;
- }
- }
-
- /* Close directory */
- closedir(dir);
-
- return usb;
-}
+/*------------------ END: FUNCTIONS USED BY SADC ONLY ---------------------*/
+#endif /* SOURCE_SADC */