Various fixes for DEVFS, in particular "devfs ruleset already running".

Approved by:	re@ (scottl)
This commit is contained in:
phk 2005-09-18 07:10:57 +00:00
parent 9e1e30a0a8
commit 051ea6d1a8
9 changed files with 384 additions and 450 deletions

View File

@ -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);

View File

@ -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);
}
/*

View File

@ -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);
}
/*
@ -367,17 +360,6 @@ devfs_rid_input(devfs_rid rid, struct devfs_mount *dm)
return (rid);
}
/*
* 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.
*
@ -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);
}

View File

@ -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);

View File

@ -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>
static struct vop_vector devfs_vnodeops;
static struct vop_vector devfs_specops;
static struct fileops devfs_ops_f;
#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 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 @@ devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, stru
}
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 @@ devfs_mknod(struct vop_mknod_args *ap)
*/
/* 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

View File

@ -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)
{

View File

@ -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);
}

View File

@ -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

View File

@ -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 */