summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/fs/nfsclient/nfs_clbio.c15
-rw-r--r--sys/fs/nwfs/nwfs_io.c11
-rw-r--r--sys/fs/smbfs/smbfs_io.c11
-rw-r--r--sys/nfsclient/nfs_bio.c8
-rw-r--r--sys/vm/vm_object.c15
-rw-r--r--sys/vm/vnode_pager.c19
-rw-r--r--sys/vm/vnode_pager.h3
7 files changed, 48 insertions, 34 deletions
diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c
index fee8b05..95138ec 100644
--- a/sys/fs/nfsclient/nfs_clbio.c
+++ b/sys/fs/nfsclient/nfs_clbio.c
@@ -302,7 +302,7 @@ ncl_putpages(struct vop_putpages_args *ap)
}
for (i = 0; i < npages; i++)
- rtvals[i] = VM_PAGER_AGAIN;
+ rtvals[i] = VM_PAGER_ERROR;
/*
* When putting pages, do not extend file past EOF.
@@ -345,16 +345,9 @@ ncl_putpages(struct vop_putpages_args *ap)
pmap_qremove(kva, npages);
relpbuf(bp, &ncl_pbuf_freecnt);
- if (!error) {
- int nwritten = round_page(count - uio.uio_resid) / PAGE_SIZE;
- for (i = 0; i < nwritten; i++) {
- rtvals[i] = VM_PAGER_OK;
- vm_page_undirty(pages[i]);
- }
- if (must_commit) {
- ncl_clearcommit(vp->v_mount);
- }
- }
+ vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
+ if (must_commit)
+ ncl_clearcommit(vp->v_mount);
return rtvals[0];
}
diff --git a/sys/fs/nwfs/nwfs_io.c b/sys/fs/nwfs/nwfs_io.c
index 141c52e..d764f79 100644
--- a/sys/fs/nwfs/nwfs_io.c
+++ b/sys/fs/nwfs/nwfs_io.c
@@ -544,7 +544,7 @@ nwfs_putpages(ap)
npages = btoc(count);
for (i = 0; i < npages; i++) {
- rtvals[i] = VM_PAGER_AGAIN;
+ rtvals[i] = VM_PAGER_ERROR;
}
bp = getpbuf(&nwfs_pbuf_freecnt);
@@ -569,13 +569,8 @@ nwfs_putpages(ap)
pmap_qremove(kva, npages);
relpbuf(bp, &nwfs_pbuf_freecnt);
- if (!error) {
- int nwritten = round_page(count - uio.uio_resid) / PAGE_SIZE;
- for (i = 0; i < nwritten; i++) {
- rtvals[i] = VM_PAGER_OK;
- vm_page_undirty(pages[i]);
- }
- }
+ if (!error)
+ vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
return rtvals[0];
#endif /* NWFS_RWCACHE */
}
diff --git a/sys/fs/smbfs/smbfs_io.c b/sys/fs/smbfs/smbfs_io.c
index 6c02fc6..4599a6f 100644
--- a/sys/fs/smbfs/smbfs_io.c
+++ b/sys/fs/smbfs/smbfs_io.c
@@ -609,7 +609,7 @@ smbfs_putpages(ap)
npages = btoc(count);
for (i = 0; i < npages; i++) {
- rtvals[i] = VM_PAGER_AGAIN;
+ rtvals[i] = VM_PAGER_ERROR;
}
bp = getpbuf(&smbfs_pbuf_freecnt);
@@ -639,13 +639,8 @@ smbfs_putpages(ap)
relpbuf(bp, &smbfs_pbuf_freecnt);
- if (!error) {
- int nwritten = round_page(count - uio.uio_resid) / PAGE_SIZE;
- for (i = 0; i < nwritten; i++) {
- rtvals[i] = VM_PAGER_OK;
- vm_page_undirty(pages[i]);
- }
- }
+ if (!error)
+ vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
return rtvals[0];
#endif /* SMBFS_RWGENERIC */
}
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c
index 9a777c8..da8a2ec 100644
--- a/sys/nfsclient/nfs_bio.c
+++ b/sys/nfsclient/nfs_bio.c
@@ -300,7 +300,7 @@ nfs_putpages(struct vop_putpages_args *ap)
}
for (i = 0; i < npages; i++)
- rtvals[i] = VM_PAGER_AGAIN;
+ rtvals[i] = VM_PAGER_ERROR;
/*
* When putting pages, do not extend file past EOF.
@@ -344,11 +344,7 @@ nfs_putpages(struct vop_putpages_args *ap)
relpbuf(bp, &nfs_pbuf_freecnt);
if (!error) {
- int nwritten = round_page(count - uio.uio_resid) / PAGE_SIZE;
- for (i = 0; i < nwritten; i++) {
- rtvals[i] = VM_PAGER_OK;
- vm_page_undirty(pages[i]);
- }
+ vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
if (must_commit) {
nfs_clearcommit(vp->v_mount);
}
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index dbcac85..1a3d398 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -852,6 +852,21 @@ rescan:
flags, &clearobjflags);
if (object->generation != curgeneration)
goto rescan;
+
+ /*
+ * If the VOP_PUTPAGES() did a truncated write, so
+ * that even the first page of the run is not fully
+ * written, vm_pageout_flush() returns 0 as the run
+ * length. Since the condition that caused truncated
+ * write may be permanent, e.g. exhausted free space,
+ * accepting n == 0 would cause an infinite loop.
+ *
+ * Forwarding the iterator leaves the unwritten page
+ * behind, but there is not much we can do there if
+ * filesystem refuses to write it.
+ */
+ if (n == 0)
+ n = 1;
np = vm_page_find_least(object, pi + n);
}
#if 0
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index f497d41..98a5be0 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -1089,7 +1089,7 @@ vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *ma, int bytecount,
count = bytecount / PAGE_SIZE;
for (i = 0; i < count; i++)
- rtvals[i] = VM_PAGER_AGAIN;
+ rtvals[i] = VM_PAGER_ERROR;
if ((int64_t)ma[0]->pindex < 0) {
printf("vnode_pager_putpages: attempt to write meta-data!!! -- 0x%lx(%lx)\n",
@@ -1191,3 +1191,20 @@ vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *ma, int bytecount,
}
return rtvals[0];
}
+
+void
+vnode_pager_undirty_pages(vm_page_t *ma, int *rtvals, int written)
+{
+ int i, pos;
+
+ for (i = 0, pos = 0; pos < written; i++, pos += PAGE_SIZE) {
+ if (pos < trunc_page(written)) {
+ rtvals[i] = VM_PAGER_OK;
+ vm_page_undirty(ma[i]);
+ } else {
+ /* Partially written page. */
+ rtvals[i] = VM_PAGER_AGAIN;
+ vm_page_clear_dirty(ma[i], 0, written & PAGE_MASK);
+ }
+ }
+}
diff --git a/sys/vm/vnode_pager.h b/sys/vm/vnode_pager.h
index 88ae306..5e3d5eb 100644
--- a/sys/vm/vnode_pager.h
+++ b/sys/vm/vnode_pager.h
@@ -49,5 +49,8 @@ int vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m,
int vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *m,
int count, boolean_t sync,
int *rtvals);
+
+void vnode_pager_undirty_pages(vm_page_t *ma, int *rtvals, int written);
+
#endif /* _KERNEL */
#endif /* _VNODE_PAGER_ */
OpenPOWER on IntegriCloud