Author: mjg Date: Thu Nov 6 08:12:34 2014 New Revision: 274167 URL: https://svnweb.freebsd.org/changeset/base/274167
Log: Add sysctl kern.proc.cwd It returns only current working directory of given process which saves a lot of overhead over kern.proc.filedesc if given proc has a lot of open fds. Submitted by: Tiwei Bie <btw mail.ustc.edu.cn> (slightly modified) X-Additional: JuniorJobs project Modified: head/sys/kern/kern_descrip.c head/sys/sys/sysctl.h head/sys/sys/user.h Modified: head/sys/kern/kern_descrip.c ============================================================================== --- head/sys/kern/kern_descrip.c Thu Nov 6 07:44:10 2014 (r274166) +++ head/sys/kern/kern_descrip.c Thu Nov 6 08:12:34 2014 (r274167) @@ -3406,6 +3406,73 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC CTLFLAG_RD|CTLFLAG_MPSAFE, sysctl_kern_proc_filedesc, "Process filedesc entries"); +/* + * Store a process current working directory information to sbuf. + * + * Takes a locked proc as argument, and returns with the proc unlocked. + */ +int +kern_proc_cwd_out(struct proc *p, struct sbuf *sb, ssize_t maxlen) +{ + struct filedesc *fdp; + struct export_fd_buf *efbuf; + int error; + + PROC_LOCK_ASSERT(p, MA_OWNED); + + fdp = fdhold(p); + PROC_UNLOCK(p); + if (fdp == NULL) + return (EINVAL); + + efbuf = malloc(sizeof(*efbuf), M_TEMP, M_WAITOK); + efbuf->fdp = fdp; + efbuf->sb = sb; + efbuf->remainder = maxlen; + + FILEDESC_SLOCK(fdp); + if (fdp->fd_cdir == NULL) + error = EINVAL; + else { + vref(fdp->fd_cdir); + error = export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD, + FREAD, efbuf); + } + FILEDESC_SUNLOCK(fdp); + fddrop(fdp); + free(efbuf, M_TEMP); + return (error); +} + +/* + * Get per-process current working directory. + */ +static int +sysctl_kern_proc_cwd(SYSCTL_HANDLER_ARGS) +{ + struct sbuf sb; + struct proc *p; + ssize_t maxlen; + int error, error2, *name; + + name = (int *)arg1; + + sbuf_new_for_sysctl(&sb, NULL, sizeof(struct kinfo_file), req); + error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p); + if (error != 0) { + sbuf_delete(&sb); + return (error); + } + maxlen = req->oldptr != NULL ? req->oldlen : -1; + error = kern_proc_cwd_out(p, &sb, maxlen); + error2 = sbuf_finish(&sb); + sbuf_delete(&sb); + return (error != 0 ? error : error2); +} + +static SYSCTL_NODE(_kern_proc, KERN_PROC_CWD, cwd, CTLFLAG_RD|CTLFLAG_MPSAFE, + sysctl_kern_proc_cwd, "Process current working directory"); + #ifdef DDB /* * For the purposes of debugging, generate a human-readable string for the Modified: head/sys/sys/sysctl.h ============================================================================== --- head/sys/sys/sysctl.h Thu Nov 6 07:44:10 2014 (r274166) +++ head/sys/sys/sysctl.h Thu Nov 6 08:12:34 2014 (r274167) @@ -657,6 +657,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_e #define KERN_PROC_UMASK 39 /* process umask */ #define KERN_PROC_OSREL 40 /* osreldate for process binary */ #define KERN_PROC_SIGTRAMP 41 /* signal trampoline location */ +#define KERN_PROC_CWD 42 /* process current working directory */ /* * KERN_IPC identifiers Modified: head/sys/sys/user.h ============================================================================== --- head/sys/sys/user.h Thu Nov 6 07:44:10 2014 (r274166) +++ head/sys/sys/user.h Thu Nov 6 08:12:34 2014 (r274167) @@ -530,6 +530,7 @@ struct sbuf; */ int kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen); +int kern_proc_cwd_out(struct proc *p, struct sbuf *sb, ssize_t maxlen); int kern_proc_out(struct proc *p, struct sbuf *sb, int flags); int kern_proc_vmmap_out(struct proc *p, struct sbuf *sb); _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"