7f4c2a
From 01ad467806e8cbcc53347aa5665795f42a16df9e Mon Sep 17 00:00:00 2001
7f4c2a
From: Nithya Balachandran <nbalacha@redhat.com>
7f4c2a
Date: Wed, 10 Jun 2015 19:09:58 +0530
7f4c2a
Subject: [PATCH 50/57] cluster/dht: fix incorrect dst subvol info in inode_ctx
7f4c2a
7f4c2a
Stashing additional information in the inode_ctx to help
7f4c2a
decide whether the migration information is stale, which could
7f4c2a
happen if a file was migrated several times but FOPs only detected
7f4c2a
the P1 migration phase. If no FOP detects the P2 phase, the inode
7f4c2a
ctx1 is never reset.
7f4c2a
We now save the src subvol as well as the dst subvol in the
7f4c2a
inode ctx. The src subvol is the subvol on which the FOP was sent
7f4c2a
when the mig info was set in the inode ctx. This information is
7f4c2a
considered stale if:
7f4c2a
1. The subvol on which the current FOP is sent is the same as
7f4c2a
the dst subvol in the ctx
7f4c2a
2. The subvol on which the current FOP is sent is not the same
7f4c2a
as the src subvol in the ctx
7f4c2a
7f4c2a
This does not handle the case where the same file might have been
7f4c2a
renamed such that the src subvol is the same but the dst subvol
7f4c2a
is different. However, that is unlikely to happen very often.
7f4c2a
7f4c2a
Change-Id: I05a2e9b107ee64750c7ca629aee03b03a02ef75f
7f4c2a
BUG: 1140506
7f4c2a
Signed-off-by: Nithya Balachandran <nbalacha@redhat.com>
7f4c2a
Reviewed-on: http://review.gluster.org/10834
7f4c2a
Tested-by: Gluster Build System <jenkins@build.gluster.com>
7f4c2a
Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
7f4c2a
Tested-by: Raghavendra G <rgowdapp@redhat.com>
7f4c2a
Signed-off-by: Nithya Balachandran <nbalacha@redhat.com>
7f4c2a
Reviewed-on: https://code.engineering.redhat.com/gerrit/50452
7f4c2a
Reviewed-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
7f4c2a
Tested-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
7f4c2a
---
7f4c2a
 xlators/cluster/dht/src/dht-common.c      |   47 ++++++-----
7f4c2a
 xlators/cluster/dht/src/dht-common.h      |   11 ++-
7f4c2a
 xlators/cluster/dht/src/dht-helper.c      |  129 +++++++++++++++++++++--------
7f4c2a
 xlators/cluster/dht/src/dht-inode-read.c  |   13 ++--
7f4c2a
 xlators/cluster/dht/src/dht-inode-write.c |   64 +++++++++-----
7f4c2a
 xlators/cluster/dht/src/dht-mem-types.h   |    1 +
7f4c2a
 6 files changed, 179 insertions(+), 86 deletions(-)
7f4c2a
7f4c2a
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
7f4c2a
index acad4da..a3a48ea 100644
7f4c2a
--- a/xlators/cluster/dht/src/dht-common.c
7f4c2a
+++ b/xlators/cluster/dht/src/dht-common.c
7f4c2a
@@ -3302,12 +3302,12 @@ int
7f4c2a
 dht_file_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
                      int op_ret, int op_errno, dict_t *xdata)
