diff options
-rw-r--r-- | sys/fs/nfsclient/nfs_clbio.c | 15 | ||||
-rw-r--r-- | sys/fs/nwfs/nwfs_io.c | 11 | ||||
-rw-r--r-- | sys/fs/smbfs/smbfs_io.c | 11 | ||||
-rw-r--r-- | sys/nfsclient/nfs_bio.c | 8 | ||||
-rw-r--r-- | sys/vm/vm_object.c | 15 | ||||
-rw-r--r-- | sys/vm/vnode_pager.c | 19 | ||||
-rw-r--r-- | sys/vm/vnode_pager.h | 3 |
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_ */ |