summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_descrip.c50
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/user.h6
-rw-r--r--usr.bin/procstat/procstat_files.c30
4 files changed, 82 insertions, 6 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 4914804..7e53062 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -2446,6 +2446,47 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS)
SYSCTL_PROC(_kern, KERN_FILE, file, CTLTYPE_OPAQUE|CTLFLAG_RD,
0, 0, sysctl_kern_file, "S,xfile", "Entire file table");
+static int
+export_vnode_for_sysctl(struct vnode *vp, int type,
+ struct kinfo_file *kif, struct filedesc *fdp, struct sysctl_req *req)
+{
+ int error;
+ char *fullpath, *freepath;
+ int vfslocked;
+
+ bzero(kif, sizeof(*kif));
+ kif->kf_structsize = sizeof(*kif);
+
+ vref(vp);
+ kif->kf_fd = type;
+ kif->kf_type = KF_TYPE_VNODE;
+ /* This function only handles directories. */
+ KASSERT(vp->v_type == VDIR, ("export_vnode_for_sysctl: vnode not directory"));
+ kif->kf_vnode_type = KF_VTYPE_VDIR;
+
+ /*
+ * This is not a true file descriptor, so we set a bogus refcount
+ * and offset to indicate these fields should be ignored.
+ */
+ kif->kf_ref_count = -1;
+ kif->kf_offset = -1;
+
+ freepath = NULL;
+ fullpath = "-";
+ FILEDESC_SUNLOCK(fdp);
+ vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ vn_fullpath(curthread, vp, &fullpath, &freepath);
+ vput(vp);
+ VFS_UNLOCK_GIANT(vfslocked);
+ strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path));
+ if (freepath != NULL)
+ free(freepath, M_TEMP);
+ error = SYSCTL_OUT(req, kif, sizeof(*kif));
+ FILEDESC_SLOCK(fdp);
+ return (error);
+}
+
/*
* Get per-process file descriptors for use by procstat(1), et al.
*/
@@ -2473,6 +2514,15 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
PROC_UNLOCK(p);
kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK);
FILEDESC_SLOCK(fdp);
+ if (fdp->fd_cdir != NULL)
+ export_vnode_for_sysctl(fdp->fd_cdir, KF_FD_TYPE_CWD, kif,
+ fdp, req);
+ if (fdp->fd_rdir != NULL)
+ export_vnode_for_sysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif,
+ fdp, req);
+ if (fdp->fd_jdir != NULL)
+ export_vnode_for_sysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif,
+ fdp, req);
for (i = 0; i < fdp->fd_nfiles; i++) {
if ((fp = fdp->fd_ofiles[i]) == NULL)
continue;
diff --git a/sys/sys/param.h b/sys/sys/param.h
index a7ff20a..1a21dc2 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -57,7 +57,7 @@
* is created, otherwise 1.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 800018 /* Master, propagated to newvers */
+#define __FreeBSD_version 800019 /* Master, propagated to newvers */
#ifndef LOCORE
#include <sys/types.h>
diff --git a/sys/sys/user.h b/sys/sys/user.h
index 8177b1b..5595476 100644
--- a/sys/sys/user.h
+++ b/sys/sys/user.h
@@ -234,7 +234,7 @@ struct user {
};
/*
- * The KERN_PROC_FILE sysctl allows a process to dumpt the file descriptor
+ * The KERN_PROC_FILE sysctl allows a process to dump the file descriptor
* array of another process.
*/
#define KF_TYPE_NONE 0
@@ -259,6 +259,10 @@ struct user {
#define KF_VTYPE_VBAD 8
#define KF_VTYPE_UNKNOWN 255
+#define KF_FD_TYPE_CWD -1 /* Current working directory */
+#define KF_FD_TYPE_ROOT -2 /* Root directory */
+#define KF_FD_TYPE_JAIL -3 /* Jail directory */
+
#define KF_FLAG_READ 0x00000001
#define KF_FLAG_WRITE 0x00000002
#define KF_FLAG_APPEND 0x00000004
diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c
index 98e4ef6..950b70d 100644
--- a/usr.bin/procstat/procstat_files.c
+++ b/usr.bin/procstat/procstat_files.c
@@ -140,7 +140,7 @@ procstat_files(pid_t pid, struct kinfo_proc *kipp)
size_t len;
if (!hflag)
- printf("%5s %-16s %3s %1s %1s %-8s %3s %7s %-3s %-12s\n",
+ printf("%5s %-16s %4s %1s %1s %-8s %3s %7s %-3s %-12s\n",
"PID", "COMM", "FD", "T", "V", "FLAGS", "REF", "OFFSET",
"PRO", "NAME");
@@ -172,7 +172,23 @@ procstat_files(pid_t pid, struct kinfo_proc *kipp)
errx(-1, "kinfo_file mismatch");
printf("%5d ", pid);
printf("%-16s ", kipp->ki_comm);
- printf("%3d ", kif->kf_fd);
+ switch (kif->kf_fd) {
+ case KF_FD_TYPE_CWD:
+ printf(" cwd ");
+ break;
+
+ case KF_FD_TYPE_ROOT:
+ printf("root ");
+ break;
+
+ case KF_FD_TYPE_JAIL:
+ printf("jail ");
+ break;
+
+ default:
+ printf("%4d ", kif->kf_fd);
+ break;
+ }
switch (kif->kf_type) {
case KF_TYPE_VNODE:
str = "v";
@@ -264,8 +280,14 @@ procstat_files(pid_t pid, struct kinfo_proc *kipp)
printf("%s", kif->kf_flags & KF_FLAG_NONBLOCK ? "n" : "-");
printf("%s", kif->kf_flags & KF_FLAG_DIRECT ? "d" : "-");
printf("%s ", kif->kf_flags & KF_FLAG_HASLOCK ? "l" : "-");
- printf("%3d ", kif->kf_ref_count);
- printf("%7jd ", (intmax_t)kif->kf_offset);
+ if (kif->kf_ref_count > -1)
+ printf("%3d ", kif->kf_ref_count);
+ else
+ printf("%3c ", '-');
+ if (kif->kf_offset > -1)
+ printf("%7jd ", (intmax_t)kif->kf_offset);
+ else
+ printf("%7c ", '-');
switch (kif->kf_type) {
case KF_TYPE_VNODE:
OpenPOWER on IntegriCloud