| 
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