@@ -205,7 +205,7 @@ asynchronous manner and the value may not be very precise. To see a precise
snapshot of a moment, you can see /proc/<pid>/smaps file and scan page table.
It's slow but very precise.
-Table 1-2: Contents of the status files (as of 3.20.0)
+Table 1-2: Contents of the status files (as of 4.1.0)
..............................................................................
Field Content
Name filename of the executable
@@ -220,6 +220,7 @@ Table 1-2: Contents of the status files (as of 3.20.0)
Uid Real, effective, saved set, and file system UIDs
Gid Real, effective, saved set, and file system GIDs
FDSize number of file descriptor slots currently allocated
+ FDAlloc number of file descriptor allocated
Groups supplementary group list
NStgid descendant namespace thread group ID hierarchy
NSpid descendant namespace process ID hierarchy
@@ -236,6 +236,18 @@ static int count_open_files(struct fdtable *fdt)
return i;
}
+int count_open_files_exact(struct fdtable *fdt)
+{
+ int size = fdt->max_fds;
+ int i, count = 0;
+
+ for (i = 0; i < size / BITS_PER_LONG; i++)
+ if (fdt->open_fds[i])
+ count += hweight_long(fdt->open_fds[i]);
+
+ return count;
+}
+
/*
* Allocate a new files structure and copy contents from the
* passed in files structure.
@@ -140,7 +140,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
struct task_struct *tracer;
const struct cred *cred;
pid_t ppid, tpid = 0, tgid, ngid;
- unsigned int max_fds = 0;
+ unsigned int max_fds = 0, count_fds = 0;
rcu_read_lock();
ppid = pid_alive(p) ?
@@ -155,8 +155,10 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
cred = get_task_cred(p);
task_lock(p);
- if (p->files)
+ if (p->files) {
max_fds = files_fdtable(p->files)->max_fds;
+ count_fds = count_open_files_exact(files_fdtable(p->files));
+ }
task_unlock(p);
rcu_read_unlock();
@@ -169,7 +171,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
"TracerPid:\t%d\n"
"Uid:\t%d\t%d\t%d\t%d\n"
"Gid:\t%d\t%d\t%d\t%d\n"
- "FDSize:\t%d\nGroups:\t",
+ "FDSize:\t%d\nFDAlloc:\t%d\nGroups:\t",
get_task_state(p),
tgid, ngid, pid_nr_ns(pid, ns), ppid, tpid,
from_kuid_munged(user_ns, cred->uid),
@@ -180,7 +182,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
from_kgid_munged(user_ns, cred->egid),
from_kgid_munged(user_ns, cred->sgid),
from_kgid_munged(user_ns, cred->fsgid),
- max_fds);
+ max_fds,
+ count_fds);
group_info = cred->group_info;
for (g = 0; g < group_info->ngroups; g++)
@@ -112,7 +112,7 @@ extern void __fd_install(struct files_struct *files,
unsigned int fd, struct file *file);
extern int __close_fd(struct files_struct *files,
unsigned int fd);
-
+extern int count_open_files_exact(struct fdtable *fdt);
extern struct kmem_cache *files_cachep;
#endif /* __LINUX_FDTABLE_H */
Iterating over the fd directory to count the number of allocated FD in a process is expensive if you have lots of them. This expose the count of open FDs from the fdtable open_fds bitmap. Signed-off-by: Yannick Brosseau <scientist@fb.com> --- Documentation/filesystems/proc.txt | 3 ++- fs/file.c | 12 ++++++++++++ fs/proc/array.c | 11 +++++++---- include/linux/fdtable.h | 2 +- 4 files changed, 22 insertions(+), 6 deletions(-)