Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Jul 2013 00:31:29 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r253124 - stable/9/sys/fs/nfsclient
Message-ID:  <201307100031.r6A0VTLC006222@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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@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;
 		}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201307100031.r6A0VTLC006222>