diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-10-18 17:20:21 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-10-18 17:20:21 -0400 |
commit | 550f57470c6506f5ef3c708335dea6bd48bf3dc4 (patch) | |
tree | be34cc170cce1e103baec1976f7903528eb4ff4d /fs/nfs/nfs4proc.c | |
parent | b8e5c4c2978fa666287525a9de2fa648a7581262 (diff) |
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/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index a8be9af610a..ff378126ccd 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, | |||
785 | exception.retry = 1; | 785 | exception.retry = 1; |
786 | continue; | 786 | continue; |
787 | } | 787 | } |
788 | /* | ||
789 | * BAD_STATEID on OPEN means that the server cancelled our | ||
790 | * state before it received the OPEN_CONFIRM. | ||
791 | * Recover by retrying the request as per the discussion | ||
792 | * on Page 181 of RFC3530. | ||
793 | */ | ||
794 | if (status == -NFS4ERR_BAD_STATEID) { | ||
795 | exception.retry = 1; | ||
796 | continue; | ||
797 | } | ||
788 | res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir), | 798 | res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir), |
789 | status, &exception)); | 799 | status, &exception)); |
790 | } while (exception.retry); | 800 | } while (exception.retry); |