NFSv41: Clean up slot table management

We no longer need to maintain a distinction between nfs41_sequence_done and
nfs41_sequence_free_slot.

This fixes a number of slot table leakages in the NFSv4.1 code.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
Trond Myklebust 2009-12-05 19:32:19 -05:00
parent f26468fb93
commit d61e612a72
5 changed files with 21 additions and 82 deletions

View File

@ -197,8 +197,7 @@ extern const u32 nfs41_maxwrite_overhead;
#endif #endif
/* nfs4proc.c */ /* nfs4proc.c */
extern void nfs4_restart_rpc(struct rpc_task *, const struct nfs_client *, extern void nfs4_restart_rpc(struct rpc_task *, const struct nfs_client *);
struct nfs4_sequence_res *);
#ifdef CONFIG_NFS_V4 #ifdef CONFIG_NFS_V4
extern struct rpc_procinfo nfs4_procedures[]; extern struct rpc_procinfo nfs4_procedures[];
#endif #endif
@ -275,20 +274,6 @@ extern int _nfs4_call_sync_session(struct nfs_server *server,
struct nfs4_sequence_res *res, struct nfs4_sequence_res *res,
int cache_reply); int cache_reply);
#ifdef CONFIG_NFS_V4_1
extern void nfs41_sequence_free_slot(const struct nfs_client *,
struct nfs4_sequence_res *res);
#endif /* CONFIG_NFS_V4_1 */
static inline void nfs4_sequence_free_slot(const struct nfs_client *clp,
struct nfs4_sequence_res *res)
{
#ifdef CONFIG_NFS_V4_1
if (nfs4_has_session(clp))
nfs41_sequence_free_slot(clp, res);
#endif /* CONFIG_NFS_V4_1 */
}
/* /*
* Determine the device name as a string * Determine the device name as a string
*/ */

View File

