summaryrefslogtreecommitdiffstats
path: root/fs/nfs/inode.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2018-09-02 15:11:57 -0400
committerTrond Myklebust <trond.myklebust@hammerspace.com>2018-09-30 15:35:16 -0400
commit1db97eaa0b482a738c715da6edb023d6f99e50b0 (patch)
treeab49a24c0d53e75780386dbbac1ab7c5531f047b /fs/nfs/inode.c
parent28ced9a84cd2f9fc68a081fb3b34e70c5d459be3 (diff)
NFS: Convert lookups of the lock context to RCU
Speed up lookups of an existing lock context by avoiding the inode->i_lock, and using RCU instead. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r--fs/nfs/inode.c25
1 files changed, 12 insertions, 13 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index b65aee481d13..09b3b7146ff4 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -857,15 +857,14 @@ static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
857 857
858static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context *ctx) 858static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context *ctx)
859{ 859{
860 struct nfs_lock_context *head = &ctx->lock_context; 860 struct nfs_lock_context *pos;
861 struct nfs_lock_context *pos = head;
862 861
863 do { 862 list_for_each_entry_rcu(pos, &ctx->lock_context.list, list) {
864 if (pos->lockowner != current->files) 863 if (pos->lockowner != current->files)
865 continue; 864 continue;
866 refcount_inc(&pos->count); 865 if (refcount_inc_not_zero(&pos->count))
867 return pos; 866 return pos;
868 } while ((pos = list_entry(pos->list.next, typeof(*pos), list)) != head); 867 }
869 return NULL; 868 return NULL;
870} 869}
871 870
@@ -874,10 +873,10 @@ struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx)
874 struct nfs_lock_context *res, *new = NULL; 873 struct nfs_lock_context *res, *new = NULL;
875 struct inode *inode = d_inode(ctx->dentry); 874 struct inode *inode = d_inode(ctx->dentry);
876 875
877 spin_lock(&inode->i_lock); 876 rcu_read_lock();
878 res = __nfs_find_lock_context(ctx); 877 res = __nfs_find_lock_context(ctx);
878 rcu_read_unlock();
879 if (res == NULL) { 879 if (res == NULL) {
880 spin_unlock(&inode->i_lock);
881 new = kmalloc(sizeof(*new), GFP_KERNEL); 880 new = kmalloc(sizeof(*new), GFP_KERNEL);
882 if (new == NULL) 881 if (new == NULL)
883 return ERR_PTR(-ENOMEM); 882 return ERR_PTR(-ENOMEM);
@@ -885,14 +884,14 @@ struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx)
885 spin_lock(&inode->i_lock); 884 spin_lock(&inode->i_lock);
886 res = __nfs_find_lock_context(ctx); 885 res = __nfs_find_lock_context(ctx);
887 if (res == NULL) { 886 if (res == NULL) {
888 list_add_tail(&new->list, &ctx->lock_context.list); 887 list_add_tail_rcu(&new->list, &ctx->lock_context.list);
889 new->open_context = ctx; 888 new->open_context = ctx;
890 res = new; 889 res = new;
891 new = NULL; 890 new = NULL;
892 } 891 }
892 spin_unlock(&inode->i_lock);
893 kfree(new);
893 } 894 }
894 spin_unlock(&inode->i_lock);
895 kfree(new);
896 return res; 895 return res;
897} 896}
898EXPORT_SYMBOL_GPL(nfs_get_lock_context); 897EXPORT_SYMBOL_GPL(nfs_get_lock_context);
@@ -904,9 +903,9 @@ void nfs_put_lock_context(struct nfs_lock_context *l_ctx)
904 903
905 if (!refcount_dec_and_lock(&l_ctx->count, &inode->i_lock)) 904 if (!refcount_dec_and_lock(&l_ctx->count, &inode->i_lock))
906 return; 905 return;
907 list_del(&l_ctx->list); 906 list_del_rcu(&l_ctx->list);
908 spin_unlock(&inode->i_lock); 907 spin_unlock(&inode->i_lock);
909 kfree(l_ctx); 908 kfree_rcu(l_ctx, rcu_head);
910} 909}
911EXPORT_SYMBOL_GPL(nfs_put_lock_context); 910EXPORT_SYMBOL_GPL(nfs_put_lock_context);
912 911