svn commit: r223054 - in stable/8/sys: fs/nfsclient fs/nwfs
fs/smbfs nfsclient vm
Konstantin Belousov
kib at FreeBSD.org
Mon Jun 13 19:33:13 UTC 2011
Author: kib
Date: Mon Jun 13 19:33:13 2011
New Revision: 223054
URL: http://svn.freebsd.org/changeset/base/223054
Log:
MFC r222586:
Fix an infinite loop in vm_object_page_clean() when the
filesystem returns permanent errors for some page writes.
To accomodate the stable/8 locking requirements, vm page queue lock
is taken around the loop in vnode_pager_undirty_pages() which modifies
m->dirty field.
Reviewed by: alc
Modified:
stable/8/sys/fs/nfsclient/nfs_clbio.c
stable/8/sys/fs/nwfs/nwfs_io.c
stable/8/sys/fs/smbfs/smbfs_io.c
stable/8/sys/nfsclient/nfs_bio.c
stable/8/sys/vm/vm_object.c
stable/8/sys/vm/vnode_pager.c
stable/8/sys/vm/vnode_pager.h
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
Modified: stable/8/sys/fs/nfsclient/nfs_clbio.c
==============================================================================
--- stable/8/sys/fs/nfsclient/nfs_clbio.c Mon Jun 13 18:27:09 2011 (r223053)
+++ stable/8/sys/fs/nfsclient/nfs_clbio.c Mon Jun 13 19:33:13 2011 (r223054)
@@ -298,7 +298,7 @@ ncl_putpages(struct vop_putpages_args *a
}
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.
@@ -341,16 +341,9 @@ ncl_putpages(struct vop_putpages_args *a
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];
}
Modified: stable/8/sys/fs/nwfs/nwfs_io.c
==============================================================================
--- stable/8/sys/fs/nwfs/nwfs_io.c Mon Jun 13 18:27:09 2011 (r223053)
+++ stable/8/sys/fs/nwfs/nwfs_io.c Mon Jun 13 19:33:13 2011 (r223054)
@@ -553,7 +553,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);
@@ -578,15 +578,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;
- vm_page_lock_queues();
- for (i = 0; i < nwritten; i++) {
- rtvals[i] = VM_PAGER_OK;
- vm_page_undirty(pages[i]);
- }
- vm_page_unlock_queues();
- }
+ if (!error)
+ vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
return rtvals[0];
#endif /* NWFS_RWCACHE */
}
Modified: stable/8/sys/fs/smbfs/smbfs_io.c
==============================================================================
--- stable/8/sys/fs/smbfs/smbfs_io.c Mon Jun 13 18:27:09 2011 (r223053)
+++ stable/8/sys/fs/smbfs/smbfs_io.c Mon Jun 13 19:33:13 2011 (r223054)
@@ -618,7 +618,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);
@@ -648,15 +648,8 @@ smbfs_putpages(ap)
relpbuf(bp, &smbfs_pbuf_freecnt);
- if (!error) {
- int nwritten = round_page(count - uio.uio_resid) / PAGE_SIZE;
- vm_page_lock_queues();
- for (i = 0; i < nwritten; i++) {
- rtvals[i] = VM_PAGER_OK;
- vm_page_undirty(pages[i]);
- }
- vm_page_unlock_queues();
- }
+ if (!error)
+ vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
return rtvals[0];
#endif /* SMBFS_RWGENERIC */
}
Modified: stable/8/sys/nfsclient/nfs_bio.c
==============================================================================
--- stable/8/sys/nfsclient/nfs_bio.c Mon Jun 13 18:27:09 2011 (r223053)
+++ stable/8/sys/nfsclient/nfs_bio.c Mon Jun 13 19:33:13 2011 (r223054)
@@ -295,7 +295,7 @@ nfs_putpages(struct vop_putpages_args *a
}
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.
@@ -339,11 +339,7 @@ nfs_putpages(struct vop_putpages_args *a
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);
}
Modified: stable/8/sys/vm/vm_object.c
==============================================================================
--- stable/8/sys/vm/vm_object.c Mon Jun 13 18:27:09 2011 (r223053)
+++ stable/8/sys/vm/vm_object.c Mon Jun 13 19:33:13 2011 (r223054)
@@ -843,6 +843,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);
}
vm_page_unlock_queues();
Modified: stable/8/sys/vm/vnode_pager.c
==============================================================================
--- stable/8/sys/vm/vnode_pager.c Mon Jun 13 18:27:09 2011 (r223053)
+++ stable/8/sys/vm/vnode_pager.c Mon Jun 13 19:33:13 2011 (r223054)
@@ -1080,7 +1080,7 @@ vnode_pager_generic_putpages(vp, m, byte
count = bytecount / PAGE_SIZE;
for (i = 0; i < count; i++)
- rtvals[i] = VM_PAGER_AGAIN;
+ rtvals[i] = VM_PAGER_ERROR;
if ((int64_t)m[0]->pindex < 0) {
printf("vnode_pager_putpages: attempt to write meta-data!!! -- 0x%lx(%lx)\n",
@@ -1171,3 +1171,22 @@ vnode_pager_generic_putpages(vp, m, byte
}
return rtvals[0];
}
+
+void
+vnode_pager_undirty_pages(vm_page_t *ma, int *rtvals, int written)
+{
+ int i, pos;
+
+ vm_page_lock_queues();
+ 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);
+ }
+ }
+ vm_page_unlock_queues();
+}
Modified: stable/8/sys/vm/vnode_pager.h
==============================================================================
--- stable/8/sys/vm/vnode_pager.h Mon Jun 13 18:27:09 2011 (r223053)
+++ stable/8/sys/vm/vnode_pager.h Mon Jun 13 19:33:13 2011 (r223054)
@@ -49,5 +49,8 @@ int vnode_pager_generic_getpages(struct
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_ */
More information about the svn-src-all
mailing list