summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordyson <dyson@FreeBSD.org>1998-01-06 05:26:17 +0000
committerdyson <dyson@FreeBSD.org>1998-01-06 05:26:17 +0000
commitcb2800cd94015c1a5a07a78ac1299961c8cbfee8 (patch)
tree458fd90f400f25f9120e71fd368963d5190181bb
parent082257799eb016d17f2ea10684dc8c250c8dce19 (diff)
downloadFreeBSD-src-cb2800cd94015c1a5a07a78ac1299961c8cbfee8.zip
FreeBSD-src-cb2800cd94015c1a5a07a78ac1299961c8cbfee8.tar.gz
Make our v_usecount vnode reference count work identically to the
original BSD code. The association between the vnode and the vm_object no longer includes reference counts. The major difference is that vm_object's are no longer freed gratuitiously from the vnode, and so once an object is created for the vnode, it will last as long as the vnode does. When a vnode object reference count is incremented, then the underlying vnode reference count is incremented also. The two "objects" are now more intimately related, and so the interactions are now much less complex. When vnodes are now normally placed onto the free queue with an object still attached. The rundown of the object happens at vnode rundown time, and happens with exactly the same filesystem semantics of the original VFS code. There is absolutely no need for vnode_pager_uncache and other travesties like that anymore. A side-effect of these changes is that SMP locking should be much simpler, the I/O copyin/copyout optimizations work, NFS should be more ponderable, and further work on layered filesystems should be less frustrating, because of the totally coherent management of the vnode objects and vnodes. Please be careful with your system while running this code, but I would greatly appreciate feedback as soon a reasonably possible.
-rw-r--r--sys/conf/files.i3863
-rw-r--r--sys/fs/procfs/procfs_map.c4
-rw-r--r--sys/fs/procfs/procfs_vnops.c9
-rw-r--r--sys/fs/specfs/spec_vnops.c25
-rw-r--r--sys/i386/conf/files.i3863
-rw-r--r--sys/kern/imgact_aout.c7
-rw-r--r--sys/kern/kern_exec.c7
-rw-r--r--sys/kern/kern_subr.c67
-rw-r--r--sys/kern/vfs_bio.c84
-rw-r--r--sys/kern/vfs_cluster.c19
-rw-r--r--sys/kern/vfs_default.c21
-rw-r--r--sys/kern/vfs_export.c166
-rw-r--r--sys/kern/vfs_extattr.c33
-rw-r--r--sys/kern/vfs_lookup.c15
-rw-r--r--sys/kern/vfs_subr.c166
-rw-r--r--sys/kern/vfs_syscalls.c33
-rw-r--r--sys/kern/vfs_vnops.c4
-rw-r--r--sys/libkern/cmpdi2.c4
-rw-r--r--sys/miscfs/procfs/procfs_map.c4
-rw-r--r--sys/miscfs/procfs/procfs_vnops.c9
-rw-r--r--sys/miscfs/specfs/spec_vnops.c25
-rw-r--r--sys/nfs/nfs_bio.c6
-rw-r--r--sys/nfsclient/nfs_bio.c6
-rw-r--r--sys/sys/lock.h3
-rw-r--r--sys/sys/lockmgr.h3
-rw-r--r--sys/sys/namei.h3
-rw-r--r--sys/sys/uio.h3
-rw-r--r--sys/sys/vnode.h5
-rw-r--r--sys/ufs/ffs/ffs_balloc.c6
-rw-r--r--sys/ufs/ffs/ffs_inode.c9
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c43
-rw-r--r--sys/ufs/ffs/ffs_vnops.c39
-rw-r--r--sys/ufs/ufs/ufs_readwrite.c28
-rw-r--r--sys/vm/vm_fault.c21
-rw-r--r--sys/vm/vm_map.c114
-rw-r--r--sys/vm/vm_map.h4
-rw-r--r--sys/vm/vm_object.c246
-rw-r--r--sys/vm/vm_object.h13
-rw-r--r--sys/vm/vm_pageout.c6
-rw-r--r--sys/vm/vnode_pager.c31
40 files changed, 867 insertions, 430 deletions
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index ea285e9..e9e493f 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.181 1997/12/09 12:04:49 jamil Exp $
+# $Id: files.i386,v 1.182 1997/12/12 14:08:45 peter Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@@ -277,6 +277,7 @@ libkern/strncmp.c standard
libkern/strncpy.c standard
libkern/udivdi3.c standard
libkern/umoddi3.c standard
+libkern/cmpdi2.c standard
gnu/i386/fpemul/div_small.s optional gpl_math_emulate
gnu/i386/fpemul/errors.c optional gpl_math_emulate
gnu/i386/fpemul/fpu_arith.c optional gpl_math_emulate
diff --git a/sys/fs/procfs/procfs_map.c b/sys/fs/procfs/procfs_map.c
index 184cee9..7033e1c 100644
--- a/sys/fs/procfs/procfs_map.c
+++ b/sys/fs/procfs/procfs_map.c
@@ -36,7 +36,7 @@
*
* @(#)procfs_status.c 8.3 (Berkeley) 2/17/94
*
- * $Id: procfs_map.c,v 1.12 1997/08/02 14:32:12 bde Exp $
+ * $Id: procfs_map.c,v 1.13 1997/11/14 22:57:46 tegge Exp $
*/
#include <sys/param.h>
@@ -101,7 +101,7 @@ procfs_domap(curp, p, pfs, uio)
continue;
obj = entry->object.vm_object;
- if (obj && (obj->ref_count == 1))
+ if (obj && (obj->shadow_count == 1))
privateresident = obj->resident_page_count;
else
privateresident = 0;
diff --git a/sys/fs/procfs/procfs_vnops.c b/sys/fs/procfs/procfs_vnops.c
index b8bd8e9..00cca89 100644
--- a/sys/fs/procfs/procfs_vnops.c
+++ b/sys/fs/procfs/procfs_vnops.c
@@ -36,7 +36,7 @@
*
* @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
*
- * $Id: procfs_vnops.c,v 1.50 1997/12/27 02:56:25 bde Exp $
+ * $Id: procfs_vnops.c,v 1.51 1998/01/06 01:37:12 sef Exp $
*/
/*
@@ -186,7 +186,7 @@ procfs_close(ap)
* vnode. While one would expect v_usecount to be 1 at
* that point, it seems that (according to John Dyson)
* the VM system will bump up the usecount. So: if the
- * usecount is 2, and VVMIO is set, then this is really
+ * usecount is 2, and VOBJBUF is set, then this is really
* the last close. Otherwise, if the usecount is < 2
* then it is definitely the last close.
* If this is the last close, then it checks to see if
@@ -197,10 +197,7 @@ procfs_close(ap)
* told to stop on an event, but then the requesting process
* has gone away or forgotten about it.
*/
- if (((ap->a_vp->v_usecount == 2
- && ap->a_vp->v_object
- && (ap->a_vp->v_flag & VVMIO)) ||
- (ap->a_vp->v_usecount < 2))
+ if ((ap->a_vp->v_usecount < 2)
&& (p = pfind(pfs->pfs_pid))
&& !(p->p_pfsflags & PF_LINGER)) {
p->p_stops = 0;
diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c
index 6da09a6..3bad030 100644
--- a/sys/fs/specfs/spec_vnops.c
+++ b/sys/fs/specfs/spec_vnops.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95
- * $Id: spec_vnops.c,v 1.51 1997/10/27 13:33:42 bde Exp $
+ * $Id: spec_vnops.c,v 1.52 1997/12/29 00:23:16 dyson Exp $
*/
#include <sys/param.h>
@@ -232,6 +232,7 @@ spec_open(ap)
(ap->a_mode & FWRITE) &&
(bdevsw[maj]->d_flags & D_TYPEMASK) == D_DISK)
return (EPERM);
+
/*
* Do not allow opens of block devices that are
* currently mounted.
@@ -392,10 +393,14 @@ spec_write(ap)
brelse(bp);
return (error);
}
+ if (vp->v_flag & VOBJBUF)
+ bp->b_flags |= B_CLUSTEROK;
error = uiomove((char *)bp->b_data + on, n, uio);
if (n + on == bsize) {
- /* bawrite(bp); */
- cluster_write(bp, 0);
+ if ((vp->v_flag & VOBJBUF) && (on == 0))
+ vfs_bio_awrite(bp);
+ else
+ bawrite(bp);
} else
bdwrite(bp);
} while (error == 0 && uio->uio_resid > 0 && n != 0);
@@ -499,10 +504,15 @@ loop:
continue;
if ((bp->b_flags & B_DELWRI) == 0)
panic("spec_fsync: not dirty");
- bremfree(bp);
- bp->b_flags |= B_BUSY;
- splx(s);
- bawrite(bp);
+ if ((vp->v_flag & VOBJBUF) && (bp->b_flags & B_CLUSTEROK)) {
+ vfs_bio_awrite(bp);
+ splx(s);
+ } else {
+ bremfree(bp);
+ bp->b_flags |= B_BUSY;
+ splx(s);
+ bawrite(bp);
+ }
goto loop;
}
if (ap->a_waitfor == MNT_WAIT) {
@@ -631,6 +641,7 @@ spec_close(ap)
error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0);
if (error)
return (error);
+
/*
* We do not want to really close the device if it
* is still in use unless we are trying to close it
diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386
index ea285e9..e9e493f 100644
--- a/sys/i386/conf/files.i386
+++ b/sys/i386/conf/files.i386
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.181 1997/12/09 12:04:49 jamil Exp $
+# $Id: files.i386,v 1.182 1997/12/12 14:08:45 peter Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@@ -277,6 +277,7 @@ libkern/strncmp.c standard
libkern/strncpy.c standard
libkern/udivdi3.c standard
libkern/umoddi3.c standard
+libkern/cmpdi2.c standard
gnu/i386/fpemul/div_small.s optional gpl_math_emulate
gnu/i386/fpemul/errors.c optional gpl_math_emulate
gnu/i386/fpemul/fpu_arith.c optional gpl_math_emulate
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c
index 7bc26e1..48cf2e3 100644
--- a/sys/kern/imgact_aout.c
+++ b/sys/kern/imgact_aout.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: imgact_aout.c,v 1.35 1997/08/26 00:02:23 bde Exp $
+ * $Id: imgact_aout.c,v 1.36 1997/09/02 20:05:33 bde Exp $
*/
#include <sys/param.h>
@@ -47,7 +47,7 @@
static int exec_aout_imgact __P((struct image_params *imgp));
-static int
+int
exec_aout_imgact(imgp)
struct image_params *imgp;
{
@@ -177,7 +177,8 @@ exec_aout_imgact(imgp)
* instruction of the same name.
*/
vmaddr = virtual_offset + a_out->a_text + a_out->a_data;
- error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
+ error = vm_map_find(&vmspace->vm_map, NULL, 0,
+ &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
if (error)
return (error);
}
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 5667868..eb40b91 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: kern_exec.c,v 1.71 1997/12/20 03:05:45 sef Exp $
+ * $Id: kern_exec.c,v 1.72 1997/12/27 02:56:21 bde Exp $
*/
#include <sys/param.h>
@@ -185,7 +185,8 @@ interpret:
* header into it.
*/
imgp->image_header = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
- error = vn_rdwr(UIO_READ, imgp->vp, (void *)imgp->image_header, PAGE_SIZE, 0,
+ error = vn_rdwr(UIO_READ, imgp->vp,
+ (void *)imgp->image_header, PAGE_SIZE, 0,
UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
/*
* Clear out any remaining junk.
@@ -316,7 +317,7 @@ interpret:
p->p_ucred->cr_gid = attr.va_gid;
setsugid(p);
} else {
- if (p->p_ucred->cr_uid == p->p_cred->p_ruid &&
+ if (p->p_ucred->cr_uid == p->p_cred->p_ruid &&
p->p_ucred->cr_gid == p->p_cred->p_rgid)
p->p_flag &= ~P_SUGID;
}
diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c
index cae8521..169711d 100644
--- a/sys/kern/kern_subr.c
+++ b/sys/kern/kern_subr.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
- * $Id: kern_subr.c,v 1.13 1997/10/10 18:14:23 phk Exp $
+ * $Id: kern_subr.c,v 1.14 1997/12/19 09:03:23 dyson Exp $
*/
#include <sys/param.h>
@@ -147,7 +147,7 @@ uiomoveco(cp, n, uio, obj)
((((int) cp) & PAGE_MASK) == 0)) {
error = vm_uiomove(&curproc->p_vmspace->vm_map, obj,
uio->uio_offset, cnt,
- (vm_offset_t) iov->iov_base);
+ (vm_offset_t) iov->iov_base, NULL);
} else {
error = copyout(cp, iov->iov_base, cnt);
}
@@ -177,6 +177,69 @@ uiomoveco(cp, n, uio, obj)
return (0);
}
+int
+uioread(n, uio, obj, nread)
+ int n;
+ struct uio *uio;
+ struct vm_object *obj;
+ int *nread;
+{
+ int npagesmoved;
+ struct iovec *iov;
+ u_int cnt, tcnt;
+ int error;
+
+ *nread = 0;
+ error = 0;
+
+ while (n > 0 && uio->uio_resid) {
+ iov = uio->uio_iov;
+ cnt = iov->iov_len;
+ if (cnt == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ continue;
+ }
+ if (cnt > n)
+ cnt = n;
+
+ if ((uio->uio_segflg == UIO_USERSPACE) &&
+ ((((int) iov->iov_base) & PAGE_MASK) == 0) &&
+ ((uio->uio_offset & PAGE_MASK) == 0) ) {
+
+ if (cnt < PAGE_SIZE)
+ break;
+
+ cnt &= ~PAGE_MASK;
+
+ error = vm_uiomove(&curproc->p_vmspace->vm_map, obj,
+ uio->uio_offset, cnt,
+ (vm_offset_t) iov->iov_base, &npagesmoved);
+
+ if (npagesmoved == 0)
+ break;
+
+ tcnt = npagesmoved * PAGE_SIZE;
+ if (tcnt != cnt) {
+ cnt = tcnt;
+ }
+
+ if (error)
+ break;
+
+ iov->iov_base += cnt;
+ iov->iov_len -= cnt;
+ uio->uio_resid -= cnt;
+ uio->uio_offset += cnt;
+ *nread += cnt;
+ n -= cnt;
+ } else {
+ break;
+ }
+ }
+ return error;
+}
+
/*
* Give next character to user as result of read.
*/
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index f5c966f..98cf7aa 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -11,7 +11,7 @@
* 2. Absolutely no warranty of function or purpose is made by the author
* John S. Dyson.
*
- * $Id: vfs_bio.c,v 1.139 1997/12/07 04:06:41 dyson Exp $
+ * $Id: vfs_bio.c,v 1.140 1997/12/22 11:54:00 dyson Exp $
*/
/*
@@ -204,8 +204,8 @@ bufinit()
* Remove the probability of deadlock conditions by limiting the
* number of dirty buffers.
*/
- hidirtybuffers = nbuf / 6 + 20;
- lodirtybuffers = nbuf / 12 + 10;
+ hidirtybuffers = nbuf / 8 + 20;
+ lodirtybuffers = nbuf / 16 + 10;
numdirtybuffers = 0;
lofreebuffers = nbuf / 18 + 5;
hifreebuffers = 2 * lofreebuffers;
@@ -396,7 +396,7 @@ bwrite(struct buf * bp)
return (0);
}
-void
+inline void
vfs_bio_need_satisfy(void) {
++numfreebuffers;
if (!needsbuffer)
@@ -850,6 +850,8 @@ vfs_bio_awrite(struct buf * bp)
int ncl;
struct buf *bpa;
int nwritten;
+ int size;
+ int maxcl;
s = splbio();
/*
@@ -858,8 +860,6 @@ vfs_bio_awrite(struct buf * bp)
if ((vp->v_type == VREG) &&
(vp->v_mount != 0) && /* Only on nodes that have the size info */
(bp->b_flags & (B_CLUSTEROK | B_INVAL)) == B_CLUSTEROK) {
- int size;
- int maxcl;
size = vp->v_mount->mnt_stat.f_iosize;
maxcl = MAXPHYS / size;
@@ -885,7 +885,33 @@ vfs_bio_awrite(struct buf * bp)
splx(s);
return nwritten;
}
+ } else if ((vp->v_flag & VOBJBUF) && (vp->v_type == VBLK) &&
+ ((size = bp->b_bufsize) >= PAGE_SIZE)) {
+ maxcl = MAXPHYS / size;
+ for (i = 1; i < maxcl; i++) {
+ if ((bpa = gbincore(vp, lblkno + i)) &&
+ ((bpa->b_flags & (B_BUSY | B_DELWRI | B_CLUSTEROK | B_INVAL)) ==
+ (B_DELWRI | B_CLUSTEROK)) &&
+ (bpa->b_bufsize == size)) {
+ if (bpa->b_blkno !=
+ bp->b_blkno + ((i * size) >> DEV_BSHIFT))
+ break;
+ } else {
+ break;
+ }
+ }
+ ncl = i;
+ /*
+ * this is a possible cluster write
+ */
+ if (ncl != 1) {
+ nwritten = cluster_wbuild(vp, size, lblkno, ncl);
+ printf("Block cluster: (%d, %d)\n", lblkno, nwritten);
+ splx(s);
+ return nwritten;
+ }
}
+
bremfree(bp);
splx(s);
/*
@@ -902,7 +928,8 @@ vfs_bio_awrite(struct buf * bp)
* Find a buffer header which is available for use.
*/
static struct buf *
-getnewbuf(struct vnode *vp, int slpflag, int slptimeo, int size, int maxsize)
+getnewbuf(struct vnode *vp, daddr_t blkno,
+ int slpflag, int slptimeo, int size, int maxsize)
{
struct buf *bp, *bp1;
int nbyteswritten = 0;
@@ -981,6 +1008,33 @@ trytofreespace:
/* if we are a delayed write, convert to an async write */
if ((bp->b_flags & (B_DELWRI | B_INVAL)) == B_DELWRI) {
+ /*
+ * If our delayed write is likely to be used soon, then
+ * recycle back onto the LRU queue.
+ */
+ if (vp && (bp->b_vp == vp) && (bp->b_qindex == QUEUE_LRU) &&
+ (bp->b_lblkno >= blkno) && (maxsize > 0)) {
+
+ if (bp->b_usecount > 0) {
+ if (bp->b_lblkno < blkno + (MAXPHYS / maxsize)) {
+
+ TAILQ_REMOVE(&bufqueues[QUEUE_LRU], bp, b_freelist);
+
+ if (TAILQ_FIRST(&bufqueues[QUEUE_LRU]) != NULL) {
+ TAILQ_INSERT_TAIL(&bufqueues[QUEUE_LRU], bp, b_freelist);
+ bp->b_usecount--;
+ goto start;
+ }
+ TAILQ_INSERT_TAIL(&bufqueues[QUEUE_LRU], bp, b_freelist);
+ }
+ }
+ }
+
+ /*
+ * Certain layered filesystems can recursively re-enter the vfs_bio
+ * code, due to delayed writes. This helps keep the system from
+ * deadlocking.
+ */
if (writerecursion > 0) {
bp = TAILQ_FIRST(&bufqueues[QUEUE_AGE]);
while (bp) {
@@ -1201,7 +1255,7 @@ inmem(struct vnode * vp, daddr_t blkno)
return 1;
if (vp->v_mount == NULL)
return 0;
- if ((vp->v_object == NULL) || (vp->v_flag & VVMIO) == 0)
+ if ((vp->v_object == NULL) || (vp->v_flag & VOBJBUF) == 0)
return 0;
obj = vp->v_object;
@@ -1351,7 +1405,8 @@ loop:
} else {
vm_object_t obj;
- if ((bp = getnewbuf(vp, slpflag, slptimeo, size, maxsize)) == 0) {
+ if ((bp = getnewbuf(vp, blkno,
+ slpflag, slptimeo, size, maxsize)) == 0) {
if (slpflag || slptimeo) {
splx(s);
return NULL;
@@ -1381,7 +1436,7 @@ loop:
bh = BUFHASH(vp, blkno);
LIST_INSERT_HEAD(bh, bp, b_hash);
- if ((obj = vp->v_object) && (vp->v_flag & VVMIO)) {
+ if ((obj = vp->v_object) && (vp->v_flag & VOBJBUF)) {
bp->b_flags |= (B_VMIO | B_CACHE);
#if defined(VFS_BIO_DEBUG)
if (vp->v_type != VREG && vp->v_type != VBLK)
@@ -1414,7 +1469,7 @@ geteblk(int size)
int s;
s = splbio();
- while ((bp = getnewbuf(0, 0, 0, size, MAXBSIZE)) == 0);
+ while ((bp = getnewbuf(0, (daddr_t) 0, 0, 0, size, MAXBSIZE)) == 0);
splx(s);
allocbuf(bp, size);
bp->b_flags |= B_INVAL;
@@ -1696,7 +1751,10 @@ biowait(register struct buf * bp)
#if defined(NO_SCHEDULE_MODS)
tsleep(bp, PRIBIO, "biowait", 0);
#else
- tsleep(bp, curproc->p_usrpri, "biowait", 0);
+ if (bp->b_flags & B_READ)
+ tsleep(bp, PRIBIO, "biord", 0);
+ else
+ tsleep(bp, curproc->p_usrpri, "biowr", 0);
#endif
splx(s);
if (bp->b_flags & B_EINTR) {
@@ -1770,7 +1828,7 @@ biodone(register struct buf * bp)
panic("biodone: missing VM object");
}
- if ((vp->v_flag & VVMIO) == 0) {
+ if ((vp->v_flag & VOBJBUF) == 0) {
panic("biodone: vnode is not setup for merged cache");
}
#endif
diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c
index 1fff926..3d82c5e 100644
--- a/sys/kern/vfs_cluster.c
+++ b/sys/kern/vfs_cluster.c
@@ -33,7 +33,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_cluster.c 8.7 (Berkeley) 2/13/94
- * $Id: vfs_cluster.c,v 1.48 1997/08/02 14:31:43 bde Exp $
+ * $Id: vfs_cluster.c,v 1.49 1997/11/07 08:53:05 phk Exp $
*/
#include <sys/param.h>
@@ -492,8 +492,13 @@ cluster_write(bp, filesize)
int async;
vp = bp->b_vp;
- async = vp->v_mount->mnt_flag & MNT_ASYNC;
- lblocksize = vp->v_mount->mnt_stat.f_iosize;
+ if (vp->v_type == VREG) {
+ async = vp->v_mount->mnt_flag & MNT_ASYNC;
+ lblocksize = vp->v_mount->mnt_stat.f_iosize;
+ } else {
+ async = 0;
+ lblocksize = bp->b_bufsize;
+ }
lbn = bp->b_lblkno;
/* Initialize vnode to beginning of file. */
@@ -565,7 +570,8 @@ cluster_write(bp, filesize)
* cluster as large as possible, otherwise find size of
* existing cluster.
*/
- if (((u_quad_t) (lbn + 1) * lblocksize) != filesize &&
+ if ((vp->v_type == VREG) &&
+ ((u_quad_t) (lbn + 1) * lblocksize) != filesize &&
(bp->b_blkno == bp->b_lblkno) &&
(VOP_BMAP(vp, lbn, NULL, &bp->b_blkno, &maxclen, NULL) ||
bp->b_blkno == -1)) {
@@ -621,7 +627,7 @@ cluster_wbuild(vp, size, start_lbn, len)
int dbsize = btodb(size);
while (len > 0) {
s = splbio();
- if ( ((tbp = gbincore(vp, start_lbn)) == NULL) ||
+ if (((tbp = gbincore(vp, start_lbn)) == NULL) ||
((tbp->b_flags & (B_INVAL|B_BUSY|B_DELWRI)) != B_DELWRI)) {
++start_lbn;
--len;
@@ -672,7 +678,8 @@ cluster_wbuild(vp, size, start_lbn, len)
bp->b_blkno = tbp->b_blkno;
bp->b_lblkno = tbp->b_lblkno;
(vm_offset_t) bp->b_data |= ((vm_offset_t) tbp->b_data) & PAGE_MASK;
- bp->b_flags |= B_CALL | B_BUSY | B_CLUSTER | (tbp->b_flags & (B_VMIO|B_NEEDCOMMIT));
+ bp->b_flags |= B_CALL | B_BUSY | B_CLUSTER |
+ (tbp->b_flags & (B_VMIO|B_NEEDCOMMIT));
bp->b_iodone = cluster_callback;
pbgetvp(vp, bp);
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index a681825..e2be193 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -189,7 +189,13 @@ vop_stdlock(ap)
struct proc *a_p;
} */ *ap;
{
- struct lock *l = (struct lock*)ap->a_vp->v_data;
+ struct lock *l;
+
+ if ((l = (struct lock *)ap->a_vp->v_data) == NULL) {
+ if (ap->a_flags & LK_INTERLOCK)
+ simple_unlock(&ap->a_vp->v_interlock);
+ return 0;
+ }
return (lockmgr(l, ap->a_flags, &ap->a_vp->v_interlock, ap->a_p));
}
@@ -202,7 +208,13 @@ vop_stdunlock(ap)
struct proc *a_p;
} */ *ap;
{
- struct lock *l = (struct lock*)ap->a_vp->v_data;
+ struct lock *l;
+
+ if ((l = (struct lock *)ap->a_vp->v_data) == NULL) {
+ if (ap->a_flags & LK_INTERLOCK)
+ simple_unlock(&ap->a_vp->v_interlock);
+ return 0;
+ }
return (lockmgr(l, ap->a_flags | LK_RELEASE, &ap->a_vp->v_interlock,
ap->a_p));
@@ -214,7 +226,10 @@ vop_stdislocked(ap)
struct vnode *a_vp;
} */ *ap;
{
- struct lock *l = (struct lock*)ap->a_vp->v_data;
+ struct lock *l;
+
+ if ((l = (struct lock *)ap->a_vp->v_data) == NULL)
+ return 0;
return (lockstatus(l));
}
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index 9a371b8..7120a81 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.118 1997/12/29 01:03:41 dyson Exp $
+ * $Id: vfs_subr.c,v 1.119 1997/12/29 16:54:03 dyson Exp $
*/
/*
@@ -83,7 +83,6 @@ static void vfree __P((struct vnode *));
static void vgonel __P((struct vnode *vp, struct proc *p));
static unsigned long numvnodes;
SYSCTL_INT(_debug, OID_AUTO, numvnodes, CTLFLAG_RD, &numvnodes, 0, "");
-static void vputrele __P((struct vnode *vp, int put));
enum vtype iftovt_tab[16] = {
VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
@@ -108,7 +107,7 @@ SYSCTL_INT(_debug, OID_AUTO, wantfreevnodes, CTLFLAG_RW, &wantfreevnodes, 0, "")
static u_long freevnodes = 0;
SYSCTL_INT(_debug, OID_AUTO, freevnodes, CTLFLAG_RD, &freevnodes, 0, "");
-int vfs_ioopt = 0;
+int vfs_ioopt = 1;
SYSCTL_INT(_vfs, OID_AUTO, ioopt, CTLFLAG_RW, &vfs_ioopt, 0, "");
struct mntlist mountlist; /* mounted filesystem list */
@@ -352,7 +351,9 @@ getnewvnode(tag, mp, vops, vpp)
struct vnode **vpp;
{
struct proc *p = curproc; /* XXX */
- struct vnode *vp;
+ struct vnode *vp, *tvp;
+ vm_object_t object;
+ TAILQ_HEAD(freelst, vnode) vnode_tmp_list;
/*
* We take the least recently used vnode from the freelist
@@ -362,6 +363,7 @@ getnewvnode(tag, mp, vops, vpp)
*/
simple_lock(&vnode_free_list_slock);
+ TAILQ_INIT(&vnode_tmp_list);
if (wantfreevnodes && freevnodes < wantfreevnodes) {
vp = NULL;
@@ -377,9 +379,11 @@ getnewvnode(tag, mp, vops, vpp)
if (vp->v_usecount)
panic("free vnode isn't");
- if (vp->v_object && vp->v_object->resident_page_count) {
+ object = vp->v_object;
+ if (object && (object->resident_page_count || object->ref_count)) {
/* Don't recycle if it's caching some pages */
- simple_unlock(&vp->v_interlock);
+ 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 */
@@ -391,6 +395,12 @@ getnewvnode(tag, mp, vops, vpp)
}
}
+ TAILQ_FOREACH(tvp, &vnode_tmp_list, 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);
@@ -429,6 +439,7 @@ getnewvnode(tag, mp, vops, vpp)
vp = (struct vnode *) malloc((u_long) sizeof *vp,
M_VNODE, M_WAITOK);
bzero((char *) vp, sizeof *vp);
+ simple_lock_init(&vp->v_interlock);
vp->v_dd = vp;
cache_purge(vp);
LIST_INIT(&vp->v_cache_src);
@@ -553,7 +564,16 @@ vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)
* check for it.
*/
if ((bp->b_flags & B_DELWRI) && (flags & V_SAVE)) {
- (void) VOP_BWRITE(bp);
+ if (bp->b_vp == vp) {
+ if (bp->b_flags & B_CLUSTEROK) {
+ vfs_bio_awrite(bp);
+ } else {
+ bp->b_flags |= B_ASYNC;
+ VOP_BWRITE(bp);
+ }
+ } else {
+ (void) VOP_BWRITE(bp);
+ }
break;
}
bp->b_flags |= (B_INVAL|B_NOCACHE|B_RELBUF);
@@ -571,11 +591,18 @@ vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)
/*
* Destroy the copy in the VM cache, too.
*/
+ simple_lock(&vp->v_interlock);
object = vp->v_object;
if (object != NULL) {
- vm_object_page_remove(object, 0, object->size,
- (flags & V_SAVE) ? TRUE : FALSE);
+ if (flags & V_SAVEMETA)
+ vm_object_page_remove(object, 0, object->size,
+ (flags & V_SAVE) ? TRUE : FALSE);
+ else
+ vm_object_page_remove(object, 0, 0,
+ (flags & V_SAVE) ? TRUE : FALSE);
}
+ simple_unlock(&vp->v_interlock);
+
if (!(flags & V_SAVEMETA) &&
(vp->v_dirtyblkhd.lh_first || vp->v_cleanblkhd.lh_first))
panic("vinvalbuf: flush failed");
@@ -863,13 +890,11 @@ vget(vp, flags, p)
/*
* Create the VM object, if needed
*/
- if (((vp->v_type == VREG) || (vp->v_type == VBLK)) &&
- ((vp->v_object == NULL) ||
- (vp->v_object->flags & OBJ_VFS_REF) == 0 ||
+ if ((flags & LK_NOOBJ) == 0 &&
+ (vp->v_type == VREG) &&
+ ((vp->v_object == NULL) ||
(vp->v_object->flags & OBJ_DEAD))) {
- simple_unlock(&vp->v_interlock);
vfs_object_create(vp, curproc, curproc->p_ucred, 0);
- simple_lock(&vp->v_interlock);
}
if (flags & LK_TYPE_MASK) {
if (error = vn_lock(vp, flags | LK_INTERLOCK, p))
@@ -909,7 +934,10 @@ vrele(vp)
vp->v_usecount--;
simple_unlock(&vp->v_interlock);
- } else if (vp->v_usecount == 1) {
+ return;
+ }
+
+ if (vp->v_usecount == 1) {
vp->v_usecount--;
@@ -927,6 +955,7 @@ vrele(vp)
} else {
#ifdef DIAGNOSTIC
vprint("vrele: negative ref count", vp);
+ simple_unlock(&vp->v_interlock);
#endif
panic("vrele: negative ref cnt");
}
@@ -942,17 +971,20 @@ vput(vp)
if (vp == NULL)
panic("vput: null vp");
#endif
+
simple_lock(&vp->v_interlock);
if (vp->v_usecount > 1) {
vp->v_usecount--;
VOP_UNLOCK(vp, LK_INTERLOCK, p);
+ return;
+
+ }
- } else if (vp->v_usecount == 1) {
+ if (vp->v_usecount == 1) {
vp->v_usecount--;
-
if (VSHOULDFREE(vp))
vfree(vp);
/*
@@ -1110,8 +1142,7 @@ vclean(vp, flags, p)
int flags;
struct proc *p;
{
- int active, irefed;
- vm_object_t object;
+ int active;
/*
* Check to see if the vnode is in use. If so we have to reference it
@@ -1120,6 +1151,10 @@ vclean(vp, flags, p)
*/
if ((active = vp->v_usecount))
vp->v_usecount++;
+
+ if (vp->v_object) {
+ vp->v_object->flags |= OBJ_DEAD;
+ }
/*
* Prevent the vnode from being recycled or brought into use while we
* clean it out.
@@ -1136,19 +1171,14 @@ vclean(vp, flags, p)
*/
VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, p);
- object = vp->v_object;
-
/*
* Clean out any buffers associated with the vnode.
*/
- if (flags & DOCLOSE)
+ if (vp->v_object)
+ vm_object_terminate(vp->v_object);
+ else
vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0);
- if (vp->v_object && (vp->v_object->flags & OBJ_VFS_REF)) {
- vp->v_object->flags &= ~OBJ_VFS_REF;
- vm_object_deallocate(object);
- }
-
/*
* If purging an active vnode, it must be closed and
* deactivated before being reclaimed. Note that the
@@ -1257,6 +1287,10 @@ vop_revoke(ap)
*/
simple_lock(&vp->v_interlock);
vp->v_flag &= ~VXLOCK;
+ if (vp->v_flag & VXWANT) {
+ vp->v_flag &= ~VXWANT;
+ wakeup(vp);
+ }
}
vgonel(vp, p);
return (0);
@@ -1321,10 +1355,6 @@ vgonel(vp, p)
return;
}
- if (vp->v_object) {
- vp->v_object->flags |= OBJ_VNODE_GONE;
- }
-
/*
* Clean out the filesystem specific data.
*/
@@ -1392,6 +1422,7 @@ vgonel(vp, p)
}
vp->v_type = VBAD;
+ simple_unlock(&vp->v_interlock);
}
/*
@@ -1488,6 +1519,8 @@ vprint(label, vp)
strcat(buf, "|VDOOMED");
if (vp->v_flag & VFREE)
strcat(buf, "|VFREE");
+ if (vp->v_flag & VOBJBUF)
+ strcat(buf, "|VOBJBUF");
if (buf[0] != '\0')
printf(" flags (%s)", &buf[1]);
if (vp->v_data == NULL) {
@@ -1999,21 +2032,41 @@ vfs_export_lookup(mp, nep, nam)
void
vfs_msync(struct mount *mp, int flags) {
struct vnode *vp, *nvp;
+ int anyio, tries;
+
+ tries = 5;
loop:
+ anyio = 0;
for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
- if (vp->v_mount != mp)
- goto loop;
nvp = vp->v_mntvnodes.le_next;
- if (VOP_ISLOCKED(vp) && (flags != MNT_WAIT))
+
+ if (vp->v_mount != mp) {
+ goto loop;
+ }
+
+ if ((vp->v_flag & VXLOCK) ||
+ (VOP_ISLOCKED(vp) && (flags != MNT_WAIT))) {
continue;
+ }
+
+ simple_lock(&vp->v_interlock);
if (vp->v_object &&
(vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);
- vm_object_page_clean(vp->v_object, 0, 0, TRUE);
- VOP_UNLOCK(vp, 0, curproc);
+ if (!vget(vp,
+ LK_INTERLOCK | LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ, curproc)) {
+ if (vp->v_object) {
+ vm_object_page_clean(vp->v_object, 0, 0, TRUE);
+ anyio = 1;
+ }
+ vput(vp);
+ }
+ } else {
+ simple_unlock(&vp->v_interlock);
}
}
+ if (anyio && (--tries > 0))
+ goto loop;
}
/*
@@ -2021,6 +2074,8 @@ loop:
* is done for all VREG files in the system. Some filesystems might
* afford the additional metadata buffering capability of the
* VMIO code by making the device node be VMIO mode also.
+ *
+ * If !waslocked, must be called with interlock.
*/
int
vfs_object_create(vp, p, cred, waslocked)
@@ -2033,44 +2088,49 @@ vfs_object_create(vp, p, cred, waslocked)
vm_object_t object;
int error = 0;
- if ((vp->v_type != VREG) && (vp->v_type != VBLK))
+ if ((vp->v_type != VREG) && (vp->v_type != VBLK)) {
return 0;
+ }
+
+ if (!waslocked)
+ vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY, p);
retry:
if ((object = vp->v_object) == NULL) {
if (vp->v_type == VREG) {
if ((error = VOP_GETATTR(vp, &vat, cred, p)) != 0)
goto retn;
- (void) vnode_pager_alloc(vp,
+ object = vnode_pager_alloc(vp,
OFF_TO_IDX(round_page(vat.va_size)), 0, 0);
- vp->v_object->flags |= OBJ_VFS_REF;
- } else {
+ } else if (major(vp->v_rdev) < nblkdev) {
/*
* This simply allocates the biggest object possible
* for a VBLK vnode. This should be fixed, but doesn't
* cause any problems (yet).
*/
- (void) vnode_pager_alloc(vp, INT_MAX, 0, 0);
- vp->v_object->flags |= OBJ_VFS_REF;
+ object = vnode_pager_alloc(vp, INT_MAX, 0, 0);
}
+ object->ref_count--;
+ vp->v_usecount--;
} else {
if (object->flags & OBJ_DEAD) {
- if (waslocked)
- VOP_UNLOCK(vp, 0, p);
+ VOP_UNLOCK(vp, 0, p);
tsleep(object, PVM, "vodead", 0);
- if (waslocked)
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
goto retry;
}
- if ((object->flags & OBJ_VFS_REF) == 0) {
- vm_object_reference(object);
- object->flags |= OBJ_VFS_REF;
- }
}
- if (vp->v_object)
- vp->v_flag |= VVMIO;
+
+ if (vp->v_object) {
+ vp->v_flag |= VOBJBUF;
+ }
retn:
+ if (!waslocked) {
+ simple_lock(&vp->v_interlock);
+ VOP_UNLOCK(vp, LK_INTERLOCK, p);
+ }
+
return error;
}
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 69751c4..b7be81e 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
- * $Id: vfs_syscalls.c,v 1.87 1997/12/27 02:56:23 bde Exp $
+ * $Id: vfs_syscalls.c,v 1.88 1997/12/29 00:22:50 dyson Exp $
*/
/* For 4.3 integer FS ID compatibility */
@@ -428,8 +428,8 @@ dounmount(mp, flags, p)
if (mp->mnt_flag & MNT_EXPUBLIC)
vfs_setpublicfs(NULL, NULL, NULL);
+ vfs_msync(mp, MNT_WAIT);
mp->mnt_flag &=~ MNT_ASYNC;
- vfs_msync(mp, MNT_NOWAIT);
cache_purgevfs(mp); /* remove cache entries for this file sys */
if (((mp->mnt_flag & MNT_RDONLY) ||
(error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
@@ -919,6 +919,8 @@ open(p, uap)
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
fp->f_flag |= FHASLOCK;
}
+ if ((vp->v_type == VREG) && (vp->v_object == NULL))
+ vfs_object_create(vp, p, p->p_ucred, TRUE);
VOP_UNLOCK(vp, 0, p);
p->p_retval[0] = indx;
return (0);
@@ -1102,14 +1104,14 @@ link(p, uap)
struct nameidata nd;
int error;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), p);
if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp->v_type == VDIR)
error = EPERM; /* POSIX */
else {
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
+ NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
error = namei(&nd);
if (!error) {
if (nd.ni_vp != NULL) {
@@ -1161,7 +1163,7 @@ symlink(p, uap)
path = zalloc(namei_zone);
if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL))
goto out;
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
+ NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
if (error = namei(&nd))
goto out;
if (nd.ni_vp) {
@@ -1266,7 +1268,7 @@ unlink(p, uap)
if (!error) {
VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
- error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
+ error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
} else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == vp)
@@ -1395,7 +1397,7 @@ access(p, uap)
t_gid = cred->cr_groups[0];
cred->cr_uid = p->p_cred->p_ruid;
cred->cr_groups[0] = p->p_cred->p_rgid;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
SCARG(uap, path), p);
if (error = namei(&nd))
goto out1;
@@ -1444,7 +1446,7 @@ ostat(p, uap)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
SCARG(uap, path), p);
if (error = namei(&nd))
return (error);
@@ -1481,7 +1483,7 @@ olstat(p, uap)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
SCARG(uap, path), p);
if (error = namei(&nd))
return (error);
@@ -1549,7 +1551,7 @@ stat(p, uap)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
SCARG(uap, path), p);
if (error = namei(&nd))
return (error);
@@ -1584,7 +1586,7 @@ lstat(p, uap)
struct stat sb;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
SCARG(uap, path), p);
if (error = namei(&nd))
return (error);
@@ -1620,7 +1622,7 @@ pathconf(p, uap)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
SCARG(uap, path), p);
if (error = namei(&nd))
return (error);
@@ -1655,7 +1657,7 @@ readlink(p, uap)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
SCARG(uap, path), p);
if (error = namei(&nd))
return (error);
@@ -2196,7 +2198,7 @@ rename(p, uap)
if (error = namei(&fromnd))
return (error);
fvp = fromnd.ni_vp;
- NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
+ NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ,
UIO_USERSPACE, SCARG(uap, to), p);
if (fromnd.ni_vp->v_type == VDIR)
tond.ni_cnd.cn_flags |= WILLBEDIR;
@@ -2235,8 +2237,9 @@ rename(p, uap)
out:
if (!error) {
VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
- if (fromnd.ni_dvp != tdvp)
+ if (fromnd.ni_dvp != tdvp) {
VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ }
if (tvp) {
VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
}
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index 8ceedd4..31754fd 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_lookup.c 8.4 (Berkeley) 2/16/94
- * $Id: vfs_lookup.c,v 1.21 1997/12/27 02:56:22 bde Exp $
+ * $Id: vfs_lookup.c,v 1.22 1997/12/29 00:22:38 dyson Exp $
*/
#include "opt_ktrace.h"
@@ -165,6 +165,13 @@ namei(ndp)
zfree(namei_zone, cnp->cn_pnbuf);
else
cnp->cn_flags |= HASBUF;
+
+ if (ndp->ni_vp && ndp->ni_vp->v_type == VREG &&
+ (cnp->cn_nameiop != DELETE) &&
+ ((cnp->cn_flags & (NOOBJ|LOCKLEAF)) == LOCKLEAF))
+ vfs_object_create(ndp->ni_vp,
+ ndp->ni_cnd.cn_proc, ndp->ni_cnd.cn_cred, 1);
+
return (0);
}
if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
@@ -538,8 +545,6 @@ nextname:
if (!wantparent)
vrele(ndp->ni_dvp);
- vfs_object_create(dp, ndp->ni_cnd.cn_proc, ndp->ni_cnd.cn_cred, 1);
-
if ((cnp->cn_flags & LOCKLEAF) == 0)
VOP_UNLOCK(dp, 0, p);
return (0);
@@ -687,7 +692,9 @@ relookup(dvp, vpp, cnp)
if (!wantparent)
vrele(dvp);
- vfs_object_create(dp, cnp->cn_proc, cnp->cn_cred, 1);
+ if (dp->v_type == VREG &&
+ ((cnp->cn_flags & (NOOBJ|LOCKLEAF)) == LOCKLEAF))
+ vfs_object_create(dp, cnp->cn_proc, cnp->cn_cred, 1);
if ((cnp->cn_flags & LOCKLEAF) == 0)
VOP_UNLOCK(dp, 0, p);
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 9a371b8..7120a81 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
- * $Id: vfs_subr.c,v 1.118 1997/12/29 01:03:41 dyson Exp $
+ * $Id: vfs_subr.c,v 1.119 1997/12/29 16:54:03 dyson Exp $
*/
/*
@@ -83,7 +83,6 @@ static void vfree __P((struct vnode *));
static void vgonel __P((struct vnode *vp, struct proc *p));
static unsigned long numvnodes;
SYSCTL_INT(_debug, OID_AUTO, numvnodes, CTLFLAG_RD, &numvnodes, 0, "");
-static void vputrele __P((struct vnode *vp, int put));
enum vtype iftovt_tab[16] = {
VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
@@ -108,7 +107,7 @@ SYSCTL_INT(_debug, OID_AUTO, wantfreevnodes, CTLFLAG_RW, &wantfreevnodes, 0, "")
static u_long freevnodes = 0;
SYSCTL_INT(_debug, OID_AUTO, freevnodes, CTLFLAG_RD, &freevnodes, 0, "");
-int vfs_ioopt = 0;
+int vfs_ioopt = 1;
SYSCTL_INT(_vfs, OID_AUTO, ioopt, CTLFLAG_RW, &vfs_ioopt, 0, "");
struct mntlist mountlist; /* mounted filesystem list */
@@ -352,7 +351,9 @@ getnewvnode(tag, mp, vops, vpp)
struct vnode **vpp;
{
struct proc *p = curproc; /* XXX */
- struct vnode *vp;
+ struct vnode *vp, *tvp;
+ vm_object_t object;
+ TAILQ_HEAD(freelst, vnode) vnode_tmp_list;
/*
* We take the least recently used vnode from the freelist
@@ -362,6 +363,7 @@ getnewvnode(tag, mp, vops, vpp)
*/
simple_lock(&vnode_free_list_slock);
+ TAILQ_INIT(&vnode_tmp_list);
if (wantfreevnodes && freevnodes < wantfreevnodes) {
vp = NULL;
@@ -377,9 +379,11 @@ getnewvnode(tag, mp, vops, vpp)
if (vp->v_usecount)
panic("free vnode isn't");
- if (vp->v_object && vp->v_object->resident_page_count) {
+ object = vp->v_object;
+ if (object && (object->resident_page_count || object->ref_count)) {
/* Don't recycle if it's caching some pages */
- simple_unlock(&vp->v_interlock);
+ 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 */
@@ -391,6 +395,12 @@ getnewvnode(tag, mp, vops, vpp)
}
}
+ TAILQ_FOREACH(tvp, &vnode_tmp_list, 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);
@@ -429,6 +439,7 @@ getnewvnode(tag, mp, vops, vpp)
vp = (struct vnode *) malloc((u_long) sizeof *vp,
M_VNODE, M_WAITOK);
bzero((char *) vp, sizeof *vp);
+ simple_lock_init(&vp->v_interlock);
vp->v_dd = vp;
cache_purge(vp);
LIST_INIT(&vp->v_cache_src);
@@ -553,7 +564,16 @@ vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)
* check for it.
*/
if ((bp->b_flags & B_DELWRI) && (flags & V_SAVE)) {
- (void) VOP_BWRITE(bp);
+ if (bp->b_vp == vp) {
+ if (bp->b_flags & B_CLUSTEROK) {
+ vfs_bio_awrite(bp);
+ } else {
+ bp->b_flags |= B_ASYNC;
+ VOP_BWRITE(bp);
+ }
+ } else {
+ (void) VOP_BWRITE(bp);
+ }
break;
}
bp->b_flags |= (B_INVAL|B_NOCACHE|B_RELBUF);
@@ -571,11 +591,18 @@ vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)
/*
* Destroy the copy in the VM cache, too.
*/
+ simple_lock(&vp->v_interlock);
object = vp->v_object;
if (object != NULL) {
- vm_object_page_remove(object, 0, object->size,
- (flags & V_SAVE) ? TRUE : FALSE);
+ if (flags & V_SAVEMETA)
+ vm_object_page_remove(object, 0, object->size,
+ (flags & V_SAVE) ? TRUE : FALSE);
+ else
+ vm_object_page_remove(object, 0, 0,
+ (flags & V_SAVE) ? TRUE : FALSE);
}
+ simple_unlock(&vp->v_interlock);
+
if (!(flags & V_SAVEMETA) &&
(vp->v_dirtyblkhd.lh_first || vp->v_cleanblkhd.lh_first))
panic("vinvalbuf: flush failed");
@@ -863,13 +890,11 @@ vget(vp, flags, p)
/*
* Create the VM object, if needed
*/
- if (((vp->v_type == VREG) || (vp->v_type == VBLK)) &&
- ((vp->v_object == NULL) ||
- (vp->v_object->flags & OBJ_VFS_REF) == 0 ||
+ if ((flags & LK_NOOBJ) == 0 &&
+ (vp->v_type == VREG) &&
+ ((vp->v_object == NULL) ||
(vp->v_object->flags & OBJ_DEAD))) {
- simple_unlock(&vp->v_interlock);
vfs_object_create(vp, curproc, curproc->p_ucred, 0);
- simple_lock(&vp->v_interlock);
}
if (flags & LK_TYPE_MASK) {
if (error = vn_lock(vp, flags | LK_INTERLOCK, p))
@@ -909,7 +934,10 @@ vrele(vp)
vp->v_usecount--;
simple_unlock(&vp->v_interlock);
- } else if (vp->v_usecount == 1) {
+ return;
+ }
+
+ if (vp->v_usecount == 1) {
vp->v_usecount--;
@@ -927,6 +955,7 @@ vrele(vp)
} else {
#ifdef DIAGNOSTIC
vprint("vrele: negative ref count", vp);
+ simple_unlock(&vp->v_interlock);
#endif
panic("vrele: negative ref cnt");
}
@@ -942,17 +971,20 @@ vput(vp)
if (vp == NULL)
panic("vput: null vp");
#endif
+
simple_lock(&vp->v_interlock);
if (vp->v_usecount > 1) {
vp->v_usecount--;
VOP_UNLOCK(vp, LK_INTERLOCK, p);
+ return;
+
+ }
- } else if (vp->v_usecount == 1) {
+ if (vp->v_usecount == 1) {
vp->v_usecount--;
-
if (VSHOULDFREE(vp))
vfree(vp);
/*
@@ -1110,8 +1142,7 @@ vclean(vp, flags, p)
int flags;
struct proc *p;
{
- int active, irefed;
- vm_object_t object;
+ int active;
/*
* Check to see if the vnode is in use. If so we have to reference it
@@ -1120,6 +1151,10 @@ vclean(vp, flags, p)
*/
if ((active = vp->v_usecount))
vp->v_usecount++;
+
+ if (vp->v_object) {
+ vp->v_object->flags |= OBJ_DEAD;
+ }
/*
* Prevent the vnode from being recycled or brought into use while we
* clean it out.
@@ -1136,19 +1171,14 @@ vclean(vp, flags, p)
*/
VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, p);
- object = vp->v_object;
-
/*
* Clean out any buffers associated with the vnode.
*/
- if (flags & DOCLOSE)
+ if (vp->v_object)
+ vm_object_terminate(vp->v_object);
+ else
vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0);
- if (vp->v_object && (vp->v_object->flags & OBJ_VFS_REF)) {
- vp->v_object->flags &= ~OBJ_VFS_REF;
- vm_object_deallocate(object);
- }
-
/*
* If purging an active vnode, it must be closed and
* deactivated before being reclaimed. Note that the
@@ -1257,6 +1287,10 @@ vop_revoke(ap)
*/
simple_lock(&vp->v_interlock);
vp->v_flag &= ~VXLOCK;
+ if (vp->v_flag & VXWANT) {
+ vp->v_flag &= ~VXWANT;
+ wakeup(vp);
+ }
}
vgonel(vp, p);
return (0);
@@ -1321,10 +1355,6 @@ vgonel(vp, p)
return;
}
- if (vp->v_object) {
- vp->v_object->flags |= OBJ_VNODE_GONE;
- }
-
/*
* Clean out the filesystem specific data.
*/
@@ -1392,6 +1422,7 @@ vgonel(vp, p)
}
vp->v_type = VBAD;
+ simple_unlock(&vp->v_interlock);
}
/*
@@ -1488,6 +1519,8 @@ vprint(label, vp)
strcat(buf, "|VDOOMED");
if (vp->v_flag & VFREE)
strcat(buf, "|VFREE");
+ if (vp->v_flag & VOBJBUF)
+ strcat(buf, "|VOBJBUF");
if (buf[0] != '\0')
printf(" flags (%s)", &buf[1]);
if (vp->v_data == NULL) {
@@ -1999,21 +2032,41 @@ vfs_export_lookup(mp, nep, nam)
void
vfs_msync(struct mount *mp, int flags) {
struct vnode *vp, *nvp;
+ int anyio, tries;
+
+ tries = 5;
loop:
+ anyio = 0;
for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
- if (vp->v_mount != mp)
- goto loop;
nvp = vp->v_mntvnodes.le_next;
- if (VOP_ISLOCKED(vp) && (flags != MNT_WAIT))
+
+ if (vp->v_mount != mp) {
+ goto loop;
+ }
+
+ if ((vp->v_flag & VXLOCK) ||
+ (VOP_ISLOCKED(vp) && (flags != MNT_WAIT))) {
continue;
+ }
+
+ simple_lock(&vp->v_interlock);
if (vp->v_object &&
(vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);
- vm_object_page_clean(vp->v_object, 0, 0, TRUE);
- VOP_UNLOCK(vp, 0, curproc);
+ if (!vget(vp,
+ LK_INTERLOCK | LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ, curproc)) {
+ if (vp->v_object) {
+ vm_object_page_clean(vp->v_object, 0, 0, TRUE);
+ anyio = 1;
+ }
+ vput(vp);
+ }
+ } else {
+ simple_unlock(&vp->v_interlock);
}
}
+ if (anyio && (--tries > 0))
+ goto loop;
}
/*
@@ -2021,6 +2074,8 @@ loop:
* is done for all VREG files in the system. Some filesystems might
* afford the additional metadata buffering capability of the
* VMIO code by making the device node be VMIO mode also.
+ *
+ * If !waslocked, must be called with interlock.
*/
int
vfs_object_create(vp, p, cred, waslocked)
@@ -2033,44 +2088,49 @@ vfs_object_create(vp, p, cred, waslocked)
vm_object_t object;
int error = 0;
- if ((vp->v_type != VREG) && (vp->v_type != VBLK))
+ if ((vp->v_type != VREG) && (vp->v_type != VBLK)) {
return 0;
+ }
+
+ if (!waslocked)
+ vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY, p);
retry:
if ((object = vp->v_object) == NULL) {
if (vp->v_type == VREG) {
if ((error = VOP_GETATTR(vp, &vat, cred, p)) != 0)
goto retn;
- (void) vnode_pager_alloc(vp,
+ object = vnode_pager_alloc(vp,
OFF_TO_IDX(round_page(vat.va_size)), 0, 0);
- vp->v_object->flags |= OBJ_VFS_REF;
- } else {
+ } else if (major(vp->v_rdev) < nblkdev) {
/*
* This simply allocates the biggest object possible
* for a VBLK vnode. This should be fixed, but doesn't
* cause any problems (yet).
*/
- (void) vnode_pager_alloc(vp, INT_MAX, 0, 0);
- vp->v_object->flags |= OBJ_VFS_REF;
+ object = vnode_pager_alloc(vp, INT_MAX, 0, 0);
}
+ object->ref_count--;
+ vp->v_usecount--;
} else {
if (object->flags & OBJ_DEAD) {
- if (waslocked)
- VOP_UNLOCK(vp, 0, p);
+ VOP_UNLOCK(vp, 0, p);
tsleep(object, PVM, "vodead", 0);
- if (waslocked)
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
goto retry;
}
- if ((object->flags & OBJ_VFS_REF) == 0) {
- vm_object_reference(object);
- object->flags |= OBJ_VFS_REF;
- }
}
- if (vp->v_object)
- vp->v_flag |= VVMIO;
+
+ if (vp->v_object) {
+ vp->v_flag |= VOBJBUF;
+ }
retn:
+ if (!waslocked) {
+ simple_lock(&vp->v_interlock);
+ VOP_UNLOCK(vp, LK_INTERLOCK, p);
+ }
+
return error;
}
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 69751c4..b7be81e 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
- * $Id: vfs_syscalls.c,v 1.87 1997/12/27 02:56:23 bde Exp $
+ * $Id: vfs_syscalls.c,v 1.88 1997/12/29 00:22:50 dyson Exp $
*/
/* For 4.3 integer FS ID compatibility */
@@ -428,8 +428,8 @@ dounmount(mp, flags, p)
if (mp->mnt_flag & MNT_EXPUBLIC)
vfs_setpublicfs(NULL, NULL, NULL);
+ vfs_msync(mp, MNT_WAIT);
mp->mnt_flag &=~ MNT_ASYNC;
- vfs_msync(mp, MNT_NOWAIT);
cache_purgevfs(mp); /* remove cache entries for this file sys */
if (((mp->mnt_flag & MNT_RDONLY) ||
(error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
@@ -919,6 +919,8 @@ open(p, uap)
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
fp->f_flag |= FHASLOCK;
}
+ if ((vp->v_type == VREG) && (vp->v_object == NULL))
+ vfs_object_create(vp, p, p->p_ucred, TRUE);
VOP_UNLOCK(vp, 0, p);
p->p_retval[0] = indx;
return (0);
@@ -1102,14 +1104,14 @@ link(p, uap)
struct nameidata nd;
int error;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), p);
if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp->v_type == VDIR)
error = EPERM; /* POSIX */
else {
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
+ NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
error = namei(&nd);
if (!error) {
if (nd.ni_vp != NULL) {
@@ -1161,7 +1163,7 @@ symlink(p, uap)
path = zalloc(namei_zone);
if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL))
goto out;
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
+ NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
if (error = namei(&nd))
goto out;
if (nd.ni_vp) {
@@ -1266,7 +1268,7 @@ unlink(p, uap)
if (!error) {
VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
- error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
+ error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
} else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == vp)
@@ -1395,7 +1397,7 @@ access(p, uap)
t_gid = cred->cr_groups[0];
cred->cr_uid = p->p_cred->p_ruid;
cred->cr_groups[0] = p->p_cred->p_rgid;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
SCARG(uap, path), p);
if (error = namei(&nd))
goto out1;
@@ -1444,7 +1446,7 @@ ostat(p, uap)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
SCARG(uap, path), p);
if (error = namei(&nd))
return (error);
@@ -1481,7 +1483,7 @@ olstat(p, uap)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
SCARG(uap, path), p);
if (error = namei(&nd))
return (error);
@@ -1549,7 +1551,7 @@ stat(p, uap)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
SCARG(uap, path), p);
if (error = namei(&nd))
return (error);
@@ -1584,7 +1586,7 @@ lstat(p, uap)
struct stat sb;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
SCARG(uap, path), p);
if (error = namei(&nd))
return (error);
@@ -1620,7 +1622,7 @@ pathconf(p, uap)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
SCARG(uap, path), p);
if (error = namei(&nd))
return (error);
@@ -1655,7 +1657,7 @@ readlink(p, uap)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
SCARG(uap, path), p);
if (error = namei(&nd))
return (error);
@@ -2196,7 +2198,7 @@ rename(p, uap)
if (error = namei(&fromnd))
return (error);
fvp = fromnd.ni_vp;
- NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
+ NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ,
UIO_USERSPACE, SCARG(uap, to), p);
if (fromnd.ni_vp->v_type == VDIR)
tond.ni_cnd.cn_flags |= WILLBEDIR;
@@ -2235,8 +2237,9 @@ rename(p, uap)
out:
if (!error) {
VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
- if (fromnd.ni_dvp != tdvp)
+ if (fromnd.ni_dvp != tdvp) {
VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ }
if (tvp) {
VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
}
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index e0c9b4a..c4b8d66 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94
- * $Id: vfs_vnops.c,v 1.44 1997/12/29 00:22:55 dyson Exp $
+ * $Id: vfs_vnops.c,v 1.45 1997/12/29 01:03:43 dyson Exp $
*/
#include <sys/param.h>
@@ -511,7 +511,7 @@ vn_lock(vp, flags, p)
if (vp->v_flag & VXLOCK) {
vp->v_flag |= VXWANT;
simple_unlock(&vp->v_interlock);
- if (tsleep((caddr_t)vp, PINOD, "vn_lock", 60*hz)) {
+ if (tsleep((caddr_t)vp, PINOD, "vn_lock", 120*hz)) {
vprint("vn_lock: timeout:", vp);
}
error = ENOENT;
diff --git a/sys/libkern/cmpdi2.c b/sys/libkern/cmpdi2.c
index 238bd4e..d9c486b 100644
--- a/sys/libkern/cmpdi2.c
+++ b/sys/libkern/cmpdi2.c
@@ -34,10 +34,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: cmpdi2.c,v 1.4 1997/02/22 09:39:52 peter Exp $
*/
-#include "quad.h"
+#include <libkern/quad.h>
/*
* Return 0, 1, or 2 as a <, =, > b respectively.
diff --git a/sys/miscfs/procfs/procfs_map.c b/sys/miscfs/procfs/procfs_map.c
index 184cee9..7033e1c 100644
--- a/sys/miscfs/procfs/procfs_map.c
+++ b/sys/miscfs/procfs/procfs_map.c
@@ -36,7 +36,7 @@
*
* @(#)procfs_status.c 8.3 (Berkeley) 2/17/94
*
- * $Id: procfs_map.c,v 1.12 1997/08/02 14:32:12 bde Exp $
+ * $Id: procfs_map.c,v 1.13 1997/11/14 22:57:46 tegge Exp $
*/
#include <sys/param.h>
@@ -101,7 +101,7 @@ procfs_domap(curp, p, pfs, uio)
continue;
obj = entry->object.vm_object;
- if (obj && (obj->ref_count == 1))
+ if (obj && (obj->shadow_count == 1))
privateresident = obj->resident_page_count;
else
privateresident = 0;
diff --git a/sys/miscfs/procfs/procfs_vnops.c b/sys/miscfs/procfs/procfs_vnops.c
index b8bd8e9..00cca89 100644
--- a/sys/miscfs/procfs/procfs_vnops.c
+++ b/sys/miscfs/procfs/procfs_vnops.c
@@ -36,7 +36,7 @@
*
* @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
*
- * $Id: procfs_vnops.c,v 1.50 1997/12/27 02:56:25 bde Exp $
+ * $Id: procfs_vnops.c,v 1.51 1998/01/06 01:37:12 sef Exp $
*/
/*
@@ -186,7 +186,7 @@ procfs_close(ap)
* vnode. While one would expect v_usecount to be 1 at
* that point, it seems that (according to John Dyson)
* the VM system will bump up the usecount. So: if the
- * usecount is 2, and VVMIO is set, then this is really
+ * usecount is 2, and VOBJBUF is set, then this is really
* the last close. Otherwise, if the usecount is < 2
* then it is definitely the last close.
* If this is the last close, then it checks to see if
@@ -197,10 +197,7 @@ procfs_close(ap)
* told to stop on an event, but then the requesting process
* has gone away or forgotten about it.
*/
- if (((ap->a_vp->v_usecount == 2
- && ap->a_vp->v_object
- && (ap->a_vp->v_flag & VVMIO)) ||
- (ap->a_vp->v_usecount < 2))
+ if ((ap->a_vp->v_usecount < 2)
&& (p = pfind(pfs->pfs_pid))
&& !(p->p_pfsflags & PF_LINGER)) {
p->p_stops = 0;
diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c
index 6da09a6..3bad030 100644
--- a/sys/miscfs/specfs/spec_vnops.c
+++ b/sys/miscfs/specfs/spec_vnops.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95
- * $Id: spec_vnops.c,v 1.51 1997/10/27 13:33:42 bde Exp $
+ * $Id: spec_vnops.c,v 1.52 1997/12/29 00:23:16 dyson Exp $
*/
#include <sys/param.h>
@@ -232,6 +232,7 @@ spec_open(ap)
(ap->a_mode & FWRITE) &&
(bdevsw[maj]->d_flags & D_TYPEMASK) == D_DISK)
return (EPERM);
+
/*
* Do not allow opens of block devices that are
* currently mounted.
@@ -392,10 +393,14 @@ spec_write(ap)
brelse(bp);
return (error);
}
+ if (vp->v_flag & VOBJBUF)
+ bp->b_flags |= B_CLUSTEROK;
error = uiomove((char *)bp->b_data + on, n, uio);
if (n + on == bsize) {
- /* bawrite(bp); */
- cluster_write(bp, 0);
+ if ((vp->v_flag & VOBJBUF) && (on == 0))
+ vfs_bio_awrite(bp);
+ else
+ bawrite(bp);
} else
bdwrite(bp);
} while (error == 0 && uio->uio_resid > 0 && n != 0);
@@ -499,10 +504,15 @@ loop:
continue;
if ((bp->b_flags & B_DELWRI) == 0)
panic("spec_fsync: not dirty");
- bremfree(bp);
- bp->b_flags |= B_BUSY;
- splx(s);
- bawrite(bp);
+ if ((vp->v_flag & VOBJBUF) && (bp->b_flags & B_CLUSTEROK)) {
+ vfs_bio_awrite(bp);
+ splx(s);
+ } else {
+ bremfree(bp);
+ bp->b_flags |= B_BUSY;
+ splx(s);
+ bawrite(bp);
+ }
goto loop;
}
if (ap->a_waitfor == MNT_WAIT) {
@@ -631,6 +641,7 @@ spec_close(ap)
error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0);
if (error)
return (error);
+
/*
* We do not want to really close the device if it
* is still in use unless we are trying to close it
diff --git a/sys/nfs/nfs_bio.c b/sys/nfs/nfs_bio.c
index 0356f42..4857d39 100644
--- a/sys/nfs/nfs_bio.c
+++ b/sys/nfs/nfs_bio.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95
- * $Id: nfs_bio.c,v 1.44 1997/09/10 19:52:25 phk Exp $
+ * $Id: nfs_bio.c,v 1.45 1997/12/08 00:59:08 dyson Exp $
*/
@@ -84,8 +84,8 @@ nfs_getpages(ap)
int error;
vm_page_t m;
- if (!(ap->a_vp->v_flag & VVMIO)) {
- printf("nfs_getpages: called with non-VMIO vnode??\n");
+ if ((ap->a_vp->v_object) == NULL) {
+ printf("nfs_getpages: called with non-merged cache vnode??\n");
return EOPNOTSUPP;
}
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c
index 0356f42..4857d39 100644
--- a/sys/nfsclient/nfs_bio.c
+++ b/sys/nfsclient/nfs_bio.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95
- * $Id: nfs_bio.c,v 1.44 1997/09/10 19:52:25 phk Exp $
+ * $Id: nfs_bio.c,v 1.45 1997/12/08 00:59:08 dyson Exp $
*/
@@ -84,8 +84,8 @@ nfs_getpages(ap)
int error;
vm_page_t m;
- if (!(ap->a_vp->v_flag & VVMIO)) {
- printf("nfs_getpages: called with non-VMIO vnode??\n");
+ if ((ap->a_vp->v_object) == NULL) {
+ printf("nfs_getpages: called with non-merged cache vnode??\n");
return EOPNOTSUPP;
}
diff --git a/sys/sys/lock.h b/sys/sys/lock.h
index af98a7a..18a9edd 100644
--- a/sys/sys/lock.h
+++ b/sys/sys/lock.h
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* @(#)lock.h 8.12 (Berkeley) 5/19/95
- * $Id: lock.h,v 1.9 1997/08/30 07:59:47 fsmp Exp $
+ * $Id: lock.h,v 1.10 1997/09/21 04:24:02 dyson Exp $
*/
#ifndef _LOCK_H_
@@ -133,6 +133,7 @@ struct lock {
#define LK_INTERLOCK 0x00010000 /* unlock passed simple lock after
getting lk_interlock */
#define LK_RETRY 0x00020000 /* vn_lock: retry until locked */
+#define LK_NOOBJ 0x00040000 /* vget: don't create object */
/*
* Internal state flags corresponding to lk_sharecount, and lk_waitcount
diff --git a/sys/sys/lockmgr.h b/sys/sys/lockmgr.h
index af98a7a..18a9edd 100644
--- a/sys/sys/lockmgr.h
+++ b/sys/sys/lockmgr.h
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* @(#)lock.h 8.12 (Berkeley) 5/19/95
- * $Id: lock.h,v 1.9 1997/08/30 07:59:47 fsmp Exp $
+ * $Id: lock.h,v 1.10 1997/09/21 04:24:02 dyson Exp $
*/
#ifndef _LOCK_H_
@@ -133,6 +133,7 @@ struct lock {
#define LK_INTERLOCK 0x00010000 /* unlock passed simple lock after
getting lk_interlock */
#define LK_RETRY 0x00020000 /* vn_lock: retry until locked */
+#define LK_NOOBJ 0x00040000 /* vget: don't create object */
/*
* Internal state flags corresponding to lk_sharecount, and lk_waitcount
diff --git a/sys/sys/namei.h b/sys/sys/namei.h
index 09acc2a..5be36f3 100644
--- a/sys/sys/namei.h
+++ b/sys/sys/namei.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)namei.h 8.5 (Berkeley) 1/9/95
- * $Id: namei.h,v 1.16 1997/09/07 05:27:18 bde Exp $
+ * $Id: namei.h,v 1.17 1997/09/07 17:08:32 bde Exp $
*/
#ifndef _SYS_NAMEI_H_
@@ -109,6 +109,7 @@ struct nameidata {
#define WANTPARENT 0x0010 /* want parent vnode returned unlocked */
#define NOCACHE 0x0020 /* name must not be left in cache */
#define FOLLOW 0x0040 /* follow symbolic links */
+#define NOOBJ 0x0080 /* don't create object */
#define NOFOLLOW 0x0000 /* do not follow symbolic links (pseudo) */
#define MODMASK 0x00fc /* mask of operational modifiers */
/*
diff --git a/sys/sys/uio.h b/sys/sys/uio.h
index ca61e66..5373f88 100644
--- a/sys/sys/uio.h
+++ b/sys/sys/uio.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)uio.h 8.5 (Berkeley) 2/22/94
- * $Id: uio.h,v 1.7 1997/12/19 09:03:37 dyson Exp $
+ * $Id: uio.h,v 1.8 1997/12/19 10:03:31 bde Exp $
*/
#ifndef _SYS_UIO_H_
@@ -78,6 +78,7 @@ struct vm_object;
int uiomove __P((caddr_t, int, struct uio *));
int uiomoveco __P((caddr_t, int, struct uio *, struct vm_object *));
+int uioread __P((int, struct uio *, struct vm_object *, int *));
#else /* !KERNEL */
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 9eb0809..fa70aae 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)vnode.h 8.7 (Berkeley) 2/4/94
- * $Id: vnode.h,v 1.61 1997/12/29 01:03:55 dyson Exp $
+ * $Id: vnode.h,v 1.62 1997/12/29 16:53:53 dyson Exp $
*/
#ifndef _SYS_VNODE_H_
@@ -146,14 +146,13 @@ struct vnode {
#define VBWAIT 0x00400 /* waiting for output to complete */
#define VALIASED 0x00800 /* vnode has an alias */
#define VDIROP 0x01000 /* LFS: vnode is involved in a directory op */
-#define VVMIO 0x02000 /* VMIO flag */
+#define VOBJBUF 0x02000 /* Allocate buffers in VM object */
#define VNINACT 0x04000 /* LFS: skip ufs_inactive() in lfs_vunref */
#define VAGE 0x08000 /* Insert vnode at head of free list */
#define VOLOCK 0x10000 /* vnode is locked waiting for an object */
#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 VOBJREF 0x100000 /* This vnode is referenced by it's object */
/*
* Vnode attributes. A field value of VNOVAL represents a field whose value
diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c
index d66d48f..c4edbd3 100644
--- a/sys/ufs/ffs/ffs_balloc.c
+++ b/sys/ufs/ffs/ffs_balloc.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95
- * $Id: ffs_balloc.c,v 1.15 1997/08/02 14:33:18 bde Exp $
+ * $Id: ffs_balloc.c,v 1.16 1997/12/05 19:55:49 bde Exp $
*/
#include <sys/param.h>
@@ -237,6 +237,8 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
if (flags & B_SYNC) {
bwrite(bp);
} else {
+ if (bp->b_bufsize == fs->fs_bsize)
+ bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
}
}
@@ -265,6 +267,8 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
if (flags & B_SYNC) {
bwrite(bp);
} else {
+ if (bp->b_bufsize == fs->fs_bsize)
+ bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
}
*bpp = nbp;
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c
index 92bb2a7..77f72d3 100644
--- a/sys/ufs/ffs/ffs_inode.c
+++ b/sys/ufs/ffs/ffs_inode.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_inode.c 8.13 (Berkeley) 4/21/95
- * $Id: ffs_inode.c,v 1.28 1997/10/16 10:49:28 phk Exp $
+ * $Id: ffs_inode.c,v 1.29 1997/10/16 20:32:34 phk Exp $
*/
#include "opt_quota.h"
@@ -134,7 +134,8 @@ ffs_update(vp, access, modify, waitfor)
if (waitfor && (vp->v_mount->mnt_flag & MNT_ASYNC) == 0)
return (bwrite(bp));
else {
- bp->b_flags |= B_CLUSTEROK;
+ if (bp->b_bufsize == fs->fs_bsize)
+ bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
return (0);
}
@@ -214,6 +215,8 @@ ffs_truncate(vp, length, flags, cred, p)
return (error);
oip->i_size = length;
vnode_pager_setsize(ovp, length);
+ if (bp->b_bufsize == fs->fs_bsize)
+ bp->b_flags |= B_CLUSTEROK;
if (aflags & B_SYNC)
bwrite(bp);
else if (ovp->v_mount->mnt_flag & MNT_ASYNC)
@@ -245,6 +248,8 @@ ffs_truncate(vp, length, flags, cred, p)
size = blksize(fs, oip, lbn);
bzero((char *)bp->b_data + offset, (u_int)(size - offset));
allocbuf(bp, size);
+ if (bp->b_bufsize == fs->fs_bsize)
+ bp->b_flags |= B_CLUSTEROK;
if (aflags & B_SYNC)
bwrite(bp);
else if (ovp->v_mount->mnt_flag & MNT_ASYNC)
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 16f77c6..e78bceb 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
- * $Id: ffs_vfsops.c,v 1.62 1997/11/12 05:42:25 julian Exp $
+ * $Id: ffs_vfsops.c,v 1.63 1997/12/29 00:24:28 dyson Exp $
*/
#include "opt_quota.h"
@@ -63,6 +63,7 @@
#include <vm/vm_prot.h>
#include <vm/vm_page.h>
#include <vm/vm_extern.h>
+#include <vm/vm_object.h>
static MALLOC_DEFINE(M_FFSNODE, "FFS node", "FFS vnode private part");
@@ -364,6 +365,7 @@ ffs_reload(mp, cred, p)
struct buf *bp;
struct fs *fs, *newfs;
struct partinfo dpart;
+ dev_t dev;
int i, blks, size, error;
int32_t *lp;
@@ -375,6 +377,18 @@ ffs_reload(mp, cred, p)
devvp = VFSTOUFS(mp)->um_devvp;
if (vinvalbuf(devvp, 0, cred, p, 0, 0))
panic("ffs_reload: dirty1");
+
+ dev = devvp->v_rdev;
+ /*
+ * Only VMIO the backing device if the backing device is a real
+ * block device. This excludes the original MFS implementation.
+ * Note that it is optional that the backing device be VMIOed. This
+ * increases the opportunity for metadata caching.
+ */
+ if ((devvp->v_type == VBLK) && (major(dev) < nblkdev)) {
+ vfs_object_create(devvp, p, p->p_ucred, 0);
+ }
+
/*
* Step 2: re-read superblock from disk.
*/
@@ -509,17 +523,31 @@ ffs_mountfs(devvp, mp, p, malloctype)
if (error)
return (error);
ncount = vcount(devvp);
+/*
if (devvp->v_object)
ncount -= 1;
+*/
if (ncount > 1 && devvp != rootvp)
return (EBUSY);
if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
return (error);
+ /*
+ * Only VMIO the backing device if the backing device is a real
+ * block device. This excludes the original MFS implementation.
+ * Note that it is optional that the backing device be VMIOed. This
+ * increases the opportunity for metadata caching.
+ */
+ if ((devvp->v_type == VBLK) && (major(dev) < nblkdev)) {
+ vfs_object_create(devvp, p, p->p_ucred, 0);
+ }
+
+
ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
if (error)
return (error);
+
if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
size = DEV_BSIZE;
else
@@ -641,15 +669,6 @@ ffs_mountfs(devvp, mp, p, malloctype)
fs->fs_clean = 0;
(void) ffs_sbupdate(ump, MNT_WAIT);
}
- /*
- * Only VMIO the backing device if the backing device is a real
- * block device. This excludes the original MFS implementation.
- * Note that it is optional that the backing device be VMIOed. This
- * increases the opportunity for metadata caching.
- */
- if ((devvp->v_type == VBLK) && (major(devvp->v_rdev) < nblkdev)) {
- vfs_object_create(devvp, p, p->p_ucred, 0);
- }
return (0);
out:
if (bp)
@@ -727,6 +746,10 @@ ffs_unmount(mp, mntflags, p)
}
ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
+ vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0);
+ if (ump->um_devvp->v_object)
+ vm_object_terminate(ump->um_devvp->v_object);
+
error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
NOCRED, p);
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 341b811..d3b68b7 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95
- * $Id: ffs_vnops.c,v 1.36 1997/10/16 20:32:35 phk Exp $
+ * $Id: ffs_vnops.c,v 1.37 1997/10/27 13:33:45 bde Exp $
*/
#include <sys/param.h>
@@ -124,6 +124,16 @@ ffs_fsync(ap)
struct buf *nbp;
int pass;
int s;
+ daddr_t lbn;
+
+
+ if (vp->v_type == VBLK) {
+ lbn = INT_MAX;
+ } else {
+ struct inode *ip;
+ ip = VTOI(vp);
+ lbn = lblkno(ip->i_fs, (ip->i_size + ip->i_fs->fs_bsize - 1));
+ }
pass = 0;
/*
@@ -133,24 +143,40 @@ loop:
s = splbio();
for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
nbp = bp->b_vnbufs.le_next;
- if ((bp->b_flags & B_BUSY) || (pass == 0 && (bp->b_blkno < 0)))
+ if ((bp->b_flags & B_BUSY) || (pass == 0 && (bp->b_lblkno < 0)))
continue;
if ((bp->b_flags & B_DELWRI) == 0)
panic("ffs_fsync: not dirty");
- if (bp->b_vp != vp || ap->a_waitfor != MNT_NOWAIT) {
+ if (((bp->b_vp != vp) || (ap->a_waitfor != MNT_NOWAIT)) ||
+ ((vp->v_type != VREG) && (vp->v_type != VBLK))) {
bremfree(bp);
bp->b_flags |= B_BUSY;
splx(s);
+
/*
* Wait for I/O associated with indirect blocks to complete,
* since there is no way to quickly wait for them below.
*/
- if (bp->b_vp == vp || ap->a_waitfor == MNT_NOWAIT)
- (void) bawrite(bp);
- else
+ if ((bp->b_vp == vp) && (ap->a_waitfor == MNT_NOWAIT)) {
+ if (bp->b_flags & B_CLUSTEROK) {
+ bdwrite(bp);
+ (void) vfs_bio_awrite(bp);
+ } else {
+ (void) bawrite(bp);
+ }
+ } else {
(void) bwrite(bp);
+ }
+
+ } else if ((vp->v_type == VREG) && (bp->b_lblkno >= lbn)) {
+
+ bremfree(bp);
+ bp->b_flags |= B_BUSY | B_INVAL | B_NOCACHE;
+ brelse(bp);
+ splx(s);
+
} else {
vfs_bio_awrite(bp);
splx(s);
@@ -182,4 +208,3 @@ loop:
gettime(&tv);
return (UFS_UPDATE(ap->a_vp, &tv, &tv, ap->a_waitfor == MNT_WAIT));
}
-
diff --git a/sys/ufs/ufs/ufs_readwrite.c b/sys/ufs/ufs/ufs_readwrite.c
index 1484082..3ae1a4a 100644
--- a/sys/ufs/ufs/ufs_readwrite.c
+++ b/sys/ufs/ufs/ufs_readwrite.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ufs_readwrite.c 8.11 (Berkeley) 5/8/95
- * $Id: ufs_readwrite.c,v 1.37 1997/12/21 10:41:19 dyson Exp $
+ * $Id: ufs_readwrite.c,v 1.38 1997/12/29 01:03:50 dyson Exp $
*/
#ifdef LFS_READWRITE
@@ -108,8 +108,34 @@ READ(ap)
return (EFBIG);
for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
+
if ((bytesinfile = ip->i_size - uio->uio_offset) <= 0)
break;
+
+#if 1
+ if ((vfs_ioopt > 1) && vp->v_object) {
+ int nread, toread;
+ vm_object_reference(vp->v_object);
+ toread = uio->uio_resid;
+ if (toread > bytesinfile)
+ toread = bytesinfile;
+ if (toread >= PAGE_SIZE) {
+ error = uioread(toread, uio, vp->v_object, &nread);
+ if ((uio->uio_resid == 0) || (error != 0)) {
+ if (!(vp->v_mount->mnt_flag & MNT_NOATIME))
+ ip->i_flag |= IN_ACCESS;
+ vm_object_vndeallocate(vp->v_object);
+ return error;
+ }
+ if (nread > 0) {
+ vm_object_vndeallocate(vp->v_object);
+ continue;
+ }
+ }
+ vm_object_vndeallocate(vp->v_object);
+ }
+#endif
+
lbn = lblkno(fs, uio->uio_offset);
nextlbn = lbn + 1;
size = BLKSIZE(fs, ip, lbn);
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index a14512d..f45d377 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -66,7 +66,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: vm_fault.c,v 1.71 1997/09/01 03:17:15 bde Exp $
+ * $Id: vm_fault.c,v 1.72 1997/12/19 09:03:10 dyson Exp $
*/
/*
@@ -222,6 +222,15 @@ RetryFault:;
}
}
+ /*
+ * Make a reference to this object to prevent its disposal while we
+ * are messing with it. Once we have the reference, the map is free
+ * to be diddled. Since objects reference their shadows (and copies),
+ * they will stay around as well.
+ */
+ vm_object_reference(first_object);
+ first_object->paging_in_progress++;
+
vp = vnode_pager_lock(first_object);
if ((fault_type & VM_PROT_WRITE) &&
(first_object->type == OBJT_VNODE)) {
@@ -236,16 +245,6 @@ RetryFault:;
first_m = NULL;
/*
- * Make a reference to this object to prevent its disposal while we
- * are messing with it. Once we have the reference, the map is free
- * to be diddled. Since objects reference their shadows (and copies),
- * they will stay around as well.
- */
-
- first_object->ref_count++;
- first_object->paging_in_progress++;
-
- /*
* INVARIANTS (through entire routine):
*
* 1) At all times, we must either have the object lock or a busy
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 11604ce..17b0e75 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -61,7 +61,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: vm_map.c,v 1.102 1997/12/29 00:24:43 dyson Exp $
+ * $Id: vm_map.c,v 1.103 1997/12/29 01:03:34 dyson Exp $
*/
/*
@@ -558,6 +558,8 @@ vm_map_insert(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
if ((object == NULL) &&
(prev_entry != &map->header) &&
(( prev_entry->eflags & (MAP_ENTRY_IS_A_MAP | MAP_ENTRY_IS_SUB_MAP)) == 0) &&
+ ((prev_entry->object.vm_object == NULL) ||
+ (prev_entry->object.vm_object->type == OBJT_DEFAULT)) &&
(prev_entry->end == start) &&
(prev_entry->wired_count == 0)) {
@@ -757,7 +759,8 @@ vm_map_simplify_entry(map, entry)
prevsize = prev->end - prev->start;
if ( (prev->end == entry->start) &&
(prev->object.vm_object == entry->object.vm_object) &&
- (!prev->object.vm_object || (prev->object.vm_object->behavior == entry->object.vm_object->behavior)) &&
+ (!prev->object.vm_object ||
+ (prev->object.vm_object->behavior == entry->object.vm_object->behavior)) &&
(!prev->object.vm_object ||
(prev->offset + prevsize == entry->offset)) &&
(prev->eflags == entry->eflags) &&
@@ -783,7 +786,8 @@ vm_map_simplify_entry(map, entry)
esize = entry->end - entry->start;
if ((entry->end == next->start) &&
(next->object.vm_object == entry->object.vm_object) &&
- (!next->object.vm_object || (next->object.vm_object->behavior == entry->object.vm_object->behavior)) &&
+ (!next->object.vm_object ||
+ (next->object.vm_object->behavior == entry->object.vm_object->behavior)) &&
(!entry->object.vm_object ||
(entry->offset + esize == next->offset)) &&
(next->eflags == entry->eflags) &&
@@ -2012,7 +2016,7 @@ vm_map_copy_entry(src_map, dst_map, src_entry, dst_entry)
(src_entry->object.vm_object->type == OBJT_DEFAULT ||
src_entry->object.vm_object->type == OBJT_SWAP))
vm_object_collapse(src_entry->object.vm_object);
- ++src_entry->object.vm_object->ref_count;
+ vm_object_reference(src_entry->object.vm_object);
src_entry->eflags |= (MAP_ENTRY_COW|MAP_ENTRY_NEEDS_COPY);
dst_entry->eflags |= (MAP_ENTRY_COW|MAP_ENTRY_NEEDS_COPY);
dst_entry->object.vm_object =
@@ -2099,7 +2103,7 @@ vmspace_fork(vm1)
new_entry = vm_map_entry_create(new_map);
*new_entry = *old_entry;
new_entry->wired_count = 0;
- ++object->ref_count;
+ vm_object_reference(object);
/*
* Insert the entry into the new map -- we know we're
@@ -2458,12 +2462,13 @@ vm_map_lookup_done(map, entry)
* operations.
*/
int
-vm_uiomove(mapa, srcobject, cp, cnt, uaddra)
+vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages)
vm_map_t mapa;
vm_object_t srcobject;
off_t cp;
int cnt;
vm_offset_t uaddra;
+ int *npages;
{
vm_map_t map;
vm_object_t first_object, object;
@@ -2475,6 +2480,9 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra)
vm_pindex_t first_pindex, osize, oindex;
off_t ooffset;
+ if (npages)
+ *npages = 0;
+
while (cnt > 0) {
map = mapa;
uaddr = uaddra;
@@ -2485,11 +2493,6 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra)
return EFAULT;
}
-#if 0
- printf("foff: 0x%x, uaddr: 0x%x\norig entry: (0x%x, 0x%x), ",
- (int) cp, uaddr, first_entry->start, first_entry->end);
-#endif
-
vm_map_clip_start(map, first_entry, uaddr);
tcnt = cnt;
@@ -2500,11 +2503,27 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra)
start = first_entry->start;
end = first_entry->end;
-#if 0
- printf("new entry: (0x%x, 0x%x)\n", start, end);
-#endif
osize = atop(tcnt);
+
+ if (npages) {
+ vm_pindex_t src_index, idx;
+ src_index = OFF_TO_IDX(cp);
+ for (idx = 0; idx < osize; idx++) {
+ vm_page_t m;
+ if ((m = vm_page_lookup(srcobject, src_index + idx)) == NULL) {
+ vm_map_lookup_done(map, first_entry);
+ return 0;
+ }
+ if ((m->flags & PG_BUSY) || m->busy ||
+ m->hold_count || m->wire_count ||
+ ((m->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL)) {
+ vm_map_lookup_done(map, first_entry);
+ return 0;
+ }
+ }
+ }
+
oindex = OFF_TO_IDX(first_entry->offset);
/*
@@ -2538,7 +2557,7 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra)
object = srcobject;
object->flags |= OBJ_OPT;
- object->ref_count++;
+ vm_object_reference(object);
ooffset = cp;
vm_object_shadow(&object, &ooffset, osize);
@@ -2577,6 +2596,8 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra)
cnt -= tcnt;
uaddra += tcnt;
cp += tcnt;
+ if (npages)
+ *npages += osize;
}
return 0;
}
@@ -2616,14 +2637,12 @@ vm_freeze_copyopts(object, froma, toa)
int s;
vm_object_t robject, robjectn;
vm_pindex_t idx, from, to;
+ return;
- if (vfs_ioopt == 0 || (object == NULL) || ((object->flags & OBJ_OPT) == 0))
+ if ((vfs_ioopt == 0) || (object == NULL) ||
+ ((object->flags & OBJ_OPT) == 0))
return;
-#if 0
- printf("sc: %d, rc: %d\n", object->shadow_count, object->ref_count);
-#endif
-
if (object->shadow_count > object->ref_count)
panic("vm_freeze_copyopts: sc > rc");
@@ -2643,7 +2662,7 @@ vm_freeze_copyopts(object, froma, toa)
if ((bo_pindex + robject->size) < froma)
continue;
- robject->ref_count++;
+ vm_object_reference(robject);
while (robject->paging_in_progress) {
robject->flags |= OBJ_PIPWNT;
tsleep(robject, PVM, "objfrz", 0);
@@ -2714,9 +2733,6 @@ retryout:
vm_object_pip_wakeup(robject);
if (((from - bo_pindex) == 0) && ((to - bo_pindex) == robject->size)) {
-#if 0
- printf("removing obj: %d, %d\n", object->shadow_count, object->ref_count);
-#endif
object->shadow_count--;
TAILQ_REMOVE(&object->shadow_head, robject, shadow_list);
@@ -2729,9 +2745,8 @@ retryout:
vm_object_deallocate(object);
vm_object_deallocate(robject);
return;
- } else {
- object->ref_count--;
}
+ vm_object_deallocate(object);
}
vm_object_deallocate(robject);
}
@@ -2750,16 +2765,18 @@ retryout:
*/
DB_SHOW_COMMAND(map, vm_map_print)
{
+ static int nlines;
/* XXX convert args. */
register vm_map_t map = (vm_map_t)addr;
boolean_t full = have_addr;
register vm_map_entry_t entry;
- db_iprintf("%s map 0x%x: pmap=0x%x,ref=%d,nentries=%d,version=%d\n",
+ db_iprintf("%s map 0x%x: pmap=0x%x, ref=%d, nentries=%d, version=%d\n",
(map->is_main_map ? "Task" : "Share"),
(int) map, (int) (map->pmap), map->ref_count, map->nentries,
map->timestamp);
+ nlines++;
if (!full && db_indent)
return;
@@ -2767,23 +2784,34 @@ DB_SHOW_COMMAND(map, vm_map_print)
db_indent += 2;
for (entry = map->header.next; entry != &map->header;
entry = entry->next) {
- db_iprintf("map entry 0x%x: start=0x%x, end=0x%x, ",
+#if 0
+ if (nlines > 18) {
+ db_printf("--More--");
+ cngetc();
+ db_printf("\r");
+ nlines = 0;
+ }
+#endif
+
+ db_iprintf("map entry 0x%x: start=0x%x, end=0x%x\n",
(int) entry, (int) entry->start, (int) entry->end);
+ nlines++;
if (map->is_main_map) {
static char *inheritance_name[4] =
{"share", "copy", "none", "donate_copy"};
- db_printf("prot=%x/%x/%s, ",
+ db_iprintf(" prot=%x/%x/%s",
entry->protection,
entry->max_protection,
inheritance_name[entry->inheritance]);
if (entry->wired_count != 0)
- db_printf("wired, ");
+ db_printf(", wired");
}
if (entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) {
- db_printf("share=0x%x, offset=0x%x\n",
+ db_printf(", share=0x%x, offset=0x%x\n",
(int) entry->object.share_map,
(int) entry->offset);
+ nlines++;
if ((entry->prev == &map->header) ||
((entry->prev->eflags & MAP_ENTRY_IS_A_MAP) == 0) ||
(entry->prev->object.share_map !=
@@ -2794,13 +2822,14 @@ DB_SHOW_COMMAND(map, vm_map_print)
db_indent -= 2;
}
} else {
- db_printf("object=0x%x, offset=0x%x",
+ db_printf(", object=0x%x, offset=0x%x",
(int) entry->object.vm_object,
(int) entry->offset);
if (entry->eflags & MAP_ENTRY_COW)
db_printf(", copy (%s)",
(entry->eflags & MAP_ENTRY_NEEDS_COPY) ? "needed" : "done");
db_printf("\n");
+ nlines++;
if ((entry->prev == &map->header) ||
(entry->prev->eflags & MAP_ENTRY_IS_A_MAP) ||
@@ -2809,10 +2838,31 @@ DB_SHOW_COMMAND(map, vm_map_print)
db_indent += 2;
vm_object_print((int)entry->object.vm_object,
full, 0, (char *)0);
+ nlines += 4;
db_indent -= 2;
}
}
}
db_indent -= 2;
+ if (db_indent == 0)
+ nlines = 0;
}
+
+
+DB_SHOW_COMMAND(procvm, procvm)
+{
+ struct proc *p;
+
+ if (have_addr) {
+ p = (struct proc *) addr;
+ } else {
+ p = curproc;
+ }
+
+ printf("p = 0x%x, vmspace = 0x%x, map = 0x%x, pmap = 0x%x\n",
+ p, p->p_vmspace, &p->p_vmspace->vm_map, &p->p_vmspace->vm_pmap);
+
+ vm_map_print ((int) &p->p_vmspace->vm_map, 1, 0, NULL);
+}
+
#endif /* DDB */
diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h
index 666205b..d70a2b1 100644
--- a/sys/vm/vm_map.h
+++ b/sys/vm/vm_map.h
@@ -61,7 +61,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: vm_map.h,v 1.28 1997/08/18 02:06:24 dyson Exp $
+ * $Id: vm_map.h,v 1.29 1997/12/19 09:03:12 dyson Exp $
*/
/*
@@ -336,7 +336,7 @@ int vm_map_submap __P((vm_map_t, vm_offset_t, vm_offset_t, vm_map_t));
void vm_map_madvise __P((vm_map_t, pmap_t, vm_offset_t, vm_offset_t, int));
void vm_map_simplify_entry __P((vm_map_t, vm_map_entry_t));
void vm_init2 __P((void));
-int vm_uiomove __P((vm_map_t, vm_object_t, off_t, int, vm_offset_t));
+int vm_uiomove __P((vm_map_t, vm_object_t, off_t, int, vm_offset_t, int *));
void vm_freeze_copyopts __P((vm_object_t, vm_pindex_t, vm_pindex_t));
#endif
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 221d7fd..a279525 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -61,7 +61,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: vm_object.c,v 1.102 1997/12/19 09:03:14 dyson Exp $
+ * $Id: vm_object.c,v 1.103 1997/12/29 00:24:49 dyson Exp $
*/
/*
@@ -94,7 +94,6 @@ static void vm_object_qcollapse __P((vm_object_t object));
#ifdef not_used
static void vm_object_deactivate_pages __P((vm_object_t));
#endif
-static void vm_object_terminate __P((vm_object_t));
/*
* Virtual memory objects maintain the actual data
@@ -236,18 +235,36 @@ vm_object_reference(object)
{
if (object == NULL)
return;
+
+#if defined(DIAGNOSTIC)
+ if (object->flags & OBJ_DEAD)
+ panic("vm_object_reference: attempting to reference dead obj");
+#endif
+
+ object->ref_count++;
+ if (object->type == OBJT_VNODE)
+ vget((struct vnode *) object->handle, LK_NOOBJ, curproc);
+}
+
+inline void
+vm_object_vndeallocate(object)
+ vm_object_t object;
+{
+ struct vnode *vp = (struct vnode *) object->handle;
+#if defined(DIAGNOSTIC)
+ if (object->type != OBJT_VNODE)
+ panic("vm_object_vndeallocate: not a vnode object");
+ if (vp == NULL)
+ panic("vm_object_vndeallocate: missing vp");
if (object->ref_count == 0) {
- panic("vm_object_reference: attempting to reference deallocated obj");
+ vprint("vm_object_vndeallocate", vp);
+ panic("vm_object_vndeallocate: bad object reference count");
}
- object->ref_count++;
- if ((object->type == OBJT_VNODE) && (object->flags & OBJ_VFS_REF)) {
- struct vnode *vp;
- vp = (struct vnode *)object->handle;
- simple_lock(&vp->v_interlock);
- if (vp->v_flag & VOBJREF)
- vp->v_flag |= VOBJREF;
- ++vp->v_usecount;
- simple_unlock(&vp->v_interlock);
+#endif
+
+ object->ref_count--;
+ if (object->type == OBJT_VNODE) {
+ vrele(vp);
}
}
@@ -266,11 +283,16 @@ void
vm_object_deallocate(object)
vm_object_t object;
{
+ int s;
vm_object_t temp;
- struct vnode *vp;
while (object != NULL) {
+ if (object->type == OBJT_VNODE) {
+ vm_object_vndeallocate(object);
+ return;
+ }
+
if (object->ref_count == 0) {
panic("vm_object_deallocate: object deallocated too many times");
} else if (object->ref_count > 2) {
@@ -282,94 +304,68 @@ vm_object_deallocate(object)
* Here on ref_count of one or two, which are special cases for
* objects.
*/
- vp = NULL;
- if (object->type == OBJT_VNODE) {
- vp = (struct vnode *)object->handle;
- if (vp->v_flag & VOBJREF) {
- if (object->ref_count < 2) {
- panic("vm_object_deallocate: "
- "not enough references for OBJT_VNODE: %d",
- object->ref_count);
- } else {
+ if ((object->ref_count == 2) && (object->shadow_count == 1)) {
- /*
- * Freeze optimized copies.
- */
- vm_freeze_copyopts(object, 0, object->size);
-
- /*
- * Loose our reference to the vnode.
- */
- vp->v_flag &= ~VOBJREF;
- vrele(vp);
- }
- }
- }
-
- /*
- * Lose the reference
- */
- if (object->ref_count == 2) {
object->ref_count--;
if ((object->handle == NULL) &&
(object->type == OBJT_DEFAULT ||
object->type == OBJT_SWAP)) {
vm_object_t robject;
+
robject = TAILQ_FIRST(&object->shadow_head);
- if ((robject != NULL) &&
- (robject->handle == NULL) &&
+#if defined(DIAGNOSTIC)
+ if (robject == NULL)
+ panic("vm_object_deallocate: ref_count: %d,"
+ " shadow_count: %d",
+ object->ref_count, object->shadow_count);
+#endif
+ if ((robject->handle == NULL) &&
(robject->type == OBJT_DEFAULT ||
robject->type == OBJT_SWAP)) {
- int s;
- robject->ref_count += 2;
- object->ref_count += 2;
-
- do {
- s = splvm();
- while (robject->paging_in_progress) {
- robject->flags |= OBJ_PIPWNT;
- tsleep(robject, PVM, "objde1", 0);
- }
-
- while (object->paging_in_progress) {
- object->flags |= OBJ_PIPWNT;
- tsleep(object, PVM, "objde2", 0);
- }
- splx(s);
- } while( object->paging_in_progress || robject->paging_in_progress);
+ robject->ref_count++;
+
+ retry:
+ s = splvm();
+ if (robject->paging_in_progress) {
+ robject->flags |= OBJ_PIPWNT;
+ tsleep(robject, PVM, "objde1", 0);
+ goto retry;
+ }
+
+ if (object->paging_in_progress) {
+ object->flags |= OBJ_PIPWNT;
+ tsleep(object, PVM, "objde2", 0);
+ goto retry;
+ }
+ splx(s);
- object->ref_count -= 2;
- robject->ref_count -= 2;
- if( robject->ref_count == 0) {
- robject->ref_count += 1;
+ if( robject->ref_count == 1) {
+ robject->ref_count--;
object = robject;
- continue;
+ goto doterm;
}
- vm_object_collapse(robject);
- return;
+
+ object = robject;
+ vm_object_collapse(object);
+ continue;
}
}
- /*
- * If there are still references, then we are done.
- */
- return;
- }
- /*
- * Make sure no one uses us.
- */
- object->flags |= OBJ_DEAD;
+ return;
- if (vp)
- vp->v_flag &= ~VTEXT;
+ } else {
+ object->ref_count--;
+ if (object->ref_count != 0)
+ return;
+ }
- object->ref_count--;
+doterm:
temp = object->backing_object;
if (temp) {
TAILQ_REMOVE(&temp->shadow_head, object, shadow_list);
- --temp->shadow_count;
+ temp->shadow_count--;
}
vm_object_terminate(object);
/* unlocks and deallocates object */
@@ -383,15 +379,17 @@ vm_object_deallocate(object)
*
* The object must be locked.
*/
-static void
+void
vm_object_terminate(object)
register vm_object_t object;
{
register vm_page_t p;
int s;
- if (object->flags & OBJ_VFS_REF)
- panic("vm_object_deallocate: freeing VFS_REF'ed object");
+ /*
+ * Make sure no one uses us.
+ */
+ object->flags |= OBJ_DEAD;
/*
* wait for the pageout daemon to be done with the object
@@ -403,29 +401,44 @@ vm_object_terminate(object)
}
splx(s);
+#if defined(DIAGNOSTIC)
if (object->paging_in_progress != 0)
panic("vm_object_deallocate: pageout in progress");
+#endif
/*
* Clean and free the pages, as appropriate. All references to the
* object are gone, so we don't need to lock it.
*/
if (object->type == OBJT_VNODE) {
- struct vnode *vp = object->handle;
+ struct vnode *vp;
+
+ /*
+ * Freeze optimized copies.
+ */
+ vm_freeze_copyopts(object, 0, object->size);
+
+ /*
+ * Clean pages and flush buffers.
+ */
vm_object_page_clean(object, 0, 0, TRUE);
+
+ vp = (struct vnode *) object->handle;
vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0);
- }
- /*
- * Now free the pages. For internal objects, this also removes them
- * from paging queues.
- */
- while ((p = TAILQ_FIRST(&object->memq)) != NULL) {
- if (p->busy || (p->flags & PG_BUSY))
- printf("vm_object_terminate: freeing busy page\n");
- PAGE_WAKEUP(p);
- vm_page_free(p);
- cnt.v_pfree++;
+ } else {
+
+ /*
+ * Now free the pages. For internal objects, this also removes them
+ * from paging queues.
+ */
+ while ((p = TAILQ_FIRST(&object->memq)) != NULL) {
+ if (p->busy || (p->flags & PG_BUSY))
+ printf("vm_object_terminate: freeing busy page\n");
+ PAGE_WAKEUP(p);
+ vm_page_free(p);
+ cnt.v_pfree++;
+ }
}
/*
@@ -1122,6 +1135,7 @@ vm_object_collapse(object)
object_collapses++;
} else {
+ vm_object_t new_backing_object;
/*
* If all of the pages in the backing object are
* shadowed by the parent object, the parent object no
@@ -1173,25 +1187,26 @@ vm_object_collapse(object)
* it, since its reference count is at least 2.
*/
- TAILQ_REMOVE(&object->backing_object->shadow_head,
+ TAILQ_REMOVE(&backing_object->shadow_head,
object, shadow_list);
- --object->backing_object->shadow_count;
- vm_object_reference(object->backing_object = backing_object->backing_object);
- if (object->backing_object) {
- TAILQ_INSERT_TAIL(&object->backing_object->shadow_head,
+ --backing_object->shadow_count;
+
+ new_backing_object = backing_object->backing_object;
+ if (object->backing_object = new_backing_object) {
+ vm_object_reference(new_backing_object);
+ TAILQ_INSERT_TAIL(&new_backing_object->shadow_head,
object, shadow_list);
- ++object->backing_object->shadow_count;
+ ++new_backing_object->shadow_count;
+ object->backing_object_offset +=
+ backing_object->backing_object_offset;
}
- object->backing_object_offset += backing_object->backing_object_offset;
/*
* Drop the reference count on backing_object. Since
* its ref_count was at least 2, it will not vanish;
* so we don't need to call vm_object_deallocate.
*/
- if (backing_object->ref_count == 1)
- printf("should have called obj deallocate\n");
- backing_object->ref_count--;
+ vm_object_deallocate(backing_object);
object_bypasses++;
@@ -1220,18 +1235,20 @@ vm_object_page_remove(object, start, end, clean_only)
{
register vm_page_t p, next;
unsigned int size;
- int s;
+ int s, all;
if (object == NULL)
return;
+ all = ((end == 0) && (start == 0));
+
object->paging_in_progress++;
again:
size = end - start;
- if (size > 4 || size >= object->size / 4) {
+ if (all || size > 4 || size >= object->size / 4) {
for (p = TAILQ_FIRST(&object->memq); p != NULL; p = next) {
next = TAILQ_NEXT(p, listq);
- if ((start <= p->pindex) && (p->pindex < end)) {
+ if (all || ((start <= p->pindex) && (p->pindex < end))) {
if (p->wire_count != 0) {
vm_page_protect(p, VM_PROT_NONE);
p->valid = 0;
@@ -1516,12 +1533,17 @@ DB_SHOW_COMMAND(object, vm_object_print_static)
if (object == NULL)
return;
- db_iprintf("Object 0x%x: size=0x%x, res=%d, ref=%d, ",
- (int) object, (int) object->size,
- object->resident_page_count, object->ref_count);
- db_printf("offset=0x%x, backing_object=(0x%x)+0x%x\n",
+ db_iprintf("Object 0x%x: type=%d, size=0x%x, res=%d, ref=%d, flags=0x%x\n",
+ (int) object, (int) object->type, (int) object->size,
+ object->resident_page_count,
+ object->ref_count,
+ object->flags);
+ db_iprintf(" sref=%d, offset=0x%x, backing_object(%d)=(0x%x)+0x%x\n",
+ object->shadow_count,
(int) object->paging_offset,
- (int) object->backing_object, (int) object->backing_object_offset);
+ (((int)object->backing_object)?object->backing_object->ref_count:0),
+ (int) object->backing_object,
+ (int) object->backing_object_offset);
if (!full)
return;
diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
index a13a5bf..ac86c6c 100644
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -61,7 +61,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: vm_object.h,v 1.39 1997/12/19 09:03:16 dyson Exp $
+ * $Id: vm_object.h,v 1.40 1997/12/29 00:24:55 dyson Exp $
*/
/*
@@ -122,16 +122,13 @@ struct vm_object {
/*
* Flags
*/
-#define OBJ_CANPERSIST 0x0001 /* allow to persist */
#define OBJ_ACTIVE 0x0004 /* active objects */
#define OBJ_DEAD 0x0008 /* dead objects (during rundown) */
-#define OBJ_PIPWNT 0x0040 /* paging in progress wanted */
+#define OBJ_PIPWNT 0x0040 /* paging in progress wanted */
#define OBJ_WRITEABLE 0x0080 /* object has been made writable */
-#define OBJ_MIGHTBEDIRTY 0x0100 /* object might be dirty */
+#define OBJ_MIGHTBEDIRTY 0x0100 /* object might be dirty */
#define OBJ_CLEANING 0x0200
-#define OBJ_VFS_REF 0x0400 /* object is refed by vfs layer */
-#define OBJ_VNODE_GONE 0x0800 /* vnode is gone */
-#define OBJ_OPT 0x1000 /* I/O optimization */
+#define OBJ_OPT 0x1000 /* I/O optimization */
#define OBJ_NORMAL 0x0 /* default behavior */
#define OBJ_SEQUENTIAL 0x1 /* expect sequential accesses */
@@ -170,6 +167,8 @@ boolean_t vm_object_coalesce __P((vm_object_t, vm_pindex_t, vm_size_t, vm_size_t
void vm_object_collapse __P((vm_object_t));
void vm_object_copy __P((vm_object_t, vm_pindex_t, vm_object_t *, vm_pindex_t *, boolean_t *));
void vm_object_deallocate __P((vm_object_t));
+void vm_object_terminate __P((vm_object_t));
+void vm_object_vndeallocate __P((vm_object_t));
void vm_object_init __P((void));
void vm_object_page_clean __P((vm_object_t, vm_pindex_t, vm_pindex_t, boolean_t));
void vm_object_page_remove __P((vm_object_t, vm_pindex_t, vm_pindex_t, boolean_t));
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 99ee5a4..eda7f30 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -65,7 +65,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: vm_pageout.c,v 1.104 1997/12/24 15:05:25 dyson Exp $
+ * $Id: vm_pageout.c,v 1.105 1997/12/29 00:25:03 dyson Exp $
*/
/*
@@ -695,11 +695,7 @@ rescan0:
*/
if ((m->flags & PG_REFERENCED) != 0) {
m->flags &= ~PG_REFERENCED;
-#if 0
- pmap_clear_reference(VM_PAGE_TO_PHYS(m));
-#else
actcount = pmap_ts_referenced(VM_PAGE_TO_PHYS(m));
-#endif
vm_page_activate(m);
m->act_count += (actcount + ACT_ADVANCE + 1);
continue;
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 360188a..f3ed776 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -38,7 +38,7 @@
* SUCH DAMAGE.
*
* from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91
- * $Id: vnode_pager.c,v 1.77 1997/12/19 09:03:17 dyson Exp $
+ * $Id: vnode_pager.c,v 1.78 1997/12/29 00:25:11 dyson Exp $
*/
/*
@@ -140,26 +140,18 @@ vnode_pager_alloc(void *handle, vm_size_t size, vm_prot_t prot,
* And an object of the appropriate size
*/
object = vm_object_allocate(OBJT_VNODE, size);
- if (vp->v_type == VREG)
- object->flags = OBJ_CANPERSIST;
- else
- object->flags = 0;
+ object->flags = 0;
object->un_pager.vnp.vnp_size = (vm_ooffset_t) size * PAGE_SIZE;
object->handle = handle;
vp->v_object = object;
+ vp->v_usecount++;
} else {
- /*
- * vm_object_reference() will remove the object from the cache if
- * found and gain a reference to the object.
- */
- vm_object_reference(object);
+ object->ref_count++;
+ vp->v_usecount++;
}
- if (vp->v_type == VREG)
- vp->v_flag |= VVMIO;
-
vp->v_flag &= ~VOLOCK;
if (vp->v_flag & VOWANT) {
vp->v_flag &= ~VOWANT;
@@ -186,10 +178,11 @@ vnode_pager_dealloc(object)
splx(s);
}
+ object->flags |= OBJ_DEAD;
object->handle = NULL;
-
+ object->type = OBJT_DEFAULT;
vp->v_object = NULL;
- vp->v_flag &= ~(VTEXT | VVMIO);
+ vp->v_flag &= ~(VTEXT|VOBJBUF);
}
static boolean_t
@@ -541,8 +534,7 @@ vnode_pager_getpages(object, m, count, reqpage)
{
int rtval;
struct vnode *vp;
- if (object->flags & OBJ_VNODE_GONE)
- return VM_PAGER_ERROR;
+
vp = object->handle;
rtval = VOP_GETPAGES(vp, m, count*PAGE_SIZE, reqpage, 0);
if (rtval == EOPNOTSUPP)
@@ -643,7 +635,7 @@ vnode_pager_leaf_getpages(object, m, count, reqpage)
IDX_TO_OFF(m[i]->pindex), &runpg);
if (firstaddr == -1) {
if (i == reqpage && foff < object->un_pager.vnp.vnp_size) {
- panic("vnode_pager_putpages: unexpected missing page: firstaddr: %d, foff: %ld, vnp_size: %d",
+ panic("vnode_pager_getpages: unexpected missing page: firstaddr: %d, foff: %ld, vnp_size: %d",
firstaddr, foff, object->un_pager.vnp.vnp_size);
}
vnode_pager_freepage(m[i]);
@@ -792,9 +784,6 @@ vnode_pager_putpages(object, m, count, sync, rtvals)
int rtval;
struct vnode *vp;
- if (object->flags & OBJ_VNODE_GONE)
- return VM_PAGER_ERROR;
-
vp = object->handle;
rtval = VOP_PUTPAGES(vp, m, count*PAGE_SIZE, sync, rtvals, 0);
if (rtval == EOPNOTSUPP)
OpenPOWER on IntegriCloud