summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2000-07-04 04:32:40 +0000
committermckusick <mckusick@FreeBSD.org>2000-07-04 04:32:40 +0000
commit2f0e9591fa0ef8bf1039608fd618c45ca89f9ec5 (patch)
tree58a79282436942422de8503a1b12b5b380619f8c
parent040e64cd9770955113ddffda73fff7b62dd5959b (diff)
downloadFreeBSD-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.c104
-rw-r--r--sys/kern/vfs_subr.c104
-rw-r--r--sys/sys/vnode.h8
-rw-r--r--sys/vm/vm_page.c8
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);
}
/*
OpenPOWER on IntegriCloud