@ -341,15 +341,11 @@ nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid)
free_slotid, tbl->highest_used_slotid); free_slotid, tbl->highest_used_slotid);
} }
void nfs41_sequence_free_slot(const struct nfs_client *clp, static void nfs41_sequence_free_slot(const struct nfs_client *clp,
struct nfs4_sequence_res *res) struct nfs4_sequence_res *res)
{ {
struct nfs4_slot_table *tbl; struct nfs4_slot_table *tbl;
if (!nfs4_has_session(clp)) {
dprintk("%s: No session\n", __func__);
return;
}
tbl = &clp->cl_session->fc_slot_table; tbl = &clp->cl_session->fc_slot_table;
if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) { if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) {
/* just wake up the next guy waiting since /* just wake up the next guy waiting since
@ -407,7 +403,6 @@ static void nfs41_sequence_done(struct nfs_client *clp,
spin_unlock(&clp->cl_lock); spin_unlock(&clp->cl_lock);
/* Check sequence flags */ /* Check sequence flags */
nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
return;
} }
out: out:
/* The session may be reset by one of the error handlers. */ /* The session may be reset by one of the error handlers. */
@ -556,7 +551,6 @@ static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
struct nfs41_call_sync_data *data = calldata; struct nfs41_call_sync_data *data = calldata;
nfs41_sequence_done(data->clp, data->seq_res, task->tk_status); nfs41_sequence_done(data->clp, data->seq_res, task->tk_status);
nfs41_sequence_free_slot(data->clp, data->seq_res);
} }
struct rpc_call_ops nfs41_call_sync_ops = { struct rpc_call_ops nfs41_call_sync_ops = {
@ -632,12 +626,10 @@ static void nfs4_sequence_done(const struct nfs_server *server,
#endif /* CONFIG_NFS_V4_1 */ #endif /* CONFIG_NFS_V4_1 */
} }
void nfs4_restart_rpc(struct rpc_task *task, const struct nfs_client *clp, void nfs4_restart_rpc(struct rpc_task *task, const struct nfs_client *clp)
struct nfs4_sequence_res *res)
{ {
#ifdef CONFIG_NFS_V4_1 #ifdef CONFIG_NFS_V4_1
if (nfs4_has_session(clp)) { if (nfs4_has_session(clp)) {
nfs41_sequence_free_slot(clp, res);
rpc_restart_call_prepare(task); rpc_restart_call_prepare(task);
return; return;
} }
@ -645,15 +637,6 @@ void nfs4_restart_rpc(struct rpc_task *task, const struct nfs_client *clp,
rpc_restart_call(task); rpc_restart_call(task);
} }
/* no restart, therefore free slot here */
static void nfs4_sequence_done_free_slot(const struct nfs_server *server,
struct nfs4_sequence_res *res,
int rpc_status)
{
nfs4_sequence_done(server, res, rpc_status);
nfs4_sequence_free_slot(server->nfs_client, res);
}
static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
{ {
struct nfs_inode *nfsi = NFS_I(dir); struct nfs_inode *nfsi = NFS_I(dir);
@ -1350,8 +1333,8 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
data->rpc_status = task->tk_status; data->rpc_status = task->tk_status;
nfs4_sequence_done_free_slot(data->o_arg.server, &data->o_res.seq_res, nfs4_sequence_done(data->o_arg.server, &data->o_res.seq_res,
task->tk_status); task->tk_status);
if (RPC_ASSASSINATED(task)) if (RPC_ASSASSINATED(task))
return; return;
@ -1757,12 +1740,10 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
break; break;
default: default:
if (nfs4_async_handle_error(task, server, state) == -EAGAIN) { if (nfs4_async_handle_error(task, server, state) == -EAGAIN) {
nfs4_restart_rpc(task, server->nfs_client, nfs4_restart_rpc(task, server->nfs_client);
&calldata->res.seq_res);
return; return;
} }
} }
nfs4_sequence_free_slot(server->nfs_client, &calldata->res.seq_res);
nfs_refresh_inode(calldata->inode, calldata->res.fattr); nfs_refresh_inode(calldata->inode, calldata->res.fattr);
} }
@ -2553,7 +2534,6 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
nfs4_sequence_done(res->server, &res->seq_res, task->tk_status); nfs4_sequence_done(res->server, &res->seq_res, task->tk_status);
if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
return 0; return 0;
nfs4_sequence_free_slot(res->server->nfs_client, &res->seq_res);
update_changeattr(dir, &res->cinfo); update_changeattr(dir, &res->cinfo);
nfs_post_op_update_inode(dir, &res->dir_attr); nfs_post_op_update_inode(dir, &res->dir_attr);
return 1; return 1;
@ -2992,20 +2972,16 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
dprintk("--> %s\n", __func__); dprintk("--> %s\n", __func__);
/* nfs4_sequence_free_slot called in the read rpc_call_done */
nfs4_sequence_done(server, &data->res.seq_res, task->tk_status); nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) {
nfs4_restart_rpc(task, server->nfs_client, &data->res.seq_res); nfs4_restart_rpc(task, server->nfs_client);
return -EAGAIN; return -EAGAIN;
} }
nfs_invalidate_atime(data->inode); nfs_invalidate_atime(data->inode);
if (task->tk_status > 0) if (task->tk_status > 0)
renew_lease(server, data->timestamp); renew_lease(server, data->timestamp);
else if (task->tk_status < 0)
nfs4_sequence_free_slot(server->nfs_client, &data->res.seq_res);
return 0; return 0;
} }
@ -3019,13 +2995,11 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
{ {
struct inode *inode = data->inode; struct inode *inode = data->inode;
/* slot is freed in nfs_writeback_done */
nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res, nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res,
task->tk_status); task->tk_status);
if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) {
nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client, nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
&data->res.seq_res);
return -EAGAIN; return -EAGAIN;
} }
if (task->tk_status >= 0) { if (task->tk_status >= 0) {
@ -3053,12 +3027,9 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res, nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res,
task->tk_status); task->tk_status);
if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) {
nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client, nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
&data->res.seq_res);
return -EAGAIN; return -EAGAIN;
} }
nfs4_sequence_free_slot(NFS_SERVER(inode)->nfs_client,
&data->res.seq_res);
nfs_refresh_inode(inode, data->res.fattr); nfs_refresh_inode(inode, data->res.fattr);
return 0; return 0;
} }
@ -3509,8 +3480,8 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
{ {
struct nfs4_delegreturndata *data = calldata; struct nfs4_delegreturndata *data = calldata;
nfs4_sequence_done_free_slot(data->res.server, &data->res.seq_res, nfs4_sequence_done(data->res.server, &data->res.seq_res,
task->tk_status); task->tk_status);
data->rpc_status = task->tk_status; data->rpc_status = task->tk_status;
if (data->rpc_status == 0) if (data->rpc_status == 0)
@ -3768,11 +3739,8 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
default: default:
if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)
nfs4_restart_rpc(task, nfs4_restart_rpc(task,
calldata->server->nfs_client, calldata->server->nfs_client);
&calldata->res.seq_res);
} }
nfs4_sequence_free_slot(calldata->server->nfs_client,
&calldata->res.seq_res);
} }
static void nfs4_locku_prepare(struct rpc_task *task, void *data) static void nfs4_locku_prepare(struct rpc_task *task, void *data)
@ -3954,8 +3922,8 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
dprintk("%s: begin!\n", __func__); dprintk("%s: begin!\n", __func__);
nfs4_sequence_done_free_slot(data->server, &data->res.seq_res, nfs4_sequence_done(data->server, &data->res.seq_res,
task->tk_status); task->tk_status);
data->rpc_status = task->tk_status; data->rpc_status = task->tk_status;
if (RPC_ASSASSINATED(task)) if (RPC_ASSASSINATED(task))
@ -4425,10 +4393,9 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
rpc_delay(task, NFS4_POLL_RETRY_MIN); rpc_delay(task, NFS4_POLL_RETRY_MIN);
task->tk_status = 0; task->tk_status = 0;
rpc_restart_call(task); nfs4_restart_rpc(task, data->clp);
return; return;
} }
nfs41_sequence_free_slot(data->clp, &data->res->lr_seq_res);
dprintk("<-- %s\n", __func__); dprintk("<-- %s\n", __func__);
} }
@ -4900,11 +4867,10 @@ void nfs41_sequence_call_done(struct rpc_task *task, void *data)
if (_nfs4_async_handle_error(task, NULL, clp, NULL) if (_nfs4_async_handle_error(task, NULL, clp, NULL)
== -EAGAIN) { == -EAGAIN) {
nfs4_restart_rpc(task, clp, task->tk_msg.rpc_resp); nfs4_restart_rpc(task, clp);
return; return;
} }
} }
nfs41_sequence_free_slot(clp, task->tk_msg.rpc_resp);
dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred); dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
kfree(task->tk_msg.rpc_argp); kfree(task->tk_msg.rpc_argp);
@ -5008,7 +4974,6 @@ static void nfs4_reclaim_complete_done(struct rpc_task *task, void *data)
return; return;
} }
} }
nfs41_sequence_free_slot(clp, res);
dprintk("<-- %s\n", __func__); dprintk("<-- %s\n", __func__);
} }

