diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-09-27 15:51:20 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-09-29 14:41:36 -0400 |
commit | 5c78f58e2d5cef65c255a556184f1f43c8d84c84 (patch) | |
tree | 64d9e8274e40343851e38a9ceadbe9d17e8cce2c /fs/nfs/inode.c | |
parent | dfb4f309830359352539919f23accc59a20a3758 (diff) |
NFS: Really fix put_nfs_open_context()
In nfs_open_revalidate(), if the open_context() call returns an inode that
is not the same as dentry->d_inode, then we will call
put_nfs_open_context() with a valid dentry->d_inode, but without the
context being part of the nfsi->open_files list.
In this case too, we want to just skip the list removal, but we do want to
call the ->close_context() callback in order to close the NFSv4 state.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Acked-by: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 702ed096e790..18be041abd23 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -639,6 +639,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cr | |||
639 | ctx->dir_cookie = 0; | 639 | ctx->dir_cookie = 0; |
640 | nfs_init_lock_context(&ctx->lock_context); | 640 | nfs_init_lock_context(&ctx->lock_context); |
641 | ctx->lock_context.open_context = ctx; | 641 | ctx->lock_context.open_context = ctx; |
642 | INIT_LIST_HEAD(&ctx->list); | ||
642 | } | 643 | } |
643 | return ctx; | 644 | return ctx; |
644 | } | 645 | } |
@@ -654,14 +655,15 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync) | |||
654 | { | 655 | { |
655 | struct inode *inode = ctx->path.dentry->d_inode; | 656 | struct inode *inode = ctx->path.dentry->d_inode; |
656 | 657 | ||
657 | if (inode) { | 658 | if (!list_empty(&ctx->list)) { |
658 | if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock)) | 659 | if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock)) |
659 | return; | 660 | return; |
660 | list_del(&ctx->list); | 661 | list_del(&ctx->list); |
661 | spin_unlock(&inode->i_lock); | 662 | spin_unlock(&inode->i_lock); |
662 | NFS_PROTO(inode)->close_context(ctx, is_sync); | ||
663 | } else if (!atomic_dec_and_test(&ctx->lock_context.count)) | 663 | } else if (!atomic_dec_and_test(&ctx->lock_context.count)) |
664 | return; | 664 | return; |
665 | if (inode != NULL) | ||
666 | NFS_PROTO(inode)->close_context(ctx, is_sync); | ||
665 | if (ctx->cred != NULL) | 667 | if (ctx->cred != NULL) |
666 | put_rpccred(ctx->cred); | 668 | put_rpccred(ctx->cred); |
667 | path_put(&ctx->path); | 669 | path_put(&ctx->path); |