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