diff options
Diffstat (limited to 'sys/fs/devfs')
-rw-r--r-- | sys/fs/devfs/devfs.h | 2 | ||||
-rw-r--r-- | sys/fs/devfs/devfs_rule.c | 35 | ||||
-rw-r--r-- | sys/fs/devfs/devfs_vfsops.c | 43 |
3 files changed, 79 insertions, 1 deletions
diff --git a/sys/fs/devfs/devfs.h b/sys/fs/devfs/devfs.h index d148f8e..d77baa8 100644 --- a/sys/fs/devfs/devfs.h +++ b/sys/fs/devfs/devfs.h @@ -182,6 +182,8 @@ void devfs_rules_apply(struct devfs_mount *, struct devfs_dirent *); void devfs_rules_cleanup(struct devfs_mount *); int devfs_rules_ioctl(struct devfs_mount *, u_long, caddr_t, struct thread *); +void devfs_ruleset_set(devfs_rsnum rsnum, struct devfs_mount *dm); +void devfs_ruleset_apply(struct devfs_mount *dm); int devfs_allocv(struct devfs_dirent *, struct mount *, int, struct vnode **); char *devfs_fqpn(char *, struct devfs_mount *, struct devfs_dirent *, diff --git a/sys/fs/devfs/devfs_rule.c b/sys/fs/devfs/devfs_rule.c index ea05797..f37dd9d 100644 --- a/sys/fs/devfs/devfs_rule.c +++ b/sys/fs/devfs/devfs_rule.c @@ -771,3 +771,38 @@ devfs_rules_cleanup(struct devfs_mount *dm) devfs_ruleset_reap(ds); } } + +/* + * Make rsnum the active ruleset for dm (locked) + */ +void +devfs_ruleset_set(devfs_rsnum rsnum, struct devfs_mount *dm) +{ + + sx_assert(&dm->dm_lock, SX_XLOCKED); + + sx_xlock(&sx_rules); + devfs_ruleset_use(rsnum, dm); + sx_xunlock(&sx_rules); +} + +/* + * Apply the current active ruleset on a mount + */ +void +devfs_ruleset_apply(struct devfs_mount *dm) +{ + struct devfs_ruleset *ds; + + sx_assert(&dm->dm_lock, SX_XLOCKED); + + sx_xlock(&sx_rules); + if (dm->dm_ruleset == 0) { + sx_xunlock(&sx_rules); + return; + } + ds = devfs_ruleset_bynum(dm->dm_ruleset); + if (ds != NULL) + devfs_ruleset_applydm(ds, dm); + sx_xunlock(&sx_rules); +} diff --git a/sys/fs/devfs/devfs_vfsops.c b/sys/fs/devfs/devfs_vfsops.c index 87ec162..bba4bfc 100644 --- a/sys/fs/devfs/devfs_vfsops.c +++ b/sys/fs/devfs/devfs_vfsops.c @@ -56,6 +56,10 @@ static vfs_unmount_t devfs_unmount; static vfs_root_t devfs_root; static vfs_statfs_t devfs_statfs; +static const char *devfs_opts[] = { + "from", "ruleset", NULL +}; + /* * Mount the filesystem */ @@ -65,15 +69,46 @@ devfs_mount(struct mount *mp) int error; struct devfs_mount *fmp; struct vnode *rvp; + int rsnum; if (devfs_unr == NULL) devfs_unr = new_unrhdr(0, INT_MAX, NULL); error = 0; - if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS)) + if (mp->mnt_flag & MNT_ROOTFS) return (EOPNOTSUPP); + rsnum = 0; + + if (mp->mnt_optnew != NULL) { + if (vfs_filteropt(mp->mnt_optnew, devfs_opts)) + return (EINVAL); + + if (vfs_getopt(mp->mnt_optnew, "ruleset", NULL, NULL) == 0 && + (vfs_scanopt(mp->mnt_optnew, "ruleset", "%d", + &rsnum) != 1 || rsnum < 0 || rsnum > 65535)) + error = EINVAL; + } + + if (error) { + vfs_mount_error(mp, "%s", "invalid ruleset specification"); + return (error); + } + + if (mp->mnt_flag & MNT_UPDATE) { + if (rsnum != 0) { + fmp = mp->mnt_data; + if (fmp != NULL) { + sx_xlock(&fmp->dm_lock); + devfs_ruleset_set((devfs_rsnum)rsnum, fmp); + devfs_ruleset_apply(fmp); + sx_xunlock(&fmp->dm_lock); + } + } + return (0); + } + fmp = malloc(sizeof *fmp, M_DEVFS, M_WAITOK | M_ZERO); fmp->dm_idx = alloc_unr(devfs_unr); sx_init(&fmp->dm_lock, "devfsmount"); @@ -101,6 +136,12 @@ devfs_mount(struct mount *mp) return (error); } + if (rsnum != 0) { + sx_xlock(&fmp->dm_lock); + devfs_ruleset_set((devfs_rsnum)rsnum, fmp); + sx_xunlock(&fmp->dm_lock); + } + VOP_UNLOCK(rvp, 0); vfs_mountedfrom(mp, "devfs"); |