summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-18 23:20:21 +0200
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-18 23:20:21 +0200
commit550f57470c6506f5ef3c708335dea6bd48bf3dc4 (patch)
treebe34cc170cce1e103baec1976f7903528eb4ff4d /fs
parentNFSv4: If a delegated open fails, ensure that we return the delegation (diff)
downloadlinux-550f57470c6506f5ef3c708335dea6bd48bf3dc4.tar.xz
linux-550f57470c6506f5ef3c708335dea6bd48bf3dc4.zip
NFSv4: Ensure that we recover from the OPEN + OPEN_CONFIRM BAD_STATEID race
If the server is in the unconfirmed OPEN state for a given open owner and receives a second OPEN for the same open owner, it will cancel the state of the first request and set up an OPEN_CONFIRM for the second. This can cause a race that is discussed in rfc3530 on page 181. The following patch allows the client to recover by retrying the original open request. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/nfs4proc.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a8be9af610ac..ff378126ccd7 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -785,6 +785,16 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry,
exception.retry = 1;
continue;
}
+ /*
+ * BAD_STATEID on OPEN means that the server cancelled our
+ * state before it received the OPEN_CONFIRM.
+ * Recover by retrying the request as per the discussion
+ * on Page 181 of RFC3530.
+ */
+ if (status == -NFS4ERR_BAD_STATEID) {
+ exception.retry = 1;
+ continue;
+ }
res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir),
status, &exception));
} while (exception.retry);