|
31 | 31 | ** -------------------------------------------------------------------------- |
32 | 32 | */ |
33 | 33 |
|
| 34 | +#define _GNU_SOURCE |
34 | 35 | #include <sys/types.h> |
35 | 36 | #include <sys/param.h> |
| 37 | +#include <sys/syscall.h> |
36 | 38 | #include <dirent.h> |
37 | 39 | #include <stdio.h> |
38 | 40 | #include <string.h> |
| 41 | +#include <fcntl.h> |
39 | 42 | #include <unistd.h> |
40 | 43 | #include <ctype.h> |
41 | 44 | #include <time.h> |
@@ -63,6 +66,7 @@ static int proccont(struct tstat *); |
63 | 66 | static void proccmd(struct tstat *); |
64 | 67 | static void procsmaps(struct tstat *); |
65 | 68 | static void procwchan(struct tstat *); |
| 69 | +static void procfd(struct tstat *); |
66 | 70 | static count_t procschedstat(struct tstat *); |
67 | 71 | static int proccgroupv2(struct tstat *); |
68 | 72 | static struct cgroupv2vals * |
@@ -218,6 +222,8 @@ photoproc(struct tstat *tasklist, int maxtask) |
218 | 222 | if (getwchan) |
219 | 223 | procwchan(curtask); |
220 | 224 |
|
| 225 | + procfd(curtask); |
| 226 | + |
221 | 227 | // read network stats from netatop |
222 | 228 | netatop_gettask(curtask->gen.tgid, 'g', curtask); |
223 | 229 |
|
@@ -955,6 +961,57 @@ procschedstat(struct tstat *curtask) |
955 | 961 | return curtask->cpu.rundelay; |
956 | 962 | } |
957 | 963 |
|
| 964 | +/* |
| 965 | +** get current number of opened file descriptors for process |
| 966 | +** to monitor if fd leaks. |
| 967 | +** Considering users may set the max number of open files to |
| 968 | +** a very large number, we use getdents[64] SYSCALL directly |
| 969 | +** instead of glibc's readdir() for performance consideration. |
| 970 | +** Also, define MAX_OPEN to be 1024 * 1024 for display. |
| 971 | +*/ |
| 972 | +struct linux_dirent64 { |
| 973 | + unsigned long d_ino; |
| 974 | + off_t d_off; |
| 975 | + unsigned short d_reclen; |
| 976 | + unsigned char d_type; |
| 977 | + char d_name[]; |
| 978 | +}; |
| 979 | + |
| 980 | +#define MAX_OPEN 1024 * 1024 |
| 981 | + |
| 982 | +static void |
| 983 | +procfd(struct tstat *curtask) |
| 984 | +{ |
| 985 | + int fd, nread, fd_num = 0; |
| 986 | + struct linux_dirent64 *buf, *d; |
| 987 | + unsigned int count = 0; |
| 988 | + |
| 989 | + if ( (fd = open("fd", O_RDONLY | O_DIRECTORY)) != -1) { |
| 990 | + count = MAX_OPEN * sizeof(struct linux_dirent64); |
| 991 | + buf = malloc(count); |
| 992 | + ptrverify(buf, "Malloc failed for process's opened files\n"); |
| 993 | + |
| 994 | + nread = syscall(SYS_getdents64, fd, buf, count); |
| 995 | + if (nread == -1) { |
| 996 | + curtask->cpu.nropen = -1; |
| 997 | + } else if (nread == 0) { |
| 998 | + curtask->cpu.nropen = 0; |
| 999 | + } else if (nread > 0) { |
| 1000 | + for (int bops = 0; bops < nread;) { |
| 1001 | + d = (struct linux_dirent64 *)((char *)buf + bops); |
| 1002 | + bops += d->d_reclen; |
| 1003 | + fd_num++; |
| 1004 | + } |
| 1005 | + curtask->cpu.nropen = fd_num - 2; |
| 1006 | + } |
| 1007 | + |
| 1008 | + close(fd); |
| 1009 | + free(buf); |
| 1010 | + } else { |
| 1011 | + curtask->cpu.nropen = 0; |
| 1012 | + } |
| 1013 | +} |
| 1014 | + |
958 | 1015 | /* |
959 | 1016 | ** CGROUP V2 specific items |
960 | 1017 | */ |
|
0 commit comments