svn commit: r253124 - stable/9/sys/fs/nfsclient
Rick Macklem
rmacklem at FreeBSD.org
Wed Jul 10 00:31:29 UTC 2013
Author: rmacklem
Date: Wed Jul 10 00:31:28 2013
New Revision: 253124
URL: http://svnweb.freebsd.org/changeset/base/253124
Log:
MFC: r252528
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 (actually
pre-r248567, r248581, r248567 for the new client) such that the call to
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.
A better solution might be to replace the mutex with a sleep lock,
but that is a non-trivial conversion, so this fix is hoped to be
sufficient in the meantime.
Tested by: remy.nonnenmacher at activnetworks.com
Modified:
stable/9/sys/fs/nfsclient/nfs_clport.c
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/fs/ (props changed)
Modified: stable/9/sys/fs/nfsclient/nfs_clport.c
==============================================================================
--- stable/9/sys/fs/nfsclient/nfs_clport.c Tue Jul 9 23:54:43 2013 (r253123)
+++ stable/9/sys/fs/nfsclient/nfs_clport.c Wed Jul 10 00:31:28 2013 (r253124)
@@ -439,6 +439,7 @@ nfscl_loadattrcache(struct vnode **vpp,
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
@@ -450,12 +451,22 @@ nfscl_loadattrcache(struct vnode **vpp,
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;
}
More information about the svn-src-stable
mailing list