Commit dfb4f309 authored by Benny Halevy's avatar Benny Halevy Committed by Trond Myklebust

NFSv4.1: keep seq_res.sr_slot as pointer rather than an index

Having to explicitly initialize sr_slotid to NFS4_MAX_SLOT_TABLE
resulted in numerous bugs.  Keeping the current slot as a pointer
to the slot table is more straight forward and robust as it's
implicitly set up to NULL wherever the seq_res member is initialized
to zeroes.
Signed-off-by: default avatarBenny Halevy <bhalevy@panasas.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 7c563cc9
...@@ -334,10 +334,12 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp ...@@ -334,10 +334,12 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
* Must be called while holding tbl->slot_tbl_lock * Must be called while holding tbl->slot_tbl_lock
*/ */
static void static void
nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid) nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *free_slot)
{ {
int free_slotid = free_slot - tbl->slots;
int slotid = free_slotid; int slotid = free_slotid;
BUG_ON(slotid < 0 || slotid >= NFS4_MAX_SLOT_TABLE);
/* clear used bit in bitmap */ /* clear used bit in bitmap */
__clear_bit(slotid, tbl->used_slots); __clear_bit(slotid, tbl->used_slots);
...@@ -379,7 +381,7 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) ...@@ -379,7 +381,7 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
struct nfs4_slot_table *tbl; struct nfs4_slot_table *tbl;
tbl = &res->sr_session->fc_slot_table; tbl = &res->sr_session->fc_slot_table;
if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) { if (!res->sr_slot) {
/* just wake up the next guy waiting since /* just wake up the next guy waiting since
* we may have not consumed a slot after all */ * we may have not consumed a slot after all */
dprintk("%s: No slot\n", __func__); dprintk("%s: No slot\n", __func__);
...@@ -387,17 +389,15 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) ...@@ -387,17 +389,15 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
} }
spin_lock(&tbl->slot_tbl_lock); spin_lock(&tbl->slot_tbl_lock);
nfs4_free_slot(tbl, res->sr_slotid); nfs4_free_slot(tbl, res->sr_slot);
nfs41_check_drain_session_complete(res->sr_session); nfs41_check_drain_session_complete(res->sr_session);
spin_unlock(&tbl->slot_tbl_lock); spin_unlock(&tbl->slot_tbl_lock);
res->sr_slotid = NFS4_MAX_SLOT_TABLE; res->sr_slot = NULL;
} }
static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
{ {
unsigned long timestamp; unsigned long timestamp;
struct nfs4_slot_table *tbl;
struct nfs4_slot *slot;
struct nfs_client *clp; struct nfs_client *clp;
/* /*
...@@ -410,17 +410,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res * ...@@ -410,17 +410,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
res->sr_status = NFS_OK; res->sr_status = NFS_OK;
/* -ERESTARTSYS can result in skipping nfs41_sequence_setup */ /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) if (!res->sr_slot)
goto out; goto out;
tbl = &res->sr_session->fc_slot_table;
slot = tbl->slots + res->sr_slotid;
/* Check the SEQUENCE operation status */ /* Check the SEQUENCE operation status */
switch (res->sr_status) { switch (res->sr_status) {
case 0: case 0:
/* Update the slot's sequence and clientid lease timer */ /* Update the slot's sequence and clientid lease timer */
++slot->seq_nr; ++res->sr_slot->seq_nr;
timestamp = res->sr_renewal_time; timestamp = res->sr_renewal_time;
clp = res->sr_session->clp; clp = res->sr_session->clp;
do_renew_lease(clp, timestamp); do_renew_lease(clp, timestamp);
...@@ -433,12 +430,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res * ...@@ -433,12 +430,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
* returned NFS4ERR_DELAY as per Section 2.10.6.2 * returned NFS4ERR_DELAY as per Section 2.10.6.2
* of RFC5661. * of RFC5661.
*/ */
dprintk("%s: slot=%d seq=%d: Operation in progress\n", dprintk("%s: slot=%ld seq=%d: Operation in progress\n",
__func__, res->sr_slotid, slot->seq_nr); __func__,
res->sr_slot - res->sr_session->fc_slot_table.slots,
res->sr_slot->seq_nr);
goto out_retry; goto out_retry;
default: default:
/* Just update the slot sequence no. */ /* Just update the slot sequence no. */
++slot->seq_nr; ++res->sr_slot->seq_nr;
} }
out: out:
/* The session may be reset by one of the error handlers. */ /* The session may be reset by one of the error handlers. */
...@@ -505,10 +504,9 @@ static int nfs41_setup_sequence(struct nfs4_session *session, ...@@ -505,10 +504,9 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
dprintk("--> %s\n", __func__); dprintk("--> %s\n", __func__);
/* slot already allocated? */ /* slot already allocated? */
if (res->sr_slotid != NFS4_MAX_SLOT_TABLE) if (res->sr_slot != NULL)
return 0; return 0;
res->sr_slotid = NFS4_MAX_SLOT_TABLE;
tbl = &session->fc_slot_table; tbl = &session->fc_slot_table;
spin_lock(&tbl->slot_tbl_lock); spin_lock(&tbl->slot_tbl_lock);
...@@ -550,7 +548,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session, ...@@ -550,7 +548,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr); dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr);
res->sr_session = session; res->sr_session = session;
res->sr_slotid = slotid; res->sr_slot = slot;
res->sr_renewal_time = jiffies; res->sr_renewal_time = jiffies;
res->sr_status_flags = 0; res->sr_status_flags = 0;
/* /*
...@@ -576,8 +574,9 @@ int nfs4_setup_sequence(const struct nfs_server *server, ...@@ -576,8 +574,9 @@ int nfs4_setup_sequence(const struct nfs_server *server,
goto out; goto out;
} }
dprintk("--> %s clp %p session %p sr_slotid %d\n", dprintk("--> %s clp %p session %p sr_slot %ld\n",
__func__, session->clp, session, res->sr_slotid); __func__, session->clp, session, res->sr_slot ?
res->sr_slot - session->fc_slot_table.slots : -1);
ret = nfs41_setup_sequence(session, args, res, cache_reply, ret = nfs41_setup_sequence(session, args, res, cache_reply,
task); task);
...@@ -650,7 +649,7 @@ static int nfs4_call_sync_sequence(struct nfs_server *server, ...@@ -650,7 +649,7 @@ static int nfs4_call_sync_sequence(struct nfs_server *server,
.callback_data = &data .callback_data = &data
}; };
res->sr_slotid = NFS4_MAX_SLOT_TABLE; res->sr_slot = NULL;
if (privileged) if (privileged)
task_setup.callback_ops = &nfs41_call_priv_sync_ops; task_setup.callback_ops = &nfs41_call_priv_sync_ops;
task = rpc_run_task(&task_setup); task = rpc_run_task(&task_setup);
...@@ -735,7 +734,6 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p) ...@@ -735,7 +734,6 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
p->o_res.server = p->o_arg.server; p->o_res.server = p->o_arg.server;
nfs_fattr_init(&p->f_attr); nfs_fattr_init(&p->f_attr);
nfs_fattr_init(&p->dir_attr); nfs_fattr_init(&p->dir_attr);
p->o_res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
} }
static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path, static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
...@@ -1975,7 +1973,6 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, i ...@@ -1975,7 +1973,6 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, i
calldata->res.fattr = &calldata->fattr; calldata->res.fattr = &calldata->fattr;
calldata->res.seqid = calldata->arg.seqid; calldata->res.seqid = calldata->arg.seqid;
calldata->res.server = server; calldata->res.server = server;
calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
path_get(path); path_get(path);
calldata->path = *path; calldata->path = *path;
...@@ -2550,7 +2547,7 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) ...@@ -2550,7 +2547,7 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
args->bitmask = server->cache_consistency_bitmask; args->bitmask = server->cache_consistency_bitmask;
res->server = server; res->server = server;
res->seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; res->seq_res.sr_slot = NULL;
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
} }
...@@ -2576,7 +2573,6 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir) ...@@ -2576,7 +2573,6 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
arg->bitmask = server->attr_bitmask; arg->bitmask = server->attr_bitmask;
res->server = server; res->server = server;
res->seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
} }
static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
...@@ -3646,7 +3642,6 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co ...@@ -3646,7 +3642,6 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
memcpy(&data->stateid, stateid, sizeof(data->stateid)); memcpy(&data->stateid, stateid, sizeof(data->stateid));
data->res.fattr = &data->fattr; data->res.fattr = &data->fattr;
data->res.server = server; data->res.server = server;
data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
nfs_fattr_init(data->res.fattr); nfs_fattr_init(data->res.fattr);
data->timestamp = jiffies; data->timestamp = jiffies;
data->rpc_status = 0; data->rpc_status = 0;
...@@ -3799,7 +3794,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, ...@@ -3799,7 +3794,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
p->arg.fl = &p->fl; p->arg.fl = &p->fl;
p->arg.seqid = seqid; p->arg.seqid = seqid;
p->res.seqid = seqid; p->res.seqid = seqid;
p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
p->arg.stateid = &lsp->ls_stateid; p->arg.stateid = &lsp->ls_stateid;
p->lsp = lsp; p->lsp = lsp;
atomic_inc(&lsp->ls_count); atomic_inc(&lsp->ls_count);
...@@ -3979,7 +3973,6 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, ...@@ -3979,7 +3973,6 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
p->arg.lock_owner.id = lsp->ls_id.id; p->arg.lock_owner.id = lsp->ls_id.id;
p->res.lock_seqid = p->arg.lock_seqid; p->res.lock_seqid = p->arg.lock_seqid;
p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
p->lsp = lsp; p->lsp = lsp;
p->server = server; p->server = server;
atomic_inc(&lsp->ls_count); atomic_inc(&lsp->ls_count);
...@@ -4612,7 +4605,6 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) ...@@ -4612,7 +4605,6 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
}; };
int status; int status;
res.lr_seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
dprintk("--> %s\n", __func__); dprintk("--> %s\n", __func__);
task = rpc_run_task(&task_setup); task = rpc_run_task(&task_setup);
...@@ -5105,12 +5097,11 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_ ...@@ -5105,12 +5097,11 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_
if (!atomic_inc_not_zero(&clp->cl_count)) if (!atomic_inc_not_zero(&clp->cl_count))
return ERR_PTR(-EIO); return ERR_PTR(-EIO);
calldata = kmalloc(sizeof(*calldata), GFP_NOFS); calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
if (calldata == NULL) { if (calldata == NULL) {
nfs_put_client(clp); nfs_put_client(clp);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
calldata->res.sr_slotid = NFS4_MAX_SLOT_TABLE;
msg.rpc_argp = &calldata->args; msg.rpc_argp = &calldata->args;
msg.rpc_resp = &calldata->res; msg.rpc_resp = &calldata->res;
calldata->clp = clp; calldata->clp = clp;
...@@ -5242,7 +5233,6 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp) ...@@ -5242,7 +5233,6 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp)
goto out; goto out;
calldata->clp = clp; calldata->clp = clp;
calldata->arg.one_fs = 0; calldata->arg.one_fs = 0;
calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
msg.rpc_argp = &calldata->arg; msg.rpc_argp = &calldata->arg;
msg.rpc_resp = &calldata->res; msg.rpc_resp = &calldata->res;
......
...@@ -4665,7 +4665,6 @@ static int decode_sequence(struct xdr_stream *xdr, ...@@ -4665,7 +4665,6 @@ static int decode_sequence(struct xdr_stream *xdr,
struct rpc_rqst *rqstp) struct rpc_rqst *rqstp)
{ {
#if defined(CONFIG_NFS_V4_1) #if defined(CONFIG_NFS_V4_1)
struct nfs4_slot *slot;
struct nfs4_sessionid id; struct nfs4_sessionid id;
u32 dummy; u32 dummy;
int status; int status;
...@@ -4697,15 +4696,14 @@ static int decode_sequence(struct xdr_stream *xdr, ...@@ -4697,15 +4696,14 @@ static int decode_sequence(struct xdr_stream *xdr,
goto out_overflow; goto out_overflow;
/* seqid */ /* seqid */
slot = &res->sr_session->fc_slot_table.slots[res->sr_slotid];
dummy = be32_to_cpup(p++); dummy = be32_to_cpup(p++);
if (dummy != slot->seq_nr) { if (dummy != res->sr_slot->seq_nr) {
dprintk("%s Invalid sequence number\n", __func__); dprintk("%s Invalid sequence number\n", __func__);
goto out_err; goto out_err;
} }
/* slot id */ /* slot id */
dummy = be32_to_cpup(p++); dummy = be32_to_cpup(p++);
if (dummy != res->sr_slotid) { if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) {
dprintk("%s Invalid slot id\n", __func__); dprintk("%s Invalid slot id\n", __func__);
goto out_err; goto out_err;
} }
......
...@@ -46,7 +46,6 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) ...@@ -46,7 +46,6 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
memset(p, 0, sizeof(*p)); memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages); INIT_LIST_HEAD(&p->pages);
p->npages = pagecount; p->npages = pagecount;
p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
if (pagecount <= ARRAY_SIZE(p->page_array)) if (pagecount <= ARRAY_SIZE(p->page_array))
p->pagevec = p->page_array; p->pagevec = p->page_array;
else { else {
......
...@@ -262,7 +262,6 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry) ...@@ -262,7 +262,6 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry)
status = PTR_ERR(data->cred); status = PTR_ERR(data->cred);
goto out_free; goto out_free;
} }
data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
data->res.dir_attr = &data->dir_attr; data->res.dir_attr = &data->dir_attr;
status = -EBUSY; status = -EBUSY;
...@@ -427,7 +426,7 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir, ...@@ -427,7 +426,7 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
.flags = RPC_TASK_ASYNC, .flags = RPC_TASK_ASYNC,
}; };
data = kmalloc(sizeof(*data), GFP_KERNEL); data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL) if (data == NULL)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
task_setup_data.callback_data = data, task_setup_data.callback_data = data,
......
...@@ -55,7 +55,6 @@ struct nfs_write_data *nfs_commitdata_alloc(void) ...@@ -55,7 +55,6 @@ struct nfs_write_data *nfs_commitdata_alloc(void)
if (p) { if (p) {
memset(p, 0, sizeof(*p)); memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages); INIT_LIST_HEAD(&p->pages);
p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
} }
return p; return p;
} }
...@@ -75,7 +74,6 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) ...@@ -75,7 +74,6 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
memset(p, 0, sizeof(*p)); memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages); INIT_LIST_HEAD(&p->pages);
p->npages = pagecount; p->npages = pagecount;
p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
if (pagecount <= ARRAY_SIZE(p->page_array)) if (pagecount <= ARRAY_SIZE(p->page_array))
p->pagevec = p->page_array; p->pagevec = p->page_array;
else { else {
......
...@@ -170,7 +170,7 @@ struct nfs4_sequence_args { ...@@ -170,7 +170,7 @@ struct nfs4_sequence_args {
struct nfs4_sequence_res { struct nfs4_sequence_res {
struct nfs4_session *sr_session; struct nfs4_session *sr_session;
u8 sr_slotid; /* slot used to send request */ struct nfs4_slot *sr_slot; /* slot used to send request */
int sr_status; /* sequence operation status */ int sr_status; /* sequence operation status */
unsigned long sr_renewal_time; unsigned long sr_renewal_time;
u32 sr_status_flags; u32 sr_status_flags;
......
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