b7d4d7
From b3a17b67a69142eef1b4adde3409d5e54dda1e0b Mon Sep 17 00:00:00 2001
b7d4d7
From: Amar Tumballi <amarts@redhat.com>
b7d4d7
Date: Sat, 9 Feb 2019 13:23:06 +0530
b7d4d7
Subject: [PATCH 507/511] inode: make critical section smaller
b7d4d7
b7d4d7
do all the 'static' tasks outside of locked region.
b7d4d7
b7d4d7
* hash_dentry() and hash_gfid() are now called outside locked region.
b7d4d7
* remove extra __dentry_hash exported in libglusterfs.sym
b7d4d7
* avoid checks in locked functions, if the check is done in calling
b7d4d7
  function.
b7d4d7
* implement dentry_destroy(), which handles freeing of dentry separately,
b7d4d7
  from that of dentry_unset (which takes care of separating dentry from
b7d4d7
  inode, and table)
b7d4d7
b7d4d7
> Updates: bz#1670031
b7d4d7
> Change-Id: I584213e0748464bb427fbdef3c4ab6615d7d5eb0
b7d4d7
> Signed-off-by: Amar Tumballi <amarts@redhat.com>
b7d4d7
> (Cherry pick from commit 8a90d346b9d3f69ff11241feb0011c90a8e57e30)
b7d4d7
> (Review on upstream link https://review.gluster.org/#/c/glusterfs/+/22184/)
b7d4d7
b7d4d7
Change-Id: I584213e0748464bb427fbdef3c4ab6615d7d5eb0
b7d4d7
BUG: 1898777
b7d4d7
Signed-off-by: Mohit Agrawal <moagrawa@redhat.com>
b7d4d7
Reviewed-on: https://code.engineering.redhat.com/gerrit/221189
b7d4d7
Tested-by: RHGS Build Bot <nigelb@redhat.com>
b7d4d7
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
b7d4d7
---
b7d4d7
 libglusterfs/src/glusterfs/inode.h |   3 -
b7d4d7
 libglusterfs/src/inode.c           | 323 +++++++++++++------------------------
b7d4d7
 libglusterfs/src/libglusterfs.sym  |   1 -
b7d4d7
 3 files changed, 111 insertions(+), 216 deletions(-)
b7d4d7
b7d4d7
diff --git a/libglusterfs/src/glusterfs/inode.h b/libglusterfs/src/glusterfs/inode.h
b7d4d7
index 4421c47..c875653 100644
b7d4d7
--- a/libglusterfs/src/glusterfs/inode.h
b7d4d7
+++ b/libglusterfs/src/glusterfs/inode.h
b7d4d7
@@ -167,9 +167,6 @@ inode_rename(inode_table_t *table, inode_t *olddir, const char *oldname,
b7d4d7
              inode_t *newdir, const char *newname, inode_t *inode,
b7d4d7
              struct iatt *stbuf);
b7d4d7
 
b7d4d7
-dentry_t *
b7d4d7
-__dentry_grep(inode_table_t *table, inode_t *parent, const char *name);
b7d4d7
-
b7d4d7
 inode_t *
b7d4d7
 inode_grep(inode_table_t *table, inode_t *parent, const char *name);
b7d4d7
 
b7d4d7
diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c
b7d4d7
index 4c3c546..71b2d2a 100644
b7d4d7
--- a/libglusterfs/src/inode.c
b7d4d7
+++ b/libglusterfs/src/inode.c
b7d4d7
@@ -159,27 +159,15 @@ hash_dentry(inode_t *parent, const char *name, int mod)
b7d4d7
 static int
b7d4d7
 hash_gfid(uuid_t uuid, int mod)
b7d4d7
 {
b7d4d7
-    int ret = 0;
b7d4d7
-
b7d4d7
-    ret = uuid[15] + (uuid[14] << 8);
b7d4d7
-
b7d4d7
-    return ret;
b7d4d7
+    return ((uuid[15] + (uuid[14] << 8)) % mod);
b7d4d7
 }
b7d4d7
 
b7d4d7
 static void
b7d4d7
-__dentry_hash(dentry_t *dentry)
b7d4d7
+__dentry_hash(dentry_t *dentry, const int hash)
b7d4d7
 {
b7d4d7
     inode_table_t *table = NULL;
b7d4d7
-    int hash = 0;
b7d4d7
-
b7d4d7
-    if (!dentry) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_DENTRY_NOT_FOUND,
b7d4d7
-                         "dentry not found");
b7d4d7
-        return;
b7d4d7
-    }
b7d4d7
 
b7d4d7
     table = dentry->inode->table;
b7d4d7
-    hash = hash_dentry(dentry->parent, dentry->name, table->hashsize);
b7d4d7
 
