aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-07 16:39:06 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-04-02 12:27:13 -0400
commit6e8768d198a2ea5f31dbd2fe679a62c605fcdbbd (patch)
tree4ce2349bbf32cb3d899bf613ead396f57dc72d7d
parent5353a89765846be06f238a00ce9b38de14f69281 (diff)
NFSv4: Return the delegation if the server returns NFS4ERR_OPENMODE
commit 3114ea7a24d3264c090556a2444fc6d2c06176d4 upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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 414ed1d27c9..e1c1365ba83 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -209,6 +209,7 @@ struct nfs4_exception {
209 long timeout; 209 long timeout;
210 int retry; 210 int retry;
211 struct nfs4_state *state; 211 struct nfs4_state *state;
212 struct inode *inode;
212}; 213};
213 214
214struct nfs4_state_recovery_ops { 215struct nfs4_state_recovery_ops {
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ae317fd9d24..301b0c95dcb 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -254,18 +254,28 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
254{ 254{
255 struct nfs_client *clp = server->nfs_client; 255 struct nfs_client *clp = server->nfs_client;
256 struct nfs4_state *state = exception->state; 256 struct nfs4_state *state = exception->state;
257 struct inode *inode = exception->inode;
257 int ret = errorcode; 258 int ret = errorcode;
258 259
259 exception->retry = 0; 260 exception->retry = 0;
260 switch(errorcode) { 261 switch(errorcode) {
261 case 0: 262 case 0:
262 return 0; 263 return 0;
264 case -NFS4ERR_OPENMODE:
265 if (nfs_have_delegation(inode, FMODE_READ)) {
266 nfs_inode_return_delegation(inode);
267 exception->retry = 1;
268 return 0;
269 }
270 if (state == NULL)
271 break;
272 nfs4_schedule_stateid_recovery(server, state);
273 goto wait_on_recovery;
263 case -NFS4ERR_DELEG_REVOKED: 274 case -NFS4ERR_DELEG_REVOKED:
264 case -NFS4ERR_ADMIN_REVOKED: 275 case -NFS4ERR_ADMIN_REVOKED:
265 case -NFS4ERR_BAD_STATEID: 276 case -NFS4ERR_BAD_STATEID:
266 if (state != NULL) 277 if (state != NULL)
267 nfs_remove_bad_delegation(state->inode); 278 nfs_remove_bad_delegation(state->inode);
268 case -NFS4ERR_OPENMODE:
269 if (state == NULL) 279 if (state == NULL)
270 break; 280 break;
271 nfs4_schedule_stateid_recovery(server, state); 281 nfs4_schedule_stateid_recovery(server, state);
@@ -1870,6 +1880,7 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
1870 struct nfs_server *server = NFS_SERVER(inode); 1880 struct nfs_server *server = NFS_SERVER(inode);
1871 struct nfs4_exception exception = { 1881 struct nfs4_exception exception = {
1872 .state = state, 1882 .state = state,
1883 .inode = inode,
1873 }; 1884 };
1874 int err; 1885 int err;
1875 do { 1886 do {