d84cf8
From 91936fe5ef854bd9d2f91e643795d0e7791b97ba Mon Sep 17 00:00:00 2001
d84cf8
From: Harpreet Kaur <hlalwani@redhat.com>
d84cf8
Date: Mon, 7 Jan 2019 16:38:25 +0530
d84cf8
Subject: [PATCH 426/449] geo-rep: Fix for "Transport End Point not connected"
d84cf8
 issue
d84cf8
d84cf8
problem: Geo-rep gsyncd process mounts the master and slave volume
d84cf8
         on master nodes and slave nodes respectively and starts
d84cf8
         the sync. But it doesn't wait for the mount to be in ready
d84cf8
         state to accept I/O. The gluster mount is considered to be
d84cf8
         ready when all the distribute sub-volumes is up. If the all
d84cf8
         the distribute subvolumes are not up, it can cause ENOTCONN
d84cf8
         error, when lookup on file comes and file is on the subvol
d84cf8
         that is down.
d84cf8
d84cf8
solution: Added a Virtual Xattr "dht.subvol.status" which returns "1"
d84cf8
          if all subvols are up and "0" if all subvols are not up.
d84cf8
          Geo-rep then uses this virtual xattr after a fresh mount, to
d84cf8
          check whether all subvols are up or not and then starts the
d84cf8
          I/O.
d84cf8
d84cf8
>fixes: bz#1664335
d84cf8
>Change-Id: If3ad01d728b1372da7c08ccbe75a45bdc1ab2a91
d84cf8
>Signed-off-by: Harpreet Kaur <hlalwani@redhat.com>
d84cf8
>Signed-off-by: Kotresh HR <khiremat@redhat.com>
d84cf8
d84cf8
backport of https://review.gluster.org/#/c/glusterfs/+/22001/
d84cf8
BUG: 1640573
d84cf8
Change-Id: If3ad01d728b1372da7c08ccbe75a45bdc1ab2a91
d84cf8
Signed-off-by: Shwetha K Acharya <sacharya@redhat.com>
d84cf8
Reviewed-on: https://code.engineering.redhat.com/gerrit/202554
d84cf8
Tested-by: RHGS Build Bot <nigelb@redhat.com>
d84cf8
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
d84cf8
---
d84cf8
 geo-replication/syncdaemon/resource.py   | 11 ++++++
d84cf8
 geo-replication/syncdaemon/syncdutils.py | 20 +++++++++--
d84cf8
 xlators/cluster/dht/src/dht-common.c     | 59 ++++++++++++++++++++++++++++++++
d84cf8
 xlators/cluster/dht/src/dht-common.h     |  4 +++
d84cf8
 4 files changed, 91 insertions(+), 3 deletions(-)
d84cf8
d84cf8
diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py
d84cf8
index 189d8a1..0c61de9 100644
d84cf8
--- a/geo-replication/syncdaemon/resource.py
d84cf8
+++ b/geo-replication/syncdaemon/resource.py
d84cf8
@@ -37,6 +37,7 @@ from syncdutils import ChangelogException, ChangelogHistoryNotAvailable
d84cf8
 from syncdutils import get_changelog_log_level, get_rsync_version
d84cf8
 from syncdutils import CHANGELOG_AGENT_CLIENT_VERSION
d84cf8
 from syncdutils import GX_GFID_CANONICAL_LEN
d84cf8
+from syncdutils import gf_mount_ready
d84cf8
 from gsyncdstatus import GeorepStatus
d84cf8
 from syncdutils import lf, Popen, sup
d84cf8
 from syncdutils import Xattr, matching_disk_gfid, get_gfid_from_mnt
d84cf8
@@ -950,6 +951,16 @@ class Mounter(object):
d84cf8
                 logging.exception('mount cleanup failure:')
d84cf8
                 rv = 200
d84cf8
             os._exit(rv)
d84cf8
+
d84cf8
+        #Polling the dht.subvol.status value.
d84cf8
+        RETRIES = 10
d84cf8
+        while not gf_mount_ready():
d84cf8
+            if RETRIES < 0:
d84cf8
+                logging.error('Subvols are not up')
d84cf8
+                break
d84cf8
+            RETRIES -= 1
d84cf8
+            time.sleep(0.2)
d84cf8
+
d84cf8
         logging.debug('auxiliary glusterfs mount prepared')
