aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-01-08 17:56:07 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-01-30 02:05:24 -0500
commit2f74c0a05612b9c2014b5b67833dba9b9f523948 (patch)
tree59bb49bd9a393774b65e3d39e53edfe7bab4613e /fs/nfs
parentacee478afc6ff7e1b8852d9a4dca1ff36021414d (diff)
NFSv4: Clean up the OPEN/CLOSE serialisation code
Reduce the time spent locking the rpc_sequence structure by queuing the nfs_seqid only when we are ready to take the lock (when calling nfs_wait_on_sequence). Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c30
-rw-r--r--fs/nfs/nfs4state.c32
2 files changed, 27 insertions, 35 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 9e2e1c7291db..a51a7537f3f6 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3331,15 +3331,12 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
3331 3331
3332 p->arg.fh = NFS_FH(inode); 3332 p->arg.fh = NFS_FH(inode);
3333 p->arg.fl = &p->fl; 3333 p->arg.fl = &p->fl;
3334 if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) { 3334 p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid);
3335 p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid); 3335 if (p->arg.open_seqid == NULL)
3336 if (p->arg.open_seqid == NULL) 3336 goto out_free;
3337 goto out_free;
3338
3339 }
3340 p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid); 3337 p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid);
3341 if (p->arg.lock_seqid == NULL) 3338 if (p->arg.lock_seqid == NULL)
3342 goto out_free; 3339 goto out_free_seqid;
3343 p->arg.lock_stateid = &lsp->ls_stateid; 3340 p->arg.lock_stateid = &lsp->ls_stateid;
3344 p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; 3341 p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
3345 p->arg.lock_owner.id = lsp->ls_id.id; 3342 p->arg.lock_owner.id = lsp->ls_id.id;
@@ -3348,9 +3345,9 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
3348 p->ctx = get_nfs_open_context(ctx); 3345 p->ctx = get_nfs_open_context(ctx);
3349 memcpy(&p->fl, fl, sizeof(p->fl)); 3346 memcpy(&p->fl, fl, sizeof(p->fl));
3350 return p; 3347 return p;
3348out_free_seqid:
3349 nfs_free_seqid(p->arg.open_seqid);
3351out_free: 3350out_free:
3352 if (p->arg.open_seqid != NULL)
3353 nfs_free_seqid(p->arg.open_seqid);
3354 kfree(p); 3351 kfree(p);
3355 return NULL; 3352 return NULL;
3356} 3353}
@@ -3368,20 +3365,16 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
3368 }; 3365 };
3369 3366
3370 dprintk("%s: begin!\n", __FUNCTION__); 3367 dprintk("%s: begin!\n", __FUNCTION__);
3368 if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0)
3369 return;
3371 /* Do we need to do an open_to_lock_owner? */ 3370 /* Do we need to do an open_to_lock_owner? */
3372 if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { 3371 if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
3373 if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) 3372 if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0)
3374 return; 3373 return;
3375 data->arg.open_stateid = &state->stateid; 3374 data->arg.open_stateid = &state->stateid;
3376 data->arg.new_lock_owner = 1; 3375 data->arg.new_lock_owner = 1;
3377 /* Retest in case we raced... */ 3376 } else
3378 if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) 3377 data->arg.new_lock_owner = 0;
3379 goto do_rpc;
3380 }
3381 if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0)
3382 return;
3383 data->arg.new_lock_owner = 0;
3384do_rpc:
3385 data->timestamp = jiffies; 3378 data->timestamp = jiffies;
3386 rpc_call_setup(task, &msg, 0); 3379 rpc_call_setup(task, &msg, 0);
3387 dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status); 3380 dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status);
@@ -3419,6 +3412,7 @@ static void nfs4_lock_release(void *calldata)
3419 struct nfs4_lockdata *data = calldata; 3412 struct nfs4_lockdata *data = calldata;
3420 3413
3421 dprintk("%s: begin!\n", __FUNCTION__); 3414 dprintk("%s: begin!\n", __FUNCTION__);
3415 nfs_free_seqid(data->arg.open_seqid);
3422 if (data->cancelled != 0) { 3416 if (data->cancelled != 0) {
3423 struct rpc_task *task; 3417 struct rpc_task *task;
3424 task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, 3418 task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,
@@ -3428,8 +3422,6 @@ static void nfs4_lock_release(void *calldata)
3428 dprintk("%s: cancelling lock!\n", __FUNCTION__); 3422 dprintk("%s: cancelling lock!\n", __FUNCTION__);
3429 } else 3423 } else
3430 nfs_free_seqid(data->arg.lock_seqid); 3424 nfs_free_seqid(data->arg.lock_seqid);
3431 if (data->arg.open_seqid != NULL)
3432 nfs_free_seqid(data->arg.open_seqid);
3433 nfs4_put_lock_state(data->lsp); 3425 nfs4_put_lock_state(data->lsp);
3434 put_nfs_open_context(data->ctx); 3426 put_nfs_open_context(data->ctx);
3435 kfree(data); 3427 kfree(data);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 5a39c6f78acf..bf94c6e0a503 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -644,27 +644,26 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f
644 644
645struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) 645struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter)
646{ 646{
647 struct rpc_sequence *sequence = counter->sequence;
648 struct nfs_seqid *new; 647 struct nfs_seqid *new;
649 648
650 new = kmalloc(sizeof(*new), GFP_KERNEL); 649 new = kmalloc(sizeof(*new), GFP_KERNEL);
651 if (new != NULL) { 650 if (new != NULL) {
652 new->sequence = counter; 651 new->sequence = counter;
653 spin_lock(&sequence->lock); 652 INIT_LIST_HEAD(&new->list);
654 list_add_tail(&new->list, &sequence->list);
655 spin_unlock(&sequence->lock);
656 } 653 }
657 return new; 654 return new;
658} 655}
659 656
660void nfs_free_seqid(struct nfs_seqid *seqid) 657void nfs_free_seqid(struct nfs_seqid *seqid)
661{ 658{
662 struct rpc_sequence *sequence = seqid->sequence->sequence; 659 if (!list_empty(&seqid->list)) {
660 struct rpc_sequence *sequence = seqid->sequence->sequence;
663 661
664 spin_lock(&sequence->lock); 662 spin_lock(&sequence->lock);
665 list_del(&seqid->list); 663 list_del(&seqid->list);
666 spin_unlock(&sequence->lock); 664 spin_unlock(&sequence->lock);
667 rpc_wake_up(&sequence->wait); 665 rpc_wake_up(&sequence->wait);
666 }
668 kfree(seqid); 667 kfree(seqid);
669} 668}
670 669
@@ -675,6 +674,7 @@ void nfs_free_seqid(struct nfs_seqid *seqid)
675 */ 674 */
676static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) 675static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
677{ 676{
677 BUG_ON(list_first_entry(&seqid->sequence->sequence->list, struct nfs_seqid, list) != seqid);
678 switch (status) { 678 switch (status) {
679 case 0: 679 case 0:
680 break; 680 break;
@@ -726,15 +726,15 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
726 struct rpc_sequence *sequence = seqid->sequence->sequence; 726 struct rpc_sequence *sequence = seqid->sequence->sequence;
727 int status = 0; 727 int status = 0;
728 728
729 if (sequence->list.next == &seqid->list)
730 goto out;
731 spin_lock(&sequence->lock); 729 spin_lock(&sequence->lock);
732 if (sequence->list.next != &seqid->list) { 730 if (list_empty(&seqid->list))
733 rpc_sleep_on(&sequence->wait, task, NULL, NULL); 731 list_add_tail(&seqid->list, &sequence->list);
734 status = -EAGAIN; 732 if (list_first_entry(&sequence->list, struct nfs_seqid, list) == seqid)
735 } 733 goto unlock;
734 rpc_sleep_on(&sequence->wait, task, NULL, NULL);
735 status = -EAGAIN;
736unlock:
736 spin_unlock(&sequence->lock); 737 spin_unlock(&sequence->lock);
737out:
738 return status; 738 return status;
739} 739}
740 740