> Another possibility would be to change filemon(4) to do fd_getfile
> each it needs to use the file descriptor.  This makes it a little
> more brittle (fails if you close the descriptor), but would sidestep
> the problem.

Hmmm, perhaps.  Failure would not be a problem, since we would just
revert to the initial "output file unspecified" conditions.

I think I like this approach.  :)  I'll give it a try.

This actually works quite well. Please see the attached diffs for your review.

One possible problem is what happens if the monitoring program closes the file descriptor, and then re-uses that fd? I've included a check to compare the original 'struct file *' pointer with the current one, which will catch "some" instances, but not guaranteed to catch them all. It could be a bit of a surprise if filemon output shows up in unexpected places. :)

Because of this potential for surprising the user, I think I'm still leaning to my earlier proposal of extending exithook processing. But given the limited number of use-cases for filemon, I could live with making the fd_getfile()-only-when-you-need-it change instead.


+------------------+--------------------------+------------------------+
| Paul Goyette     | PGP Key fingerprint:     | E-mail addresses:      |
| (Retired)        | FA29 0E3B 35AF E8AE 6651 | paul at whooppee.com   |
| Kernel Developer | 0786 F758 55DE 53BA 7731 | pgoyette at netbsd.org |
+------------------+--------------------------+------------------------+
Index: filemon.c
===================================================================
RCS file: /cvsroot/src/sys/dev/filemon/filemon.c,v
retrieving revision 1.24
diff -u -p -r1.24 filemon.c
--- filemon.c   5 Jan 2016 22:08:54 -0000       1.24
+++ filemon.c   7 Jan 2016 00:45:46 -0000
@@ -94,9 +94,21 @@ filemon_output(struct filemon * filemon,
 {
        struct uio auio;
        struct iovec aiov;
+       struct file *fp;     /* Output file pointer. */
 
-       if (filemon->fm_fp == NULL)
+
+       if (filemon->fm_fp == NULL)     /* No output file specified */
+               return;
+       if ((fp = fd_getfile(filemon->fm_fd)) != filemon->fm_fp) {
+               /*
+                * The file descriptor refers to a different file
+                * than when it was passed to SET_FD.  So assume we
+                * never had an output file.
+                */
+               filemon->fm_fp = NULL;
+               filemon->fm_fd = -1;
                return;
+       }
 
        aiov.iov_base = msg;
        aiov.iov_len = len;
@@ -122,6 +134,7 @@ filemon_output(struct filemon * filemon,
        (*filemon->fm_fp->f_ops->fo_write) (filemon->fm_fp,
            &(filemon->fm_fp->f_offset),
            &auio, curlwp->l_cred, FOF_UPDATE_OFFSET);
+       fd_putfile(filemon->fm_fd);     /* release our reference */
 }
 
 void
@@ -264,10 +277,7 @@ filemon_close(struct file * fp)
         * 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;
-       }
+       filemon->fm_fp = NULL;
        rw_exit(&filemon->fm_mtx);
        rw_destroy(&filemon->fm_mtx);
        kmem_free(filemon, sizeof(struct filemon));
@@ -309,6 +319,7 @@ filemon_ioctl(struct file * fp, u_long c
                        error = EBADF;
                        break;
                }
+               fd_putfile(filemon->fm_fd);
                /* Write the file header. */
                filemon_comment(filemon);
                break;

Reply via email to