diff options
author | mckusick <mckusick@FreeBSD.org> | 2000-07-04 04:32:40 +0000 |
---|---|---|
committer | mckusick <mckusick@FreeBSD.org> | 2000-07-04 04:32:40 +0000 |
commit | 2f0e9591fa0ef8bf1039608fd618c45ca89f9ec5 (patch) | |
tree | 58a79282436942422de8503a1b12b5b380619f8c | |
parent | 040e64cd9770955113ddffda73fff7b62dd5959b (diff) | |
download | FreeBSD-src-2f0e9591fa0ef8bf1039608fd618c45ca89f9ec5.zip FreeBSD-src-2f0e9591fa0ef8bf1039608fd618c45ca89f9ec5.tar.gz |
Simplify and rationalise the management of the vnode free list
(preparing the code to add snapshots).
-rw-r--r-- | sys/kern/vfs_export.c | 104 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 104 | ||||
-rw-r--r-- | sys/sys/vnode.h | 8 | ||||
-rw-r--r-- | sys/vm/vm_page.c | 8 |
4 files changed, 65 insertions, 159 deletions
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index fa6e117..14ec284 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -83,7 +83,6 @@ static MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure"); static void insmntque __P((struct vnode *vp, struct mount *mp)); static void vclean __P((struct vnode *vp, int flags, struct proc *p)); -static void vfree __P((struct vnode *)); static unsigned long numvnodes; SYSCTL_INT(_debug, OID_AUTO, numvnodes, CTLFLAG_RD, &numvnodes, 0, ""); @@ -97,7 +96,6 @@ int vttoif_tab[9] = { }; static TAILQ_HEAD(freelst, vnode) vnode_free_list; /* vnode free list */ -struct tobefreelist vnode_tobefree_list; /* vnode free list */ static u_long wantfreevnodes = 25; SYSCTL_INT(_debug, OID_AUTO, wantfreevnodes, CTLFLAG_RW, &wantfreevnodes, 0, ""); @@ -175,7 +173,6 @@ vntblinit() simple_lock_init(&mntid_slock); simple_lock_init(&spechash_slock); TAILQ_INIT(&vnode_free_list); - TAILQ_INIT(&vnode_tobefree_list); simple_lock_init(&vnode_free_list_slock); vnode_zone = zinit("VNODE", sizeof (struct vnode), 0, 0, 5); /* @@ -451,11 +448,10 @@ getnewvnode(tag, mp, vops, vpp) vop_t **vops; struct vnode **vpp; { - int s; + int s, count; struct proc *p = curproc; /* XXX */ - struct vnode *vp, *tvp, *nvp; + struct vnode *vp = NULL; vm_object_t object; - TAILQ_HEAD(freelst, vnode) vnode_tmp_list; /* * We take the least recently used vnode from the freelist @@ -466,22 +462,6 @@ getnewvnode(tag, mp, vops, vpp) s = splbio(); simple_lock(&vnode_free_list_slock); - TAILQ_INIT(&vnode_tmp_list); - - for (vp = TAILQ_FIRST(&vnode_tobefree_list); vp; vp = nvp) { - nvp = TAILQ_NEXT(vp, v_freelist); - TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); - if (vp->v_flag & VAGE) { - TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); - } else { - TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); - } - vp->v_flag &= ~(VTBFREE|VAGE); - vp->v_flag |= VFREE; - if (vp->v_usecount) - panic("tobe free vnode isn't"); - freevnodes++; - } if (wantfreevnodes && freevnodes < wantfreevnodes) { vp = NULL; @@ -490,42 +470,29 @@ getnewvnode(tag, mp, vops, vpp) * XXX: this is only here to be backwards compatible */ vp = NULL; - } else { - for (vp = TAILQ_FIRST(&vnode_free_list); vp; vp = nvp) { - nvp = TAILQ_NEXT(vp, v_freelist); - if (!simple_lock_try(&vp->v_interlock)) - continue; - if (vp->v_usecount) - panic("free vnode isn't"); - - object = vp->v_object; - if (object && (object->resident_page_count || object->ref_count)) { - printf("object inconsistant state: RPC: %d, RC: %d\n", - object->resident_page_count, object->ref_count); - /* Don't recycle if it's caching some pages */ - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - TAILQ_INSERT_TAIL(&vnode_tmp_list, vp, v_freelist); - continue; - } else if (LIST_FIRST(&vp->v_cache_src)) { - /* Don't recycle if active in the namecache */ - simple_unlock(&vp->v_interlock); - continue; - } else { - break; - } + } else for (count = 0; count < freevnodes; count++) { + vp = TAILQ_FIRST(&vnode_free_list); + if (vp == NULL || vp->v_usecount) + panic("getnewvnode: free vnode isn't"); + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + /* + * Don't recycle if active in the namecache or + * if it still has cached pages or we cannot get + * its interlock. + */ + object = vp->v_object; + if (LIST_FIRST(&vp->v_cache_src) != NULL || + (object && (object->resident_page_count || + object->ref_count)) || + !simple_lock_try(&vp->v_interlock)) { + TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); + vp = NULL; + continue; } + break; } - - for (tvp = TAILQ_FIRST(&vnode_tmp_list); tvp; tvp = nvp) { - nvp = TAILQ_NEXT(tvp, v_freelist); - TAILQ_REMOVE(&vnode_tmp_list, tvp, v_freelist); - TAILQ_INSERT_TAIL(&vnode_free_list, tvp, v_freelist); - simple_unlock(&tvp->v_interlock); - } - if (vp) { vp->v_flag |= VDOOMED; - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); freevnodes--; simple_unlock(&vnode_free_list_slock); cache_purge(vp); @@ -1868,8 +1835,8 @@ vgonel(vp, p) /* * If it is on the freelist and not already at the head, - * move it to the head of the list. The test of the back - * pointer and the reference count of zero is because + * move it to the head of the list. The test of the + * VDOOMED flag and the reference count of zero is because * it will be removed from the free list by getnewvnode, * but will not have its reference count incremented until * after calling vgone. If the reference count were @@ -1879,13 +1846,9 @@ vgonel(vp, p) if (vp->v_usecount == 0 && !(vp->v_flag & VDOOMED)) { s = splbio(); simple_lock(&vnode_free_list_slock); - if (vp->v_flag & VFREE) { + if (vp->v_flag & VFREE) TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - } else if (vp->v_flag & VTBFREE) { - TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); - vp->v_flag &= ~VTBFREE; - freevnodes++; - } else + else freevnodes++; vp->v_flag |= VFREE; TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); @@ -2593,7 +2556,7 @@ retn: return error; } -static void +void vfree(vp) struct vnode *vp; { @@ -2601,10 +2564,7 @@ vfree(vp) s = splbio(); simple_lock(&vnode_free_list_slock); - if (vp->v_flag & VTBFREE) { - TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); - vp->v_flag &= ~VTBFREE; - } + KASSERT((vp->v_flag & VFREE) == 0, ("vnode already free")); if (vp->v_flag & VAGE) { TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); } else { @@ -2625,13 +2585,9 @@ vbusy(vp) s = splbio(); simple_lock(&vnode_free_list_slock); - if (vp->v_flag & VTBFREE) { - TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); - vp->v_flag &= ~VTBFREE; - } else { - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - freevnodes--; - } + KASSERT((vp->v_flag & VFREE) != 0, ("vnode not free")); + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + freevnodes--; simple_unlock(&vnode_free_list_slock); vp->v_flag &= ~(VFREE|VAGE); splx(s); diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index fa6e117..14ec284 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -83,7 +83,6 @@ static MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure"); static void insmntque __P((struct vnode *vp, struct mount *mp)); static void vclean __P((struct vnode *vp, int flags, struct proc *p)); -static void vfree __P((struct vnode *)); static unsigned long numvnodes; SYSCTL_INT(_debug, OID_AUTO, numvnodes, CTLFLAG_RD, &numvnodes, 0, ""); @@ -97,7 +96,6 @@ int vttoif_tab[9] = { }; static TAILQ_HEAD(freelst, vnode) vnode_free_list; /* vnode free list */ -struct tobefreelist vnode_tobefree_list; /* vnode free list */ static u_long wantfreevnodes = 25; SYSCTL_INT(_debug, OID_AUTO, wantfreevnodes, CTLFLAG_RW, &wantfreevnodes, 0, ""); @@ -175,7 +173,6 @@ vntblinit() simple_lock_init(&mntid_slock); simple_lock_init(&spechash_slock); TAILQ_INIT(&vnode_free_list); - TAILQ_INIT(&vnode_tobefree_list); simple_lock_init(&vnode_free_list_slock); vnode_zone = zinit("VNODE", sizeof (struct vnode), 0, 0, 5); /* @@ -451,11 +448,10 @@ getnewvnode(tag, mp, vops, vpp) vop_t **vops; struct vnode **vpp; { - int s; + int s, count; struct proc *p = curproc; /* XXX */ - struct vnode *vp, *tvp, *nvp; + struct vnode *vp = NULL; vm_object_t object; - TAILQ_HEAD(freelst, vnode) vnode_tmp_list; /* * We take the least recently used vnode from the freelist @@ -466,22 +462,6 @@ getnewvnode(tag, mp, vops, vpp) s = splbio(); simple_lock(&vnode_free_list_slock); - TAILQ_INIT(&vnode_tmp_list); - - for (vp = TAILQ_FIRST(&vnode_tobefree_list); vp; vp = nvp) { - nvp = TAILQ_NEXT(vp, v_freelist); - TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); - if (vp->v_flag & VAGE) { - TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); - } else { - TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); - } - vp->v_flag &= ~(VTBFREE|VAGE); - vp->v_flag |= VFREE; - if (vp->v_usecount) - panic("tobe free vnode isn't"); - freevnodes++; - } if (wantfreevnodes && freevnodes < wantfreevnodes) { vp = NULL; @@ -490,42 +470,29 @@ getnewvnode(tag, mp, vops, vpp) * XXX: this is only here to be backwards compatible */ vp = NULL; - } else { - for (vp = TAILQ_FIRST(&vnode_free_list); vp; vp = nvp) { - nvp = TAILQ_NEXT(vp, v_freelist); - if (!simple_lock_try(&vp->v_interlock)) - continue; - if (vp->v_usecount) - panic("free vnode isn't"); - - object = vp->v_object; - if (object && (object->resident_page_count || object->ref_count)) { - printf("object inconsistant state: RPC: %d, RC: %d\n", - object->resident_page_count, object->ref_count); - /* Don't recycle if it's caching some pages */ - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - TAILQ_INSERT_TAIL(&vnode_tmp_list, vp, v_freelist); - continue; - } else if (LIST_FIRST(&vp->v_cache_src)) { - /* Don't recycle if active in the namecache */ - simple_unlock(&vp->v_interlock); - continue; - } else { - break; - } + } else for (count = 0; count < freevnodes; count++) { + vp = TAILQ_FIRST(&vnode_free_list); + if (vp == NULL || vp->v_usecount) + panic("getnewvnode: free vnode isn't"); + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + /* + * Don't recycle if active in the namecache or + * if it still has cached pages or we cannot get + * its interlock. + */ + object = vp->v_object; + if (LIST_FIRST(&vp->v_cache_src) != NULL || + (object && (object->resident_page_count || + object->ref_count)) || + !simple_lock_try(&vp->v_interlock)) { + TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); + vp = NULL; + continue; } + break; } - - for (tvp = TAILQ_FIRST(&vnode_tmp_list); tvp; tvp = nvp) { - nvp = TAILQ_NEXT(tvp, v_freelist); - TAILQ_REMOVE(&vnode_tmp_list, tvp, v_freelist); - TAILQ_INSERT_TAIL(&vnode_free_list, tvp, v_freelist); - simple_unlock(&tvp->v_interlock); - } - if (vp) { vp->v_flag |= VDOOMED; - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); freevnodes--; simple_unlock(&vnode_free_list_slock); cache_purge(vp); @@ -1868,8 +1835,8 @@ vgonel(vp, p) /* * If it is on the freelist and not already at the head, - * move it to the head of the list. The test of the back - * pointer and the reference count of zero is because + * move it to the head of the list. The test of the + * VDOOMED flag and the reference count of zero is because * it will be removed from the free list by getnewvnode, * but will not have its reference count incremented until * after calling vgone. If the reference count were @@ -1879,13 +1846,9 @@ vgonel(vp, p) if (vp->v_usecount == 0 && !(vp->v_flag & VDOOMED)) { s = splbio(); simple_lock(&vnode_free_list_slock); - if (vp->v_flag & VFREE) { + if (vp->v_flag & VFREE) TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - } else if (vp->v_flag & VTBFREE) { - TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); - vp->v_flag &= ~VTBFREE; - freevnodes++; - } else + else freevnodes++; vp->v_flag |= VFREE; TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); @@ -2593,7 +2556,7 @@ retn: return error; } -static void +void vfree(vp) struct vnode *vp; { @@ -2601,10 +2564,7 @@ vfree(vp) s = splbio(); simple_lock(&vnode_free_list_slock); - if (vp->v_flag & VTBFREE) { - TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); - vp->v_flag &= ~VTBFREE; - } + KASSERT((vp->v_flag & VFREE) == 0, ("vnode already free")); if (vp->v_flag & VAGE) { TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); } else { @@ -2625,13 +2585,9 @@ vbusy(vp) s = splbio(); simple_lock(&vnode_free_list_slock); - if (vp->v_flag & VTBFREE) { - TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); - vp->v_flag &= ~VTBFREE; - } else { - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - freevnodes--; - } + KASSERT((vp->v_flag & VFREE) != 0, ("vnode not free")); + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + freevnodes--; simple_unlock(&vnode_free_list_slock); vp->v_flag &= ~(VFREE|VAGE); splx(s); diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index b2ab76c..5817855 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -164,7 +164,7 @@ struct vnode { #define VOWANT 0x20000 /* a process is waiting for VOLOCK */ #define VDOOMED 0x40000 /* This vnode is being recycled */ #define VFREE 0x80000 /* This vnode is on the freelist */ -#define VTBFREE 0x100000 /* This vnode is on the to-be-freelist */ +/* open for business 0x100000 */ #define VONWORKLST 0x200000 /* On syncer work-list */ #define VMOUNT 0x400000 /* Mount in progress */ @@ -298,7 +298,7 @@ extern void (*lease_updatetime) __P((int deltat)); !((vp)->v_object->ref_count || (vp)->v_object->resident_page_count))) #define VSHOULDBUSY(vp) \ - (((vp)->v_flag & (VFREE|VTBFREE)) && \ + (((vp)->v_flag & VFREE) && \ ((vp)->v_holdcnt || (vp)->v_usecount)) #endif /* _KERNEL */ @@ -613,6 +613,7 @@ int vop_defaultop __P((struct vop_generic_args *ap)); int vop_null __P((struct vop_generic_args *ap)); int vop_panic __P((struct vop_generic_args *ap)); +void vfree __P((struct vnode *)); void vput __P((struct vnode *vp)); void vrele __P((struct vnode *vp)); void vref __P((struct vnode *vp)); @@ -621,9 +622,6 @@ void vbusy __P((struct vnode *vp)); extern vop_t **default_vnodeop_p; extern vop_t **spec_vnodeop_p; -extern TAILQ_HEAD(tobefreelist, vnode) - vnode_tobefree_list; /* vnode free list */ - #endif /* _KERNEL */ #endif /* !_SYS_VNODE_H_ */ diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 9701150..038a5ad 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -1120,12 +1120,8 @@ vm_page_free_toq(vm_page_t m) ) { struct vnode *vp = (struct vnode *)object->handle; - if (vp && VSHOULDFREE(vp)) { - if ((vp->v_flag & (VTBFREE|VDOOMED|VFREE)) == 0) { - TAILQ_INSERT_TAIL(&vnode_tobefree_list, vp, v_freelist); - vp->v_flag |= VTBFREE; - } - } + if (vp && VSHOULDFREE(vp)) + vfree(vp); } /* |