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:
parent
925be47cdb
commit
8abea41d80
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user