b7d4d7
     list_del_init(&dentry->hash);
b7d4d7
     list_add(&dentry->hash, &table->name_hash[hash]);
b7d4d7
@@ -188,49 +176,44 @@ __dentry_hash(dentry_t *dentry)
b7d4d7
 static int
b7d4d7
 __is_dentry_hashed(dentry_t *dentry)
b7d4d7
 {
b7d4d7
-    if (!dentry) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_DENTRY_NOT_FOUND,
b7d4d7
-                         "dentry not found");
b7d4d7
-        return 0;
b7d4d7
-    }
b7d4d7
-
b7d4d7
     return !list_empty(&dentry->hash);
b7d4d7
 }
b7d4d7
 
b7d4d7
 static void
b7d4d7
 __dentry_unhash(dentry_t *dentry)
b7d4d7
 {
b7d4d7
-    if (!dentry) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_DENTRY_NOT_FOUND,
b7d4d7
-                         "dentry not found");
b7d4d7
-        return;
b7d4d7
-    }
b7d4d7
-
b7d4d7
     list_del_init(&dentry->hash);
b7d4d7
 }
b7d4d7
 
b7d4d7
 static void
b7d4d7
-__dentry_unset(dentry_t *dentry)
b7d4d7
+dentry_destroy(dentry_t *dentry)
b7d4d7
 {
b7d4d7
-    if (!dentry) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_DENTRY_NOT_FOUND,
b7d4d7
-                         "dentry not found");
b7d4d7
+    if (!dentry)
b7d4d7
         return;
b7d4d7
-    }
b7d4d7
+
b7d4d7
+    GF_FREE(dentry->name);
b7d4d7
+    dentry->name = NULL;
b7d4d7
+    mem_put(dentry);
b7d4d7
+
b7d4d7
+    return;
b7d4d7
+}
b7d4d7
+
b7d4d7
+static dentry_t *
b7d4d7
+__dentry_unset(dentry_t *dentry)
b7d4d7
+{
b7d4d7
+    if (!dentry)
b7d4d7
+        return NULL;
b7d4d7
 
b7d4d7
     __dentry_unhash(dentry);
b7d4d7
 
b7d4d7
     list_del_init(&dentry->inode_list);
b7d4d7
 
b7d4d7
-    GF_FREE(dentry->name);
b7d4d7
-    dentry->name = NULL;
b7d4d7
-
b7d4d7
     if (dentry->parent) {
b7d4d7
         __inode_unref(dentry->parent, false);
b7d4d7
         dentry->parent = NULL;
b7d4d7
     }
b7d4d7
 
b7d4d7
-    mem_put(dentry);
b7d4d7
+    return dentry;
b7d4d7
 }
b7d4d7
 
b7d4d7
 static int
b7d4d7
@@ -289,22 +272,14 @@ static int
b7d4d7
 __is_dentry_cyclic(dentry_t *dentry)
b7d4d7
 {
b7d4d7
     int ret = 0;
b7d4d7
-    inode_t *inode = NULL;
b7d4d7
-    char *name = "<nul>";
b7d4d7
 
b7d4d7
     ret = __foreach_ancestor_dentry(dentry, __check_cycle, dentry->inode);
b7d4d7
     if (ret) {
b7d4d7
-        inode = dentry->inode;
b7d4d7
-
b7d4d7
-        if (dentry->name)
b7d4d7
-            name = dentry->name;
b7d4d7
-
b7d4d7
         gf_msg(dentry->inode->table->name, GF_LOG_CRITICAL, 0,
b7d4d7
                LG_MSG_DENTRY_CYCLIC_LOOP,
b7d4d7
-               "detected cyclic loop "
b7d4d7
-               "formation during inode linkage. inode (%s) linking "
b7d4d7
-               "under itself as %s",
b7d4d7
-               uuid_utoa(inode->gfid), name);
b7d4d7
+               "detected cyclic loop formation during inode linkage. "
b7d4d7
+               "inode (%s) linking under itself as %s",
b7d4d7
+               uuid_utoa(dentry->inode->gfid), dentry->name);
b7d4d7
     }
b7d4d7
 
b7d4d7
     return ret;
b7d4d7
@@ -313,41 +288,19 @@ __is_dentry_cyclic(dentry_t *dentry)
b7d4d7
 static void
b7d4d7
 __inode_unhash(inode_t *inode)
b7d4d7
 {
b7d4d7
-    if (!inode) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_INODE_NOT_FOUND,
b7d4d7
-                         "inode not found");
b7d4d7
-        return;
b7d4d7
-    }
b7d4d7
-
b7d4d7
     list_del_init(&inode->hash);
b7d4d7
 }
b7d4d7
 
b7d4d7
 static int
