aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/inode.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-06-25 16:35:53 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-07-30 14:41:56 -0400
commitf11ac8db5d07b6e99d41ff4aa39d878ee5cef1c5 (patch)
tree4393cbc2653145ba3269d5143f5db7811a59698b /fs/nfs/inode.c
parent1f0e890dba5b0f543fea47732116b1c65d55614e (diff)
NFSv4: Ensure that we track the NFSv4 lock state in read/write requests.
This patch fixes bugzilla entry 14501: https://bugzilla.kernel.org/show_bug.cgi?id=14501 Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r--fs/nfs/inode.c70
1 files changed, 66 insertions, 4 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 099b3518feea..ec7a8f96a2c2 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -530,6 +530,68 @@ out:
530 return err; 530 return err;
531} 531}
532 532
533static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
534{
535 atomic_set(&l_ctx->count, 1);
536 l_ctx->lockowner = current->files;
537 l_ctx->pid = current->tgid;
538 INIT_LIST_HEAD(&l_ctx->list);
539}
540
541static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context *ctx)
542{
543 struct nfs_lock_context *pos;
544
545 list_for_each_entry(pos, &ctx->lock_context.list, list) {
546 if (pos->lockowner != current->files)
547 continue;
548 if (pos->pid != current->tgid)
549 continue;
550 atomic_inc(&pos->count);
551 return pos;
552 }
553 return NULL;
554}
555
556struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx)
557{
558 struct nfs_lock_context *res, *new = NULL;
559 struct inode *inode = ctx->path.dentry->d_inode;
560
561 spin_lock(&inode->i_lock);
562 res = __nfs_find_lock_context(ctx);
563 if (res == NULL) {
564 spin_unlock(&inode->i_lock);
565 new = kmalloc(sizeof(*new), GFP_KERNEL);
566 if (new == NULL)
567 return NULL;
568 nfs_init_lock_context(new);
569 spin_lock(&inode->i_lock);
570 res = __nfs_find_lock_context(ctx);
571 if (res == NULL) {
572 list_add_tail(&new->list, &ctx->lock_context.list);
573 new->open_context = ctx;
574 res = new;
575 new = NULL;
576 }
577 }
578 spin_unlock(&inode->i_lock);
579 kfree(new);
580 return res;
581}
582
583void nfs_put_lock_context(struct nfs_lock_context *l_ctx)
584{
585 struct nfs_open_context *ctx = l_ctx->open_context;
586 struct inode *inode = ctx->path.dentry->d_inode;
587
588 if (!atomic_dec_and_lock(&l_ctx->count, &inode->i_lock))
589 return;
590 list_del(&l_ctx->list);
591 spin_unlock(&inode->i_lock);
592 kfree(l_ctx);
593}
594
533/** 595/**
534 * nfs_close_context - Common close_context() routine NFSv2/v3 596 * nfs_close_context - Common close_context() routine NFSv2/v3
535 * @ctx: pointer to context 597 * @ctx: pointer to context
@@ -566,11 +628,11 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct
566 path_get(&ctx->path); 628 path_get(&ctx->path);
567 ctx->cred = get_rpccred(cred); 629 ctx->cred = get_rpccred(cred);
568 ctx->state = NULL; 630 ctx->state = NULL;
569 ctx->lockowner = current->files;
570 ctx->flags = 0; 631 ctx->flags = 0;
571 ctx->error = 0; 632 ctx->error = 0;
572 ctx->dir_cookie = 0; 633 ctx->dir_cookie = 0;
573 atomic_set(&ctx->count, 1); 634 nfs_init_lock_context(&ctx->lock_context);
635 ctx->lock_context.open_context = ctx;
574 } 636 }
575 return ctx; 637 return ctx;
576} 638}
@@ -578,7 +640,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct
578struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) 640struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
579{ 641{
580 if (ctx != NULL) 642 if (ctx != NULL)
581 atomic_inc(&ctx->count); 643 atomic_inc(&ctx->lock_context.count);
582 return ctx; 644 return ctx;
583} 645}
584 646
@@ -586,7 +648,7 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
586{ 648{
587 struct inode *inode = ctx->path.dentry->d_inode; 649 struct inode *inode = ctx->path.dentry->d_inode;
588 650
589 if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock)) 651 if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
590 return; 652 return;
591 list_del(&ctx->list); 653 list_del(&ctx->list);
592 spin_unlock(&inode->i_lock); 654 spin_unlock(&inode->i_lock);