View File

@ -356,26 +356,19 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data
struct nfs_readres *resp = &data->res; struct nfs_readres *resp = &data->res;
if (resp->eof || resp->count == argp->count) if (resp->eof || resp->count == argp->count)
goto out; return;
/* This is a short read! */ /* This is a short read! */
nfs_inc_stats(data->inode, NFSIOS_SHORTREAD); nfs_inc_stats(data->inode, NFSIOS_SHORTREAD);
/* Has the server at least made some progress? */ /* Has the server at least made some progress? */
if (resp->count == 0) if (resp->count == 0)
goto out; return;
/* Yes, so retry the read at the end of the data */ /* Yes, so retry the read at the end of the data */
argp->offset += resp->count; argp->offset += resp->count;
argp->pgbase += resp->count; argp->pgbase += resp->count;
argp->count -= resp->count; argp->count -= resp->count;
nfs4_restart_rpc(task, NFS_SERVER(data->inode)->nfs_client, nfs4_restart_rpc(task, NFS_SERVER(data->inode)->nfs_client);
&data->res.seq_res);
return;
out:
nfs4_sequence_free_slot(NFS_SERVER(data->inode)->nfs_client,
&data->res.seq_res);
return;
} }
/* /*

View File

@ -81,11 +81,9 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
{ {
struct nfs_unlinkdata *data = calldata; struct nfs_unlinkdata *data = calldata;
struct inode *dir = data->dir; struct inode *dir = data->dir;
struct nfs_removeres *res = task->tk_msg.rpc_resp;
if (!NFS_PROTO(dir)->unlink_done(task, dir)) if (!NFS_PROTO(dir)->unlink_done(task, dir))
nfs4_restart_rpc(task, NFS_SERVER(dir)->nfs_client, nfs4_restart_rpc(task, NFS_SERVER(dir)->nfs_client);
&res->seq_res);
} }
/** /**

View File

@ -1216,8 +1216,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
*/ */
argp->stable = NFS_FILE_SYNC; argp->stable = NFS_FILE_SYNC;
} }
nfs4_restart_rpc(task, server->nfs_client, nfs4_restart_rpc(task, server->nfs_client);
&data->res.seq_res);
return -EAGAIN; return -EAGAIN;
} }
if (time_before(complain, jiffies)) { if (time_before(complain, jiffies)) {
@ -1229,7 +1228,6 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
/* Can't do anything about it except throw an error. */ /* Can't do anything about it except throw an error. */
task->tk_status = -EIO; task->tk_status = -EIO;
} }
nfs4_sequence_free_slot(server->nfs_client, &data->res.seq_res);
return 0; return 0;
} }