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