Author: bdrewery
Date: Tue Jun 21 20:13:19 2016
New Revision: 302066
URL: https://svnweb.freebsd.org/changeset/base/302066

Log:
  MFC r297156,r297157,r297158,r297159,r297161,r297172,r297200,r297201,r297202,
      r297203,r297256:
  
    r297156:
      Track filemon usage via a proc.p_filemon pointer rather than its own 
lists.
    r297157:
      Stop tracking stat(2).
    r297158:
      Consolidate open(2) and openat(2) code.
    r297159:
      Use curthread for vn_fullpath.
    r297161:
      Attempt to use the namecache for openat(2) path resolution.
    r297172:
      Consolidate common link(2) logic.
    r297200:
      Follow-up r297156: Close the log in filemon_dtr rather than in the last
      reference.
    r297201:
      Return any log write failure encountered when closing the filemon fd.
    r297202:
      Remove unused done argument to copyinstr(9).
    r297203:
      Handle copyin failures.
    r297256:
      Remove unneeded return left from refactoring.
  
  Relnotes:     yes (filemon stability/performance updates)
  Sponsored by: EMC / Isilon Storage Division

Deleted:
  stable/10/sys/dev/filemon/filemon_lock.c
Modified:
  stable/10/share/man/man4/filemon.4
  stable/10/sys/dev/filemon/filemon.c
  stable/10/sys/dev/filemon/filemon_wrapper.c
  stable/10/sys/kern/kern_fork.c
  stable/10/sys/sys/param.h
  stable/10/sys/sys/proc.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/share/man/man4/filemon.4
==============================================================================
--- stable/10/share/man/man4/filemon.4  Tue Jun 21 18:16:45 2016        
(r302065)
+++ stable/10/share/man/man4/filemon.4  Tue Jun 21 20:13:19 2016        
(r302066)
@@ -31,7 +31,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd March 9, 2016
+.Dd June 21, 2016
 .Dt FILEMON 4
 .Os
 .Sh NAME
@@ -83,8 +83,6 @@ System calls are denoted using the follo
 .It Ql R
 .Xr open 2
 for read
-.It Ql S
-.Xr stat 2
 .It Ql W
 .Xr open 2
 for write
@@ -116,6 +114,10 @@ Each takes a single argument.
 Write the internal tracing buffer to the supplied open file descriptor.
 .It Dv FILEMON_SET_PID
 Child process ID to trace.
+This should normally be done under the control of a parent in the child after
+.Xr fork 2
+but before anything else.
+See the example below.
 .El
 .Sh RETURN VALUES
 .\" .Rv -std ioctl
@@ -138,6 +140,35 @@ The
 .Nm
 handle is already associated with a file descriptor.
 .El
+.Pp
+The
+.Fn ioctl
+system call
+with
+.Dv FILEMON_SET_PID
+will fail if:
+.Bl -tag -width Er
+.It Bq Er ESRCH
+No process having the specified process ID exists.
+.It Bq Er EBUSY
+The process ID specified is already being traced and was not the current
+process.
+.El
+.Pp
+The
+.Fn close
+system call on the filemon file descriptor may fail with the errors from
+.Xr write 2
+if any error is encountered while writing the log.
+It may also fail if:
+.Bl -tag -width Er
+.It Bq Er EFAULT
+An invalid address was used for a traced system call argument, resulting in
+no log entry for the system call.
+.It Bq Er ENAMETOOLONG
+An argument for a traced system call was too long, resulting in
+no log entry for the system call.
+.El
 .Sh FILES
 .Bl -tag -width ".Pa /dev/filemon"
 .It Pa /dev/filemon
@@ -198,14 +229,5 @@ A
 device appeared in
 .Fx 9.1 .
 .Sh BUGS
-Loading
-.Nm
-may reduce system performance for the noted syscalls.
-.Pp
-Only children of the set process are logged.
-Processes can escape being traced by double forking.
-This is not seen as a problem as the intended use is build monitoring, which
-does not make sense to have daemons for.
-.Pp
 Unloading the module may panic the system, thus requires using
 .Ic kldunload -f .