b7d4d7
 __is_inode_hashed(inode_t *inode)
b7d4d7
 {
b7d4d7
-    if (!inode) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_INODE_NOT_FOUND,
b7d4d7
-                         "inode not found");
b7d4d7
-        return 0;
b7d4d7
-    }
b7d4d7
-
b7d4d7
     return !list_empty(&inode->hash);
b7d4d7
 }
b7d4d7
 
b7d4d7
 static void
b7d4d7
-__inode_hash(inode_t *inode)
b7d4d7
+__inode_hash(inode_t *inode, const int hash)
b7d4d7
 {
b7d4d7
-    inode_table_t *table = NULL;
b7d4d7
-    int hash = 0;
b7d4d7
-
b7d4d7
-    if (!inode) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_INODE_NOT_FOUND,
b7d4d7
-                         "inode not found");
b7d4d7
-        return;
b7d4d7
-    }
b7d4d7
-
b7d4d7
-    table = inode->table;
b7d4d7
-    hash = hash_gfid(inode->gfid, 65536);
b7d4d7
+    inode_table_t *table = inode->table;
b7d4d7
 
b7d4d7
     list_del_init(&inode->hash);
b7d4d7
     list_add(&inode->hash, &table->inode_hash[hash]);
b7d4d7
@@ -359,12 +312,6 @@ __dentry_search_for_inode(inode_t *inode, uuid_t pargfid, const char *name)
b7d4d7
     dentry_t *dentry = NULL;
b7d4d7
     dentry_t *tmp = NULL;
b7d4d7
 
b7d4d7
-    if (!inode || !name) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
b7d4d7
-                         "inode || name not found");
b7d4d7
-        return NULL;
b7d4d7
-    }
b7d4d7
-
b7d4d7
     /* earlier, just the ino was sent, which could have been 0, now
b7d4d7
        we deal with gfid, and if sent gfid is null or 0, no need to
b7d4d7
        continue with the check */
b7d4d7
@@ -390,12 +337,6 @@ __inode_ctx_free(inode_t *inode)
b7d4d7
     xlator_t *xl = NULL;
b7d4d7
     xlator_t *old_THIS = NULL;
b7d4d7
 
b7d4d7
-    if (!inode) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_INODE_NOT_FOUND,
b7d4d7
-                         "inode not found");
b7d4d7
-        return;
b7d4d7
-    }
b7d4d7
-
b7d4d7
     if (!inode->_ctx) {
b7d4d7
         gf_msg(THIS->name, GF_LOG_WARNING, 0, LG_MSG_CTX_NULL,
b7d4d7
                "_ctx not found");
b7d4d7
@@ -424,12 +365,6 @@ noctx:
b7d4d7
 static void
b7d4d7
 __inode_destroy(inode_t *inode)
b7d4d7
 {
b7d4d7
-    if (!inode) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_INODE_NOT_FOUND,
b7d4d7
-                         "inode not found");
b7d4d7
-        return;
b7d4d7
-    }
b7d4d7
-
b7d4d7
     __inode_ctx_free(inode);
b7d4d7
 
b7d4d7
     LOCK_DESTROY(&inode->lock);
b7d4d7
@@ -472,9 +407,6 @@ inode_ctx_merge(fd_t *fd, inode_t *inode, inode_t *linked_inode)
b7d4d7
 static void
b7d4d7
 __inode_activate(inode_t *inode)
b7d4d7
 {
b7d4d7
-    if (!inode)
b7d4d7
-        return;
b7d4d7
-
b7d4d7
     list_move(&inode->list, &inode->table->active);
b7d4d7
     inode->table->active_size++;
b7d4d7
 }
b7d4d7
@@ -485,19 +417,13 @@ __inode_passivate(inode_t *inode)
b7d4d7
     dentry_t *dentry = NULL;
b7d4d7
     dentry_t *t = NULL;
b7d4d7
 
b7d4d7
-    if (!inode) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_INODE_NOT_FOUND,
b7d4d7
-                         "inode not found");
b7d4d7
-        return;
b7d4d7
-    }
b7d4d7
-
b7d4d7
     list_move_tail(&inode->list, &inode->table->lru);
b7d4d7
     inode->table->lru_size++;
b7d4d7
 
b7d4d7
     list_for_each_entry_safe(dentry, t, &inode->dentry_list, inode_list)
b7d4d7
     {
b7d4d7
         if (!__is_dentry_hashed(dentry))
b7d4d7
-            __dentry_unset(dentry);
b7d4d7
+            dentry_destroy(__dentry_unset(dentry));
b7d4d7
     }
b7d4d7
 }
b7d4d7
 
b7d4d7
@@ -507,12 +433,6 @@ __inode_retire(inode_t *inode)
b7d4d7
     dentry_t *dentry = NULL;
