summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralfred <alfred@FreeBSD.org>2004-07-04 10:52:54 +0000
committeralfred <alfred@FreeBSD.org>2004-07-04 10:52:54 +0000
commitbbaa6c3ec045b7de225f726d3c9367510b287184 (patch)
treee36ccfebbc87cf44cd8c6c2eedfe0a0290e0350a
parent68fa9f13518916e9d3dc979c995d384f129e12d9 (diff)
downloadFreeBSD-src-bbaa6c3ec045b7de225f726d3c9367510b287184.zip
FreeBSD-src-bbaa6c3ec045b7de225f726d3c9367510b287184.tar.gz
Introduce a new kevent filter. EVFILT_FS that will be used to signal
generic filesystem events to userspace. Currently only mount and unmount of filesystems are signalled. Soon to be added, up/down status of NFS. Introduce a sysctl node used to route requests to/from filesystems based on filesystem ids. Introduce a new vfsop, vfs_sysctl(mp, req) that is used as the callback/ entrypoint by the sysctl code to change individual filesystems.
-rw-r--r--sys/kern/kern_event.c2
-rw-r--r--sys/kern/vfs_mount.c2
-rw-r--r--sys/kern/vfs_subr.c62
-rw-r--r--sys/sys/event.h3
-rw-r--r--sys/sys/mount.h63
5 files changed, 131 insertions, 1 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 0a9aaad..bd0e6d9 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -132,6 +132,7 @@ struct filterops null_filtops =
{ 0, filt_nullattach, NULL, NULL };
extern struct filterops sig_filtops;
+extern struct filterops fs_filtops;
/*
* Table for for all system-defined filters.
@@ -145,6 +146,7 @@ static struct filterops *sysfilt_ops[] = {
&sig_filtops, /* EVFILT_SIGNAL */
&timer_filtops, /* EVFILT_TIMER */
&file_filtops, /* EVFILT_NETDEV */
+ &fs_filtops, /* EVFILT_FS */
};
static int
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index fc39a6b..d759646 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -928,6 +928,7 @@ update:
mtx_lock(&mountlist_mtx);
TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
mtx_unlock(&mountlist_mtx);
+ vfs_event_signal(NULL, VQ_MOUNT, NULL);
if (VFS_ROOT(mp, &newdp))
panic("mount: lost mount");
checkdirs(vp, newdp);
@@ -1173,6 +1174,7 @@ dounmount(mp, flags, td)
if ((coveredvp = mp->mnt_vnodecovered) != NULL)
coveredvp->v_mountedhere = NULL;
mtx_unlock(&mountlist_mtx);
+ vfs_event_signal(NULL, VQ_UNMOUNT, NULL);
vfs_mount_destroy(mp, td);
if (coveredvp != NULL)
vrele(coveredvp);
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index af6106a..daef020 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/conf.h>
+#include <sys/event.h>
#include <sys/eventhandler.h>
#include <sys/extattr.h>
#include <sys/fcntl.h>
@@ -3906,3 +3907,64 @@ vop_unlock_post(void *ap, int rc)
ASSERT_VI_UNLOCKED(a->a_vp, "VOP_UNLOCK");
}
#endif /* DEBUG_VFS_LOCKS */
+
+static struct klist fs_klist = SLIST_HEAD_INITIALIZER(&fs_klist);
+
+void
+vfs_event_signal(fsid_t *fsid, u_int32_t event, void *data __unused)
+{
+
+ KNOTE(&fs_klist, event);
+}
+
+static int filt_fsattach(struct knote *kn);
+static void filt_fsdetach(struct knote *kn);
+static int filt_fsevent(struct knote *kn, long hint);
+
+struct filterops fs_filtops =
+ { 0, filt_fsattach, filt_fsdetach, filt_fsevent };
+
+static int
+filt_fsattach(struct knote *kn)
+{
+
+ kn->kn_flags |= EV_CLEAR;
+ SLIST_INSERT_HEAD(&fs_klist, kn, kn_selnext);
+ return (0);
+}
+
+static void
+filt_fsdetach(struct knote *kn)
+{
+
+ SLIST_REMOVE(&fs_klist, kn, knote, kn_selnext);
+}
+
+static int
+filt_fsevent(struct knote *kn, long hint)
+{
+
+ kn->kn_fflags |= hint;
+ return (kn->kn_fflags != 0);
+}
+
+static int
+sysctl_vfs_ctl(SYSCTL_HANDLER_ARGS)
+{
+ struct vfsidctl vc;
+ int error;
+ struct mount *mp;
+
+ error = SYSCTL_IN(req, &vc, sizeof(vc));
+ if (error)
+ return (error);
+
+ mp = vfs_getvfs(&vc.vc_fsid);
+ if (mp == NULL)
+ return (ENOENT);
+ VCTLTOREQ(&vc, req);
+ return (VFS_SYSCTL(mp, req));
+}
+
+SYSCTL_PROC(_vfs, OID_AUTO, ctl, CTLFLAG_RD,
+ NULL, 0, sysctl_vfs_ctl, "", "Message queue IDs");
diff --git a/sys/sys/event.h b/sys/sys/event.h
index 900089c..b735dd5 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -37,8 +37,9 @@
#define EVFILT_SIGNAL (-6) /* attached to struct proc */
#define EVFILT_TIMER (-7) /* timers */
#define EVFILT_NETDEV (-8) /* network devices */
+#define EVFILT_FS (-9) /* filesystem events */
-#define EVFILT_SYSCOUNT 8
+#define EVFILT_SYSCOUNT 9
#define EV_SET(kevp_, a, b, c, d, e, f) do { \
struct kevent *kevp = (kevp_); \
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 735216a..251605a 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -380,6 +380,62 @@ struct ovfsconf {
#define VFCF_LOOPBACK 0x00100000 /* aliases some other mounted FS */
#define VFCF_UNICODE 0x00200000 /* stores file names as Unicode*/
+struct vfsidctl {
+ int vc_vers; /* should be VFSIDCTL_VERS1 (below) */
+ fsid_t vc_fsid; /* fsid to operate on. */
+ void *vc_ptr; /* pointer to data structure. */
+ size_t vc_len; /* sizeof said structure. */
+ u_int32_t vc_spare[12]; /* spare (must be zero). */
+};
+
+/* vfsidctl API version. */
+#define VFS_CTL_VERS1 0x01
+
+/*
+ * New style VFS sysctls, do not reuse/conflict with the namespace for
+ * private sysctls.
+ */
+#define VFS_CTL_STATFS 0x00010001 /* statfs */
+#define VFS_CTL_UMOUNT 0x00010002 /* unmount */
+#define VFS_CTL_QUERY 0x00010003 /* anything wrong? (vfsquery) */
+#define VFS_CTL_NEWADDR 0x00010004 /* reconnect to new address */
+#define VFS_CTL_TIMEO 0x00010005 /* set timeout for vfs notification */
+#define VFS_CTL_NOLOCKS 0x00010006 /* disable file locking */
+
+struct vfsquery {
+ u_int32_t vq_flags;
+ u_int32_t vq_spare[31];
+};
+
+/* vfsquery flags */
+#define VQ_NOTRESP 0x0001 /* server down */
+#define VQ_NEEDAUTH 0x0002 /* server bad auth */
+#define VQ_LOWDISK 0x0004 /* we're low on space */
+#define VQ_MOUNT 0x0008 /* new filesystem arrived */
+#define VQ_UNMOUNT 0x0010 /* filesystem has left */
+#define VQ_DEAD 0x0020 /* filesystem is dead, needs force unmount */
+#define VQ_ASSIST 0x0040 /* filesystem needs assistance from external
+ program */
+#define VQ_NOTRESPLOCK 0x0080 /* server lockd down */
+#define VQ_FLAG0100 0x0100 /* placeholder */
+#define VQ_FLAG0200 0x0200 /* placeholder */
+#define VQ_FLAG0400 0x0400 /* placeholder */
+#define VQ_FLAG0800 0x0800 /* placeholder */
+#define VQ_FLAG1000 0x1000 /* placeholder */
+#define VQ_FLAG2000 0x2000 /* placeholder */
+#define VQ_FLAG4000 0x4000 /* placeholder */
+#define VQ_FLAG8000 0x8000 /* placeholder */
+
+#ifdef _KERNEL
+/* Point a sysctl request at a vfsidctl's data. */
+#define VCTLTOREQ(vc, req) \
+ do { \
+ (req)->newptr = (vc)->vc_ptr; \
+ (req)->newlen = (vc)->vc_len; \
+ (req)->newidx = 0; \
+ } while (0)
+#endif
+
struct iovec;
struct uio;
@@ -397,6 +453,7 @@ extern struct vfsconf *vfsconf; /* head of list of filesystem types */
*/
struct mount_args;
struct nameidata;
+struct sysctl_req;
typedef int vfs_mount_t(struct mount *mp, char *path, caddr_t data,
struct nameidata *ndp, struct thread *td);
@@ -422,6 +479,7 @@ typedef int vfs_extattrctl_t(struct mount *mp, int cmd,
const char *attrname, struct thread *td);
typedef int vfs_nmount_t(struct mount *mp, struct nameidata *ndp,
struct thread *td);
+typedef int vfs_sysctl_t(struct mount *mp, struct sysctl_req *req);
struct vfsops {
vfs_mount_t *vfs_mount;
@@ -440,6 +498,7 @@ struct vfsops {
vfs_extattrctl_t *vfs_extattrctl;
/* Additions below are not binary compatible with 5.0 and below. */
vfs_nmount_t *vfs_nmount;
+ vfs_sysctl_t *vfs_sysctl;
};
#define VFS_NMOUNT(MP, NDP, P) (*(MP)->mnt_op->vfs_nmount)(MP, NDP, P)
@@ -460,6 +519,9 @@ struct vfsops {
(*(MP)->mnt_op->vfs_checkexp)(MP, NAM, EXFLG, CRED)
#define VFS_EXTATTRCTL(MP, C, FN, NS, N, P) \
(*(MP)->mnt_op->vfs_extattrctl)(MP, C, FN, NS, N, P)
+#define VFS_SYSCTL(MP, REQ) \
+ ((MP) == NULL ? ENOTSUP : \
+ (*(MP)->mnt_op->vfs_sysctl)(MP, REQ))
#include <sys/module.h>
@@ -486,6 +548,7 @@ extern char *mountrootfsname;
int dounmount(struct mount *, int, struct thread *);
int kernel_mount(struct iovec *, u_int, int);
int kernel_vmount(int flags, ...);
+void vfs_event_signal(fsid_t *, u_int32_t, void *);
int vfs_getopt(struct vfsoptlist *, const char *, void **, int *);
int vfs_copyopt(struct vfsoptlist *, const char *, void *, int);
int vfs_mount(struct thread *, const char *, char *, int, void *);
OpenPOWER on IntegriCloud