From 8abea41d80bbf91a65915394ec1c2634b26a0761 Mon Sep 17 00:00:00 2001 From: Poul-Henning Kamp Date: Mon, 9 Oct 2000 14:18:07 +0000 Subject: [PATCH] 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. --- sys/fs/devfs/devfs_devs.c | 16 ++++++---------- sys/fs/devfs/devfs_vfsops.c | 6 ++++-- sys/fs/devfs/devfs_vnops.c | 30 ++++++++++++++++++------------ 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c index 49854a0624d..1d5d32b825a 100644 --- a/sys/fs/devfs/devfs_devs.c +++ b/sys/fs/devfs/devfs_devs.c @@ -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) { diff --git a/sys/fs/devfs/devfs_vfsops.c b/sys/fs/devfs/devfs_vfsops.c index 00951ae24da..0c5d1bbc03a 100644 --- a/sys/fs/devfs/devfs_vfsops.c +++ b/sys/fs/devfs/devfs_vfsops.c @@ -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); diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index cb8caff6698..e3c717e4a41 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -106,7 +106,6 @@ loop: } 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;