Modified: stable/10/sys/dev/filemon/filemon.c
==============================================================================
--- stable/10/sys/dev/filemon/filemon.c Tue Jun 21 18:16:45 2016        
(r302065)
+++ stable/10/sys/dev/filemon/filemon.c Tue Jun 21 20:13:19 2016        
(r302066)
@@ -1,7 +1,7 @@
 /*-
  * Copyright (c) 2011, David E. O'Brien.
  * Copyright (c) 2009-2011, Juniper Networks, Inc.
- * Copyright (c) 2015, EMC Corp.
+ * Copyright (c) 2015-2016, EMC Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/module.h>
 #include <sys/poll.h>
 #include <sys/proc.h>
-#include <sys/queue.h>
 #include <sys/sx.h>
 #include <sys/syscall.h>
 #include <sys/sysent.h>
@@ -80,23 +79,112 @@ static struct cdevsw filemon_cdevsw = {
 MALLOC_DECLARE(M_FILEMON);
 MALLOC_DEFINE(M_FILEMON, "filemon", "File access monitor");
 
+/*
+ * The filemon->lock protects several things currently:
+ * - fname1/fname2/msgbufr are pre-allocated and used per syscall
+ *   for logging and copyins rather than stack variables.
+ * - Serializing the filemon's log output.
+ * - Preventing inheritance or removal of the filemon into proc.p_filemon.
+ */
 struct filemon {
-       TAILQ_ENTRY(filemon) link;      /* Link into the in-use list. */
-       struct sx       lock;           /* Lock mutex for this filemon. */
+       struct sx       lock;           /* Lock for this filemon. */
        struct file     *fp;            /* Output file pointer. */
-       struct proc     *p;             /* The process being monitored. */
        char            fname1[MAXPATHLEN]; /* Temporary filename buffer. */
        char            fname2[MAXPATHLEN]; /* Temporary filename buffer. */
        char            msgbufr[1024];  /* Output message buffer. */
+       int             error;          /* Log write error, returned on 
close(2). */
+       u_int           refcnt;         /* Pointer reference count. */
+       u_int           proccnt;        /* Process count. */
 };
 
-static TAILQ_HEAD(, filemon) filemons_inuse = 
TAILQ_HEAD_INITIALIZER(filemons_inuse);
-static TAILQ_HEAD(, filemon) filemons_free = 
TAILQ_HEAD_INITIALIZER(filemons_free);
-static struct sx access_lock;
-
 static struct cdev *filemon_dev;
+static void filemon_output(struct filemon *filemon, char *msg, size_t len);
+
+static __inline struct filemon *
+filemon_acquire(struct filemon *filemon)
+{
+
+       if (filemon != NULL)
+               refcount_acquire(&filemon->refcnt);
+       return (filemon);
+}
+
+/*
+ * Release a reference and free on the last one.
+ */
+static void
+filemon_release(struct filemon *filemon)
+{
+
+       if (refcount_release(&filemon->refcnt) == 0)
+               return;
+       /*
+        * There are valid cases of releasing while locked, such as in
+        * filemon_untrack_processes, but none which are done where there
+        * is not at least 1 reference remaining.
+        */
+       sx_assert(&filemon->lock, SA_UNLOCKED);
+
+       sx_destroy(&filemon->lock);
+       free(filemon, M_FILEMON);
+}
+
+/*
+ * Acquire the proc's p_filemon reference and lock the filemon.
+ * The proc's p_filemon may not match this filemon on return.
+ */
+static struct filemon *
+filemon_proc_get(struct proc *p)
+{
+       struct filemon *filemon;
+
+       PROC_LOCK(p);
+       filemon = filemon_acquire(p->p_filemon);
+       PROC_UNLOCK(p);
+
+       if (filemon == NULL)
+               return (NULL);
+       /*
+        * The p->p_filemon may have changed by now.  That case is handled
+        * by the exit and fork hooks and filemon_attach_proc specially.
+        */
+       sx_xlock(&filemon->lock);
+       return (filemon);
+}
+
+/* Remove and release the filemon on the given process. */
+static void
+filemon_proc_drop(struct proc *p)
+{
+       struct filemon *filemon;
+
+       KASSERT(p->p_filemon != NULL, ("%s: proc %p NULL p_filemon",
+           __func__, p));
+       sx_assert(&p->p_filemon->lock, SA_XLOCKED);
+       PROC_LOCK(p);
+       filemon = p->p_filemon;
+       p->p_filemon = NULL;
+       --filemon->proccnt;
+       PROC_UNLOCK(p);
+       /*
+        * This should not be the last reference yet.  filemon_release()
+        * cannot be called with filemon locked, which the caller expects
+        * will stay locked.
+        */
+       KASSERT(filemon->refcnt > 1, ("%s: proc %p dropping filemon %p "
+           "with last reference", __func__, p, filemon));
+       filemon_release(filemon);
+}
+
+/* Unlock and release the filemon. */
+static __inline void
+filemon_drop(struct filemon *filemon)
+{
+
+       sx_xunlock(&filemon->lock);
+       filemon_release(filemon);
+}
 