b7d4d7
     dentry_t *t = NULL;
b7d4d7
 
b7d4d7
-    if (!inode) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_INODE_NOT_FOUND,
b7d4d7
-                         "inode not found");
b7d4d7
-        return;
b7d4d7
-    }
b7d4d7
-
b7d4d7
     list_move_tail(&inode->list, &inode->table->purge);
b7d4d7
     inode->table->purge_size++;
b7d4d7
 
b7d4d7
@@ -520,7 +440,7 @@ __inode_retire(inode_t *inode)
b7d4d7
 
b7d4d7
     list_for_each_entry_safe(dentry, t, &inode->dentry_list, inode_list)
b7d4d7
     {
b7d4d7
-        __dentry_unset(dentry);
b7d4d7
+        dentry_destroy(__dentry_unset(dentry));
b7d4d7
     }
b7d4d7
 }
b7d4d7
 
b7d4d7
@@ -547,9 +467,6 @@ __inode_unref(inode_t *inode, bool clear)
b7d4d7
     xlator_t *this = NULL;
b7d4d7
     uint64_t nlookup = 0;
b7d4d7
 
b7d4d7
-    if (!inode)
b7d4d7
-        return NULL;
b7d4d7
-
b7d4d7
     /*
b7d4d7
      * Root inode should always be in active list of inode table. So unrefs
b7d4d7
      * on root inode are no-ops.
b7d4d7
@@ -677,16 +594,10 @@ inode_ref(inode_t *inode)
b7d4d7
 }
b7d4d7
 
b7d4d7
 static dentry_t *
b7d4d7
-__dentry_create(inode_t *inode, inode_t *parent, const char *name)
b7d4d7
+dentry_create(inode_t *inode, inode_t *parent, const char *name)
b7d4d7
 {
b7d4d7
     dentry_t *newd = NULL;
b7d4d7
 
b7d4d7
-    if (!inode || !parent || !name) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
b7d4d7
-                         "inode || parent || name not found");
b7d4d7
-        return NULL;
b7d4d7
-    }
b7d4d7
-
b7d4d7
     newd = mem_get0(parent->table->dentry_pool);
b7d4d7
     if (newd == NULL) {
b7d4d7
         goto out;
b7d4d7
@@ -702,10 +613,6 @@ __dentry_create(inode_t *inode, inode_t *parent, const char *name)
b7d4d7
         goto out;
b7d4d7
     }
b7d4d7
 
b7d4d7
-    if (parent)
b7d4d7
-        newd->parent = __inode_ref(parent, false);
b7d4d7
-
b7d4d7
-    list_add(&newd->inode_list, &inode->dentry_list);
b7d4d7
     newd->inode = inode;
b7d4d7
 
b7d4d7
 out:
b7d4d7
@@ -717,14 +624,6 @@ __inode_create(inode_table_t *table)
b7d4d7
 {
b7d4d7
     inode_t *newi = NULL;
b7d4d7
 
b7d4d7
-    if (!table) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0,
b7d4d7
-                         LG_MSG_INODE_TABLE_NOT_FOUND,
b7d4d7
-                         "table not "
b7d4d7
-                         "found");
b7d4d7
-        return NULL;
b7d4d7
-    }
b7d4d7
-
b7d4d7
     newi = mem_get0(table->inode_pool);
b7d4d7
     if (!newi) {
b7d4d7
         goto out;
b7d4d7
@@ -795,9 +694,6 @@ __inode_ref_reduce_by_n(inode_t *inode, uint64_t nref)
b7d4d7
 {
b7d4d7
     uint64_t nlookup = 0;
b7d4d7
 
b7d4d7
-    if (!inode)
b7d4d7
-        return NULL;
b7d4d7
-
b7d4d7
     GF_ASSERT(inode->ref >= nref);
b7d4d7
 
b7d4d7
     inode->ref -= nref;
b7d4d7
@@ -837,17 +733,12 @@ inode_forget_atomic(inode_t *inode, uint64_t nlookup)
b7d4d7
 }
b7d4d7
 
b7d4d7
 dentry_t *
b7d4d7
-__dentry_grep(inode_table_t *table, inode_t *parent, const char *name)
b7d4d7
+__dentry_grep(inode_table_t *table, inode_t *parent, const char *name,
b7d4d7
+              const int hash)
b7d4d7
 {
b7d4d7
-    int hash = 0;
b7d4d7
     dentry_t *dentry = NULL;
b7d4d7
     dentry_t *tmp = NULL;
b7d4d7
 
b7d4d7
-    if (!table || !name || !parent)
b7d4d7
-        return NULL;
b7d4d7
-
b7d4d7
-    hash = hash_dentry(parent, name, table->hashsize);
b7d4d7
-
b7d4d7
     list_for_each_entry(tmp, &table->name_hash[hash], hash)
b7d4d7
     {
b7d4d7
         if (tmp->parent == parent && !strcmp(tmp->name, name)) {
b7d4d7
@@ -872,15 +763,16 @@ inode_grep(inode_table_t *table, inode_t *parent, const char *name)
b7d4d7
         return NULL;
b7d4d7
     }
b7d4d7
 
b7d4d7
+    int hash = hash_dentry(parent, name, table->hashsize);
b7d4d7
+
b7d4d7
     pthread_mutex_lock(&table->lock);
b7d4d7
     {
b7d4d7
-        dentry = __dentry_grep(table, parent, name);
b7d4d7
-
b7d4d7
-        if (dentry)
b7d4d7
+        dentry = __dentry_grep(table, parent, name, hash);
b7d4d7
+        if (dentry) {
b7d4d7
             inode = dentry->inode;
b7d4d7
-
b7d4d7
-        if (inode)
b7d4d7
-            __inode_ref(inode, false);
b7d4d7
+            if (inode)
b7d4d7
+                __inode_ref(inode, false);
b7d4d7
+        }
b7d4d7
     }
b7d4d7
     pthread_mutex_unlock(&table->lock);
b7d4d7
 
b7d4d7
@@ -947,17 +839,18 @@ inode_grep_for_gfid(inode_table_t *table, inode_t *parent, const char *name,
b7d4d7
         return ret;
b7d4d7
     }
b7d4d7
 
b7d4d7
+    int hash = hash_dentry(parent, name, table->hashsize);
b7d4d7
+
b7d4d7
     pthread_mutex_lock(&table->lock);
b7d4d7
     {
b7d4d7
-        dentry = __dentry_grep(table, parent, name);
b7d4d7
-
b7d4d7
-        if (dentry)
b7d4d7
+        dentry = __dentry_grep(table, parent, name, hash);
b7d4d7
+        if (dentry) {
b7d4d7
             inode = dentry->inode;
b7d4d7
-
b7d4d7
-        if (inode) {
b7d4d7
-            gf_uuid_copy(gfid, inode->gfid);
b7d4d7
-            *type = inode->ia_type;
b7d4d7
-            ret = 0;
b7d4d7
+            if (inode) {
b7d4d7
+                gf_uuid_copy(gfid, inode->gfid);
b7d4d7
+                *type = inode->ia_type;
b7d4d7
+                ret = 0;
b7d4d7
+            }
b7d4d7
         }
b7d4d7
     }
b7d4d7
     pthread_mutex_unlock(&table->lock);
b7d4d7
@@ -978,25 +871,14 @@ __is_root_gfid(uuid_t gfid)
b7d4d7
 }
b7d4d7
 
b7d4d7
 inode_t *
b7d4d7
-__inode_find(inode_table_t *table, uuid_t gfid)
b7d4d7
+__inode_find(inode_table_t *table, uuid_t gfid, const int hash)
b7d4d7
 {
b7d4d7
     inode_t *inode = NULL;
b7d4d7
     inode_t *tmp = NULL;
b7d4d7
-    int hash = 0;
b7d4d7
-
b7d4d7
-    if (!table) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0,
b7d4d7
-                         LG_MSG_INODE_TABLE_NOT_FOUND,
b7d4d7
-                         "table not "
b7d4d7
-                         "found");
b7d4d7
-        goto out;
b7d4d7
-    }
b7d4d7
 
b7d4d7
     if (__is_root_gfid(gfid))
b7d4d7
         return table->root;
b7d4d7
 
b7d4d7
-    hash = hash_gfid(gfid, 65536);
b7d4d7
-
b7d4d7
     list_for_each_entry(tmp, &table->inode_hash[hash], hash)
b7d4d7
     {
b7d4d7
         if (gf_uuid_compare(tmp->gfid, gfid) == 0) {
b7d4d7
@@ -1005,7 +887,6 @@ __inode_find(inode_table_t *table, uuid_t gfid)
b7d4d7
         }
b7d4d7
     }
b7d4d7
 
b7d4d7
-out:
b7d4d7
     return inode;
b7d4d7
 }
b7d4d7
 
b7d4d7
@@ -1022,9 +903,11 @@ inode_find(inode_table_t *table, uuid_t gfid)
b7d4d7
         return NULL;
b7d4d7
     }
b7d4d7
 
b7d4d7
+    int hash = hash_gfid(gfid, 65536);
b7d4d7
+
b7d4d7
     pthread_mutex_lock(&table->lock);
b7d4d7
     {
b7d4d7
-        inode = __inode_find(table, gfid);
b7d4d7
+        inode = __inode_find(table, gfid, hash);
b7d4d7
         if (inode)
b7d4d7
             __inode_ref(inode, false);
b7d4d7
     }
b7d4d7
@@ -1035,7 +918,7 @@ inode_find(inode_table_t *table, uuid_t gfid)
b7d4d7
 
b7d4d7
 static inode_t *
b7d4d7
 __inode_link(inode_t *inode, inode_t *parent, const char *name,
b7d4d7
-             struct iatt *iatt)
b7d4d7
+             struct iatt *iatt, const int dhash)
b7d4d7
 {
b7d4d7
     dentry_t *dentry = NULL;
b7d4d7
     dentry_t *old_dentry = NULL;
b7d4d7
@@ -1043,16 +926,7 @@ __inode_link(inode_t *inode, inode_t *parent, const char *name,
b7d4d7
     inode_table_t *table = NULL;
b7d4d7
     inode_t *link_inode = NULL;
b7d4d7
 
b7d4d7
-    if (!inode) {
b7d4d7
-        errno = EINVAL;
b7d4d7
-        return NULL;
b7d4d7
-    }
b7d4d7
-
b7d4d7
     table = inode->table;
b7d4d7
-    if (!table) {
b7d4d7
-        errno = EINVAL;
b7d4d7
-        return NULL;
b7d4d7
-    }
b7d4d7
 
b7d4d7
     if (parent) {
b7d4d7
         /* We should prevent inode linking between different
b7d4d7
@@ -1090,14 +964,16 @@ __inode_link(inode_t *inode, inode_t *parent, const char *name,
b7d4d7
             return NULL;
b7d4d7
         }
b7d4d7
 
b7d4d7
-        old_inode = __inode_find(table, iatt->ia_gfid);
b7d4d7
+        int ihash = hash_gfid(iatt->ia_gfid, 65536);
b7d4d7
+
b7d4d7
+        old_inode = __inode_find(table, iatt->ia_gfid, ihash);
b7d4d7
 
b7d4d7
         if (old_inode) {
b7d4d7
             link_inode = old_inode;
b7d4d7
         } else {
b7d4d7
             gf_uuid_copy(inode->gfid, iatt->ia_gfid);
b7d4d7
             inode->ia_type = iatt->ia_type;
b7d4d7
-            __inode_hash(inode);
b7d4d7
+            __inode_hash(inode, ihash);
b7d4d7
         }
b7d4d7
     } else {
b7d4d7
         /* @old_inode serves another important purpose - it indicates
b7d4d7
@@ -1112,22 +988,16 @@ __inode_link(inode_t *inode, inode_t *parent, const char *name,
b7d4d7
         old_inode = inode;
b7d4d7
     }
b7d4d7
 
b7d4d7
-    if (name) {
b7d4d7
-        if (!strcmp(name, ".") || !strcmp(name, ".."))
b7d4d7
-            return link_inode;
b7d4d7
-
b7d4d7
-        if (strchr(name, '/')) {
b7d4d7
-            GF_ASSERT(!"inode link attempted with '/' in name");
b7d4d7
-            return NULL;
b7d4d7
-        }
b7d4d7
+    if (name && (!strcmp(name, ".") || !strcmp(name, ".."))) {
b7d4d7
+        return link_inode;
b7d4d7
     }
b7d4d7
 
b7d4d7
     /* use only link_inode beyond this point */
