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