-#include "filemon_lock.c"
 #include "filemon_wrapper.c"
 
 static void
@@ -115,35 +203,151 @@ filemon_comment(struct filemon *filemon)
        filemon_output(filemon, filemon->msgbufr, len);
 }
 
+/*
+ * Invalidate the passed filemon in all processes.
+ */
 static void
-filemon_dtr(void *data)
+filemon_untrack_processes(struct filemon *filemon)
 {
-       struct filemon *filemon = data;
+       struct proc *p;
 
-       if (filemon != NULL) {
-               struct file *fp;
+       sx_assert(&filemon->lock, SA_XLOCKED);
 
-               /* Follow same locking order as filemon_pid_check. */
-               filemon_lock_write();
-               sx_xlock(&filemon->lock);
+       /* Avoid allproc loop if there is no need. */
+       if (filemon->proccnt == 0)
+               return;
+
+       /*
+        * Processes in this list won't go away while here since
+        * filemon_event_process_exit() will lock on filemon->lock
+        * which we hold.
+        */
+       sx_slock(&allproc_lock);
+       FOREACH_PROC_IN_SYSTEM(p) {
+               /*
+                * No PROC_LOCK is needed to compare here since it is
+                * guaranteed to not change since we have its filemon
+                * locked.  Everything that changes this p_filemon will
+                * be locked on it.
+                */
+               if (p->p_filemon == filemon)
+                       filemon_proc_drop(p);
+       }
+       sx_sunlock(&allproc_lock);
+
+       /*
+        * It's possible some references were acquired but will be
+        * dropped shortly as they are restricted from being
+        * inherited.  There is at least the reference in cdevpriv remaining.
+        */
+       KASSERT(filemon->refcnt > 0, ("%s: filemon %p should have "
+           "references still.", __func__, filemon));
+       KASSERT(filemon->proccnt == 0, ("%s: filemon %p should not have "
+           "attached procs still.", __func__, filemon));
+}
 
-               /* Remove from the in-use list. */
-               TAILQ_REMOVE(&filemons_inuse, filemon, link);
+/*
+ * Close out the log.
+ */
+static void
+filemon_close_log(struct filemon *filemon)
+{
+       struct file *fp;
+       struct timeval now;
+       size_t len;
 
-               fp = filemon->fp;
-               filemon->fp = NULL;
-               filemon->p = NULL;
+       sx_assert(&filemon->lock, SA_XLOCKED);
+       if (filemon->fp == NULL)
+               return;
 
-               /* Add to the free list. */
-               TAILQ_INSERT_TAIL(&filemons_free, filemon, link);
+       getmicrotime(&now);
 
-               /* Give up write access. */
-               sx_xunlock(&filemon->lock);
-               filemon_unlock_write();
+       len = snprintf(filemon->msgbufr,
+           sizeof(filemon->msgbufr),
+           "# Stop %ju.%06ju\n# Bye bye\n",
+           (uintmax_t)now.tv_sec, (uintmax_t)now.tv_usec);
+
+       filemon_output(filemon, filemon->msgbufr, len);
+       fp = filemon->fp;
+       filemon->fp = NULL;
+
+       sx_xunlock(&filemon->lock);
+       fdrop(fp, curthread);
+       sx_xlock(&filemon->lock);
+}
 
-               if (fp != NULL)
-                       fdrop(fp, curthread);
+/*
+ * The devfs file is being closed.  Untrace all processes.  It is possible
+ * filemon_close/close(2) was not called.
+ */
+static void
+filemon_dtr(void *data)
+{
+       struct filemon *filemon = data;
+
+       if (filemon == NULL)
+               return;
+
+       sx_xlock(&filemon->lock);
+       /*
+        * Detach the filemon.  It cannot be inherited after this.
+        */
+       filemon_untrack_processes(filemon);
+       filemon_close_log(filemon);
+       filemon_drop(filemon);
+}
+
+/* Attach the filemon to the process. */
+static int
+filemon_attach_proc(struct filemon *filemon, struct proc *p)
+{
+       struct filemon *filemon2;
+
+       sx_assert(&filemon->lock, SA_XLOCKED);
+       PROC_LOCK_ASSERT(p, MA_OWNED);
+       KASSERT((p->p_flag & P_WEXIT) == 0,
+           ("%s: filemon %p attaching to exiting process %p",
+           __func__, filemon, p));
+
+       if (p->p_filemon == filemon)
+               return (0);
+       /*
+        * Don't allow truncating other process traces.  It is
+        * not really intended to trace procs other than curproc
+        * anyhow.
+        */
+       if (p->p_filemon != NULL && p != curproc)
+               return (EBUSY);
+       /*
+        * Historic behavior of filemon has been to let a child initiate
+        * tracing on itself and cease existing tracing.  Bmake
+        * .META + .MAKE relies on this.  It is only relevant for attaching to
+        * curproc.
+        */
+       while (p->p_filemon != NULL) {
+               PROC_UNLOCK(p);
+               sx_xunlock(&filemon->lock);
+               while ((filemon2 = filemon_proc_get(p)) != NULL) {
+                       /* It may have changed. */
+                       if (p->p_filemon == filemon2)
+                               filemon_proc_drop(p);
+                       filemon_drop(filemon2);
+               }
+               sx_xlock(&filemon->lock);
+               PROC_LOCK(p);
+               /*
+                * It may have been attached to, though unlikely.
+                * Try again if needed.
+                */
        }
+
+       KASSERT(p->p_filemon == NULL,
+           ("%s: proc %p didn't detach filemon %p", __func__, p,
+           p->p_filemon));
+       p->p_filemon = filemon_acquire(filemon);
+       ++filemon->proccnt;
+
+       return (0);
 }
 
 static int
@@ -178,10 +382,16 @@ filemon_ioctl(struct cdev *dev, u_long c
 
        /* Set the monitored process ID. */
        case FILEMON_SET_PID:
+               /* Invalidate any existing processes already set. */
+               filemon_untrack_processes(filemon);
+
                error = pget(*((pid_t *)data), PGET_CANDEBUG | PGET_NOTWEXIT,
                    &p);
                if (error == 0) {
-                       filemon->p = p;
+                       KASSERT(p->p_filemon != filemon,
+                           ("%s: proc %p didn't untrack filemon %p",
+                           __func__, p, filemon));
+                       error = filemon_attach_proc(filemon, p);
                        PROC_UNLOCK(p);
                }
                break;
@@ -199,49 +409,48 @@ static int
 filemon_open(struct cdev *dev, int oflags __unused, int devtype __unused,
     struct thread *td __unused)
 {
+       int error;
        struct filemon *filemon;
 
-       /* Get exclusive write access. */
-       filemon_lock_write();
-
-       if ((filemon = TAILQ_FIRST(&filemons_free)) != NULL)
-               TAILQ_REMOVE(&filemons_free, filemon, link);
-
-       /* Give up write access. */
-       filemon_unlock_write();
-
-       if (filemon == NULL) {
-               filemon = malloc(sizeof(struct filemon), M_FILEMON,
-                   M_WAITOK | M_ZERO);
-               sx_init(&filemon->lock, "filemon");
-       }
-
-       devfs_set_cdevpriv(filemon, filemon_dtr);
+       filemon = malloc(sizeof(*filemon), M_FILEMON,
+           M_WAITOK | M_ZERO);
+       sx_init(&filemon->lock, "filemon");
+       refcount_init(&filemon->refcnt, 1);
+
+       error = devfs_set_cdevpriv(filemon, filemon_dtr);
+       if (error != 0)
+               filemon_release(filemon);
 
-       /* Get exclusive write access. */
-       filemon_lock_write();
-
-       /* Add to the in-use list. */
-       TAILQ_INSERT_TAIL(&filemons_inuse, filemon, link);
-
-       /* Give up write access. */
-       filemon_unlock_write();
-
-       return (0);
+       return (error);
 }
 
+/* Called on close of last devfs file handle, before filemon_dtr(). */
 static int
 filemon_close(struct cdev *dev __unused, int flag __unused, int fmt __unused,
     struct thread *td __unused)
 {
+       struct filemon *filemon;
+       int error;
 
-       return (0);
+       if ((error = devfs_get_cdevpriv((void **) &filemon)) != 0)
+               return (error);
+
+       sx_xlock(&filemon->lock);
+       filemon_close_log(filemon);
+       error = filemon->error;
+       sx_xunlock(&filemon->lock);
+       /*
+        * Processes are still being traced but won't log anything
+        * now.  After this call returns filemon_dtr() is called which
+        * will detach processes.
+        */
+
+       return (error);
 }
 
 static void
 filemon_load(void *dummy __unused)
 {
-       sx_init(&access_lock, "filemons_inuse");
 
        /* Install the syscall wrappers. */
        filemon_wrapper_install();
@@ -253,38 +462,11 @@ filemon_load(void *dummy __unused)
 static int
 filemon_unload(void)
 {
-       struct filemon *filemon;
-       int error = 0;
-
-       /* Get exclusive write access. */
-       filemon_lock_write();
-
-       if (TAILQ_FIRST(&filemons_inuse) != NULL)
-               error = EBUSY;
-       else {
-               destroy_dev(filemon_dev);
-
-               /* Deinstall the syscall wrappers. */
-               filemon_wrapper_deinstall();
-       }
 
-       /* Give up write access. */
-       filemon_unlock_write();
+       destroy_dev(filemon_dev);
+       filemon_wrapper_deinstall();
 
-       if (error == 0) {
-               /* free() filemon structs free list. */
-               filemon_lock_write();
-               while ((filemon = TAILQ_FIRST(&filemons_free)) != NULL) {
-                       TAILQ_REMOVE(&filemons_free, filemon, link);
-                       sx_destroy(&filemon->lock);
-                       free(filemon, M_FILEMON);
-               }
-               filemon_unlock_write();
-
-               sx_destroy(&access_lock);
-       }
-
-       return (error);
+       return (0);
 }
 
 static int

Modified: stable/10/sys/dev/filemon/filemon_wrapper.c
==============================================================================
--- stable/10/sys/dev/filemon/filemon_wrapper.c Tue Jun 21 18:16:45 2016        
(r302065)
+++ stable/10/sys/dev/filemon/filemon_wrapper.c Tue Jun 21 20:13:19 2016        
(r302066)
@@ -1,7 +1,7 @@
 /*-
  * Copyright (c) 2011, David E. O'Brien.
  * Copyright (c) 2009-2011, Juniper Networks, Inc.
- * Copyright (c) 2015, EMC Corp.
+ * Copyright (c) 2015-2016, EMC Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -29,8 +29,9 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include <sys/imgact.h>
 #include <sys/eventhandler.h>
+#include <sys/filedesc.h>
+#include <sys/imgact.h>
 #include <sys/sx.h>
 #include <sys/vnode.h>
 
@@ -45,6 +46,7 @@ filemon_output(struct filemon *filemon, 
 {
        struct uio auio;
        struct iovec aiov;
+       int error;
 
        if (filemon->fp == NULL)
                return;
@@ -62,56 +64,33 @@ filemon_output(struct filemon *filemon, 
        if (filemon->fp->f_type == DTYPE_VNODE)
                bwillwrite();
 
-       fo_write(filemon->fp, &auio, curthread->td_ucred, 0, curthread);
-}
-
-static struct filemon *
-filemon_pid_check(struct proc *p)
-{
-       struct filemon *filemon;
-
-       filemon_lock_read();
-       if (TAILQ_EMPTY(&filemons_inuse)) {
-               filemon_unlock_read();
-               return (NULL);
-       }
-       sx_slock(&proctree_lock);
-       while (p->p_pid != 0) {
-               TAILQ_FOREACH(filemon, &filemons_inuse, link) {
-                       if (p == filemon->p) {
-                               sx_sunlock(&proctree_lock);
-                               sx_xlock(&filemon->lock);
-                               filemon_unlock_read();
-                               return (filemon);
-                       }
-               }
-               p = proc_realparent(p);
-       }
-       sx_sunlock(&proctree_lock);
-       filemon_unlock_read();
-       return (NULL);
+       error = fo_write(filemon->fp, &auio, curthread->td_ucred, 0, curthread);
+       if (error != 0)
+               filemon->error = error;
 }
 
 static int
 filemon_wrapper_chdir(struct thread *td, struct chdir_args *uap)
 {
-       int ret;
-       size_t done;
+       int error, ret;
        size_t len;
        struct filemon *filemon;
 
        if ((ret = sys_chdir(td, uap)) == 0) {
-               if ((filemon = filemon_pid_check(curproc)) != NULL) {
-                       copyinstr(uap->path, filemon->fname1,
-                           sizeof(filemon->fname1), &done);
+               if ((filemon = filemon_proc_get(curproc)) != NULL) {
+                       if ((error = copyinstr(uap->path, filemon->fname1,
+                           sizeof(filemon->fname1), NULL)) != 0) {
+                               filemon->error = error;
+                               goto copyfail;
+                       }
 
                        len = snprintf(filemon->msgbufr,
                            sizeof(filemon->msgbufr), "C %d %s\n",
                            curproc->p_pid, filemon->fname1);
 
                        filemon_output(filemon, filemon->msgbufr, len);
-
-                       sx_xunlock(&filemon->lock);
+copyfail:
+                       filemon_drop(filemon);
                }
        }
 
@@ -126,12 +105,11 @@ filemon_event_process_exec(void *arg __u
        char *fullpath, *freepath;
        size_t len;
 
-       if ((filemon = filemon_pid_check(p)) != NULL) {
+       if ((filemon = filemon_proc_get(p)) != NULL) {
                fullpath = "<unknown>";
                freepath = NULL;
 
-               vn_fullpath(FIRST_THREAD_IN_PROC(p), imgp->vp, &fullpath,
-                   &freepath);
+               vn_fullpath(curthread, imgp->vp, &fullpath, &freepath);
 
                len = snprintf(filemon->msgbufr,
                    sizeof(filemon->msgbufr), "E %d %s\n",
@@ -139,321 +117,244 @@ filemon_event_process_exec(void *arg __u
 
                filemon_output(filemon, filemon->msgbufr, len);
 
-               sx_xunlock(&filemon->lock);
+               filemon_drop(filemon);
 
                free(freepath, M_TEMP);
        }
 }
 
-static int
-filemon_wrapper_open(struct thread *td, struct open_args *uap)
+static void
+_filemon_wrapper_openat(struct thread *td, char *upath, int flags, int fd)
 {
-       int ret;
-       size_t done;
+       int error;
        size_t len;
+       struct file *fp;
        struct filemon *filemon;
+       char *atpath, *freepath;
+       cap_rights_t rights;
 
-       if ((ret = sys_open(td, uap)) == 0) {
-               if ((filemon = filemon_pid_check(curproc)) != NULL) {
-                       copyinstr(uap->path, filemon->fname1,
-                           sizeof(filemon->fname1), &done);
-
-                       if (uap->flags & O_RDWR) {
-                               /*
-                                * We'll get the W record below, but need
-                                * to also output an R to distingish from
-                                * O_WRONLY.
-                                */
-                               len = snprintf(filemon->msgbufr,
-                                   sizeof(filemon->msgbufr), "R %d %s\n",
-                                   curproc->p_pid, filemon->fname1);
-                               filemon_output(filemon, filemon->msgbufr, len);
-                       }
-
+       if ((filemon = filemon_proc_get(curproc)) != NULL) {
+               atpath = "";
+               freepath = NULL;
+               fp = NULL;
 
+               if ((error = copyinstr(upath, filemon->fname1,
+                   sizeof(filemon->fname1), NULL)) != 0) {
+                       filemon->error = error;
+                       goto copyfail;
+               }
+
+               if (filemon->fname1[0] != '/' && fd != AT_FDCWD) {
+                       /*
+                        * rats - we cannot do too much about this.
+                        * the trace should show a dir we read
+                        * recently.. output an A record as a clue
+                        * until we can do better.
+                        * XXX: This may be able to come out with
+                        * the namecache lookup now.
+                        */
                        len = snprintf(filemon->msgbufr,
-                           sizeof(filemon->msgbufr), "%c %d %s\n",
-                           (uap->flags & O_ACCMODE) ? 'W':'R',
+                           sizeof(filemon->msgbufr), "A %d %s\n",
                            curproc->p_pid, filemon->fname1);
                        filemon_output(filemon, filemon->msgbufr, len);
-
-                       sx_xunlock(&filemon->lock);
+                       /*
+                        * Try to resolve the path from the vnode using the
+                        * namecache.  It may be inaccurate, but better
+                        * than nothing.
+                        */
+                       if (getvnode(td->td_proc->p_fd, fd,
+                           cap_rights_init(&rights, CAP_LOOKUP), &fp) == 0) {
+                               vn_fullpath(td, fp->f_vnode, &atpath,
+                                   &freepath);
+                       }
+               }
+               if (flags & O_RDWR) {
+                       /*
+                        * We'll get the W record below, but need
+                        * to also output an R to distinguish from
+                        * O_WRONLY.
+                        */
+                       len = snprintf(filemon->msgbufr,
+                           sizeof(filemon->msgbufr), "R %d %s%s%s\n",
+                           curproc->p_pid, atpath,
+                           atpath[0] != '\0' ? "/" : "", filemon->fname1);
+                       filemon_output(filemon, filemon->msgbufr, len);
                }
-       }
 
-       return (ret);
+               len = snprintf(filemon->msgbufr,
+                   sizeof(filemon->msgbufr), "%c %d %s%s%s\n",
+                   (flags & O_ACCMODE) ? 'W':'R',
+                   curproc->p_pid, atpath,
+                   atpath[0] != '\0' ? "/" : "", filemon->fname1);
+               filemon_output(filemon, filemon->msgbufr, len);
+copyfail:
+               filemon_drop(filemon);
+               if (fp != NULL)
+                       fdrop(fp, td);
+               free(freepath, M_TEMP);
+       }
 }
 
 static int
