aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenny Halevy <bhalevy@panasas.com>2010-09-24 09:17:01 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-09-24 09:17:01 -0400
commitdfb4f309830359352539919f23accc59a20a3758 (patch)
treec692dbb873e212bd919e6b98dac62478cb9ba968
parent7c563cc9f3f4aca70c27bd08a135499227f67014 (diff)
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: Benny Halevy <bhalevy@panasas.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/nfs4proc.c52
-rw-r--r--fs/nfs/nfs4xdr.c6
-rw-r--r--fs/nfs/read.c1
-rw-r--r--fs/nfs/unlink.c3
-rw-r--r--fs/nfs/write.c2
-rw-r--r--include/linux/nfs_xdr.h2
6 files changed, 25 insertions, 41 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 72aa7067b85d..aee1bcc1fcc9 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -334,10 +334,12 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
334 * Must be called while holding tbl->slot_tbl_lock 334 * Must be called while holding tbl->slot_tbl_lock
335 */ 335 */
336static void 336static void
337nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid) 337nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *free_slot)
338{ 338{
339 int free_slotid = free_slot - tbl->slots;
339 int slotid = free_slotid; 340 int slotid = free_slotid;
340 341
342 BUG_ON(slotid < 0 || slotid >= NFS4_MAX_SLOT_TABLE);
341 /* clear used bit in bitmap */ 343 /* clear used bit in bitmap */
342 __clear_bit(slotid, tbl->used_slots); 344 __clear_bit(slotid, tbl->used_slots);
343 345
@@ -379,7 +381,7 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
379 struct nfs4_slot_table *tbl; 381 struct nfs4_slot_table *tbl;
380 382
381 tbl = &res->sr_session->fc_slot_table; 383 tbl = &res->sr_session->fc_slot_table;
382 if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) { 384 if (!res->sr_slot) {
383 /* just wake up the next guy waiting since 385 /* just wake up the next guy waiting since
384 * we may have not consumed a slot after all */ 386 * we may have not consumed a slot after all */
385 dprintk("%s: No slot\n", __func__); 387 dprintk("%s: No slot\n", __func__);
@@ -387,17 +389,15 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
387 } 389 }
388 390
389 spin_lock(&tbl->slot_tbl_lock); 391 spin_lock(&tbl->slot_tbl_lock);
390 nfs4_free_slot(tbl, res->sr_slotid); 392 nfs4_free_slot(tbl, res->sr_slot);
391 nfs41_check_drain_session_complete(res->sr_session); 393 nfs41_check_drain_session_complete(res->sr_session);
392 spin_unlock(&tbl->slot_tbl_lock); 394 spin_unlock(&tbl->slot_tbl_lock);
393 res->sr_slotid = NFS4_MAX_SLOT_TABLE; 395 res->sr_slot = NULL;
394} 396}
395 397
396static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) 398static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
397{ 399{
398 unsigned long timestamp; 400 unsigned long timestamp;
399 struct nfs4_slot_table *tbl;
400 struct nfs4_slot *slot;
401 struct nfs_client *clp; 401 struct nfs_client *clp;
402 402
403 /* 403 /*
@@ -410,17 +410,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
410 res->sr_status = NFS_OK; 410 res->sr_status = NFS_OK;
411 411
412 /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */ 412 /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
413 if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) 413 if (!res->sr_slot)
414 goto out; 414 goto out;
415 415
416 tbl = &res->sr_session->fc_slot_table;
417 slot = tbl->slots + res->sr_slotid;
418
419 /* Check the SEQUENCE operation status */ 416 /* Check the SEQUENCE operation status */
420 switch (res->sr_status) { 417 switch (res->sr_status) {
421 case 0: 418 case 0:
422 /* Update the slot's sequence and clientid lease timer */ 419 /* Update the slot's sequence and clientid lease timer */
423 ++slot->seq_nr; 420 ++res->sr_slot->seq_nr;
424 timestamp = res->sr_renewal_time; 421 timestamp = res->sr_renewal_time;
425 clp = res->sr_session->clp; 422 clp = res->sr_session->clp;
426 do_renew_lease(clp, timestamp); 423 do_renew_lease(clp, timestamp);
@@ -433,12 +430,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
433 * returned NFS4ERR_DELAY as per Section 2.10.6.2 430 * returned NFS4ERR_DELAY as per Section 2.10.6.2
434 * of RFC5661. 431 * of RFC5661.
435 */ 432 */
436 dprintk("%s: slot=%d seq=%d: Operation in progress\n", 433 dprintk("%s: slot=%ld seq=%d: Operation in progress\n",
437 __func__, res->sr_slotid, slot->seq_nr); 434 __func__,
435 res->sr_slot - res->sr_session->fc_slot_table.slots,
436 res->sr_slot->seq_nr);
438 goto out_retry; 437 goto out_retry;
439 default: 438 default:
440 /* Just update the slot sequence no. */ 439 /* Just update the slot sequence no. */
441 ++slot->seq_nr; 440 ++res->sr_slot->seq_nr;
442 } 441 }
443out: 442out:
444 /* The session may be reset by one of the error handlers. */ 443 /* 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 504
506 dprintk("--> %s\n", __func__); 505 dprintk("--> %s\n", __func__);
507 /* slot already allocated? */ 506 /* slot already allocated? */
508 if (res->sr_slotid != NFS4_MAX_SLOT_TABLE) 507 if (res->sr_slot != NULL)
509 return 0; 508 return 0;
510 509
511 res->sr_slotid = NFS4_MAX_SLOT_TABLE;
512 tbl = &session->fc_slot_table; 510 tbl = &session->fc_slot_table;
513 511
514 spin_lock(&tbl->slot_tbl_lock); 512 spin_lock(&tbl->slot_tbl_lock);
@@ -550,7 +548,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
550 dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr); 548 dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr);
551 549
552 res->sr_session = session; 550 res->sr_session = session;
553 res->sr_slotid = slotid; 551 res->sr_slot = slot;
554 res->sr_renewal_time = jiffies; 552 res->sr_renewal_time = jiffies;
555 res->sr_status_flags = 0; 553 res->sr_status_flags = 0;
556 /* 554 /*
@@ -576,8 +574,9 @@ int nfs4_setup_sequence(const struct nfs_server *server,
576 goto out; 574 goto out;
577 } 575 }
578 576
579 dprintk("--> %s clp %p session %p sr_slotid %d\n", 577 dprintk("--> %s clp %p session %p sr_slot %ld\n",
580 __func__, session->clp, session, res->sr_slotid); 578 __func__, session->clp, session, res->sr_slot ?
579 res->sr_slot - session->fc_slot_table.slots : -1);
581 580
582 ret = nfs41_setup_sequence(session, args, res, cache_reply, 581 ret = nfs41_setup_sequence(session, args, res, cache_reply,
583 task); 582 task);
@@ -650,7 +649,7 @@ static int nfs4_call_sync_sequence(struct nfs_server *server,
650 .callback_data = &data 649 .callback_data = &data
651 }; 650 };
652 651
653 res->sr_slotid = NFS4_MAX_SLOT_TABLE; 652 res->sr_slot = NULL;
654 if (privileged) 653 if (privileged)
655 task_setup.callback_ops = &nfs41_call_priv_sync_ops; 654 task_setup.callback_ops = &nfs41_call_priv_sync_ops;
656 task = rpc_run_task(&task_setup); 655 task = rpc_run_task(&task_setup);
@@ -735,7 +734,6 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
735 p->o_res.server = p->o_arg.server; 734 p->o_res.server = p->o_arg.server;
736 nfs_fattr_init(&p->f_attr); 735 nfs_fattr_init(&p->f_attr);
737 nfs_fattr_init(&p->dir_attr); 736 nfs_fattr_init(&p->dir_attr);
738 p->o_res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
739} 737}
740 738
741static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path, 739static 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 calldata->res.fattr = &calldata->fattr; 1973 calldata->res.fattr = &calldata->fattr;
1976 calldata->res.seqid = calldata->arg.seqid; 1974 calldata->res.seqid = calldata->arg.seqid;
1977 calldata->res.server = server; 1975 calldata->res.server = server;
1978 calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
1979 path_get(path); 1976 path_get(path);
1980 calldata->path = *path; 1977 calldata->path = *path;
1981 1978
@@ -2550,7 +2547,7 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
2550 2547
2551 args->bitmask = server->cache_consistency_bitmask; 2548 args->bitmask = server->cache_consistency_bitmask;
2552 res->server = server; 2549 res->server = server;
2553 res->seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; 2550 res->seq_res.sr_slot = NULL;
2554 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; 2551 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
2555} 2552}
2556 2553
@@ -2576,7 +2573,6 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
2576 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; 2573 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
2577 arg->bitmask = server->attr_bitmask; 2574 arg->bitmask = server->attr_bitmask;
2578 res->server = server; 2575 res->server = server;
2579 res->seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
2580} 2576}
2581 2577
2582static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, 2578static 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 memcpy(&data->stateid, stateid, sizeof(data->stateid)); 3642 memcpy(&data->stateid, stateid, sizeof(data->stateid));
3647 data->res.fattr = &data->fattr; 3643 data->res.fattr = &data->fattr;
3648 data->res.server = server; 3644 data->res.server = server;
3649 data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
3650 nfs_fattr_init(data->res.fattr); 3645 nfs_fattr_init(data->res.fattr);
3651 data->timestamp = jiffies; 3646 data->timestamp = jiffies;
3652 data->rpc_status = 0; 3647 data->rpc_status = 0;
@@ -3799,7 +3794,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
3799 p->arg.fl = &p->fl; 3794 p->arg.fl = &p->fl;
3800 p->arg.seqid = seqid; 3795 p->arg.seqid = seqid;
3801 p->res.seqid = seqid; 3796 p->res.seqid = seqid;
3802 p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
3803 p->arg.stateid = &lsp->ls_stateid; 3797 p->arg.stateid = &lsp->ls_stateid;
3804 p->lsp = lsp; 3798 p->lsp = lsp;
3805 atomic_inc(&lsp->ls_count); 3799 atomic_inc(&lsp->ls_count);
@@ -3979,7 +3973,6 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
3979 p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; 3973 p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
3980 p->arg.lock_owner.id = lsp->ls_id.id; 3974 p->arg.lock_owner.id = lsp->ls_id.id;
3981 p->res.lock_seqid = p->arg.lock_seqid; 3975 p->res.lock_seqid = p->arg.lock_seqid;
3982 p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
3983 p->lsp = lsp; 3976 p->lsp = lsp;
3984 p->server = server; 3977 p->server = server;
3985 atomic_inc(&lsp->ls_count); 3978 atomic_inc(&lsp->ls_count);
@@ -4612,7 +4605,6 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
4612 }; 4605 };
4613 int status; 4606 int status;
4614 4607
4615 res.lr_seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
4616 dprintk("--> %s\n", __func__); 4608 dprintk("--> %s\n", __func__);
4617 task = rpc_run_task(&task_setup); 4609 task = rpc_run_task(&task_setup);
4618 4610
@@ -5105,12 +5097,11 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_
5105 5097
5106 if (!atomic_inc_not_zero(&clp->cl_count)) 5098 if (!atomic_inc_not_zero(&clp->cl_count))
5107 return ERR_PTR(-EIO); 5099 return ERR_PTR(-EIO);
5108 calldata = kmalloc(sizeof(*calldata), GFP_NOFS); 5100 calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
5109 if (calldata == NULL) { 5101 if (calldata == NULL) {
5110 nfs_put_client(clp); 5102 nfs_put_client(clp);
5111 return ERR_PTR(-ENOMEM); 5103 return ERR_PTR(-ENOMEM);
5112 } 5104 }
5113 calldata->res.sr_slotid = NFS4_MAX_SLOT_TABLE;
5114 msg.rpc_argp = &calldata->args; 5105 msg.rpc_argp = &calldata->args;
5115 msg.rpc_resp = &calldata->res; 5106 msg.rpc_resp = &calldata->res;
5116 calldata->clp = clp; 5107 calldata->clp = clp;
@@ -5242,7 +5233,6 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp)
5242 goto out; 5233 goto out;
5243 calldata->clp = clp; 5234 calldata->clp = clp;
5244 calldata->arg.one_fs = 0; 5235 calldata->arg.one_fs = 0;
5245 calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
5246 5236
5247 msg.rpc_argp = &calldata->arg; 5237 msg.rpc_argp = &calldata->arg;
5248 msg.rpc_resp = &calldata->res; 5238 msg.rpc_resp = &calldata->res;
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 86ab69eb149c..3feace66b981 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -4665,7 +4665,6 @@ static int decode_sequence(struct xdr_stream *xdr,
4665 struct rpc_rqst *rqstp) 4665 struct rpc_rqst *rqstp)
4666{ 4666{
4667#if defined(CONFIG_NFS_V4_1) 4667#if defined(CONFIG_NFS_V4_1)
4668 struct nfs4_slot *slot;
4669 struct nfs4_sessionid id; 4668 struct nfs4_sessionid id;
4670 u32 dummy; 4669 u32 dummy;
4671 int status; 4670 int status;
@@ -4697,15 +4696,14 @@ static int decode_sequence(struct xdr_stream *xdr,
4697 goto out_overflow; 4696 goto out_overflow;
4698 4697
4699 /* seqid */ 4698 /* seqid */
4700 slot = &res->sr_session->fc_slot_table.slots[res->sr_slotid];
4701 dummy = be32_to_cpup(p++); 4699 dummy = be32_to_cpup(p++);
4702 if (dummy != slot->seq_nr) { 4700 if (dummy != res->sr_slot->seq_nr) {
4703 dprintk("%s Invalid sequence number\n", __func__); 4701 dprintk("%s Invalid sequence number\n", __func__);
4704 goto out_err; 4702 goto out_err;
4705 } 4703 }
4706 /* slot id */ 4704 /* slot id */
4707 dummy = be32_to_cpup(p++); 4705 dummy = be32_to_cpup(p++);
4708 if (dummy != res->sr_slotid) { 4706 if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) {
4709 dprintk("%s Invalid slot id\n", __func__); 4707 dprintk("%s Invalid slot id\n", __func__);
4710 goto out_err; 4708 goto out_err;
4711 } 4709 }
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 87adc2744246..79859c81a943 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -46,7 +46,6 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
46 memset(p, 0, sizeof(*p)); 46 memset(p, 0, sizeof(*p));
47 INIT_LIST_HEAD(&p->pages); 47 INIT_LIST_HEAD(&p->pages);
48 p->npages = pagecount; 48 p->npages = pagecount;
49 p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
50 if (pagecount <= ARRAY_SIZE(p->page_array)) 49 if (pagecount <= ARRAY_SIZE(p->page_array))
51 p->pagevec = p->page_array; 50 p->pagevec = p->page_array;
52 else { 51 else {
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 47530aacebfd..9a16bad5d2ea 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -262,7 +262,6 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry)
262 status = PTR_ERR(data->cred); 262 status = PTR_ERR(data->cred);
263 goto out_free; 263 goto out_free;
264 } 264 }
265 data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
266 data->res.dir_attr = &data->dir_attr; 265 data->res.dir_attr = &data->dir_attr;
267 266
268 status = -EBUSY; 267 status = -EBUSY;
@@ -427,7 +426,7 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
427 .flags = RPC_TASK_ASYNC, 426 .flags = RPC_TASK_ASYNC,
428 }; 427 };
429 428
430 data = kmalloc(sizeof(*data), GFP_KERNEL); 429 data = kzalloc(sizeof(*data), GFP_KERNEL);
431 if (data == NULL) 430 if (data == NULL)
432 return ERR_PTR(-ENOMEM); 431 return ERR_PTR(-ENOMEM);
433 task_setup_data.callback_data = data, 432 task_setup_data.callback_data = data,
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 874972d9427c..4d6d35dd2b4b 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -55,7 +55,6 @@ struct nfs_write_data *nfs_commitdata_alloc(void)
55 if (p) { 55 if (p) {
56 memset(p, 0, sizeof(*p)); 56 memset(p, 0, sizeof(*p));
57 INIT_LIST_HEAD(&p->pages); 57 INIT_LIST_HEAD(&p->pages);
58 p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
59 } 58 }
60 return p; 59 return p;
61} 60}
@@ -75,7 +74,6 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
75 memset(p, 0, sizeof(*p)); 74 memset(p, 0, sizeof(*p));
76 INIT_LIST_HEAD(&p->pages); 75 INIT_LIST_HEAD(&p->pages);
77 p->npages = pagecount; 76 p->npages = pagecount;
78 p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
79 if (pagecount <= ARRAY_SIZE(p->page_array)) 77 if (pagecount <= ARRAY_SIZE(p->page_array))
80 p->pagevec = p->page_array; 78 p->pagevec = p->page_array;
81 else { 79 else {
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 172df83ac54b..5772b2c2f063 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -170,7 +170,7 @@ struct nfs4_sequence_args {
170 170
171struct nfs4_sequence_res { 171struct nfs4_sequence_res {
172 struct nfs4_session *sr_session; 172 struct nfs4_session *sr_session;
173 u8 sr_slotid; /* slot used to send request */ 173 struct nfs4_slot *sr_slot; /* slot used to send request */
174 int sr_status; /* sequence operation status */ 174 int sr_status; /* sequence operation status */
175 unsigned long sr_renewal_time; 175 unsigned long sr_renewal_time;
176 u32 sr_status_flags; 176 u32 sr_status_flags;