b7d4d7
     if (parent) {
b7d4d7
-        old_dentry = __dentry_grep(table, parent, name);
b7d4d7
+        old_dentry = __dentry_grep(table, parent, name, dhash);
b7d4d7
 
b7d4d7
         if (!old_dentry || old_dentry->inode != link_inode) {
b7d4d7
-            dentry = __dentry_create(link_inode, parent, name);
b7d4d7
+            dentry = dentry_create(link_inode, parent, name);
b7d4d7
             if (!dentry) {
b7d4d7
                 gf_msg_callingfn(
b7d4d7
                     THIS->name, GF_LOG_ERROR, 0, LG_MSG_DENTRY_CREATE_FAILED,
b7d4d7
@@ -1137,15 +1007,20 @@ __inode_link(inode_t *inode, inode_t *parent, const char *name,
b7d4d7
                 errno = ENOMEM;
b7d4d7
                 return NULL;
b7d4d7
             }
b7d4d7
+
b7d4d7
+            /* dentry linking needs to happen inside lock */
b7d4d7
+            dentry->parent = __inode_ref(parent, false);
b7d4d7
+            list_add(&dentry->inode_list, &link_inode->dentry_list);
b7d4d7
+
b7d4d7
             if (old_inode && __is_dentry_cyclic(dentry)) {
b7d4d7
                 errno = ELOOP;
b7d4d7
-                __dentry_unset(dentry);
b7d4d7
+                dentry_destroy(__dentry_unset(dentry));
b7d4d7
                 return NULL;
b7d4d7
             }
b7d4d7
-            __dentry_hash(dentry);
b7d4d7
+            __dentry_hash(dentry, dhash);
b7d4d7
 
b7d4d7
             if (old_dentry)
b7d4d7
-                __dentry_unset(old_dentry);
b7d4d7
+                dentry_destroy(__dentry_unset(old_dentry));
b7d4d7
         }
b7d4d7
     }
b7d4d7
 
b7d4d7
@@ -1155,6 +1030,7 @@ __inode_link(inode_t *inode, inode_t *parent, const char *name,
b7d4d7
 inode_t *
b7d4d7
 inode_link(inode_t *inode, inode_t *parent, const char *name, struct iatt *iatt)
b7d4d7
 {
b7d4d7
+    int hash = 0;
b7d4d7
     inode_table_t *table = NULL;
b7d4d7
     inode_t *linked_inode = NULL;
b7d4d7
 
b7d4d7
@@ -1166,10 +1042,18 @@ inode_link(inode_t *inode, inode_t *parent, const char *name, struct iatt *iatt)
b7d4d7
 
b7d4d7
     table = inode->table;
b7d4d7
 
b7d4d7
+    if (parent && name) {
b7d4d7
+        hash = hash_dentry(parent, name, table->hashsize);
b7d4d7
+    }
b7d4d7
+
b7d4d7
+    if (name && strchr(name, '/')) {
b7d4d7
+        GF_ASSERT(!"inode link attempted with '/' in name");
b7d4d7
+        return NULL;
b7d4d7
+    }
b7d4d7
+
b7d4d7
     pthread_mutex_lock(&table->lock);
b7d4d7
     {
b7d4d7
-        linked_inode = __inode_link(inode, parent, name, iatt);
b7d4d7
-
b7d4d7
+        linked_inode = __inode_link(inode, parent, name, iatt, hash);
b7d4d7
         if (linked_inode)
b7d4d7
             __inode_ref(linked_inode, false);
b7d4d7
     }
b7d4d7
@@ -1312,48 +1196,47 @@ inode_invalidate(inode_t *inode)
b7d4d7
     return ret;
b7d4d7
 }
b7d4d7
 
b7d4d7
-static void
b7d4d7
+static dentry_t *
b7d4d7
 __inode_unlink(inode_t *inode, inode_t *parent, const char *name)
b7d4d7
 {
b7d4d7
     dentry_t *dentry = NULL;
b7d4d7
     char pgfid[64] = {0};
b7d4d7
     char gfid[64] = {0};
b7d4d7
 
b7d4d7
-    if (!inode || !parent || !name)
b7d4d7
-        return;
b7d4d7
-
b7d4d7
     dentry = __dentry_search_for_inode(inode, parent->gfid, name);
b7d4d7
 
b7d4d7
     /* dentry NULL for corrupted backend */
b7d4d7
     if (dentry) {
b7d4d7
-        __dentry_unset(dentry);
b7d4d7
+        dentry = __dentry_unset(dentry);
b7d4d7
     } else {
b7d4d7
         gf_msg("inode", GF_LOG_WARNING, 0, LG_MSG_DENTRY_NOT_FOUND,
b7d4d7
                "%s/%s: dentry not found in %s",
b7d4d7
                uuid_utoa_r(parent->gfid, pgfid), name,
b7d4d7
                uuid_utoa_r(inode->gfid, gfid));
b7d4d7
     }
b7d4d7
+
b7d4d7
+    return dentry;
b7d4d7
 }
b7d4d7
 
b7d4d7
 void
b7d4d7
 inode_unlink(inode_t *inode, inode_t *parent, const char *name)
b7d4d7
 {
b7d4d7
-    inode_table_t *table = NULL;
b7d4d7
+    inode_table_t *table;
b7d4d7
+    dentry_t *dentry;
b7d4d7
 
b7d4d7
-    if (!inode) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_INODE_NOT_FOUND,
b7d4d7
-                         "inode not found");
b7d4d7
+    if (!inode || !parent || !name)
b7d4d7
         return;
b7d4d7
-    }
b7d4d7
 
b7d4d7
     table = inode->table;
b7d4d7
 
b7d4d7
     pthread_mutex_lock(&table->lock);
b7d4d7
     {
b7d4d7
-        __inode_unlink(inode, parent, name);
b7d4d7
+        dentry = __inode_unlink(inode, parent, name);
b7d4d7
     }
b7d4d7
     pthread_mutex_unlock(&table->lock);
b7d4d7
 
b7d4d7
+    dentry_destroy(dentry);
b7d4d7
+
b7d4d7
     inode_table_prune(table);
b7d4d7
 }
b7d4d7
 
b7d4d7
@@ -1362,6 +1245,9 @@ inode_rename(inode_table_t *table, inode_t *srcdir, const char *srcname,
b7d4d7
              inode_t *dstdir, const char *dstname, inode_t *inode,
b7d4d7
              struct iatt *iatt)
b7d4d7
 {
b7d4d7
+    int hash = 0;
b7d4d7
+    dentry_t *dentry = NULL;
b7d4d7
+
b7d4d7
     if (!inode) {
b7d4d7
         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_INODE_NOT_FOUND,
b7d4d7
                          "inode not found");
b7d4d7
@@ -1370,13 +1256,26 @@ inode_rename(inode_table_t *table, inode_t *srcdir, const char *srcname,
b7d4d7
 
b7d4d7
     table = inode->table;
b7d4d7
 
b7d4d7
+    if (dstname && strchr(dstname, '/')) {
b7d4d7
+        GF_ASSERT(!"inode link attempted with '/' in name");
b7d4d7
+        return -1;
b7d4d7
+    }
b7d4d7
+
b7d4d7
+    if (dstdir && dstname) {
b7d4d7
+        hash = hash_dentry(dstdir, dstname, table->hashsize);
b7d4d7
+    }
b7d4d7
+
b7d4d7
     pthread_mutex_lock(&table->lock);
b7d4d7
     {
b7d4d7
-        __inode_link(inode, dstdir, dstname, iatt);
b7d4d7
-        __inode_unlink(inode, srcdir, srcname);
b7d4d7
+        __inode_link(inode, dstdir, dstname, iatt, hash);
b7d4d7
+        /* pick the old dentry */
b7d4d7
+        dentry = __inode_unlink(inode, srcdir, srcname);
b7d4d7
     }
b7d4d7
     pthread_mutex_unlock(&table->lock);
b7d4d7
 
b7d4d7
+    /* free the old dentry */
b7d4d7
+    dentry_destroy(dentry);
b7d4d7
+
b7d4d7
     inode_table_prune(table);
b7d4d7
 
b7d4d7
     return 0;
b7d4d7
@@ -1447,12 +1346,6 @@ inode_parent(inode_t *inode, uuid_t pargfid, const char *name)
b7d4d7
 static int
b7d4d7
 __inode_has_dentry(inode_t *inode)
b7d4d7
 {
b7d4d7
-    if (!inode) {
b7d4d7
-        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_INODE_NOT_FOUND,
b7d4d7
-                         "inode not found");
b7d4d7
-        return 0;
b7d4d7
-    }
b7d4d7
-
b7d4d7
     return !list_empty(&inode->dentry_list);
b7d4d7
 }
b7d4d7
 
b7d4d7
@@ -1461,6 +1354,12 @@ inode_has_dentry(inode_t *inode)
b7d4d7
 {
b7d4d7
     int dentry_present = 0;
b7d4d7
 
b7d4d7
+    if (!inode) {
b7d4d7
+        gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0, LG_MSG_INODE_NOT_FOUND,
b7d4d7
+                         "inode not found");
b7d4d7
+        return 0;
b7d4d7
+    }
b7d4d7
+
b7d4d7
     LOCK(&inode->lock);
b7d4d7
     {
b7d4d7
         dentry_present = __inode_has_dentry(inode);
b7d4d7
@@ -1720,7 +1619,7 @@ __inode_table_init_root(inode_table_t *table)
b7d4d7
     iatt.ia_ino = 1;
b7d4d7
     iatt.ia_type = IA_IFDIR;
b7d4d7
 
b7d4d7
-    __inode_link(root, NULL, NULL, &iatt);
b7d4d7
+    __inode_link(root, NULL, NULL, &iatt, 0);
b7d4d7
     table->root = root;
b7d4d7
 }
b7d4d7
 
b7d4d7
diff --git a/libglusterfs/src/libglusterfs.sym b/libglusterfs/src/libglusterfs.sym
b7d4d7
index 5a721e0..d060292 100644
b7d4d7
--- a/libglusterfs/src/libglusterfs.sym
b7d4d7
+++ b/libglusterfs/src/libglusterfs.sym
b7d4d7
@@ -357,7 +357,6 @@ default_copy_file_range
b7d4d7
 default_copy_file_range_cbk
b7d4d7
 default_copy_file_range_failure_cbk
b7d4d7
 default_copy_file_range_resume
b7d4d7
-__dentry_grep
b7d4d7
 dht_is_linkfile
b7d4d7
 dict_add
b7d4d7
 dict_addn
b7d4d7
-- 
b7d4d7
1.8.3.1
b7d4d7