summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_export.c
diff options
context:
space:
mode:
authordyson <dyson@FreeBSD.org>1997-12-29 00:25:11 +0000
committerdyson <dyson@FreeBSD.org>1997-12-29 00:25:11 +0000
commitcd67bb82fe37f70fed8e42c14c818de84029e3c0 (patch)
treea5d04c1ccd61a23a22dbd5ecd8264d7c3e866024 /sys/kern/vfs_export.c
parentf5f5008388092430288cb0018453755be5be7bdb (diff)
downloadFreeBSD-src-cd67bb82fe37f70fed8e42c14c818de84029e3c0.zip
FreeBSD-src-cd67bb82fe37f70fed8e42c14c818de84029e3c0.tar.gz
Lots of improvements, including restructring the caching and management
of vnodes and objects. There are some metadata performance improvements that come along with this. There are also a few prototypes added when the need is noticed. Changes include: 1) Cleaning up vref, vget. 2) Removal of the object cache. 3) Nuke vnode_pager_uncache and friends, because they aren't needed anymore. 4) Correct some missing LK_RETRY's in vn_lock. 5) Correct the page range in the code for msync. Be gentle, and please give me feedback asap.
Diffstat (limited to 'sys/kern/vfs_export.c')
-rw-r--r--sys/kern/vfs_export.c173
1 files changed, 73 insertions, 100 deletions
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index c2e5369..f39c17d 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
- * $Id: vfs_subr.c,v 1.115 1997/12/15 03:09:32 wollman Exp $
+ * $Id: vfs_subr.c,v 1.116 1997/12/19 09:03:28 dyson Exp $
*/
/*
@@ -57,6 +57,7 @@
#include <sys/poll.h>
#include <sys/domain.h>
#include <sys/dirent.h>
+#include <sys/vmmeter.h>
#include <machine/limits.h>
@@ -130,7 +131,7 @@ void
vntblinit()
{
- desiredvnodes = maxproc + vm_object_cache_max;
+ desiredvnodes = maxproc + cnt.v_page_count / 4;
simple_lock_init(&mntvnode_slock);
simple_lock_init(&mntid_slock);
simple_lock_init(&spechash_slock);
@@ -394,9 +395,9 @@ getnewvnode(tag, mp, vops, vpp)
simple_unlock(&vnode_free_list_slock);
cache_purge(vp);
vp->v_lease = NULL;
- if (vp->v_type != VBAD)
+ if (vp->v_type != VBAD) {
vgonel(vp, p);
- else {
+ } else {
simple_unlock(&vp->v_interlock);
}
@@ -588,8 +589,10 @@ bgetvp(vp, bp)
{
int s;
+#if defined(DIAGNOSTIC)
if (bp->b_vp)
panic("bgetvp: not free");
+#endif
vhold(vp);
bp->b_vp = vp;
if (vp->v_type == VBLK || vp->v_type == VCHR)
@@ -614,8 +617,11 @@ brelvp(bp)
struct vnode *vp;
int s;
+#if defined(DIAGNOSTIC)
if (bp->b_vp == (struct vnode *) 0)
panic("brelvp: NULL");
+#endif
+
/*
* Delete from old vnode list, if on one.
*/
@@ -846,19 +852,18 @@ vget(vp, flags, p)
tsleep((caddr_t)vp, PINOD, "vget", 0);
return (ENOENT);
}
+
vp->v_usecount++;
+
if (VSHOULDBUSY(vp))
vbusy(vp);
/*
* Create the VM object, if needed
*/
- if ((vp->v_type == VREG) &&
+ if (((vp->v_type == VREG) || (vp->v_type == VBLK)) &&
((vp->v_object == NULL) ||
(vp->v_object->flags & OBJ_VFS_REF) == 0 ||
(vp->v_object->flags & OBJ_DEAD))) {
- /*
- * XXX vfs_object_create probably needs the interlock.
- */
simple_unlock(&vp->v_interlock);
vfs_object_create(vp, curproc, curproc->p_ucred, 0);
simple_lock(&vp->v_interlock);
@@ -871,119 +876,88 @@ vget(vp, flags, p)
simple_unlock(&vp->v_interlock);
return (0);
}
-/* #ifdef DIAGNOSTIC */
+
/*
- * Vnode reference, just increment the count
+ * Vnode put/release.
+ * If count drops to zero, call inactive routine and return to freelist.
*/
void
-vref(vp)
+vrele(vp)
struct vnode *vp;
{
+ struct proc *p = curproc; /* XXX */
+
+#ifdef DIAGNOSTIC
+ if (vp == NULL)
+ panic("vrele: null vp");
+#endif
simple_lock(&vp->v_interlock);
- if (vp->v_usecount <= 0)
- panic("vref used where vget required");
- vp->v_usecount++;
+ if (vp->v_usecount > 1) {
- if ((vp->v_type == VREG) &&
- ((vp->v_object == NULL) ||
- ((vp->v_object->flags & OBJ_VFS_REF) == 0) ||
- (vp->v_object->flags & OBJ_DEAD))) {
- /*
- * We need to lock to VP during the time that
- * the object is created. This is necessary to
- * keep the system from re-entrantly doing it
- * multiple times.
- * XXX vfs_object_create probably needs the interlock?
- */
+ vp->v_usecount--;
simple_unlock(&vp->v_interlock);
- vfs_object_create(vp, curproc, curproc->p_ucred, 0);
- return;
+
+ } else if (vp->v_usecount == 1) {
+
+ vp->v_usecount--;
+
+ if (VSHOULDFREE(vp))
+ vfree(vp);
+ /*
+ * If we are doing a vput, the node is already locked, and we must
+ * call VOP_INACTIVE with the node locked. So, in the case of
+ * vrele, we explicitly lock the vnode before calling VOP_INACTIVE.
+ */
+ if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) == 0) {
+ VOP_INACTIVE(vp, p);
+ }
+
+ } else {
+#ifdef DIAGNOSTIC
+ vprint("vrele: negative ref count", vp);
+#endif
+ panic("vrele: negative ref cnt");
}
- simple_unlock(&vp->v_interlock);
}
-/*
- * Vnode put/release.
- * If count drops to zero, call inactive routine and return to freelist.
- */
-static void
-vputrele(vp, put)
+void
+vput(vp)
struct vnode *vp;
- int put;
{
struct proc *p = curproc; /* XXX */
#ifdef DIAGNOSTIC
if (vp == NULL)
- panic("vputrele: null vp");
+ panic("vput: null vp");
#endif
simple_lock(&vp->v_interlock);
- if ((vp->v_usecount == 2) &&
- vp->v_object &&
- (vp->v_object->flags & OBJ_VFS_REF)) {
+ if (vp->v_usecount > 1) {
- vm_freeze_copyopts(vp->v_object, 0, vp->v_object->size);
vp->v_usecount--;
- vp->v_object->flags &= ~OBJ_VFS_REF;
- if (put) {
- VOP_UNLOCK(vp, LK_INTERLOCK, p);
- } else {
- simple_unlock(&vp->v_interlock);
- }
- vm_object_deallocate(vp->v_object);
- return;
- }
+ VOP_UNLOCK(vp, LK_INTERLOCK, p);
- if (vp->v_usecount > 1) {
- vp->v_usecount--;
- if (put) {
- VOP_UNLOCK(vp, LK_INTERLOCK, p);
- } else {
- simple_unlock(&vp->v_interlock);
- }
- return;
- }
+ } else if (vp->v_usecount == 1) {
- if (vp->v_usecount < 1) {
-#ifdef DIAGNOSTIC
- vprint("vputrele: negative ref count", vp);
-#endif
- panic("vputrele: negative ref cnt");
- }
+ vp->v_usecount--;
- vp->v_usecount--;
- if (VSHOULDFREE(vp))
- vfree(vp);
+ if (VSHOULDFREE(vp))
+ vfree(vp);
/*
* If we are doing a vput, the node is already locked, and we must
* call VOP_INACTIVE with the node locked. So, in the case of
* vrele, we explicitly lock the vnode before calling VOP_INACTIVE.
*/
- if (put) {
simple_unlock(&vp->v_interlock);
VOP_INACTIVE(vp, p);
- } else if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) == 0) {
- VOP_INACTIVE(vp, p);
- }
-}
-/*
- * vput(), just unlock and vrele()
- */
-void
-vput(vp)
- struct vnode *vp;
-{
- vputrele(vp, 1);
-}
-
-void
-vrele(vp)
- struct vnode *vp;
-{
- vputrele(vp, 0);
+ } else {
+#ifdef DIAGNOSTIC
+ vprint("vput: negative ref count", vp);
+#endif
+ panic("vput: negative ref cnt");
+ }
}
/*
@@ -1152,15 +1126,6 @@ vclean(vp, flags, p)
VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, p);
object = vp->v_object;
- irefed = 0;
- if (object && ((object->flags & OBJ_DEAD) == 0)) {
- if (object->ref_count == 0) {
- vm_object_reference(object);
- irefed = 1;
- }
- ++object->ref_count;
- pager_cache(object, FALSE);
- }
/*
* Clean out any buffers associated with the vnode.
@@ -1168,7 +1133,8 @@ vclean(vp, flags, p)
if (flags & DOCLOSE)
vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0);
- if (irefed) {
+ if (vp->v_object && (vp->v_object->flags & OBJ_VFS_REF)) {
+ vp->v_object->flags &= ~OBJ_VFS_REF;
vm_object_deallocate(object);
}
@@ -1352,6 +1318,7 @@ vgonel(vp, p)
* Clean out the filesystem specific data.
*/
vclean(vp, DOCLOSE, p);
+
/*
* Delete from old mount point vnode list, if on one.
*/
@@ -2031,7 +1998,9 @@ loop:
continue;
if (vp->v_object &&
(vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
- vm_object_page_clean(vp->v_object, 0, 0, TRUE, TRUE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);
+ vm_object_page_clean(vp->v_object, 0, 0, TRUE);
+ VOP_UNLOCK(vp, 0, curproc);
}
}
}
@@ -2053,6 +2022,9 @@ vfs_object_create(vp, p, cred, waslocked)
vm_object_t object;
int error = 0;
+ if ((vp->v_type != VREG) && (vp->v_type != VBLK))
+ return 0;
+
retry:
if ((object = vp->v_object) == NULL) {
if (vp->v_type == VREG) {
@@ -2060,6 +2032,7 @@ retry:
goto retn;
(void) vnode_pager_alloc(vp,
OFF_TO_IDX(round_page(vat.va_size)), 0, 0);
+ vp->v_object->flags |= OBJ_VFS_REF;
} else {
/*
* This simply allocates the biggest object possible
@@ -2067,8 +2040,8 @@ retry:
* cause any problems (yet).
*/
(void) vnode_pager_alloc(vp, INT_MAX, 0, 0);
+ vp->v_object->flags |= OBJ_VFS_REF;
}
- vp->v_object->flags |= OBJ_VFS_REF;
} else {
if (object->flags & OBJ_DEAD) {
if (waslocked)
@@ -2079,8 +2052,8 @@ retry:
goto retry;
}
if ((object->flags & OBJ_VFS_REF) == 0) {
- object->flags |= OBJ_VFS_REF;
vm_object_reference(object);
+ object->flags |= OBJ_VFS_REF;
}
}
if (vp->v_object)
OpenPOWER on IntegriCloud