aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-07 16:39:06 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-07 17:11:19 -0500
commit3114ea7a24d3264c090556a2444fc6d2c06176d4 (patch)
tree50b8f1f3f43c6eb93093abec368c070e2efdc7d2 /fs
parentcf470c3e004efe16d73dc8ba9b29bdc9a5327cda (diff)
NFSv4: Return the delegation if the server returns NFS4ERR_OPENMODE
If a setattr() fails because of an NFS4ERR_OPENMODE error, it is probably due to us holding a read delegation. Ensure that the recovery routines return that delegation in this case. Reported-by: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Cc: stable@vger.kernel.org
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/nfs4_fs.h1
-rw-r--r--fs/nfs/nfs4proc.c13
2 files changed, 13 insertions, 1 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 026878cb2698..d1989e3f23c3 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -182,6 +182,7 @@ struct nfs4_exception {
182 long timeout; 182 long timeout;
183 int retry; 183 int retry;
184 struct nfs4_state *state; 184 struct nfs4_state *state;
185 struct inode *inode;
185}; 186};
186 187
187struct nfs4_state_recovery_ops { 188struct nfs4_state_recovery_ops {
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 32e0d08a9771..a8dd04db764f 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -262,18 +262,28 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
262{ 262{
263 struct nfs_client *clp = server->nfs_client; 263 struct nfs_client *clp = server->nfs_client;
264 struct nfs4_state *state = exception->state; 264 struct nfs4_state *state = exception->state;
265 struct inode *inode = exception->inode;
265 int ret = errorcode; 266 int ret = errorcode;
266 267
267 exception->retry = 0; 268 exception->retry = 0;
268 switch(errorcode) { 269 switch(errorcode) {
269 case 0: 270 case 0:
270 return 0; 271 return 0;
272 case -NFS4ERR_OPENMODE:
273 if (nfs_have_delegation(inode, FMODE_READ)) {
274 nfs_inode_return_delegation(inode);
275 exception->retry = 1;
276 return 0;
277 }
278 if (state == NULL)
279 break;
280 nfs4_schedule_stateid_recovery(server, state);
281 goto wait_on_recovery;
271 case -NFS4ERR_DELEG_REVOKED: 282 case -NFS4ERR_DELEG_REVOKED:
272 case -NFS4ERR_ADMIN_REVOKED: 283 case -NFS4ERR_ADMIN_REVOKED:
273 case -NFS4ERR_BAD_STATEID: 284 case -NFS4ERR_BAD_STATEID:
274 if (state != NULL) 285 if (state != NULL)
275 nfs_remove_bad_delegation(state->inode); 286 nfs_remove_bad_delegation(state->inode);
276 case -NFS4ERR_OPENMODE:
277 if (state == NULL) 287 if (state == NULL)
278 break; 288 break;
279 nfs4_schedule_stateid_recovery(server, state); 289 nfs4_schedule_stateid_recovery(server, state);
@@ -1939,6 +1949,7 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
1939 struct nfs_server *server = NFS_SERVER(inode); 1949 struct nfs_server *server = NFS_SERVER(inode);
1940 struct nfs4_exception exception = { 1950 struct nfs4_exception exception = {
1941 .state = state, 1951 .state = state,
1952 .inode = inode,
1942 }; 1953 };
1943 int err; 1954 int err;
1944 do { 1955 do {