Blob Blame History Raw
From 7b65a8599465354462ec420f9124a3e4b0aa03dc Mon Sep 17 00:00:00 2001
From: Raghavendra G <rgowdapp@redhat.com>
Date: Wed, 11 May 2016 17:49:10 +0530
Subject: [PATCH 157/158] cluster/distribute: use a linked inode in directory heal codepath

This is needed for following reasons:
* healing is done in lookup and mkdir codepath where inode is not
  linked _yet_ as normally linking is done in interface layers
  (fuse-bridge, gfapi, nfsv3 etc).

* healing consists of non-lookup fops like inodelk, setattr, setxattr
  etc. All non-lookup fops expect a linked inode.

Change-Id: I1bda157baabe58431b7f6f6fffee0abfe5225342
BUG: 1325760
Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/74412
---
 xlators/cluster/dht/src/dht-common.c   |    2 +-
 xlators/cluster/dht/src/dht-selfheal.c |   67 +++++++++++++++++++++++++++-----
 2 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
index e9fcf47..10d47de 100644
--- a/xlators/cluster/dht/src/dht-common.c
+++ b/xlators/cluster/dht/src/dht-common.c
@@ -1605,7 +1605,7 @@ unwind_hashed_and_cached:
         DHT_STRIP_PHASE1_FLAGS (&local->stbuf);
         dht_set_fixed_dir_stat (&local->postparent);
         DHT_STACK_UNWIND (lookup, frame, local->op_ret, local->op_errno,
-                          local->loc.inode, &local->stbuf, local->xattr,
+                          local->inode, &local->stbuf, local->xattr,
                           &local->postparent);
         return 0;
 }
diff --git a/xlators/cluster/dht/src/dht-selfheal.c b/xlators/cluster/dht/src/dht-selfheal.c
index a70b3f7..83bbd0a 100644
--- a/xlators/cluster/dht/src/dht-selfheal.c
+++ b/xlators/cluster/dht/src/dht-selfheal.c
@@ -1957,23 +1957,50 @@ dht_selfheal_new_directory (call_frame_t *frame,
                             dht_selfheal_dir_cbk_t dir_cbk,
                             dht_layout_t *layout)
 {
-        dht_local_t *local = NULL;
-        int          ret   = 0;
+        dht_local_t *local                   = NULL;
+        int          ret                     = 0;
+        inode_t     *linked_inode            = NULL, *inode = NULL;
+        loc_t       *loc                     = NULL;
+        char         pgfid[GF_UUID_BUF_SIZE] = {0};
+        char         gfid[GF_UUID_BUF_SIZE]  = {0};
+        int32_t      op_errno                = EIO;
 
         local = frame->local;
 
+        loc = &local->loc;
+
+        gf_uuid_unparse(local->stbuf.ia_gfid, gfid);
+        gf_uuid_unparse(loc->parent->gfid, pgfid);
+
+        linked_inode = inode_link (loc->inode, loc->parent, loc->name,
+                                   &local->stbuf);
+        if (!linked_inode) {
+                gf_msg (frame->this->name, GF_LOG_WARNING, 0,
+                        DHT_MSG_DIR_SELFHEAL_FAILED,
+                        "linking inode failed (%s/%s) => %s",
+                        pgfid, loc->name, gfid);
+                ret = -1;
+                goto out;
+        }
+
+        inode = loc->inode;
+        loc->inode = linked_inode;
+        inode_unref (inode);
+
         local->selfheal.dir_cbk = dir_cbk;
         local->selfheal.layout = dht_layout_ref (frame->this, layout);
 
         dht_layout_sort_volname (layout);
         dht_selfheal_layout_new_directory (frame, &local->loc, layout);
 
+        op_errno = ENOMEM;
         ret = dht_selfheal_layout_lock (frame, layout, _gf_true,
                                         dht_selfheal_dir_xattr,
                                         dht_should_heal_layout);
 
+out:
         if (ret < 0) {
-                dir_cbk (frame, NULL, frame->this, -1, ENOMEM, NULL);
+                dir_cbk (frame, NULL, frame->this, -1, op_errno, NULL);
         }
 
         return 0;
@@ -2011,17 +2038,37 @@ int
 dht_selfheal_directory (call_frame_t *frame, dht_selfheal_dir_cbk_t dir_cbk,
                         loc_t *loc, dht_layout_t *layout)
 {
-        dht_local_t *local    = NULL;
-        uint32_t     down     = 0;
-        uint32_t     misc     = 0;
-        int          ret      = 0;
-        xlator_t    *this     = NULL;
-        char         gfid[GF_UUID_BUF_SIZE] = {0};
+        dht_local_t *local                   = NULL;
+        uint32_t     down                    = 0;
+        uint32_t     misc                    = 0;
+        int          ret                     = 0;
+        xlator_t    *this                    = NULL;
+        char         pgfid[GF_UUID_BUF_SIZE] = {0};
+        char         gfid[GF_UUID_BUF_SIZE]  = {0};
+        inode_t     *linked_inode            = NULL, *inode = NULL;
 
         local = frame->local;
         this = frame->this;
 
-        gf_uuid_unparse(loc->gfid, gfid);
+        if (!__is_root_gfid (local->stbuf.ia_gfid)) {
+                gf_uuid_unparse(local->stbuf.ia_gfid, gfid);
+                gf_uuid_unparse(loc->parent->gfid, pgfid);
+
+                linked_inode = inode_link (loc->inode, loc->parent, loc->name,
+                                           &local->stbuf);
+                if (!linked_inode) {
+                        gf_msg (this->name, GF_LOG_WARNING, 0,
+                                DHT_MSG_DIR_SELFHEAL_FAILED,
+                                "linking inode failed (%s/%s) => %s",
+                                pgfid, loc->name, gfid);
+                        ret = 0;
+                        goto sorry_no_fix;
+                }
+
+                inode = loc->inode;
+                loc->inode = linked_inode;
+                inode_unref (inode);
+        }
 
         dht_layout_anomalies (this, loc, layout,
                               &local->selfheal.hole_cnt,
-- 
1.7.1