|
|
e3c68b |
From 29ec87484b1ee3ad6417c37726db8aa9296f3a83 Mon Sep 17 00:00:00 2001
|
|
|
e3c68b |
From: Kotresh HR <khiremat@redhat.com>
|
|
|
e3c68b |
Date: Wed, 8 May 2019 11:26:06 +0530
|
|
|
e3c68b |
Subject: [PATCH 163/169] geo-rep: Fix sync hang with tarssh
|
|
|
e3c68b |
|
|
|
e3c68b |
Problem:
|
|
|
e3c68b |
Geo-rep sync hangs when tarssh is used as sync
|
|
|
e3c68b |
engine at heavy workload.
|
|
|
e3c68b |
|
|
|
e3c68b |
Analysis and Root cause:
|
|
|
e3c68b |
It's found out that the tar process was hung.
|
|
|
e3c68b |
When debugged further, it's found out that stderr
|
|
|
e3c68b |
buffer of tar process on master was full i.e., 64k.
|
|
|
e3c68b |
When the buffer was copied to a file from /proc/pid/fd/2,
|
|
|
e3c68b |
the hang is resolved.
|
|
|
e3c68b |
|
|
|
e3c68b |
This can happen when files picked by tar process
|
|
|
e3c68b |
to sync doesn't exist on master anymore. If this count
|
|
|
e3c68b |
increases around 1k, the stderr buffer is filled up.
|
|
|
e3c68b |
|
|
|
e3c68b |
Fix:
|
|
|
e3c68b |
The tar process is executed using Popen with stderr as PIPE.
|
|
|
e3c68b |
The final execution is something like below.
|
|
|
e3c68b |
|
|
|
e3c68b |
tar | ssh <args> root@slave tar --overwrite -xf - -C <path>
|
|
|
e3c68b |
|
|
|
e3c68b |
It was waiting on ssh process first using communicate() and then tar.
|
|
|
e3c68b |
Note that communicate() reads stdout and stderr. So when stderr of tar
|
|
|
e3c68b |
process is filled up, there is no one to read until untar via ssh is
|
|
|
e3c68b |
completed. This can't happen and leads to deadlock.
|
|
|
e3c68b |
Hence we should be waiting on both process parallely, so that stderr is
|
|
|
e3c68b |
read on both processes.
|
|
|
e3c68b |
|
|
|
e3c68b |
Backport of:
|
|
|
e3c68b |
> Patch: https://review.gluster.org/22684
|
|
|
e3c68b |
> Change-Id: I609c7cc5c07e210c504771115b4d551a2e891adf
|
|
|
e3c68b |
> BUG: 1707728
|
|
|
e3c68b |
> Signed-off-by: Kotresh HR <khiremat@redhat.com>
|
|
|
e3c68b |
|
|
|
e3c68b |
Change-Id: I609c7cc5c07e210c504771115b4d551a2e891adf
|
|
|
e3c68b |
fixes: bz#1708116
|
|
|
e3c68b |
Signed-off-by: Kotresh HR <khiremat@redhat.com>
|
|
|
e3c68b |
Reviewed-on: https://code.engineering.redhat.com/gerrit/172395
|
|
|
e3c68b |
Tested-by: RHGS Build Bot <nigelb@redhat.com>
|
|
|
e3c68b |
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
|
|
|
e3c68b |
---
|
|
|
e3c68b |
geo-replication/syncdaemon/resource.py | 22 ++++--
|
|
|
e3c68b |
tests/00-geo-rep/georep-stderr-hang.t | 128 +++++++++++++++++++++++++++++++++
|
|
|
e3c68b |
tests/geo-rep.rc | 17 +++++
|
|
|
e3c68b |
3 files changed, 163 insertions(+), 4 deletions(-)
|
|
|
e3c68b |
create mode 100644 tests/00-geo-rep/georep-stderr-hang.t
|
|
|
e3c68b |
|
|
|
e3c68b |
diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py
|
|
|
e3c68b |
index 522279b..b16db60 100644
|
|
|
e3c68b |
--- a/geo-replication/syncdaemon/resource.py
|
|
|
e3c68b |
+++ b/geo-replication/syncdaemon/resource.py
|
|
|
e3c68b |
@@ -1540,15 +1540,29 @@ class SSH(object):
|
|
|
e3c68b |
|
|
|
e3c68b |
p0.stdin.close()
|
|
|
e3c68b |
p0.stdout.close() # Allow p0 to receive a SIGPIPE if p1 exits.
|
|
|
e3c68b |
- # wait for tar to terminate, collecting any errors, further
|
|
|
e3c68b |
- # waiting for transfer to complete
|
|
|
e3c68b |
- _, stderr1 = p1.communicate()
|
|
|
e3c68b |
|
|
|
e3c68b |
# stdin and stdout of p0 is already closed, Reset to None and
|
|
|
e3c68b |
# wait for child process to complete
|
|
|
e3c68b |
p0.stdin = None
|
|
|
e3c68b |
p0.stdout = None
|
|
|
e3c68b |
- p0.communicate()
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+ def wait_for_tar(p0):
|
|
|
e3c68b |
+ _, stderr = p0.communicate()
|
|
|
e3c68b |
+ if log_err:
|
|
|
e3c68b |
+ for errline in stderr.strip().split("\n")[:-1]:
|
|
|
e3c68b |
+ if "No such file or directory" not in errline:
|
|
|
e3c68b |
+ logging.error(lf("SYNC Error",
|
|
|
e3c68b |
+ sync_engine="Tarssh",
|
|
|
e3c68b |
+ error=errline))
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+ t = syncdutils.Thread(target=wait_for_tar, args=(p0, ))
|
|
|
e3c68b |
+ # wait for tar to terminate, collecting any errors, further
|
|
|
e3c68b |
+ # waiting for transfer to complete
|
|
|
e3c68b |
+ t.start()
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+ # wait for ssh process
|
|
|
e3c68b |
+ _, stderr1 = p1.communicate()
|
|
|
e3c68b |
+ t.join()
|
|
|
e3c68b |
|
|
|
e3c68b |
if log_err:
|
|
|
e3c68b |
for errline in stderr1.strip().split("\n")[:-1]:
|
|
|
e3c68b |
diff --git a/tests/00-geo-rep/georep-stderr-hang.t b/tests/00-geo-rep/georep-stderr-hang.t
|
|
|
e3c68b |
new file mode 100644
|
|
|
e3c68b |
index 0000000..496f0e6
|
|
|
e3c68b |
--- /dev/null
|
|
|
e3c68b |
+++ b/tests/00-geo-rep/georep-stderr-hang.t
|
|
|
e3c68b |
@@ -0,0 +1,128 @@
|
|
|
e3c68b |
+#!/bin/bash
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+. $(dirname $0)/../include.rc
|
|
|
e3c68b |
+. $(dirname $0)/../volume.rc
|
|
|
e3c68b |
+. $(dirname $0)/../geo-rep.rc
|
|
|
e3c68b |
+. $(dirname $0)/../env.rc
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+SCRIPT_TIMEOUT=500
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+AREQUAL_PATH=$(dirname $0)/../utils
|
|
|
e3c68b |
+test "`uname -s`" != "Linux" && {
|
|
|
e3c68b |
+ CFLAGS="$CFLAGS -lintl";
|
|
|
e3c68b |
+}
|
|
|
e3c68b |
+build_tester $AREQUAL_PATH/arequal-checksum.c $CFLAGS
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+### Basic Tests with Distribute Replicate volumes
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+##Cleanup and start glusterd
|
|
|
e3c68b |
+cleanup;
|
|
|
e3c68b |
+TEST glusterd;
|
|
|
e3c68b |
+TEST pidof glusterd
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+##Variables
|
|
|
e3c68b |
+GEOREP_CLI="$CLI volume geo-replication"
|
|
|
e3c68b |
+master=$GMV0
|
|
|
e3c68b |
+SH0="127.0.0.1"
|
|
|
e3c68b |
+slave=${SH0}::${GSV0}
|
|
|
e3c68b |
+num_active=2
|
|
|
e3c68b |
+num_passive=2
|
|
|
e3c68b |
+master_mnt=$M0
|
|
|
e3c68b |
+slave_mnt=$M1
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+############################################################
|
|
|
e3c68b |
+#SETUP VOLUMES AND GEO-REPLICATION
|
|
|
e3c68b |
+############################################################
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+##create_and_start_master_volume
|
|
|
e3c68b |
+TEST $CLI volume create $GMV0 $H0:$B0/${GMV0}1;
|
|
|
e3c68b |
+TEST $CLI volume start $GMV0
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+##create_and_start_slave_volume
|
|
|
e3c68b |
+TEST $CLI volume create $GSV0 $H0:$B0/${GSV0}1;
|
|
|
e3c68b |
+TEST $CLI volume start $GSV0
|
|
|
e3c68b |
+TEST $CLI volume set $GSV0 performance.stat-prefetch off
|
|
|
e3c68b |
+TEST $CLI volume set $GSV0 performance.quick-read off
|
|
|
e3c68b |
+TEST $CLI volume set $GSV0 performance.readdir-ahead off
|
|
|
e3c68b |
+TEST $CLI volume set $GSV0 performance.read-ahead off
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+##Mount master
|
|
|
e3c68b |
+TEST glusterfs -s $H0 --volfile-id $GMV0 $M0
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+##Mount slave
|
|
|
e3c68b |
+TEST glusterfs -s $H0 --volfile-id $GSV0 $M1
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+############################################################
|
|
|
e3c68b |
+#BASIC GEO-REPLICATION TESTS
|
|
|
e3c68b |
+############################################################
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+TEST create_georep_session $master $slave
|
|
|
e3c68b |
+EXPECT_WITHIN $GEO_REP_TIMEOUT 1 check_status_num_rows "Created"
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Config gluster-command-dir
|
|
|
e3c68b |
+TEST $GEOREP_CLI $master $slave config gluster-command-dir ${GLUSTER_CMD_DIR}
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Config gluster-command-dir
|
|
|
e3c68b |
+TEST $GEOREP_CLI $master $slave config slave-gluster-command-dir ${GLUSTER_CMD_DIR}
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Set changelog roll-over time to 45 secs
|
|
|
e3c68b |
+TEST $CLI volume set $GMV0 changelog.rollover-time 45
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Wait for common secret pem file to be created
|
|
|
e3c68b |
+EXPECT_WITHIN $GEO_REP_TIMEOUT 0 check_common_secret_file
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Verify the keys are distributed
|
|
|
e3c68b |
+EXPECT_WITHIN $GEO_REP_TIMEOUT 0 check_keys_distributed
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Set sync-jobs to 1
|
|
|
e3c68b |
+TEST $GEOREP_CLI $master $slave config sync-jobs 1
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Start_georep
|
|
|
e3c68b |
+TEST $GEOREP_CLI $master $slave start
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+touch $M0
|
|
|
e3c68b |
+EXPECT_WITHIN $GEO_REP_TIMEOUT 1 check_status_num_rows "Active"
|
|
|
e3c68b |
+EXPECT_WITHIN $GEO_REP_TIMEOUT 1 check_status_num_rows "Changelog Crawl"
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Check History Crawl.
|
|
|
e3c68b |
+TEST $GEOREP_CLI $master $slave stop
|
|
|
e3c68b |
+TEST create_data_hang "rsync_hang"
|
|
|
e3c68b |
+TEST create_data "history_rsync"
|
|
|
e3c68b |
+TEST $GEOREP_CLI $master $slave start
|
|
|
e3c68b |
+EXPECT_WITHIN $GEO_REP_TIMEOUT 1 check_status_num_rows "Active"
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Verify arequal for whole volume
|
|
|
e3c68b |
+EXPECT_WITHIN $GEO_REP_TIMEOUT "x0" arequal_checksum ${master_mnt} ${slave_mnt}
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Stop Geo-rep
|
|
|
e3c68b |
+TEST $GEOREP_CLI $master $slave stop
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Config tarssh as sync-engine
|
|
|
e3c68b |
+TEST $GEOREP_CLI $master $slave config sync-method tarssh
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Create tarssh hang data
|
|
|
e3c68b |
+TEST create_data_hang "tarssh_hang"
|
|
|
e3c68b |
+TEST create_data "history_tar"
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+TEST $GEOREP_CLI $master $slave start
|
|
|
e3c68b |
+EXPECT_WITHIN $GEO_REP_TIMEOUT 1 check_status_num_rows "Active"
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Verify arequal for whole volume
|
|
|
e3c68b |
+EXPECT_WITHIN $GEO_REP_TIMEOUT "x0" arequal_checksum ${master_mnt} ${slave_mnt}
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Stop Geo-rep
|
|
|
e3c68b |
+TEST $GEOREP_CLI $master $slave stop
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Delete Geo-rep
|
|
|
e3c68b |
+TEST $GEOREP_CLI $master $slave delete
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Cleanup are-equal binary
|
|
|
e3c68b |
+TEST rm $AREQUAL_PATH/arequal-checksum
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+#Cleanup authorized keys
|
|
|
e3c68b |
+sed -i '/^command=.*SSH_ORIGINAL_COMMAND#.*/d' ~/.ssh/authorized_keys
|
|
|
e3c68b |
+sed -i '/^command=.*gsyncd.*/d' ~/.ssh/authorized_keys
|
|
|
e3c68b |
+
|
|
|
e3c68b |
+cleanup;
|
|
|
e3c68b |
+#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=000000
|
|
|
e3c68b |
diff --git a/tests/geo-rep.rc b/tests/geo-rep.rc
|
|
|
e3c68b |
index 2035b9f..e4f014e 100644
|
|
|
e3c68b |
--- a/tests/geo-rep.rc
|
|
|
e3c68b |
+++ b/tests/geo-rep.rc
|
|
|
e3c68b |
@@ -101,6 +101,23 @@ function create_data()
|
|
|
e3c68b |
chown 1000:1000 ${master_mnt}/${prefix}_chown_f1_ಸಂತಸ
|
|
|
e3c68b |
}
|
|
|
e3c68b |
|
|
|
e3c68b |
+function create_data_hang()
|
|
|
e3c68b |
+{
|
|
|
e3c68b |
+ prefix=$1
|
|
|
e3c68b |
+ mkdir ${master_mnt}/${prefix}
|
|
|
e3c68b |
+ cd ${master_mnt}/${prefix}
|
|
|
e3c68b |
+ # ~1k files is required with 1 sync-job and hang happens if
|
|
|
e3c68b |
+ # stderr buffer of tar/ssh executed with Popen is full (i.e., 64k).
|
|
|
e3c68b |
+ # 64k is hit when ~800 files were not found while syncing data
|
|
|
e3c68b |
+ # from master. So around 1k files is required to hit the condition.
|
|
|
e3c68b |
+ for i in {1..1000}
|
|
|
e3c68b |
+ do
|
|
|
e3c68b |
+ echo "test data" > file$i
|
|
|
e3c68b |
+ mv -f file$i file
|
|
|
e3c68b |
+ done
|
|
|
e3c68b |
+ cd -
|
|
|
e3c68b |
+}
|
|
|
e3c68b |
+
|
|
|
e3c68b |
function chown_file_ok()
|
|
|
e3c68b |
{
|
|
|
e3c68b |
local file_owner=$(stat --format "%u:%g" "$1")
|
|
|
e3c68b |
--
|
|
|
e3c68b |
1.8.3.1
|
|
|
e3c68b |
|