summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormm <mm@FreeBSD.org>2012-02-09 10:09:12 +0000
committermm <mm@FreeBSD.org>2012-02-09 10:09:12 +0000
commit27a58a0dde89f99954c275fce42e656d2c5a7cbf (patch)
treedbeb835f14a88b3d6a3b043db2ed23b39f0d5275
parent0fd71d974ef947d1cda47ec787a9f307bc4ba8ad (diff)
downloadFreeBSD-src-27a58a0dde89f99954c275fce42e656d2c5a7cbf.zip
FreeBSD-src-27a58a0dde89f99954c275fce42e656d2c5a7cbf.tar.gz
Introduce the "ruleset=number" option for devfs(5) mounts.
Add support for updating the devfs mount (currently only changing the ruleset number is supported). Check mnt_optnew with vfs_filteropt(9). This new option sets the specified ruleset number as the active ruleset of the new devfs mount and applies all its rules at mount time. If the specified ruleset doesn't exist, a new empty ruleset is created. MFC after: 1 month
-rw-r--r--share/man/man5/devfs.525
-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
4 files changed, 103 insertions, 2 deletions
diff --git a/share/man/man5/devfs.5 b/share/man/man5/devfs.5
index 8c7e598..7b483fc 100644
--- a/share/man/man5/devfs.5
+++ b/share/man/man5/devfs.5
@@ -38,7 +38,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 18, 2010
+.Dd February 9, 2012
.Dt DEVFS 5
.Os
.Sh NAME
@@ -90,6 +90,29 @@ and
.Pa 2 .
.Xr fdescfs 5
creates files for all open descriptors.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl o Ar options
+Use the specified mount
+.Ar options ,
+as described in
+.Xr mount 8 .
+The following devfs file system-specific options are available:
+.Bl -tag -width indent
+.It Cm ruleset Ns No = Ns Ar ruleset
+Set ruleset number
+.Ar ruleset
+as the current ruleset for the mount-point and apply all its rules. If the
+ruleset number
+.Ar ruleset
+does not exist, an empty ruleset with the number
+.Ar ruleset
+is created. See
+.Xr devfs 8
+for more information on working with devfs rulesets.
+.El
+.El
.Sh FILES
.Bl -tag -width /dev/XXXX -compact
.It Pa /dev
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