New upstream version 2.5.0
Marc Haber
3 years ago
0 | commit 6fa0306b8966ac0210bb013de4289951f8499ab8 | |
1 | Merge: a802f1a 43b50d0 | |
2 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
3 | Date: Sat Oct 26 22:32:32 2019 +0200 | |
4 | ||
5 | Merge branch 'timers' | |
6 | ||
7 | commit 43b50d02d413aba226154d3ce8b4721b27b0a06c | |
8 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
9 | Date: Sat Oct 26 22:28:37 2019 +0200 | |
10 | ||
11 | Modify man pages and spec files for added unit files | |
12 | The atop.daily script is not used any more for systemd-based systems. | |
13 | The man page of atop has been changed accordingly. Furthermore, the | |
14 | spec files have been modified to install the new unit files. | |
15 | ||
16 | M Makefile | |
17 | M atop-rotate.service | |
18 | M atop-rotate.timer | |
19 | D atop.cronsystemd | |
20 | M atop.service | |
21 | M man/atop.1 | |
22 | M rpmspec/atop.specsystemd | |
23 | M rpmspec/atop.specsysv | |
24 | ||
25 | commit f8024a674203cec60ab311879b34292a10abff5d | |
26 | Merge: a802f1a 97d7b82 | |
27 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
28 | Date: Wed Oct 23 21:31:33 2019 +0200 | |
29 | ||
30 | Merge branch 'master' of git://github.com/SjonHortensius/atop into timers | |
31 | ||
32 | commit 97d7b8225d486211a0a02521a406f83780262253 | |
33 | Author: Justin Kromlinger <mail@hashworks.net> | |
34 | Date: Fri Oct 11 13:37:27 2019 +0200 | |
35 | ||
36 | Read environment file in systemd service, use atop defaults (#1) | |
37 | ||
38 | Read environment file in systemd service, use atop defaults instead of hardcoded | |
39 | ||
40 | M atop.service | |
41 | ||
42 | commit a802f1a68ff0f3f06e6a4c609a87c0679bd07fce | |
43 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
44 | Date: Wed Sep 18 21:43:20 2019 +0200 | |
45 | ||
46 | Allow raw data to be read from a named pipe | |
47 | When reading raw data from a named pipe instead of from | |
48 | a regular file, it is not possible to branch ('b'), reset ('r') | |
49 | or go to a precious sample in an interactive session. With atopsar, | |
50 | only one report can be generated (no combination of various reporting | |
51 | flags). | |
52 | ||
53 | M atop.h | |
54 | M atopsar.c | |
55 | M man/atop.1 | |
56 | M rawlog.c | |
57 | ||
58 | commit db74804d15e98af37ed62bfcad95a93959c9d277 | |
59 | Merge: b10ee34 78f99bb | |
60 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
61 | Date: Wed Sep 18 12:02:31 2019 +0200 | |
62 | ||
63 | Merge pull request #69 from gleventhal/fix-lseek-segfault-on-nonseekable-piped-rawlog | |
64 | ||
65 | Check that rawlog is seekable to prevent later segfaults | |
66 | ||
67 | commit b10ee3492ee232a600aa934a724c4c687c691e79 | |
68 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
69 | Date: Wed Sep 18 11:46:58 2019 +0200 | |
70 | ||
71 | Improve determination of container ID | |
72 | Many processes might use the cpuset cgroup without being a | |
73 | container. The length of the basename is verified to be at | |
74 | least 64 characters (length of SHA256 identifying a container). | |
75 | ||
76 | M photoproc.c | |
77 | ||
78 | commit fea96f0690f6694624d85b9cb4f216fafea09b79 | |
79 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
80 | Date: Mon Sep 16 21:02:23 2019 +0200 | |
81 | ||
82 | Correction to avoid loosing first position of CID. | |
83 | ||
84 | M photoproc.c | |
85 | ||
86 | commit 3fe8f59d71cb8cd70d0fa8d4fd77f232be2922d1 | |
87 | Merge: 3e0b68c a3db75e | |
88 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
89 | Date: Mon Sep 16 20:57:26 2019 +0200 | |
90 | ||
91 | Merge branch 'bytedance-fix-docker-container-k8s' | |
92 | ||
93 | commit a3db75e174efbe95518f5a18fe89b9aa8154e177 | |
94 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
95 | Date: Mon Sep 16 20:55:04 2019 +0200 | |
96 | ||
97 | Proposed solution for K8s containers modified. | |
98 | Docker containers on RedHat/CentOS based systems have | |
99 | a prefix 'docker-' behind the last '/' that should | |
100 | be skipped. | |
101 | ||
102 | M photoproc.c | |
103 | ||
104 | commit 82f2fc889419555a9a1df868e6d1133c0b0169cc | |
105 | Author: zhenwei pi <pizhenwei@bytedance.com> | |
106 | Date: Fri May 24 19:54:42 2019 +0800 | |
107 | ||
108 | Fix container compatibility for docker created by k8s | |
109 | ||
110 | Cpuset of a docker created by k8s looks like this: | |
111 | /kubepods/burstable/pod07dbb922-[SNAP]/223dc5e15b[SNAP] | |
112 | ||
113 | Instead of checking prefix "docker", we usually get 12 char from | |
114 | last '/'. | |
115 | Test for docker and k8s, both of them work well. 'CID' row shows | |
116 | the same string as the `docker ps`. | |
117 | ||
118 | Test result for k8s: | |
119 | ~# docker ps | |
120 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
121 | e978af4928f6 hub.byted.org/google_containers/pause-amd64:3.0 "/pause" 39 hours ago Up 39 hours k8s_POD_dp-9fe0dd7536-55fd89b474-[SNAP] | |
122 | ||
123 | ~# atop -j | |
124 | NPROCS SYSCPU USRCPU VSIZE RSIZE PSIZE SWAPSZ RDDSK WRDSK RNET SNET CPU CID 1/1 | |
125 | 557 1h42m 2h57m 29.6G 1.3G 1.1G 0K 1.9G 19.0G 0 0 11% host-------- | |
126 | 1 0.00s 0.00s 1028K 4K 109K 0K 0K 0K 0 0 0% e978af4928f6 | |
127 | ||
128 | Signed-off-by: zhenwei pi <pizhenwei@bytedance.com> | |
129 | ||
130 | M photoproc.c | |
131 | ||
132 | commit 3e0b68cb9858a16749c98c3d399d2373e239caa6 | |
133 | Merge: 1b50456 086366f | |
134 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
135 | Date: Sat Aug 10 12:20:13 2019 +0200 | |
136 | ||
137 | Merge branch 'bytedance-perfevent' | |
138 | By default, suppress gathering of 'perf' counters on VM guests. | |
139 | ||
140 | commit 086366f9e008c711d51e8400ae9d54479224fae0 | |
141 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
142 | Date: Sat Aug 10 12:18:46 2019 +0200 | |
143 | ||
144 | Adapt documentation to new keyword 'perfevents' in atoprc. | |
145 | ||
146 | M man/atop.1 | |
147 | M man/atoprc.5 | |
148 | M photosyst.c | |
149 | ||
150 | commit ea9e1814e255922dfedbb428bea48d2800f681f3 | |
151 | Merge: 1b50456 16abcac | |
152 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
153 | Date: Sat Aug 10 10:34:48 2019 +0200 | |
154 | ||
155 | Merge branch 'perfevent' of git://github.com/bytedance/atop into bytedance-perfevent | |
156 | Avoid overhead using perf in VMs. | |
157 | ||
158 | commit 1b504568a4562ce6fca93275898e084a8f832d29 | |
159 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
160 | Date: Sat Aug 3 12:47:11 2019 +0200 | |
161 | ||
162 | Error messages no longer wiped by clear screen | |
163 | By introducing function mcleanstop, error messages are | |
164 | shown after ncurses has closed the window (solves issue #67). | |
165 | ||
166 | M acctproc.c | |
167 | M atop.c | |
168 | M atop.h | |
169 | M atopsar.c | |
170 | M deviate.c | |
171 | M netatopif.c | |
172 | M photoproc.c | |
173 | M photosyst.c | |
174 | M rawlog.c | |
175 | M showlinux.c | |
176 | M various.c | |
177 | ||
178 | commit 1e93ac6a8e486dfda633af049c950040020373c9 | |
179 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
180 | Date: Sat Aug 3 09:52:18 2019 +0200 | |
181 | ||
182 | Exchanged a TAB by spaces in front of statement | |
183 | (TAB was accepted by Python2 but refused by Python3). | |
184 | ||
185 | M atopgpud | |
186 | M man/atopgpud.8 | |
187 | ||
188 | commit 78f99bbfb6d54a420c404fd8c37dc4f48b7f8110 | |
189 | Author: gregg leventhal <gregglev@yahoo.com> | |
190 | Date: Mon Jun 24 16:25:58 2019 -0400 | |
191 | ||
192 | Check if rawlog is a regular, seekable file. If the user does atop -r <(gunzip atop_2019_06_10.gz) for example, a failing lseek will result in a later segfault | |
193 | ||
194 | M rawlog.c | |
195 | ||
196 | commit 16abcac132eec4755373aa673389e67219488844 | |
197 | Author: zhenwei pi <pizhenwei@bytedance.com> | |
198 | Date: Wed Mar 20 14:58:18 2019 +0800 | |
199 | ||
200 | Auto detect hypervisor and apply to perfevents | |
201 | ||
202 | In virtualization case, PMU in guest is emulated by hypervisor, such as | |
203 | vPMU is emulated by KVM. | |
204 | Currently perf in guest has overhead, typically rdpmc/wrmsr cause a lot | |
205 | of vm-exits, and guest will hit a performance drop. atop should be | |
206 | careful while useing perf. | |
207 | ||
208 | Support "perfevents" config in atoprc, which supports 3 modes: | |
209 | "enable": force using perf. | |
210 | "disable": force disable perf. | |
211 | "auto": default mode, atop will detect hypervisor. if atop is running in | |
212 | guest, auto disable perf, otherwise enable perf. | |
213 | ||
214 | Signed-off-by: zhenwei pi <pizhenwei@bytedance.com> | |
215 | ||
216 | M atop.c | |
217 | M photosyst.c | |
218 | ||
219 | commit 7ebca1362e7158c769770006afd61b7e4ec67211 | |
220 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
221 | Date: Fri Jun 7 16:06:30 2019 +0200 | |
222 | ||
223 | Cosmetic changes. | |
224 | ||
225 | M rawlog.c | |
226 | ||
227 | commit b55f28a740258e33206443612be2d4fb80464d96 | |
228 | Merge: a4e3664 25007e9 | |
229 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
230 | Date: Fri Jun 7 15:43:31 2019 +0200 | |
231 | ||
232 | Merge pull request #60 from bytedance/writev-record | |
233 | ||
234 | Use writev to write record data | |
235 | ||
236 | commit 25007e9d927f8d37a9f8659d5d2122435409ee7d | |
237 | Author: zhenwei pi <pizhenwei@bytedance.com> | |
238 | Date: Tue Mar 19 16:18:15 2019 +0800 | |
239 | ||
240 | Use writev to write record data | |
241 | ||
242 | Currently atop writes 3 parts of one raw record by 3 write syscall. | |
243 | atop may be killed during writing record, and continue to append records | |
244 | after the original log. uncompleted record data is generated. Ex, | |
245 | good case : ... rr,scompbuf,pcompbuf ... rr,scompbuf,pcompbuf ... | |
246 | bad case : ... rr,scompbuf[missing] ... rr,scompbuf,pcompbuf ... | |
247 | ||
248 | 1-writev syscall makes writing record as a atomic operation, and make sure | |
249 | each raw record is completed. | |
250 | ||
251 | Signed-off-by: zhenwei pi <pizhenwei@bytedance.com> | |
252 | ||
253 | M rawlog.c | |
254 | ||
255 | commit a4e3664f78d8588136696102bb9624b2ec46a54d | |
256 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
257 | Date: Sun May 26 16:55:01 2019 +0200 | |
258 | ||
259 | Added comment (cosmetic change) | |
260 | ||
261 | M photoproc.c | |
262 | ||
263 | commit 1338f5f47cc4e11b7afe8f6ce5543126754ae416 | |
264 | Merge: b54801c eea28ab | |
265 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
266 | Date: Sun May 26 16:49:16 2019 +0200 | |
267 | ||
268 | Merge pull request #54 from pacepi/use-smaps-rollup | |
269 | ||
270 | Prefer to use smaps_rollup instead of smaps | |
271 | ||
272 | commit b54801ca81c06b073126f7f941db1d922a2f1e1c | |
273 | Merge: fa4db43 e7000f7 | |
274 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
275 | Date: Sun May 26 16:28:08 2019 +0200 | |
276 | ||
277 | Merge pull request #57 from gleventhal/master | |
278 | ||
279 | Fix unchecked opendir to prevent dereferencing a NULL pointer | |
280 | ||
281 | commit e7000f778465cf4e73a60604b799a4b1c0e80b15 | |
282 | Author: gregg leventhal <gregglev@yahoo.com> | |
283 | Date: Thu May 2 15:03:02 2019 -0400 | |
284 | ||
285 | Fix unchecked opendir to prevent dereferrencing a NULL pointer | |
286 | ||
287 | M photoproc.c | |
288 | ||
289 | commit 65fb301d59208692da4fec1ead38e8efbed66c33 | |
290 | Author: Sjon Hortensius <sjon@hortensius.net> | |
291 | Date: Mon Mar 18 13:44:23 2019 +0100 | |
292 | ||
293 | For systemd - replace 5 files with rotate service and timer | |
294 | ||
295 | M Makefile | |
296 | A atop-rotate.service | |
297 | A atop-rotate.timer | |
298 | M atop.service | |
299 | ||
300 | commit eea28abb735cbf941045ade56d2c22657bf014b7 | |
301 | Author: zhenwei pi <pizhenwei@bytedance.com> | |
302 | Date: Mon Jan 28 20:27:47 2019 +0800 | |
303 | ||
304 | Prefer to use smaps_rollup instead of smaps | |
305 | ||
306 | Since Linux-4.14, kernel supports "/proc/PID/smaps_rollup" to count process | |
307 | Pss. | |
308 | Test case on CPU Intel i7-8700K : | |
309 | 1, create a virtual machine with 12G memory. | |
310 | 2, count Pss for 3 time with smaps : 7176, 7221, 7182. | |
311 | average 7193(microseconds). | |
312 | 3, count Pss for 3 time with smaps_rollup : 1963, 1985, 1972. | |
313 | average 1973(microseconds). | |
314 | ||
315 | smaps_rollup has better performence than smaps. We check it in first call, | |
316 | and prefer to use. | |
317 | ||
318 | Signed-off-by: zhenwei pi <pizhenwei@bytedance.com> | |
319 | ||
320 | M photoproc.c | |
321 | ||
322 | commit fa4db436865887f3e451692b9439d2943b4b2936 | |
323 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
324 | Date: Thu Feb 7 12:03:42 2019 +0100 | |
325 | ||
326 | Correction of PSI value 'io full' | |
327 | 'I/O full' showed the same value as 'I/O some', which has been | |
328 | corrected now. | |
329 | ||
330 | M showsys.c | |
331 | ||
332 | commit 58a25af78314d432a7591e536fd2d5b23666ecb4 | |
333 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
334 | Date: Tue Jan 22 17:32:37 2019 +0100 | |
335 | ||
336 | Atopconvert shows version of input file and copies if needed. | |
337 | When only the name of the input file is given, then atopconvert | |
338 | shows the version of the input file. | |
339 | When the version of the input file is already up-to-date, still | |
340 | the input file is copied to the output file. | |
341 | ||
342 | M atopconvert.c | |
343 | M man/atopconvert.1 | |
344 | ||
345 | commit c3073ee609509857620c58aa4d050344b63696a2 | |
346 | Merge: 41333c6 4b0a957 | |
347 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
348 | Date: Sun Jan 13 00:04:29 2019 +0100 | |
349 | ||
350 | Merge branch 'master' of github.com:Atoptool/atop | |
351 | ||
352 | commit 41333c6dab5c16b60d610bfa79f33f1f56793307 | |
353 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
354 | Date: Sat Jan 12 23:43:59 2019 +0100 | |
355 | ||
356 | Various corrections. | |
357 | ||
358 | M rpmspec/atop.specsystemd | |
359 | ||
0 | 360 | commit 3ca52a7c0c9948eedd6ba25a1a902ebc6488a79f |
1 | 361 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> |
2 | 362 | Date: Sat Jan 12 22:31:10 2019 +0100 |
97 | 457 | M showlinux.h |
98 | 458 | M showprocs.c |
99 | 459 | M showsys.c |
460 | ||
461 | commit 4b0a957aed6370c4268d592fa6bef78aa141fe82 | |
462 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> | |
463 | Date: Tue Jan 8 20:06:15 2019 +0100 | |
464 | ||
465 | Not enough entries created to register all tasks. | |
466 | Calculation has been adapted. | |
467 | ||
468 | M atop.c | |
469 | M photoproc.c | |
100 | 470 | |
101 | 471 | commit 8fe68ff3ed14bd25da93ba0480ec116a7f36b731 |
102 | 472 | Author: Gerlof Langeveld <gerlof.langeveld@atoptool.nl> |
11 | 11 | MAN5PATH = /usr/share/man/man5 |
12 | 12 | MAN8PATH = /usr/share/man/man8 |
13 | 13 | INIPATH = /etc/init.d |
14 | DEFPATH = /etc/default | |
14 | 15 | SYSDPATH = /usr/lib/systemd/system |
15 | 16 | CRNPATH = /etc/cron.d |
16 | 17 | ROTPATH = /etc/logrotate.d |
63 | 64 | if [ ! -d $(DESTDIR)$(PMPATHD) ]; \ |
64 | 65 | then mkdir -p $(DESTDIR)$(PMPATHD); fi |
65 | 66 | # |
66 | cp atop.service $(DESTDIR)$(SYSDPATH) | |
67 | chmod 0644 $(DESTDIR)$(SYSDPATH)/atop.service | |
68 | cp atopgpu.service $(DESTDIR)$(SYSDPATH) | |
69 | chmod 0644 $(DESTDIR)$(SYSDPATH)/atopgpu.service | |
70 | cp atopacct.service $(DESTDIR)$(SYSDPATH) | |
71 | chmod 0644 $(DESTDIR)$(SYSDPATH)/atopacct.service | |
72 | cp atop.cronsystemd $(DESTDIR)$(CRNPATH)/atop | |
73 | cp atop-pm.sh $(DESTDIR)$(PMPATHD) | |
74 | chmod 0711 $(DESTDIR)$(PMPATHD)/atop-pm.sh | |
67 | cp atop.service $(DESTDIR)$(SYSDPATH) | |
68 | chmod 0644 $(DESTDIR)$(SYSDPATH)/atop.service | |
69 | cp atopgpu.service $(DESTDIR)$(SYSDPATH) | |
70 | chmod 0644 $(DESTDIR)$(SYSDPATH)/atopgpu.service | |
71 | cp atop-rotate.service $(DESTDIR)$(SYSDPATH) | |
72 | chmod 0644 $(DESTDIR)$(SYSDPATH)/atop-rotate.service | |
73 | cp atop-rotate.timer $(DESTDIR)$(SYSDPATH) | |
74 | chmod 0644 $(DESTDIR)$(SYSDPATH)/atop-rotate.timer | |
75 | cp atopacct.service $(DESTDIR)$(SYSDPATH) | |
76 | chmod 0644 $(DESTDIR)$(SYSDPATH)/atopacct.service | |
77 | cp atop-pm.sh $(DESTDIR)$(PMPATHD) | |
78 | chmod 0711 $(DESTDIR)$(PMPATHD)/atop-pm.sh | |
75 | 79 | # |
76 | 80 | # only when making on target system: |
77 | 81 | # |
78 | 82 | if [ -z "$(DESTDIR)" -a -f /bin/systemctl ]; \ |
79 | then /bin/systemctl stop atop 2> /dev/null; \ | |
80 | /bin/systemctl disable atop 2> /dev/null; \ | |
81 | /bin/systemctl stop atopacct 2> /dev/null; \ | |
82 | /bin/systemctl disable atopacct 2> /dev/null; \ | |
83 | /bin/systemctl enable atopacct; \ | |
84 | /bin/systemctl start atopacct; \ | |
85 | /bin/systemctl enable atop; \ | |
86 | /bin/systemctl start atop; \ | |
83 | then /bin/systemctl disable --now atop 2> /dev/null; \ | |
84 | /bin/systemctl disable --now atopacct 2> /dev/null; \ | |
85 | /bin/systemctl daemon-reload; \ | |
86 | /bin/systemctl enable --now atopacct; \ | |
87 | /bin/systemctl enable --now atop; \ | |
88 | /bin/systemctl enable --now atop-rotate.timer; \ | |
87 | 89 | fi |
88 | 90 | |
89 | 91 | sysvinstall: genericinstall |
90 | 92 | if [ ! -d $(DESTDIR)$(INIPATH) ]; \ |
91 | then mkdir -p $(DESTDIR)$(INIPATH); fi | |
93 | then mkdir -p $(DESTDIR)$(INIPATH); fi | |
94 | if [ ! -d $(DESTDIR)$(SCRPATH) ]; \ | |
95 | then mkdir -p $(DESTDIR)$(SCRPATH); fi | |
96 | if [ ! -d $(DESTDIR)$(CRNPATH) ]; \ | |
97 | then mkdir -p $(DESTDIR)$(CRNPATH); fi | |
98 | if [ ! -d $(DESTDIR)$(ROTPATH) ]; \ | |
99 | then mkdir -p $(DESTDIR)$(ROTPATH); fi | |
92 | 100 | # |
93 | 101 | cp atop.init $(DESTDIR)$(INIPATH)/atop |
94 | 102 | cp atopacct.init $(DESTDIR)$(INIPATH)/atopacct |
95 | 103 | cp atop.cronsysv $(DESTDIR)$(CRNPATH)/atop |
104 | cp atop.daily $(DESTDIR)$(SCRPATH) | |
105 | chmod 0711 $(DESTDIR)$(SCRPATH)/atop.daily | |
106 | cp psaccs_atop $(DESTDIR)$(ROTPATH)/psaccs_atop | |
107 | cp psaccu_atop $(DESTDIR)$(ROTPATH)/psaccu_atop | |
108 | touch $(DESTDIR)$(LOGPATH)/dummy_before | |
109 | touch $(DESTDIR)$(LOGPATH)/dummy_after | |
96 | 110 | # |
97 | 111 | if [ -d $(DESTDIR)$(PMPATH1) ]; \ |
98 | 112 | then cp 45atoppm $(DESTDIR)$(PMPATH1); \ |
129 | 143 | then mkdir -p $(DESTDIR)$(BINPATH); fi |
130 | 144 | if [ ! -d $(DESTDIR)$(SBINPATH) ]; \ |
131 | 145 | then mkdir -p $(DESTDIR)$(SBINPATH); fi |
132 | if [ ! -d $(DESTDIR)$(SCRPATH) ]; \ | |
133 | then mkdir -p $(DESTDIR)$(SCRPATH); fi | |
134 | 146 | if [ ! -d $(DESTDIR)$(MAN1PATH) ]; \ |
135 | 147 | then mkdir -p $(DESTDIR)$(MAN1PATH); fi |
136 | 148 | if [ ! -d $(DESTDIR)$(MAN5PATH) ]; \ |
137 | 149 | then mkdir -p $(DESTDIR)$(MAN5PATH); fi |
138 | 150 | if [ ! -d $(DESTDIR)$(MAN8PATH) ]; \ |
139 | 151 | then mkdir -p $(DESTDIR)$(MAN8PATH); fi |
140 | if [ ! -d $(DESTDIR)$(CRNPATH) ]; \ | |
141 | then mkdir -p $(DESTDIR)$(CRNPATH); fi | |
142 | if [ ! -d $(DESTDIR)$(ROTPATH) ]; \ | |
143 | then mkdir -p $(DESTDIR)$(ROTPATH); fi | |
152 | # | |
153 | touch $(DESTDIR)$(DEFPATH)/atop | |
154 | chmod 644 $(DESTDIR)$(DEFPATH)/atop | |
144 | 155 | # |
145 | 156 | cp atop $(DESTDIR)$(BINPATH)/atop |
146 | 157 | chown root $(DESTDIR)$(BINPATH)/atop |
157 | 168 | cp atopconvert $(DESTDIR)$(BINPATH)/atopconvert |
158 | 169 | chown root $(DESTDIR)$(BINPATH)/atopconvert |
159 | 170 | chmod 0711 $(DESTDIR)$(BINPATH)/atopconvert |
160 | cp atop.daily $(DESTDIR)$(SCRPATH) | |
161 | chmod 0711 $(DESTDIR)$(SCRPATH)/atop.daily | |
162 | 171 | cp man/atop.1 $(DESTDIR)$(MAN1PATH) |
163 | 172 | cp man/atopsar.1 $(DESTDIR)$(MAN1PATH) |
164 | 173 | cp man/atopconvert.1 $(DESTDIR)$(MAN1PATH) |
165 | 174 | cp man/atoprc.5 $(DESTDIR)$(MAN5PATH) |
166 | 175 | cp man/atopacctd.8 $(DESTDIR)$(MAN8PATH) |
167 | 176 | cp man/atopgpud.8 $(DESTDIR)$(MAN8PATH) |
168 | cp psaccs_atop $(DESTDIR)$(ROTPATH)/psaccs_atop | |
169 | cp psaccu_atop $(DESTDIR)$(ROTPATH)/psaccu_atop | |
170 | touch $(DESTDIR)$(LOGPATH)/dummy_before | |
171 | touch $(DESTDIR)$(LOGPATH)/dummy_after | |
172 | 177 | |
173 | 178 | ########################################################################## |
174 | 179 |
221 | 221 | ** open active account file with the specified name |
222 | 222 | */ |
223 | 223 | if (! droprootprivs() ) |
224 | cleanstop(42); | |
224 | mcleanstop(42, "failed to drop root privs\n"); | |
225 | 225 | |
226 | 226 | if ( (acctfd = open(ep, O_RDONLY) ) == -1) |
227 | 227 | return 1; |
256 | 256 | struct flock flock; |
257 | 257 | |
258 | 258 | if (! droprootprivs() ) |
259 | cleanstop(42); | |
259 | mcleanstop(42, "failed to drop root privs\n"); | |
260 | 260 | |
261 | 261 | (void) semop(sempacctpubid, &semclaim, 1); |
262 | 262 | |
549 | 549 | break; |
550 | 550 | |
551 | 551 | default: |
552 | fprintf(stderr, "Unknown format of process accounting file\n"); | |
553 | cleanstop(8); | |
552 | mcleanstop(8, "Unknown format of process accounting file\n"); | |
554 | 553 | } |
555 | 554 | |
556 | 555 | /* |
630 | 629 | (void) rmdir(ACCTDIR); |
631 | 630 | |
632 | 631 | if (! droprootprivs() ) |
633 | cleanstop(42); | |
632 | mcleanstop(42, | |
633 | "failed to drop root privs\n"); | |
634 | 634 | } |
635 | 635 | } |
636 | 636 | |
970 | 970 | (void) acct(ACCTDIR "/" ACCTFILE); |
971 | 971 | |
972 | 972 | if (! droprootprivs() ) |
973 | cleanstop(42); | |
973 | mcleanstop(42, "failed to drop root privs\n"); | |
974 | 974 | |
975 | 975 | acctsize = 0; |
976 | 976 |
0 | [Unit] | |
1 | Description=Restart atop daemon to rotate logs | |
2 | ||
3 | [Service] | |
4 | Type=oneshot | |
5 | ExecStart=/usr/bin/systemctl try-restart atop.service |
0 | [Unit] | |
1 | Description=Daily atop restart | |
2 | ||
3 | [Timer] | |
4 | OnCalendar=daily | |
5 | ||
6 | [Install] | |
7 | WantedBy=timers.target |
390 | 390 | void do_almostcrit(char *, char *); |
391 | 391 | void do_atopsarflags(char *, char *); |
392 | 392 | void do_pacctdir(char *, char *); |
393 | void do_perfevents(char *, char *); | |
393 | 394 | |
394 | 395 | static struct { |
395 | 396 | char *tag; |
437 | 438 | { "swoutcritsec", do_swoutcritsec, 0, }, |
438 | 439 | { "almostcrit", do_almostcrit, 0, }, |
439 | 440 | { "atopsarflags", do_atopsarflags, 0, }, |
441 | { "perfevents", do_perfevents, 0, }, | |
440 | 442 | { "pacctdir", do_pacctdir, 1, }, |
441 | 443 | }; |
442 | 444 | |
695 | 697 | ** effective user-id to real user-id |
696 | 698 | */ |
697 | 699 | if (! droprootprivs() ) |
698 | cleanstop(42); | |
700 | mcleanstop(42, "failed to drop root privs\n"); | |
699 | 701 | |
700 | 702 | /* |
701 | 703 | ** start the engine now ..... |
907 | 909 | |
908 | 910 | do |
909 | 911 | { |
910 | curtlen = counttasks(); | |
912 | curtlen = counttasks(); // worst-case value | |
911 | 913 | curtpres = realloc(curtpres, |
912 | 914 | curtlen * sizeof(struct tstat)); |
913 | 915 | |
914 | ptrverify(curtpres, "Malloc failed for %d tstats\n", | |
916 | ptrverify(curtpres, "Malloc failed for %lu tstats\n", | |
915 | 917 | curtlen); |
916 | 918 | |
917 | 919 | memset(curtpres, 0, curtlen * sizeof(struct tstat)); |
1163 | 1165 | if (tagname[0] == '#') |
1164 | 1166 | continue; |
1165 | 1167 | |
1166 | fprintf(stderr, | |
1168 | mcleanstop(1, | |
1167 | 1169 | "%s: syntax error line " |
1168 | 1170 | "%d (no value specified)\n", |
1169 | 1171 | path, line); |
1170 | 1172 | |
1171 | cleanstop(1); | |
1172 | 1173 | break; /* not reached */ |
1173 | 1174 | |
1174 | 1175 | default: |
1178 | 1179 | if (tagvalue[0] != '#') |
1179 | 1180 | break; |
1180 | 1181 | |
1181 | fprintf(stderr, | |
1182 | mcleanstop(1, | |
1182 | 1183 | "%s: syntax error line " |
1183 | 1184 | "%d (no value specified)\n", |
1184 | 1185 | path, line); |
1185 | ||
1186 | cleanstop(1); | |
1187 | 1186 | } |
1188 | 1187 | |
1189 | 1188 | /* |
163 | 163 | int contcompar(const void *, const void *); |
164 | 164 | |
165 | 165 | count_t subcount(count_t, count_t); |
166 | void rawread(void); | |
166 | int rawread(void); | |
167 | 167 | char rawwrite (time_t, int, |
168 | 168 | struct devtstat *, struct sstat *, |
169 | 169 | int, unsigned int, char); |
174 | 174 | char *getstrvers(void); |
175 | 175 | unsigned short getnumvers(void); |
176 | 176 | void ptrverify(const void *, const char *, ...); |
177 | void mcleanstop(int, const char *, ...); | |
177 | 178 | void cleanstop(int); |
178 | 179 | void prusage(char *); |
179 | 180 |
2 | 2 | Documentation=man:atop(1) |
3 | 3 | |
4 | 4 | [Service] |
5 | Type=simple | |
6 | ExecStart=/usr/share/atop/atop.daily | |
5 | Environment=LOGOPTS="-R" | |
6 | Environment=LOGINTERVAL=600 | |
7 | Environment=LOGGENERATIONS=28 | |
8 | Environment=LOGPATH=/var/log/atop | |
9 | EnvironmentFile=/etc/default/atop | |
10 | ExecStartPre=/bin/sh -c 'test -n "$LOGINTERVAL" -a "$LOGINTERVAL" -eq "$LOGINTERVAL"' | |
11 | ExecStartPre=/bin/sh -c 'test -n "$LOGGENERATIONS" -a "$LOGGENERATIONS" -eq "$LOGGENERATIONS"' | |
12 | ExecStart=/bin/sh -c 'exec /usr/bin/atop ${LOGOPTS} -w "${LOGPATH}/atop_$(date +%%Y%%m%%d)" ${LOGINTERVAL}' | |
13 | ExecStartPost=/usr/bin/find "${LOGPATH}" -name "atop_*" -mtime +${LOGGENERATIONS} -exec rm -v {} \; | |
7 | 14 | KillSignal=SIGUSR2 |
8 | #ExecStopPost=/usr/bin/sleep 3 | |
9 | 15 | |
10 | 16 | [Install] |
11 | 17 | WantedBy=multi-user.target |
66 | 66 | #include "prev/photosyst_24.h" |
67 | 67 | #include "prev/photoproc_24.h" |
68 | 68 | |
69 | #include "prev/photosyst_25.h" | |
70 | #include "prev/photoproc_25.h" | |
71 | ||
69 | 72 | |
70 | 73 | /////////////////////////////////////////////////////////////// |
71 | 74 | // Conversion functions |
233 | 236 | struct sstat_22 sstat_22; |
234 | 237 | struct sstat_23 sstat_23; |
235 | 238 | struct sstat_24 sstat_24; |
239 | struct sstat_25 sstat_25; | |
236 | 240 | struct sstat sstat; |
237 | 241 | |
238 | 242 | struct tstat_20 tstat_20; |
240 | 244 | struct tstat_22 tstat_22; |
241 | 245 | struct tstat_23 tstat_23; |
242 | 246 | struct tstat_24 tstat_24; |
247 | struct tstat_25 tstat_25; | |
243 | 248 | struct tstat tstat; |
244 | 249 | |
245 | 250 | struct convertall { |
417 | 422 | STROFFSET(&tstat_24.net, &tstat_24), justcopy}, |
418 | 423 | {sizeof(struct gpu_24), |
419 | 424 | STROFFSET(&tstat_24.gpu, &tstat_24), justcopy}, |
425 | }, | |
426 | ||
427 | {SETVERSION(2,5), // 2.4 --> 2.5 | |
428 | sizeof(struct sstat_25), &sstat_25, | |
429 | sizeof(struct tstat_25), NULL, | |
430 | ||
431 | {sizeof(struct cpustat_25), &sstat_25.cpu, justcopy}, | |
432 | {sizeof(struct memstat_25), &sstat_25.mem, justcopy}, | |
433 | {sizeof(struct netstat_25), &sstat_25.net, justcopy}, | |
434 | {sizeof(struct intfstat_25), &sstat_25.intf, justcopy}, | |
435 | {sizeof(struct dskstat_25), &sstat_25.dsk, justcopy}, | |
436 | {sizeof(struct nfsstat_25), &sstat_25.nfs, justcopy}, | |
437 | {sizeof(struct contstat_25), &sstat_25.cfs, justcopy}, | |
438 | {sizeof(struct wwwstat_25), &sstat_25.www, justcopy}, | |
439 | {sizeof(struct pressure_25), &sstat_25.psi, justcopy}, | |
440 | {sizeof(struct gpustat_25), &sstat_25.gpu, justcopy}, | |
441 | {sizeof(struct ifbstat_25), &sstat_25.ifb, justcopy}, | |
442 | ||
443 | {sizeof(struct gen_25), | |
444 | STROFFSET(&tstat_25.gen, &tstat_25), justcopy}, | |
445 | {sizeof(struct cpu_25), | |
446 | STROFFSET(&tstat_25.cpu, &tstat_25), justcopy}, | |
447 | {sizeof(struct dsk_25), | |
448 | STROFFSET(&tstat_25.dsk, &tstat_25), justcopy}, | |
449 | {sizeof(struct mem_25), | |
450 | STROFFSET(&tstat_25.mem, &tstat_25), justcopy}, | |
451 | {sizeof(struct net_25), | |
452 | STROFFSET(&tstat_25.net, &tstat_25), justcopy}, | |
453 | {sizeof(struct gpu_25), | |
454 | STROFFSET(&tstat_25.gpu, &tstat_25), justcopy}, | |
420 | 455 | }, |
421 | 456 | }; |
422 | 457 | |
499 | 534 | static void writesamp(int, struct rawrecord *, void *, int, void *, |
500 | 535 | int, int); |
501 | 536 | |
537 | static void copy_file(int, int); | |
502 | 538 | static void convert_samples(int, int, struct rawheader *, int, int); |
503 | 539 | static void do_sconvert(struct sconvstruct *, struct sconvstruct *); |
504 | 540 | static void do_tconvert(void *, void *, |
520 | 556 | // verify the command line arguments: |
521 | 557 | // optional flags and mandatory input and output filename |
522 | 558 | // |
523 | if (argc < 3) | |
559 | if (argc < 2) | |
524 | 560 | prusage(argv[0]); |
525 | 561 | |
526 | 562 | while ((c = getopt(argc, argv, "?t:")) != EOF) |
566 | 602 | } |
567 | 603 | } |
568 | 604 | |
569 | if (optind < argc-2) | |
605 | if (optind >= argc) | |
570 | 606 | prusage(argv[0]); |
571 | 607 | |
572 | 608 | infile = argv[optind++]; |
573 | outfile = argv[optind++]; | |
574 | ||
575 | if (strcmp(infile, outfile) == 0) | |
576 | { | |
577 | fprintf(stderr, | |
578 | "input file and output file should not be identical!\n"); | |
579 | exit(12); | |
580 | } | |
581 | 609 | |
582 | 610 | // determine target version (default: latest version) |
583 | 611 | // |
632 | 660 | exit(11); |
633 | 661 | } |
634 | 662 | |
635 | if (versionix >= targetix) | |
636 | { | |
637 | fprintf(stderr, | |
638 | "This version is already up-to-date!\n"); | |
639 | exit(0); | |
663 | if (versionix > targetix) | |
664 | { | |
665 | fprintf(stderr, "Downgrading of version is not supported!\n"); | |
666 | exit(11); | |
640 | 667 | } |
641 | 668 | |
642 | 669 | if (irh.sstatlen != convs[versionix].sstatlen || |
652 | 679 | exit(11); |
653 | 680 | } |
654 | 681 | |
682 | // handle the output file | |
683 | // | |
684 | if (optind >= argc) | |
685 | exit(0); | |
686 | ||
687 | outfile = argv[optind++]; | |
688 | ||
689 | if (strcmp(infile, outfile) == 0) | |
690 | { | |
691 | fprintf(stderr, | |
692 | "input file and output file should not be identical!\n"); | |
693 | exit(12); | |
694 | } | |
695 | ||
655 | 696 | // open the output file |
656 | 697 | // |
657 | 698 | if ( (ofd = openout(outfile)) == -1) |
673 | 714 | printf("Version of %s: %d.%d\n", outfile, |
674 | 715 | (orh.aversion >> 8) & 0x7f, orh.aversion & 0xff); |
675 | 716 | |
676 | // copy and convert every sample | |
677 | // | |
678 | convert_samples(ifd, ofd, &irh, versionix, targetix); | |
717 | // copy and convert every sample, unless the version of the | |
718 | // input file is identical to the target version (then just copy) | |
719 | // | |
720 | if (versionix < targetix) | |
721 | convert_samples(ifd, ofd, &irh, versionix, targetix); | |
722 | else | |
723 | copy_file(ifd, ofd); | |
724 | ||
725 | close(ifd); | |
726 | close(ofd); | |
679 | 727 | |
680 | 728 | return 0; |
681 | 729 | } |
823 | 871 | } |
824 | 872 | } |
825 | 873 | |
874 | ||
875 | // | |
876 | // Function to copy input file transparently to output file | |
877 | // | |
878 | static void | |
879 | copy_file(int ifd, int ofd) | |
880 | { | |
881 | unsigned char buf[64*1024]; | |
882 | int nr, nw; | |
883 | ||
884 | (void) lseek(ifd, 0, SEEK_SET); | |
885 | (void) lseek(ofd, 0, SEEK_SET); | |
886 | ||
887 | while ( (nr = read(ifd, buf, sizeof buf)) > 0) | |
888 | { | |
889 | if ( (nw = write(ofd, buf, nr)) < nr) | |
890 | { | |
891 | if (nw == -1) | |
892 | { | |
893 | perror("write output file"); | |
894 | exit(42); | |
895 | } | |
896 | else | |
897 | { | |
898 | fprintf(stderr, | |
899 | "Output file saturated\n"); | |
900 | exit(42); | |
901 | } | |
902 | } | |
903 | } | |
904 | ||
905 | if (nr == -1) | |
906 | { | |
907 | perror("read input file"); | |
908 | exit(42); | |
909 | } | |
910 | else | |
911 | { | |
912 | printf("Raw file copied (version already up-to-date)\n"); | |
913 | } | |
914 | } | |
915 | ||
826 | 916 | // |
827 | 917 | // Function that opens an existing raw file and |
828 | 918 | // verifies the magic number |
910 | 1000 | prusage(char *name) |
911 | 1001 | { |
912 | 1002 | fprintf(stderr, |
913 | "Usage: %s [-t version] rawinput rawoutput\n", name); | |
1003 | "Usage: %s [-t version] rawinput [rawoutput]\n", name); | |
914 | 1004 | fprintf(stderr, |
915 | "\t\t-t version target version (default: %d.%d) for output\n", | |
1005 | "\t-t version target version (default: %d.%d) for output\n", | |
916 | 1006 | (convs[numconvs-1].version >> 8) & 0x7f, |
917 | 1007 | convs[numconvs-1].version & 0x7f); |
918 | 1008 |
180 | 180 | self.stats.procstats[pid].memcum += proc.usedGpuMemory//1024 |
181 | 181 | self.stats.procstats[pid].sample += 1 |
182 | 182 | |
183 | if self.stats.tasksupport & ACCOUNT: | |
183 | if self.stats.tasksupport & ACCOUNT: | |
184 | 184 | try: |
185 | 185 | stats = pynvml.nvmlDeviceGetAccountingStats(self.gpuhandle, pid) |
186 | 186 |
317 | 317 | prinow = i; |
318 | 318 | daylim = 0; |
319 | 319 | begintime = saved_begintime; |
320 | rawread(); | |
320 | ||
321 | if (!rawread()) // reading from named pipe | |
322 | break; // can only be done once | |
323 | ||
321 | 324 | printf("\n"); |
322 | 325 | } |
323 | 326 | } |
383 | 386 | ** effective user-id to real user-id |
384 | 387 | */ |
385 | 388 | if (! droprootprivs() ) |
386 | cleanstop(42); | |
389 | mcleanstop(42, "failed to drop root privs\n"); | |
387 | 390 | |
388 | 391 | /* |
389 | 392 | ** start live reporting |
933 | 933 | initifprop(); /* refresh interface info */ |
934 | 934 | |
935 | 935 | if (! droprootprivs()) /* drop setuid-root privs */ |
936 | cleanstop(42); | |
936 | mcleanstop(42, "failed to drop root privs\n"); | |
937 | 937 | |
938 | 938 | for (i=0; cur->intf.intf[i].name[0]; i++) |
939 | 939 | { |
0 | .TH ATOP 1 "January 2019" "Linux" | |
0 | .TH ATOP 1 "November 2019" "Linux" | |
1 | 1 | .SH NAME |
2 | 2 | .B atop |
3 | 3 | - Advanced System & Process Monitor |
685 | 685 | .TP 5 |
686 | 686 | .B T |
687 | 687 | When viewing the contents of a raw file, this key can be used to show the |
688 | previous sample from the file. | |
688 | previous sample from the file (except when reading raw data from a named pipe). | |
689 | 689 | .PP |
690 | 690 | .TP 5 |
691 | 691 | .B b |
692 | 692 | When viewing the contents of a raw file, this key can be used to branch |
693 | to a certain timestamp within the file (either forward or backward). | |
693 | to a certain timestamp within the file either forward or backward | |
694 | (except when reading raw data from a named pipe). | |
694 | 695 | .PP |
695 | 696 | .TP 5 |
696 | 697 | .B r |
698 | 699 | boot again. |
699 | 700 | |
700 | 701 | When viewing the contents of a raw file, this key can be used to rewind |
701 | to the beginning of the file again. | |
702 | to the beginning of the file again | |
703 | (except when reading raw data from a named pipe). | |
702 | 704 | .PP |
703 | 705 | .TP 5 |
704 | 706 | .B U |
924 | 926 | (end time) followed by a time argument of the form HH:MM, |
925 | 927 | a certain time period within the raw file can be selected. |
926 | 928 | .PP |
927 | When | |
929 | Every day at midnight | |
928 | 930 | .B atop |
929 | is installed, the script | |
930 | .B atop.daily | |
931 | is stored in the | |
932 | .I /usr/share/atop | |
933 | directory. | |
934 | This scripts takes care that | |
935 | .B atop | |
936 | is activated every day at midnight to write compressed binary data to the file | |
931 | is restarted to write compressed binary data to the file | |
937 | 932 | .BI /var/log/atop/atop_ YYYYMMDD |
938 | 933 | with an interval of 10 minutes by default. The |
939 | 934 | .B -R |
940 | 935 | flag is passed by default to gather information about the proportional |
941 | 936 | set size of every process. |
942 | 937 | .br |
943 | Furthermore the script removes all raw files which are by default | |
944 | older than 28 days. | |
945 | .br | |
946 | The mentioned default values can be overruled by creating the file | |
938 | Furthermore all raw files are removed that are older than 28 days | |
939 | (by default). | |
940 | .br | |
941 | The mentioned default values can be overruled in the file | |
947 | 942 | .B /etc/default/atop |
948 | 943 | that might contain other values for |
949 | 944 | .B LOGOPTS |
951 | 946 | .B -R |
952 | 947 | flag), |
953 | 948 | .B LOGINTERVAL |
954 | (in seconds, by default 600), and | |
949 | (in seconds, by default 600), | |
955 | 950 | .B LOGGENERATIONS |
956 | (in days, by default 28). | |
957 | .PP | |
958 | The | |
959 | .B atop.daily | |
960 | script is activated via the | |
961 | .B cron | |
962 | daemon using the file | |
963 | .I /etc/cron.d/atop | |
964 | with the contents | |
965 | .br | |
966 | .B \ \ \ \ \ \ \ \ 0 0 * * * root /usr/share/atop/atop.daily | |
967 | .PP | |
968 | When the package | |
969 | .B psacct | |
970 | is installed, the process accounting is automatically restarted via the | |
971 | .B logrotate | |
972 | mechanism. The file | |
973 | .B /etc/logrotate.d/psaccs_atop | |
974 | takes care that | |
975 | .B atop | |
976 | is finished just before the rotation of the process accounting file | |
977 | and the file | |
978 | .B /etc/logrotate.d/psaccu_atop | |
979 | takes care that | |
980 | .B atop | |
981 | is restarted again after the rotation. | |
982 | When the package | |
983 | .B psacct | |
984 | is not installed, these logrotate-files have no effect. | |
951 | (in days, by default 28), and | |
952 | .B LOGPATH | |
953 | (directory in which logfiles are stored). | |
985 | 954 | .PP |
986 | 955 | Unfortunately, it is not always possible to keep the format of the raw files |
987 | 956 | compatible in newer versions of |
1114 | 1083 | .I average |
1115 | 1084 | instructions per cycle and number of cycles is shown in the CPU line |
1116 | 1085 | for all CPUs. |
1086 | .br | |
1087 | Beware that reading the cycle counter in virtual machines (guests) might | |
1088 | introduce performance delays. Therefore this metric is by default disabled | |
1089 | in virtual machines. However, with the keyword 'perfevents' in the atoprc file | |
1090 | this metric can be explicitly set to 'enable' or 'disable' | |
1091 | (see separate man-page of atoprc). | |
1117 | 1092 | .br |
1118 | 1093 | See also: http://www.brendangregg.com/blog/2017-05-09/cpu-utilization-is-wrong.html |
1119 | 1094 | |
2381 | 2356 | Configuration file to overrule the settings of |
2382 | 2357 | .I atop |
2383 | 2358 | that runs in the background to create the daily logfile. |
2384 | This file is not created or overwritten when | |
2385 | .I atop | |
2386 | is installed, so it has to be created manually to override | |
2387 | the default settings. | |
2359 | This file is created when | |
2360 | .I atop | |
2361 | is installed. | |
2388 | 2362 | The default settings are: |
2389 | 2363 | .TP 8 |
2390 | 2364 | \ |
2400 | 2374 | Raw file, where |
2401 | 2375 | .I YYYYMMDD |
2402 | 2376 | are digits representing the current date. |
2403 | This name is used by the script | |
2404 | .B atop.daily | |
2405 | as default name for the output file, and by | |
2377 | This name is used by | |
2378 | .B atop | |
2379 | running in the background as default name for the output file, and by | |
2406 | 2380 | .B atop |
2407 | 2381 | as default name for the input file when using the |
2408 | 2382 | .B -r |
0 | .TH ATOPACCTD 8 "June 2018" "Linux" | |
0 | .TH ATOPACCTD 8 "November 2019" "Linux" | |
1 | 1 | .SH NAME |
2 | 2 | .B atopacctd |
3 | 3 | - process accounting daemon |
0 | .TH ATOPCONVERT 1 "January 2019" "Linux" | |
0 | .TH ATOPCONVERT 1 "November 2019" "Linux" | |
1 | 1 | .SH NAME |
2 | 2 | .B atopconvert |
3 | 3 | - convert raw log file to newer version |
6 | 6 | .B atopconvert |
7 | 7 | [\-t |
8 | 8 | .I version |
9 | ] rawinput rawoutput | |
9 | ] rawinput [rawoutput] | |
10 | 10 | .P |
11 | 11 | .SH DESCRIPTION |
12 | 12 | The program |
13 | 13 | .I atopconvert |
14 | 14 | can be used to convert the layout of a raw log file to a newer version. |
15 | The only mandatory arguments are the name of the raw input file to be converted | |
16 | and the name of the raw output file. The program | |
15 | The only mandatory argument is the name of the raw input file. When no | |
16 | output file is specified on the command line, | |
17 | 17 | .I atopconvert |
18 | verifies the version of the input file and converts it (by default) to | |
19 | the format used by the newest version of | |
18 | only shows the version of the input file. | |
19 | When the name of an output file is specified, the input file will | |
20 | be converted to the output file, or just copied when the input file | |
21 | already has the required version. | |
22 | ||
23 | The program | |
24 | .I atopconvert | |
25 | converts the input file (by default) to the format used by the | |
26 | newest version of | |
20 | 27 | .I atop |
21 | 28 | and writes to the output file. With the |
22 | 29 | .B -t |
31 | 38 | or can even be extended by that |
32 | 39 | .I atop |
33 | 40 | version. |
34 | .PP | |
41 | .SH NOTES | |
35 | 42 | The raw input file should be at least of version 2.0! |
43 | ||
44 | Files can only be upgraded to higher version, but not downgraded. | |
36 | 45 | .SH SEE ALSO |
37 | 46 | .B atop(1), |
38 | 47 | .B atopsar(1) |
0 | .TH ATOPGPUD 8 "January 2019" "Linux" | |
0 | .TH ATOPGPUD 8 "November 2019" "Linux" | |
1 | 1 | .SH NAME |
2 | 2 | .B atopgpud |
3 | 3 | - GPU statistics daemon |
117 | 117 | while the subsequent three bytes indicate the length (big endian order) of the |
118 | 118 | response string that follows. |
119 | 119 | .br |
120 | In the reponse strings the character '@' introduces system level information | |
120 | In the response strings the character '@' introduces system level information | |
121 | 121 | of one specific GPU and the character '#' introduces process level information |
122 | 122 | related to that GPU. |
123 | 123 | .br |
0 | .TH ATOPRC 5 "January 2019" "Linux" | |
0 | .TH ATOPRC 5 "November 2019" "Linux" | |
1 | 1 | .SH NAME |
2 | 2 | .B atoprc |
3 | 3 | - atop/atopsar related rcfile |
191 | 191 | can be defined here. The flags that are allowed |
192 | 192 | are 'S', 'x', 'C', 'M', 'H', 'a', 'A' and the flags to select |
193 | 193 | one or more specific reports. |
194 | .PP | |
195 | .TP 4 | |
196 | .B perfevents | |
197 | Defines whether or not the CPU cycle counter should be retrieved | |
198 | by | |
199 | .B atop | |
200 | via the 'perf' counters. The values 'auto' (default), 'enable' | |
201 | or 'disable' can be specified. In case of 'auto', the CPU cycle | |
202 | counter will not be retrieved on virtual machines due to the | |
203 | overhead of reading this counter in a guest. | |
194 | 204 | .PP |
195 | 205 | .TP 4 |
196 | 206 | .B pacctdir |
0 | .TH ATOPSAR 1 "January 2019" "Linux" | |
0 | .TH ATOPSAR 1 "November 2019" "Linux" | |
1 | 1 | .SH NAME |
2 | 2 | .B atopsar |
3 | 3 | - Advanced System Activity Report (atop related) |
209 | 209 | kill(nahp->mypid, SIGHUP); |
210 | 210 | |
211 | 211 | if (! droprootprivs()) |
212 | cleanstop(42); | |
212 | mcleanstop(42, "failed to drop root privs\n"); | |
213 | 213 | |
214 | 214 | (void) munmap(nahp, sizeof *nahp); |
215 | 215 | (void) close(netexitfd); |
247 | 247 | memset(&tp->net, 0, sizeof tp->net); |
248 | 248 | |
249 | 249 | if (! droprootprivs()) |
250 | cleanstop(42); | |
250 | mcleanstop(42, "failed to drop root privs\n"); | |
251 | 251 | |
252 | 252 | if (errno == ENOPROTOOPT || errno == EPERM) |
253 | 253 | { |
261 | 261 | } |
262 | 262 | |
263 | 263 | if (! droprootprivs()) |
264 | cleanstop(42); | |
264 | mcleanstop(42, "failed to drop root privs\n"); | |
265 | 265 | |
266 | 266 | /* |
267 | 267 | ** statistics available: fill counters |
301 | 301 | */ |
302 | 302 | if (getsockopt(netsock, SOL_IP, NETATOP_FORCE_GC, NULL, &socklen)!=0) { |
303 | 303 | if (! droprootprivs()) |
304 | cleanstop(42); | |
304 | mcleanstop(42, "failed to drop root privs\n"); | |
305 | 305 | |
306 | 306 | if (errno == ENOPROTOOPT || errno == EPERM) |
307 | 307 | { |
320 | 320 | */ |
321 | 321 | if (getsockopt(netsock, SOL_IP, NETATOP_EMPTY_EXIT, 0, &socklen) !=0) { |
322 | 322 | if (! droprootprivs()) |
323 | cleanstop(42); | |
323 | mcleanstop(42, "failed to drop root privs\n"); | |
324 | 324 | |
325 | 325 | if (errno == ENOPROTOOPT || errno == EPERM) |
326 | 326 | { |
334 | 334 | } |
335 | 335 | |
336 | 336 | if (! droprootprivs()) |
337 | cleanstop(42); | |
337 | mcleanstop(42, "failed to drop root privs\n"); | |
338 | 338 | |
339 | 339 | /* |
340 | 340 | ** verify how many exited processes are available to be read |
199 | 199 | } |
200 | 200 | |
201 | 201 | if (! droprootprivs()) |
202 | cleanstop(42); | |
202 | mcleanstop(42, "failed to drop root privs\n"); | |
203 | 203 | |
204 | 204 | /* |
205 | 205 | ** find epoch time of boot moment |
218 | 218 | netatop_probe(); |
219 | 219 | |
220 | 220 | if (! droprootprivs()) |
221 | cleanstop(42); | |
221 | mcleanstop(42, "failed to drop root privs\n"); | |
222 | 222 | |
223 | 223 | /* |
224 | 224 | ** read all subdirectory-names below the /proc directory |
225 | 225 | */ |
226 | 226 | if ( getcwd(origdir, sizeof origdir) == NULL) |
227 | { | |
228 | perror("save current dir"); | |
229 | cleanstop(53); | |
230 | } | |
227 | mcleanstop(53, "failed to save current dir\n"); | |
231 | 228 | |
232 | 229 | if ( chdir("/proc") == -1) |
233 | { | |
234 | perror("change to /proc"); | |
235 | cleanstop(54); | |
236 | } | |
230 | mcleanstop(54, "failed to change to /proc\n"); | |
237 | 231 | |
238 | 232 | dirp = opendir("."); |
239 | 233 | |
310 | 304 | { |
311 | 305 | dirtask = opendir("."); |
312 | 306 | |
307 | /* | |
308 | ** due to race condition, opendir() might | |
309 | ** have failed (leave task and process-level | |
310 | ** directories) | |
311 | */ | |
312 | if( dirtask == NULL ) | |
313 | { | |
314 | if(chdir("../..") == -1); | |
315 | continue; | |
316 | } | |
317 | ||
313 | 318 | while ((tent=readdir(dirtask)) && tval<maxtask) |
314 | 319 | { |
315 | 320 | struct tstat *curthr = tasklist+tval; |
340 | 345 | } |
341 | 346 | |
342 | 347 | strcpy(curthr->gen.container, |
343 | curtask->gen.container); | |
348 | curtask->gen.container); | |
344 | 349 | |
345 | 350 | switch (curthr->gen.state) |
346 | 351 | { |
359 | 364 | |
360 | 365 | // read network stats from netatop |
361 | 366 | netatop_gettask(curthr->gen.pid, 't', |
362 | curthr); | |
367 | curthr); | |
363 | 368 | |
364 | 369 | // all stats read now |
365 | 370 | tval++; /* increment thread-level */ |
377 | 382 | closedir(dirp); |
378 | 383 | |
379 | 384 | if ( chdir(origdir) == -1) |
380 | { | |
381 | perror(origdir); | |
382 | cleanstop(55); | |
383 | } | |
385 | mcleanstop(55, "cannot change to %s\n", origdir); | |
384 | 386 | |
385 | 387 | if (dockstat) |
386 | 388 | supportflags |= DOCKSTAT; |
412 | 414 | if ( fgets(linebuf, sizeof(linebuf), fp) != NULL) |
413 | 415 | { |
414 | 416 | if ( sscanf(linebuf, "%*f %*f %*f %*d/%lu", &nr) < 1) |
415 | cleanstop(53); | |
417 | mcleanstop(53, "wrong /proc/loadavg\n"); | |
416 | 418 | } |
417 | 419 | else |
418 | cleanstop(53); | |
420 | mcleanstop(53, "unreadable /proc/loadavg\n"); | |
419 | 421 | |
420 | 422 | fclose(fp); |
421 | 423 | } |
422 | 424 | else |
423 | cleanstop(53); | |
425 | mcleanstop(53, "can not open /proc/loadavg\n"); | |
424 | 426 | |
425 | 427 | |
426 | 428 | /* |
427 | 429 | ** add total number of processes |
428 | 430 | */ |
429 | 431 | if ( getcwd(origdir, sizeof origdir) == NULL) |
430 | cleanstop(53); | |
432 | mcleanstop(53, "cannot determine cwd\n"); | |
431 | 433 | |
432 | 434 | if ( chdir("/proc") == -1) |
433 | cleanstop(53); | |
435 | mcleanstop(53, "cannot change to /proc\n"); | |
434 | 436 | |
435 | 437 | dirp = opendir("."); |
436 | 438 | |
446 | 448 | closedir(dirp); |
447 | 449 | |
448 | 450 | if ( chdir(origdir) == -1) |
449 | cleanstop(53); | |
451 | mcleanstop(53, "cannot change to %s\n", origdir); | |
450 | 452 | |
451 | 453 | return nr; |
452 | 454 | } |
716 | 718 | } |
717 | 719 | |
718 | 720 | if (! droprootprivs()) |
719 | cleanstop(42); | |
721 | mcleanstop(42, "failed to drop root privs\n"); | |
720 | 722 | } |
721 | 723 | |
722 | 724 | return 1; |
762 | 764 | |
763 | 765 | |
764 | 766 | /* |
765 | ** store the Docker container ID, retrieved from the cpuset | |
766 | ** that could look like this: | |
767 | ** store the Docker container ID, retrieved from the 'cpuset' | |
768 | ** that might look like this: | |
767 | 769 | ** /system.slice/docker-af78216c2a230f1aa5dce56cbf[SNAP].scope (e.g. CentOS) |
768 | 770 | ** /docker/af78216c2a230f1aa5dce56cbf[SNAP] (e.g. openSUSE and Ubuntu)) |
771 | ** | |
772 | ** docker created by k8s might look like this: | |
773 | ** /kubepods/burstable/pod07dbb922-[SNAP]/223dc5e15b[SNAP] | |
774 | ** | |
775 | ** In general: | |
776 | ** - search for last '/' (basename) | |
777 | ** - check if '/' followed by 'docker-': then skip 'docker-' | |
778 | ** - take 12 positions for the container ID | |
779 | ** | |
780 | ** Return value: | |
781 | ** 0 - no container | |
782 | ** 1 - container | |
769 | 783 | */ |
770 | #define CIDPREFIX "docker" | |
771 | 784 | #define CIDSIZE 12 |
785 | #define SHA256SIZE 64 | |
786 | #define DOCKPREFIX "docker-" | |
772 | 787 | |
773 | 788 | static int |
774 | 789 | proccont(struct tstat *curtask) |
775 | 790 | { |
776 | FILE *fp; | |
777 | char line[80]; | |
791 | FILE *fp; | |
792 | char line[256]; | |
778 | 793 | |
779 | 794 | if ( (fp = fopen("cpuset", "r")) != NULL) |
780 | 795 | { |
782 | 797 | |
783 | 798 | if ( fgets(line, sizeof line, fp) ) |
784 | 799 | { |
785 | // default string (so if not used) is "/" | |
786 | if (line[1] && (p = strstr(line, CIDPREFIX)) ) | |
800 | fclose(fp); | |
801 | ||
802 | // fast check for processes not using cpuset | |
803 | // i.e. anyhow not container | |
804 | if (memcmp(line, "/\n", 3) == 0) | |
805 | return 0; | |
806 | ||
807 | // possibly container: find basename in path and | |
808 | // verify that its minimum length is the size of SHA256 | |
809 | if ( (p = strrchr(line, '/')) != NULL && | |
810 | strlen(p) >= SHA256SIZE) | |
787 | 811 | { |
788 | memcpy(curtask->gen.container, | |
789 | p + sizeof CIDPREFIX, CIDSIZE); | |
790 | ||
791 | fclose(fp); | |
812 | p++; | |
813 | ||
814 | if (memcmp(p, DOCKPREFIX, | |
815 | sizeof(DOCKPREFIX)-1) == 0) | |
816 | p += sizeof(DOCKPREFIX)-1; | |
817 | ||
818 | memcpy(curtask->gen.container, p, CIDSIZE); | |
792 | 819 | return 1; |
793 | 820 | } |
794 | 821 | } |
795 | ||
796 | fclose(fp); | |
822 | else | |
823 | { | |
824 | fclose(fp); | |
825 | } | |
797 | 826 | } |
798 | 827 | |
799 | 828 | return 0; |
802 | 831 | |
803 | 832 | /* |
804 | 833 | ** open file "smaps" and obtain required info |
834 | ** since Linux-4.14, kernel supports "smaps_rollup" which has better | |
835 | ** performence. check "smaps_rollup" in first call | |
836 | ** if kernel supports "smaps_rollup", use "smaps_rollup" instead | |
805 | 837 | */ |
806 | 838 | static void |
807 | 839 | procsmaps(struct tstat *curtask) |
809 | 841 | FILE *fp; |
810 | 842 | char line[4096]; |
811 | 843 | count_t pssval; |
812 | ||
813 | ||
844 | static int procsmaps_firstcall = 1; | |
845 | static char *smapsfile = "smaps"; | |
846 | ||
847 | if (procsmaps_firstcall) | |
848 | { | |
849 | regainrootprivs(); | |
850 | if ( (fp = fopen("/proc/1/smaps_rollup", "r")) ) | |
851 | { | |
852 | smapsfile = "smaps_rollup"; | |
853 | fclose(fp); | |
854 | } | |
855 | ||
856 | procsmaps_firstcall = 0; | |
857 | } | |
814 | 858 | /* |
815 | 859 | ** open the file (always succeeds, even if no root privs) |
816 | 860 | */ |
817 | 861 | regainrootprivs(); |
818 | 862 | |
819 | if ( (fp = fopen("smaps", "r")) ) | |
863 | if ( (fp = fopen(smapsfile, "r")) ) | |
820 | 864 | { |
821 | 865 | curtask->mem.pmem = 0; |
822 | 866 | |
844 | 888 | } |
845 | 889 | |
846 | 890 | if (! droprootprivs()) |
847 | cleanstop(42); | |
891 | mcleanstop(42, "failed to drop root privs\n"); | |
848 | 892 | } |
193 | 193 | #define MDDTYPE 2 |
194 | 194 | #define LVMTYPE 3 |
195 | 195 | |
196 | /* hypervisor enum */ | |
197 | enum { | |
198 | HYPER_NONE = 0, | |
199 | HYPER_XEN, | |
200 | HYPER_KVM, | |
201 | HYPER_MSHV, | |
202 | HYPER_VMWARE, | |
203 | HYPER_IBM, | |
204 | HYPER_VSERVER, | |
205 | HYPER_UML, | |
206 | HYPER_INNOTEK, | |
207 | HYPER_HITACHI, | |
208 | HYPER_PARALLELS, | |
209 | HYPER_VBOX, | |
210 | HYPER_OS400, | |
211 | HYPER_PHYP, | |
212 | HYPER_SPAR, | |
213 | HYPER_WSL, | |
214 | }; | |
215 | ||
196 | 216 | #ifndef NOPERFEVENT |
217 | enum { | |
218 | PERF_EVENTS_AUTO = 0, | |
219 | PERF_EVENTS_ENABLE, | |
220 | PERF_EVENTS_DISABLE, | |
221 | }; | |
222 | ||
223 | static int perfevents = PERF_EVENTS_AUTO; | |
197 | 224 | static void getperfevents(struct cpustat *); |
198 | 225 | #endif |
199 | 226 | |
201 | 228 | |
202 | 229 | static int isdisk(unsigned int, unsigned int, |
203 | 230 | char *, struct perdsk *, int); |
231 | ||
232 | static int run_in_guest(void); | |
204 | 233 | |
205 | 234 | static struct ipv6_stats ipv6_tmp; |
206 | 235 | static struct icmpv6_stats icmpv6_tmp; |
299 | 328 | memset(si, 0, sizeof(struct sstat)); |
300 | 329 | |
301 | 330 | if ( getcwd(origdir, sizeof origdir) == NULL) |
302 | { | |
303 | perror("save current dir"); | |
304 | cleanstop(53); | |
305 | } | |
331 | mcleanstop(54, "failed to save current dir\n"); | |
306 | 332 | |
307 | 333 | if ( chdir("/proc") == -1) |
308 | { | |
309 | perror("change to /proc"); | |
310 | cleanstop(54); | |
311 | } | |
312 | ||
334 | mcleanstop(54, "failed to change to /proc\n"); | |
313 | 335 | |
314 | 336 | /* |
315 | 337 | ** gather various general statistics from the file /proc/stat and |
1291 | 1313 | } |
1292 | 1314 | |
1293 | 1315 | if (! droprootprivs()) |
1294 | cleanstop(42); | |
1316 | mcleanstop(42, "failed to drop root privs\n"); | |
1295 | 1317 | |
1296 | 1318 | /* |
1297 | 1319 | ** pressure statistics in /proc/pressure (>= 4.20) |
1378 | 1400 | } |
1379 | 1401 | |
1380 | 1402 | if ( chdir("..") == -1) |
1381 | { | |
1382 | perror("return to /proc"); | |
1383 | cleanstop(54); | |
1384 | } | |
1403 | mcleanstop(54, "failed to return to /proc\n"); | |
1385 | 1404 | } |
1386 | 1405 | else |
1387 | 1406 | { |
1494 | 1513 | ** return to original directory |
1495 | 1514 | */ |
1496 | 1515 | if ( chdir(origdir) == -1) |
1497 | { | |
1498 | perror(origdir); | |
1499 | cleanstop(55); | |
1500 | } | |
1516 | mcleanstop(55, "failed to change to %s\n", origdir); | |
1501 | 1517 | |
1502 | 1518 | #ifndef NOPERFEVENT |
1503 | 1519 | /* |
2055 | 2071 | ** instructions and cycles per CPU |
2056 | 2072 | */ |
2057 | 2073 | #ifndef NOPERFEVENT |
2074 | ||
2075 | void | |
2076 | do_perfevents(char *tagname, char *tagvalue) | |
2077 | { | |
2078 | if (!strcmp("enable", tagvalue)) | |
2079 | perfevents = PERF_EVENTS_ENABLE; | |
2080 | else if (!strcmp("disable", tagvalue)) | |
2081 | perfevents = PERF_EVENTS_DISABLE; | |
2082 | else | |
2083 | { | |
2084 | if (run_in_guest()) | |
2085 | perfevents = PERF_EVENTS_DISABLE; | |
2086 | else | |
2087 | perfevents = PERF_EVENTS_ENABLE; | |
2088 | } | |
2089 | } | |
2090 | ||
2091 | static int | |
2092 | enable_perfevents() | |
2093 | { | |
2094 | if (perfevents == PERF_EVENTS_AUTO) | |
2095 | do_perfevents("perfevents", "auto"); | |
2096 | ||
2097 | return perfevents == PERF_EVENTS_ENABLE; | |
2098 | } | |
2099 | ||
2058 | 2100 | long |
2059 | 2101 | perf_event_open(struct perf_event_attr *hwevent, pid_t pid, |
2060 | 2102 | int cpu, int groupfd, unsigned long flags) |
2068 | 2110 | static int firstcall = 1, cpualloced, *fdi, *fdc; |
2069 | 2111 | int i; |
2070 | 2112 | |
2113 | if (!enable_perfevents()) | |
2114 | return; | |
2115 | ||
2071 | 2116 | /* |
2072 | 2117 | ** once initialize perf event counter retrieval |
2073 | 2118 | */ |
2113 | 2158 | } |
2114 | 2159 | |
2115 | 2160 | if (! droprootprivs()) |
2116 | cleanstop(42); | |
2161 | mcleanstop(42, "failed to drop root privs\n"); | |
2162 | ||
2117 | 2163 | |
2118 | 2164 | /* |
2119 | 2165 | ** all failed (probably no kernel support)? |
2156 | 2202 | cs->all.cycle += cs->cpu[i].cycle; |
2157 | 2203 | } |
2158 | 2204 | } |
2205 | } | |
2206 | #else | |
2207 | void | |
2208 | do_perfevents(char *tagname, char *tagvalue) | |
2209 | { | |
2210 | wcleanstop(1, "atop built with NOPERFEVENT, cannot use perfevents\n"); | |
2159 | 2211 | } |
2160 | 2212 | #endif |
2161 | 2213 | |
2274 | 2326 | return 1; |
2275 | 2327 | } |
2276 | 2328 | #endif |
2329 | ||
2330 | ||
2331 | #if defined(__x86_64__) || defined(__i386__) | |
2332 | #define HYPERVISOR_INFO_LEAF 0x40000000 | |
2333 | ||
2334 | static inline void | |
2335 | x86_cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, | |
2336 | unsigned int *ecx, unsigned int *edx) | |
2337 | { | |
2338 | __asm__( | |
2339 | #if defined(__PIC__) && defined(__i386__) | |
2340 | "xchg %%ebx, %%esi;" | |
2341 | "cpuid;" | |
2342 | "xchg %%esi, %%ebx;" | |
2343 | : "=S" (*ebx), | |
2344 | #else | |
2345 | "cpuid;" | |
2346 | : "=b" (*ebx), | |
2347 | #endif | |
2348 | "=a" (*eax), | |
2349 | "=c" (*ecx), | |
2350 | "=d" (*edx) | |
2351 | : "1" (op), "c"(0)); | |
2352 | } | |
2353 | ||
2354 | static int | |
2355 | get_hypervisor(void) | |
2356 | { | |
2357 | unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0, hyper = HYPER_NONE; | |
2358 | char hyper_vendor_id[13]; | |
2359 | ||
2360 | memset(hyper_vendor_id, 0, sizeof(hyper_vendor_id)); | |
2361 | ||
2362 | x86_cpuid(HYPERVISOR_INFO_LEAF, &eax, &ebx, &ecx, &edx); | |
2363 | memcpy(hyper_vendor_id + 0, &ebx, 4); | |
2364 | memcpy(hyper_vendor_id + 4, &ecx, 4); | |
2365 | memcpy(hyper_vendor_id + 8, &edx, 4); | |
2366 | hyper_vendor_id[12] = '\0'; | |
2367 | ||
2368 | if (!hyper_vendor_id[0]) | |
2369 | return hyper; | |
2370 | ||
2371 | if (!strncmp("XenVMMXenVMM", hyper_vendor_id, 12)) | |
2372 | hyper = HYPER_XEN; | |
2373 | else if (!strncmp("KVMKVMKVM", hyper_vendor_id, 9)) | |
2374 | hyper = HYPER_KVM; | |
2375 | else if (!strncmp("Microsoft Hv", hyper_vendor_id, 12)) | |
2376 | hyper = HYPER_MSHV; | |
2377 | else if (!strncmp("VMwareVMware", hyper_vendor_id, 12)) | |
2378 | hyper = HYPER_VMWARE; | |
2379 | else if (!strncmp("UnisysSpar64", hyper_vendor_id, 12)) | |
2380 | hyper = HYPER_SPAR; | |
2381 | ||
2382 | return hyper; | |
2383 | } | |
2384 | #else /* ! (__x86_64__ || __i386__) */ | |
2385 | static int | |
2386 | get_hypervisor(void) | |
2387 | { | |
2388 | return HYPER_NONE; | |
2389 | } | |
2390 | #endif | |
2391 | ||
2392 | static int | |
2393 | run_in_guest(void) | |
2394 | { | |
2395 | return get_hypervisor() != HYPER_NONE; | |
2396 | } |
0 | /* | |
1 | ** structure containing only relevant process-info extracted | |
2 | ** from kernel's process-administration | |
3 | */ | |
4 | struct tstat_25 { | |
5 | /* GENERAL TASK INFO */ | |
6 | struct gen_25 { | |
7 | int tgid; /* threadgroup identification */ | |
8 | int pid; /* process identification */ | |
9 | int ppid; /* parent process identification*/ | |
10 | int ruid; /* real user identification */ | |
11 | int euid; /* eff. user identification */ | |
12 | int suid; /* saved user identification */ | |
13 | int fsuid; /* fs user identification */ | |
14 | int rgid; /* real group identification */ | |
15 | int egid; /* eff. group identification */ | |
16 | int sgid; /* saved group identification */ | |
17 | int fsgid; /* fs group identification */ | |
18 | int nthr; /* number of threads in tgroup */ | |
19 | char name[PNAMLEN+1];/* process name string */ | |
20 | char isproc; /* boolean: process level? */ | |
21 | char state; /* process state ('E' = exited) */ | |
22 | int excode; /* process exit status */ | |
23 | time_t btime; /* process start time (epoch) */ | |
24 | time_t elaps; /* process elaps time (hertz) */ | |
25 | char cmdline[CMDLEN+1];/* command-line string */ | |
26 | int nthrslpi; /* # threads in state 'S' */ | |
27 | int nthrslpu; /* # threads in state 'D' */ | |
28 | int nthrrun; /* # threads in state 'R' */ | |
29 | ||
30 | int ctid; /* OpenVZ container ID */ | |
31 | int vpid; /* OpenVZ virtual PID */ | |
32 | ||
33 | int wasinactive; /* boolean: task inactive */ | |
34 | ||
35 | char container[16]; /* Docker container id (12 pos) */ | |
36 | } gen; | |
37 | ||
38 | /* CPU STATISTICS */ | |
39 | struct cpu_25 { | |
40 | count_t utime; /* time user text (ticks) */ | |
41 | count_t stime; /* time system text (ticks) */ | |
42 | int nice; /* nice value */ | |
43 | int prio; /* priority */ | |
44 | int rtprio; /* realtime priority */ | |
45 | int policy; /* scheduling policy */ | |
46 | int curcpu; /* current processor */ | |
47 | int sleepavg; /* sleep average percentage */ | |
48 | int ifuture[4]; /* reserved for future use */ | |
49 | count_t cfuture[4]; /* reserved for future use */ | |
50 | } cpu; | |
51 | ||
52 | /* DISK STATISTICS */ | |
53 | struct dsk_25 { | |
54 | count_t rio; /* number of read requests */ | |
55 | count_t rsz; /* cumulative # sectors read */ | |
56 | count_t wio; /* number of write requests */ | |
57 | count_t wsz; /* cumulative # sectors written */ | |
58 | count_t cwsz; /* cumulative # written sectors */ | |
59 | /* being cancelled */ | |
60 | count_t cfuture[4]; /* reserved for future use */ | |
61 | } dsk; | |
62 | ||
63 | /* MEMORY STATISTICS */ | |
64 | struct mem_25 { | |
65 | count_t minflt; /* number of page-reclaims */ | |
66 | count_t majflt; /* number of page-faults */ | |
67 | count_t vexec; /* virtmem execfile (Kb) */ | |
68 | count_t vmem; /* virtual memory (Kb) */ | |
69 | count_t rmem; /* resident memory (Kb) */ | |
70 | count_t pmem; /* resident memory (Kb) */ | |
71 | count_t vgrow; /* virtual growth (Kb) */ | |
72 | count_t rgrow; /* resident growth (Kb) */ | |
73 | count_t vdata; /* virtmem data (Kb) */ | |
74 | count_t vstack; /* virtmem stack (Kb) */ | |
75 | count_t vlibs; /* virtmem libexec (Kb) */ | |
76 | count_t vswap; /* swap space used (Kb) */ | |
77 | count_t cfuture[4]; /* reserved for future use */ | |
78 | } mem; | |
79 | ||
80 | /* NETWORK STATISTICS */ | |
81 | struct net_25 { | |
82 | count_t tcpsnd; /* number of TCP-packets sent */ | |
83 | count_t tcpssz; /* cumulative size packets sent */ | |
84 | count_t tcprcv; /* number of TCP-packets recved */ | |
85 | count_t tcprsz; /* cumulative size packets rcvd */ | |
86 | count_t udpsnd; /* number of UDP-packets sent */ | |
87 | count_t udpssz; /* cumulative size packets sent */ | |
88 | count_t udprcv; /* number of UDP-packets recved */ | |
89 | count_t udprsz; /* cumulative size packets sent */ | |
90 | count_t avail1; /* */ | |
91 | count_t avail2; /* */ | |
92 | count_t cfuture[4]; /* reserved for future use */ | |
93 | } net; | |
94 | ||
95 | struct gpu_25 { | |
96 | char state; // A - active, E - Exit, '\0' - no use | |
97 | char cfuture[3]; // | |
98 | short nrgpus; // number of GPUs for this process | |
99 | int32_t gpulist; // bitlist with GPU numbers | |
100 | ||
101 | int gpubusy; // gpu busy perc process lifetime -1 = n/a | |
102 | int membusy; // memory busy perc process lifetime -1 = n/a | |
103 | count_t timems; // milliseconds accounting -1 = n/a | |
104 | // value 0 for active process, | |
105 | // value > 0 after termination | |
106 | ||
107 | count_t memnow; // current memory consumption in KiB | |
108 | count_t memcum; // cumulative memory consumption in KiB | |
109 | count_t sample; // number of samples | |
110 | } gpu; | |
111 | }; |
0 | #define MAXCPU_25 2048 | |
1 | #define MAXDSK_25 1024 | |
2 | #define MAXLVM_25 2048 | |
3 | #define MAXMDD_25 256 | |
4 | #define MAXINTF_25 128 | |
5 | #define MAXCONTAINER_25 128 | |
6 | #define MAXNFSMOUNT_25 64 | |
7 | #define MAXIBPORT_25 32 | |
8 | #define MAXGPU_25 32 | |
9 | ||
10 | /************************************************************************/ | |
11 | struct memstat_25 { | |
12 | count_t physmem; // number of physical pages | |
13 | count_t freemem; // number of free pages | |
14 | count_t buffermem; // number of buffer pages | |
15 | count_t slabmem; // number of slab pages | |
16 | count_t cachemem; // number of cache pages | |
17 | count_t cachedrt; // number of cache pages (dirty) | |
18 | ||
19 | count_t totswap; // number of pages in swap | |
20 | count_t freeswap; // number of free swap pages | |
21 | ||
22 | count_t pgscans; // number of page scans | |
23 | count_t pgsteal; // number of page steals | |
24 | count_t allocstall; // try to free pages forced | |
25 | count_t swouts; // number of pages swapped out | |
26 | count_t swins; // number of pages swapped in | |
27 | ||
28 | count_t commitlim; // commit limit in pages | |
29 | count_t committed; // number of reserved pages | |
30 | ||
31 | count_t shmem; // tot shmem incl. tmpfs (pages) | |
32 | count_t shmrss; // resident shared memory (pages) | |
33 | count_t shmswp; // swapped shared memory (pages) | |
34 | ||
35 | count_t slabreclaim; // reclaimable slab (pages) | |
36 | ||
37 | count_t tothugepage; // total huge pages (huge pages) | |
38 | count_t freehugepage; // free huge pages (huge pages) | |
39 | count_t hugepagesz; // huge page size (bytes) | |
40 | ||
41 | count_t vmwballoon; // vmware claimed balloon pages | |
42 | count_t cfuture[8]; // reserved for future use | |
43 | }; | |
44 | ||
45 | /************************************************************************/ | |
46 | ||
47 | struct netstat_25 { | |
48 | struct ipv4_stats ipv4; | |
49 | struct icmpv4_stats icmpv4; | |
50 | struct udpv4_stats udpv4; | |
51 | ||
52 | struct ipv6_stats ipv6; | |
53 | struct icmpv6_stats icmpv6; | |
54 | struct udpv6_stats udpv6; | |
55 | ||
56 | struct tcp_stats tcp; | |
57 | }; | |
58 | ||
59 | /************************************************************************/ | |
60 | ||
61 | struct freqcnt_25 { | |
62 | count_t maxfreq;/* frequency in MHz */ | |
63 | count_t cnt; /* number of clock ticks times state */ | |
64 | count_t ticks; /* number of total clock ticks */ | |
65 | /* if zero, cnt is actul freq */ | |
66 | }; | |
67 | ||
68 | struct percpu_25 { | |
69 | int cpunr; | |
70 | count_t stime; /* system time in clock ticks */ | |
71 | count_t utime; /* user time in clock ticks */ | |
72 | count_t ntime; /* nice time in clock ticks */ | |
73 | count_t itime; /* idle time in clock ticks */ | |
74 | count_t wtime; /* iowait time in clock ticks */ | |
75 | count_t Itime; /* irq time in clock ticks */ | |
76 | count_t Stime; /* softirq time in clock ticks */ | |
77 | count_t steal; /* steal time in clock ticks */ | |
78 | count_t guest; /* guest time in clock ticks */ | |
79 | struct freqcnt_25 freqcnt;/* frequency scaling info */ | |
80 | count_t instr; /* CPU instructions */ | |
81 | count_t cycle; /* CPU cycles */ | |
82 | count_t cfuture[2]; /* reserved for future use */ | |
83 | }; | |
84 | ||
85 | struct cpustat_25 { | |
86 | count_t nrcpu; /* number of cpu's */ | |
87 | count_t devint; /* number of device interrupts */ | |
88 | count_t csw; /* number of context switches */ | |
89 | count_t nprocs; /* number of processes started */ | |
90 | float lavg1; /* load average last minute */ | |
91 | float lavg5; /* load average last 5 minutes */ | |
92 | float lavg15; /* load average last 15 minutes */ | |
93 | count_t cfuture[4]; /* reserved for future use */ | |
94 | ||
95 | struct percpu_25 all; | |
96 | struct percpu_25 cpu[MAXCPU_25]; | |
97 | }; | |
98 | ||
99 | /************************************************************************/ | |
100 | ||
101 | struct perdsk_25 { | |
102 | char name[MAXDKNAM]; /* empty string for last */ | |
103 | count_t nread; /* number of read transfers */ | |
104 | count_t nrsect; /* number of sectors read */ | |
105 | count_t nwrite; /* number of write transfers */ | |
106 | count_t nwsect; /* number of sectors written */ | |
107 | count_t io_ms; /* number of millisecs spent for I/O */ | |
108 | count_t avque; /* average queue length */ | |
109 | count_t cfuture[4]; /* reserved for future use */ | |
110 | }; | |
111 | ||
112 | struct dskstat_25 { | |
113 | int ndsk; /* number of physical disks */ | |
114 | int nmdd; /* number of md volumes */ | |
115 | int nlvm; /* number of logical volumes */ | |
116 | struct perdsk_25 dsk[MAXDSK_25]; | |
117 | struct perdsk_25 mdd[MAXMDD_25]; | |
118 | struct perdsk_25 lvm[MAXLVM_25]; | |
119 | }; | |
120 | ||
121 | /************************************************************************/ | |
122 | ||
123 | struct perintf_25 { | |
124 | char name[16]; /* empty string for last */ | |
125 | ||
126 | count_t rbyte; /* number of read bytes */ | |
127 | count_t rpack; /* number of read packets */ | |
128 | count_t rerrs; /* receive errors */ | |
129 | count_t rdrop; /* receive drops */ | |
130 | count_t rfifo; /* receive fifo */ | |
131 | count_t rframe; /* receive framing errors */ | |
132 | count_t rcompr; /* receive compressed */ | |
133 | count_t rmultic;/* receive multicast */ | |
134 | count_t rfuture[4]; /* reserved for future use */ | |
135 | ||
136 | count_t sbyte; /* number of written bytes */ | |
137 | count_t spack; /* number of written packets */ | |
138 | count_t serrs; /* transmit errors */ | |
139 | count_t sdrop; /* transmit drops */ | |
140 | count_t sfifo; /* transmit fifo */ | |
141 | count_t scollis;/* collisions */ | |
142 | count_t scarrier;/* transmit carrier */ | |
143 | count_t scompr; /* transmit compressed */ | |
144 | count_t sfuture[4]; /* reserved for future use */ | |
145 | ||
146 | char type; /* interface type ('e'/'w'/'?') */ | |
147 | long speed; /* interface speed in megabits/second */ | |
148 | long speedp; /* previous interface speed */ | |
149 | char duplex; /* full duplex (boolean) */ | |
150 | count_t cfuture[4]; /* reserved for future use */ | |
151 | }; | |
152 | ||
153 | struct intfstat_25 { | |
154 | int nrintf; | |
155 | struct perintf_25 intf[MAXINTF_25]; | |
156 | }; | |
157 | ||
158 | /************************************************************************/ | |
159 | ||
160 | struct pernfsmount_25 { | |
161 | char mountdev[128]; /* mountdevice */ | |
162 | count_t age; /* number of seconds mounted */ | |
163 | ||
164 | count_t bytesread; /* via normal reads */ | |
165 | count_t byteswrite; /* via normal writes */ | |
166 | count_t bytesdread; /* via direct reads */ | |
167 | count_t bytesdwrite; /* via direct writes */ | |
168 | count_t bytestotread; /* via reads */ | |
169 | count_t bytestotwrite; /* via writes */ | |
170 | count_t pagesmread; /* via mmap reads */ | |
171 | count_t pagesmwrite; /* via mmap writes */ | |
172 | ||
173 | count_t future[8]; | |
174 | }; | |
175 | ||
176 | struct nfsstat_25 { | |
177 | struct { | |
178 | count_t netcnt; | |
179 | count_t netudpcnt; | |
180 | count_t nettcpcnt; | |
181 | count_t nettcpcon; | |
182 | ||
183 | count_t rpccnt; | |
184 | count_t rpcbadfmt; | |
185 | count_t rpcbadaut; | |
186 | count_t rpcbadcln; | |
187 | ||
188 | count_t rpcread; | |
189 | count_t rpcwrite; | |
190 | ||
191 | count_t rchits; /* repcache hits */ | |
192 | count_t rcmiss; /* repcache misses */ | |
193 | count_t rcnoca; /* uncached requests */ | |
194 | ||
195 | count_t nrbytes; /* read bytes */ | |
196 | count_t nwbytes; /* written bytes */ | |
197 | ||
198 | count_t future[8]; | |
199 | } server; | |
200 | ||
201 | struct { | |
202 | count_t rpccnt; | |
203 | count_t rpcretrans; | |
204 | count_t rpcautrefresh; | |
205 | ||
206 | count_t rpcread; | |
207 | count_t rpcwrite; | |
208 | ||
209 | count_t future[8]; | |
210 | } client; | |
211 | ||
212 | struct { | |
213 | int nrmounts; | |
214 | struct pernfsmount_25 nfsmnt[MAXNFSMOUNT_25]; | |
215 | } nfsmounts; | |
216 | }; | |
217 | ||
218 | /************************************************************************/ | |
219 | struct psi_25 { | |
220 | float avg10; // average pressure last 10 seconds | |
221 | float avg60; // average pressure last 60 seconds | |
222 | float avg300; // average pressure last 300 seconds | |
223 | count_t total; // total number of milliseconds | |
224 | }; | |
225 | ||
226 | struct pressure_25 { | |
227 | char present; /* pressure stats supported? */ | |
228 | char future[3]; | |
229 | struct psi_25 cpusome; /* pressure stall info 'some' */ | |
230 | struct psi_25 memsome; /* pressure stall info 'some' */ | |
231 | struct psi_25 memfull; /* pressure stall info 'full' */ | |
232 | struct psi_25 iosome; /* pressure stall info 'some' */ | |
233 | struct psi_25 iofull; /* pressure stall info 'full' */ | |
234 | }; | |
235 | ||
236 | /************************************************************************/ | |
237 | ||
238 | struct percontainer_25 { | |
239 | unsigned long ctid; /* container id */ | |
240 | unsigned long numproc; /* number of processes */ | |
241 | ||
242 | count_t system; /* */ | |
243 | count_t user; /* */ | |
244 | count_t nice; /* */ | |
245 | count_t uptime; /* */ | |
246 | ||
247 | count_t physpages; /* */ | |
248 | }; | |
249 | ||
250 | struct contstat_25 { | |
251 | int nrcontainer; | |
252 | struct percontainer_25 cont[MAXCONTAINER_25]; | |
253 | }; | |
254 | ||
255 | /************************************************************************/ | |
256 | /* | |
257 | ** experimental stuff for access to local HTTP daemons | |
258 | */ | |
259 | struct wwwstat_25 { | |
260 | count_t accesses; /* total number of HTTP-requests */ | |
261 | count_t totkbytes; /* total kbytes transfer for HTTP-req */ | |
262 | count_t uptime; /* number of seconds since startup */ | |
263 | int bworkers; /* number of busy httpd-daemons */ | |
264 | int iworkers; /* number of idle httpd-daemons */ | |
265 | }; | |
266 | ||
267 | /************************************************************************/ | |
268 | ||
269 | struct pergpu_25 { | |
270 | char taskstats; // GPU task statistics supported? | |
271 | unsigned char nrprocs; // number of processes using GPU | |
272 | char type[MAXGPUTYPE+1]; // GPU type | |
273 | char busid[MAXGPUBUS+1]; // GPU bus identification | |
274 | int gpunr; // GPU number | |
275 | int gpupercnow; // processor percentage last second | |
276 | // -1 if not supported | |
277 | int mempercnow; // memory percentage last second | |
278 | // -1 if not supported | |
279 | count_t memtotnow; // total memory in KiB | |
280 | count_t memusenow; // used memory in KiB | |
281 | count_t samples; // number of samples | |
282 | count_t gpuperccum; // cumulative processor busy percentage | |
283 | // -1 if not supported | |
284 | count_t memperccum; // cumulative memory percentage | |
285 | // -1 if not supported | |
286 | count_t memusecum; // cumulative used memory in KiB | |
287 | }; | |
288 | ||
289 | struct gpustat_25 { | |
290 | int nrgpus; // total number of GPUs | |
291 | struct pergpu_25 gpu[MAXGPU_25]; | |
292 | }; | |
293 | ||
294 | /************************************************************************/ | |
295 | ||
296 | struct perifb_25 { | |
297 | char ibname[MAXIBNAME]; // InfiniBand controller | |
298 | short portnr; // InfiniBand controller port | |
299 | ||
300 | short lanes; // number of lanes (traffic factor) | |
301 | count_t rate; // transfer rate in megabits/sec | |
302 | count_t rcvb; // bytes received | |
303 | count_t sndb; // bytes transmitted | |
304 | count_t rcvp; // packets received | |
305 | count_t sndp; // packets transmitted | |
306 | }; | |
307 | ||
308 | struct ifbstat_25 { | |
309 | int nrports; // total number of IB ports | |
310 | struct perifb_25 ifb[MAXIBPORT_25]; | |
311 | }; | |
312 | /************************************************************************/ | |
313 | ||
314 | struct sstat_25 { | |
315 | struct cpustat_25 cpu; | |
316 | struct memstat_25 mem; | |
317 | struct netstat_25 net; | |
318 | struct intfstat_25 intf; | |
319 | struct dskstat_25 dsk; | |
320 | struct nfsstat_25 nfs; | |
321 | struct contstat_25 cfs; | |
322 | struct pressure_25 psi; | |
323 | struct gpustat_25 gpu; | |
324 | struct ifbstat_25 ifb; | |
325 | ||
326 | struct wwwstat_25 www; | |
327 | }; |
43 | 43 | #include <sys/time.h> |
44 | 44 | #include <sys/resource.h> |
45 | 45 | #include <unistd.h> |
46 | #include <sys/uio.h> | |
46 | 47 | |
47 | 48 | #include "atop.h" |
48 | 49 | #include "showgeneric.h" |
117 | 118 | static int getrawsstat(int, struct sstat *, int); |
118 | 119 | static int getrawtstat(int, struct tstat *, int, int); |
119 | 120 | static int rawwopen(void); |
121 | static int readchunk(int, void *, int); | |
120 | 122 | static int lookslikedatetome(char *); |
121 | 123 | static void testcompval(int, char *); |
122 | 124 | static void try_other_version(int, int); |
139 | 141 | unsigned long scomplen = sizeof scompbuf; |
140 | 142 | unsigned long pcomplen = sizeof(struct tstat) * |
141 | 143 | devtstat->ntaskall; |
144 | struct iovec iov[3]; | |
142 | 145 | |
143 | 146 | /* |
144 | 147 | ** first call: |
213 | 216 | if (supportflags & GPUSTAT) |
214 | 217 | rr.flags |= RRGPUSTAT; |
215 | 218 | |
216 | if ( write(rawfd, &rr, sizeof rr) == -1) | |
219 | /* | |
220 | ** use 1-writev to make record operation atomic | |
221 | ** to avoid write uncompleted record data. | |
222 | */ | |
223 | iov[0].iov_base = &rr; | |
224 | iov[0].iov_len = sizeof (rr); | |
225 | ||
226 | iov[1].iov_base = scompbuf; | |
227 | iov[1].iov_len = scomplen; | |
228 | ||
229 | iov[2].iov_base = pcompbuf; | |
230 | iov[2].iov_len = pcomplen; | |
231 | ||
232 | if ( writev(rawfd, iov, 3) == -1) | |
217 | 233 | { |
218 | 234 | fprintf(stderr, "%s - ", rawname); |
219 | perror("write raw record"); | |
220 | 235 | if ( ftruncate(rawfd, filestat.st_size) == -1) |
221 | cleanstop(8); | |
222 | cleanstop(7); | |
223 | } | |
224 | ||
225 | /* | |
226 | ** write compressed system status structure to file | |
227 | */ | |
228 | if ( write(rawfd, scompbuf, scomplen) == -1) | |
229 | { | |
230 | fprintf(stderr, "%s - ", rawname); | |
231 | perror("write raw status record"); | |
232 | if ( ftruncate(rawfd, filestat.st_size) == -1) | |
233 | cleanstop(8); | |
234 | cleanstop(7); | |
235 | } | |
236 | ||
237 | /* | |
238 | ** write compressed list of process status structures to file | |
239 | */ | |
240 | if ( write(rawfd, pcompbuf, pcomplen) == -1) | |
241 | { | |
242 | fprintf(stderr, "%s - ", rawname); | |
243 | perror("write raw process record"); | |
244 | if ( ftruncate(rawfd, filestat.st_size) == -1) | |
245 | cleanstop(8); | |
246 | cleanstop(7); | |
236 | mcleanstop(8, | |
237 | "failed to write raw/status/process record to %s\n", | |
238 | rawname); | |
239 | ||
240 | mcleanstop(7, | |
241 | "failed to write raw/status/process record to %s\n", | |
242 | rawname); | |
247 | 243 | } |
248 | 244 | |
249 | 245 | free(pcompbuf); |
280 | 276 | ** read and verify header record |
281 | 277 | */ |
282 | 278 | if ( read(fd, &rh, sizeof rh) < sizeof rh) |
283 | { | |
284 | fprintf(stderr, "%s - cannot read header\n", rawname); | |
285 | cleanstop(7); | |
286 | } | |
279 | mcleanstop(7, "%s - cannot read header\n", rawname); | |
287 | 280 | |
288 | 281 | if (rh.magic != MYMAGIC) |
289 | { | |
290 | fprintf(stderr, | |
291 | "file %s exists but does not contain raw " | |
282 | mcleanstop(7, "file %s exists but does not contain raw " | |
292 | 283 | "atop output (wrong magic number)\n", rawname); |
293 | ||
294 | cleanstop(7); | |
295 | } | |
296 | 284 | |
297 | 285 | if ( rh.sstatlen != sizeof(struct sstat) || |
298 | 286 | rh.tstatlen != sizeof(struct tstat) || |
365 | 353 | */ |
366 | 354 | #define OFFCHUNK 256 |
367 | 355 | |
368 | void | |
356 | int | |
369 | 357 | rawread(void) |
370 | 358 | { |
371 | int i, j, rawfd, len; | |
359 | int i, j, rawfd, len, isregular = 1; | |
372 | 360 | char *py; |
373 | 361 | struct rawheader rh; |
374 | 362 | struct rawrecord rr; |
381 | 369 | ** variables to maintain the offsets of the raw records |
382 | 370 | ** to be able to see previous samples again |
383 | 371 | */ |
384 | off_t *offlist; | |
372 | off_t *offlist = NULL; | |
385 | 373 | unsigned int offsize = 0; |
386 | 374 | unsigned int offcur = 0; |
387 | 375 | char lastcmd = 'X', flags; |
463 | 451 | } |
464 | 452 | |
465 | 453 | /* |
454 | ** make sure the file is a regular file (seekable) or | |
455 | ** a pipe (not seekable) | |
456 | */ | |
457 | if (stat(rawname, &filestat) == -1) | |
458 | { | |
459 | fprintf(stderr, "%s - ", rawname); | |
460 | perror("stat raw file"); | |
461 | cleanstop(7); | |
462 | } | |
463 | ||
464 | if (!S_ISREG(filestat.st_mode) && !S_ISFIFO(filestat.st_mode)) | |
465 | { | |
466 | fprintf(stderr, "raw file must be a regular file or pipe\n"); | |
467 | cleanstop(7); | |
468 | } | |
469 | ||
470 | isregular = S_ISREG(filestat.st_mode); | |
471 | ||
472 | /* | |
466 | 473 | ** open raw file |
467 | 474 | */ |
468 | 475 | if ( (rawfd = open(rawname, O_RDONLY)) == -1) |
509 | 516 | /* |
510 | 517 | ** read the raw header and verify the magic |
511 | 518 | */ |
512 | if ( read(rawfd, &rh, sizeof rh) < sizeof rh) | |
519 | if ( readchunk(rawfd, &rh, sizeof rh) < sizeof rh) | |
513 | 520 | { |
514 | 521 | fprintf(stderr, "can not read raw file header\n"); |
515 | 522 | cleanstop(7); |
581 | 588 | /* |
582 | 589 | ** allocate a list for backtracking of rawrecord-offsets |
583 | 590 | */ |
584 | offlist = malloc(sizeof(off_t) * OFFCHUNK); | |
585 | ||
586 | ptrverify(offlist, "Malloc failed for backtrack list\n"); | |
587 | ||
588 | offsize = OFFCHUNK; | |
589 | ||
590 | *offlist = lseek(rawfd, 0, SEEK_CUR); | |
591 | offcur = 1; | |
591 | if (isregular) | |
592 | { | |
593 | offlist = malloc(sizeof(off_t) * OFFCHUNK); | |
594 | ||
595 | ptrverify(offlist, "Malloc failed for backtrack list\n"); | |
596 | ||
597 | offsize = OFFCHUNK; | |
598 | ||
599 | *offlist = lseek(rawfd, 0, SEEK_CUR); | |
600 | offcur = 1; | |
601 | } | |
592 | 602 | |
593 | 603 | /* |
594 | 604 | ** read a raw record header until end-of-file |
606 | 616 | ** store the offset of the raw record in the offset list |
607 | 617 | ** in case of offset list overflow, extend the list |
608 | 618 | */ |
609 | *(offlist+offcur) = lseek(rawfd, 0, SEEK_CUR) - | |
619 | if (isregular) | |
620 | { | |
621 | *(offlist+offcur) = lseek(rawfd, 0, SEEK_CUR) - | |
610 | 622 | rh.rawreclen; |
611 | 623 | |
612 | if ( ++offcur >= offsize ) | |
613 | { | |
614 | offlist = realloc(offlist, | |
624 | if ( ++offcur >= offsize ) | |
625 | { | |
626 | offlist = realloc(offlist, | |
615 | 627 | (offsize+OFFCHUNK)*sizeof(off_t)); |
616 | 628 | |
617 | ptrverify(offlist, | |
629 | ptrverify(offlist, | |
618 | 630 | "Realloc failed for backtrack list\n"); |
619 | 631 | |
620 | offsize+= OFFCHUNK; | |
632 | offsize+= OFFCHUNK; | |
633 | } | |
621 | 634 | } |
622 | 635 | |
623 | 636 | /* |
627 | 640 | if ( (begintime && begintime > secsinday) ) |
628 | 641 | { |
629 | 642 | lastcmd = 1; |
630 | lseek(rawfd, rr.scomplen+rr.pcomplen, SEEK_CUR); | |
643 | ||
644 | if (isregular) | |
645 | { | |
646 | lseek(rawfd, rr.scomplen+rr.pcomplen, | |
647 | SEEK_CUR); | |
648 | } | |
649 | else // named pipe not seekable | |
650 | { | |
651 | char *dummybuf = | |
652 | malloc(rr.scomplen+rr.pcomplen); | |
653 | ||
654 | ptrverify(dummybuf, | |
655 | "Malloc rawlog pipe buffer failed\n"); | |
656 | ||
657 | readchunk(rawfd, dummybuf, | |
658 | rr.scomplen+rr.pcomplen); | |
659 | ||
660 | free(dummybuf); | |
661 | } | |
662 | ||
631 | 663 | continue; |
632 | 664 | } |
633 | 665 | |
635 | 667 | |
636 | 668 | if ( (endtime && endtime < secsinday) ) |
637 | 669 | { |
638 | free(offlist); | |
670 | if (isregular) | |
671 | free(offlist); | |
672 | ||
639 | 673 | close(rawfd); |
640 | return; | |
674 | return isregular; | |
641 | 675 | } |
642 | 676 | |
643 | 677 | /* |
747 | 781 | |
748 | 782 | nrgpus = sstat.gpu.nrgpus; |
749 | 783 | |
750 | (void) fstat(rawfd, &filestat); | |
751 | ||
752 | if ( filestat.st_size - | |
753 | lseek(rawfd, (off_t)0, SEEK_CUR) <= rh.rawreclen) | |
754 | flags |= RRLAST; | |
755 | ||
756 | lastcmd = (vis.show_samp)(rr.curtime, rr.interval, | |
784 | if (isregular) | |
785 | { | |
786 | (void) fstat(rawfd, &filestat); | |
787 | ||
788 | if ( filestat.st_size - | |
789 | lseek(rawfd, (off_t)0, SEEK_CUR) | |
790 | <= rh.rawreclen) | |
791 | flags |= RRLAST; | |
792 | } | |
793 | ||
794 | do | |
795 | { | |
796 | lastcmd = (vis.show_samp)(rr.curtime, | |
797 | rr.interval, | |
757 | 798 | &devtstat, &sstat, |
758 | 799 | rr.nexit, rr.noverflow, flags); |
800 | } | |
801 | while (!isregular && | |
802 | (lastcmd == MSAMPPREV || | |
803 | lastcmd == MSAMPBRANCH || | |
804 | lastcmd == MRESET )); | |
759 | 805 | |
760 | 806 | free(devtstat.taskall); |
761 | 807 | free(devtstat.procall); |
762 | 808 | free(devtstat.procactive); |
763 | ||
809 | ||
764 | 810 | switch (lastcmd) |
765 | 811 | { |
766 | case MSAMPPREV: | |
812 | case MSAMPPREV: | |
767 | 813 | if (offcur >= 2) |
768 | 814 | offcur-= 2; |
769 | 815 | else |
770 | 816 | offcur = 0; |
771 | ||
817 | ||
772 | 818 | lseek(rawfd, *(offlist+offcur), SEEK_SET); |
773 | 819 | break; |
774 | 820 | |
775 | case MRESET: | |
821 | case MRESET: | |
776 | 822 | lseek(rawfd, *offlist, SEEK_SET); |
777 | 823 | offcur = 1; |
778 | 824 | break; |
780 | 826 | case MSAMPBRANCH: |
781 | 827 | if (begintime && begintime < secsinday) |
782 | 828 | { |
783 | lseek(rawfd, *offlist, SEEK_SET); | |
829 | lseek(rawfd, *offlist, | |
830 | SEEK_SET); | |
784 | 831 | offcur = 1; |
785 | 832 | } |
786 | 833 | } |
788 | 835 | |
789 | 836 | begintime = 0; // allow earlier times from now on |
790 | 837 | |
791 | if (offcur >= 1) | |
792 | offcur--; | |
793 | ||
794 | lseek(rawfd, *(offlist+offcur), SEEK_SET); | |
795 | } | |
796 | ||
797 | free(offlist); | |
838 | if (isregular) | |
839 | { | |
840 | if (offcur >= 1) | |
841 | offcur--; | |
842 | ||
843 | lseek(rawfd, *(offlist+offcur), SEEK_SET); | |
844 | } | |
845 | else | |
846 | { | |
847 | lastcmd = 'q'; | |
848 | } | |
849 | } | |
850 | ||
851 | if (isregular) | |
852 | free(offlist); | |
798 | 853 | |
799 | 854 | close(rawfd); |
855 | ||
856 | return isregular; | |
800 | 857 | } |
801 | 858 | |
802 | 859 | /* |
805 | 862 | static int |
806 | 863 | getrawrec(int rawfd, struct rawrecord *prr, int rrlen) |
807 | 864 | { |
808 | return read(rawfd, prr, rrlen); | |
865 | return readchunk(rawfd, prr, rrlen); | |
809 | 866 | } |
810 | 867 | |
811 | 868 | /* |
818 | 875 | unsigned long uncomplen = sizeof(struct sstat); |
819 | 876 | int rv; |
820 | 877 | |
821 | if ( (compbuf = malloc(complen)) == NULL) | |
878 | compbuf = malloc(complen); | |
822 | 879 | |
823 | 880 | ptrverify(compbuf, "Malloc failed for reading compressed sysstats\n"); |
824 | 881 | |
825 | if ( read(rawfd, compbuf, complen) < complen) | |
882 | if ( readchunk(rawfd, compbuf, complen) < complen) | |
826 | 883 | { |
827 | 884 | free(compbuf); |
828 | 885 | return 0; |
851 | 908 | |
852 | 909 | ptrverify(compbuf, "Malloc failed for reading compressed procstats\n"); |
853 | 910 | |
854 | if ( read(rawfd, compbuf, complen) < complen) | |
911 | if ( readchunk(rawfd, compbuf, complen) < complen) | |
855 | 912 | { |
856 | 913 | free(compbuf); |
857 | 914 | return 0; |
901 | 958 | break; |
902 | 959 | |
903 | 960 | case Z_MEM_ERROR: |
904 | fprintf(stderr, "atop/atopsar - " | |
961 | mcleanstop(7, "atop/atopsar - " | |
905 | 962 | "%s: failed due to lack of memory\n", func); |
906 | cleanstop(7); | |
907 | 963 | |
908 | 964 | case Z_BUF_ERROR: |
909 | fprintf(stderr, "atop/atopsar - " | |
965 | mcleanstop(7, "atop/atopsar - " | |
910 | 966 | "%s: failed due to lack of room in buffer\n", func); |
911 | cleanstop(7); | |
912 | 967 | |
913 | 968 | case Z_DATA_ERROR: |
914 | fprintf(stderr, "atop/atopsar - " | |
969 | mcleanstop(7, "atop/atopsar - " | |
915 | 970 | "%s: failed due to corrupted/incomplete data\n", func); |
916 | cleanstop(7); | |
917 | 971 | |
918 | 972 | default: |
919 | fprintf(stderr, "atop/atopsar - " | |
973 | mcleanstop(7, "atop/atopsar - " | |
920 | 974 | "%s: unexpected error %d\n", func, rv); |
921 | cleanstop(7); | |
922 | } | |
975 | } | |
976 | } | |
977 | ||
978 | static int | |
979 | readchunk(int fd, void *buf, int len) | |
980 | { | |
981 | char *p = buf; | |
982 | int n; | |
983 | ||
984 | while (len > 0) | |
985 | { | |
986 | switch (n = read(fd, p, len)) | |
987 | { | |
988 | case 0: | |
989 | return 0; // EOF | |
990 | case -1: | |
991 | perror("read raw file"); | |
992 | cleanstop(9); | |
993 | default: | |
994 | len -= n; | |
995 | p += n; | |
996 | } | |
997 | } | |
998 | ||
999 | return (char *)p - (char *)buf; | |
923 | 1000 | } |
924 | 1001 | |
925 | 1002 | /* |
710 | 710 | *p=0; |
711 | 711 | } |
712 | 712 | else |
713 | { | |
714 | fprintf(stderr, | |
715 | "atoprc - %s: no name:prio pair for " | |
716 | "`%s'\n", name, linename); | |
717 | cleanstop(1); | |
718 | } | |
713 | mcleanstop(1, "atoprc - %s: no name:prio pair for " | |
714 | "`%s'\n", name, linename); | |
719 | 715 | |
720 | 716 | /* now get number */ |
721 | 717 | p++; |
777 | 773 | } |
778 | 774 | } |
779 | 775 | if (permissables[j]==0) |
780 | { | |
781 | fprintf(stderr, | |
782 | "atoprc - own system line: item %s invalid in %s line!\n", | |
783 | name, linename); | |
784 | cleanstop(1); | |
785 | } | |
776 | mcleanstop(1, | |
777 | "atoprc - own system line: item %s invalid in %s line\n", | |
778 | name, linename); | |
786 | 779 | } |
787 | 780 | ar[i].f=0; |
788 | 781 | ar[i].prio=0; |
866 | 859 | } |
867 | 860 | if (allprocpdefs[j]==0) |
868 | 861 | { |
869 | fprintf(stderr, | |
862 | mcleanstop(1, | |
870 | 863 | "atoprc - ownprocline: item %s invalid!\n", |
871 | 864 | name); |
872 | cleanstop(1); | |
873 | 865 | } |
874 | 866 | } |
875 | 867 | ar[i].f=0; |
1593 | 1593 | { |
1594 | 1594 | struct sstat *sstat=p; |
1595 | 1595 | static char buf[16]; |
1596 | psiformat(&(sstat->psi.iosome), "if", buf, sizeof buf); | |
1596 | psiformat(&(sstat->psi.iofull), "if", buf, sizeof buf); | |
1597 | 1597 | return buf; |
1598 | 1598 | } |
1599 | 1599 | sys_printdef syspdef_PSIIOF = {"PSIIOF", sysprt_PSIIOF}; |
571 | 571 | |
572 | 572 | va_start(args, errormsg); |
573 | 573 | vfprintf(stderr, errormsg, args); |
574 | va_end (args); | |
574 | va_end(args); | |
575 | 575 | |
576 | 576 | exit(13); |
577 | 577 | } |
578 | 578 | } |
579 | 579 | |
580 | 580 | /* |
581 | ** signal catcher for cleanup before exit | |
581 | ** cleanup, give error message and exit | |
582 | 582 | */ |
583 | 583 | void |
584 | cleanstop(int exitcode) | |
585 | { | |
584 | mcleanstop(int exitcode, const char *errormsg, ...) | |
585 | { | |
586 | va_list args; | |
587 | ||
586 | 588 | acctswoff(); |
587 | 589 | netatop_signoff(); |
588 | 590 | (vis.show_end)(); |
591 | ||
592 | va_start(args, errormsg); | |
593 | vfprintf(stderr, errormsg, args); | |
594 | va_end(args); | |
595 | ||
596 | exit(exitcode); | |
597 | } | |
598 | ||
599 | /* | |
600 | ** cleanup, give error message and exit | |
601 | */ | |
602 | void | |
603 | cleanstop(int exitcode) | |
604 | { | |
605 | acctswoff(); | |
606 | netatop_signoff(); | |
607 | (vis.show_end)(); | |
608 | ||
589 | 609 | exit(exitcode); |
590 | 610 | } |
591 | 611 |