aboutsummaryrefslogtreecommitdiff
path: root/sys/vm
diff options
context:
space:
mode:
authorAlan Cox <alc@FreeBSD.org>1999-05-02 23:57:16 +0000
committerAlan Cox <alc@FreeBSD.org>1999-05-02 23:57:16 +0000
commit4221e284a34553fa3bbebd4d618f9747fa962d53 (patch)
treeadbf361e51123ffae88735ef75da1564ccd32077 /sys/vm
parent1b3859ce9a9514ed69c4ab7dcb98ee11ee33cfe4 (diff)
Notes
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm_fault.c30
-rw-r--r--sys/vm/vm_page.c51
-rw-r--r--sys/vm/vm_page.h8
-rw-r--r--sys/vm/vm_pager.c5
-rw-r--r--sys/vm/vm_pager.h18
-rw-r--r--sys/vm/vnode_pager.c5
6 files changed, 95 insertions, 22 deletions
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 047f10f6cbe6d..882d52efdffd2 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.100 1999/02/17 09:08:29 dillon Exp $
+ * $Id: vm_fault.c,v 1.101 1999/02/25 06:00:52 alc Exp $
*/
/*
@@ -409,6 +409,12 @@ readrest:
firstpindex = fs.first_pindex -
2*(VM_FAULT_READ_BEHIND + VM_FAULT_READ_AHEAD + 1);
+ /*
+ * note: partially valid pages cannot be
+ * included in the lookahead - NFS piecemeal
+ * writes will barf on it badly.
+ */
+
for(tmppindex = fs.first_pindex - 1;
tmppindex >= firstpindex;
--tmppindex) {
@@ -552,12 +558,16 @@ readrest:
}
fs.first_m = NULL;
+ /*
+ * Zero the page if necessary and mark it valid.
+ */
if ((fs.m->flags & PG_ZERO) == 0) {
vm_page_zero_fill(fs.m);
- }
- else
+ } else {
cnt.v_ozfod++;
+ }
cnt.v_zfod++;
+ fs.m->valid = VM_PAGE_BITS_ALL;
break; /* break to PAGE HAS BEEN FOUND */
} else {
if (fs.object != fs.first_object) {
@@ -788,14 +798,24 @@ readrest:
#endif
unlock_things(&fs);
- fs.m->valid = VM_PAGE_BITS_ALL;
- vm_page_flag_clear(fs.m, PG_ZERO);
+
+ /*
+ * Sanity check: page must be completely valid or it is not fit to
+ * map into user space. vm_pager_get_pages() ensures this.
+ */
+
+ if (fs.m->valid != VM_PAGE_BITS_ALL) {
+ vm_page_zero_invalid(fs.m, TRUE);
+ printf("Warning: page %p partially invalid on fault\n", fs.m);
+ }
pmap_enter(fs.map->pmap, vaddr, VM_PAGE_TO_PHYS(fs.m), prot, wired);
+
if (((fault_flags & VM_FAULT_WIRE_MASK) == 0) && (wired == 0)) {
pmap_prefault(fs.map->pmap, vaddr, fs.entry);
}
+ vm_page_flag_clear(fs.m, PG_ZERO);
vm_page_flag_set(fs.m, PG_MAPPED|PG_REFERENCED);
if (fault_flags & VM_FAULT_HOLD)
vm_page_hold(fs.m);
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index e07ea633ed170..0d85a946757cb 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)vm_page.c 7.4 (Berkeley) 5/7/91
- * $Id: vm_page.c,v 1.128 1999/03/19 05:21:03 alc Exp $
+ * $Id: vm_page.c,v 1.129 1999/04/05 19:38:29 julian Exp $
*/
/*
@@ -1460,14 +1460,16 @@ vm_page_bits(int base, int size)
}
/*
- * set a page valid and clean. May not block.
+ * vm_page_set_validclean:
*
- * In order to maintain consistancy due to the DEV_BSIZE granularity
- * of the valid bits, we have to zero non-DEV_BSIZE aligned portions of
- * the page at the beginning and end of the valid range when the
- * associated valid bits are not already set.
+ * Sets portions of a page valid and clean. The arguments are expected
+ * to be DEV_BSIZE aligned but if they aren't the bitmap is inclusive
+ * of any partial chunks touched by the range. The invalid portion of
+ * such chunks will be zero'd.
*
- * (base + size) must be less then or equal to PAGE_SIZE.
+ * This routine may not block.
+ *
+ * (base + size) must be less then or equal to PAGE_SIZE.
*/
void
vm_page_set_validclean(m, base, size)
@@ -1529,8 +1531,35 @@ vm_page_set_validclean(m, base, size)
pmap_clear_modify(VM_PAGE_TO_PHYS(m));
}
+#if 0
+
+void
+vm_page_set_dirty(m, base, size)
+ vm_page_t m;
+ int base;
+ int size;
+{
+ m->dirty |= vm_page_bits(base, size);
+}
+
+#endif
+
+void
+vm_page_clear_dirty(m, base, size)
+ vm_page_t m;
+ int base;
+ int size;
+{
+ m->dirty &= ~vm_page_bits(base, size);
+}
+
/*
- * set a page (partially) invalid. May not block.
+ * vm_page_set_invalid:
+ *
+ * Invalidates DEV_BSIZE'd chunks within a page. Both the
+ * valid and dirty bits for the effected areas are cleared.
+ *
+ * May not block.
*/
void
vm_page_set_invalid(m, base, size)
@@ -1540,9 +1569,9 @@ vm_page_set_invalid(m, base, size)
{
int bits;
- m->valid &= ~(bits = vm_page_bits(base, size));
- if (m->valid == 0)
- m->dirty &= ~bits;
+ bits = vm_page_bits(base, size);
+ m->valid &= ~bits;
+ m->dirty &= ~bits;
m->object->generation++;
}
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index 8072f666b4c39..abff79486aadb 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -61,7 +61,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: vm_page.h,v 1.58 1999/03/15 05:09:48 julian Exp $
+ * $Id: vm_page.h,v 1.59 1999/04/05 19:38:29 julian Exp $
*/
/*
@@ -101,6 +101,10 @@
* Fields in this structure are locked either by the lock on the
* object that the page belongs to (O) or by the lock on the page
* queues (P).
+ *
+ * The 'valid' and 'dirty' fields are distinct. A page may have dirty
+ * bits set without having associated valid bits set. This is used by
+ * NFS to implement piecemeal writes.
*/
TAILQ_HEAD(pglist, vm_page);
@@ -404,6 +408,8 @@ void vm_page_wire __P((vm_page_t));
void vm_page_unqueue __P((vm_page_t));
void vm_page_unqueue_nowakeup __P((vm_page_t));
void vm_page_set_validclean __P((vm_page_t, int, int));
+void vm_page_set_dirty __P((vm_page_t, int, int));
+void vm_page_clear_dirty __P((vm_page_t, int, int));
void vm_page_set_invalid __P((vm_page_t, int, int));
static __inline boolean_t vm_page_zero_fill __P((vm_page_t));
int vm_page_is_valid __P((vm_page_t, int, int));
diff --git a/sys/vm/vm_pager.c b/sys/vm/vm_pager.c
index 36a905ec6dc9b..dbacceb030508 100644
--- a/sys/vm/vm_pager.c
+++ b/sys/vm/vm_pager.c
@@ -61,7 +61,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: vm_pager.c,v 1.44 1999/03/14 09:20:00 julian Exp $
+ * $Id: vm_pager.c,v 1.45 1999/04/11 02:16:27 eivind Exp $
*/
/*
@@ -523,6 +523,9 @@ vm_pager_chain_iodone(struct buf *nbp)
* Obtain a physical buffer and chain it to its parent buffer. When
* I/O completes, the parent buffer will be B_SIGNAL'd. Errors are
* automatically propogated to the parent
+ *
+ * Since these are brand new buffers, we do not have to clear B_INVAL
+ * and B_ERROR because they are already clear.
*/
struct buf *
diff --git a/sys/vm/vm_pager.h b/sys/vm/vm_pager.h
index 82b65740f8459..aff14ab29aef9 100644
--- a/sys/vm/vm_pager.h
+++ b/sys/vm/vm_pager.h
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vm_pager.h 8.4 (Berkeley) 1/12/94
- * $Id: vm_pager.h,v 1.20 1999/01/24 02:32:15 dillon Exp $
+ * $Id: vm_pager.h,v 1.21 1999/03/14 09:20:00 julian Exp $
*/
/*
@@ -110,6 +110,14 @@ void flushchainbuf(struct buf *nbp);
void waitchainbuf(struct buf *bp, int count, int done);
void autochaindone(struct buf *bp);
+/*
+ * vm_page_get_pages:
+ *
+ * Retrieve pages from the VM system in order to map them into an object
+ * ( or into VM space somewhere ). If the pagein was successful, we
+ * must fully validate it.
+ */
+
static __inline int
vm_pager_get_pages(
vm_object_t object,
@@ -117,7 +125,13 @@ vm_pager_get_pages(
int count,
int reqpage
) {
- return ((*pagertab[object->type]->pgo_getpages)(object, m, count, reqpage));
+ int r;
+
+ r = (*pagertab[object->type]->pgo_getpages)(object, m, count, reqpage);
+ if (r == VM_PAGER_OK && m[reqpage]->valid != VM_PAGE_BITS_ALL) {
+ vm_page_zero_invalid(m[reqpage], TRUE);
+ }
+ return(r);
}
static __inline void
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 628bec7cf5ab0..83f379a206a1b 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.106 1999/04/05 19:38:29 julian Exp $
+ * $Id: vnode_pager.c,v 1.107 1999/04/10 20:52:11 dt Exp $
*/
/*
@@ -789,7 +789,8 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage)
* read.
*/
vm_page_set_validclean(mt, 0, size - tfoff);
- vm_page_zero_invalid(mt, FALSE);
+ /* handled by vm_fault now */
+ /* vm_page_zero_invalid(mt, FALSE); */
}
vm_page_flag_clear(mt, PG_ZERO);