diff options
Diffstat (limited to 'sys/fs')
-rw-r--r-- | sys/fs/devfs/devfs.h | 2 | ||||
-rw-r--r-- | sys/fs/devfs/devfs_devs.c | 4 | ||||
-rw-r--r-- | sys/fs/devfs/devfs_rule.c | 72 |
3 files changed, 34 insertions, 44 deletions
diff --git a/sys/fs/devfs/devfs.h b/sys/fs/devfs/devfs.h index 7a71c48..5d25fd7 100644 --- a/sys/fs/devfs/devfs.h +++ b/sys/fs/devfs/devfs.h @@ -177,6 +177,8 @@ struct devfs_mount { devfs_rsnum dm_ruleset; }; +extern unsigned devfs_rule_depth; + /* * This is what we fill in dm_dirent[N] for a deleted entry. */ diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c index 2329b84..9cec56d 100644 --- a/sys/fs/devfs/devfs_devs.c +++ b/sys/fs/devfs/devfs_devs.c @@ -71,6 +71,10 @@ SYSCTL_UINT(_vfs_devfs, OID_AUTO, inodes, CTLFLAG_RD, SYSCTL_UINT(_vfs_devfs, OID_AUTO, topinode, CTLFLAG_RD, &devfs_topino, 0, "DEVFS highest inode#"); +unsigned devfs_rule_depth = 1; +SYSCTL_UINT(_vfs_devfs, OID_AUTO, rule_depth, CTLFLAG_RW, + &devfs_rule_depth, 0, "Max depth of ruleset include"); + /* * Helper sysctl for devname(3). We're given a struct cdev * and return * the name, if any, registered by the device driver. diff --git a/sys/fs/devfs/devfs_rule.c b/sys/fs/devfs/devfs_rule.c index 7469aec..0c573a9 100644 --- a/sys/fs/devfs/devfs_rule.c +++ b/sys/fs/devfs/devfs_rule.c @@ -96,12 +96,10 @@ struct devfs_ruleset { int ds_refcount; int ds_flags; #define DS_IMMUTABLE 0x001 - int ds_running; }; static devfs_rid devfs_rid_input(devfs_rid rid, struct devfs_mount *dm); -static void devfs_rule_applyde(struct devfs_krule *dk,struct devfs_dirent *de); static void devfs_rule_applyde_recursive(struct devfs_krule *dk, struct devfs_dirent *de); static void devfs_rule_applydm(struct devfs_krule *dk, struct devfs_mount *dm); @@ -114,10 +112,10 @@ static int devfs_rule_insert(struct devfs_rule *dr); static int devfs_rule_match(struct devfs_krule *dk, struct devfs_dirent *de); static int devfs_rule_matchpath(struct devfs_krule *dk, struct devfs_dirent *de); -static void devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de); +static void devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de, unsigned depth); static void devfs_ruleset_applyde(struct devfs_ruleset *ds, - struct devfs_dirent *de); + struct devfs_dirent *de, unsigned depth); static void devfs_ruleset_applydm(struct devfs_ruleset *ds, struct devfs_mount *dm); static struct devfs_ruleset *devfs_ruleset_bynum(devfs_rsnum rsnum); @@ -129,7 +127,7 @@ static int devfs_ruleset_use(devfs_rsnum rsnum, struct devfs_mount *dm); static SLIST_HEAD(, devfs_ruleset) devfs_rulesets; /* - * Called to apply the proper rules for de before the latter can be + * Called to apply the proper rules for 'de' before it can be * exposed to the userland. This should be called with an exclusive * lock on dm in case we need to run anything. */ @@ -140,7 +138,7 @@ devfs_rules_apply(struct devfs_mount *dm, struct devfs_dirent *de) ds = devfs_ruleset_bynum(dm->dm_ruleset); KASSERT(ds != NULL, ("mount-point has NULL ruleset")); - devfs_ruleset_applyde(ds, de); + devfs_ruleset_applyde(ds, de, devfs_rule_depth); } /* @@ -368,17 +366,6 @@ devfs_rid_input(devfs_rid rid, struct devfs_mount *dm) } /* - * Apply dk to de. - */ -static void -devfs_rule_applyde(struct devfs_krule *dk, struct devfs_dirent *de) -{ - - if (devfs_rule_match(dk, de)) - devfs_rule_run(dk, de); -} - -/* * Apply dk to de and everything under de. * * XXX: This method needs a function call for every nested @@ -390,11 +377,9 @@ devfs_rule_applyde_recursive(struct devfs_krule *dk, struct devfs_dirent *de) { struct devfs_dirent *de2; - /* XXX: Should we apply to ourselves first or last? Does it matter? */ - TAILQ_FOREACH(de2, &de->de_dlist, de_list) { + TAILQ_FOREACH(de2, &de->de_dlist, de_list) devfs_rule_applyde_recursive(dk, de2); - } - devfs_rule_applyde(dk, de); + devfs_rule_run(dk, de, devfs_rule_depth); } /* @@ -610,15 +595,12 @@ devfs_rule_match(struct devfs_krule *dk, struct devfs_dirent *de) if (dr->dr_icond & DRC_DSWFLAGS) if (dev == NULL || (dev->si_devsw->d_flags & dr->dr_dswflags) == 0) - goto nomatch; + return (0); if (dr->dr_icond & DRC_PATHPTRN) if (!devfs_rule_matchpath(dk, de)) - goto nomatch; + return (0); return (1); - -nomatch: - return (0); } /* @@ -648,11 +630,13 @@ devfs_rule_matchpath(struct devfs_krule *dk, struct devfs_dirent *de) * Run dk on de. */ static void -devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de) +devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de, unsigned depth) { struct devfs_rule *dr = &dk->dk_rule; struct devfs_ruleset *ds; + if (!devfs_rule_match(dk, de)) + return; if (dr->dr_iacts & DRA_BACTS) { if (dr->dr_bacts & DRB_HIDE) de->de_flags |= DE_WHITEOUT; @@ -666,13 +650,20 @@ devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de) if (dr->dr_iacts & DRA_MODE) de->de_mode = dr->dr_mode; if (dr->dr_iacts & DRA_INCSET) { - ds = devfs_ruleset_bynum(dk->dk_rule.dr_incset); - KASSERT(ds != NULL, ("DRA_INCSET but bad dr_incset")); - if (ds->ds_running) - printf("Warning: avoiding loop through ruleset %d\n", - ds->ds_number); - else - devfs_ruleset_applyde(ds, de); + /* + * XXX: we should tell the user if the depth is exceeded here + * XXX: but it is not obvious how to. A return value will + * XXX: not work as this is called when devices are created + * XXX: long time after the rules were instantiated. + * XXX: a printf() would probably give too much noise, or + * XXX: DoS the machine. I guess a a rate-limited message + * XXX: might work. + */ + if (depth > 0) { + ds = devfs_ruleset_bynum(dk->dk_rule.dr_incset); + KASSERT(ds != NULL, ("DRA_INCSET but bad dr_incset")); + devfs_ruleset_applyde(ds, de, depth - 1); + } } } @@ -680,16 +671,12 @@ devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de) * Apply all the rules in ds to de. */ static void -devfs_ruleset_applyde(struct devfs_ruleset *ds, struct devfs_dirent *de) +devfs_ruleset_applyde(struct devfs_ruleset *ds, struct devfs_dirent *de, unsigned depth) { struct devfs_krule *dk; - KASSERT(!ds->ds_running,("ruleset %d already running", ds->ds_number)); - ds->ds_running = 1; - SLIST_FOREACH(dk, &ds->ds_rules, dk_list) { - devfs_rule_applyde(dk, de); - } - ds->ds_running = 0; + SLIST_FOREACH(dk, &ds->ds_rules, dk_list) + devfs_rule_run(dk, de, depth); } /* @@ -700,8 +687,6 @@ devfs_ruleset_applydm(struct devfs_ruleset *ds, struct devfs_mount *dm) { struct devfs_krule *dk; - KASSERT(!ds->ds_running,("ruleset %d already running", ds->ds_number)); - ds->ds_running = 1; /* * XXX: Does it matter whether we do * @@ -721,7 +706,6 @@ devfs_ruleset_applydm(struct devfs_ruleset *ds, struct devfs_mount *dm) SLIST_FOREACH(dk, &ds->ds_rules, dk_list) { devfs_rule_applydm(dk, dm); } - ds->ds_running = 0; } /* |