diff options
author | alfred <alfred@FreeBSD.org> | 2004-07-04 10:52:54 +0000 |
---|---|---|
committer | alfred <alfred@FreeBSD.org> | 2004-07-04 10:52:54 +0000 |
commit | bbaa6c3ec045b7de225f726d3c9367510b287184 (patch) | |
tree | e36ccfebbc87cf44cd8c6c2eedfe0a0290e0350a | |
parent | 68fa9f13518916e9d3dc979c995d384f129e12d9 (diff) | |
download | FreeBSD-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.c | 2 | ||||
-rw-r--r-- | sys/kern/vfs_mount.c | 2 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 62 | ||||
-rw-r--r-- | sys/sys/event.h | 3 | ||||
-rw-r--r-- | sys/sys/mount.h | 63 |
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 *); |