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