summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPoul-Henning Kamp <phk@FreeBSD.org>2005-09-18 07:10:57 +0000
committerPoul-Henning Kamp <phk@FreeBSD.org>2005-09-18 07:10:57 +0000
commit5dc21d2be6f7413a9bb39502733d07949ef8f777 (patch)
tree9c32d6f6b1025eee316da4e581b15b41d93a4577
parent30ad9643f089ee53d94c71120ce16d5be9f59903 (diff)
Notes
-rw-r--r--sys/fs/devfs/devfs.h7
-rw-r--r--sys/fs/devfs/devfs_devs.c52
-rw-r--r--sys/fs/devfs/devfs_rule.c100
-rw-r--r--sys/fs/devfs/devfs_vfsops.c1
-rw-r--r--sys/fs/devfs/devfs_vnops.c455
-rw-r--r--sys/kern/kern_conf.c185
-rw-r--r--sys/kern/vfs_subr.c27
-rw-r--r--sys/sys/conf.h5
-rw-r--r--sys/sys/vnode.h2
9 files changed, 384 insertions, 450 deletions
diff --git a/sys/fs/devfs/devfs.h b/sys/fs/devfs/devfs.h
index c8f107419ed3..07912a9a0dcf 100644
--- a/sys/fs/devfs/devfs.h
+++ b/sys/fs/devfs/devfs.h
@@ -169,7 +169,6 @@ struct devfs_dirent {
struct devfs_mount {
struct mount *dm_mount;
struct devfs_dirent *dm_rootdir;
- struct devfs_dirent *dm_basedir;
unsigned dm_generation;
struct devfs_dirent **dm_dirent;
struct devfs_dirent **dm_overflow;
@@ -178,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.
*/
@@ -186,12 +187,12 @@ struct devfs_mount {
#define VFSTODEVFS(mp) ((struct devfs_mount *)((mp)->mnt_data))
void devfs_rules_apply(struct devfs_mount *dm, struct devfs_dirent *de);
-int devfs_rules_ioctl(struct mount *mp, u_long cmd, caddr_t data, struct thread *td);
+int devfs_rules_ioctl(struct devfs_mount *dm, u_long cmd, caddr_t data, struct thread *td);
void devfs_rules_newmount(struct devfs_mount *dm, struct thread *td);
int devfs_allocv (struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, struct thread *td);
struct cdev **devfs_itod (int inode);
struct devfs_dirent **devfs_itode (struct devfs_mount *dm, int inode);
-int devfs_populate (struct devfs_mount *dm);
+void devfs_populate (struct devfs_mount *dm);
struct devfs_dirent *devfs_newdirent (char *name, int namelen);
void devfs_purge (struct devfs_dirent *dd);
struct devfs_dirent *devfs_vmkdir (char *name, int namelen, struct devfs_dirent *dotdot);
diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c
index 172a63c8902a..77a514083e3b 100644
--- a/sys/fs/devfs/devfs_devs.c
+++ b/sys/fs/devfs/devfs_devs.c
@@ -46,6 +46,7 @@
#include <machine/atomic.h>
#include <fs/devfs/devfs.h>
+#include <fs/devfs/devfs_int.h>
static struct cdev *devfs_inot[NDEVFSINO];
static struct cdev **devfs_overflow;
@@ -70,6 +71,42 @@ 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.
+ */
+static int
+sysctl_devname(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ dev_t ud;
+ struct cdev *dev, **dp;
+
+ error = SYSCTL_IN(req, &ud, sizeof (ud));
+ if (error)
+ return (error);
+ if (ud == NODEV)
+ return(EINVAL);
+ dp = devfs_itod(ud);
+ if (dp == NULL)
+ return(ENOENT);
+ dev = *dp;
+ if (dev == NULL)
+ return(ENOENT);
+ return(SYSCTL_OUT(req, dev->si_name, strlen(dev->si_name) + 1));
+ return (error);
+}
+
+SYSCTL_PROC(_kern, OID_AUTO, devname, CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_ANYBODY,
+ NULL, 0, sysctl_devname, "", "devname(3) handler");
+
+SYSCTL_INT(_debug_sizeof, OID_AUTO, cdev, CTLFLAG_RD,
+ 0, sizeof(struct cdev), "sizeof(struct cdev)");
+
static int *
devfs_itor(int inode)
{
@@ -164,7 +201,7 @@ devfs_newdirent(char *name, int namelen)
d.d_namlen = namelen;
i = sizeof (*de) + GENERIC_DIRSIZ(&d);
- MALLOC(de, struct devfs_dirent *, i, M_DEVFS, M_WAITOK | M_ZERO);
+ de = malloc(i, M_DEVFS, M_WAITOK | M_ZERO);
de->de_dirent = (struct dirent *)(de + 1);
de->de_dirent->d_namlen = namelen;
de->de_dirent->d_reclen = GENERIC_DIRSIZ(&d);
@@ -217,7 +254,7 @@ devfs_delete(struct devfs_dirent *dd, struct devfs_dirent *de)
{
if (de->de_symlink) {
- FREE(de->de_symlink, M_DEVFS);
+ free(de->de_symlink, M_DEVFS);
de->de_symlink = NULL;
}
if (de->de_vnode)
@@ -226,7 +263,7 @@ devfs_delete(struct devfs_dirent *dd, struct devfs_dirent *de)
#ifdef MAC
mac_destroy_devfsdirent(de);
#endif
- FREE(de, M_DEVFS);
+ free(de, M_DEVFS);
}
void
@@ -244,7 +281,7 @@ devfs_purge(struct devfs_dirent *dd)
}
-int
+void
devfs_populate(struct devfs_mount *dm)
{
int i, j;
@@ -254,8 +291,7 @@ devfs_populate(struct devfs_mount *dm)
char *q, *s;
if (dm->dm_generation == devfs_generation)
- return (0);
- lockmgr(&dm->dm_lock, LK_UPGRADE, 0, curthread);
+ return;
if (devfs_noverflow && dm->dm_overflow == NULL) {
i = devfs_noverflow * sizeof (struct devfs_dirent *);
MALLOC(dm->dm_overflow, struct devfs_dirent **, i,
@@ -284,7 +320,7 @@ devfs_populate(struct devfs_mount *dm)
continue;
if (!devfs_getref(i))
continue;
- dd = dm->dm_basedir;
+ dd = dm->dm_rootdir;
s = dev->si_name;
for (;;) {
for (q = s; *q != '/' && *q != '\0'; q++)
@@ -333,8 +369,6 @@ devfs_populate(struct devfs_mount *dm)
TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list);
}
}
- lockmgr(&dm->dm_lock, LK_DOWNGRADE, 0, curthread);
- return (0);
}
/*
diff --git a/sys/fs/devfs/devfs_rule.c b/sys/fs/devfs/devfs_rule.c
index 5168efe6cc31..5e25f4eaeadf 100644
--- a/sys/fs/devfs/devfs_rule.c
+++ b/sys/fs/devfs/devfs_rule.c
@@ -71,8 +71,8 @@
#include <sys/malloc.h>
#include <sys/dirent.h>
#include <sys/vnode.h>
-#include <sys/mount.h>
#include <sys/ioccom.h>
+#include <sys/sx.h>
#include <fs/devfs/devfs.h>
@@ -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);
@@ -126,10 +124,11 @@ static void devfs_ruleset_destroy(struct devfs_ruleset **dsp);
static void devfs_ruleset_reap(struct devfs_ruleset **dsp);
static int devfs_ruleset_use(devfs_rsnum rsnum, struct devfs_mount *dm);
+static struct sx sx_rules;
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.
*/
@@ -138,9 +137,11 @@ devfs_rules_apply(struct devfs_mount *dm, struct devfs_dirent *de)
{
struct devfs_ruleset *ds;
+ sx_slock(&sx_rules);
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);
+ sx_sunlock(&sx_rules);
}
/*
@@ -151,6 +152,7 @@ devfs_rules_init(void *junk __unused)
{
struct devfs_ruleset *ds;
+ sx_init(&sx_rules, "devfsrules");
SLIST_INIT(&devfs_rulesets);
ds = devfs_ruleset_create(0);
@@ -164,9 +166,8 @@ SYSINIT(devfs_rules, SI_SUB_DEVFS, SI_ORDER_FIRST, devfs_rules_init, NULL);
* Rule subsystem ioctl hook.
*/
int
-devfs_rules_ioctl(struct mount *mp, u_long cmd, caddr_t data, struct thread *td)
+devfs_rules_ioctl(struct devfs_mount *dm, u_long cmd, caddr_t data, struct thread *td)
{
- struct devfs_mount *dm = VFSTODEVFS(mp);
struct devfs_ruleset *ds;
struct devfs_krule *dk;
struct devfs_rule *dr;
@@ -183,8 +184,7 @@ devfs_rules_ioctl(struct mount *mp, u_long cmd, caddr_t data, struct thread *td)
if (error != 0)
return (error);
- lockmgr(&dm->dm_lock, LK_SHARED, 0, td);
-
+ sx_xlock(&sx_rules);
switch (cmd) {
case DEVFSIO_RADD:
dr = (struct devfs_rule *)data;
@@ -196,7 +196,6 @@ devfs_rules_ioctl(struct mount *mp, u_long cmd, caddr_t data, struct thread *td)
error = EEXIST;
goto out;
}
- lockmgr(&dm->dm_lock, LK_UPGRADE, 0, td);
error = devfs_rule_insert(dr);
break;
case DEVFSIO_RAPPLY:
@@ -226,9 +225,7 @@ devfs_rules_ioctl(struct mount *mp, u_long cmd, caddr_t data, struct thread *td)
}
dk = malloc(sizeof(*dk), M_TEMP, M_WAITOK | M_ZERO);
memcpy(&dk->dk_rule, dr, sizeof(*dr));
- lockmgr(&dm->dm_lock, LK_UPGRADE, 0, td);
devfs_rule_applydm(dk, dm);
- lockmgr(&dm->dm_lock, LK_DOWNGRADE, 0, td);
free(dk, M_TEMP);
error = 0;
break;
@@ -240,7 +237,6 @@ devfs_rules_ioctl(struct mount *mp, u_long cmd, caddr_t data, struct thread *td)
error = ENOENT;
goto out;
}
- lockmgr(&dm->dm_lock, LK_UPGRADE, 0, td);
devfs_rule_applydm(dk, dm);
error = 0;
break;
@@ -253,7 +249,6 @@ devfs_rules_ioctl(struct mount *mp, u_long cmd, caddr_t data, struct thread *td)
goto out;
}
ds = dk->dk_ruleset;
- lockmgr(&dm->dm_lock, LK_UPGRADE, 0, td);
error = devfs_rule_delete(&dk);
devfs_ruleset_reap(&ds);
break;
@@ -289,7 +284,6 @@ devfs_rules_ioctl(struct mount *mp, u_long cmd, caddr_t data, struct thread *td)
break;
case DEVFSIO_SUSE:
rsnum = *(devfs_rsnum *)data;
- lockmgr(&dm->dm_lock, LK_UPGRADE, 0, td);
error = devfs_ruleset_use(rsnum, dm);
break;
case DEVFSIO_SAPPLY:
@@ -300,7 +294,6 @@ devfs_rules_ioctl(struct mount *mp, u_long cmd, caddr_t data, struct thread *td)
error = ESRCH;
goto out;
}
- lockmgr(&dm->dm_lock, LK_UPGRADE, 0, td);
devfs_ruleset_applydm(ds, dm);
error = 0;
break;
@@ -323,7 +316,7 @@ devfs_rules_ioctl(struct mount *mp, u_long cmd, caddr_t data, struct thread *td)
}
out:
- lockmgr(&dm->dm_lock, LK_RELEASE, 0, td);
+ sx_xunlock(&sx_rules);
return (error);
}
@@ -335,18 +328,18 @@ devfs_rules_newmount(struct devfs_mount *dm, struct thread *td)
{
struct devfs_ruleset *ds;
- lockmgr(&dm->dm_lock, LK_EXCLUSIVE, 0, td);
/*
* We can't use devfs_ruleset_use() since it will try to
* decrement the refcount for the old ruleset, and there is no
* old ruleset. Making some value of ds_ruleset "special" to
* mean "don't decrement refcount" is uglier than this.
*/
+ sx_slock(&sx_rules);
ds = devfs_ruleset_bynum(0);
KASSERT(ds != NULL, ("no ruleset 0"));
++ds->ds_refcount;
dm->dm_ruleset = 0;
- lockmgr(&dm->dm_lock, LK_RELEASE, 0, td);
+ sx_sunlock(&sx_rules);
}
/*
@@ -368,17 +361,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 +372,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);
}
/*
@@ -404,7 +384,7 @@ static void
devfs_rule_applydm(struct devfs_krule *dk, struct devfs_mount *dm)
{
- devfs_rule_applyde_recursive(dk, dm->dm_basedir);
+ devfs_rule_applyde_recursive(dk, dm->dm_rootdir);
}
/*
@@ -610,15 +590,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 +625,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 +645,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 +666,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 +682,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 +701,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;
}
/*
@@ -829,4 +808,3 @@ devfs_ruleset_use(devfs_rsnum rsnum, struct devfs_mount *dm)
devfs_ruleset_reap(&cds);
return (0);
}
-
diff --git a/sys/fs/devfs/devfs_vfsops.c b/sys/fs/devfs/devfs_vfsops.c
index b93f123f39a4..307b4a28ceaf 100644
--- a/sys/fs/devfs/devfs_vfsops.c
+++ b/sys/fs/devfs/devfs_vfsops.c
@@ -93,7 +93,6 @@ devfs_mount(struct mount *mp, struct thread *td)
#ifdef MAC
mac_create_devfs_directory(mp, "", 0, fmp->dm_rootdir);
#endif
- fmp->dm_basedir = fmp->dm_rootdir;
devfs_rules_newmount(fmp, td);
error = devfs_root(mp, LK_EXCLUSIVE, &rvp, td);
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index aafcd2616fc8..6cf2f49b888d 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -61,133 +61,16 @@
#include <sys/proc.h>
#include <sys/stat.h>
#include <sys/sx.h>
-#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/ttycom.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
-#include <fs/devfs/devfs.h>
-
-static fo_rdwr_t devfs_read_f;
-static fo_rdwr_t devfs_write_f;
-static fo_ioctl_t devfs_ioctl_f;
-static fo_poll_t devfs_poll_f;
-static fo_kqfilter_t devfs_kqfilter_f;
-static fo_stat_t devfs_stat_f;
-static fo_close_t devfs_close_f;
-
-static struct fileops devfs_ops_f = {
- .fo_read = devfs_read_f,
- .fo_write = devfs_write_f,
- .fo_ioctl = devfs_ioctl_f,
- .fo_poll = devfs_poll_f,
- .fo_kqfilter = devfs_kqfilter_f,
- .fo_stat = devfs_stat_f,
- .fo_close = devfs_close_f,
- .fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
-};
-
-static vop_access_t devfs_access;
-static vop_advlock_t devfs_advlock;
-static vop_close_t devfs_close;
-static vop_fsync_t devfs_fsync;
-static vop_getattr_t devfs_getattr;
-static vop_lookup_t devfs_lookup;
-static vop_lookup_t devfs_lookupx;
-static vop_mknod_t devfs_mknod;
-static vop_open_t devfs_open;
-static vop_pathconf_t devfs_pathconf;
-static vop_print_t devfs_print;
-static vop_readdir_t devfs_readdir;
-static vop_readlink_t devfs_readlink;
-static vop_reclaim_t devfs_reclaim;
-static vop_remove_t devfs_remove;
-static vop_revoke_t devfs_revoke;
-static vop_ioctl_t devfs_rioctl;
-static vop_read_t devfs_rread;
-static vop_setattr_t devfs_setattr;
-#ifdef MAC
-static vop_setlabel_t devfs_setlabel;
-#endif
-static vop_symlink_t devfs_symlink;
-
-static struct vop_vector devfs_vnodeops = {
- .vop_default = &default_vnodeops,
-
- .vop_access = devfs_access,
- .vop_getattr = devfs_getattr,
- .vop_ioctl = devfs_rioctl,
- .vop_lookup = devfs_lookup,
- .vop_mknod = devfs_mknod,
- .vop_pathconf = devfs_pathconf,
- .vop_read = devfs_rread,
- .vop_readdir = devfs_readdir,
- .vop_readlink = devfs_readlink,
- .vop_reclaim = devfs_reclaim,
- .vop_remove = devfs_remove,
- .vop_revoke = devfs_revoke,
- .vop_setattr = devfs_setattr,
-#ifdef MAC
- .vop_setlabel = devfs_setlabel,
-#endif
- .vop_symlink = devfs_symlink,
-};
-
-static struct vop_vector devfs_specops = {
- .vop_default = &default_vnodeops,
-
- .vop_access = devfs_access,
- .vop_advlock = devfs_advlock,
- .vop_bmap = VOP_PANIC,
- .vop_close = devfs_close,
- .vop_create = VOP_PANIC,
- .vop_fsync = devfs_fsync,
- .vop_getattr = devfs_getattr,
- .vop_lease = VOP_NULL,
- .vop_link = VOP_PANIC,
- .vop_mkdir = VOP_PANIC,
- .vop_mknod = VOP_PANIC,
- .vop_open = devfs_open,
- .vop_pathconf = devfs_pathconf,
- .vop_print = devfs_print,
- .vop_read = VOP_PANIC,
- .vop_readdir = VOP_PANIC,
- .vop_readlink = VOP_PANIC,
- .vop_reallocblks = VOP_PANIC,
- .vop_reclaim = devfs_reclaim,
- .vop_remove = devfs_remove,
- .vop_rename = VOP_PANIC,
- .vop_revoke = devfs_revoke,
- .vop_rmdir = VOP_PANIC,
- .vop_setattr = devfs_setattr,
-#ifdef MAC
- .vop_setlabel = devfs_setlabel,
-#endif
- .vop_strategy = VOP_PANIC,
- .vop_symlink = VOP_PANIC,
- .vop_write = VOP_PANIC,
-};
-
-static u_int
-devfs_random(void)
-{
- static u_int devfs_seed;
-
- while (devfs_seed == 0) {
- /*
- * Make sure people don't make stupid assumptions
- * about device major/minor numbers in userspace.
- * We do this late to get entropy and for the same
- * reason we force a reseed, but it may not be
- * late enough for entropy to be available.
- */
- arc4rand(&devfs_seed, sizeof devfs_seed, 1);
- devfs_seed &= 0xf0f;
- }
- return (devfs_seed);
-}
+static struct vop_vector devfs_vnodeops;
+static struct vop_vector devfs_specops;
+static struct fileops devfs_ops_f;
+#include <fs/devfs/devfs.h>
static int
devfs_fp_check(struct file *fp, struct cdev **devp, struct cdevsw **dswp)
{
@@ -222,7 +105,7 @@ devfs_fqpn(char *buf, struct vnode *dvp, struct componentname *cnp)
return (NULL);
bcopy(cnp->cn_nameptr, buf + i, cnp->cn_namelen);
de = dd;
- while (de != dmp->dm_basedir) {
+ while (de != dmp->dm_rootdir) {
i--;
if (i < 0)
return (NULL);
@@ -297,13 +180,7 @@ loop:
}
static int
-devfs_access(ap)
- struct vop_access_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
+devfs_access(struct vop_access_args *ap)
{
struct vnode *vp = ap->a_vp;
struct devfs_dirent *de;
@@ -332,14 +209,7 @@ devfs_access(ap)
*/
/* ARGSUSED */
static int
-devfs_advlock(ap)
- struct vop_advlock_args /* {
- struct vnode *a_vp;
- caddr_t a_id;
- int a_op;
- struct flock *a_fl;
- int a_flags;
- } */ *ap;
+devfs_advlock(struct vop_advlock_args *ap)
{
return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL);
@@ -350,13 +220,7 @@ devfs_advlock(ap)
*/
/* ARGSUSED */
static int
-devfs_close(ap)
- struct vop_close_args /* {
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
+devfs_close(struct vop_close_args *ap)
{
struct vnode *vp = ap->a_vp, *oldvp;
struct thread *td = ap->a_td;
@@ -424,9 +288,7 @@ devfs_close(ap)
error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td);
PICKUP_GIANT();
} else {
- mtx_lock(&Giant);
error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td);
- mtx_unlock(&Giant);
}
dev_relthread(dev);
return (error);
@@ -444,13 +306,7 @@ devfs_close_f(struct file *fp, struct thread *td)
*/
/* ARGSUSED */
static int
-devfs_fsync(ap)
- struct vop_fsync_args /* {
- struct vnode *a_vp;
- struct ucred *a_cred;
- int a_waitfor;
- struct thread *a_td;
- } */ *ap;
+devfs_fsync(struct vop_fsync_args *ap)
{
if (!vn_isdisk(ap->a_vp, NULL))
return (0);
@@ -459,13 +315,7 @@ devfs_fsync(ap)
}
static int
-devfs_getattr(ap)
- struct vop_getattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
+devfs_getattr(struct vop_getattr_args *ap)
{
struct vnode *vp = ap->a_vp;
struct vattr *vap = ap->a_vap;
@@ -520,7 +370,7 @@ devfs_getattr(ap)
fix(dev->si_ctime);
vap->va_ctime = dev->si_ctime;
- vap->va_rdev = dev->si_inode ^ devfs_random();
+ vap->va_rdev = dev->si_inode;
}
vap->va_gen = 0;
vap->va_flags = 0;
@@ -564,11 +414,7 @@ devfs_ioctl_f(struct file *fp, u_long com, void *data, struct ucred *cred, struc
dev_relthread(dev);
return (error);
}
- if (dsw->d_flags & D_NEEDGIANT)
- mtx_lock(&Giant);
error = dsw->d_ioctl(dev, com, data, fp->f_flag, td);
- if (dsw->d_flags & D_NEEDGIANT)
- mtx_unlock(&Giant);
dev_relthread(dev);
if (error == ENOIOCTL)
error = ENOTTY;
@@ -612,22 +458,13 @@ devfs_kqfilter_f(struct file *fp, struct knote *kn)
error = devfs_fp_check(fp, &dev, &dsw);
if (error)
return (error);
- if (dsw->d_flags & D_NEEDGIANT)
- mtx_lock(&Giant);
error = dsw->d_kqfilter(dev, kn);
- if (dsw->d_flags & D_NEEDGIANT)
- mtx_unlock(&Giant);
dev_relthread(dev);
return (error);
}
static int
-devfs_lookupx(ap)
- struct vop_lookup_args /* {
- struct vnode * a_dvp;
- struct vnode ** a_vpp;
- struct componentname * a_cnp;
- } */ *ap;
+devfs_lookupx(struct vop_lookup_args *ap)
{
struct componentname *cnp;
struct vnode *dvp, **vpp;
@@ -683,7 +520,9 @@ devfs_lookupx(ap)
return (error);
}
+ lockmgr(&dmp->dm_lock, LK_UPGRADE, 0, curthread);
devfs_populate(dmp);
+ lockmgr(&dmp->dm_lock, LK_DOWNGRADE, 0, curthread);
dd = dvp->v_data;
TAILQ_FOREACH(de, &dd->de_dlist, de_list) {
if (cnp->cn_namelen != de->de_dirent->d_namlen)
@@ -713,7 +552,9 @@ devfs_lookupx(ap)
if (cdev == NULL)
goto notfound;
+ lockmgr(&dmp->dm_lock, LK_UPGRADE, 0, curthread);
devfs_populate(dmp);
+ lockmgr(&dmp->dm_lock, LK_DOWNGRADE, 0, curthread);
dde = devfs_itode(dmp, cdev->si_inode);
dev_rel(cdev);
@@ -772,14 +613,6 @@ devfs_lookup(struct vop_lookup_args *ap)
static int
devfs_mknod(struct vop_mknod_args *ap)
- /*
- struct vop_mknod_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- }; */
{
struct componentname *cnp;
struct vnode *dvp, **vpp;
@@ -828,14 +661,7 @@ notfound:
*/
/* ARGSUSED */
static int
-devfs_open(ap)
- struct vop_open_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct thread *a_td;
- int a_fdidx;
- } */ *ap;
+devfs_open(struct vop_open_args *ap)
{
struct thread *td = ap->a_td;
struct vnode *vp = ap->a_vp;
@@ -884,12 +710,10 @@ devfs_open(ap)
error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td);
PICKUP_GIANT();
} else {
- mtx_lock(&Giant);
if (dsw->d_fdopen != NULL)
error = dsw->d_fdopen(dev, ap->a_mode, td, ap->a_fdidx);
else
error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td);
- mtx_unlock(&Giant);
}
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
@@ -921,21 +745,10 @@ devfs_open(ap)
}
static int
-devfs_pathconf(ap)
- struct vop_pathconf_args /* {
- struct vnode *a_vp;
- int a_name;
- int *a_retval;
- } */ *ap;
+devfs_pathconf(struct vop_pathconf_args *ap)
{
switch (ap->a_name) {
- case _PC_NAME_MAX:
- *ap->a_retval = NAME_MAX;
- return (0);
- case _PC_PATH_MAX:
- *ap->a_retval = PATH_MAX;
- return (0);
case _PC_MAC_PRESENT:
#ifdef MAC
/*
@@ -964,11 +777,7 @@ devfs_poll_f(struct file *fp, int events, struct ucred *cred, struct thread *td)
error = devfs_fp_check(fp, &dev, &dsw);
if (error)
return (error);
- if (dsw->d_flags & D_NEEDGIANT)
- mtx_lock(&Giant);
error = dsw->d_poll(dev, events, td);
- if (dsw->d_flags & D_NEEDGIANT)
- mtx_unlock(&Giant);
dev_relthread(dev);
return(error);
}
@@ -977,10 +786,7 @@ devfs_poll_f(struct file *fp, int events, struct ucred *cred, struct thread *td)
* Print out the contents of a special device vnode.
*/
static int
-devfs_print(ap)
- struct vop_print_args /* {
- struct vnode *a_vp;
- } */ *ap;
+devfs_print(struct vop_print_args *ap)
{
printf("\tdev %s\n", devtoname(ap->a_vp->v_rdev));
@@ -1009,11 +815,7 @@ devfs_read_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, st
if ((flags & FOF_OFFSET) == 0)
uio->uio_offset = fp->f_offset;
- if (dsw->d_flags & D_NEEDGIANT)
- mtx_lock(&Giant);
error = dsw->d_read(dev, uio, ioflag);
- if (dsw->d_flags & D_NEEDGIANT)
- mtx_unlock(&Giant);
dev_relthread(dev);
if (uio->uio_resid != resid || (error == 0 && resid != 0))
vfs_timestamp(&dev->si_atime);
@@ -1025,15 +827,7 @@ devfs_read_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, st
}
static int
-devfs_readdir(ap)
- struct vop_readdir_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
- int *a_eofflag;
- int *a_ncookies;
- u_long **a_cookies;
- } */ *ap;
+devfs_readdir(struct vop_readdir_args *ap)
{
int error;
struct uio *uio;
@@ -1042,9 +836,6 @@ devfs_readdir(ap)
struct devfs_dirent *de;
struct devfs_mount *dmp;
off_t off, oldoff;
- int ncookies = 0;
- u_long *cookiebuf, *cookiep;
- struct dirent *dps, *dpe;
if (ap->a_vp->v_type != VDIR)
return (ENOTDIR);
@@ -1054,12 +845,17 @@ devfs_readdir(ap)
return (EINVAL);
dmp = VFSTODEVFS(ap->a_vp->v_mount);
- lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread);
+ lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, curthread);
devfs_populate(dmp);
+ lockmgr(&dmp->dm_lock, LK_DOWNGRADE, 0, curthread);
error = 0;
de = ap->a_vp->v_data;
off = 0;
oldoff = uio->uio_offset;
+ if (ap->a_ncookies != NULL) {
+ *ap->a_ncookies = 0;
+ *ap->a_cookies = NULL;
+ }
TAILQ_FOREACH(dd, &de->de_dlist, de_list) {
if (dd->de_flags & DE_WHITEOUT)
continue;
@@ -1072,55 +868,28 @@ devfs_readdir(ap)
break;
dp->d_fileno = de->de_inode;
if (off >= uio->uio_offset) {
- ncookies++;
- error = uiomove(dp, dp->d_reclen, uio);
+ error = vfs_read_dirent(ap, dp, off);
if (error)
break;
}
off += dp->d_reclen;
}
- if( !error && ap->a_ncookies != NULL && ap->a_cookies != NULL ) {
- MALLOC(cookiebuf, u_long *, ncookies * sizeof(u_long),
- M_TEMP, M_WAITOK);
- cookiep = cookiebuf;
- dps = (struct dirent *)((char *)uio->uio_iov->iov_base -
- (uio->uio_offset - oldoff));
- dpe = (struct dirent *) uio->uio_iov->iov_base;
- for( dp = dps;
- dp < dpe;
- dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) {
- oldoff += dp->d_reclen;
- *cookiep++ = (u_long) oldoff;
- }
- *ap->a_ncookies = ncookies;
- *ap->a_cookies = cookiebuf;
- }
lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread);
uio->uio_offset = off;
return (error);
}
static int
-devfs_readlink(ap)
- struct vop_readlink_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cead;
- } */ *ap;
+devfs_readlink(struct vop_readlink_args *ap)
{
- int error;
struct devfs_dirent *de;
de = ap->a_vp->v_data;
- error = uiomove(de->de_symlink, strlen(de->de_symlink), ap->a_uio);
- return (error);
+ return (uiomove(de->de_symlink, strlen(de->de_symlink), ap->a_uio));
}
static int
-devfs_reclaim(ap)
- struct vop_reclaim_args /* {
- struct vnode *a_vp;
- } */ *ap;
+devfs_reclaim(struct vop_reclaim_args *ap)
{
struct vnode *vp = ap->a_vp;
struct devfs_dirent *de;
@@ -1148,12 +917,7 @@ devfs_reclaim(ap)
}
static int
-devfs_remove(ap)
- struct vop_remove_args /* {
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
- } */ *ap;
+devfs_remove(struct vop_remove_args *ap)
{
struct vnode *vp = ap->a_vp;
struct devfs_dirent *dd;
@@ -1170,7 +934,7 @@ devfs_remove(ap)
#ifdef MAC
mac_destroy_devfsdirent(de);
#endif
- FREE(de, M_DEVFS);
+ free(de, M_DEVFS);
} else {
de->de_flags |= DE_WHITEOUT;
}
@@ -1184,11 +948,7 @@ devfs_remove(ap)
* as well so that we create a new one next time around.
*/
static int
-devfs_revoke(ap)
- struct vop_revoke_args /* {
- struct vnode *a_vp;
- int a_flags;
- } */ *ap;
+devfs_revoke(struct vop_revoke_args *ap)
{
struct vnode *vp = ap->a_vp;
struct cdev *dev;
@@ -1209,36 +969,21 @@ devfs_revoke(ap)
}
static int
-devfs_rioctl(ap)
- struct vop_ioctl_args /* {
- struct vnode *a_vp;
- u_long a_command;
- caddr_t a_data;
- int a_fflag;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
+devfs_rioctl(struct vop_ioctl_args *ap)
{
int error;
struct devfs_mount *dmp;
dmp = VFSTODEVFS(ap->a_vp->v_mount);
- lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread);
+ lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, curthread);
devfs_populate(dmp);
+ error = devfs_rules_ioctl(dmp, ap->a_command, ap->a_data, ap->a_td);
lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread);
- error = devfs_rules_ioctl(ap->a_vp->v_mount, ap->a_command, ap->a_data,
- ap->a_td);
return (error);
}
static int
-devfs_rread(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
+devfs_rread(struct vop_read_args *ap)
{
if (ap->a_vp->v_type != VDIR)
@@ -1247,13 +992,7 @@ devfs_rread(ap)
}
static int
-devfs_setattr(ap)
- struct vop_setattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
+devfs_setattr(struct vop_setattr_args *ap)
{
struct devfs_dirent *de;
struct vattr *vap;
@@ -1339,13 +1078,7 @@ devfs_setattr(ap)
#ifdef MAC
static int
-devfs_setlabel(ap)
- struct vop_setlabel_args /* {
- struct vnode *a_vp;
- struct mac *a_label;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
+devfs_setlabel(struct vop_setlabel_args *ap)
{
struct vnode *vp;
struct devfs_dirent *de;
@@ -1368,14 +1101,7 @@ devfs_stat_f(struct file *fp, struct stat *sb, struct ucred *cred, struct thread
}
static int
-devfs_symlink(ap)
- struct vop_symlink_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- char *a_target;
- } */ *ap;
+devfs_symlink(struct vop_symlink_args *ap)
{
int i, error;
struct devfs_dirent *dd;
@@ -1397,7 +1123,7 @@ devfs_symlink(ap)
de->de_inode = dmp->dm_inode++;
de->de_dirent->d_type = DT_LNK;
i = strlen(ap->a_target) + 1;
- MALLOC(de->de_symlink, char *, i, M_DEVFS, M_WAITOK);
+ de->de_symlink = malloc(i, M_DEVFS, M_WAITOK);
bcopy(ap->a_target, de->de_symlink, i);
lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, td);
#ifdef MAC
@@ -1417,7 +1143,6 @@ static int
devfs_write_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td)
{
struct cdev *dev;
- struct vnode *vp;
int error, ioflag, resid;
struct cdevsw *dsw;
@@ -1425,7 +1150,6 @@ devfs_write_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, s
if (error)
return (error);
KASSERT(uio->uio_td == td, ("uio_td %p is not td %p", uio->uio_td, td));
- vp = fp->f_vnode;
ioflag = fp->f_flag & (O_NONBLOCK | O_DIRECT | O_FSYNC);
if (ioflag & O_DIRECT)
ioflag |= IO_DIRECT;
@@ -1434,11 +1158,7 @@ devfs_write_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, s
resid = uio->uio_resid;
- if (dsw->d_flags & D_NEEDGIANT)
- mtx_lock(&Giant);
error = dsw->d_write(dev, uio, ioflag);
- if (dsw->d_flags & D_NEEDGIANT)
- mtx_unlock(&Giant);
dev_relthread(dev);
if (uio->uio_resid != resid || (error == 0 && resid != 0)) {
vfs_timestamp(&dev->si_ctime);
@@ -1456,37 +1176,76 @@ dev2udev(struct cdev *x)
{
if (x == NULL)
return (NODEV);
- return (x->si_inode ^ devfs_random());
+ return (x->si_inode);
}
-/*
- * Helper sysctl for devname(3). We're given a struct cdev * and return
- * the name, if any, registered by the device driver.
- */
-static int
-sysctl_devname(SYSCTL_HANDLER_ARGS)
-{
- int error;
- dev_t ud;
- struct cdev *dev, **dp;
+static struct fileops devfs_ops_f = {
+ .fo_read = devfs_read_f,
+ .fo_write = devfs_write_f,
+ .fo_ioctl = devfs_ioctl_f,
+ .fo_poll = devfs_poll_f,
+ .fo_kqfilter = devfs_kqfilter_f,
+ .fo_stat = devfs_stat_f,
+ .fo_close = devfs_close_f,
+ .fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
+};
- error = SYSCTL_IN(req, &ud, sizeof (ud));
- if (error)
- return (error);
- if (ud == NODEV)
- return(EINVAL);
- dp = devfs_itod(ud ^ devfs_random());
- if (dp == NULL)
- return(ENOENT);
- dev = *dp;
- if (dev == NULL)
- return(ENOENT);
- return(SYSCTL_OUT(req, dev->si_name, strlen(dev->si_name) + 1));
- return (error);
-}
+static struct vop_vector devfs_vnodeops = {
+ .vop_default = &default_vnodeops,
-SYSCTL_PROC(_kern, OID_AUTO, devname, CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_ANYBODY,
- NULL, 0, sysctl_devname, "", "devname(3) handler");
+ .vop_access = devfs_access,
+ .vop_getattr = devfs_getattr,
+ .vop_ioctl = devfs_rioctl,
+ .vop_lookup = devfs_lookup,
+ .vop_mknod = devfs_mknod,
+ .vop_pathconf = devfs_pathconf,
+ .vop_read = devfs_rread,
+ .vop_readdir = devfs_readdir,
+ .vop_readlink = devfs_readlink,
+ .vop_reclaim = devfs_reclaim,
+ .vop_remove = devfs_remove,
+ .vop_revoke = devfs_revoke,
+ .vop_setattr = devfs_setattr,
+#ifdef MAC
+ .vop_setlabel = devfs_setlabel,
+#endif
+ .vop_symlink = devfs_symlink,
+};
+
+static struct vop_vector devfs_specops = {
+ .vop_default = &default_vnodeops,
+
+ .vop_access = devfs_access,
+ .vop_advlock = devfs_advlock,
+ .vop_bmap = VOP_PANIC,
+ .vop_close = devfs_close,
+ .vop_create = VOP_PANIC,
+ .vop_fsync = devfs_fsync,
+ .vop_getattr = devfs_getattr,
+ .vop_lease = VOP_NULL,
+ .vop_link = VOP_PANIC,
+ .vop_mkdir = VOP_PANIC,
+ .vop_mknod = VOP_PANIC,
+ .vop_open = devfs_open,
+ .vop_pathconf = devfs_pathconf,
+ .vop_print = devfs_print,
+ .vop_read = VOP_PANIC,
+ .vop_readdir = VOP_PANIC,
+ .vop_readlink = VOP_PANIC,
+ .vop_reallocblks = VOP_PANIC,
+ .vop_reclaim = devfs_reclaim,
+ .vop_remove = devfs_remove,
+ .vop_rename = VOP_PANIC,
+ .vop_revoke = devfs_revoke,
+ .vop_rmdir = VOP_PANIC,
+ .vop_setattr = devfs_setattr,
+#ifdef MAC
+ .vop_setlabel = devfs_setlabel,
+#endif
+ .vop_strategy = VOP_PANIC,
+ .vop_symlink = VOP_PANIC,
+ .vop_write = VOP_PANIC,
+};
/*
* Our calling convention to the device drivers used to be that we passed
diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c
index 3c4ab29274fd..a6fcf83ab144 100644
--- a/sys/kern/kern_conf.c
+++ b/sys/kern/kern_conf.c
@@ -45,9 +45,9 @@ __FBSDID("$FreeBSD$");
#include <sys/ucred.h>
#include <machine/stdarg.h>
-static MALLOC_DEFINE(M_DEVT, "cdev", "cdev storage");
+#include <fs/devfs/devfs_int.h>
-/* Built at compile time from sys/conf/majors */
+static MALLOC_DEFINE(M_DEVT, "cdev", "cdev storage");
static struct mtx devmtx;
static void freedev(struct cdev *dev);
@@ -232,6 +232,125 @@ no_poll(struct cdev *dev __unused, int events, struct thread *td __unused)
#define no_dump (dumper_t *)enodev
+static int
+giant_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ int retval;
+
+ mtx_lock(&Giant);
+ retval = dev->si_devsw->d_gianttrick->
+ d_open(dev, oflags, devtype, td);
+ mtx_unlock(&Giant);
+ return (retval);
+}
+
+static int
+giant_fdopen(struct cdev *dev, int oflags, struct thread *td, int fdidx)
+{
+ int retval;
+
+ mtx_lock(&Giant);
+ retval = dev->si_devsw->d_gianttrick->
+ d_fdopen(dev, oflags, td, fdidx);
+ mtx_unlock(&Giant);
+ return (retval);
+}
+
+static int
+giant_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
+{
+ int retval;
+
+ mtx_lock(&Giant);
+ retval = dev->si_devsw->d_gianttrick->
+ d_close(dev, fflag, devtype, td);
+ mtx_unlock(&Giant);
+ return (retval);
+}
+
+static void
+giant_strategy(struct bio *bp)
+{
+
+ mtx_lock(&Giant);
+ bp->bio_dev->si_devsw->d_gianttrick->
+ d_strategy(bp);
+ mtx_unlock(&Giant);
+}
+
+static int
+giant_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
+{
+ int retval;
+
+ mtx_lock(&Giant);
+ retval = dev->si_devsw->d_gianttrick->
+ d_ioctl(dev, cmd, data, fflag, td);
+ mtx_unlock(&Giant);
+ return (retval);
+}
+
+static int
+giant_read(struct cdev *dev, struct uio *uio, int ioflag)
+{
+ int retval;
+
+ mtx_lock(&Giant);
+ retval = dev->si_devsw->d_gianttrick->
+ d_read(dev, uio, ioflag);
+ mtx_unlock(&Giant);
+ return (retval);
+}
+
+static int
+giant_write(struct cdev *dev, struct uio *uio, int ioflag)
+{
+ int retval;
+
+ mtx_lock(&Giant);
+ retval = dev->si_devsw->d_gianttrick->
+ d_write(dev, uio, ioflag);
+ mtx_unlock(&Giant);
+ return (retval);
+}
+
+static int
+giant_poll(struct cdev *dev, int events, struct thread *td)
+{
+ int retval;
+
+ mtx_lock(&Giant);
+ retval = dev->si_devsw->d_gianttrick->
+ d_poll(dev, events, td);
+ mtx_unlock(&Giant);
+ return (retval);
+}
+
+static int
+giant_kqfilter(struct cdev *dev, struct knote *kn)
+{
+ int retval;
+
+ mtx_lock(&Giant);
+ retval = dev->si_devsw->d_gianttrick->
+ d_kqfilter(dev, kn);
+ mtx_unlock(&Giant);
+ return (retval);
+}
+
+static int
+giant_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
+{
+ int retval;
+
+ mtx_lock(&Giant);
+ retval = dev->si_devsw->d_gianttrick->
+ d_mmap(dev, offset, paddr, nprot);
+ mtx_unlock(&Giant);
+ return (retval);
+}
+
+
/*
* struct cdev * and u_dev_t primitives
*/
@@ -324,14 +443,26 @@ umajor(dev_t dev)
static void
fini_cdevsw(struct cdevsw *devsw)
{
+ struct cdevsw *gt;
+ if (devsw->d_gianttrick != NULL) {
+ gt = devsw->d_gianttrick;
+ memcpy(devsw, gt, sizeof *devsw);
+ free(gt, M_DEVT);
+ devsw->d_gianttrick = NULL;
+ }
devsw->d_flags &= ~D_INIT;
}
static void
prep_cdevsw(struct cdevsw *devsw)
{
+ struct cdevsw *dsw2;
+ if (devsw->d_flags & D_NEEDGIANT)
+ dsw2 = malloc(sizeof *dsw2, M_DEVT, M_WAITOK);
+ else
+ dsw2 = NULL;
dev_lock();
if (devsw->d_version != D_VERSION_01) {
@@ -358,16 +489,35 @@ prep_cdevsw(struct cdevsw *devsw)
if (devsw->d_poll == NULL) devsw->d_poll = ttypoll;
}
- if (devsw->d_open == NULL) devsw->d_open = null_open;
- if (devsw->d_close == NULL) devsw->d_close = null_close;
- if (devsw->d_read == NULL) devsw->d_read = no_read;
- if (devsw->d_write == NULL) devsw->d_write = no_write;
- if (devsw->d_ioctl == NULL) devsw->d_ioctl = no_ioctl;
- if (devsw->d_poll == NULL) devsw->d_poll = no_poll;
- if (devsw->d_mmap == NULL) devsw->d_mmap = no_mmap;
- if (devsw->d_strategy == NULL) devsw->d_strategy = no_strategy;
+ if (devsw->d_flags & D_NEEDGIANT) {
+ if (devsw->d_gianttrick == NULL) {
+ memcpy(dsw2, devsw, sizeof *dsw2);
+ devsw->d_gianttrick = dsw2;
+ } else
+ free(dsw2, M_DEVT);
+ }
+
+#define FIXUP(member, noop, giant) \
+ do { \
+ if (devsw->member == NULL) { \
+ devsw->member = noop; \
+ } else if (devsw->d_flags & D_NEEDGIANT) \
+ devsw->member = giant; \
+ } \
+ while (0)
+
+ FIXUP(d_open, null_open, giant_open);
+ FIXUP(d_fdopen, NULL, giant_fdopen);
+ FIXUP(d_close, null_close, giant_close);
+ FIXUP(d_read, no_read, giant_read);
+ FIXUP(d_write, no_write, giant_write);
+ FIXUP(d_ioctl, no_ioctl, giant_ioctl);
+ FIXUP(d_poll, no_poll, giant_poll);
+ FIXUP(d_mmap, no_mmap, giant_mmap);
+ FIXUP(d_strategy, no_strategy, giant_strategy);
+ FIXUP(d_kqfilter, no_kqfilter, giant_kqfilter);
+
if (devsw->d_dump == NULL) devsw->d_dump = no_dump;
- if (devsw->d_kqfilter == NULL) devsw->d_kqfilter = no_kqfilter;
LIST_INIT(&devsw->d_devs);
@@ -454,19 +604,6 @@ make_dev_cred(struct cdevsw *devsw, int minornr, struct ucred *cr, uid_t uid,
return (dev);
}
-int
-dev_named(struct cdev *pdev, const char *name)
-{
- struct cdev *cdev;
-
- if (strcmp(devtoname(pdev), name) == 0)
- return (1);
- LIST_FOREACH(cdev, &pdev->si_children, si_siblings)
- if (strcmp(devtoname(cdev), name) == 0)
- return (1);
- return (0);
-}
-
void
dev_depends(struct cdev *pdev, struct cdev *cdev)
{
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 7140aec6e508..a35389104590 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/conf.h>
+#include <sys/dirent.h>
#include <sys/event.h>
#include <sys/eventhandler.h>
#include <sys/extattr.h>
@@ -3851,3 +3852,29 @@ filt_vfsvnode(struct knote *kn, long hint)
}
return (kn->kn_fflags != 0);
}
+
+int
+vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t off)
+{
+ int error;
+
+ if (dp->d_reclen > ap->a_uio->uio_resid)
+ return (ENAMETOOLONG);
+ error = uiomove(dp, dp->d_reclen, ap->a_uio);
+ if (error) {
+ if (ap->a_ncookies != NULL) {
+ if (ap->a_cookies != NULL)
+ free(ap->a_cookies, M_TEMP);
+ ap->a_cookies = NULL;
+ *ap->a_ncookies = 0;
+ }
+ return (error);
+ }
+ if (ap->a_ncookies == NULL)
+ return (0);
+ *ap->a_cookies = realloc(*ap->a_cookies,
+ (*ap->a_ncookies + 1) * sizeof(u_long), M_TEMP, M_WAITOK | M_ZERO);
+ (*ap->a_cookies)[*ap->a_ncookies] = off;
+ return (0);
+}
+
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index 2dfa9561dee8..1ceadc0eb206 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -213,6 +213,7 @@ struct cdevsw {
LIST_ENTRY(cdevsw) d_list;
LIST_HEAD(, cdev) d_devs;
int d_spare3;
+ struct cdevsw *d_gianttrick;
};
#define NUMCDEVSW 256
@@ -246,7 +247,6 @@ int count_dev(struct cdev *_dev);
void destroy_dev(struct cdev *_dev);
struct cdevsw *dev_refthread(struct cdev *_dev);
void dev_relthread(struct cdev *_dev);
-int dev_named(struct cdev *_pdev, const char *_name);
void dev_depends(struct cdev *_pdev, struct cdev *_cdev);
void dev_ref(struct cdev *dev);
void dev_refl(struct cdev *dev);
@@ -265,9 +265,6 @@ int unit2minor(int _unit);
u_int minor2unit(u_int _minor);
void setconf(void);
-void devfs_create(struct cdev *dev);
-void devfs_destroy(struct cdev *dev);
-
#define UID_ROOT 0
#define UID_BIN 3
#define UID_UUCP 66
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 598062f05a80..3c84baf54425 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -736,6 +736,8 @@ void vfs_hash_rehash(struct vnode *vp, u_int hash);
void vfs_hash_remove(struct vnode *vp);
int vfs_kqfilter(struct vop_kqfilter_args *);
+struct dirent;
+int vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t off);
#endif /* _KERNEL */