summaryrefslogtreecommitdiffstats
path: root/sys/fs/devfs
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/devfs')
-rw-r--r--sys/fs/devfs/devfs.h2
-rw-r--r--sys/fs/devfs/devfs_rule.c35
-rw-r--r--sys/fs/devfs/devfs_vfsops.c43
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");
OpenPOWER on IntegriCloud