Author: rmacklem Date: Thu Jul 11 01:30:24 2013 New Revision: 253177 URL: http://svnweb.freebsd.org/changeset/base/253177
Log: MFC: r252673 A problem with the old NFS client where large writes to large files would sometimes result in a corrupted file was reported via email. This problem appears to have been caused by r251719 (reverting r251719 fixed the problem). Although I have not been able to reproduce this problem, I suspect it is caused by another thread increasing np->n_size after the mtx_unlock(&np->n_mtx) but before the vnode_pager_setsize() call. Since the np->n_mtx mutex serializes updates to np->n_size, doing the vnode_pager_setsize() with the mutex locked appears to avoid the problem. Unfortunately, vnode_pager_setsize() where the new size is smaller, cannot be called with a mutex held. This patch returns the semantics to be close to pre-r251719 such that the call to the vnode_pager_setsize() is only delayed until after the mutex is unlocked when np->n_size is shrinking. Since the file is growing when being written, I believe this will fix the corruption. Tested by: remy.nonnenmac...@activnetworks.com Modified: stable/9/sys/nfsclient/nfs_subs.c Directory Properties: stable/9/sys/ (props changed) Modified: stable/9/sys/nfsclient/nfs_subs.c ============================================================================== --- stable/9/sys/nfsclient/nfs_subs.c Wed Jul 10 23:14:24 2013 (r253176) +++ stable/9/sys/nfsclient/nfs_subs.c Thu Jul 11 01:30:24 2013 (r253177) @@ -595,6 +595,7 @@ nfs_loadattrcache(struct vnode **vpp, st vap->va_size = np->n_size; np->n_attrstamp = 0; KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); + vnode_pager_setsize(vp, np->n_size); } else if (np->n_flag & NMODIFIED) { /* * We've modified the file: Use the larger @@ -606,12 +607,22 @@ nfs_loadattrcache(struct vnode **vpp, st np->n_size = vap->va_size; np->n_flag |= NSIZECHANGED; } + vnode_pager_setsize(vp, np->n_size); + } else if (vap->va_size < np->n_size) { + /* + * When shrinking the size, the call to + * vnode_pager_setsize() cannot be done + * with the mutex held, so delay it until + * after the mtx_unlock call. + */ + nsize = np->n_size = vap->va_size; + np->n_flag |= NSIZECHANGED; + setnsize = 1; } else { np->n_size = vap->va_size; np->n_flag |= NSIZECHANGED; + vnode_pager_setsize(vp, np->n_size); } - setnsize = 1; - nsize = vap->va_size; } else { np->n_size = vap->va_size; } _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"