d84cf8
 
d84cf8
 
d84cf8
diff --git a/geo-replication/syncdaemon/syncdutils.py b/geo-replication/syncdaemon/syncdutils.py
d84cf8
index b08098e..7560fa1 100644
d84cf8
--- a/geo-replication/syncdaemon/syncdutils.py
d84cf8
+++ b/geo-replication/syncdaemon/syncdutils.py
d84cf8
@@ -21,8 +21,8 @@ import subprocess
d84cf8
 import socket
d84cf8
 from subprocess import PIPE
d84cf8
 from threading import Lock, Thread as baseThread
d84cf8
-from errno import EACCES, EAGAIN, EPIPE, ENOTCONN, ECONNABORTED
d84cf8
-from errno import EINTR, ENOENT, ESTALE, EBUSY, errorcode
d84cf8
+from errno import EACCES, EAGAIN, EPIPE, ENOTCONN, ENOMEM, ECONNABORTED
d84cf8
+from errno import EINTR, ENOENT, ESTALE, EBUSY, ENODATA, errorcode
d84cf8
 from signal import signal, SIGTERM
d84cf8
 import select as oselect
d84cf8
 from os import waitpid as owaitpid
d84cf8
@@ -55,6 +55,8 @@ from rconf import rconf
d84cf8
 
d84cf8
 from hashlib import sha256 as sha256
d84cf8
 
d84cf8
+ENOTSUP = getattr(errno, 'ENOTSUP', 'EOPNOTSUPP')
d84cf8
+
d84cf8
 # auxiliary gfid based access prefix
d84cf8
 _CL_AUX_GFID_PFX = ".gfid/"
d84cf8
 ROOT_GFID = "00000000-0000-0000-0000-000000000001"
d84cf8
@@ -100,6 +102,19 @@ def unescape_space_newline(s):
d84cf8
             .replace(NEWLINE_ESCAPE_CHAR, "\n")\
d84cf8
             .replace(PERCENTAGE_ESCAPE_CHAR, "%")
d84cf8
 
d84cf8
+# gf_mount_ready() returns 1 if all subvols are up, else 0
d84cf8
+def gf_mount_ready():
d84cf8
+    ret = errno_wrap(Xattr.lgetxattr,
d84cf8
+                     ['.', 'dht.subvol.status', 16],
d84cf8
+                     [ENOENT, ENOTSUP, ENODATA], [ENOMEM])
d84cf8
+
d84cf8
+    if isinstance(ret, int):
d84cf8
+       logging.error("failed to get the xattr value")
d84cf8
+       return 1
d84cf8
+    ret = ret.rstrip('\x00')
d84cf8
+    if ret == "1":
d84cf8
+       return 1
d84cf8
+    return 0
d84cf8
 
d84cf8
 def norm(s):
d84cf8
     if s:
d84cf8
@@ -564,7 +579,6 @@ def errno_wrap(call, arg=[], errnos=[], retry_errnos=[]):
d84cf8
 def lstat(e):
d84cf8
     return errno_wrap(os.lstat, [e], [ENOENT], [ESTALE, EBUSY])
d84cf8
 
d84cf8
-
d84cf8
 def get_gfid_from_mnt(gfidpath):
