Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 21 Jun 2015 10:30:34 -0400 (EDT)
From:      Rick Macklem <rmacklem@uoguelph.ca>
To:        "alex.burlyga.ietf alex.burlyga.ietf" <alex.burlyga.ietf@gmail.com>
Cc:        freebsd-fs@freebsd.org
Subject:   Re: [nfs][client] - Question about handling of the NFS3_EEXIST error in SYMLINK rpc
Message-ID:  <1969046464.61534041.1434897034960.JavaMail.root@uoguelph.ca>
In-Reply-To: <CA%2BJhTNTSC-xPVdpUGcQemVMLUwuQB6D8-3d2HD6WjU%2Bjd1SMNQ@mail.gmail.com>

index | next in thread | previous in thread | raw e-mail

[-- Attachment #1 --]
Alex Burlyga wrote:
> Hi,
> 
> NFS client code in nfsrpc_symlink() masks server returned NFS3_EEXIST
> error
> code
> by returning 0 to the upper layers. I'm assuming this was an attempt
> to
> work around
> some server's broken replay cache out there, however, it breaks a
> more
> common
> case where server is returning EEXIST for legitimate reason and
> application
> is expecting this error code and equipped to deal with it.
> 
> To fix it I see three ways of doing this:
>  * Remove offending code
>  * Make it optional, sysctl?
>  * On NFS3_EEXIST send READLINK rpc to make sure symlink content is
>  right
> 
> Which of the ways will maximize the chances of getting this fix
> upstream?
> 
I've attached a patch for testing/review that does essentially #2.
It has no effect on trivial tests, since the syscall does a Lookup
before trying to create the symlink and fails with EEXIST.
Do you have a case where competing clients are trying to create
the symlink or something like that, which runs into this?

Please test the attached patch, since I don't know how to do that, rick

> One more point, old client circa FreeBSD 7.0 does not exhibit this
> problem.
> 
> Alex
> _______________________________________________
> freebsd-fs@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-fs
> To unsubscribe, send any mail to "freebsd-fs-unsubscribe@freebsd.org"
> 

[-- Attachment #2 --]
--- fs/nfsclient/nfs_clrpcops.c.sav2	2015-06-21 09:27:38.640947000 -0400
+++ fs/nfsclient/nfs_clrpcops.c	2015-06-21 09:53:42.723085000 -0400
@@ -46,6 +46,13 @@ __FBSDID("$FreeBSD: head/sys/fs/nfsclien
 #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);
 }
help

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