Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys First cut of simple syscall wrapper, which make(1) can use



details:   https://anonhg.NetBSD.org/src/rev/4b4fa6c77a13
branches:  trunk
changeset: 757637:4b4fa6c77a13
user:      sjg <sjg%NetBSD.org@localhost>
date:      Thu Sep 09 00:10:16 2010 +0000

description:
First cut of simple syscall wrapper, which make(1) can use
to track process activity.

diffstat:

 sys/dev/filemon/filemon.c         |  366 ++++++++++++++++++++++++++++++++++++
 sys/dev/filemon/filemon.h         |   52 +++++
 sys/dev/filemon/filemon_wrapper.c |  385 ++++++++++++++++++++++++++++++++++++++
 sys/dev/filemon/mknod-sh          |   22 ++
 sys/modules/filemon/Makefile      |   11 +
 5 files changed, 836 insertions(+), 0 deletions(-)

diffs (truncated from 856 to 300 lines):

diff -r 293897e562c7 -r 4b4fa6c77a13 sys/dev/filemon/filemon.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/filemon/filemon.c Thu Sep 09 00:10:16 2010 +0000
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2010, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: filemon.c,v 1.1 2010/09/09 00:10:16 sjg Exp $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/fcntl.h>
+#include <sys/rwlock.h>
+#include <sys/condvar.h>
+#include <sys/lwp.h>
+#include <sys/proc.h>
+#include <sys/kmem.h>
+#include <sys/syslog.h>
+
+#include "filemon.h"
+
+MODULE(MODULE_CLASS_DRIVER, filemon, NULL);
+
+static dev_type_open(filemon_open);
+
+static struct cdevsw filemon_cdevsw = {
+       .d_open = filemon_open,
+       .d_flag = D_MPSAFE,
+       .d_close = noclose,
+       .d_read = noread,
+       .d_write = nowrite,
+       .d_ioctl = noioctl,
+       .d_stop = nostop,
+       .d_tty = notty,
+       .d_poll = nopoll,
+       .d_mmap = nommap,
+       .d_kqfilter = nokqfilter,
+};
+
+static int filemon_ioctl(struct file *, u_long, void *);
+static int filemon_close(struct file *);
+
+static const struct fileops filemon_fileops = {
+       .fo_ioctl = filemon_ioctl,
+       .fo_close = filemon_close,
+       .fo_read = fbadop_read,
+       .fo_write = fbadop_write,
+       .fo_fcntl = fnullop_fcntl,
+       .fo_poll = fnullop_poll,
+       .fo_stat = fbadop_stat,
+       .fo_kqfilter = fnullop_kqfilter,
+};
+
+static krwlock_t filemon_mtx;
+
+static TAILQ_HEAD(, filemon) filemons_inuse =
+       TAILQ_HEAD_INITIALIZER(filemons_inuse);
+
+#ifdef DEBUG
+static int logLevel = LOG_DEBUG;
+#endif
+
+void
+filemon_output(struct filemon * filemon, char *msg, size_t len)
+{
+       struct uio auio;
+       struct iovec aiov;
+
+       if (filemon->fm_fp == NULL)
+               return;
+
+       aiov.iov_base = msg;
+       aiov.iov_len = len;
+       auio.uio_iov = &aiov;
+       auio.uio_iovcnt = 1;
+       auio.uio_resid = len;
+       auio.uio_rw = UIO_WRITE;
+       auio.uio_offset = (off_t) - 1;
+       uio_setup_sysspace(&auio);
+
+#ifdef DEBUG
+       {
+               char *cp;
+               int x = 16;
+
+               cp = strchr(msg, '\n');
+               if (cp && cp - msg <= 16)
+                       x = (cp - msg) - 2;
+               log(logLevel, "filemont_output:('%.*s%s'", x,
+                   (x < 16) ? "..." : "", msg);
+       }
+#endif
+       (*filemon->fm_fp->f_ops->fo_write) (filemon->fm_fp,
+           &(filemon->fm_fp->f_offset),
+           &auio, curlwp->l_cred, FOF_UPDATE_OFFSET);
+}
+
+static void
+filemon_comment(struct filemon * filemon)
+{
+       int len;
+
+       len = snprintf(filemon->fm_msgbufr, sizeof(filemon->fm_msgbufr),
+           "# filemon version 2\n# Target pid %d\nV 2\n",
+           curproc->p_pid);
+
+       filemon_output(filemon, filemon->fm_msgbufr, len);
+}
+
+
+static struct filemon *
+filemon_pid_check(struct proc * p)
+{
+       struct filemon *filemon;
+
+       TAILQ_FOREACH(filemon, &filemons_inuse, fm_link) {
+               if (p->p_pid == filemon->fm_pid)
+                       return (filemon);
+       }
+
+       if (p->p_pptr == NULL)
+               return (NULL);
+
+       return (filemon_pid_check(p->p_pptr));
+}
+
+/*
+ * return exclusive access to a filemon struct
+ */
+struct filemon *
+filemon_lookup(struct proc * p)
+{
+       struct filemon *filemon;
+
+       rw_enter(&filemon_mtx, RW_READER);
+       filemon = filemon_pid_check(p);
+       if (filemon) {
+               rw_enter(&filemon->fm_mtx, RW_WRITER);
+       }
+       rw_exit(&filemon_mtx);
+       return filemon;
+}
+
+static struct filemon *
+filemon_fp_data(struct file * fp, int lck)
+{
+       struct filemon *filemon;
+       
+       rw_enter(&filemon_mtx, RW_READER);
+       filemon = fp->f_data;
+       if (filemon && lck) {
+               rw_enter(&filemon->fm_mtx, lck);
+       }
+       rw_exit(&filemon_mtx);
+       return filemon;
+}
+
+static int n_open = 0;
+
+static int
+filemon_open(dev_t dev, int oflags __unused, int mode __unused,
+    struct lwp * l __unused)
+{
+       struct filemon *filemon;
+       struct file *fp;
+       int error, fd;
+
+       /* falloc() will use the descriptor for us. */
+       if ((error = fd_allocfile(&fp, &fd)) != 0)
+               return error;
+
+       filemon = kmem_alloc(sizeof(struct filemon), KM_SLEEP);
+       if (!filemon)
+               return ENOMEM;
+
+       rw_init(&filemon->fm_mtx);
+       filemon->fm_fd = -1;
+       filemon->fm_fp = NULL;
+       filemon->fm_pid = curproc->p_pid;
+
+       rw_enter(&filemon_mtx, RW_WRITER);
+       n_open++;
+
+       TAILQ_INSERT_TAIL(&filemons_inuse, filemon, fm_link);
+
+       rw_exit(&filemon_mtx);
+       return fd_clone(fp, fd, oflags, &filemon_fileops, filemon);
+}
+
+
+static int
+filemon_close(struct file * fp)
+{
+       struct filemon *filemon;
+
+#ifdef DEBUG
+       log(logLevel, "filemon_close()");
+#endif
+       /*
+        * Follow the same lock order as filemon_lookup()
+        * and filemon_fp_data() but hold exclusive access to
+        * filemon_mtx until we are done.
+        */
+       rw_enter(&filemon_mtx, RW_WRITER);
+       filemon = fp->f_data;
+       if (!filemon) {
+               rw_exit(&filemon_mtx);
+               return EBADF;
+       }
+       /* ensure that filemon_lookup() will now fail */
+       TAILQ_REMOVE(&filemons_inuse, filemon, fm_link);
+       n_open--;
+       /* ensure that filemon_fp_data() will now fail */
+       fp->f_data = NULL;
+
+       /*
+        * once we have exclusive access, it should never be used again
+        */
+       rw_enter(&filemon->fm_mtx, RW_WRITER);
+       if (filemon->fm_fp) {
+               fd_putfile(filemon->fm_fd);     /* release our reference */
+               filemon->fm_fp = NULL;
+       }
+       rw_exit(&filemon->fm_mtx);
+       rw_destroy(&filemon->fm_mtx);
+       kmem_free(filemon, sizeof(struct filemon));
+       rw_exit(&filemon_mtx);
+       return (0);
+}
+
+static int
+filemon_ioctl(struct file * fp, u_long cmd, void *data)
+{
+       int error = 0;
+       struct filemon *filemon;
+
+
+#ifdef DEBUG
+       log(logLevel, "filemon_ioctl(%lu)", cmd);;
+#endif
+
+       /*
+        * this ensures we cannot get filemon if it is closing.
+        */
+       filemon = filemon_fp_data(fp, RW_WRITER);
+       if (!filemon)
+               return EBADF;
+
+       switch (cmd) {
+       case FILEMON_SET_FD:
+               /* Set the output file descriptor. */
+               filemon->fm_fd = *((int *) data);
+               if ((filemon->fm_fp = fd_getfile(filemon->fm_fd)) == NULL) {
+                       rw_exit(&filemon->fm_mtx);
+                       return EBADF;
+               }
+               /* Write the file header. */
+               filemon_comment(filemon);
+               break;
+
+       case FILEMON_SET_PID:
+               /* Set the monitored process ID. */
+               filemon->fm_pid = *((pid_t *) data);
+               break;
+
+       default:
+               error = EINVAL;
+               break;
+       }
+
+       rw_exit(&filemon->fm_mtx);



Home | Main Index | Thread Index | Old Index