d84cf8
     return errno_wrap(Xattr.lgetxattr,
d84cf8
                       [gfidpath, 'glusterfs.gfid.string',
d84cf8
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
d84cf8
index 6aa18f3..23cc80c 100644
d84cf8
--- a/xlators/cluster/dht/src/dht-common.c
d84cf8
+++ b/xlators/cluster/dht/src/dht-common.c
d84cf8
@@ -4858,6 +4858,60 @@ out:
d84cf8
     return 0;
d84cf8
 }
d84cf8
 
d84cf8
+/* Virtual Xattr which returns 1 if all subvols are up,
d84cf8
+   else returns 0. Geo-rep then uses this virtual xattr
d84cf8
+   after a fresh mount and starts the I/O.
d84cf8
+*/
d84cf8
+
d84cf8
+enum dht_vxattr_subvol {
d84cf8
+    DHT_VXATTR_SUBVOLS_UP = 1,
d84cf8
+    DHT_VXATTR_SUBVOLS_DOWN = 0,
d84cf8
+};
d84cf8
+
d84cf8
+int
d84cf8
+dht_vgetxattr_subvol_status(call_frame_t *frame, xlator_t *this,
d84cf8
+                            const char *key)
d84cf8
+{
d84cf8
+    dht_local_t *local = NULL;
d84cf8
+    int ret = -1;
d84cf8
+    int op_errno = ENODATA;
d84cf8
+    int value = DHT_VXATTR_SUBVOLS_UP;
d84cf8
+    int i = 0;
d84cf8
+    dht_conf_t *conf = NULL;
d84cf8
+
d84cf8
+    conf = this->private;
d84cf8
+    local = frame->local;
d84cf8
+
d84cf8
+    if (!key) {
d84cf8
+        op_errno = EINVAL;
d84cf8
+        goto out;
d84cf8
+    }
d84cf8
+    local->xattr = dict_new();
d84cf8
+    if (!local->xattr) {
d84cf8
+        op_errno = ENOMEM;
d84cf8
+        goto out;
d84cf8
+    }
d84cf8
+    for (i = 0; i < conf->subvolume_cnt; i++) {
d84cf8
+        if (!conf->subvolume_status[i]) {
d84cf8
+            value = DHT_VXATTR_SUBVOLS_DOWN;
d84cf8
+            gf_msg_debug(this->name, 0, "subvol %s is down ",
d84cf8
+                         conf->subvolumes[i]->name);
d84cf8
+            break;
d84cf8
+        }
d84cf8
+    }
d84cf8
+    ret = dict_set_int8(local->xattr, (char *)key, value);
d84cf8
+    if (ret < 0) {
d84cf8
+        op_errno = -ret;
d84cf8
+        ret = -1;
d84cf8
+        goto out;
d84cf8
+    }
d84cf8
+    ret = 0;
d84cf8
+
d84cf8
+out:
d84cf8
+    DHT_STACK_UNWIND(getxattr, frame, ret, op_errno, local->xattr, NULL);
d84cf8
+    return 0;
d84cf8
+}
d84cf8
+
d84cf8
 int
d84cf8
 dht_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *key,
d84cf8
              dict_t *xdata)
d84cf8
@@ -4915,6 +4969,11 @@ dht_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *key,
d84cf8
         goto err;
d84cf8
     }
d84cf8
 
d84cf8
+    if (strncmp(key, DHT_SUBVOL_STATUS_KEY, SLEN(DHT_SUBVOL_STATUS_KEY)) == 0) {
d84cf8
+        dht_vgetxattr_subvol_status(frame, this, key);
d84cf8
+        return 0;
d84cf8
+    }
d84cf8
+
d84cf8
     /* skip over code which is irrelevant if !DHT_IS_DIR(layout) */
d84cf8
     if (!DHT_IS_DIR(layout))
d84cf8
         goto no_dht_is_dir;
d84cf8
diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h
d84cf8
index 1b3e826..9ec5b51 100644
d84cf8
--- a/xlators/cluster/dht/src/dht-common.h
d84cf8
+++ b/xlators/cluster/dht/src/dht-common.h
d84cf8
@@ -45,6 +45,10 @@
d84cf8
 #define DHT_DIR_STAT_BLOCKS 8
d84cf8
 #define DHT_DIR_STAT_SIZE 4096
d84cf8
 
d84cf8
+/* Virtual xattr for subvols status */
d84cf8
+
d84cf8
+#define DHT_SUBVOL_STATUS_KEY "dht.subvol.status"
d84cf8
+
d84cf8
 /* Virtual xattrs for debugging */
d84cf8
 
d84cf8
 #define DHT_DBG_HASHED_SUBVOL_PATTERN "dht.file.hashed-subvol.*"
d84cf8
-- 
d84cf8
1.8.3.1
d84cf8