Don't hold an extra reference to vnodes. Devfs vnodes are sufficiently

cheap to setup that it doesn't really matter that we recycle device
vnodes at kleenex speed.

Implement first cut try at killing cloned devices when they are
not needed anymore.  For now only the bpf driver is involved in
this experiment.  Cloned devices can set the SI_CHEAPCLONE flag
which allows us to destroy_dev() it when the vcount() drops to zero
and the vnode is reclaimed.  For now it's a requirement that the
driver doesn't keep persistent state from close to (re)open.

Some whitespace changes.
This commit is contained in:
Poul-Henning Kamp 2000-10-09 14:18:07 +00:00
parent 925be47cdb
commit 8abea41d80
3 changed files with 28 additions and 24 deletions

View File

@ -153,10 +153,10 @@ devfs_attemptoverflow(int insist)
bzero(ot, nb);
nb = sizeof (int) * n;
MALLOC(or, int *, nb, M_DEVFS, insist ? M_WAITOK : M_NOWAIT);
if (or == NULL)
if (or == NULL)
goto bail;
bzero(or, nb);
if (!atomic_cmpset_ptr(&devfs_overflow, NULL, ot))
if (!atomic_cmpset_ptr(&devfs_overflow, NULL, ot))
goto bail;
devfs_refoverflow = or;
devfs_noverflow = n;
@ -249,10 +249,8 @@ devfs_delete(struct devfs_dirent *dd, struct devfs_dirent *de)
FREE(de->de_symlink, M_DEVFS);
de->de_symlink = NULL;
}
if (de->de_vnode) {
if (de->de_vnode)
de->de_vnode->v_data = NULL;
vdrop(de->de_vnode);
}
TAILQ_REMOVE(&dd->de_dlist, de, de_list);
FREE(de, M_DEVFS);
}
@ -281,7 +279,7 @@ devfs_populate(struct devfs_mount *dm)
struct devfs_dirent *de, **dep;
char *q, *s;
if (dm->dm_generation == devfs_generation)
if (dm->dm_generation == devfs_generation)
return (0);
lockmgr(&dm->dm_lock, LK_UPGRADE, 0, curproc);
if (devfs_noverflow && dm->dm_overflow == NULL) {
@ -304,10 +302,8 @@ devfs_populate(struct devfs_mount *dm)
dd = de->de_dir;
*dep = NULL;
TAILQ_REMOVE(&dd->de_dlist, de, de_list);
if (de->de_vnode) {
if (de->de_vnode)
de->de_vnode->v_data = NULL;
vdrop(de->de_vnode);
}
FREE(de, M_DEVFS);
devfs_dropref(i);
continue;
@ -323,7 +319,7 @@ devfs_populate(struct devfs_mount *dm)
for (;;) {
for (q = s; *q != '/' && *q != '\0'; q++)
continue;
if (*q != '/')
if (*q != '/')
break;
de = devfs_find(dd, s, q - s);
if (de == NULL) {

View File

@ -133,12 +133,14 @@ devfs_unmount(mp, mntflags, p)
fmp = VFSTODEVFS(mp);
if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
if (rootvp->v_usecount > 1)
if (rootvp->v_usecount > 2) {
vrele(rootvp);
return (EBUSY);
devfs_purge(fmp->dm_rootdir);
}
error = vflush(mp, rootvp, flags);
if (error)
return (error);
devfs_purge(fmp->dm_rootdir);
vput(rootvp);
vrele(rootvp);
vgone(rootvp);

View File

@ -106,7 +106,6 @@ devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, stru
}
vp->v_data = de;
de->de_vnode = vp;
vhold(vp);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return (0);
@ -148,7 +147,7 @@ devfs_getattr(ap)
dev_t dev;
de = vp->v_data;
if (vp->v_type == VDIR)
if (vp->v_type == VDIR)
de = de->de_dir;
bzero((caddr_t) vap, sizeof(*vap));
vattr_null(vap);
@ -245,7 +244,7 @@ devfs_lookupx(ap)
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
}
if ((flags & LOCKPARENT) && (flags & ISLASTCN))
if ((flags & LOCKPARENT) && (flags & ISLASTCN))
error = vn_lock(dvp, LK_EXCLUSIVE, p);
if (error)
vput(*vpp);
@ -296,13 +295,13 @@ devfs_lookupx(ap)
printf("Finished specname: %d \"%s\"\n", i, specname + i);
#endif
cdev = NODEV;
EVENTHANDLER_INVOKE(dev_clone, specname + i,
EVENTHANDLER_INVOKE(dev_clone, specname + i,
strlen(specname + i), &cdev);
#if 0
printf("cloned %s -> %p %s\n", specname + i, cdev,
cdev == NODEV ? "NODEV" : cdev->si_name);
#endif
if (cdev == NODEV)
if (cdev == NODEV)
goto notfound;
devfs_populate(dmp);
@ -431,7 +430,7 @@ devfs_readdir(ap)
dd = TAILQ_FIRST(&de->de_dlist);
off = 0;
while (dd != NULL) {
if (dd->de_dirent->d_type == DT_DIR)
if (dd->de_dirent->d_type == DT_DIR)
de = dd->de_dir;
else
de = dd;
@ -476,14 +475,24 @@ devfs_reclaim(ap)
{
struct vnode *vp = ap->a_vp;
struct devfs_dirent *de;
int i;
de = vp->v_data;
if (de != NULL)
de->de_vnode = NULL;
if (de != NULL && de->de_flags & DE_ORPHAN) {
if (de->de_symlink)
if (de->de_symlink)
FREE(de->de_symlink, M_DEVFS);
FREE(de, M_DEVFS);
FREE(de, M_DEVFS);
}
vp->v_data = NULL;
if (vp->v_rdev != NODEV && vp->v_rdev != NULL) {
i = vcount(vp);
if ((vp->v_rdev->si_flags & SI_CHEAPCLONE) && i == 0) {
destroy_dev(vp->v_rdev);
printf("Reclaim <%s> %d %d Killed\n", vp->v_rdev->si_name, vp->v_rdev->si_flags, i);
}
}
return (0);
}
@ -508,7 +517,6 @@ devfs_remove(ap)
if (dep != NULL)
*dep = DE_DELETED;
de->de_flags |= DE_ORPHAN;
vdrop(de->de_vnode);
lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curproc);
return (0);
}
@ -529,8 +537,6 @@ devfs_revoke(ap)
struct devfs_dirent *de;
de = vp->v_data;
if (!(de->de_flags & DE_ORPHAN))
vdrop(de->de_vnode);
de->de_vnode = NULL;
vop_revoke(ap);
return (0);
@ -565,7 +571,7 @@ devfs_setattr(ap)
}
de = ap->a_vp->v_data;
if (ap->a_vp->v_type == VDIR)
if (ap->a_vp->v_type == VDIR)
de = de->de_dir;
error = c = 0;