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)
{
struct inode *inode = state->inode;
struct nfs4_state_owner *owner = state->owner;
struct nfs4_exception exception = { };
int status = 0;
if (!atomic_dec_and_lock(&state->count, &inode->i_lock)) {
......@@ -427,15 +428,17 @@ __nfs4_put_open_state(struct nfs4_state *state)
spin_unlock(&inode->i_lock);
list_del(&state->open_states);
if (state->state != 0) {
do {
status = nfs4_do_close(inode, state);
for (;;) {
status = _nfs4_do_close(inode, state);
up(&owner->so_sema);
if (!status)
break;
up(&owner->so_sema);
status = nfs4_handle_error(NFS_SERVER(inode), status);
status = nfs4_handle_exception(NFS_SERVER(inode), status, &exception);
if (!exception.retry)
break;
down(&owner->so_sema);
} while (!status);
}
} else
up(&owner->so_sema);
nfs4_free_open_state(state);
nfs4_put_state_owner(owner);
......@@ -453,6 +456,7 @@ nfs4_close_state(struct nfs4_state *state, mode_t mode)
{
struct inode *inode = state->inode;
struct nfs4_state_owner *owner = state->owner;
struct nfs4_exception exception = { };
int newstate;
int status = 0;
......@@ -477,17 +481,17 @@ nfs4_close_state(struct nfs4_state *state, mode_t mode)
if (state->state == newstate)
break;
if (newstate != 0)
status = nfs4_do_downgrade(inode, state, newstate);
status = _nfs4_do_downgrade(inode, state, newstate);
else
status = nfs4_do_close(inode, state);
status = _nfs4_do_close(inode, state);
if (!status) {
state->state = newstate;
break;
}
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);
} while (!status);
} while (exception.retry);
__nfs4_put_open_state(state);
}
......
......@@ -629,6 +629,11 @@ struct nfs4_state {
};
struct nfs4_exception {
long timeout;
int retry;
};
extern struct dentry_operations nfs4_dentry_operations;
extern struct inode_operations nfs4_dir_inode_operations;
......@@ -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_proc_async_renew(struct nfs4_client *);
extern int nfs4_proc_renew(struct nfs4_client *);
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_close(struct inode *, struct nfs4_state *);
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 struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
extern int nfs4_open_revalidate(struct inode *, struct dentry *, int);
extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *);
/* nfs4renewd.c */
extern void nfs4_schedule_state_renewal(struct nfs4_client *);
......@@ -663,7 +669,6 @@ extern void nfs4_put_open_state(struct nfs4_state *);
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 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 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);
......
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