-filemon_wrapper_openat(struct thread *td, struct openat_args *uap)
+filemon_wrapper_open(struct thread *td, struct open_args *uap)
 {
        int ret;
-       size_t done;
-       size_t len;
-       struct filemon *filemon;
-
-       if ((ret = sys_openat(td, uap)) == 0) {
-               if ((filemon = filemon_pid_check(curproc)) != NULL) {
-                       copyinstr(uap->path, filemon->fname1,
-                           sizeof(filemon->fname1), &done);
-
-                       filemon->fname2[0] = '\0';
-                       if (filemon->fname1[0] != '/' && uap->fd != AT_FDCWD) {
-                               /*
-                                * rats - we cannot do too much about this.
-                                * the trace should show a dir we read
-                                * recently.. output an A record as a clue
-                                * until we can do better.
-                                */
-                               len = snprintf(filemon->msgbufr,
-                                   sizeof(filemon->msgbufr), "A %d %s\n",
-                                   curproc->p_pid, filemon->fname1);
-                               filemon_output(filemon, filemon->msgbufr, len);
-                       }
-                       if (uap->flag & O_RDWR) {
-                               /*
-                                * We'll get the W record below, but need
-                                * to also output an R to distingish from
-                                * O_WRONLY.
-                                */
-                               len = snprintf(filemon->msgbufr,
-                                   sizeof(filemon->msgbufr), "R %d %s%s\n",
-                                   curproc->p_pid, filemon->fname2, 
filemon->fname1);
-                               filemon_output(filemon, filemon->msgbufr, len);
-                       }
-
-
-                       len = snprintf(filemon->msgbufr,
-                           sizeof(filemon->msgbufr), "%c %d %s%s\n",
-                           (uap->flag & O_ACCMODE) ? 'W':'R',
-                           curproc->p_pid, filemon->fname2, filemon->fname1);
-                       filemon_output(filemon, filemon->msgbufr, len);
 
-                       sx_xunlock(&filemon->lock);
-               }
-       }
+       if ((ret = sys_open(td, uap)) == 0)
+               _filemon_wrapper_openat(td, uap->path, uap->flags, AT_FDCWD);
 
        return (ret);
 }
 
 static int
