"Fossies" - the Fresh Open Source Software Archive 
Member "atop-2.8.1/deviate.c" (7 Jan 2023, 57440 Bytes) of package /linux/misc/atop-2.8.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "deviate.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
2.7.1_vs_2.8.0.
1 /*
2 ** ATOP - System & Process Monitor
3 **
4 ** The program 'atop' offers the possibility to view the activity of
5 ** the system on system-level as well as process-level.
6 **
7 ** This source-file contains functions to calculate the differences for
8 ** the system-level and process-level counters since the previous sample.
9 ** ==========================================================================
10 ** Author: Gerlof Langeveld
11 ** E-mail: gerlof.langeveld@atoptool.nl
12 ** Date: November 1996
13 ** LINUX-port: June 2000
14 ** --------------------------------------------------------------------------
15 ** Copyright (C) 2000-2021 Gerlof Langeveld
16 **
17 ** This program is free software; you can redistribute it and/or modify it
18 ** under the terms of the GNU General Public License as published by the
19 ** Free Software Foundation; either version 2, or (at your option) any
20 ** later version.
21 **
22 ** This program is distributed in the hope that it will be useful, but
23 ** WITHOUT ANY WARRANTY; without even the implied warranty of
24 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25 ** See the GNU General Public License for more details.
26 **
27 ** You should have received a copy of the GNU General Public License
28 ** along with this program; if not, write to the Free Software
29 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 ** --------------------------------------------------------------------------
31 */
32
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/stat.h>
36 #include <signal.h>
37 #include <time.h>
38 #include <stdio.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <unistd.h>
42 #include <stdlib.h>
43 #include <limits.h>
44 #include <memory.h>
45 #include <string.h>
46
47 #include "atop.h"
48 #include "ifprop.h"
49 #include "photoproc.h"
50 #include "photosyst.h"
51
52 static void calcdiff(struct tstat *, const struct tstat *,
53 const struct tstat *,
54 char, count_t);
55 static inline count_t subcount(count_t, count_t);
56
57 /*
58 ** calculate the process-activity during the last sample
59 */
60 void
61 deviattask(struct tstat *curtpres, unsigned long ntaskpres,
62 struct tstat *curpexit, unsigned long nprocexit,
63 struct devtstat *devtstat,
64 struct sstat *devsstat)
65 {
66 register int c, d, pall=0, pact=0;
67 register struct tstat *curstat, *devstat, *thisproc;
68 struct tstat prestat, *pprestat;
69 struct pinfo *pinfo;
70 count_t totusedcpu;
71 char hashtype = 'p';
72
73 /*
74 ** needed for sanity check later on...
75 */
76 totusedcpu = devsstat->cpu.all.stime + devsstat->cpu.all.utime +
77 devsstat->cpu.all.ntime + devsstat->cpu.all.itime +
78 devsstat->cpu.all.wtime + devsstat->cpu.all.Itime +
79 devsstat->cpu.all.Stime + devsstat->cpu.all.steal;
80
81 /*
82 ** make new list of all tasks in the task-database;
83 ** after handling all task, the left-overs are tasks
84 ** that have disappeared since the previous sample
85 */
86 pdb_makeresidue();
87
88 /*
89 ** remove allocated lists of previous sample and initialize counters
90 */
91 if (devtstat->taskall)
92 free(devtstat->taskall);
93
94 if (devtstat->procall)
95 free(devtstat->procall);
96
97 if (devtstat->procactive)
98 free(devtstat->procactive);
99
100 memset(devtstat, 0, sizeof *devtstat);
101
102 /*
103 ** create list for the sample deviations of all tasks
104 */
105 devtstat->ntaskall = ntaskpres + nprocexit;
106 devtstat->taskall = malloc(devtstat->ntaskall * sizeof(struct tstat));
107
108 ptrverify(devtstat->taskall, "Malloc failed for %lu deviated tasks\n",
109 devtstat->ntaskall);
110
111 /*
112 ** calculate deviations per present task
113 */
114 for (c=0, thisproc = devtstat->taskall; c < ntaskpres; c++)
115 {
116 char newtask = 0;
117
118 curstat = curtpres+c;
119 devstat = devtstat->taskall+c;
120
121 if (curstat->gen.isproc)
122 {
123 thisproc = devstat; // remember last process seen
124
125 devtstat->nprocall++;
126
127 if (curstat->gen.state == 'Z')
128 {
129 devtstat->totzombie++;
130 }
131 else
132 {
133 devtstat->totrun += curstat->gen.nthrrun;
134 devtstat->totslpi += curstat->gen.nthrslpi;
135 devtstat->totslpu += curstat->gen.nthrslpu;
136 }
137 }
138
139 /*
140 ** get previous figures from task-database
141 */
142 if ( pdb_gettask(curstat->gen.pid, curstat->gen.isproc,
143 curstat->gen.btime, &pinfo))
144 {
145 /*
146 ** task already present in the previous sample
147 **
148 ** save stats from previous sample (to use for
149 ** further calculations) and store new statistics
150 ** in task-database
151 */
152 if (memcmp(curstat, &pinfo->tstat,
153 sizeof(struct tstat)) == EQ)
154 {
155 /*
156 ** no activity for task
157 */
158 curstat->gen.wasinactive = 1;
159 pprestat = curstat;
160 }
161 else
162 {
163 /*
164 ** save the values of the previous sample
165 ** and overwrite the previous sample in
166 ** the database with the current sample
167 */
168 prestat = pinfo->tstat;
169 pprestat = &prestat;
170 pinfo->tstat = *curstat;
171
172 curstat->gen.wasinactive = 0;
173
174 devtstat->ntaskactive++;
175
176 if (curstat->gen.isproc)
177 {
178 devtstat->nprocactive++;
179 }
180 else
181 {
182 if (thisproc->gen.wasinactive)
183 {
184 thisproc->gen.wasinactive = 0;
185 devtstat->ntaskactive++;
186 devtstat->nprocactive++;
187 }
188 }
189 }
190 }
191 else
192 {
193 /*
194 ** new task which must have been started during
195 ** last interval
196 */
197 memset(&prestat, 0, sizeof(prestat));
198 pprestat = &prestat;
199
200 curstat->gen.wasinactive = 0;
201 devtstat->ntaskactive++;
202
203 if (curstat->gen.isproc)
204 {
205 devtstat->nprocactive++;
206 }
207 else
208 {
209 if (thisproc->gen.wasinactive)
210 {
211 thisproc->gen.wasinactive = 0;
212 devtstat->ntaskactive++;
213 devtstat->nprocactive++;
214 }
215 }
216
217 /*
218 ** create new task struct
219 */
220 pinfo = calloc(1, sizeof(struct pinfo));
221
222 ptrverify(pinfo, "Malloc failed for new pinfo\n");
223
224 pinfo->tstat = *curstat;
225
226 /*
227 ** add new task to task-database
228 */
229 pdb_addtask(curstat->gen.pid, pinfo);
230
231 newtask = 1;
232 }
233
234 /*
235 ** do the difference calculations
236 */
237 calcdiff(devstat, curstat, pprestat, newtask, totusedcpu);
238 }
239
240 /*
241 ** calculate deviations per exited process
242 */
243 if (nprocexit > 0 && supportflags&NETATOPD)
244 {
245 if (curpexit->gen.pid)
246 hashtype = 'p';
247 else
248 hashtype = 'b';
249
250 netatop_exithash(hashtype);
251 }
252
253 for (d=c, c=0; c < nprocexit; c++)
254 {
255 /*
256 ** check if this process has been started AND
257 ** finished since previous sample;
258 ** if so, it has no use to check if there is still
259 ** existing info present in the process-database
260 */
261 curstat = curpexit+c;
262 curstat->gen.wasinactive = 0;
263
264 devtstat->nprocall++;
265 devtstat->nprocactive++;
266 devtstat->ntaskactive++;
267
268 if (curstat->gen.pid) /* acctrecord contains pid? */
269 {
270 if ( pdb_gettask(curstat->gen.pid, 1,
271 curstat->gen.btime, &pinfo))
272 prestat = pinfo->tstat;
273 else
274 memset(&prestat, 0, sizeof(prestat));
275 }
276 else
277 {
278 if ( curstat->gen.btime > pretime )
279 {
280 /*
281 ** process-start and -finish in same interval
282 */
283 memset(&prestat, 0, sizeof(prestat));
284 }
285 else
286 {
287 /*
288 ** process must be known in process-database;
289 ** try to match one of the remaining processes
290 ** against this exited one
291 */
292 if ( pdb_srchresidue(curstat, &pinfo) )
293 prestat = pinfo->tstat;
294 else
295 memset(&prestat, 0, sizeof(prestat));
296 }
297 }
298
299 /*
300 ** now do the calculations
301 */
302 devstat = devtstat->taskall+d;
303 memset(devstat, 0, sizeof *devstat);
304
305 devstat->gen = curstat->gen;
306
307 if ( curstat->gen.pid == 0 )
308 devstat->gen.pid = prestat.gen.pid;
309
310 if (!prestat.gen.pid)
311 devstat->gen.excode |= ~(INT_MAX);
312
313 strcpy(devstat->gen.cmdline, prestat.gen.cmdline);
314
315 devstat->cpu.curcpu = -1;
316
317 /*
318 ** due to the strange exponent-type storage of values
319 ** in the process accounting record, the resource-value
320 ** in the exit-record might have been smaller than the
321 ** stored value of the last registered sample; in that
322 ** case the deviation should be set to zero
323 */
324 if (curstat->cpu.stime > prestat.cpu.stime)
325 devstat->cpu.stime = curstat->cpu.stime -
326 prestat.cpu.stime;
327
328 if (curstat->cpu.utime > prestat.cpu.utime)
329 devstat->cpu.utime = curstat->cpu.utime -
330 prestat.cpu.utime;
331
332 if (curstat->mem.minflt > prestat.mem.minflt)
333 devstat->mem.minflt = curstat->mem.minflt -
334 prestat.mem.minflt;
335
336 if (curstat->mem.majflt > prestat.mem.majflt)
337 devstat->mem.majflt = curstat->mem.majflt -
338 prestat.mem.majflt;
339
340 if (curstat->dsk.rio > (prestat.dsk.rio + prestat.dsk.wio))
341 devstat->dsk.rio = curstat->dsk.rio -
342 prestat.dsk.rio -
343 prestat.dsk.wio;
344
345 /*
346 ** try to match the network counters of netatop
347 */
348 if (supportflags & NETATOPD)
349 {
350 unsigned long val = (hashtype == 'p' ?
351 curstat->gen.pid :
352 curstat->gen.btime);
353
354 netatop_exitfind(val, devstat, &prestat);
355 }
356
357 /*
358 ** handle the gpu counters
359 */
360 if (curstat->gpu.state || prestat.gpu.state) // GPU use?
361 {
362 if (curstat->gpu.state)
363 devstat->gpu.state = curstat->gpu.state;
364 else
365 devstat->gpu.state = prestat.gpu.state;
366
367 devstat->gpu.nrgpus = curstat->gpu.nrgpus;
368 devstat->gpu.gpulist = curstat->gpu.gpulist;
369 devstat->gpu.gpubusy = curstat->gpu.gpubusy;
370 devstat->gpu.membusy = curstat->gpu.membusy;
371 devstat->gpu.timems = curstat->gpu.timems;
372
373 devstat->gpu.memnow = curstat->gpu.memnow;
374 devstat->gpu.memcum = curstat->gpu.memcum -
375 prestat.gpu.memcum;
376 devstat->gpu.sample = curstat->gpu.sample -
377 prestat.gpu.sample;
378 }
379 else
380 {
381 devstat->gpu.state = '\0';
382 }
383
384 if (prestat.gen.pid > 0)
385 pdb_deltask(prestat.gen.pid, prestat.gen.isproc);
386
387 d++;
388 }
389
390 /*
391 ** remove unused entries from RESIDUE chain
392 */
393 pdb_cleanresidue();
394
395 /*
396 ** create and fill other pointer lists
397 */
398 devtstat->procall = malloc(devtstat->nprocall *
399 sizeof(struct tstat *));
400 devtstat->procactive = malloc(devtstat->nprocactive *
401 sizeof(struct tstat *));
402
403 ptrverify(devtstat->procall, "Malloc failed for %d processes\n",
404 devtstat->nprocall);
405
406 ptrverify(devtstat->procactive, "Malloc failed for %d active procs\n",
407 devtstat->nprocactive);
408
409
410 for (c=0, thisproc=devstat=devtstat->taskall; c < devtstat->ntaskall;
411 c++, devstat++)
412 {
413 if (devstat->gen.isproc)
414 {
415 devtstat->procall[pall++] = devstat;
416
417 if (! devstat->gen.wasinactive)
418 devtstat->procactive[pact++] = devstat;
419 }
420 }
421 }
422
423 /*
424 ** calculate the differences between the current sample and
425 ** the previous sample for a task
426 */
427 static void
428 calcdiff(struct tstat *devstat, const struct tstat *curstat,
429 const struct tstat *prestat,
430 char newtask, count_t totusedcpu)
431 {
432 /*
433 ** for inactive tasks, set all counters to zero to avoid calculating
434 ** the deviations (after all, there are no deviations)
435 */
436 if (curstat->gen.wasinactive)
437 {
438 memset(devstat, 0, sizeof *devstat);
439 }
440
441 /*
442 ** copy all STATIC values from the current task settings
443 */
444 devstat->gen = curstat->gen;
445
446 if (newtask)
447 devstat->gen.excode |= ~(INT_MAX);
448
449 devstat->cpu.nice = curstat->cpu.nice;
450 devstat->cpu.prio = curstat->cpu.prio;
451 devstat->cpu.rtprio = curstat->cpu.rtprio;
452 devstat->cpu.policy = curstat->cpu.policy;
453 devstat->cpu.curcpu = curstat->cpu.curcpu;
454 devstat->cpu.sleepavg = curstat->cpu.sleepavg;
455 devstat->cpu.cgcpuweight = curstat->cpu.cgcpuweight;
456 devstat->cpu.cgcpumax = curstat->cpu.cgcpumax;
457 devstat->cpu.cgcpumaxr = curstat->cpu.cgcpumaxr;
458
459 if (curstat->cpu.wchan[0])
460 strcpy(devstat->cpu.wchan, curstat->cpu.wchan);
461 else
462 devstat->cpu.wchan[0] = 0;
463
464 devstat->mem.vexec = curstat->mem.vexec;
465 devstat->mem.vmem = curstat->mem.vmem;
466 devstat->mem.rmem = curstat->mem.rmem;
467 devstat->mem.pmem = curstat->mem.pmem;
468 devstat->mem.vdata = curstat->mem.vdata;
469 devstat->mem.vstack = curstat->mem.vstack;
470 devstat->mem.vlibs = curstat->mem.vlibs;
471 devstat->mem.vswap = curstat->mem.vswap;
472 devstat->mem.vlock = curstat->mem.vlock;
473
474 devstat->mem.cgmemmax = curstat->mem.cgmemmax;
475 devstat->mem.cgmemmaxr = curstat->mem.cgmemmaxr;
476 devstat->mem.cgswpmax = curstat->mem.cgswpmax;
477 devstat->mem.cgswpmaxr = curstat->mem.cgswpmaxr;
478
479 if (curstat->gpu.state || prestat->gpu.state) // GPU use?
480 {
481 if (curstat->gpu.state)
482 devstat->gpu.state = curstat->gpu.state;
483 else
484 devstat->gpu.state = prestat->gpu.state;
485
486 devstat->gpu.nrgpus = curstat->gpu.nrgpus;
487 devstat->gpu.gpulist = curstat->gpu.gpulist;
488 devstat->gpu.gpubusy = curstat->gpu.gpubusy;
489 devstat->gpu.membusy = curstat->gpu.membusy;
490 devstat->gpu.memnow = curstat->gpu.memnow;
491 devstat->gpu.timems = curstat->gpu.timems;
492 }
493 else
494 {
495 devstat->gpu.state = '\0';
496 }
497
498 /*
499 ** for inactive tasks, only the static values had to be copied, while
500 ** all use counters have already been set to zero
501 */
502 if (curstat->gen.wasinactive)
503 return;
504
505 /*
506 ** calculate deviations for tasks that were really active
507 ** (i.e. modified) during the sample
508 */
509 devstat->cpu.stime =
510 subcount(curstat->cpu.stime, prestat->cpu.stime);
511 devstat->cpu.utime =
512 subcount(curstat->cpu.utime, prestat->cpu.utime);
513
514 /*
515 ** particular kernel versions sometimes supply a smaller
516 ** amount for consumed CPU-ticks than a previous sample;
517 ** with unsigned calculations this results in 497 days of
518 ** CPU-consumption so a sanity-check is needed here...
519 */
520 if (devstat->cpu.stime > totusedcpu)
521 devstat->cpu.stime = 1;
522
523 if (devstat->cpu.utime > totusedcpu)
524 devstat->cpu.utime = 1;
525
526 devstat->cpu.rundelay =
527 subcount(curstat->cpu.rundelay, prestat->cpu.rundelay);
528
529 devstat->cpu.blkdelay =
530 subcount(curstat->cpu.blkdelay, prestat->cpu.blkdelay);
531
532 devstat->dsk.rio =
533 subcount(curstat->dsk.rio, prestat->dsk.rio);
534 devstat->dsk.rsz =
535 subcount(curstat->dsk.rsz, prestat->dsk.rsz);
536 devstat->dsk.wio =
537 subcount(curstat->dsk.wio, prestat->dsk.wio);
538 devstat->dsk.wsz =
539 subcount(curstat->dsk.wsz, prestat->dsk.wsz);
540 devstat->dsk.cwsz =
541 subcount(curstat->dsk.cwsz, prestat->dsk.cwsz);
542
543 devstat->mem.vgrow = curstat->mem.vmem - prestat->mem.vmem;
544 devstat->mem.rgrow = curstat->mem.rmem - prestat->mem.rmem;
545
546 devstat->mem.minflt =
547 subcount(curstat->mem.minflt, prestat->mem.minflt);
548 devstat->mem.majflt =
549 subcount(curstat->mem.majflt, prestat->mem.majflt);
550
551 /*
552 ** network counters: due to an unload/load of the netatop module,
553 ** previous counters might be larger than the current
554 */
555 if (curstat->net.tcpsnd >= prestat->net.tcpsnd)
556 devstat->net.tcpsnd =
557 subcount(curstat->net.tcpsnd, prestat->net.tcpsnd);
558 else
559 devstat->net.tcpsnd = curstat->net.tcpsnd;
560
561 if (curstat->net.tcpssz >= prestat->net.tcpssz)
562 devstat->net.tcpssz =
563 subcount(curstat->net.tcpssz, prestat->net.tcpssz);
564 else
565 devstat->net.tcpssz = curstat->net.tcpssz;
566
567 if (curstat->net.tcprcv >= prestat->net.tcprcv)
568 devstat->net.tcprcv =
569 subcount(curstat->net.tcprcv, prestat->net.tcprcv);
570 else
571 devstat->net.tcprcv = curstat->net.tcprcv;
572
573 if (curstat->net.tcprsz >= prestat->net.tcprsz)
574 devstat->net.tcprsz =
575 subcount(curstat->net.tcprsz, prestat->net.tcprsz);
576 else
577 devstat->net.tcprsz = curstat->net.tcprsz;
578
579 if (curstat->net.udpsnd >= prestat->net.udpsnd)
580 devstat->net.udpsnd =
581 subcount(curstat->net.udpsnd, prestat->net.udpsnd);
582 else
583 devstat->net.udpsnd = curstat->net.udpsnd;
584
585 if (curstat->net.udpssz >= prestat->net.udpssz)
586 devstat->net.udpssz =
587 subcount(curstat->net.udpssz, prestat->net.udpssz);
588 else
589 devstat->net.udpssz = curstat->net.udpssz;
590
591 if (curstat->net.udprcv >= prestat->net.udprcv)
592 devstat->net.udprcv =
593 subcount(curstat->net.udprcv, prestat->net.udprcv);
594 else
595 devstat->net.udprcv = curstat->net.udprcv;
596
597 if (curstat->net.udprsz >= prestat->net.udprsz)
598 devstat->net.udprsz =
599 subcount(curstat->net.udprsz, prestat->net.udprsz);
600 else
601 devstat->net.udprsz = curstat->net.udprsz;
602
603
604 if (curstat->gpu.state)
605 {
606 devstat->gpu.memcum = curstat->gpu.memcum - prestat->gpu.memcum;
607 devstat->gpu.sample = curstat->gpu.sample - prestat->gpu.sample;
608 }
609 }
610
611 /*
612 ** calculate the system-activity during the last sample
613 */
614 void
615 deviatsyst(struct sstat *cur, struct sstat *pre, struct sstat *dev,
616 long interval)
617 {
618 register int i, j;
619 count_t *cdev, *ccur, *cpre;
620 struct ifprop ifprop;
621
622 dev->cpu.nrcpu = cur->cpu.nrcpu;
623 dev->cpu.devint = subcount(cur->cpu.devint, pre->cpu.devint);
624 dev->cpu.csw = subcount(cur->cpu.csw, pre->cpu.csw);
625 dev->cpu.nprocs = subcount(cur->cpu.nprocs, pre->cpu.nprocs);
626
627 dev->cpu.all.stime = subcount(cur->cpu.all.stime, pre->cpu.all.stime);
628 dev->cpu.all.utime = subcount(cur->cpu.all.utime, pre->cpu.all.utime);
629 dev->cpu.all.ntime = subcount(cur->cpu.all.ntime, pre->cpu.all.ntime);
630 dev->cpu.all.itime = subcount(cur->cpu.all.itime, pre->cpu.all.itime);
631 dev->cpu.all.wtime = subcount(cur->cpu.all.wtime, pre->cpu.all.wtime);
632 dev->cpu.all.Itime = subcount(cur->cpu.all.Itime, pre->cpu.all.Itime);
633 dev->cpu.all.Stime = subcount(cur->cpu.all.Stime, pre->cpu.all.Stime);
634
635 dev->cpu.all.steal = subcount(cur->cpu.all.steal, pre->cpu.all.steal);
636 dev->cpu.all.guest = subcount(cur->cpu.all.guest, pre->cpu.all.guest);
637
638 dev->cpu.all.instr = subcount(cur->cpu.all.instr, pre->cpu.all.instr);
639 dev->cpu.all.cycle = subcount(cur->cpu.all.cycle, pre->cpu.all.cycle);
640
641 for (i=0; i < dev->cpu.nrcpu; i++)
642 {
643 count_t ticks;
644
645 dev->cpu.cpu[i].cpunr = cur->cpu.cpu[i].cpunr;
646 dev->cpu.cpu[i].stime = subcount(cur->cpu.cpu[i].stime,
647 pre->cpu.cpu[i].stime);
648 dev->cpu.cpu[i].utime = subcount(cur->cpu.cpu[i].utime,
649 pre->cpu.cpu[i].utime);
650 dev->cpu.cpu[i].ntime = subcount(cur->cpu.cpu[i].ntime,
651 pre->cpu.cpu[i].ntime);
652 dev->cpu.cpu[i].itime = subcount(cur->cpu.cpu[i].itime,
653 pre->cpu.cpu[i].itime);
654 dev->cpu.cpu[i].wtime = subcount(cur->cpu.cpu[i].wtime,
655 pre->cpu.cpu[i].wtime);
656 dev->cpu.cpu[i].Itime = subcount(cur->cpu.cpu[i].Itime,
657 pre->cpu.cpu[i].Itime);
658 dev->cpu.cpu[i].Stime = subcount(cur->cpu.cpu[i].Stime,
659 pre->cpu.cpu[i].Stime);
660
661 dev->cpu.cpu[i].steal = subcount(cur->cpu.cpu[i].steal,
662 pre->cpu.cpu[i].steal);
663 dev->cpu.cpu[i].guest = subcount(cur->cpu.cpu[i].guest,
664 pre->cpu.cpu[i].guest);
665
666 dev->cpu.cpu[i].instr = subcount(cur->cpu.cpu[i].instr,
667 pre->cpu.cpu[i].instr);
668 dev->cpu.cpu[i].cycle = subcount(cur->cpu.cpu[i].cycle,
669 pre->cpu.cpu[i].cycle);
670
671 ticks = cur->cpu.cpu[i].freqcnt.ticks;
672
673 dev->cpu.cpu[i].freqcnt.maxfreq =
674 cur->cpu.cpu[i].freqcnt.maxfreq;
675 dev->cpu.cpu[i].freqcnt.cnt = ticks ?
676 subcount(cur->cpu.cpu[i].freqcnt.cnt,
677 pre->cpu.cpu[i].freqcnt.cnt)
678 : cur->cpu.cpu[i].freqcnt.cnt;
679
680 dev->cpu.cpu[i].freqcnt.ticks = ticks ?
681 subcount(cur->cpu.cpu[i].freqcnt.ticks,
682 pre->cpu.cpu[i].freqcnt.ticks)
683 : cur->cpu.cpu[i].freqcnt.ticks;
684 }
685
686 dev->cpu.lavg1 = cur->cpu.lavg1;
687 dev->cpu.lavg5 = cur->cpu.lavg5;
688 dev->cpu.lavg15 = cur->cpu.lavg15;
689
690 dev->mem.physmem = cur->mem.physmem;
691 dev->mem.freemem = cur->mem.freemem;
692 dev->mem.buffermem = cur->mem.buffermem;
693 dev->mem.slabmem = cur->mem.slabmem;
694 dev->mem.slabreclaim = cur->mem.slabreclaim;
695 dev->mem.committed = cur->mem.committed;
696 dev->mem.commitlim = cur->mem.commitlim;
697 dev->mem.cachemem = cur->mem.cachemem;
698 dev->mem.cachedrt = cur->mem.cachedrt;
699 dev->mem.totswap = cur->mem.totswap;
700 dev->mem.freeswap = cur->mem.freeswap;
701 dev->mem.swapcached = cur->mem.swapcached;
702 dev->mem.pagetables = cur->mem.pagetables;
703
704 dev->mem.shmem = cur->mem.shmem;
705 dev->mem.shmrss = cur->mem.shmrss;
706 dev->mem.shmswp = cur->mem.shmswp;
707
708 dev->mem.tothugepage = cur->mem.tothugepage;
709 dev->mem.freehugepage = cur->mem.freehugepage;
710 dev->mem.hugepagesz = cur->mem.hugepagesz;
711
712 dev->mem.vmwballoon = cur->mem.vmwballoon;
713 dev->mem.zfsarcsize = cur->mem.zfsarcsize;
714 dev->mem.ksmsharing = cur->mem.ksmsharing;
715 dev->mem.ksmshared = cur->mem.ksmshared;
716 dev->mem.zswstored = cur->mem.zswstored;
717 dev->mem.zswtotpool = cur->mem.zswtotpool;
718
719 dev->mem.tcpsock = cur->mem.tcpsock;
720 dev->mem.udpsock = cur->mem.udpsock;
721
722 dev->mem.pgouts = subcount(cur->mem.pgouts, pre->mem.pgouts);
723 dev->mem.pgins = subcount(cur->mem.pgins, pre->mem.pgins);
724 dev->mem.swouts = subcount(cur->mem.swouts, pre->mem.swouts);
725 dev->mem.swins = subcount(cur->mem.swins, pre->mem.swins);
726 dev->mem.pgscans = subcount(cur->mem.pgscans, pre->mem.pgscans);
727 dev->mem.pgsteal = subcount(cur->mem.pgsteal, pre->mem.pgsteal);
728 dev->mem.allocstall = subcount(cur->mem.allocstall,
729 pre->mem.allocstall);
730
731 if (cur->mem.oomkills != -1)
732 dev->mem.oomkills = subcount(cur->mem.oomkills, pre->mem.oomkills);
733 else
734 dev->mem.oomkills = -1;
735
736 dev->mem.compactstall = subcount(cur->mem.compactstall,
737 pre->mem.compactstall);
738 dev->mem.numamigrate = subcount(cur->mem.numamigrate, pre->mem.numamigrate);
739 dev->mem.pgmigrate = subcount(cur->mem.pgmigrate, pre->mem.pgmigrate);
740
741 dev->memnuma.nrnuma = cur->memnuma.nrnuma;
742
743 for (i=0; i < dev->memnuma.nrnuma; i++)
744 {
745 dev->memnuma.numa[i].numanr = cur->memnuma.numa[i].numanr;
746 dev->memnuma.numa[i].totmem = cur->memnuma.numa[i].totmem;
747 dev->memnuma.numa[i].freemem = cur->memnuma.numa[i].freemem;
748 dev->memnuma.numa[i].filepage = cur->memnuma.numa[i].filepage;
749 dev->memnuma.numa[i].active = cur->memnuma.numa[i].active;
750 dev->memnuma.numa[i].inactive = cur->memnuma.numa[i].inactive;
751 dev->memnuma.numa[i].dirtymem = cur->memnuma.numa[i].dirtymem;
752 dev->memnuma.numa[i].shmem = cur->memnuma.numa[i].shmem;
753 dev->memnuma.numa[i].slabmem = cur->memnuma.numa[i].slabmem;
754 dev->memnuma.numa[i].slabreclaim = cur->memnuma.numa[i].slabreclaim;
755 dev->memnuma.numa[i].tothp = cur->memnuma.numa[i].tothp;
756 dev->memnuma.numa[i].frag = cur->memnuma.numa[i].frag;
757 }
758
759 dev->cpunuma.nrnuma = cur->cpunuma.nrnuma;
760
761 if (dev->cpunuma.nrnuma > 1)
762 {
763 for (i=0; i < dev->cpunuma.nrnuma; i++)
764 {
765 dev->cpunuma.numa[i].nrcpu = cur->cpunuma.numa[i].nrcpu;
766 dev->cpunuma.numa[i].numanr = cur->cpunuma.numa[i].numanr;
767
768 dev->cpunuma.numa[i].utime = subcount(cur->cpunuma.numa[i].utime,
769 pre->cpunuma.numa[i].utime);
770 dev->cpunuma.numa[i].ntime = subcount(cur->cpunuma.numa[i].ntime,
771 pre->cpunuma.numa[i].ntime);
772 dev->cpunuma.numa[i].stime = subcount(cur->cpunuma.numa[i].stime,
773 pre->cpunuma.numa[i].stime);
774 dev->cpunuma.numa[i].itime = subcount(cur->cpunuma.numa[i].itime,
775 pre->cpunuma.numa[i].itime);
776 dev->cpunuma.numa[i].wtime = subcount(cur->cpunuma.numa[i].wtime,
777 pre->cpunuma.numa[i].wtime);
778 dev->cpunuma.numa[i].Itime = subcount(cur->cpunuma.numa[i].Itime,
779 pre->cpunuma.numa[i].Itime);
780 dev->cpunuma.numa[i].Stime = subcount(cur->cpunuma.numa[i].Stime,
781 pre->cpunuma.numa[i].Stime);
782 dev->cpunuma.numa[i].steal = subcount(cur->cpunuma.numa[i].steal,
783 pre->cpunuma.numa[i].steal);
784 dev->cpunuma.numa[i].guest = subcount(cur->cpunuma.numa[i].guest,
785 pre->cpunuma.numa[i].guest);
786 }
787 }
788
789 dev->psi = cur->psi;
790
791 if (cur->psi.present)
792 {
793 dev->psi.cpusome.total = cur->psi.cpusome.total -
794 pre->psi.cpusome.total;
795 dev->psi.memsome.total = cur->psi.memsome.total -
796 pre->psi.memsome.total;
797 dev->psi.memfull.total = cur->psi.memfull.total -
798 pre->psi.memfull.total;
799 dev->psi.iosome.total = cur->psi.iosome.total -
800 pre->psi.iosome.total;
801 dev->psi.iofull.total = cur->psi.iofull.total -
802 pre->psi.iofull.total;
803 }
804
805 /*
806 ** structures with network-related counters are considered
807 ** as tables of frequency-counters that have to be subtracted;
808 ** values that do not represent a frequency are corrected afterwards
809 */
810 for (cdev = (count_t *)&dev->net.ipv4,
811 ccur = (count_t *)&cur->net.ipv4,
812 cpre = (count_t *)&pre->net.ipv4,
813 i = 0;
814 i < (sizeof dev->net.ipv4 / sizeof(count_t));
815 cdev++, ccur++, cpre++, i++)
816 *cdev = *ccur - *cpre;
817
818 dev->net.ipv4.Forwarding = cur->net.ipv4.Forwarding;
819 dev->net.ipv4.DefaultTTL = cur->net.ipv4.DefaultTTL;
820
821 /* ------------- */
822
823 for (cdev = (count_t *)&dev->net.icmpv4,
824 ccur = (count_t *)&cur->net.icmpv4,
825 cpre = (count_t *)&pre->net.icmpv4,
826 i = 0;
827 i < (sizeof dev->net.icmpv4 / sizeof(count_t));
828 cdev++, ccur++, cpre++, i++)
829 *cdev = *ccur - *cpre;
830
831 /* ------------- */
832
833 for (cdev = (count_t *)&dev->net.udpv4,
834 ccur = (count_t *)&cur->net.udpv4,
835 cpre = (count_t *)&pre->net.udpv4,
836 i = 0;
837 i < (sizeof dev->net.udpv4 / sizeof(count_t));
838 cdev++, ccur++, cpre++, i++)
839 *cdev = *ccur - *cpre;
840
841 /* ------------- */
842
843 for (cdev = (count_t *)&dev->net.ipv6,
844 ccur = (count_t *)&cur->net.ipv6,
845 cpre = (count_t *)&pre->net.ipv6,
846 i = 0;
847 i < (sizeof dev->net.ipv6 / sizeof(count_t));
848 cdev++, ccur++, cpre++, i++)
849 *cdev = *ccur - *cpre;
850
851 /* ------------- */
852
853 for (cdev = (count_t *)&dev->net.icmpv6,
854 ccur = (count_t *)&cur->net.icmpv6,
855 cpre = (count_t *)&pre->net.icmpv6,
856 i = 0;
857 i < (sizeof dev->net.icmpv6 / sizeof(count_t));
858 cdev++, ccur++, cpre++, i++)
859 *cdev = *ccur - *cpre;
860
861 /* ------------- */
862
863 for (cdev = (count_t *)&dev->net.udpv6,
864 ccur = (count_t *)&cur->net.udpv6,
865 cpre = (count_t *)&pre->net.udpv6,
866 i = 0;
867 i < (sizeof dev->net.udpv6 / sizeof(count_t));
868 cdev++, ccur++, cpre++, i++)
869 *cdev = *ccur - *cpre;
870
871 /* ------------- */
872
873 for (cdev = (count_t *)&dev->net.tcp,
874 ccur = (count_t *)&cur->net.tcp,
875 cpre = (count_t *)&pre->net.tcp,
876 i = 0;
877 i < (sizeof dev->net.tcp / sizeof(count_t));
878 cdev++, ccur++, cpre++, i++)
879 *cdev = *ccur - *cpre;
880
881 dev->net.tcp.RtoAlgorithm = cur->net.tcp.RtoAlgorithm;
882 dev->net.tcp.RtoMin = cur->net.tcp.RtoMin;
883 dev->net.tcp.RtoMax = cur->net.tcp.RtoMax;
884 dev->net.tcp.MaxConn = cur->net.tcp.MaxConn;
885 dev->net.tcp.CurrEstab = cur->net.tcp.CurrEstab;
886
887 /*
888 ** calculate deviations for interfaces
889 */
890 for (i=0; cur->intf.intf[i].name[0]; i++)
891 {
892 // fill current properties for each valid interface
893 strcpy(ifprop.name, cur->intf.intf[i].name);
894
895 getifprop(&ifprop);
896
897 cur->intf.intf[i].type = ifprop.type;
898 cur->intf.intf[i].speed = ifprop.speed;
899 cur->intf.intf[i].speedp = ifprop.speed;
900 cur->intf.intf[i].duplex = ifprop.fullduplex;
901 }
902
903 if (pre->intf.intf[0].name[0] == '\0') /* first sample? */
904 {
905 for (i=0; cur->intf.intf[i].name[0]; i++)
906 {
907 strcpy(pre->intf.intf[i].name, cur->intf.intf[i].name);
908
909 pre->intf.intf[i].type = cur->intf.intf[i].type;
910 pre->intf.intf[i].speed = cur->intf.intf[i].speed;
911 pre->intf.intf[i].speedp = cur->intf.intf[i].speedp;
912 pre->intf.intf[i].duplex = cur->intf.intf[i].duplex;
913 }
914 }
915
916 for (i=0, j=0; cur->intf.intf[i].name[0]; i++, j++)
917 {
918 /*
919 ** be sure that we have the same interface
920 ** (interfaces could have been added or removed since
921 ** previous sample)
922 */
923 if (strcmp(cur->intf.intf[i].name, pre->intf.intf[j].name) != 0)
924 {
925 // try to resync
926 for (j=0; pre->intf.intf[j].name[0]; j++)
927 {
928 if (strcmp(cur->intf.intf[i].name,
929 pre->intf.intf[j].name) == 0)
930 break;
931 }
932
933 // resync not succeeded?
934 if (! pre->intf.intf[j].name[0])
935 {
936 memcpy(&dev->intf.intf[i],
937 &cur->intf.intf[i],
938 sizeof cur->intf.intf[i]);
939
940 j = 0;
941 continue;
942 }
943 }
944
945 /*
946 ** calculate interface deviations for this sample
947 */
948 strcpy(dev->intf.intf[i].name, cur->intf.intf[i].name);
949
950 dev->intf.intf[i].rbyte = subcount(cur->intf.intf[i].rbyte,
951 pre->intf.intf[j].rbyte);
952 dev->intf.intf[i].rpack = subcount(cur->intf.intf[i].rpack,
953 pre->intf.intf[j].rpack);
954 dev->intf.intf[i].rerrs = subcount(cur->intf.intf[i].rerrs,
955 pre->intf.intf[j].rerrs);
956 dev->intf.intf[i].rdrop = subcount(cur->intf.intf[i].rdrop,
957 pre->intf.intf[j].rdrop);
958 dev->intf.intf[i].rfifo = subcount(cur->intf.intf[i].rfifo,
959 pre->intf.intf[j].rfifo);
960 dev->intf.intf[i].rframe= subcount(cur->intf.intf[i].rframe,
961 pre->intf.intf[j].rframe);
962 dev->intf.intf[i].rcompr= subcount(cur->intf.intf[i].rcompr,
963 pre->intf.intf[j].rcompr);
964 dev->intf.intf[i].rmultic=subcount(cur->intf.intf[i].rmultic,
965 pre->intf.intf[j].rmultic);
966
967 dev->intf.intf[i].sbyte = subcount(cur->intf.intf[i].sbyte,
968 pre->intf.intf[j].sbyte);
969 dev->intf.intf[i].spack = subcount(cur->intf.intf[i].spack,
970 pre->intf.intf[j].spack);
971 dev->intf.intf[i].serrs = subcount(cur->intf.intf[i].serrs,
972 pre->intf.intf[j].serrs);
973 dev->intf.intf[i].sdrop = subcount(cur->intf.intf[i].sdrop,
974 pre->intf.intf[j].sdrop);
975 dev->intf.intf[i].sfifo = subcount(cur->intf.intf[i].sfifo,
976 pre->intf.intf[j].sfifo);
977 dev->intf.intf[i].scollis= subcount(cur->intf.intf[i].scollis,
978 pre->intf.intf[j].scollis);
979 dev->intf.intf[i].scarrier= subcount(cur->intf.intf[i].scarrier,
980 pre->intf.intf[j].scarrier);
981 dev->intf.intf[i].scompr= subcount(cur->intf.intf[i].scompr,
982 pre->intf.intf[j].scompr);
983
984 dev->intf.intf[i].type = cur->intf.intf[i].type;
985 dev->intf.intf[i].duplex = cur->intf.intf[i].duplex;
986 dev->intf.intf[i].speed = cur->intf.intf[i].speed;
987 dev->intf.intf[i].speedp = pre->intf.intf[j].speed;
988
989 cur->intf.intf[i].speedp = pre->intf.intf[j].speed;
990 }
991
992 dev->intf.intf[i].name[0] = '\0';
993 dev->intf.nrintf = i;
994
995 /*
996 ** calculate deviations for disks
997 */
998 for (i=j=0; cur->dsk.dsk[i].name[0]; i++)
999 {
1000 int realj = j;
1001
1002 /*
1003 ** check if disk has been added or removed since
1004 ** previous interval
1005 */
1006 if ( strcmp(cur->dsk.dsk[i].name, pre->dsk.dsk[j].name) != 0)
1007 {
1008 for (j++; pre->dsk.dsk[j].name[0]; j++)
1009 {
1010 if ( strcmp(cur->dsk.dsk[i].name,
1011 pre->dsk.dsk[j].name) == 0)
1012 break;
1013 }
1014
1015 /*
1016 ** either the corresponding entry has been found
1017 ** in the case that a disk has been removed, or
1018 ** an empty entry has been found (all counters
1019 ** on zero) in the case that a disk has been added
1020 ** during the last sample
1021 */
1022 }
1023
1024 strcpy(dev->dsk.dsk[i].name, cur->dsk.dsk[i].name);
1025
1026 dev->dsk.dsk[i].nread = subcount(cur->dsk.dsk[i].nread,
1027 pre->dsk.dsk[j].nread);
1028 dev->dsk.dsk[i].nrsect = subcount(cur->dsk.dsk[i].nrsect,
1029 pre->dsk.dsk[j].nrsect);
1030 dev->dsk.dsk[i].nwrite = subcount(cur->dsk.dsk[i].nwrite,
1031 pre->dsk.dsk[j].nwrite);
1032 dev->dsk.dsk[i].nwsect = subcount(cur->dsk.dsk[i].nwsect,
1033 pre->dsk.dsk[j].nwsect);
1034 dev->dsk.dsk[i].inflight = cur->dsk.dsk[i].inflight;
1035 dev->dsk.dsk[i].io_ms = subcount(cur->dsk.dsk[i].io_ms,
1036 pre->dsk.dsk[j].io_ms);
1037 dev->dsk.dsk[i].avque = subcount(cur->dsk.dsk[i].avque,
1038 pre->dsk.dsk[j].avque);
1039
1040 if (cur->dsk.dsk[i].ndisc != -1) // discards supported?
1041 {
1042 dev->dsk.dsk[i].ndisc = subcount(cur->dsk.dsk[i].ndisc,
1043 pre->dsk.dsk[j].ndisc);
1044 dev->dsk.dsk[i].ndsect = subcount(cur->dsk.dsk[i].ndsect,
1045 pre->dsk.dsk[j].ndsect);
1046 }
1047 else
1048 {
1049 dev->dsk.dsk[i].ndisc = -1;
1050 dev->dsk.dsk[i].ndsect = 0;
1051 }
1052
1053 /*
1054 ** determine new j
1055 */
1056 if (pre->dsk.dsk[j].name) // existing matching entry
1057 j++;
1058 else
1059 j = realj; // empty entry: stick to old j
1060 }
1061
1062 dev->dsk.dsk[i].name[0] = '\0';
1063 dev->dsk.ndsk = i;
1064
1065 /*
1066 ** calculate deviations for multiple devices
1067 */
1068 for (i=j=0; cur->dsk.mdd[i].name[0]; i++)
1069 {
1070 int realj = j;
1071
1072 /*
1073 ** check if md has been added or removed since
1074 ** previous interval
1075 */
1076 if ( strcmp(cur->dsk.mdd[i].name, pre->dsk.mdd[j].name) != 0)
1077 {
1078 for (j++; pre->dsk.mdd[j].name[0]; j++)
1079 {
1080 if ( strcmp(cur->dsk.mdd[i].name,
1081 pre->dsk.mdd[j].name) == 0)
1082 break;
1083 }
1084
1085 /*
1086 ** either the corresponding entry has been found
1087 ** in the case that a md has been removed, or
1088 ** an empty entry has been found (all counters
1089 ** on zero) in the case that a md has been added
1090 ** during the last sample
1091 */
1092 }
1093
1094 strcpy(dev->dsk.mdd[i].name, cur->dsk.mdd[i].name);
1095
1096 dev->dsk.mdd[i].nread = subcount(cur->dsk.mdd[i].nread,
1097 pre->dsk.mdd[j].nread);
1098 dev->dsk.mdd[i].nrsect = subcount(cur->dsk.mdd[i].nrsect,
1099 pre->dsk.mdd[j].nrsect);
1100 dev->dsk.mdd[i].nwrite = subcount(cur->dsk.mdd[i].nwrite,
1101 pre->dsk.mdd[j].nwrite);
1102 dev->dsk.mdd[i].nwsect = subcount(cur->dsk.mdd[i].nwsect,
1103 pre->dsk.mdd[j].nwsect);
1104 dev->dsk.mdd[i].io_ms = subcount(cur->dsk.mdd[i].io_ms,
1105 pre->dsk.mdd[j].io_ms);
1106 dev->dsk.mdd[i].avque = subcount(cur->dsk.mdd[i].avque,
1107 pre->dsk.mdd[j].avque);
1108
1109 if (cur->dsk.mdd[i].ndisc != -1) // discards supported?
1110 {
1111 dev->dsk.mdd[i].ndisc = subcount(cur->dsk.mdd[i].ndisc,
1112 pre->dsk.mdd[j].ndisc);
1113 dev->dsk.mdd[i].ndsect = subcount(cur->dsk.mdd[i].ndsect,
1114 pre->dsk.mdd[j].ndsect);
1115 }
1116 else
1117 {
1118 dev->dsk.mdd[i].ndisc = -1;
1119 dev->dsk.mdd[i].ndsect = 0;
1120 }
1121
1122 /*
1123 ** determine new j
1124 */
1125 if (pre->dsk.mdd[j].name) // existing matching entry
1126 j++;
1127 else
1128 j = realj; // empty entry: stick to old j
1129 }
1130
1131 dev->dsk.mdd[i].name[0] = '\0';
1132 dev->dsk.nmdd = i;
1133
1134 /*
1135 ** calculate deviations for LVM logical volumes
1136 */
1137 for (i=j=0; cur->dsk.lvm[i].name[0]; i++)
1138 {
1139 int realj = j;
1140
1141 /*
1142 ** check if logical volume has been added or removed since
1143 ** previous interval
1144 */
1145 if ( strcmp(cur->dsk.lvm[i].name, pre->dsk.lvm[j].name) != 0)
1146 {
1147 for (j++; pre->dsk.lvm[j].name[0]; j++)
1148 {
1149 if ( strcmp(cur->dsk.lvm[i].name,
1150 pre->dsk.lvm[j].name) == 0)
1151 break;
1152 }
1153
1154 /*
1155 ** either the corresponding entry has been found
1156 ** in the case that a logical volume has been removed,
1157 ** or an empty entry has been found (all counters
1158 ** on zero) in the case that a logical volume has
1159 ** been added during the last sample
1160 */
1161 }
1162
1163 strcpy(dev->dsk.lvm[i].name, cur->dsk.lvm[i].name);
1164
1165 dev->dsk.lvm[i].nread = subcount(cur->dsk.lvm[i].nread,
1166 pre->dsk.lvm[j].nread);
1167 dev->dsk.lvm[i].nrsect = subcount(cur->dsk.lvm[i].nrsect,
1168 pre->dsk.lvm[j].nrsect);
1169 dev->dsk.lvm[i].nwrite = subcount(cur->dsk.lvm[i].nwrite,
1170 pre->dsk.lvm[j].nwrite);
1171 dev->dsk.lvm[i].nwsect = subcount(cur->dsk.lvm[i].nwsect,
1172 pre->dsk.lvm[j].nwsect);
1173 dev->dsk.lvm[i].io_ms = subcount(cur->dsk.lvm[i].io_ms,
1174 pre->dsk.lvm[j].io_ms);
1175 dev->dsk.lvm[i].avque = subcount(cur->dsk.lvm[i].avque,
1176 pre->dsk.lvm[j].avque);
1177
1178 if (cur->dsk.lvm[i].ndisc != -1) // discards supported?
1179 {
1180 dev->dsk.lvm[i].ndisc = subcount(cur->dsk.lvm[i].ndisc,
1181 pre->dsk.lvm[j].ndisc);
1182 dev->dsk.lvm[i].ndsect = subcount(cur->dsk.lvm[i].ndsect,
1183 pre->dsk.lvm[j].ndsect);
1184 }
1185 else
1186 {
1187 dev->dsk.lvm[i].ndisc = -1;
1188 dev->dsk.lvm[i].ndsect = 0;
1189 }
1190
1191 /*
1192 ** determine new j
1193 */
1194 if (pre->dsk.lvm[j].name) // existing matching entry
1195 j++;
1196 else
1197 j = realj; // empty entry: stick to old j
1198 }
1199
1200 dev->dsk.lvm[i].name[0] = '\0';
1201 dev->dsk.nlvm = i;
1202
1203 /*
1204 ** calculate deviations for NFS
1205 */
1206 dev->nfs.server.netcnt = subcount(cur->nfs.server.netcnt,
1207 pre->nfs.server.netcnt);
1208 dev->nfs.server.netudpcnt = subcount(cur->nfs.server.netudpcnt,
1209 pre->nfs.server.netudpcnt);
1210 dev->nfs.server.nettcpcnt = subcount(cur->nfs.server.nettcpcnt,
1211 pre->nfs.server.nettcpcnt);
1212 dev->nfs.server.nettcpcon = subcount(cur->nfs.server.nettcpcon,
1213 pre->nfs.server.nettcpcon);
1214
1215 dev->nfs.server.rpccnt = subcount(cur->nfs.server.rpccnt,
1216 pre->nfs.server.rpccnt);
1217 dev->nfs.server.rpcread = subcount(cur->nfs.server.rpcread,
1218 pre->nfs.server.rpcread);
1219 dev->nfs.server.rpcwrite = subcount(cur->nfs.server.rpcwrite,
1220 pre->nfs.server.rpcwrite);
1221 dev->nfs.server.rpcbadfmt = subcount(cur->nfs.server.rpcbadfmt,
1222 pre->nfs.server.rpcbadfmt);
1223 dev->nfs.server.rpcbadaut = subcount(cur->nfs.server.rpcbadaut,
1224 pre->nfs.server.rpcbadaut);
1225 dev->nfs.server.rpcbadcln = subcount(cur->nfs.server.rpcbadcln,
1226 pre->nfs.server.rpcbadcln);
1227
1228 dev->nfs.server.rchits = subcount(cur->nfs.server.rchits,
1229 pre->nfs.server.rchits);
1230 dev->nfs.server.rcmiss = subcount(cur->nfs.server.rcmiss,
1231 pre->nfs.server.rcmiss);
1232 dev->nfs.server.rcnoca = subcount(cur->nfs.server.rcnoca,
1233 pre->nfs.server.rcnoca);
1234
1235 dev->nfs.server.nrbytes = subcount(cur->nfs.server.nrbytes,
1236 pre->nfs.server.nrbytes);
1237 dev->nfs.server.nwbytes = subcount(cur->nfs.server.nwbytes,
1238 pre->nfs.server.nwbytes);
1239
1240 dev->nfs.client.rpccnt = subcount(cur->nfs.client.rpccnt,
1241 pre->nfs.client.rpccnt);
1242 dev->nfs.client.rpcread = subcount(cur->nfs.client.rpcread,
1243 pre->nfs.client.rpcread);
1244 dev->nfs.client.rpcwrite = subcount(cur->nfs.client.rpcwrite,
1245 pre->nfs.client.rpcwrite);
1246 dev->nfs.client.rpcretrans = subcount(cur->nfs.client.rpcretrans,
1247 pre->nfs.client.rpcretrans);
1248 dev->nfs.client.rpcautrefresh = subcount(cur->nfs.client.rpcautrefresh,
1249 pre->nfs.client.rpcautrefresh);
1250
1251
1252 for (i=j=0; i < cur->nfs.nfsmounts.nrmounts; i++, j++)
1253 {
1254 /*
1255 ** check if nfsmounts have been added or removed since
1256 ** previous interval
1257 */
1258 if ( strcmp(cur->nfs.nfsmounts.nfsmnt[i].mountdev,
1259 pre->nfs.nfsmounts.nfsmnt[j].mountdev) != 0)
1260 {
1261 for (j=0; j < pre->nfs.nfsmounts.nrmounts; j++)
1262 {
1263 if ( strcmp(cur->nfs.nfsmounts.nfsmnt[i].mountdev,
1264 pre->nfs.nfsmounts.nfsmnt[j].mountdev)
1265 == 0)
1266 break;
1267 }
1268
1269 /*
1270 ** either the corresponding entry has been found
1271 ** in the case that a container has been removed,
1272 ** or an empty entry has been found (all counters
1273 ** on zero) in the case that a container has
1274 ** been added during the last sample
1275 */
1276 }
1277
1278 strcpy(dev->nfs.nfsmounts.nfsmnt[i].mountdev,
1279 cur->nfs.nfsmounts.nfsmnt[i].mountdev);
1280
1281 dev->nfs.nfsmounts.nfsmnt[i].age =
1282 cur->nfs.nfsmounts.nfsmnt[i].age;
1283
1284 if (dev->nfs.nfsmounts.nfsmnt[i].age <= interval)
1285 memset(&(pre->nfs.nfsmounts.nfsmnt[j]), 0,
1286 sizeof(struct pernfsmount));
1287
1288 dev->nfs.nfsmounts.nfsmnt[i].bytesread =
1289 subcount(cur->nfs.nfsmounts.nfsmnt[i].bytesread,
1290 pre->nfs.nfsmounts.nfsmnt[j].bytesread);
1291
1292 dev->nfs.nfsmounts.nfsmnt[i].byteswrite =
1293 subcount(cur->nfs.nfsmounts.nfsmnt[i].byteswrite,
1294 pre->nfs.nfsmounts.nfsmnt[j].byteswrite);
1295
1296 dev->nfs.nfsmounts.nfsmnt[i].bytesdread =
1297 subcount(cur->nfs.nfsmounts.nfsmnt[i].bytesdread,
1298 pre->nfs.nfsmounts.nfsmnt[j].bytesdread);
1299
1300 dev->nfs.nfsmounts.nfsmnt[i].bytesdwrite =
1301 subcount(cur->nfs.nfsmounts.nfsmnt[i].bytesdwrite,
1302 pre->nfs.nfsmounts.nfsmnt[j].bytesdwrite);
1303
1304 dev->nfs.nfsmounts.nfsmnt[i].bytestotread =
1305 subcount(cur->nfs.nfsmounts.nfsmnt[i].bytestotread,
1306 pre->nfs.nfsmounts.nfsmnt[j].bytestotread);
1307
1308 dev->nfs.nfsmounts.nfsmnt[i].bytestotwrite =
1309 subcount(cur->nfs.nfsmounts.nfsmnt[i].bytestotwrite,
1310 pre->nfs.nfsmounts.nfsmnt[j].bytestotwrite);
1311
1312 dev->nfs.nfsmounts.nfsmnt[i].pagesmread =
1313 subcount(cur->nfs.nfsmounts.nfsmnt[i].pagesmread,
1314 pre->nfs.nfsmounts.nfsmnt[j].pagesmread);
1315
1316 dev->nfs.nfsmounts.nfsmnt[i].pagesmwrite =
1317 subcount(cur->nfs.nfsmounts.nfsmnt[i].pagesmwrite,
1318 pre->nfs.nfsmounts.nfsmnt[j].pagesmwrite);
1319 }
1320
1321 dev->nfs.nfsmounts.nrmounts = cur->nfs.nfsmounts.nrmounts;
1322
1323 /*
1324 ** calculate deviations for containers
1325 */
1326 for (i=j=0; i < cur->cfs.nrcontainer; i++, j++)
1327 {
1328 /*
1329 ** check if containers have been added or removed since
1330 ** previous interval
1331 */
1332 if (cur->cfs.cont[i].ctid != pre->cfs.cont[j].ctid)
1333 {
1334 for (j=0; j < pre->cfs.nrcontainer; j++)
1335 {
1336 if (cur->cfs.cont[i].ctid ==
1337 pre->cfs.cont[j].ctid)
1338 break;
1339 }
1340
1341 /*
1342 ** either the corresponding entry has been found
1343 ** in the case that a container has been removed,
1344 ** or an empty entry has been found (all counters
1345 ** on zero) in the case that a container has
1346 ** been added during the last sample
1347 */
1348 }
1349
1350 dev->cfs.cont[i].ctid = cur->cfs.cont[i].ctid;
1351 dev->cfs.cont[i].numproc = cur->cfs.cont[i].numproc;
1352 dev->cfs.cont[i].physpages = cur->cfs.cont[i].physpages;
1353
1354 dev->cfs.cont[i].system = subcount(cur->cfs.cont[i].system,
1355 pre->cfs.cont[j].system);
1356 dev->cfs.cont[i].user = subcount(cur->cfs.cont[i].user,
1357 pre->cfs.cont[j].user);
1358 dev->cfs.cont[i].nice = subcount(cur->cfs.cont[i].nice,
1359 pre->cfs.cont[j].nice);
1360 dev->cfs.cont[i].uptime = subcount(cur->cfs.cont[i].uptime,
1361 pre->cfs.cont[j].uptime);
1362 }
1363
1364 dev->cfs.nrcontainer = cur->cfs.nrcontainer;
1365
1366 /*
1367 ** calculate deviations for GPUs
1368 */
1369 for (i=0; i < cur->gpu.nrgpus; i++)
1370 {
1371 dev->gpu.gpu[i].gpunr = i;
1372
1373 strcpy(dev->gpu.gpu[i].type, cur->gpu.gpu[i].type);
1374 strcpy(dev->gpu.gpu[i].busid, cur->gpu.gpu[i].busid);
1375
1376 dev->gpu.gpu[i].taskstats = cur->gpu.gpu[i].taskstats;
1377 dev->gpu.gpu[i].nrprocs = cur->gpu.gpu[i].nrprocs;
1378
1379 dev->gpu.gpu[i].gpupercnow = cur->gpu.gpu[i].gpupercnow;
1380 dev->gpu.gpu[i].mempercnow = cur->gpu.gpu[i].mempercnow;
1381 dev->gpu.gpu[i].memtotnow = cur->gpu.gpu[i].memtotnow;
1382 dev->gpu.gpu[i].memusenow = cur->gpu.gpu[i].memusenow;
1383
1384 dev->gpu.gpu[i].samples = subcount(cur->gpu.gpu[i].samples,
1385 pre->gpu.gpu[i].samples);
1386
1387 if (cur->gpu.gpu[i].gpuperccum >= 0)
1388 dev->gpu.gpu[i].gpuperccum = subcount(cur->gpu.gpu[i].gpuperccum,
1389 pre->gpu.gpu[i].gpuperccum);
1390 else
1391 dev->gpu.gpu[i].gpuperccum = -1;
1392
1393 if (cur->gpu.gpu[i].memusecum >= 0)
1394 dev->gpu.gpu[i].memusecum = subcount(cur->gpu.gpu[i].memusecum,
1395 pre->gpu.gpu[i].memusecum);
1396 else
1397 dev->gpu.gpu[i].memusecum = -1;
1398
1399 if (cur->gpu.gpu[i].memperccum >= 0)
1400 dev->gpu.gpu[i].memperccum = subcount(cur->gpu.gpu[i].memperccum,
1401 pre->gpu.gpu[i].memperccum);
1402 else
1403 dev->gpu.gpu[i].memperccum = -1;
1404 }
1405
1406 dev->gpu.nrgpus = cur->gpu.nrgpus;
1407
1408 /*
1409 ** calculate deviations for InfiniBand
1410 */
1411 for (i=0; i < cur->ifb.nrports; i++)
1412 {
1413 strcpy(dev->ifb.ifb[i].ibname, cur->ifb.ifb[i].ibname);
1414
1415 dev->ifb.ifb[i].portnr = cur->ifb.ifb[i].portnr;
1416 dev->ifb.ifb[i].lanes = cur->ifb.ifb[i].lanes;
1417 dev->ifb.ifb[i].rate = cur->ifb.ifb[i].rate;
1418
1419 dev->ifb.ifb[i].rcvb = cur->ifb.ifb[i].rcvb -
1420 pre->ifb.ifb[i].rcvb;
1421 dev->ifb.ifb[i].sndb = cur->ifb.ifb[i].sndb -
1422 pre->ifb.ifb[i].sndb;
1423 dev->ifb.ifb[i].rcvp = cur->ifb.ifb[i].rcvp -
1424 pre->ifb.ifb[i].rcvp;
1425 dev->ifb.ifb[i].sndp = cur->ifb.ifb[i].sndp -
1426 pre->ifb.ifb[i].sndp;
1427 }
1428
1429 dev->ifb.nrports = cur->ifb.nrports;
1430
1431 /*
1432 ** calculate deviations for Last Level Cache
1433 */
1434 for (i = 0; i < cur->llc.nrllcs; i++)
1435 {
1436 dev->llc.perllc[i].id = cur->llc.perllc[i].id;
1437 dev->llc.perllc[i].occupancy = cur->llc.perllc[i].occupancy;
1438 dev->llc.perllc[i].mbm_local = cur->llc.perllc[i].mbm_local -
1439 pre->llc.perllc[i].mbm_local;
1440 dev->llc.perllc[i].mbm_total = cur->llc.perllc[i].mbm_total -
1441 pre->llc.perllc[i].mbm_total;
1442 }
1443
1444 dev->llc.nrllcs = cur->llc.nrllcs;
1445
1446 #if HTTPSTATS
1447 /*
1448 ** application-specific counters
1449 */
1450 if (cur->www.uptime >= pre->www.uptime)
1451 {
1452 dev->www.accesses = subcount(cur->www.accesses,
1453 pre->www.accesses);
1454 dev->www.totkbytes = subcount(cur->www.totkbytes,
1455 pre->www.totkbytes);
1456 }
1457 else
1458 {
1459 dev->www.accesses = cur->www.accesses;
1460 dev->www.totkbytes = cur->www.totkbytes;
1461 }
1462
1463 dev->www.bworkers = cur->www.bworkers;
1464 dev->www.iworkers = cur->www.iworkers;
1465 #endif
1466 }
1467
1468 /*
1469 ** add the values of a new sample to a structure holding the totals
1470 ** for the indicated category (c=cpu, m=memory, d=disk, n=network).
1471 */
1472 void
1473 totalsyst(char category, struct sstat *new, struct sstat *tot)
1474 {
1475 register int i;
1476 count_t *ctot, *cnew;
1477
1478 switch (category)
1479 {
1480 case 'c': /* accumulate cpu-related counters */
1481 tot->cpu.nrcpu = new->cpu.nrcpu;
1482 tot->cpu.devint += new->cpu.devint;
1483 tot->cpu.csw += new->cpu.csw;
1484 tot->cpu.nprocs += new->cpu.nprocs;
1485
1486 tot->cpu.all.stime += new->cpu.all.stime;
1487 tot->cpu.all.utime += new->cpu.all.utime;
1488 tot->cpu.all.ntime += new->cpu.all.ntime;
1489 tot->cpu.all.itime += new->cpu.all.itime;
1490 tot->cpu.all.wtime += new->cpu.all.wtime;
1491 tot->cpu.all.Itime += new->cpu.all.Itime;
1492 tot->cpu.all.Stime += new->cpu.all.Stime;
1493 tot->cpu.all.steal += new->cpu.all.steal;
1494 tot->cpu.all.guest += new->cpu.all.guest;
1495
1496 if (new->cpu.nrcpu == 1)
1497 {
1498 tot->cpu.cpu[0] = tot->cpu.all;
1499 }
1500 else
1501 {
1502 for (i=0; i < new->cpu.nrcpu; i++)
1503 {
1504 tot->cpu.cpu[i].cpunr = new->cpu.cpu[i].cpunr;
1505 tot->cpu.cpu[i].stime += new->cpu.cpu[i].stime;
1506 tot->cpu.cpu[i].utime += new->cpu.cpu[i].utime;
1507 tot->cpu.cpu[i].ntime += new->cpu.cpu[i].ntime;
1508 tot->cpu.cpu[i].itime += new->cpu.cpu[i].itime;
1509 tot->cpu.cpu[i].wtime += new->cpu.cpu[i].wtime;
1510 tot->cpu.cpu[i].Itime += new->cpu.cpu[i].Itime;
1511 tot->cpu.cpu[i].Stime += new->cpu.cpu[i].Stime;
1512 tot->cpu.cpu[i].steal += new->cpu.cpu[i].steal;
1513 tot->cpu.cpu[i].guest += new->cpu.cpu[i].guest;
1514 }
1515 }
1516
1517 tot->cpu.lavg1 = new->cpu.lavg1;
1518 tot->cpu.lavg5 = new->cpu.lavg5;
1519 tot->cpu.lavg15 = new->cpu.lavg15;
1520 break;
1521
1522 case 'm': /* accumulate memory-related counters */
1523 tot->mem.physmem = new->mem.physmem;
1524 tot->mem.freemem = new->mem.freemem;
1525 tot->mem.buffermem = new->mem.buffermem;
1526 tot->mem.slabmem = new->mem.slabmem;
1527 tot->mem.slabreclaim = new->mem.slabreclaim;
1528 tot->mem.committed = new->mem.committed;
1529 tot->mem.commitlim = new->mem.commitlim;
1530 tot->mem.cachemem = new->mem.cachemem;
1531 tot->mem.cachedrt = new->mem.cachedrt;
1532 tot->mem.totswap = new->mem.totswap;
1533 tot->mem.freeswap = new->mem.freeswap;
1534 tot->mem.swapcached = new->mem.swapcached;
1535 tot->mem.pagetables = new->mem.pagetables;
1536
1537 tot->mem.shmem = new->mem.shmem;
1538 tot->mem.shmrss = new->mem.shmrss;
1539 tot->mem.shmswp = new->mem.shmswp;
1540
1541 tot->mem.tcpsock = new->mem.tcpsock;
1542 tot->mem.udpsock = new->mem.udpsock;
1543
1544 tot->mem.pgouts += new->mem.pgouts;
1545 tot->mem.pgins += new->mem.pgins;
1546 tot->mem.swouts += new->mem.swouts;
1547 tot->mem.swins += new->mem.swins;
1548 tot->mem.pgscans += new->mem.pgscans;
1549 tot->mem.allocstall += new->mem.allocstall;
1550 tot->mem.compactstall += new->mem.compactstall;
1551 break;
1552
1553 case 'n': /* accumulate network-related counters */
1554 tot->nfs.server.rpccnt += new->nfs.server.rpccnt;
1555 tot->nfs.server.rpcread += new->nfs.server.rpcread;
1556 tot->nfs.server.rpcwrite += new->nfs.server.rpcwrite;
1557 tot->nfs.server.rpcbadfmt += new->nfs.server.rpcbadfmt;
1558 tot->nfs.server.rpcbadaut += new->nfs.server.rpcbadaut;
1559 tot->nfs.server.rpcbadcln += new->nfs.server.rpcbadcln;
1560
1561 tot->nfs.server.netcnt += new->nfs.server.netcnt;
1562 tot->nfs.server.nettcpcnt += new->nfs.server.nettcpcnt;
1563 tot->nfs.server.netudpcnt += new->nfs.server.netudpcnt;
1564 tot->nfs.server.nettcpcon += new->nfs.server.nettcpcon;
1565
1566 tot->nfs.server.rchits += new->nfs.server.rchits;
1567 tot->nfs.server.rcmiss += new->nfs.server.rcmiss;
1568 tot->nfs.server.rcnoca += new->nfs.server.rcnoca;
1569
1570 tot->nfs.server.nrbytes += new->nfs.server.nrbytes;
1571 tot->nfs.server.nwbytes += new->nfs.server.nwbytes;
1572
1573 tot->nfs.client.rpccnt += new->nfs.client.rpccnt;
1574 tot->nfs.client.rpcread += new->nfs.client.rpcread;
1575 tot->nfs.client.rpcwrite += new->nfs.client.rpcwrite;
1576 tot->nfs.client.rpcretrans += new->nfs.client.rpcretrans;
1577 tot->nfs.client.rpcautrefresh += new->nfs.client.rpcautrefresh;
1578
1579 /*
1580 ** other structures with network counters are considered
1581 ** as tables of frequency-counters that will be accumulated;
1582 ** values that do not represent a frequency are corrected
1583 ** afterwards
1584 */
1585 for (ctot = (count_t *)&tot->net.ipv4,
1586 cnew = (count_t *)&new->net.ipv4, i = 0;
1587 i < (sizeof tot->net.ipv4 / sizeof(count_t));
1588 ctot++, cnew++, i++)
1589 *ctot += *cnew;
1590
1591 tot->net.ipv4.Forwarding = new->net.ipv4.Forwarding;
1592 tot->net.ipv4.DefaultTTL = new->net.ipv4.DefaultTTL;
1593
1594 /* ------------- */
1595
1596 for (ctot = (count_t *)&tot->net.icmpv4,
1597 cnew = (count_t *)&new->net.icmpv4, i = 0;
1598 i < (sizeof tot->net.icmpv4 / sizeof(count_t));
1599 ctot++, cnew++, i++)
1600 *ctot += *cnew;
1601
1602 /* ------------- */
1603
1604 for (ctot = (count_t *)&tot->net.udpv4,
1605 cnew = (count_t *)&new->net.udpv4, i = 0;
1606 i < (sizeof tot->net.udpv4 / sizeof(count_t));
1607 ctot++, cnew++, i++)
1608 *ctot += *cnew;
1609
1610 /* ------------- */
1611
1612 for (ctot = (count_t *)&tot->net.ipv6,
1613 cnew = (count_t *)&new->net.ipv6, i = 0;
1614 i < (sizeof tot->net.ipv6 / sizeof(count_t));
1615 ctot++, cnew++, i++)
1616 *ctot += *cnew;
1617
1618 /* ------------- */
1619
1620 for (ctot = (count_t *)&tot->net.icmpv6,
1621 cnew = (count_t *)&new->net.icmpv6, i = 0;
1622 i < (sizeof tot->net.icmpv6 / sizeof(count_t));
1623 ctot++, cnew++, i++)
1624 *ctot += *cnew;
1625
1626 /* ------------- */
1627
1628 for (ctot = (count_t *)&tot->net.udpv6,
1629 cnew = (count_t *)&new->net.udpv6, i = 0;
1630 i < (sizeof tot->net.udpv6 / sizeof(count_t));
1631 ctot++, cnew++, i++)
1632 *ctot += *cnew;
1633
1634 /* ------------- */
1635
1636 for (ctot = (count_t *)&tot->net.tcp,
1637 cnew = (count_t *)&new->net.tcp, i = 0;
1638 i < (sizeof tot->net.tcp / sizeof(count_t));
1639 ctot++, cnew++, i++)
1640 *ctot += *cnew;
1641
1642 tot->net.tcp.RtoAlgorithm = new->net.tcp.RtoAlgorithm;
1643 tot->net.tcp.RtoMin = new->net.tcp.RtoMin;
1644 tot->net.tcp.RtoMax = new->net.tcp.RtoMax;
1645 tot->net.tcp.MaxConn = new->net.tcp.MaxConn;
1646 tot->net.tcp.CurrEstab = new->net.tcp.CurrEstab;
1647
1648 for (i=0; new->intf.intf[i].name[0]; i++)
1649 {
1650 /*
1651 ** check if an interface has been added or removed;
1652 ** in that case, zero all counters
1653 */
1654 if (strcmp(new->intf.intf[i].name,
1655 tot->intf.intf[i].name) != 0)
1656 {
1657 tot->intf.intf[i].rbyte = 0;
1658 tot->intf.intf[i].rpack = 0;
1659 tot->intf.intf[i].rerrs = 0;
1660 tot->intf.intf[i].rdrop = 0;
1661 tot->intf.intf[i].rfifo = 0;
1662 tot->intf.intf[i].rframe = 0;
1663 tot->intf.intf[i].rcompr = 0;
1664 tot->intf.intf[i].rmultic = 0;
1665
1666 tot->intf.intf[i].sbyte = 0;
1667 tot->intf.intf[i].spack = 0;
1668 tot->intf.intf[i].serrs = 0;
1669 tot->intf.intf[i].sdrop = 0;
1670 tot->intf.intf[i].sfifo = 0;
1671 tot->intf.intf[i].scollis = 0;
1672 tot->intf.intf[i].scarrier = 0;
1673 tot->intf.intf[i].scompr = 0;
1674 }
1675
1676 /*
1677 ** accumulate counters for this sample
1678 */
1679 strcpy(tot->intf.intf[i].name, new->intf.intf[i].name);
1680
1681 tot->intf.intf[i].rbyte += new->intf.intf[i].rbyte;
1682 tot->intf.intf[i].rpack += new->intf.intf[i].rpack;
1683 tot->intf.intf[i].rerrs += new->intf.intf[i].rerrs;
1684 tot->intf.intf[i].rdrop += new->intf.intf[i].rdrop;
1685 tot->intf.intf[i].rfifo += new->intf.intf[i].rfifo;
1686 tot->intf.intf[i].rframe += new->intf.intf[i].rframe;
1687 tot->intf.intf[i].rcompr += new->intf.intf[i].rcompr;
1688 tot->intf.intf[i].rmultic += new->intf.intf[i].rmultic;
1689
1690 tot->intf.intf[i].sbyte += new->intf.intf[i].sbyte;
1691 tot->intf.intf[i].spack += new->intf.intf[i].spack;
1692 tot->intf.intf[i].serrs += new->intf.intf[i].serrs;
1693 tot->intf.intf[i].sdrop += new->intf.intf[i].sdrop;
1694 tot->intf.intf[i].sfifo += new->intf.intf[i].sfifo;
1695 tot->intf.intf[i].scollis += new->intf.intf[i].scollis;
1696 tot->intf.intf[i].scarrier+= new->intf.intf[i].scarrier;
1697 tot->intf.intf[i].scompr += new->intf.intf[i].scompr;
1698
1699 tot->intf.intf[i].type = new->intf.intf[i].type;
1700 tot->intf.intf[i].speed = new->intf.intf[i].speed;
1701 tot->intf.intf[i].duplex = new->intf.intf[i].duplex;
1702 }
1703
1704 tot->intf.intf[i].name[0] = '\0';
1705 tot->intf.nrintf = i;
1706
1707 #if HTTPSTATS
1708 tot->www.accesses += new->www.accesses;
1709 tot->www.totkbytes += new->www.totkbytes;
1710 tot->www.bworkers = new->www.bworkers;
1711 tot->www.iworkers = new->www.iworkers;
1712 #endif
1713 break;
1714
1715 case 'd': /* accumulate disk-related counters */
1716 for (i=0; new->dsk.dsk[i].name[0]; i++)
1717 {
1718 strcpy(tot->dsk.dsk[i].name, new->dsk.dsk[i].name);
1719
1720 tot->dsk.dsk[i].nread += new->dsk.dsk[i].nread;
1721 tot->dsk.dsk[i].nrsect += new->dsk.dsk[i].nrsect;
1722 tot->dsk.dsk[i].nwrite += new->dsk.dsk[i].nwrite;
1723 tot->dsk.dsk[i].nwsect += new->dsk.dsk[i].nwsect;
1724 tot->dsk.dsk[i].io_ms += new->dsk.dsk[i].io_ms;
1725 tot->dsk.dsk[i].avque += new->dsk.dsk[i].avque;
1726
1727 if (new->dsk.dsk[i].ndisc != -1) // discards?
1728 {
1729 tot->dsk.dsk[i].ndisc += new->dsk.dsk[i].ndisc;
1730 tot->dsk.dsk[i].ndsect += new->dsk.dsk[i].ndsect;
1731 }
1732
1733 }
1734
1735 tot->dsk.dsk[i].name[0] = '\0';
1736 tot->dsk.ndsk = i;
1737
1738 for (i=0; new->dsk.lvm[i].name[0]; i++)
1739 {
1740 strcpy(tot->dsk.lvm[i].name, new->dsk.lvm[i].name);
1741
1742 tot->dsk.lvm[i].nread += new->dsk.lvm[i].nread;
1743 tot->dsk.lvm[i].nrsect += new->dsk.lvm[i].nrsect;
1744 tot->dsk.lvm[i].nwrite += new->dsk.lvm[i].nwrite;
1745 tot->dsk.lvm[i].nwsect += new->dsk.lvm[i].nwsect;
1746 tot->dsk.lvm[i].io_ms += new->dsk.lvm[i].io_ms;
1747 tot->dsk.lvm[i].avque += new->dsk.lvm[i].avque;
1748
1749 if (new->dsk.lvm[i].ndisc != -1) // discards?
1750 {
1751 tot->dsk.lvm[i].ndisc += new->dsk.lvm[i].ndisc;
1752 tot->dsk.lvm[i].ndsect += new->dsk.lvm[i].ndsect;
1753 }
1754 }
1755
1756 tot->dsk.lvm[i].name[0] = '\0';
1757 tot->dsk.nlvm = i;
1758
1759 for (i=0; new->dsk.mdd[i].name[0]; i++)
1760 {
1761 strcpy(tot->dsk.mdd[i].name, new->dsk.mdd[i].name);
1762
1763 tot->dsk.mdd[i].nread += new->dsk.mdd[i].nread;
1764 tot->dsk.mdd[i].nrsect += new->dsk.mdd[i].nrsect;
1765 tot->dsk.mdd[i].nwrite += new->dsk.mdd[i].nwrite;
1766 tot->dsk.mdd[i].nwsect += new->dsk.mdd[i].nwsect;
1767 tot->dsk.mdd[i].io_ms += new->dsk.mdd[i].io_ms;
1768 tot->dsk.mdd[i].avque += new->dsk.mdd[i].avque;
1769
1770 if (new->dsk.mdd[i].ndisc != -1) // discards?
1771 {
1772 tot->dsk.mdd[i].ndisc += new->dsk.lvm[i].ndisc;
1773 tot->dsk.mdd[i].ndsect += new->dsk.lvm[i].ndsect;
1774 }
1775 }
1776
1777 tot->dsk.mdd[i].name[0] = '\0';
1778 tot->dsk.nmdd = i;
1779 break;
1780 }
1781 }
1782
1783
1784 /*
1785 ** Generic function to subtract two counters taking into
1786 ** account the possibility that the counter is invalid
1787 ** (i.e. non-existing).
1788 */
1789 static inline count_t
1790 subcount(count_t newval, count_t oldval)
1791 {
1792 if (newval == -1) // invalid counter?
1793 return -1;
1794
1795 if (newval >= oldval) // normal situation
1796 return newval - oldval;
1797 else // counter seems to be reset
1798 return newval;
1799 }