Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 3 Jul 2015 01:15:21 +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: r285066 - head/sys/fs/nfsclient
Message-ID:  <201507030115.t631FL6J020675@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Fri Jul  3 01:15:21 2015
New Revision: 285066
URL: https://svnweb.freebsd.org/changeset/base/285066

Log:
  Alex Burlyga reported a POLA violation for the new NFS client as
  compared to the old NFS client via email to the freebsd-fs@ mailing list.
  For the new client, when multiple clients attempted to create a symbolic
  link concurrently, more that one client would report success instead of
  EEXIST. This was caused by code in the new client that mapped EEXIST to
  OK assuming it was caused by a retried RPC request.
  Since the old client did not do this, the patch defaults to the old
  behaviour and permits the new behaviour to be enabled via a sysctl.
  
  Reported by:	alex.burlyga.ietf@gmail.com
  Tested by:	alex.burlyga.ietf@gmail.com
  MFC after:	2 weeks

Modified:
  head/sys/fs/nfsclient/nfs_clrpcops.c

Modified: head/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clrpcops.c	Fri Jul  3 00:37:16 2015	(r285065)
+++ head/sys/fs/nfsclient/nfs_clrpcops.c	Fri Jul  3 01:15:21 2015	(r285066)
@@ -46,6 +46,13 @@ __FBSDID("$FreeBSD$");
 #include "opt_inet6.h"
 
 #include <fs/nfs/nfsport.h>
+#include <sys/sysctl.h>
+
+SYSCTL_DECL(_vfs_nfs);
+
+static int	nfsignore_eexist = 0;
+SYSCTL_INT(_vfs_nfs, OID_AUTO, ignore_eexist, CTLFLAG_RW,
+    &nfsignore_eexist, 0, "NFS ignore EEXIST replies for mkdir/symlink");
 
 /*
  * Global variables
@@ -2530,8 +2537,12 @@ nfsrpc_symlink(vnode_t dvp, char *name, 
 	mbuf_freem(nd->nd_mrep);
 	/*
 	 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
+	 * Only do this if vfs.nfs.ignore_eexist is set.
+	 * Never do this for NFSv4.1 or later minor versions, since sessions
+	 * should guarantee "exactly once" RPC semantics.
 	 */
-	if (error == EEXIST)
+	if (error == EEXIST && nfsignore_eexist != 0 && (!NFSHASNFSV4(nmp) ||
+	    nmp->nm_minorvers == 0))
 		error = 0;
 	return (error);
 }
@@ -2550,10 +2561,12 @@ nfsrpc_mkdir(vnode_t dvp, char *name, in
 	nfsattrbit_t attrbits;
 	int error = 0;
 	struct nfsfh *fhp;
+	struct nfsmount *nmp;
 
 	*nfhpp = NULL;
 	*attrflagp = 0;
 	*dattrflagp = 0;
+	nmp = VFSTONFS(vnode_mount(dvp));
 	fhp = VTONFS(dvp)->n_fhp;
 	if (namelen > NFS_MAXNAMLEN)
 		return (ENAMETOOLONG);
@@ -2605,9 +2618,13 @@ nfsrpc_mkdir(vnode_t dvp, char *name, in
 nfsmout:
 	mbuf_freem(nd->nd_mrep);
 	/*
-	 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry.
+	 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
+	 * Only do this if vfs.nfs.ignore_eexist is set.
+	 * Never do this for NFSv4.1 or later minor versions, since sessions
+	 * should guarantee "exactly once" RPC semantics.
 	 */
-	if (error == EEXIST)
+	if (error == EEXIST && nfsignore_eexist != 0 && (!NFSHASNFSV4(nmp) ||
+	    nmp->nm_minorvers == 0))
 		error = 0;
 	return (error);
 }



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