7f4c2a
 {
7f4c2a
-        int           ret    = -1;
7f4c2a
-        dht_local_t  *local  = NULL;
7f4c2a
-        call_frame_t *prev   = NULL;
7f4c2a
-        struct iatt  *stbuf  = NULL;
7f4c2a
-        inode_t      *inode  = NULL;
7f4c2a
-        xlator_t     *subvol = NULL;
7f4c2a
+        int           ret     = -1;
7f4c2a
+        dht_local_t  *local   = NULL;
7f4c2a
+        call_frame_t *prev    = NULL;
7f4c2a
+        struct iatt  *stbuf   = NULL;
7f4c2a
+        inode_t      *inode   = NULL;
7f4c2a
+        xlator_t     *subvol1 = NULL, *subvol2 = NULL;
7f4c2a
 
7f4c2a
         local = frame->local;
7f4c2a
         prev = cookie;
7f4c2a
@@ -3345,9 +3345,11 @@ dht_file_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
         if (IS_DHT_MIGRATION_PHASE1 (stbuf)) {
7f4c2a
                 inode = (local->fd) ? local->fd->inode : local->loc.inode;
7f4c2a
 
7f4c2a
-                ret = dht_inode_ctx_get1 (this, inode, &subvol);
7f4c2a
-                if (subvol) {
7f4c2a
-                        dht_setxattr2 (this, subvol, frame);
7f4c2a
+                ret = dht_inode_ctx_get_mig_info (this, inode,
7f4c2a
+                                                  &subvol1, &subvol2);
7f4c2a
+                if (!dht_mig_info_is_invalid (local->cached_subvol,
7f4c2a
+                                              subvol1, subvol2)) {
7f4c2a
+                        dht_setxattr2 (this, subvol2, frame);
7f4c2a
                         return 0;
7f4c2a
                 }
7f4c2a
 
7f4c2a
@@ -3814,12 +3816,12 @@ int
7f4c2a
 dht_file_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
                      int op_ret, int op_errno, dict_t *xdata)
7f4c2a
 {
7f4c2a
-        int           ret    = -1;
7f4c2a
-        dht_local_t  *local  = NULL;
7f4c2a
-        call_frame_t *prev   = NULL;
7f4c2a
-        struct iatt  *stbuf  = NULL;
7f4c2a
-        inode_t      *inode  = NULL;
7f4c2a
-        xlator_t     *subvol = NULL;
7f4c2a
+        int           ret     = -1;
7f4c2a
+        dht_local_t  *local   = NULL;
7f4c2a
+        call_frame_t *prev    = NULL;
7f4c2a
+        struct iatt  *stbuf   = NULL;
7f4c2a
+        inode_t      *inode   = NULL;
7f4c2a
+        xlator_t     *subvol1 = NULL, *subvol2 = NULL;
7f4c2a
 
7f4c2a
         local = frame->local;
7f4c2a
         prev = cookie;
7f4c2a
@@ -3856,9 +3858,12 @@ dht_file_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
         /* Phase 1 of migration */
7f4c2a
         if (IS_DHT_MIGRATION_PHASE1 (stbuf)) {
7f4c2a
                 inode = (local->fd) ? local->fd->inode : local->loc.inode;
7f4c2a
-                ret = dht_inode_ctx_get1 (this, inode, &subvol);
7f4c2a
-                if (subvol) {
7f4c2a
-                        dht_removexattr2 (this, subvol, frame);
7f4c2a
+
7f4c2a
+                ret = dht_inode_ctx_get_mig_info (this, inode,
7f4c2a
+                                                  &subvol1, &subvol2);
7f4c2a
+                if (!dht_mig_info_is_invalid (local->cached_subvol,
7f4c2a
+                                              subvol1, subvol2)) {
7f4c2a
+                        dht_removexattr2 (this, subvol2, frame);
7f4c2a
                         return 0;
7f4c2a
                 }
7f4c2a
 
7f4c2a
@@ -5228,7 +5233,8 @@ dht_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
         local->rebalance.target_op_fn = dht_link2;
7f4c2a
         /* Check if the rebalance phase2 is true */
7f4c2a
         if (IS_DHT_MIGRATION_PHASE2 (stbuf)) {
7f4c2a
-                ret = dht_inode_ctx_get1 (this, local->loc.inode, &subvol);
7f4c2a
+                ret = dht_inode_ctx_get_mig_info (this, local->loc.inode, NULL,
7f4c2a
+                                                  &subvol);
7f4c2a
                 if (!subvol) {
7f4c2a
                         /* Phase 2 of migration */
7f4c2a
                         ret = dht_rebalance_complete_check (this, frame);
7f4c2a
@@ -5242,7 +5248,8 @@ dht_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
 
7f4c2a
         /* Check if the rebalance phase1 is true */
7f4c2a
         if (IS_DHT_MIGRATION_PHASE1 (stbuf)) {
7f4c2a
-                ret = dht_inode_ctx_get1 (this, local->loc.inode, &subvol);
7f4c2a
+                ret = dht_inode_ctx_get_mig_info (this, local->loc.inode, NULL,
7f4c2a
+                                                  &subvol);
7f4c2a
                 if (subvol) {
7f4c2a
                         dht_link2 (this, subvol, frame);
7f4c2a
                         return 0;
7f4c2a
diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h
7f4c2a
index eebc13b..0351819 100644
7f4c2a
--- a/xlators/cluster/dht/src/dht-common.h
7f4c2a
+++ b/xlators/cluster/dht/src/dht-common.h
7f4c2a
@@ -503,6 +503,11 @@ struct dir_dfmeta {
7f4c2a
         int                     *fetch_entries;
7f4c2a
 };
7f4c2a
 
7f4c2a
+typedef struct dht_migrate_info {
7f4c2a
+        xlator_t *src_subvol;
7f4c2a
+        xlator_t *dst_subvol;
7f4c2a
+} dht_migrate_info_t;
7f4c2a
+
7f4c2a
 #define ENTRY_MISSING(op_ret, op_errno) (op_ret == -1 && op_errno == ENOENT)
7f4c2a
 
7f4c2a
 #define is_revalidate(loc) (dht_inode_ctx_layout_get (loc->inode, this, NULL) == 0)
7f4c2a
@@ -978,7 +983,11 @@ int32_t
7f4c2a
 dht_inodectx_dump (xlator_t *this, inode_t *inode);
7f4c2a
 
7f4c2a
 int
7f4c2a
-dht_inode_ctx_get1 (xlator_t *this, inode_t *inode, xlator_t **subvol);
7f4c2a
+dht_inode_ctx_get_mig_info (xlator_t *this, inode_t *inode,
7f4c2a
+                            xlator_t **src_subvol, xlator_t **dst_subvol);
7f4c2a
+gf_boolean_t
7f4c2a
+dht_mig_info_is_invalid (xlator_t *current, xlator_t *src_subvol,
7f4c2a
+                         xlator_t *dst_subvol);
7f4c2a
 
7f4c2a
 int
7f4c2a
 dht_subvol_status (dht_conf_t *conf, xlator_t *subvol);
7f4c2a
diff --git a/xlators/cluster/dht/src/dht-helper.c b/xlators/cluster/dht/src/dht-helper.c
7f4c2a
index ee99b99..ac2f794 100644
7f4c2a
--- a/xlators/cluster/dht/src/dht-helper.c
7f4c2a
+++ b/xlators/cluster/dht/src/dht-helper.c
7f4c2a
@@ -20,27 +20,81 @@
7f4c2a
 #include "dht-helper.h"
7f4c2a
 
7f4c2a
 static inline int
7f4c2a
-dht_inode_ctx_set1 (xlator_t *this, inode_t *inode, xlator_t *subvol)
7f4c2a
+dht_inode_ctx_set_mig_info (xlator_t *this, inode_t *inode,
7f4c2a
+                            xlator_t *src_subvol, xlator_t *dst_subvol)
7f4c2a
 {
7f4c2a
-        uint64_t tmp_subvol = 0;
7f4c2a
+        dht_migrate_info_t *miginfo = NULL;
7f4c2a
+        uint64_t            value   = 0;
7f4c2a
+        int                 ret     = -1;
7f4c2a
 
7f4c2a
-        tmp_subvol = (long)subvol;
7f4c2a
-        return inode_ctx_set1 (inode, this, &tmp_subvol);
7f4c2a
+        miginfo = GF_CALLOC (1, sizeof (*miginfo), gf_dht_mt_miginfo_t);
7f4c2a
+        if (miginfo == NULL)
7f4c2a
+                goto out;
7f4c2a
+
7f4c2a
+        miginfo->src_subvol = src_subvol;
7f4c2a
+        miginfo->dst_subvol = dst_subvol;
7f4c2a
+
7f4c2a
+        value = (uint64_t) miginfo;
7f4c2a
+
7f4c2a
+        ret = inode_ctx_set1 (inode, this, &value);
7f4c2a
+        if (ret < 0) {
7f4c2a
+                GF_FREE (miginfo);
7f4c2a
+        }
7f4c2a
+
7f4c2a
+out:
7f4c2a
+        return ret;
7f4c2a
 }
7f4c2a
 
7f4c2a
+
7f4c2a
 int
7f4c2a
-dht_inode_ctx_get1 (xlator_t *this, inode_t *inode, xlator_t **subvol)
7f4c2a
+dht_inode_ctx_get_mig_info (xlator_t *this, inode_t *inode,
7f4c2a
+                            xlator_t **src_subvol, xlator_t **dst_subvol)
7f4c2a
 {
7f4c2a
-        int ret = -1;
7f4c2a
-        uint64_t tmp_subvol = 0;
7f4c2a
+        int                 ret         = -1;
7f4c2a
+        uint64_t            tmp_miginfo = 0;
7f4c2a
+        dht_migrate_info_t *miginfo     = NULL;
7f4c2a
 
7f4c2a
-        ret =  inode_ctx_get1 (inode, this, &tmp_subvol);
7f4c2a
-        if (tmp_subvol && subvol)
7f4c2a
-                *subvol = (xlator_t *)tmp_subvol;
7f4c2a
+        ret =  inode_ctx_get1 (inode, this, &tmp_miginfo);
7f4c2a
+        if ((ret < 0) || (tmp_miginfo == 0))
7f4c2a
+                goto out;
7f4c2a
+
7f4c2a
+        miginfo = (dht_migrate_info_t *)tmp_miginfo;
7f4c2a
+
7f4c2a
+        if (src_subvol)
7f4c2a
+                *src_subvol = miginfo->src_subvol;
7f4c2a
 
7f4c2a
+        if (dst_subvol)
7f4c2a
+                *dst_subvol = miginfo->dst_subvol;
7f4c2a
+
7f4c2a
+out:
7f4c2a
         return ret;
7f4c2a
 }
7f4c2a
 
7f4c2a
+gf_boolean_t
7f4c2a
+dht_mig_info_is_invalid (xlator_t *current, xlator_t *src_subvol,
7f4c2a
+                      xlator_t *dst_subvol)
7f4c2a
+{
7f4c2a
+
7f4c2a
+/* Not set
7f4c2a
+ */
7f4c2a
+        if (!src_subvol || !dst_subvol)
7f4c2a
+                return _gf_true;
7f4c2a
+
7f4c2a
+/* Invalid scenarios:
7f4c2a
+ * The src_subvol does not match the subvol on which the current op was sent
7f4c2a
+ * so the cached subvol has changed between the last mig_info_set and now.
7f4c2a
+ * src_subvol == dst_subvol. The file was migrated without any FOP detecting
7f4c2a
+ * a P2 so the old dst is now the current subvol.
7f4c2a
+ *
7f4c2a
+ * There is still one scenario where the info could be outdated - if
7f4c2a
+ * file has undergone multiple migrations and ends up on the same src_subvol
7f4c2a
+ * on which the mig_info was first set.
7f4c2a
+ */
7f4c2a
+        if ((current == dst_subvol) || (current != src_subvol))
7f4c2a
+                return _gf_true;
7f4c2a
+
7f4c2a
+        return _gf_false;
7f4c2a
+}
7f4c2a
 
7f4c2a
 int
7f4c2a
 dht_frame_return (call_frame_t *frame)
7f4c2a
@@ -845,20 +899,20 @@ out:
7f4c2a
 int
7f4c2a
 dht_migration_complete_check_task (void *data)
7f4c2a
 {
7f4c2a
-        int           ret      = -1;
7f4c2a
-        xlator_t     *src_node = NULL;
7f4c2a
-        xlator_t     *dst_node = NULL,  *linkto_target = NULL;
7f4c2a
-        dht_local_t  *local    = NULL;
7f4c2a
-        dict_t       *dict     = NULL;
7f4c2a
-        struct iatt   stbuf    = {0,};
7f4c2a
-        xlator_t     *this     = NULL;
7f4c2a
-        call_frame_t *frame    = NULL;
7f4c2a
-        loc_t         tmp_loc  = {0,};
7f4c2a
-        char         *path     = NULL;
7f4c2a
-        dht_conf_t   *conf     = NULL;
7f4c2a
-        inode_t      *inode    = NULL;
7f4c2a
-        fd_t         *iter_fd  = NULL;
7f4c2a
-        uint64_t      tmp_subvol = 0;
7f4c2a
+        int           ret         = -1;
7f4c2a
+        xlator_t     *src_node    = NULL;
7f4c2a
+        xlator_t     *dst_node    = NULL, *linkto_target = NULL;
7f4c2a
+        dht_local_t  *local       = NULL;
7f4c2a
+        dict_t       *dict        = NULL;
7f4c2a
+        struct iatt   stbuf       = {0,};
7f4c2a
+        xlator_t     *this        = NULL;
7f4c2a
+        call_frame_t *frame       = NULL;
7f4c2a
+        loc_t         tmp_loc     = {0,};
7f4c2a
+        char         *path        = NULL;
7f4c2a
+        dht_conf_t   *conf        = NULL;
7f4c2a
+        inode_t      *inode       = NULL;
7f4c2a
+        fd_t         *iter_fd     = NULL;
7f4c2a
+        uint64_t      tmp_miginfo = 0;
7f4c2a
         int           open_failed = 0;
7f4c2a
 
7f4c2a
         this  = THIS;
7f4c2a
@@ -950,9 +1004,11 @@ dht_migration_complete_check_task (void *data)
7f4c2a
         /* once we detect the migration complete, the inode-ctx2 is no more
7f4c2a
            required.. delete the ctx and also, it means, open() already
7f4c2a
            done on all the fd of inode */
7f4c2a
-        ret = inode_ctx_reset1 (inode, this, &tmp_subvol);
7f4c2a
-        if (tmp_subvol)
7f4c2a
+        ret = inode_ctx_reset1 (inode, this, &tmp_miginfo);
7f4c2a
+        if (tmp_miginfo) {
7f4c2a
+                GF_FREE ((void *)tmp_miginfo);
7f4c2a
                 goto out;
7f4c2a
+        }
7f4c2a
 
7f4c2a
         if (list_empty (&inode->fd_list))
7f4c2a
                 goto out;
7f4c2a
@@ -1011,15 +1067,15 @@ dht_rebalance_complete_check (xlator_t *this, call_frame_t *frame)
7f4c2a
                             dht_migration_complete_check_done,
7f4c2a
                             frame, frame);
7f4c2a
         return ret;
7f4c2a
-}
7f4c2a
 
7f4c2a
+}
7f4c2a
 /* During 'in-progress' state, both nodes should have the file */
7f4c2a
 static int
7f4c2a
 dht_inprogress_check_done (int op_ret, call_frame_t *frame, void *data)
7f4c2a
 {
7f4c2a
-        dht_local_t *local  = NULL;
7f4c2a
-        xlator_t    *subvol = NULL;
7f4c2a
-        inode_t     *inode  = NULL;
7f4c2a
+        dht_local_t *local      = NULL;
7f4c2a
+        xlator_t    *dst_subvol = NULL, *src_subvol = NULL;
7f4c2a
+        inode_t     *inode      = NULL;
7f4c2a
 
7f4c2a
         local = frame->local;
7f4c2a
 
7f4c2a
@@ -1028,17 +1084,18 @@ dht_inprogress_check_done (int op_ret, call_frame_t *frame, void *data)
7f4c2a
 
7f4c2a
         inode = local->loc.inode ? local->loc.inode : local->fd->inode;
7f4c2a
 
7f4c2a
-        dht_inode_ctx_get1 (THIS, inode, &subvol);
7f4c2a
-        if (!subvol) {
7f4c2a
-                subvol = dht_subvol_get_cached (THIS, inode);
7f4c2a
-                if (!subvol) {
7f4c2a
+        dht_inode_ctx_get_mig_info (THIS, inode, &src_subvol, &dst_subvol);
7f4c2a
+        if (dht_mig_info_is_invalid (local->cached_subvol,
7f4c2a
+                                     src_subvol, dst_subvol)) {
7f4c2a
+                dst_subvol = dht_subvol_get_cached (THIS, inode);
7f4c2a
+                if (!dst_subvol) {
7f4c2a
                         local->op_errno = EINVAL;
7f4c2a
                         goto out;
7f4c2a
                 }
7f4c2a
         }
7f4c2a
 
7f4c2a
 out:
7f4c2a
-        local->rebalance.target_op_fn (THIS, subvol, frame);
7f4c2a
+        local->rebalance.target_op_fn (THIS, dst_subvol, frame);
7f4c2a
 
7f4c2a
         return 0;
7f4c2a
 }
7f4c2a
@@ -1170,7 +1227,7 @@ dht_rebalance_inprogress_task (void *data)
7f4c2a
         }
7f4c2a
 
7f4c2a
 done:
7f4c2a
-        ret = dht_inode_ctx_set1 (this, inode, dst_node);
7f4c2a
+        ret = dht_inode_ctx_set_mig_info (this, inode, src_node, dst_node);
7f4c2a
         if (ret) {
7f4c2a
                 gf_log (this->name, GF_LOG_ERROR,
7f4c2a
                         "%s: failed to set inode-ctx target file at %s",
7f4c2a
diff --git a/xlators/cluster/dht/src/dht-inode-read.c b/xlators/cluster/dht/src/dht-inode-read.c
7f4c2a
index 46df5b6..5dd055a 100644
7f4c2a
--- a/xlators/cluster/dht/src/dht-inode-read.c
7f4c2a
+++ b/xlators/cluster/dht/src/dht-inode-read.c
7f4c2a
@@ -158,7 +158,7 @@ dht_file_attr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
         /* Check if the rebalance phase2 is true */
7f4c2a
         if ((op_ret == -1) || IS_DHT_MIGRATION_PHASE2 (stbuf)) {
7f4c2a
                 inode = (local->fd) ? local->fd->inode : local->loc.inode;
7f4c2a
-                ret = dht_inode_ctx_get1 (this, inode, &subvol);
7f4c2a
+                ret = dht_inode_ctx_get_mig_info (this, inode, NULL, &subvol);
7f4c2a
                 if (!subvol) {
7f4c2a
                         /* Phase 2 of migration */
7f4c2a
                         local->rebalance.target_op_fn = dht_attr2;
7f4c2a
@@ -382,7 +382,6 @@ dht_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
 {
7f4c2a
         dht_local_t *local      = NULL;
7f4c2a
         int          ret        = 0;
7f4c2a
-        inode_t     *inode      = NULL;
7f4c2a
         xlator_t    *subvol = 0;
7f4c2a
 
7f4c2a
         local = frame->local;
7f4c2a
@@ -402,7 +401,8 @@ dht_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
         local->op_errno = op_errno;
7f4c2a
         if ((op_ret == -1) || IS_DHT_MIGRATION_PHASE2 (stbuf)) {
7f4c2a
                 /* File would be migrated to other node */
7f4c2a
-                ret = dht_inode_ctx_get1 (this, inode, &subvol);
7f4c2a
+                ret = dht_inode_ctx_get_mig_info (this, local->fd->inode, NULL,
7f4c2a
+                                                  &subvol);
7f4c2a
                 if (!subvol) {
7f4c2a
                         local->rebalance.target_op_fn = dht_readv2;
7f4c2a
                         ret = dht_rebalance_complete_check (this, frame);
7f4c2a
@@ -617,7 +617,6 @@ dht_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
                int op_ret, int op_errno, dict_t *xdata)
7f4c2a
 {
7f4c2a
         dht_local_t  *local  = NULL;
7f4c2a
-        inode_t      *inode  = NULL;
7f4c2a
         xlator_t     *subvol = 0;
7f4c2a
 
7f4c2a
         local = frame->local;
7f4c2a
@@ -628,7 +627,7 @@ dht_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
                 goto out;
7f4c2a
 
7f4c2a
         /* If context is set, then send flush() it to the destination */
7f4c2a
-        dht_inode_ctx_get1 (this, inode, &subvol);
7f4c2a
+        dht_inode_ctx_get_mig_info (this, local->fd->inode, NULL, &subvol);
7f4c2a
         if (subvol) {
7f4c2a
                 dht_flush2 (this, subvol, frame);
7f4c2a
                 return 0;
7f4c2a
@@ -653,6 +652,7 @@ dht_flush2 (xlator_t *this, xlator_t *subvol, call_frame_t *frame)
7f4c2a
 
7f4c2a
         op_errno = local->op_errno;
7f4c2a
 
7f4c2a
+        dht_inode_ctx_get_mig_info (this, local->fd->inode, NULL, &subvol);
7f4c2a
         if (subvol == NULL)
7f4c2a
                 goto out;
7f4c2a
 
7f4c2a
@@ -740,7 +740,8 @@ dht_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
7f4c2a
         }
7f4c2a
 
7f4c2a
         local->op_errno = op_errno;
7f4c2a
-        dht_inode_ctx_get1 (this, inode, &subvol);
7f4c2a
+        inode = local->fd->inode;
7f4c2a
+        dht_inode_ctx_get_mig_info (this, inode, NULL, &subvol);
7f4c2a
         if (!subvol) {
7f4c2a
                 local->rebalance.target_op_fn = dht_fsync2;
7f4c2a
 
7f4c2a
diff --git a/xlators/cluster/dht/src/dht-inode-write.c b/xlators/cluster/dht/src/dht-inode-write.c
7f4c2a
index 57ce89c..85102a3 100644
7f4c2a
--- a/xlators/cluster/dht/src/dht-inode-write.c
7f4c2a
+++ b/xlators/cluster/dht/src/dht-inode-write.c
7f4c2a
@@ -30,7 +30,8 @@ dht_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
 {
7f4c2a
         dht_local_t *local = NULL;
7f4c2a
         int          ret   = -1;
7f4c2a
-        xlator_t    *subvol = NULL;
7f4c2a
+        xlator_t    *subvol1 = NULL;
7f4c2a
+        xlator_t    *subvol2 = NULL;
7f4c2a
 
7f4c2a
         if (op_ret == -1 && !dht_inode_missing(op_errno)) {
7f4c2a
                 goto out;
7f4c2a
@@ -67,9 +68,11 @@ dht_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
                 dht_iatt_merge (this, &local->stbuf, postbuf, NULL);
7f4c2a
                 dht_iatt_merge (this, &local->prebuf, prebuf, NULL);
7f4c2a
 
7f4c2a
-                ret = dht_inode_ctx_get1 (this, local->fd->inode, &subvol);
7f4c2a
-                if (subvol) {
7f4c2a
-                        dht_writev2 (this, subvol, frame);
7f4c2a
+                ret = dht_inode_ctx_get_mig_info (this, local->fd->inode,
7f4c2a
+                                                  &subvol1, &subvol2);
7f4c2a
+                if (!dht_mig_info_is_invalid (local->cached_subvol,
7f4c2a
+                                              subvol1, subvol2)) {
7f4c2a
+                        dht_writev2 (this, subvol2, frame);
7f4c2a
                         return 0;
7f4c2a
                 }
7f4c2a
                 ret = dht_rebalance_in_progress_check (this, frame);
7f4c2a
@@ -177,7 +180,8 @@ dht_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
         dht_local_t  *local = NULL;
7f4c2a
         call_frame_t *prev = NULL;
7f4c2a
         int           ret = -1;
7f4c2a
-        xlator_t    *subvol = NULL;
7f4c2a
+        xlator_t    *src_subvol = NULL;
7f4c2a
+        xlator_t    *dst_subvol = NULL;
7f4c2a
         inode_t      *inode = NULL;
7f4c2a
 
7f4c2a
         GF_VALIDATE_OR_GOTO ("dht", frame, err);
7f4c2a
@@ -221,9 +225,12 @@ dht_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
                 dht_iatt_merge (this, &local->stbuf, postbuf, NULL);
7f4c2a
                 dht_iatt_merge (this, &local->prebuf, prebuf, NULL);
7f4c2a
                 inode = (local->fd) ? local->fd->inode : local->loc.inode;
7f4c2a
-                dht_inode_ctx_get1 (this, inode, &subvol);
7f4c2a
-                if (subvol) {
7f4c2a
-                        dht_truncate2 (this, subvol, frame);
7f4c2a
+
7f4c2a
+                dht_inode_ctx_get_mig_info (this, inode, &src_subvol,
7f4c2a
+                                            &dst_subvol);
7f4c2a
+                if (!dht_mig_info_is_invalid (local->cached_subvol,
7f4c2a
+                                              src_subvol, dst_subvol)) {
7f4c2a
+                        dht_truncate2 (this, dst_subvol, frame);
7f4c2a
                         return 0;
7f4c2a
                 }
7f4c2a
                 ret = dht_rebalance_in_progress_check (this, frame);
7f4c2a
@@ -368,7 +375,8 @@ dht_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
         dht_local_t  *local = NULL;
7f4c2a
         call_frame_t *prev = NULL;
7f4c2a
         int           ret = -1;
7f4c2a
-        xlator_t    *subvol = NULL;
7f4c2a
+        xlator_t    *src_subvol = NULL;
7f4c2a
+        xlator_t    *dst_subvol = NULL;
7f4c2a
 
7f4c2a
         GF_VALIDATE_OR_GOTO ("dht", frame, err);
7f4c2a
         GF_VALIDATE_OR_GOTO ("dht", this, out);
7f4c2a
@@ -408,9 +416,12 @@ dht_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
         if (IS_DHT_MIGRATION_PHASE1 (postbuf)) {
7f4c2a
                 dht_iatt_merge (this, &local->stbuf, postbuf, NULL);
7f4c2a
                 dht_iatt_merge (this, &local->prebuf, prebuf, NULL);
7f4c2a
-                dht_inode_ctx_get1 (this, local->fd->inode, &subvol);
7f4c2a
-                if (subvol) {
7f4c2a
-                        dht_fallocate2 (this, subvol, frame);
7f4c2a
+
7f4c2a
+                dht_inode_ctx_get_mig_info (this, local->fd->inode, &src_subvol,
7f4c2a
+                                            &dst_subvol);
7f4c2a
+                if (!dht_mig_info_is_invalid (local->cached_subvol,
7f4c2a
+                                              src_subvol, dst_subvol)) {
7f4c2a
+                        dht_fallocate2 (this, dst_subvol, frame);
7f4c2a
                         return 0;
7f4c2a
                 }
7f4c2a
                 ret = dht_rebalance_in_progress_check (this, frame);
7f4c2a
@@ -508,7 +519,8 @@ dht_discard_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
         dht_local_t  *local = NULL;
7f4c2a
         call_frame_t *prev = NULL;
7f4c2a
         int           ret = -1;
7f4c2a
-        xlator_t    *subvol = NULL;
7f4c2a
+        xlator_t    *src_subvol = NULL;
7f4c2a
+        xlator_t    *dst_subvol = NULL;
7f4c2a
 
7f4c2a
         GF_VALIDATE_OR_GOTO ("dht", frame, err);
7f4c2a
         GF_VALIDATE_OR_GOTO ("dht", this, out);
7f4c2a
@@ -548,9 +560,12 @@ dht_discard_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
         if (IS_DHT_MIGRATION_PHASE1 (postbuf)) {
7f4c2a
                 dht_iatt_merge (this, &local->stbuf, postbuf, NULL);
7f4c2a
                 dht_iatt_merge (this, &local->prebuf, prebuf, NULL);
7f4c2a
-                dht_inode_ctx_get1 (this, local->fd->inode, &subvol);
7f4c2a
-                if (subvol) {
7f4c2a
-                        dht_discard2 (this, subvol, frame);
7f4c2a
+
7f4c2a
+                dht_inode_ctx_get_mig_info (this, local->fd->inode, &src_subvol,
7f4c2a
+                                            &dst_subvol);
7f4c2a
+                if (!dht_mig_info_is_invalid(local->cached_subvol,
7f4c2a
+                                             src_subvol, dst_subvol)) {
7f4c2a
+                        dht_discard2 (this, dst_subvol, frame);
7f4c2a
                         return 0;
7f4c2a
                 }
7f4c2a
                 ret = dht_rebalance_in_progress_check (this, frame);
7f4c2a
@@ -642,10 +657,10 @@ dht_zerofill_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
                 int op_ret, int op_errno, struct iatt *prebuf,
7f4c2a
                 struct iatt *postbuf, dict_t *xdata)
7f4c2a
 {
7f4c2a
-        dht_local_t  *local  = NULL;
7f4c2a
-        call_frame_t *prev   = NULL;
7f4c2a
-        int           ret    = -1;
7f4c2a
-        xlator_t     *subvol = NULL;
7f4c2a
+        dht_local_t  *local   = NULL;
7f4c2a
+        call_frame_t *prev    = NULL;
7f4c2a
+        int           ret     = -1;
7f4c2a
+        xlator_t     *subvol1 = NULL, *subvol2 = NULL;
7f4c2a
 
7f4c2a
         GF_VALIDATE_OR_GOTO ("dht", frame, err);
7f4c2a
         GF_VALIDATE_OR_GOTO ("dht", this, out);
7f4c2a
@@ -683,9 +698,12 @@ dht_zerofill_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
         if (IS_DHT_MIGRATION_PHASE1 (postbuf)) {
7f4c2a
                 dht_iatt_merge (this, &local->stbuf, postbuf, NULL);
7f4c2a
                 dht_iatt_merge (this, &local->prebuf, prebuf, NULL);
7f4c2a
-                dht_inode_ctx_get1 (this, local->fd->inode, &subvol);
7f4c2a
-                if (subvol) {
7f4c2a
-                        dht_zerofill2 (this, subvol, frame);
7f4c2a
+
7f4c2a
+                ret = dht_inode_ctx_get_mig_info (this, local->fd->inode,
7f4c2a
+                                                  &subvol1, &subvol2);
7f4c2a
+                if (!dht_mig_info_is_invalid (local->cached_subvol,
7f4c2a
+                                              subvol1, subvol2)) {
7f4c2a
+                        dht_zerofill2 (this, subvol2, frame);
7f4c2a
                         return 0;
7f4c2a
                 }
7f4c2a
 
7f4c2a
diff --git a/xlators/cluster/dht/src/dht-mem-types.h b/xlators/cluster/dht/src/dht-mem-types.h
7f4c2a
index 46028e6..85e5bae 100644
7f4c2a
--- a/xlators/cluster/dht/src/dht-mem-types.h
7f4c2a
+++ b/xlators/cluster/dht/src/dht-mem-types.h
7f4c2a
@@ -33,6 +33,7 @@ enum gf_dht_mem_types_ {
7f4c2a
         gf_dht_mt_dirent_t,
7f4c2a
         gf_dht_mt_container_t,
7f4c2a
         gf_dht_mt_octx_t,
7f4c2a
+        gf_dht_mt_miginfo_t,
7f4c2a
         gf_dht_mt_end
7f4c2a
 };
7f4c2a
 #endif
7f4c2a
-- 
7f4c2a
1.7.1
7f4c2a