Commit b6b42cec authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: Fix up the exception handling. Ensure we always handle

   NFS4ERR_DELAY properly.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@fys.uio.no>
parent ecebe0fc
This diff is collapsed.
...@@ -416,6 +416,7 @@ __nfs4_put_open_state(struct nfs4_state *state) ...@@ -416,6 +416,7 @@ __nfs4_put_open_state(struct nfs4_state *state)
{ {
struct inode *inode = state->inode; struct inode *inode = state->inode;
struct nfs4_state_owner *owner = state->owner; struct nfs4_state_owner *owner = state->owner;
struct nfs4_exception exception = { };
int status = 0; int status = 0;
if (!atomic_dec_and_lock(&state->count, &inode->i_lock)) { if (!atomic_dec_and_lock(&state->count, &inode->i_lock)) {
...@@ -427,15 +428,17 @@ __nfs4_put_open_state(struct nfs4_state *state) ...@@ -427,15 +428,17 @@ __nfs4_put_open_state(struct nfs4_state *state)
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
list_del(&state->open_states); list_del(&state->open_states);
if (state->state != 0) { if (state->state != 0) {
do { for (;;) {
status = nfs4_do_close(inode, state); status = _nfs4_do_close(inode, state);
up(&owner->so_sema);
if (!status) if (!status)
break; break;
up(&owner->so_sema); status = nfs4_handle_exception(NFS_SERVER(inode), status, &exception);
status = nfs4_handle_error(NFS_SERVER(inode), status); if (!exception.retry)
break;
down(&owner->so_sema); down(&owner->so_sema);
} while (!status);
} }
} else
up(&owner->so_sema); up(&owner->so_sema);
nfs4_free_open_state(state); nfs4_free_open_state(state);
nfs4_put_state_owner(owner); nfs4_put_state_owner(owner);
...@@ -453,6 +456,7 @@ nfs4_close_state(struct nfs4_state *state, mode_t mode) ...@@ -453,6 +456,7 @@ nfs4_close_state(struct nfs4_state *state, mode_t mode)
{ {
struct inode *inode = state->inode; struct inode *inode = state->inode;
struct nfs4_state_owner *owner = state->owner; struct nfs4_state_owner *owner = state->owner;
struct nfs4_exception exception = { };
int newstate; int newstate;
int status = 0; int status = 0;
...@@ -477,17 +481,17 @@ nfs4_close_state(struct nfs4_state *state, mode_t mode) ...@@ -477,17 +481,17 @@ nfs4_close_state(struct nfs4_state *state, mode_t mode)
if (state->state == newstate) if (state->state == newstate)
break; break;
if (newstate != 0) if (newstate != 0)
status = nfs4_do_downgrade(inode, state, newstate); status = _nfs4_do_downgrade(inode, state, newstate);
else else
status = nfs4_do_close(inode, state); status = _nfs4_do_close(inode, state);
if (!status) { if (!status) {
state->state = newstate; state->state = newstate;
break; break;
} }
up(&owner->so_sema); up(&owner->so_sema);
status = nfs4_handle_error(NFS_SERVER(inode), status); status = nfs4_handle_exception(NFS_SERVER(inode), status, &exception);
down(&owner->so_sema); down(&owner->so_sema);
} while (!status); } while (exception.retry);
__nfs4_put_open_state(state); __nfs4_put_open_state(state);
} }
......
...@@ -629,6 +629,11 @@ struct nfs4_state { ...@@ -629,6 +629,11 @@ struct nfs4_state {
}; };
struct nfs4_exception {
long timeout;
int retry;
};
extern struct dentry_operations nfs4_dentry_operations; extern struct dentry_operations nfs4_dentry_operations;
extern struct inode_operations nfs4_dir_inode_operations; extern struct inode_operations nfs4_dir_inode_operations;
...@@ -638,11 +643,12 @@ extern int nfs4_proc_setclientid_confirm(struct nfs4_client *); ...@@ -638,11 +643,12 @@ extern int nfs4_proc_setclientid_confirm(struct nfs4_client *);
extern int nfs4_open_reclaim(struct nfs4_state_owner *, struct nfs4_state *); extern int nfs4_open_reclaim(struct nfs4_state_owner *, struct nfs4_state *);
extern int nfs4_proc_async_renew(struct nfs4_client *); extern int nfs4_proc_async_renew(struct nfs4_client *);
extern int nfs4_proc_renew(struct nfs4_client *); extern int nfs4_proc_renew(struct nfs4_client *);
extern int nfs4_do_close(struct inode *, struct nfs4_state *); extern int _nfs4_do_close(struct inode *, struct nfs4_state *);
int nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode); extern int _nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode);
extern int nfs4_wait_clnt_recover(struct rpc_clnt *, struct nfs4_client *); extern int nfs4_wait_clnt_recover(struct rpc_clnt *, struct nfs4_client *);
extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
extern int nfs4_open_revalidate(struct inode *, struct dentry *, int); extern int nfs4_open_revalidate(struct inode *, struct dentry *, int);
extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *);
/* nfs4renewd.c */ /* nfs4renewd.c */
extern void nfs4_schedule_state_renewal(struct nfs4_client *); extern void nfs4_schedule_state_renewal(struct nfs4_client *);
...@@ -663,7 +669,6 @@ extern void nfs4_put_open_state(struct nfs4_state *); ...@@ -663,7 +669,6 @@ extern void nfs4_put_open_state(struct nfs4_state *);
extern void nfs4_close_state(struct nfs4_state *, mode_t); extern void nfs4_close_state(struct nfs4_state *, mode_t);
extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode); extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode);
extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp); extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp);
extern int nfs4_handle_error(struct nfs_server *, int);
extern void nfs4_schedule_state_recovery(struct nfs4_client *); extern void nfs4_schedule_state_recovery(struct nfs4_client *);
extern struct nfs4_lock_state *nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t); extern struct nfs4_lock_state *nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t);
extern struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t); extern struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment