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.
This commit is contained in:
Alfred Perlstein 2004-07-04 10:52:54 +00:00
parent dddd0d87a3
commit 94ed9c8af5
5 changed files with 131 additions and 1 deletions

View File

@ -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

View File

@ -928,6 +928,7 @@ vfs_domount(
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);

View File

@ -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");

View File

@ -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_); \

View File

@ -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 *);