Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 31 Jul 2011 20:06:11 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r224554 - head/sys/fs/nfsserver
Message-ID:  <201107312006.p6VK6Cuq061547@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Sun Jul 31 20:06:11 2011
New Revision: 224554
URL: http://svn.freebsd.org/changeset/base/224554

Log:
  Fix rename in the new NFS server so that it does not require a
  recursive vnode lock on the directory for the case where the
  new file name is in the same directory as the old one. The patch
  handles this as a special case, recognized by the new directory
  having the same file handle as the old one and just VREF()s the old
  dir vnode for this case, instead of doing a second VFS_FHTOVP() to get it.
  This is required so that the server will work for file systems like
  msdosfs, that do not support recursive vnode locking.
  This problem was discovered during recent testing by pho@
  when exporting an msdosfs file system via the new NFS server.
  
  Tested by:	pho
  Reviewed by:	zkirsch
  Approved by:	re (kib)
  MFC after:	2 weeks

Modified:
  head/sys/fs/nfsserver/nfs_nfsdserv.c

Modified: head/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdserv.c	Sun Jul 31 18:34:38 2011	(r224553)
+++ head/sys/fs/nfsserver/nfs_nfsdserv.c	Sun Jul 31 20:06:11 2011	(r224554)
@@ -1425,6 +1425,7 @@ nfsrvd_rename(struct nfsrv_descript *nd,
 	struct nfsrvfh tfh;
 	char *bufp, *tbufp = NULL;
 	u_long *hashp;
+	fhandle_t fh;
 
 	if (nd->nd_repstat) {
 		nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
@@ -1450,19 +1451,34 @@ nfsrvd_rename(struct nfsrv_descript *nd,
 		tnes = *toexp;
 		tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred, p, 0);
 	} else {
+		tfh.nfsrvfh_len = 0;
 		error = nfsrv_mtofh(nd, &tfh);
+		if (error == 0)
+			error = nfsvno_getfh(dp, &fh, p);
 		if (error) {
 			vput(dp);
 			/* todp is always NULL except NFSv4 */
 			nfsvno_relpathbuf(&fromnd);
 			goto out;
 		}
-		nd->nd_cred->cr_uid = nd->nd_saveduid;
-		nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, NULL, 0, p);
-		if (tdp) {
+
+		/* If this is the same file handle, just VREF() the vnode. */
+		if (tfh.nfsrvfh_len == NFSX_MYFH &&
+		    !NFSBCMP(tfh.nfsrvfh_data, &fh, NFSX_MYFH)) {
+			VREF(dp);
+			tdp = dp;
+			tnes = *exp;
 			tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred,
 			    p, 1);
-			NFSVOPUNLOCK(tdp, 0);
+		} else {
+			nd->nd_cred->cr_uid = nd->nd_saveduid;
+			nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, NULL,
+			    0, p);
+			if (tdp) {
+				tdirfor_ret = nfsvno_getattr(tdp, &tdirfor,
+				    nd->nd_cred, p, 1);
+				NFSVOPUNLOCK(tdp, 0);
+			}
 		}
 	}
 	NFSNAMEICNDSET(&tond.ni_cnd, nd->nd_cred, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART);



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