diff options
author | rmacklem <rmacklem@FreeBSD.org> | 2012-06-18 22:17:28 +0000 |
---|---|---|
committer | rmacklem <rmacklem@FreeBSD.org> | 2012-06-18 22:17:28 +0000 |
commit | 24def143f7e068fffdacb2e1e4f46941b4ce5dec (patch) | |
tree | c435e72adcc3d3f414fe21dc019ac70b87d618d2 | |
parent | 4eede7506a622bcd2565763d6252acab3158d730 (diff) | |
download | FreeBSD-src-24def143f7e068fffdacb2e1e4f46941b4ce5dec.zip FreeBSD-src-24def143f7e068fffdacb2e1e4f46941b4ce5dec.tar.gz |
Fix the NFSv4 client for the case where mmap'd files are
written, but not msync'd by a process. A VOP_PUTPAGES()
called when VOP_RECLAIM() happens will usually fail, since
the NFSv4 Open has already been closed by VOP_INACTIVE().
Add a vm_object_page_clean() call to the NFSv4 client's
VOP_INACTIVE(), so that the write happens before the NFSv4
Open is closed. kib@ suggested using vgone() instead and
I will explore this, but this patch fixes things in the
meantime. For some reason, the VOP_PUTPAGES() is still
attaempted in VOP_RECLAIM(), but having this fail doesn't
cause any problems except a "stateid0 in write" being logged.
Reviewed by: kib
MFC after: 1 week
-rw-r--r-- | sys/fs/nfsclient/nfs_clnode.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/sys/fs/nfsclient/nfs_clnode.c b/sys/fs/nfsclient/nfs_clnode.c index 087858d..d721931 100644 --- a/sys/fs/nfsclient/nfs_clnode.c +++ b/sys/fs/nfsclient/nfs_clnode.c @@ -210,18 +210,28 @@ ncl_inactive(struct vop_inactive_args *ap) struct nfsnode *np; struct sillyrename *sp; struct vnode *vp = ap->a_vp; + boolean_t retv; np = VTONFS(vp); if (NFS_ISV4(vp) && vp->v_type == VREG) { /* * Since mmap()'d files do I/O after VOP_CLOSE(), the NFSv4 - * Close operations are delayed until now. Any dirty buffers - * must be flushed before the close, so that the stateid is - * available for the writes. + * Close operations are delayed until now. Any dirty + * buffers/pages must be flushed before the close, so that the + * stateid is available for the writes. */ - (void) ncl_flush(vp, MNT_WAIT, NULL, ap->a_td, 1, 0); - (void) nfsrpc_close(vp, 1, ap->a_td); + if (vp->v_object != NULL) { + VM_OBJECT_LOCK(vp->v_object); + retv = vm_object_page_clean(vp->v_object, 0, 0, + OBJPC_SYNC); + VM_OBJECT_UNLOCK(vp->v_object); + } else + retv = TRUE; + if (retv == TRUE) { + (void)ncl_flush(vp, MNT_WAIT, NULL, ap->a_td, 1, 0); + (void)nfsrpc_close(vp, 1, ap->a_td); + } } mtx_lock(&np->n_mtx); |