From 4177d9f7d3bc8e8bbf8d7bc6fc0df86028e7b066 Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Tue, 22 Mar 2016 22:41:07 +0000 Subject: [PATCH] Return any log write failure encountered when closing the filemon fd. Discussed with: sjg, markj Reviewed by: sjg MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division --- share/man/man4/filemon.4 | 6 ++++++ sys/dev/filemon/filemon.c | 24 ++++++++++++++++++++++-- sys/dev/filemon/filemon_wrapper.c | 5 ++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/share/man/man4/filemon.4 b/share/man/man4/filemon.4 index 60f622dd13b..8b78d1b0c07 100644 --- a/share/man/man4/filemon.4 +++ b/share/man/man4/filemon.4 @@ -161,6 +161,12 @@ No process having the specified process ID exists. 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. .Sh FILES .Bl -tag -width ".Pa /dev/filemon" .It Pa /dev/filemon diff --git a/sys/dev/filemon/filemon.c b/sys/dev/filemon/filemon.c index 37b9be672c5..564d0f16fb0 100644 --- a/sys/dev/filemon/filemon.c +++ b/sys/dev/filemon/filemon.c @@ -92,6 +92,7 @@ struct filemon { 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. */ }; @@ -277,7 +278,10 @@ filemon_close_log(struct filemon *filemon) return; } -/* The devfs file is being closed. Untrace all processes. */ +/* + * 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) { @@ -422,12 +426,28 @@ filemon_open(struct cdev *dev, int oflags __unused, int devtype __unused, 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 diff --git a/sys/dev/filemon/filemon_wrapper.c b/sys/dev/filemon/filemon_wrapper.c index 3acf92c9147..3270600efcb 100644 --- a/sys/dev/filemon/filemon_wrapper.c +++ b/sys/dev/filemon/filemon_wrapper.c @@ -46,6 +46,7 @@ filemon_output(struct filemon *filemon, char *msg, size_t len) { struct uio auio; struct iovec aiov; + int error; if (filemon->fp == NULL) return; @@ -63,7 +64,9 @@ filemon_output(struct filemon *filemon, char *msg, size_t len) if (filemon->fp->f_type == DTYPE_VNODE) bwillwrite(); - fo_write(filemon->fp, &auio, curthread->td_ucred, 0, curthread); + error = fo_write(filemon->fp, &auio, curthread->td_ucred, 0, curthread); + if (error != 0) + filemon->error = error; } static int