-filemon_wrapper_rename(struct thread *td, struct rename_args *uap)
+filemon_wrapper_openat(struct thread *td, struct openat_args *uap)
 {
        int ret;
-       size_t done;
-       size_t len;
-       struct filemon *filemon;
 
-       if ((ret = sys_rename(td, uap)) == 0) {
-               if ((filemon = filemon_pid_check(curproc)) != NULL) {
-                       copyinstr(uap->from, filemon->fname1,
-                           sizeof(filemon->fname1), &done);
-                       copyinstr(uap->to, filemon->fname2,
-                           sizeof(filemon->fname2), &done);
-
-                       len = snprintf(filemon->msgbufr,
-                           sizeof(filemon->msgbufr), "M %d '%s' '%s'\n",
-                           curproc->p_pid, filemon->fname1, filemon->fname2);
-
-                       filemon_output(filemon, filemon->msgbufr, len);
-
-                       sx_xunlock(&filemon->lock);
-               }
-       }
+       if ((ret = sys_openat(td, uap)) == 0)
+               _filemon_wrapper_openat(td, uap->path, uap->flag, uap->fd);
 
        return (ret);
 }
 
 static int
-filemon_wrapper_link(struct thread *td, struct link_args *uap)
+filemon_wrapper_rename(struct thread *td, struct rename_args *uap)
 {
-       int ret;
-       size_t done;
+       int error, ret;
        size_t len;
        struct filemon *filemon;
 
-       if ((ret = sys_link(td, uap)) == 0) {
-               if ((filemon = filemon_pid_check(curproc)) != NULL) {
-                       copyinstr(uap->path, filemon->fname1,
-                           sizeof(filemon->fname1), &done);
-                       copyinstr(uap->link, filemon->fname2,
-                           sizeof(filemon->fname2), &done);
+       if ((ret = sys_rename(td, uap)) == 0) {
+               if ((filemon = filemon_proc_get(curproc)) != NULL) {
+                       if (((error = copyinstr(uap->from, filemon->fname1,
+                            sizeof(filemon->fname1), NULL)) != 0) ||
+                           ((error = copyinstr(uap->to, filemon->fname2,
+                            sizeof(filemon->fname2), NULL)) != 0)) {
+                               filemon->error = error;
+                               goto copyfail;
+                       }
 
                        len = snprintf(filemon->msgbufr,
-                           sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
+                           sizeof(filemon->msgbufr), "M %d '%s' '%s'\n",
                            curproc->p_pid, filemon->fname1, filemon->fname2);
 
                        filemon_output(filemon, filemon->msgbufr, len);
-
-                       sx_xunlock(&filemon->lock);
+copyfail:
+                       filemon_drop(filemon);
                }
        }
 
        return (ret);
 }
 
-static int
-filemon_wrapper_symlink(struct thread *td, struct symlink_args *uap)
+static void
+_filemon_wrapper_link(struct thread *td, char *upath1, char *upath2)
 {
-       int ret;
-       size_t done;
-       size_t len;
        struct filemon *filemon;
+       size_t len;
+       int error;
 
-       if ((ret = sys_symlink(td, uap)) == 0) {
-               if ((filemon = filemon_pid_check(curproc)) != NULL) {
-                       copyinstr(uap->path, filemon->fname1,
-                           sizeof(filemon->fname1), &done);
-                       copyinstr(uap->link, filemon->fname2,
-                           sizeof(filemon->fname2), &done);
-
-                       len = snprintf(filemon->msgbufr,
-                           sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
-                           curproc->p_pid, filemon->fname1, filemon->fname2);
+       if ((filemon = filemon_proc_get(curproc)) != NULL) {
+               if (((error = copyinstr(upath1, filemon->fname1,
+                    sizeof(filemon->fname1), NULL)) != 0) ||
+                   ((error = copyinstr(upath2, filemon->fname2,
+                    sizeof(filemon->fname2), NULL)) != 0)) {
+                       filemon->error = error;
+                       goto copyfail;
+               }
 
-                       filemon_output(filemon, filemon->msgbufr, len);
+               len = snprintf(filemon->msgbufr,
+                   sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
+                   curproc->p_pid, filemon->fname1, filemon->fname2);
 
-                       sx_xunlock(&filemon->lock);
-               }
+               filemon_output(filemon, filemon->msgbufr, len);
+copyfail:
+               filemon_drop(filemon);
        }
-
-       return (ret);
 }
 
 static int
-filemon_wrapper_linkat(struct thread *td, struct linkat_args *uap)
+filemon_wrapper_link(struct thread *td, struct link_args *uap)
 {
        int ret;
-       size_t done;
-       size_t len;
-       struct filemon *filemon;
-
-       if ((ret = sys_linkat(td, uap)) == 0) {
-               if ((filemon = filemon_pid_check(curproc)) != NULL) {
-                       copyinstr(uap->path1, filemon->fname1,
-                           sizeof(filemon->fname1), &done);
-                       copyinstr(uap->path2, filemon->fname2,
-                           sizeof(filemon->fname2), &done);
-
-                       len = snprintf(filemon->msgbufr,
-                           sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
-                           curproc->p_pid, filemon->fname1, filemon->fname2);
-
-                       filemon_output(filemon, filemon->msgbufr, len);
 
-                       sx_xunlock(&filemon->lock);
-               }
-       }
+       if ((ret = sys_link(td, uap)) == 0)
+               _filemon_wrapper_link(td, uap->path, uap->link);
 
        return (ret);
 }
 
 static int
-filemon_wrapper_stat(struct thread *td, struct stat_args *uap)
+filemon_wrapper_symlink(struct thread *td, struct symlink_args *uap)
 {
        int ret;
-       size_t done;
-       size_t len;
-       struct filemon *filemon;
 
-       if ((ret = sys_stat(td, uap)) == 0) {
-               if ((filemon = filemon_pid_check(curproc)) != NULL) {
-                       copyinstr(uap->path, filemon->fname1,
-                           sizeof(filemon->fname1), &done);
-
-                       len = snprintf(filemon->msgbufr,
-                           sizeof(filemon->msgbufr), "S %d %s\n",
-                           curproc->p_pid, filemon->fname1);
-
-                       filemon_output(filemon, filemon->msgbufr, len);
-
-                       sx_xunlock(&filemon->lock);
-               }
-       }
+       if ((ret = sys_symlink(td, uap)) == 0)
+               _filemon_wrapper_link(td, uap->path, uap->link);
 
        return (ret);
 }
 
-#if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
 static int
-filemon_wrapper_freebsd32_stat(struct thread *td,
-    struct freebsd32_stat_args *uap)
+filemon_wrapper_linkat(struct thread *td, struct linkat_args *uap)
 {
        int ret;
-       size_t done;
-       size_t len;
-       struct filemon *filemon;
-
-       if ((ret = freebsd32_stat(td, uap)) == 0) {

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to