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"

Reply via email to