link() not increasing link count on NFS server
Robert Watson
rwatson at FreeBSD.org
Fri Nov 16 06:38:06 PST 2007
On Thu, 15 Nov 2007, Mohan Srinivasan wrote:
> The code you cite, which launches a lookup on the receipt of an EEXIST in
> nfs_link() is a horrible hack that needs to be removed. I always wanted to
> remove it but did not want to stir up controversy.
>
> The logic predates the NFS/UDP duplicate request cache, which all NFS
> servers will support. The NFS dupreq cache caches the replies for
> non-idempotent operations and will replay the cached response if a
> non-idenpotent operation is retransmitted. This works around spurious errors
> in the event the NFS response was lost, of course. The dupreq cache appeared
> in most NFS server implementations in late 1989.
>
> There is no justification for the logic that the FreeBSD NFS client has at
> the end of these ops. In fact it breaks more things that it fixes. At
> Yahoo!, we had a group that was doing locking by creating lockfiles and
> checking for the existence of these lockfiles. As you can imagine, that
> application broke over FreeBSD NFS. I worked around this in FreeBSD's Yahoo!
> implementation.
>
> I have not looked at the original link bug reported, but I would
> wholeheartedly endorse ripping out the "launch a lookup on a an error in
> these ops" in all of the NFS ops and just return the error/or success
> returned by the original NFS op.
OK, I've attached an initial patch that does this -- we still need to keep the
lookup code for NFSv2, where the file handle of the new node isn't returned
with the reply, but I drop the EEXIST handling cases. Does this look
reasonable to you? I'm not set up to easily test this scenario, however.
Robert N M Watson
Computer Laboratory
University of Cambridge
Index: nfs_vnops.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/nfsclient/nfs_vnops.c,v
retrieving revision 1.276
diff -u -r1.276 nfs_vnops.c
--- nfs_vnops.c 1 Jun 2007 01:12:44 -0000 1.276
+++ nfs_vnops.c 16 Nov 2007 14:35:59 -0000
@@ -1769,11 +1769,6 @@
VTONFS(vp)->n_attrstamp = 0;
if (!wccflag)
VTONFS(tdvp)->n_attrstamp = 0;
- /*
- * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
- */
- if (error == EEXIST)
- error = 0;
return (error);
}
@@ -1837,17 +1832,9 @@
nfsmout:
/*
- * If we get an EEXIST error, silently convert it to no-error
- * in case of an NFS retry.
- */
- if (error == EEXIST)
- error = 0;
-
- /*
- * If we do not have (or no longer have) an error, and we could
- * not extract the newvp from the response due to the request being
- * NFSv2 or the error being EEXIST. We have to do a lookup in order
- * to obtain a newvp to return.
+ * If we do not have an error and we could not extract the newvp from
+ * the response due to the request being NFSv2, we have to do a
+ * lookup in order to obtain a newvp to return.
*/
if (error == 0 && newvp == NULL) {
struct nfsnode *np = NULL;
@@ -1925,15 +1912,7 @@
mtx_unlock(&(VTONFS(dvp))->n_mtx);
if (!wccflag)
VTONFS(dvp)->n_attrstamp = 0;
- /*
- * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
- * if we can succeed in looking up the directory.
- */
- if (error == EEXIST || (!error && !gotvp)) {
- if (newvp) {
- vput(newvp);
- newvp = NULL;
- }
+ if (error == 0 && newvp == NULL) {
error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
cnp->cn_thread, &np);
if (!error) {
More information about the freebsd-current
mailing list