autobuild v3.12.2-41

Resolves: bz#1390151 bz#1410145 bz#1429190 bz#1510752 bz#1511779
Resolves: bz#1570958 bz#1574490 bz#1595246 bz#1618669 bz#1661393
Resolves: bz#1668989 bz#1669020
Signed-off-by: Milind Changire <mchangir@redhat.com>
This commit is contained in:
Milind Changire 2019-02-11 20:46:22 -05:00
parent 7674b73703
commit 2f3c8edfdf
20 changed files with 6018 additions and 74 deletions

View File

@ -0,0 +1,27 @@
From 4049de578f44e028ebe6beab3b1b13ce4d3de954 Mon Sep 17 00:00:00 2001
From: Milind Changire <mchangir@redhat.com>
Date: Fri, 1 Feb 2019 19:55:33 +0530
Subject: [PATCH 511/529] Update rfc.sh to rhgs-3.4.4
Change-Id: I826c246fefecf8cf12999e3b4b307d0a29aef668
Signed-off-by: Milind Changire <mchangir@redhat.com>
---
rfc.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rfc.sh b/rfc.sh
index bd52851..6f5c77c 100755
--- a/rfc.sh
+++ b/rfc.sh
@@ -17,7 +17,7 @@ done
shift $((OPTIND-1))
-branch="rhgs-3.4.3";
+branch="rhgs-3.4.4";
set_hooks_commit_msg()
{
--
1.8.3.1

View File

@ -0,0 +1,533 @@
From 5f8f80190c154bbb159a3cebbb7d3e12014275ed Mon Sep 17 00:00:00 2001
From: Nigel Babu <nbabu@redhat.com>
Date: Mon, 30 Apr 2018 11:28:06 +0530
Subject: [PATCH 512/529] Test fixes for rhgs-3.4 downstream
This patch includes test fixes and two tests are removed
because they're not supported downstream.
Label: DOWNSTREAM ONLY
Change-Id: I99072130cea4780654980837522c76eab38e79d3
Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com>
Signed-off-by: Sanju Rakonde <srakonde@redhat.com>
Signed-off-by: Ravishankar N <ravishankar@redhat.com>
Signed-off-by: Sunil Kumar Acharya <sheggodu@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162177
---
tests/basic/bd.t | 142 ---------------------
tests/basic/ec/ec-1468261.t | 1 +
tests/bugs/cli/bug-1169302.t | 4 +-
tests/bugs/core/multiplex-limit-issue-151.t | 2 +-
tests/bugs/distribute/bug-882278.t | 73 -----------
tests/bugs/glusterd/brick-mux-fd-cleanup.t | 3 +
.../glusterd/bug-1245045-remove-brick-validation.t | 16 ++-
.../glusterd/bug-1293414-import-brickinfo-uuid.t | 1 +
.../bug-1483058-replace-brick-quorum-validation.t | 9 +-
tests/bugs/glusterd/bug-1595320.t | 2 +-
.../df-results-post-replace-brick-operations.t | 3 +
tests/bugs/posix/bug-990028.t | 2 +-
tests/bugs/readdir-ahead/bug-1439640.t | 1 +
.../replicate/bug-1591193-assign-gfid-and-heal.t | 5 +-
.../bug-1637802-arbiter-stale-data-heal-lock.t | 1 +
tests/bugs/shard/zero-flag.t | 1 +
tests/cluster.rc | 10 ++
tests/include.rc | 1 +
18 files changed, 48 insertions(+), 229 deletions(-)
delete mode 100755 tests/basic/bd.t
delete mode 100755 tests/bugs/distribute/bug-882278.t
diff --git a/tests/basic/bd.t b/tests/basic/bd.t
deleted file mode 100755
index 63622ed..0000000
--- a/tests/basic/bd.t
+++ /dev/null
@@ -1,142 +0,0 @@
-#!/bin/bash
-
-. $(dirname $0)/../include.rc
-. $(dirname $0)/../volume.rc
-
-function execute()
-{
- cmd=$1
- shift
- ${cmd} $@ >/dev/null 2>&1
-}
-
-function bd_cleanup()
-{
- execute vgremove -f ${V0}
- execute pvremove ${ld}
- execute losetup -d ${ld}
- execute rm ${BD_DISK}
- cleanup
-}
-
-function check()
-{
- if [ $? -ne 0 ]; then
- echo prerequsite $@ failed
- bd_cleanup
- exit
- fi
-}
-
-SIZE=256 #in MB
-
-bd_cleanup;
-
-## Configure environment needed for BD backend volumes
-## Create a file with configured size and
-## set it as a temporary loop device to create
-## physical volume & VG. These are basic things needed
-## for testing BD xlator if anyone of these steps fail,
-## test script exits
-function configure()
-{
- GLDIR=`$CLI system:: getwd`
- BD_DISK=${GLDIR}/bd_disk
-
- execute truncate -s${SIZE}M ${BD_DISK}
- check ${BD_DISK} creation
-
- execute losetup -f
- check losetup
- ld=`losetup -f`
-
- execute losetup ${ld} ${BD_DISK}
- check losetup ${BD_DISK}
- execute pvcreate -f ${ld}
- check pvcreate ${ld}
- execute vgcreate ${V0} ${ld}
- check vgcreate ${V0}
- execute lvcreate --thin ${V0}/pool --size 128M
-}
-
-function volinfo_field()
-{
- local vol=$1;
- local field=$2;
- $CLI volume info $vol | grep "^$field: " | sed 's/.*: //';
-}
-
-function volume_type()
-{
- getfattr -n volume.type $M0/. --only-values --absolute-names -e text
-}
-
-case $OSTYPE in
-NetBSD)
- echo "Skip test on LVM which is not available on NetBSD" >&2
- SKIP_TESTS
- exit 0
- ;;
-*)
- ;;
-esac
-
-TEST glusterd
-TEST pidof glusterd
-configure
-
-TEST $CLI volume create $V0 ${H0}:/$B0/$V0?${V0}
-EXPECT "$V0" volinfo_field $V0 'Volume Name';
-EXPECT 'Created' volinfo_field $V0 'Status';
-
-## Start volume and verify
-TEST $CLI volume start $V0;
-EXPECT 'Started' volinfo_field $V0 'Status'
-
-TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0;
-EXPECT '1' volume_type
-
-## Create posix file
-TEST touch $M0/posix
-
-TEST touch $M0/lv
-gfid=`getfattr -n glusterfs.gfid.string $M0/lv --only-values --absolute-names`
-TEST setfattr -n user.glusterfs.bd -v "lv:4MB" $M0/lv
-# Check if LV is created
-TEST stat /dev/$V0/${gfid}
-
-## Create filesystem
-sleep 1
-TEST mkfs.ext4 -qF $M0/lv
-# Cloning
-TEST touch $M0/lv_clone
-gfid=`getfattr -n glusterfs.gfid.string $M0/lv_clone --only-values --absolute-names`
-TEST setfattr -n clone -v ${gfid} $M0/lv
-TEST stat /dev/$V0/${gfid}
-
-sleep 1
-## Check mounting
-TEST mount -o loop $M0/lv $M1
-EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M1
-
-# Snapshot
-TEST touch $M0/lv_sn
-gfid=`getfattr -n glusterfs.gfid.string $M0/lv_sn --only-values --absolute-names`
-TEST setfattr -n snapshot -v ${gfid} $M0/lv
-TEST stat /dev/$V0/${gfid}
-
-# Merge
-sleep 1
-TEST setfattr -n merge -v "$M0/lv_sn" $M0/lv_sn
-TEST ! stat $M0/lv_sn
-TEST ! stat /dev/$V0/${gfid}
-
-
-rm $M0/* -f
-
-EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
-TEST $CLI volume stop ${V0}
-EXPECT 'Stopped' volinfo_field $V0 'Status';
-TEST $CLI volume delete ${V0}
-
-bd_cleanup
diff --git a/tests/basic/ec/ec-1468261.t b/tests/basic/ec/ec-1468261.t
index d687d7b..b2d92fc 100644
--- a/tests/basic/ec/ec-1468261.t
+++ b/tests/basic/ec/ec-1468261.t
@@ -14,6 +14,7 @@ TEST glusterd
TEST pidof glusterd
TEST $CLI volume create $V0 disperse 6 redundancy 2 $H0:$B0/${V0}{0..5}
TEST $CLI volume set $V0 disperse.optimistic-change-log on
+TEST $CLI volume set $V0 disperse.other-eager-lock on
TEST $CLI volume start $V0
#Mount the volume
diff --git a/tests/bugs/cli/bug-1169302.t b/tests/bugs/cli/bug-1169302.t
index 24355e5..05c006c 100755
--- a/tests/bugs/cli/bug-1169302.t
+++ b/tests/bugs/cli/bug-1169302.t
@@ -40,7 +40,9 @@ cleanup_statedump
# hostname or IP-address with the connection from the bug-1169302 executable.
# In our CI it seems not possible to use $H0, 'localhost', $(hostname --fqdn)
# or even "127.0.0.1"....
-TEST $CLI_3 volume statedump $V0 client $H1:$GFAPI_PID
+sleep 2
+host=`netstat -nap | grep $GFAPI_PID | grep 24007 | awk '{print $4}' | cut -d: -f1`
+TEST $CLI_3 volume statedump $V0 client $host:$GFAPI_PID
EXPECT_WITHIN $STATEDUMP_TIMEOUT "Y" path_exists $statedumpdir/glusterdump.$GFAPI_PID*
kill $GFAPI_PID
diff --git a/tests/bugs/core/multiplex-limit-issue-151.t b/tests/bugs/core/multiplex-limit-issue-151.t
index 9511756..c5bbbda 100644
--- a/tests/bugs/core/multiplex-limit-issue-151.t
+++ b/tests/bugs/core/multiplex-limit-issue-151.t
@@ -50,7 +50,7 @@ EXPECT_WITHIN $PROCESS_UP_TIMEOUT 3 count_brick_pids
EXPECT_WITHIN $PROCESS_UP_TIMEOUT 7 count_up_bricks
TEST $CLI volume remove-brick $V0 $H0:$B0/brick3 start
-TEST $CLI volume remove-brick $V0 $H0:$B0/brick3 commit
+TEST $CLI volume remove-brick $V0 $H0:$B0/brick3 force
EXPECT_WITHIN $PROCESS_UP_TIMEOUT 3 count_brick_processes
EXPECT_WITHIN $PROCESS_UP_TIMEOUT 3 count_brick_pids
diff --git a/tests/bugs/distribute/bug-882278.t b/tests/bugs/distribute/bug-882278.t
deleted file mode 100755
index 8cb5147..0000000
--- a/tests/bugs/distribute/bug-882278.t
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/bash
-
-. $(dirname $0)/../../include.rc
-. $(dirname $0)/../../volume.rc
-cleanup
-
-# Is there a good reason to require --fqdn elsewhere? It's worse than useless
-# here.
-H0=$(hostname -s)
-
-function recreate {
- # The rm is necessary so we don't get fooled by leftovers from old runs.
- rm -rf $1 && mkdir -p $1
-}
-
-function count_lines {
- grep "$1" $2/* | wc -l
-}
-
-TEST glusterd
-TEST pidof glusterd
-TEST $CLI volume info;
-
-## Start and create a volume
-TEST recreate ${B0}/${V0}-0
-TEST recreate ${B0}/${V0}-1
-TEST $CLI volume create $V0 $H0:$B0/${V0}-{0,1}
-TEST $CLI volume set $V0 cluster.nufa on
-
-function volinfo_field()
-{
- local vol=$1;
- local field=$2;
-
- $CLI volume info $vol | grep "^$field: " | sed 's/.*: //';
-}
-
-
-## Verify volume is created
-EXPECT "$V0" volinfo_field $V0 'Volume Name';
-EXPECT 'Created' volinfo_field $V0 'Status';
-
-## Start volume and verify
-TEST $CLI volume start $V0;
-EXPECT 'Started' volinfo_field $V0 'Status';
-
-## Mount native
-special_option="--xlator-option ${V0}-dht.local-volume-name=${V0}-client-1"
-TEST glusterfs --volfile-server=$H0 --volfile-id=$V0 $special_option $M0
-
-## Create a bunch of test files.
-for i in $(seq 0 99); do
- echo hello > $(printf $M0/file%02d $i)
-done
-
-## Make sure the files went to the right place. There might be link files in
-## the other brick, but they won't have any contents.
-EXPECT "0" count_lines hello ${B0}/${V0}-0
-EXPECT "100" count_lines hello ${B0}/${V0}-1
-
-if [ "$EXIT_EARLY" = "1" ]; then
- exit 0;
-fi
-
-## Finish up
-EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
-TEST $CLI volume stop $V0;
-EXPECT 'Stopped' volinfo_field $V0 'Status';
-
-TEST $CLI volume delete $V0;
-TEST ! $CLI volume info $V0;
-
-cleanup;
diff --git a/tests/bugs/glusterd/brick-mux-fd-cleanup.t b/tests/bugs/glusterd/brick-mux-fd-cleanup.t
index de11c17..2ac7f9c 100644
--- a/tests/bugs/glusterd/brick-mux-fd-cleanup.t
+++ b/tests/bugs/glusterd/brick-mux-fd-cleanup.t
@@ -76,3 +76,6 @@ EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M1
cleanup
+
+#delay-gen in not present downstream
+#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=000000
diff --git a/tests/bugs/glusterd/bug-1245045-remove-brick-validation.t b/tests/bugs/glusterd/bug-1245045-remove-brick-validation.t
index 597c40c..a931d29 100644
--- a/tests/bugs/glusterd/bug-1245045-remove-brick-validation.t
+++ b/tests/bugs/glusterd/bug-1245045-remove-brick-validation.t
@@ -3,12 +3,16 @@
. $(dirname $0)/../../include.rc
. $(dirname $0)/../../cluster.rc
+function peer_count {
+eval \$CLI_$1 peer status | grep 'Peer in Cluster (Connected)' | wc -l
+}
+
cleanup
TEST launch_cluster 3;
TEST $CLI_1 peer probe $H2;
TEST $CLI_1 peer probe $H3;
-EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count
+EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count 1
TEST $CLI_1 volume create $V0 $H1:$B1/$V0 $H2:$B2/$V0
TEST $CLI_1 volume start $V0
@@ -21,7 +25,9 @@ TEST ! $CLI_1 volume remove-brick $V0 $H2:$B2/${V0} start
TEST start_glusterd 2
EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status_1 $V0 $H2 $B2/${V0}
-EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count
+EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count 1
+EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count 2
+EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count 3
#volume status should work
TEST $CLI_2 volume status
@@ -36,7 +42,7 @@ TEST ! $CLI_1 volume remove-brick $V0 $H2:$B2/${V0} commit
TEST start_glusterd 2
EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status_1 $V0 $H2 $B2/${V0}
-EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count
+EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count 1
#volume status should work
TEST $CLI_2 volume status
@@ -44,12 +50,12 @@ TEST $CLI_2 volume status
TEST $CLI_1 volume remove-brick $V0 $H2:$B2/${V0} stop
kill_glusterd 3
-EXPECT_WITHIN $PROBE_TIMEOUT 1 peer_count
+EXPECT_WITHIN $PROBE_TIMEOUT 1 peer_count 1
TEST $CLI_1 volume remove-brick $V0 $H2:$B2/${V0} start
TEST start_glusterd 3
-EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count
+EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count 1
TEST $CLI_3 volume status
diff --git a/tests/bugs/glusterd/bug-1293414-import-brickinfo-uuid.t b/tests/bugs/glusterd/bug-1293414-import-brickinfo-uuid.t
index 9f67e4c..977276e 100755
--- a/tests/bugs/glusterd/bug-1293414-import-brickinfo-uuid.t
+++ b/tests/bugs/glusterd/bug-1293414-import-brickinfo-uuid.t
@@ -24,6 +24,7 @@ EXPECT_WITHIN $PROBE_TIMEOUT 3 peer_count
TEST ! $CLI_3 peer detach $H1
TEST ! $CLI_3 peer detach $H2
+EXPECT_WITHIN $PROBE_TIMEOUT 3 peer_count
# peer not hosting bricks should be detachable
TEST $CLI_3 peer detach $H4
diff --git a/tests/bugs/glusterd/bug-1483058-replace-brick-quorum-validation.t b/tests/bugs/glusterd/bug-1483058-replace-brick-quorum-validation.t
index 3dbe28a..2d9e528 100644
--- a/tests/bugs/glusterd/bug-1483058-replace-brick-quorum-validation.t
+++ b/tests/bugs/glusterd/bug-1483058-replace-brick-quorum-validation.t
@@ -45,7 +45,14 @@ TEST start_glusterd 2
EXPECT_WITHIN $PROBE_TIMEOUT 2 peer_count
+# checking peer_count is not enough to call that quorum is regained as
+# peer_count is based on peerinfo->connected where as quorum is calculated based
+# on peerinfo->quorum_contrib. To avoid this spurious race of replace brick
+# commit force to execute and fail before the quorum is regained run the command
+# in EXPECT_WITHIN to ensure that with multiple attempts the command goes
+# through once the quorum is regained.
+
# Now quorum is met. replace-brick will execute successfuly
-TEST $CLI_1 volume replace-brick $V0 $H2:$B2/${V0}1 $H1:$B1/${V0}1_new commit force
+EXPECT_WITHIN $PEER_SYNC_TIMEOUT 0 attempt_replace_brick 1 $V0 $H2:$B2/${V0}1 $H1:$B1/${V0}1_new
#cleanup;
diff --git a/tests/bugs/glusterd/bug-1595320.t b/tests/bugs/glusterd/bug-1595320.t
index f41df9d..3a289f3 100644
--- a/tests/bugs/glusterd/bug-1595320.t
+++ b/tests/bugs/glusterd/bug-1595320.t
@@ -25,7 +25,7 @@ TEST pidof glusterd
# Create volume and enable brick multiplexing
TEST $CLI volume create $V0 $H0:$L1 $H0:$L2 $H0:$L3
-gluster v set all cluster.brick-multiplex on
+TEST $CLI v set all cluster.brick-multiplex on
# Start the volume
TEST $CLI volume start $V0
diff --git a/tests/bugs/glusterd/df-results-post-replace-brick-operations.t b/tests/bugs/glusterd/df-results-post-replace-brick-operations.t
index 443911c..04f7588 100644
--- a/tests/bugs/glusterd/df-results-post-replace-brick-operations.t
+++ b/tests/bugs/glusterd/df-results-post-replace-brick-operations.t
@@ -53,6 +53,9 @@ total_space=$(df -P $M0 | tail -1 | awk '{ print $2}')
TEST $CLI volume replace-brick $V0 $H0:$B0/${V0}1/brick1 $H0:$B0/${V0}4/brick1 commit force
TEST $CLI volume replace-brick $V0 $H0:$B0/${V0}2/brick1 $H0:$B0/${V0}5/brick1 commit force
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1
+
# check for the size at mount point, it should be same as previous
total_space_new=$(df -P $M0 | tail -1 | awk '{ print $2}')
TEST [ $total_space -eq $total_space_new ]
diff --git a/tests/bugs/posix/bug-990028.t b/tests/bugs/posix/bug-990028.t
index c864214..bef36a8 100755
--- a/tests/bugs/posix/bug-990028.t
+++ b/tests/bugs/posix/bug-990028.t
@@ -78,7 +78,7 @@ function links_across_directories()
TEST [ $LINES = 2 ]
for i in $(seq 1 2); do
- HL=`getfattr -m "trusted.pgfid.*" -de hex $B0/brick/dir$i/file$i 2>&1 | grep "trusted.pgfid" | cut -d$'\n' -f$i | cut -d'=' -f2`
+ HL=`getfattr -m "trusted.pgfid.*" -de hex $B0/brick/dir$i/file$i 2>&1 | grep "trusted.pgfid" | awk -v n=$i 'NR==n' | cut -d'=' -f2`
TEST_IN_LOOP [ $HL = "0x00000001" ]
done
diff --git a/tests/bugs/readdir-ahead/bug-1439640.t b/tests/bugs/readdir-ahead/bug-1439640.t
index cc6c829..dcd5407 100755
--- a/tests/bugs/readdir-ahead/bug-1439640.t
+++ b/tests/bugs/readdir-ahead/bug-1439640.t
@@ -8,6 +8,7 @@ cleanup;
TEST glusterd
TEST $CLI volume create $V0 $H0:$B{0..1}/$V0
+TEST $CLI volume set $V0 readdir-ahead on
TEST $CLI volume start $V0
TEST ! $CLI volume set $V0 parallel-readdir sdf
diff --git a/tests/bugs/replicate/bug-1591193-assign-gfid-and-heal.t b/tests/bugs/replicate/bug-1591193-assign-gfid-and-heal.t
index d3b5f9a..a2abaf6 100644
--- a/tests/bugs/replicate/bug-1591193-assign-gfid-and-heal.t
+++ b/tests/bugs/replicate/bug-1591193-assign-gfid-and-heal.t
@@ -108,10 +108,7 @@ TEST stat $M0/file2
# Though file is created on all 3 bricks, lookup will fail as arbiter blames the
# other 2 bricks and ariter is not 'readable'.
-# TEST ! stat $M0/file3
-# But the checks for failing lookups when quorum is not met is not yet there in
-# rhgs-3.4.0, so stat will succeed.
-TEST stat $M0/file3
+TEST ! stat $M0/file3
# Launch index heal to complete any pending data/metadata heals.
TEST $CLI volume heal $V0
diff --git a/tests/bugs/replicate/bug-1637802-arbiter-stale-data-heal-lock.t b/tests/bugs/replicate/bug-1637802-arbiter-stale-data-heal-lock.t
index 91ed39b..d7d1f28 100644
--- a/tests/bugs/replicate/bug-1637802-arbiter-stale-data-heal-lock.t
+++ b/tests/bugs/replicate/bug-1637802-arbiter-stale-data-heal-lock.t
@@ -32,6 +32,7 @@ EXPECT 2 get_pending_heal_count $V0
# Bring it back up and let heal complete.
TEST $CLI volume start $V0 force
EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}2
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0
EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1
EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 2
diff --git a/tests/bugs/shard/zero-flag.t b/tests/bugs/shard/zero-flag.t
index 84cb963..1f39787 100644
--- a/tests/bugs/shard/zero-flag.t
+++ b/tests/bugs/shard/zero-flag.t
@@ -14,6 +14,7 @@ TEST glusterd
TEST pidof glusterd
TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1,2,3}
TEST $CLI volume set $V0 features.shard on
+TEST $CLI volume set $V0 features.shard-block-size 4MB
TEST $CLI volume start $V0
TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0
diff --git a/tests/cluster.rc b/tests/cluster.rc
index c1ff8ab..e258b58 100644
--- a/tests/cluster.rc
+++ b/tests/cluster.rc
@@ -142,6 +142,16 @@ function peer_count() {
$CLI_1 peer status | grep 'Peer in Cluster (Connected)' | wc -l
}
+function attempt_replace_brick {
+ local cli_no=$1
+ local vol=$2;
+ local src_brick=$3;
+ local dst_brick=$4;
+
+ eval \$CLI_$cli_no volume replace-brick $vol $src_brick $dst_brick commit force;
+ echo $?
+}
+
function cluster_rebalance_status_field {
#The rebalance status can be up to 3 words, (e.g.:'fix-layout in progress'), hence the awk-print $7 thru $9.
#But if the status is less than 3 words, it also prints the next field i.e the run_time_in_secs.(e.g.:'completed 3.00').
diff --git a/tests/include.rc b/tests/include.rc
index aca4c4a..81146f4 100644
--- a/tests/include.rc
+++ b/tests/include.rc
@@ -74,6 +74,7 @@ PROCESS_UP_TIMEOUT=30
NFS_EXPORT_TIMEOUT=20
CHILD_UP_TIMEOUT=20
PROBE_TIMEOUT=60
+PEER_SYNC_TIMEOUT=20
REBALANCE_TIMEOUT=360
REOPEN_TIMEOUT=20
HEAL_TIMEOUT=80
--
1.8.3.1

View File

@ -0,0 +1,114 @@
From 61d178c25468adfac4cbdfcef43a0d002c635466 Mon Sep 17 00:00:00 2001
From: Mohit Agrawal <moagrawa@redhat.com>
Date: Tue, 5 Feb 2019 12:49:10 +0530
Subject: [PATCH 513/529] core: heketi-cli is throwing error "target is busy"
Problem: When rpc-transport-disconnect happens, server_connection_cleanup_flush_cbk()
is supposed to call rpc_transport_unref() after open-files on
that transport are flushed per transport.But open-fd-count is
maintained in bound_xl->fd_count, which can be incremented/decremented
cumulatively in server_connection_cleanup() by all transport
disconnect paths. So instead of rpc_transport_unref() happening
per transport, it ends up doing it only once after all the files
on all the transports for the brick are flushed leading to
rpc-leaks.
Solution: To avoid races maintain fd_cnt at client instead of maintaining
on brick
Credits: Pranith Kumar Karampuri
> Change-Id: I6e8ea37a61f82d9aefb227c5b3ab57a7a36850e6
> fixes: bz#1668190
> (Cherry pick from commit b41cdeb638f9f9ec2fef13ec95c216faf52a9df9)
> (Reviewed on upstream link https://review.gluster.org/#/c/glusterfs/+/22108/)
Change-Id: Ic810095ea1ce418836d240d411168df8be0e4a41
BUG: 1669020
Signed-off-by: Mohit Agrawal <moagrawa@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162251
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
libglusterfs/src/client_t.c | 1 +
libglusterfs/src/client_t.h | 2 ++
libglusterfs/src/xlator.c | 1 -
libglusterfs/src/xlator.h | 3 ---
xlators/protocol/server/src/server-helpers.c | 4 ++--
5 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/libglusterfs/src/client_t.c b/libglusterfs/src/client_t.c
index a9ae62c..7d92e0d 100644
--- a/libglusterfs/src/client_t.c
+++ b/libglusterfs/src/client_t.c
@@ -232,6 +232,7 @@ gf_client_get (xlator_t *this, struct rpcsvc_auth_data *cred, char *client_uid,
GF_ATOMIC_INIT (client->bind, 1);
GF_ATOMIC_INIT (client->count, 1);
+ GF_ATOMIC_INIT(client->fd_cnt, 0);
client->auth.flavour = cred->flavour;
if (cred->flavour != AUTH_NONE) {
diff --git a/libglusterfs/src/client_t.h b/libglusterfs/src/client_t.h
index 088508e..403c488 100644
--- a/libglusterfs/src/client_t.h
+++ b/libglusterfs/src/client_t.h
@@ -46,6 +46,8 @@ typedef struct _client {
inode_t *subdir_inode;
uuid_t subdir_gfid;
int32_t opversion;
+ /* Variable to save fd_count for detach brick */
+ gf_atomic_t fd_cnt;
} client_t;
#define GF_CLIENTCTX_INITIAL_SIZE 8
diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c
index 340d83d..7d90baa 100644
--- a/libglusterfs/src/xlator.c
+++ b/libglusterfs/src/xlator.c
@@ -490,7 +490,6 @@ xlator_init (xlator_t *xl)
xl->instance_name = NULL;
GF_ATOMIC_INIT(xl->xprtrefcnt, 0);
- GF_ATOMIC_INIT(xl->fd_cnt, 0);
if (!xl->init) {
gf_msg (xl->name, GF_LOG_WARNING, 0, LG_MSG_INIT_FAILED,
"No init() found");
diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h
index f8f2630..202bdca 100644
--- a/libglusterfs/src/xlator.h
+++ b/libglusterfs/src/xlator.h
@@ -965,9 +965,6 @@ struct _xlator {
/* flag to avoid recall of xlator_mem_cleanup for xame xlator */
uint32_t call_cleanup;
- /* Variable to save fd_count for detach brick */
- gf_atomic_t fd_cnt;
-
/* Variable to save xprt associated for detach brick */
gf_atomic_t xprtrefcnt;
diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c
index 99256bf..30045ef 100644
--- a/xlators/protocol/server/src/server-helpers.c
+++ b/xlators/protocol/server/src/server-helpers.c
@@ -266,7 +266,7 @@ server_connection_cleanup_flush_cbk (call_frame_t *frame, void *cookie,
victim = client->bound_xl;
if (victim) {
- fd_cnt = GF_ATOMIC_DEC(victim->fd_cnt);
+ fd_cnt = GF_ATOMIC_DEC(client->fd_cnt);
if (!fd_cnt && conf && detach) {
pthread_mutex_lock(&conf->mutex);
{
@@ -413,7 +413,7 @@ server_connection_cleanup (xlator_t *this, client_t *client,
if (fd_cnt) {
if (fd_exist)
(*fd_exist) = _gf_true;
- GF_ATOMIC_ADD(bound_xl->fd_cnt, fd_cnt);
+ GF_ATOMIC_ADD(client->fd_cnt, fd_cnt);
}
}
--
1.8.3.1

View File

@ -0,0 +1,49 @@
From 4413ccd6818a8680c74bc072b784319ce8d8429f Mon Sep 17 00:00:00 2001
From: Sanju Rakonde <srakonde@redhat.com>
Date: Thu, 9 Nov 2017 13:15:51 +0530
Subject: [PATCH 514/529] glusterd: display gluster volume status, when quorum
type is server
Problem: when server-quorum-type is server, after restarting glusterd
in the node which is up, gluster volume status is giving incorrect
information.
Fix: check whether server is blank, before adding other keys into the
dictionary.
upstream patch: https://review.gluster.org/#/c/glusterfs/+/18703/
>Change-Id: I926ebdffab330ccef844f23f6d6556e137914047
>BUG: 1511339
>Signed-off-by: Sanju Rakonde <srakonde@redhat.com>
Change-Id: I926ebdffab330ccef844f23f6d6556e137914047
BUG: 1574490
Signed-off-by: Sanju Rakonde <srakonde@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162399
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
xlators/mgmt/glusterd/src/glusterd-utils.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
index e21ec4e..bafc3af 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -5204,6 +5204,12 @@ glusterd_add_node_to_dict (char *server, dict_t *dict, int count,
* the brick as hostname+path, so this will make more sense
* when output.
*/
+
+ if (!strcmp(server, "")) {
+ ret = 0;
+ goto out;
+ }
+
snprintf (key, sizeof (key), "brick%d.hostname", count);
if (!strcmp (server, priv->nfs_svc.name))
ret = dict_set_str (dict, key, "NFS Server");
--
1.8.3.1

View File

@ -0,0 +1,38 @@
From d7d4504b6f3e7fb659dd20640b53922812d50445 Mon Sep 17 00:00:00 2001
From: Sanju Rakonde <srakonde@redhat.com>
Date: Wed, 6 Feb 2019 19:06:45 +0530
Subject: [PATCH 515/529] cli: change the warning message
This patch changes the warning message user gets, when enabling brick
multiplexing to reflect OCS instead of CNS/CRS.
Label: DOWNSTREAM ONLY
Change-Id: Id5fd87955d5a692f8e57560245f8b0cf9882e1da
BUG: 1661393
Signed-off-by: Sanju Rakonde <srakonde@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162405
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
Tested-by: RHGS Build Bot <nigelb@redhat.com>
---
cli/src/cli-cmd-parser.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index e790d79..dcce9d3 100644
--- a/cli/src/cli-cmd-parser.c
+++ b/cli/src/cli-cmd-parser.c
@@ -1742,8 +1742,8 @@ cli_cmd_volume_set_parse (struct cli_state *state, const char **words,
if ((strcmp (key, "cluster.brick-multiplex") == 0)) {
question = "Brick-multiplexing is supported only for "
- "container workloads (CNS/CRS). Also it is "
- "advised to make sure that either all "
+ "OCS converged or independent mode. Also it"
+ " is advised to make sure that either all "
"volumes are in stopped state or no bricks "
"are running before this option is modified."
"Do you still want to continue?";
--
1.8.3.1

View File

@ -0,0 +1,84 @@
From 39bf395e91021dd51d53c312d6e02638267c3a6b Mon Sep 17 00:00:00 2001
From: Kotresh HR <khiremat@redhat.com>
Date: Tue, 20 Nov 2018 12:36:55 +0530
Subject: [PATCH 516/529] geo-rep: Fix permissions with non-root setup
Problem:
In non-root fail-over/fail-back(FO/FB), when slave is
promoted as master, the session goes to 'Faulty'
Cause:
The command 'gluster-mountbroker <mountbroker-root> <group>'
is run as a pre-requisite on slave in non-root setup.
It modifies the permission and group of following required
directories and files recursively
[1] /var/lib/glusterd/geo-replication
[2] /var/log/glusterfs/geo-replication-slaves
In a normal setup, this is executed on slave node and hence
doing it recursively is not an issue on [1]. But when original
master becomes slave in non-root during FO/FB, it contains
ssh public keys and modifying permissions on them causes
geo-rep to fail with incorrect permissions.
Fix:
Don't do permission change recursively. Fix permissions for
required files.
Backport of:
> Patch: https://review.gluster.org/#/c/glusterfs/+/21689/
> BUG: bz#1651498
> Change-Id: I68a744644842e3b00abc26c95c06f123aa78361d
> Signed-off-by: Kotresh HR <khiremat@redhat.com>
BUG: 1510752
Change-Id: I68a744644842e3b00abc26c95c06f123aa78361d
Signed-off-by: Kotresh HR <khiremat@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162463
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
geo-replication/src/peer_mountbroker.py.in | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/geo-replication/src/peer_mountbroker.py.in b/geo-replication/src/peer_mountbroker.py.in
index be182c5..5be16a2 100644
--- a/geo-replication/src/peer_mountbroker.py.in
+++ b/geo-replication/src/peer_mountbroker.py.in
@@ -8,6 +8,7 @@ from gluster.cliutils import (execute, Cmd, node_output_ok,
from prettytable import PrettyTable
LOG_DIR = "@localstatedir@/log/glusterfs/geo-replication-slaves"
+CLI_LOG = "@localstatedir@/log/glusterfs/cli.log"
GEOREP_DIR = "@GLUSTERD_WORKDIR@/geo-replication"
GLUSTERD_VOLFILE = "@GLUSTERD_VOLFILE@"
@@ -142,7 +143,7 @@ class NodeSetup(Cmd):
# chgrp -R <grp> /var/log/glusterfs/geo-replication-slaves
# chgrp -R <grp> /var/lib/glusterd/geo-replication
# chmod -R 770 /var/log/glusterfs/geo-replication-slaves
- # chmod -R 770 /var/lib/glusterd/geo-replication
+ # chmod 770 /var/lib/glusterd/geo-replication
# mkdir -p <mnt_root>
# chmod 0711 <mnt_root>
# If selinux,
@@ -192,8 +193,13 @@ class NodeSetup(Cmd):
execute(["chgrp", "-R", args.group, GEOREP_DIR])
execute(["chgrp", "-R", args.group, LOG_DIR])
- execute(["chmod", "-R", "770", GEOREP_DIR])
- execute(["chmod", "-R", "770", args.group, LOG_DIR])
+ execute(["chgrp", args.group, CLI_LOG])
+ execute(["chmod", "770", args.group, GEOREP_DIR])
+ execute(["find", LOG_DIR, "-type", "d", "-exec", "chmod", "770", "{}",
+ "+"])
+ execute(["find", LOG_DIR, "-type", "f", "-exec", "chmod", "660", "{}",
+ "+"])
+ execute(["chmod", "660", CLI_LOG])
m.set_mount_root_and_group(args.mount_root, args.group)
m.save()
--
1.8.3.1

View File

@ -0,0 +1,39 @@
From ba30dc0db99f0cd6e83ba5085be43607e4710711 Mon Sep 17 00:00:00 2001
From: Shwetha Acharya <sacharya@gmail.com>
Date: Wed, 21 Nov 2018 12:24:00 +0530
Subject: [PATCH 517/529] geo-rep: validate the config checkpoint date format
Added a strlen check to ensure that the format is (Y-m-d H:M:S).
>Change-Id: I8844aaa33418d43ffe2320c4a05eb1eddd306903
>updates: bz#1651584
>Signed-off-by: Shwetha Acharya <sacharya@gmail.com>
backport of https://review.gluster.org/#/c/glusterfs/+/21692/
BUG: 1429190
Change-Id: I70d56925abfffb02d2d4b7d6f570b2c063a8d9c2
Signed-off-by: Shwetha K Acharya <sacharya@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162467
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
cli/src/cli-cmd-parser.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index dcce9d3..a450797 100644
--- a/cli/src/cli-cmd-parser.c
+++ b/cli/src/cli-cmd-parser.c
@@ -2774,7 +2774,7 @@ config_parse (const char **words, int wordcount, dict_t *dict,
ret_chkpt = strptime(append_str, "%Y-%m-%d %H:%M:%S",
&checkpoint_time);
- if (ret_chkpt == NULL) {
+ if (ret_chkpt == NULL || *ret_chkpt != '\0') {
ret = -1;
cli_err ("Invalid Checkpoint label. Use format "
"\"Y-m-d H:M:S\", Example: 2016-10-25 15:30:45");
--
1.8.3.1

View File

@ -0,0 +1,57 @@
From 1e1bda15377a133e9a91e6f99d13e02bf4469269 Mon Sep 17 00:00:00 2001
From: Amar Tumballi <amarts@redhat.com>
Date: Thu, 7 Feb 2019 13:57:21 +0530
Subject: [PATCH 518/529] logging: create parent dir if not available
As glusterfs logging uses different directory than /var/log
(ie, /var/log/glusterfs), there is a chance it may not be
present when starting glusterfs. Create parent dir if it
doesn't exist.
Upstream fix:
>> URL: https://review.gluster.org/21536
BUG: 1570958
Change-Id: I6efaffd1e7e8aee350afcf2ca354b27747ff5e50
Signed-off-by: Amar Tumballi <amarts@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162470
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
libglusterfs/src/logging.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/libglusterfs/src/logging.c b/libglusterfs/src/logging.c
index 0f238d0..631bc98 100644
--- a/libglusterfs/src/logging.c
+++ b/libglusterfs/src/logging.c
@@ -758,6 +758,26 @@ gf_log_init (void *data, const char *file, const char *ident)
goto out;
}
+ /* Also create parent dir */
+ char *logdir = gf_strdup(file);
+ if (!logdir) {
+ return -1;
+ }
+ char *tmp_index = rindex(logdir, '/');
+ if (tmp_index) {
+ tmp_index[0] = '\0';
+ }
+ if (mkdir_p(logdir, 0755, _gf_true)) {
+ /* EEXIST is handled in mkdir_p() itself */
+ gf_msg("logging", GF_LOG_ERROR, 0, LG_MSG_STRDUP_ERROR,
+ "failed to create metrics dir %s (%s)", logdir,
+ strerror(errno));
+ GF_FREE(logdir);
+ return -1;
+ }
+ /* no need of this variable */
+ GF_FREE(logdir);
+
ctx->log.filename = gf_strdup (file);
if (!ctx->log.filename) {
fprintf (stderr, "ERROR: updating log-filename failed: %s\n",
--
1.8.3.1

View File

@ -0,0 +1,118 @@
From a902a17263648180bba8a0167a221e549ba5186a Mon Sep 17 00:00:00 2001
From: N Balachandran <nbalacha@redhat.com>
Date: Wed, 6 Feb 2019 10:26:42 +0530
Subject: [PATCH 519/529] cluster/dht: Delete invalid linkto files in rmdir
rm -rf <dir> fails on dirs which contain linkto files
that point to themselves because dht incorrectly thought
that they were cached files after looking them up.
The fix now treats them as invalid linkto files
and deletes them.
upstream master: https://review.gluster.org/#/c/glusterfs/+/22066/
> Change-Id: I376c72a5309714ee339c74485e02cfb4e29be643
> fixes: bz#1667804
> Signed-off-by: N Balachandran <nbalacha@redhat.com>
Change-Id: Ib759907131f791e5853b2e0cb38a68d94a3efd81
BUG: 1668989
Signed-off-by: N Balachandran <nbalacha@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162342
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
tests/bugs/distribute/bug-1667804.t | 63 ++++++++++++++++++++++++++++++++++++
xlators/cluster/dht/src/dht-common.c | 6 ++--
2 files changed, 67 insertions(+), 2 deletions(-)
create mode 100644 tests/bugs/distribute/bug-1667804.t
diff --git a/tests/bugs/distribute/bug-1667804.t b/tests/bugs/distribute/bug-1667804.t
new file mode 100644
index 0000000..3f7c431
--- /dev/null
+++ b/tests/bugs/distribute/bug-1667804.t
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+. $(dirname $0)/../../dht.rc
+
+function confirm_all_linkto_files ()
+{
+ inpath=$1
+ for infile in $inpath/*
+ do
+ echo $infile
+ ret1=$(is_dht_linkfile $infile)
+ if [ "$ret1" -eq 0 ]; then
+ echo "$infile is not a linkto file"
+ echo 0
+ return
+ fi
+ done
+ echo 1
+}
+
+cleanup;
+
+#Basic checks
+TEST glusterd
+TEST pidof glusterd
+TEST $CLI volume info
+
+#Create a distributed volume
+TEST $CLI volume create $V0 $H0:$B0/${V0}{1..2};
+TEST $CLI volume start $V0
+
+# Mount FUSE
+TEST glusterfs -s $H0 --volfile-id $V0 $M0
+
+#Create files and rename them in order to create linkto files
+TEST mkdir -p $M0/dir0/dir1
+TEST touch $M0/dir0/dir1/file-{1..50}
+
+for i in {1..50}; do
+ mv $M0/dir0/dir1/file-$i $M0/dir0/dir1/nfile-$i;
+done
+
+#Remove the second brick to force the creation of linkto files
+#on the removed brick
+
+TEST $CLI volume remove-brick $V0 $H0:$B0/${V0}2 start
+EXPECT_WITHIN $REBALANCE_TIMEOUT "completed" remove_brick_status_completed_field "$V0 $H0:$B0/${V0}2"
+TEST $CLI volume remove-brick $V0 $H0:$B0/${V0}2 stop
+
+EXPECT "1" confirm_all_linkto_files $B0/${V0}2/dir0/dir1
+
+#Modify the xattrs of the linkto files on the removed brick to point to itself.
+
+target=$(cat $M0/.meta/graphs/active/$V0-dht/subvolumes/1/name)
+
+setfattr -n trusted.glusterfs.dht.linkto -v "$target\0" $B0/${V0}2/dir0/dir1/nfile*
+
+
+TEST rm -rf $M0/dir0
+
+cleanup;
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
index 767c6a8..1311a8d 100644
--- a/xlators/cluster/dht/src/dht-common.c
+++ b/xlators/cluster/dht/src/dht-common.c
@@ -10062,8 +10062,10 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this,
subvol = dht_linkfile_subvol (this, NULL, &trav->d_stat,
trav->dict);
- if (!subvol) {
-
+ if (!subvol || (subvol == src)) {
+ /* we need to delete the linkto file if it does not
+ * have a valid subvol or it points to itself.
+ */
gf_msg (this->name, GF_LOG_INFO, 0,
DHT_MSG_INVALID_LINKFILE,
"Linkfile does not have link subvolume. "
--
1.8.3.1

View File

@ -0,0 +1,205 @@
From f807b5dd999808a8e56061690da01420d3cb4cc5 Mon Sep 17 00:00:00 2001
From: Milind Changire <mchangir@redhat.com>
Date: Sat, 9 Feb 2019 14:01:28 +0530
Subject: [PATCH 520/529] spec: avoid creation of temp file in lua script
Avoiding creation of temporary file to execute bash shell script from a
lua scriptlet increases install time security.
Label: DOWNSTREAM ONLY
BUG: 1410145
Change-Id: Ie5b9035f292402b18dea768aca8bc82a1e7fa615
Signed-off-by: Milind Changire <mchangir@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162621
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
glusterfs.spec.in | 87 ++++++++++---------------------------------------------
1 file changed, 15 insertions(+), 72 deletions(-)
diff --git a/glusterfs.spec.in b/glusterfs.spec.in
index 0ad4ffc..2680bec 100644
--- a/glusterfs.spec.in
+++ b/glusterfs.spec.in
@@ -1643,12 +1643,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
-tmpname = os.tmpname()
-tmpfile = io.open(tmpname, "w")
-tmpfile:write(script)
-tmpfile:close()
-ok, how, val = os.execute("/bin/bash " .. tmpname)
-os.remove(tmpname)
+ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@@ -1685,12 +1680,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
-tmpname = os.tmpname()
-tmpfile = io.open(tmpname, "w")
-tmpfile:write(script)
-tmpfile:close()
-ok, how, val = os.execute("/bin/bash " .. tmpname)
-os.remove(tmpname)
+ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@@ -1727,12 +1717,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
-tmpname = os.tmpname()
-tmpfile = io.open(tmpname, "w")
-tmpfile:write(script)
-tmpfile:close()
-ok, how, val = os.execute("/bin/bash " .. tmpname)
-os.remove(tmpname)
+ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@@ -1769,12 +1754,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
-tmpname = os.tmpname()
-tmpfile = io.open(tmpname, "w")
-tmpfile:write(script)
-tmpfile:close()
-ok, how, val = os.execute("/bin/bash " .. tmpname)
-os.remove(tmpname)
+ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@@ -1811,12 +1791,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
-tmpname = os.tmpname()
-tmpfile = io.open(tmpname, "w")
-tmpfile:write(script)
-tmpfile:close()
-ok, how, val = os.execute("/bin/bash " .. tmpname)
-os.remove(tmpname)
+ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@@ -1853,12 +1828,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
-tmpname = os.tmpname()
-tmpfile = io.open(tmpname, "w")
-tmpfile:write(script)
-tmpfile:close()
-ok, how, val = os.execute("/bin/bash " .. tmpname)
-os.remove(tmpname)
+ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@@ -1895,12 +1865,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
-tmpname = os.tmpname()
-tmpfile = io.open(tmpname, "w")
-tmpfile:write(script)
-tmpfile:close()
-ok, how, val = os.execute("/bin/bash " .. tmpname)
-os.remove(tmpname)
+ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@@ -1938,12 +1903,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
-tmpname = os.tmpname()
-tmpfile = io.open(tmpname, "w")
-tmpfile:write(script)
-tmpfile:close()
-ok, how, val = os.execute("/bin/bash " .. tmpname)
-os.remove(tmpname)
+ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@@ -1981,12 +1941,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
-tmpname = os.tmpname()
-tmpfile = io.open(tmpname, "w")
-tmpfile:write(script)
-tmpfile:close()
-ok, how, val = os.execute("/bin/bash " .. tmpname)
-os.remove(tmpname)
+ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@@ -2024,12 +1979,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
-tmpname = os.tmpname()
-tmpfile = io.open(tmpname, "w")
-tmpfile:write(script)
-tmpfile:close()
-ok, how, val = os.execute("/bin/bash " .. tmpname)
-os.remove(tmpname)
+ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@@ -2068,12 +2018,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
-tmpname = os.tmpname()
-tmpfile = io.open(tmpname, "w")
-tmpfile:write(script)
-tmpfile:close()
-ok, how, val = os.execute("/bin/bash " .. tmpname)
-os.remove(tmpname)
+ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@@ -2111,12 +2056,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
-tmpname = os.tmpname()
-tmpfile = io.open(tmpname, "w")
-tmpfile:write(script)
-tmpfile:close()
-ok, how, val = os.execute("/bin/bash " .. tmpname)
-os.remove(tmpname)
+ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@@ -2173,6 +2113,9 @@ fi
%endif
%changelog
+* Sat Feb 09 2019 Milind Changire <mchangir@redhat.com>
+- Avoid creation of temporary file in lua script during install (#1410145)
+
* Wed Dec 19 2018 Milind Changire <mchangir@redhat.com>
- Add explicit package dependencies (#1656357)
- Remove absolute paths from spec file (#1350745)
--
1.8.3.1

View File

@ -0,0 +1,276 @@
From ae01f8acacf8e51b6c3486e3349497bb4e982866 Mon Sep 17 00:00:00 2001
From: Milind Changire <mchangir@redhat.com>
Date: Sat, 9 Feb 2019 13:38:40 +0530
Subject: [PATCH 521/529] rpc: use address-family option from vol file
This patch helps enable IPv6 connections in the cluster.
The default address-family is IPv4 without using this option explicitly.
When address-family is set to "inet6" in the /etc/glusterfs/glusterd.vol
file, the mount command-line also needs to have
-o xlator-option="transport.address-family=inet6" added to it.
This option also gets added to the brick command-line.
Snapshot and gfapi use-cases should also use this option to pass in the
inet6 address-family.
mainline:
> Change-Id: I97db91021af27bacb6d7578e33ea4817f66d7270
> fixes: bz#1635863
> Signed-off-by: Milind Changire <mchangir@redhat.com>
> Reviewed-on: https://review.gluster.org/c/glusterfs/+/21948
Change-Id: I97db91021af27bacb6d7578e33ea4817f66d7270
BUG: 1618669
Signed-off-by: Milind Changire <mchangir@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162620
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Amar Tumballi Suryanarayan <amarts@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
api/src/glfs-mgmt.c | 12 +++++++++---
glusterfsd/src/glusterfsd-mgmt.c | 6 +++++-
libglusterfs/src/common-utils.c | 18 ++++++++++++++++--
libglusterfs/src/common-utils.h | 3 +++
rpc/rpc-lib/src/rpc-transport.c | 6 +++---
rpc/rpc-lib/src/rpc-transport.h | 2 +-
.../snapview-server/src/snapview-server-mgmt.c | 5 ++++-
xlators/mgmt/glusterd/src/glusterd-handler.c | 11 ++++++++---
xlators/mgmt/glusterd/src/glusterd-utils.c | 7 +++++++
9 files changed, 56 insertions(+), 14 deletions(-)
diff --git a/api/src/glfs-mgmt.c b/api/src/glfs-mgmt.c
index b70dc35..f1281bb 100644
--- a/api/src/glfs-mgmt.c
+++ b/api/src/glfs-mgmt.c
@@ -646,8 +646,10 @@ glfs_mgmt_getspec_cbk (struct rpc_req *req, struct iovec *iov, int count,
* volfile if topology hasn't changed.
* glusterfs_volfile_reconfigure returns 3 possible return states
* return 0 =======> reconfiguration of options has succeeded
- * return 1 =======> the graph has to be reconstructed and all the xlators should be inited
- * return -1(or -ve) =======> Some Internal Error occurred during the operation
+ * return 1 =======> the graph has to be reconstructed and all the
+ * xlators should be inited
+ * return -1(or -ve) =======> Some Internal Error occurred during the
+ * operation
*/
ret = gf_volfile_reconfigure (fs->oldvollen, tmpfp, fs->ctx,
@@ -988,7 +990,11 @@ glfs_mgmt_init (struct glfs *fs)
!strcmp (cmd_args->volfile_server_transport, "unix")) {
ret = rpc_transport_unix_options_build (&options, host, 0);
} else {
- ret = rpc_transport_inet_options_build (&options, host, port);
+ xlator_cmdline_option_t *opt =
+ find_xlator_option_in_cmd_args_t("address-family",
+ cmd_args);
+ ret = rpc_transport_inet_options_build(&options, host, port,
+ (opt ? opt->value : NULL));
}
if (ret)
diff --git a/glusterfsd/src/glusterfsd-mgmt.c b/glusterfsd/src/glusterfsd-mgmt.c
index b952526..e38ad64 100644
--- a/glusterfsd/src/glusterfsd-mgmt.c
+++ b/glusterfsd/src/glusterfsd-mgmt.c
@@ -2552,6 +2552,7 @@ glusterfs_mgmt_init (glusterfs_ctx_t *ctx)
int ret = -1;
int port = GF_DEFAULT_BASE_PORT;
char *host = NULL;
+ xlator_cmdline_option_t *opt = NULL;
cmd_args = &ctx->cmd_args;
GF_VALIDATE_OR_GOTO (THIS->name, cmd_args->volfile_server, out);
@@ -2570,7 +2571,10 @@ glusterfs_mgmt_init (glusterfs_ctx_t *ctx)
!strcmp (cmd_args->volfile_server_transport, "unix")) {
ret = rpc_transport_unix_options_build (&options, host, 0);
} else {
- ret = rpc_transport_inet_options_build (&options, host, port);
+ opt = find_xlator_option_in_cmd_args_t("address-family",
+ cmd_args);
+ ret = rpc_transport_inet_options_build(&options, host, port,
+ (opt ? opt->value : NULL));
}
if (ret)
goto out;
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c
index 1243754..e3f3989 100644
--- a/libglusterfs/src/common-utils.c
+++ b/libglusterfs/src/common-utils.c
@@ -477,8 +477,9 @@ gf_resolve_ip6 (const char *hostname,
}
if ((ret = getaddrinfo(hostname, port_str, &hints, &cache->first)) != 0) {
gf_msg ("resolver", GF_LOG_ERROR, 0,
- LG_MSG_GETADDRINFO_FAILED, "getaddrinfo failed"
- " (%s)", gai_strerror (ret));
+ LG_MSG_GETADDRINFO_FAILED,
+ "getaddrinfo failed (family:%d) (%s)", family,
+ gai_strerror (ret));
GF_FREE (*dnscache);
*dnscache = NULL;
@@ -5136,3 +5137,16 @@ out:
return NULL;
}
+xlator_cmdline_option_t *
+find_xlator_option_in_cmd_args_t(const char *option_name, cmd_args_t *args)
+{
+ xlator_cmdline_option_t *pos = NULL;
+ xlator_cmdline_option_t *tmp = NULL;
+
+ list_for_each_entry_safe(pos, tmp, &args->xlator_options, cmd_args)
+ {
+ if (strcmp(pos->key, option_name) == 0)
+ return pos;
+ }
+ return NULL;
+}
diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h
index 50c1f9a..15a31a3 100644
--- a/libglusterfs/src/common-utils.h
+++ b/libglusterfs/src/common-utils.h
@@ -945,4 +945,7 @@ glusterfs_compute_sha256 (const unsigned char *content, size_t size,
char*
get_struct_variable (int mem_num, gf_gsync_status_t *sts_val);
+xlator_cmdline_option_t *
+find_xlator_option_in_cmd_args_t(const char *option_name, cmd_args_t *args);
+
#endif /* _COMMON_UTILS_H */
diff --git a/rpc/rpc-lib/src/rpc-transport.c b/rpc/rpc-lib/src/rpc-transport.c
index 0c6ab66..b737ff2 100644
--- a/rpc/rpc-lib/src/rpc-transport.c
+++ b/rpc/rpc-lib/src/rpc-transport.c
@@ -666,7 +666,7 @@ out:
int
rpc_transport_inet_options_build (dict_t **options, const char *hostname,
- int port)
+ int port, char *af)
{
dict_t *dict = NULL;
char *host = NULL;
@@ -702,10 +702,10 @@ rpc_transport_inet_options_build (dict_t **options, const char *hostname,
goto out;
}
- ret = dict_set_str (dict, "address-family", addr_family);
+ ret = dict_set_str (dict, "address-family", (af != NULL ? af : addr_family));
if (ret) {
gf_log (THIS->name, GF_LOG_WARNING,
- "failed to set address-family to %s", addr_family);
+ "failed to set address-family to %s", (af != NULL ? af : addr_family));
goto out;
}
diff --git a/rpc/rpc-lib/src/rpc-transport.h b/rpc/rpc-lib/src/rpc-transport.h
index f5fb6e1..c97f98d 100644
--- a/rpc/rpc-lib/src/rpc-transport.h
+++ b/rpc/rpc-lib/src/rpc-transport.h
@@ -316,7 +316,7 @@ rpc_transport_unix_options_build (dict_t **options, char *filepath,
int frame_timeout);
int
-rpc_transport_inet_options_build (dict_t **options, const char *hostname, int port);
+rpc_transport_inet_options_build (dict_t **options, const char *hostname, int port, char *af);
void
rpc_transport_cleanup(rpc_transport_t *);
diff --git a/xlators/features/snapview-server/src/snapview-server-mgmt.c b/xlators/features/snapview-server/src/snapview-server-mgmt.c
index 18c902d..f82c8a0 100644
--- a/xlators/features/snapview-server/src/snapview-server-mgmt.c
+++ b/xlators/features/snapview-server/src/snapview-server-mgmt.c
@@ -84,6 +84,7 @@ svs_mgmt_init (xlator_t *this)
char *host = NULL;
cmd_args_t *cmd_args = NULL;
glusterfs_ctx_t *ctx = NULL;
+ xlator_cmdline_option_t *opt = NULL;
GF_VALIDATE_OR_GOTO ("snapview-server", this, out);
GF_VALIDATE_OR_GOTO (this->name, this->private, out);
@@ -98,7 +99,9 @@ svs_mgmt_init (xlator_t *this)
if (cmd_args->volfile_server)
host = cmd_args->volfile_server;
- ret = rpc_transport_inet_options_build (&options, host, port);
+ opt = find_xlator_option_in_cmd_args_t("address-family", cmd_args);
+ ret = rpc_transport_inet_options_build(&options, host, port,
+ (opt != NULL ? opt->value : NULL));
if (ret) {
gf_log (this->name, GF_LOG_ERROR, "failed to build the "
"transport options");
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c
index 81b1c02..e92cb5f 100644
--- a/xlators/mgmt/glusterd/src/glusterd-handler.c
+++ b/xlators/mgmt/glusterd/src/glusterd-handler.c
@@ -3440,7 +3440,7 @@ out:
int
glusterd_transport_inet_options_build (dict_t **options, const char *hostname,
- int port)
+ int port, char *af)
{
xlator_t *this = NULL;
dict_t *dict = NULL;
@@ -3458,7 +3458,7 @@ glusterd_transport_inet_options_build (dict_t **options, const char *hostname,
port = GLUSTERD_DEFAULT_PORT;
/* Build default transport options */
- ret = rpc_transport_inet_options_build (&dict, hostname, port);
+ ret = rpc_transport_inet_options_build (&dict, hostname, port, af);
if (ret)
goto out;
@@ -3518,6 +3518,7 @@ glusterd_friend_rpc_create (xlator_t *this, glusterd_peerinfo_t *peerinfo,
int ret = -1;
glusterd_peerctx_t *peerctx = NULL;
data_t *data = NULL;
+ char *af = NULL;
peerctx = GF_CALLOC (1, sizeof (*peerctx), gf_gld_mt_peerctx_t);
if (!peerctx)
@@ -3532,10 +3533,14 @@ glusterd_friend_rpc_create (xlator_t *this, glusterd_peerinfo_t *peerinfo,
number can be used to
uniquely identify a
peerinfo */
+ ret = dict_get_str(this->options, "transport.address-family", &af);
+ if (ret)
+ gf_log(this->name, GF_LOG_TRACE,
+ "option transport.address-family is not set in xlator options");
ret = glusterd_transport_inet_options_build (&options,
peerinfo->hostname,
- peerinfo->port);
+ peerinfo->port, af);
if (ret)
goto out;
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
index bafc3af..50758ca 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -1975,6 +1975,7 @@ glusterd_volume_start_glusterfs (glusterd_volinfo_t *volinfo,
rpc_clnt_connection_t *conn = NULL;
int pid = -1;
glusterd_brick_proc_t *brick_proc = NULL;
+ char *inet_family = NULL;
GF_ASSERT (volinfo);
GF_ASSERT (brickinfo);
@@ -2140,6 +2141,12 @@ retry:
runner_argprintf (&runner,
"--volfile-server-transport=socket,rdma");
+ ret = dict_get_str(this->options, "transport.address-family", &inet_family);
+ if (!ret) {
+ runner_add_arg(&runner, "--xlator-option");
+ runner_argprintf(&runner, "transport.address-family=%s", inet_family);
+ }
+
if (volinfo->memory_accounting)
runner_add_arg (&runner, "--mem-accounting");
--
1.8.3.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,225 @@
From 60bd1dcd283b2d464968092711b658c12a900918 Mon Sep 17 00:00:00 2001
From: Raghavendra Gowdappa <rgowdapp@redhat.com>
Date: Mon, 11 Feb 2019 16:42:48 +0530
Subject: [PATCH 523/529] libglusterfs: rename macros roof and floor to not
conflict with math.h
mainline:
> Change-Id: I666eeb63ebd000711b3f793b948d4e0c04b1a242
> Signed-off-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
> Updates: bz#1644629
> Reviewed-on: https://review.gluster.org/c/glusterfs/+/21703
Change-Id: I666eeb63ebd000711b3f793b948d4e0c04b1a242
BUG: 1390151
Signed-off-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162678
Tested-by: RHGS Build Bot <nigelb@redhat.com>
---
libglusterfs/src/common-utils.h | 4 ++--
rpc/rpc-transport/socket/src/socket.c | 2 +-
xlators/cluster/stripe/src/stripe.c | 18 +++++++++---------
xlators/performance/io-cache/src/io-cache.c | 4 ++--
xlators/performance/io-cache/src/page.c | 4 ++--
xlators/performance/read-ahead/src/page.c | 4 ++--
xlators/performance/read-ahead/src/read-ahead.c | 8 ++++----
xlators/protocol/server/src/server-rpc-fops.c | 2 +-
8 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h
index 15a31a3..af2e0fd 100644
--- a/libglusterfs/src/common-utils.h
+++ b/libglusterfs/src/common-utils.h
@@ -53,8 +53,8 @@ void trap (void);
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
-#define roof(a,b) ((((a)+(b)-1)/((b)?(b):1))*(b))
-#define floor(a,b) (((a)/((b)?(b):1))*(b))
+#define gf_roof(a, b) ((((a) + (b) - 1)/((b) ? (b) : 1)) * (b))
+#define gf_floor(a, b) (((a) / ((b) ? (b) : 1)) * (b))
#define IPv4_ADDR_SIZE 32
diff --git a/rpc/rpc-transport/socket/src/socket.c b/rpc/rpc-transport/socket/src/socket.c
index 34a937f..e28c5cd 100644
--- a/rpc/rpc-transport/socket/src/socket.c
+++ b/rpc/rpc-transport/socket/src/socket.c
@@ -1646,7 +1646,7 @@ __socket_read_accepted_successful_reply (rpc_transport_t *this)
/* need to round off to proper roof (%4), as XDR packing pads
the end of opaque object with '0' */
- size = roof (read_rsp.xdata.xdata_len, 4);
+ size = gf_roof (read_rsp.xdata.xdata_len, 4);
if (!size) {
frag->call_body.reply.accepted_success_state
diff --git a/xlators/cluster/stripe/src/stripe.c b/xlators/cluster/stripe/src/stripe.c
index 6b32f7f..fc809a0 100644
--- a/xlators/cluster/stripe/src/stripe.c
+++ b/xlators/cluster/stripe/src/stripe.c
@@ -698,10 +698,10 @@ stripe_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset,
* to the size of the previous stripe.
*/
if (i < eof_idx)
- tmp_offset = roof(offset, fctx->stripe_size *
+ tmp_offset = gf_roof(offset, fctx->stripe_size *
fctx->stripe_count);
else if (i > eof_idx)
- tmp_offset = floor(offset, fctx->stripe_size *
+ tmp_offset = gf_floor(offset, fctx->stripe_size *
fctx->stripe_count);
else
tmp_offset = offset;
@@ -3067,10 +3067,10 @@ stripe_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, d
if (fctx->stripe_coalesce) {
if (i < eof_idx)
- tmp_offset = roof(offset, fctx->stripe_size *
+ tmp_offset = gf_roof(offset, fctx->stripe_size *
fctx->stripe_count);
else if (i > eof_idx)
- tmp_offset = floor(offset, fctx->stripe_size *
+ tmp_offset = gf_floor(offset, fctx->stripe_size *
fctx->stripe_count);
else
tmp_offset = offset;
@@ -3476,8 +3476,8 @@ stripe_readv (call_frame_t *frame, xlator_t *this, fd_t *fd,
* the file is in which child node. Always '0-<stripe_size>' part of
* the file resides in the first child.
*/
- rounded_start = floor (offset, stripe_size);
- rounded_end = roof (offset+size, stripe_size);
+ rounded_start = gf_floor (offset, stripe_size);
+ rounded_end = gf_roof (offset+size, stripe_size);
num_stripe = (rounded_end- rounded_start)/stripe_size;
local = mem_get0 (this->local_pool);
@@ -3510,7 +3510,7 @@ stripe_readv (call_frame_t *frame, xlator_t *this, fd_t *fd,
goto err;
}
- frame_size = min (roof (frame_offset+1, stripe_size),
+ frame_size = min (gf_roof (frame_offset+1, stripe_size),
(offset + size)) - frame_offset;
rlocal->node_index = index - off_index;
@@ -3693,8 +3693,8 @@ stripe_writev (call_frame_t *frame, xlator_t *this, fd_t *fd,
goto err;
}
- rounded_start = floor(offset, stripe_size);
- rounded_end = roof(offset + total_size, stripe_size);
+ rounded_start = gf_floor(offset, stripe_size);
+ rounded_end = gf_roof(offset + total_size, stripe_size);
total_chunks = (rounded_end - rounded_start) / stripe_size;
local->replies = GF_CALLOC(total_chunks, sizeof(struct stripe_replies),
gf_stripe_mt_stripe_replies);
diff --git a/xlators/performance/io-cache/src/io-cache.c b/xlators/performance/io-cache/src/io-cache.c
index d7b3b37..5ef77b0 100644
--- a/xlators/performance/io-cache/src/io-cache.c
+++ b/xlators/performance/io-cache/src/io-cache.c
@@ -953,8 +953,8 @@ ioc_dispatch_requests (call_frame_t *frame, ioc_inode_t *ioc_inode, fd_t *fd,
local = frame->local;
table = ioc_inode->table;
- rounded_offset = floor (offset, table->page_size);
- rounded_end = roof (offset + size, table->page_size);
+ rounded_offset = gf_floor (offset, table->page_size);
+ rounded_end = gf_roof (offset + size, table->page_size);
trav_offset = rounded_offset;
/* once a frame does read, it should be waiting on something */
diff --git a/xlators/performance/io-cache/src/page.c b/xlators/performance/io-cache/src/page.c
index 50f5e19..832c4ee 100644
--- a/xlators/performance/io-cache/src/page.c
+++ b/xlators/performance/io-cache/src/page.c
@@ -43,7 +43,7 @@ __ioc_page_get (ioc_inode_t *ioc_inode, off_t offset)
table = ioc_inode->table;
GF_VALIDATE_OR_GOTO ("io-cache", ioc_inode, out);
- rounded_offset = floor (offset, table->page_size);
+ rounded_offset = gf_floor (offset, table->page_size);
page = rbthash_get (ioc_inode->cache.page_table, &rounded_offset,
sizeof (rounded_offset));
@@ -256,7 +256,7 @@ __ioc_page_create (ioc_inode_t *ioc_inode, off_t offset)
table = ioc_inode->table;
GF_VALIDATE_OR_GOTO ("io-cache", table, out);
- rounded_offset = floor (offset, table->page_size);
+ rounded_offset = gf_floor (offset, table->page_size);
newpage = GF_CALLOC (1, sizeof (*newpage), gf_ioc_mt_ioc_newpage_t);
if (newpage == NULL) {
diff --git a/xlators/performance/read-ahead/src/page.c b/xlators/performance/read-ahead/src/page.c
index 17e346e..8a5ce58 100644
--- a/xlators/performance/read-ahead/src/page.c
+++ b/xlators/performance/read-ahead/src/page.c
@@ -25,7 +25,7 @@ ra_page_get (ra_file_t *file, off_t offset)
GF_VALIDATE_OR_GOTO ("read-ahead", file, out);
page = file->pages.next;
- rounded_offset = floor (offset, file->page_size);
+ rounded_offset = gf_floor (offset, file->page_size);
while (page != &file->pages && page->offset < rounded_offset)
page = page->next;
@@ -48,7 +48,7 @@ ra_page_create (ra_file_t *file, off_t offset)
GF_VALIDATE_OR_GOTO ("read-ahead", file, out);
page = file->pages.next;
- rounded_offset = floor (offset, file->page_size);
+ rounded_offset = gf_floor (offset, file->page_size);
while (page != &file->pages && page->offset < rounded_offset)
page = page->next;
diff --git a/xlators/performance/read-ahead/src/read-ahead.c b/xlators/performance/read-ahead/src/read-ahead.c
index e02ca9f..8adbd53 100644
--- a/xlators/performance/read-ahead/src/read-ahead.c
+++ b/xlators/performance/read-ahead/src/read-ahead.c
@@ -283,7 +283,7 @@ read_ahead (call_frame_t *frame, ra_file_t *file)
}
ra_size = file->page_size * file->page_count;
- ra_offset = floor (file->offset, file->page_size);
+ ra_offset = gf_floor (file->offset, file->page_size);
cap = file->size ? file->size : file->offset + ra_size;
while (ra_offset < min (file->offset + ra_size, cap)) {
@@ -372,8 +372,8 @@ dispatch_requests (call_frame_t *frame, ra_file_t *file)
local = frame->local;
conf = file->conf;
- rounded_offset = floor (local->offset, file->page_size);
- rounded_end = roof (local->offset + local->size, file->page_size);
+ rounded_offset = gf_floor (local->offset, file->page_size);
+ rounded_end = gf_roof (local->offset + local->size, file->page_size);
trav_offset = rounded_offset;
@@ -532,7 +532,7 @@ ra_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
dispatch_requests (frame, file);
- flush_region (frame, file, 0, floor (offset, file->page_size), 0);
+ flush_region (frame, file, 0, gf_floor (offset, file->page_size), 0);
read_ahead (frame, file);
diff --git a/xlators/protocol/server/src/server-rpc-fops.c b/xlators/protocol/server/src/server-rpc-fops.c
index 35d0887..b7bb26a 100644
--- a/xlators/protocol/server/src/server-rpc-fops.c
+++ b/xlators/protocol/server/src/server-rpc-fops.c
@@ -4123,7 +4123,7 @@ server3_3_writev_vecsizer (int state, ssize_t *readsize, char *base_addr,
/* need to round off to proper roof (%4), as XDR packing pads
the end of opaque object with '0' */
- size = roof (write_req.xdata.xdata_len, 4);
+ size = gf_roof (write_req.xdata.xdata_len, 4);
*readsize = size;
--
1.8.3.1

View File

@ -0,0 +1,266 @@
From 3de9cc04cdf5a65825cc86c8239734a284775470 Mon Sep 17 00:00:00 2001
From: Raghavendra G <rgowdapp@redhat.com>
Date: Wed, 6 Feb 2019 17:30:30 +0530
Subject: [PATCH 524/529] program/GF-DUMP: Shield ping processing from traffic
to Glusterfs Program
Since poller thread bears the brunt of execution till the request is
handed over to io-threads, poller thread experiencies lock
contention(s) in the control flow till io-threads, which slows it
down. This delay invariably affects reading ping requests from network
and responding to them, resulting in increased ping latencies, which
sometimes results in a ping-timer-expiry on client leading to
disconnect of transport. So, this patch aims to free up poller thread
from executing code of Glusterfs Program. We do this by making
* Glusterfs Program registering itself asking rpcsvc to execute its
actors in its own threads.
* GF-DUMP Program registering itself asking rpcsvc to _NOT_ execute
its actors in its own threads. Otherwise program's ownthreads become
bottleneck in processing ping traffic. This means that poller thread
reads a ping packet, invokes its actor and hands the response msg to
transport queue.
Change-Id: I526268c10bdd5ef93f322a4f95385137550a6a49
Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
BUG: 1390151
Reviewed-on: https://review.gluster.org/17105
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
Smoke: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: Amar Tumballi <amarts@redhat.com>
Reviewed-by: Jeff Darcy <jeff@pl.atyp.us>
(cherry picked from commit 2e72b24707f1886833db0b09e48b3f48b8d68d37)
Reviewed-on: https://code.engineering.redhat.com/gerrit/162426
Tested-by: RHGS Build Bot <nigelb@redhat.com>
---
rpc/rpc-lib/src/rpcsvc.c | 90 ++++++++++++++++++++++++++-
rpc/rpc-lib/src/rpcsvc.h | 18 +++++-
xlators/protocol/server/src/server-helpers.c | 4 --
xlators/protocol/server/src/server-rpc-fops.c | 1 +
4 files changed, 106 insertions(+), 7 deletions(-)
diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c
index 695e9fb..faa1956 100644
--- a/rpc/rpc-lib/src/rpcsvc.c
+++ b/rpc/rpc-lib/src/rpcsvc.c
@@ -304,6 +304,7 @@ rpcsvc_program_actor (rpcsvc_request_t *req)
goto err;
}
+ req->ownthread = program->ownthread;
req->synctask = program->synctask;
err = SUCCESS;
@@ -411,6 +412,7 @@ rpcsvc_request_init (rpcsvc_t *svc, rpc_transport_t *trans,
req->progver = rpc_call_progver (callmsg);
req->procnum = rpc_call_progproc (callmsg);
req->trans = rpc_transport_ref (trans);
+ gf_client_ref (req->trans->xl_private);
req->count = msg->count;
req->msg[0] = progmsg;
req->iobref = iobref_ref (msg->iobref);
@@ -426,6 +428,7 @@ rpcsvc_request_init (rpcsvc_t *svc, rpc_transport_t *trans,
req->trans_private = msg->private;
INIT_LIST_HEAD (&req->txlist);
+ INIT_LIST_HEAD (&req->request_list);
req->payloadsize = 0;
/* By this time, the data bytes for the auth scheme would have already
@@ -576,7 +579,7 @@ rpcsvc_handle_rpc_call (rpcsvc_t *svc, rpc_transport_t *trans,
rpcsvc_request_t *req = NULL;
int ret = -1;
uint16_t port = 0;
- gf_boolean_t is_unix = _gf_false;
+ gf_boolean_t is_unix = _gf_false, empty = _gf_false;
gf_boolean_t unprivileged = _gf_false;
drc_cached_op_t *reply = NULL;
rpcsvc_drc_globals_t *drc = NULL;
@@ -692,6 +695,20 @@ rpcsvc_handle_rpc_call (rpcsvc_t *svc, rpc_transport_t *trans,
(synctask_fn_t) actor_fn,
rpcsvc_check_and_reply_error, NULL,
req);
+ } else if (req->ownthread) {
+ pthread_mutex_lock (&req->prog->queue_lock);
+ {
+ empty = list_empty (&req->prog->request_queue);
+
+ list_add_tail (&req->request_list,
+ &req->prog->request_queue);
+
+ if (empty)
+ pthread_cond_signal (&req->prog->queue_cond);
+ }
+ pthread_mutex_unlock (&req->prog->queue_lock);
+
+ ret = 0;
} else {
ret = actor_fn (req);
}
@@ -1572,6 +1589,12 @@ rpcsvc_program_unregister (rpcsvc_t *svc, rpcsvc_program_t *program)
" Ver: %d, Port: %d", prog->progname, prog->prognum,
prog->progver, prog->progport);
+ if (prog->ownthread) {
+ prog->alive = _gf_false;
+ ret = 0;
+ goto out;
+ }
+
pthread_mutex_lock (&svc->rpclock);
{
list_del_init (&prog->program);
@@ -1838,6 +1861,56 @@ out:
return ret;
}
+void *
+rpcsvc_request_handler (void *arg)
+{
+ rpcsvc_program_t *program = arg;
+ rpcsvc_request_t *req = NULL;
+ rpcsvc_actor_t *actor = NULL;
+ gf_boolean_t done = _gf_false;
+ int ret = 0;
+
+ if (!program)
+ return NULL;
+
+ while (1) {
+ pthread_mutex_lock (&program->queue_lock);
+ {
+ if (!program->alive
+ && list_empty (&program->request_queue)) {
+ done = 1;
+ goto unlock;
+ }
+
+ while (list_empty (&program->request_queue))
+ pthread_cond_wait (&program->queue_cond,
+ &program->queue_lock);
+
+ req = list_entry (program->request_queue.next,
+ typeof (*req), request_list);
+
+ list_del_init (&req->request_list);
+ }
+ unlock:
+ pthread_mutex_unlock (&program->queue_lock);
+
+ if (done)
+ break;
+
+ THIS = req->svc->xl;
+
+ actor = rpcsvc_program_actor (req);
+
+ ret = actor->actor (req);
+
+ if (ret != 0) {
+ rpcsvc_check_and_reply_error (ret, NULL, req);
+ }
+ }
+
+ return NULL;
+}
+
int
rpcsvc_program_register (rpcsvc_t *svc, rpcsvc_program_t *program)
{
@@ -1878,6 +1951,21 @@ rpcsvc_program_register (rpcsvc_t *svc, rpcsvc_program_t *program)
memcpy (newprog, program, sizeof (*program));
INIT_LIST_HEAD (&newprog->program);
+ INIT_LIST_HEAD (&newprog->request_queue);
+ pthread_mutex_init (&newprog->queue_lock, NULL);
+ pthread_cond_init (&newprog->queue_cond, NULL);
+
+ newprog->alive = _gf_true;
+
+ /* make sure synctask gets priority over ownthread */
+ if (newprog->synctask)
+ newprog->ownthread = _gf_false;
+
+ if (newprog->ownthread) {
+ gf_thread_create (&newprog->thread, NULL,
+ rpcsvc_request_handler,
+ newprog, "reqhnd");
+ }
pthread_mutex_lock (&svc->rpclock);
{
diff --git a/rpc/rpc-lib/src/rpcsvc.h b/rpc/rpc-lib/src/rpcsvc.h
index d3aafac..58c0055 100644
--- a/rpc/rpc-lib/src/rpcsvc.h
+++ b/rpc/rpc-lib/src/rpcsvc.h
@@ -233,7 +233,9 @@ struct rpcsvc_request {
*/
rpcsvc_auth_data_t verf;
- /* Execute this request's actor function as a synctask?*/
+ /* Execute this request's actor function in ownthread of program?*/
+ gf_boolean_t ownthread;
+
gf_boolean_t synctask;
/* Container for a RPC program wanting to store a temp
* request-specific item.
@@ -245,6 +247,10 @@ struct rpcsvc_request {
/* pointer to cached reply for use in DRC */
drc_cached_op_t *reply;
+
+ /* request queue in rpcsvc */
+ struct list_head request_list;
+
};
#define rpcsvc_request_program(req) ((rpcsvc_program_t *)((req)->prog))
@@ -395,10 +401,18 @@ struct rpcsvc_program {
*/
int min_auth;
- /* Execute actor function as a synctask? */
+ /* Execute actor function in program's own thread? */
+ /* This will reduce the workload on poller threads */
+ gf_boolean_t ownthread;
+ gf_boolean_t alive;
+
gf_boolean_t synctask;
/* list member to link to list of registered services with rpcsvc */
struct list_head program;
+ struct list_head request_queue;
+ pthread_mutex_t queue_lock;
+ pthread_cond_t queue_cond;
+ pthread_t thread;
};
typedef struct rpcsvc_cbk_program {
diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c
index 30045ef..7cc3d15 100644
--- a/xlators/protocol/server/src/server-helpers.c
+++ b/xlators/protocol/server/src/server-helpers.c
@@ -557,10 +557,6 @@ get_frame_from_request (rpcsvc_request_t *req)
}
}
- /* Add a ref for this fop */
- if (client)
- gf_client_ref (client);
-
frame->root->uid = req->uid;
frame->root->gid = req->gid;
frame->root->pid = req->pid;
diff --git a/xlators/protocol/server/src/server-rpc-fops.c b/xlators/protocol/server/src/server-rpc-fops.c
index b7bb26a..db4242d 100644
--- a/xlators/protocol/server/src/server-rpc-fops.c
+++ b/xlators/protocol/server/src/server-rpc-fops.c
@@ -6143,4 +6143,5 @@ struct rpcsvc_program glusterfs3_3_fop_prog = {
.progver = GLUSTER_FOP_VERSION,
.numactors = GLUSTER_FOP_PROCCNT,
.actors = glusterfs3_3_fop_actors,
+ .ownthread = _gf_true,
};
--
1.8.3.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,671 @@
From 77716a11910ca2b88f37ff549776f7778cc17dae Mon Sep 17 00:00:00 2001
From: Csaba Henk <csaba@redhat.com>
Date: Thu, 9 Aug 2018 11:46:33 +0200
Subject: [PATCH 526/529] fuse: interrupt handling framework
- add sub-framework to send timed responses to kernel
- add interrupt handler queue
- implement INTERRUPT
fuse_interrupt looks up handlers for interrupted messages
in the queue. If found, it invokes the handler function.
Else responds with EAGAIN with a delay.
See spec at
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/fuse.txt?h=v4.17#n148
and explanation in comments.
Upstream: https://review.gluster.org/20686
> Change-Id: I1a79d3679b31f36e14b4ac8f60b7f2c1ea2badfb
> updates: #465
> Signed-off-by: Csaba Henk <csaba@redhat.com>
Change-Id: Idff76920aaa9f87b185dabb0b431a31fcd2a2c77
BUG: 1595246
Signed-off-by: Csaba Henk <csaba@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162549
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Amar Tumballi Suryanarayan <amarts@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
libglusterfs/src/timespec.c | 16 ++
libglusterfs/src/timespec.h | 1 +
xlators/mount/fuse/src/fuse-bridge.c | 464 +++++++++++++++++++++++++++++++-
xlators/mount/fuse/src/fuse-bridge.h | 39 +++
xlators/mount/fuse/src/fuse-mem-types.h | 2 +
5 files changed, 521 insertions(+), 1 deletion(-)
diff --git a/libglusterfs/src/timespec.c b/libglusterfs/src/timespec.c
index 903303d..55f7575 100644
--- a/libglusterfs/src/timespec.c
+++ b/libglusterfs/src/timespec.c
@@ -72,3 +72,19 @@ void timespec_sub (const struct timespec *begin, const struct timespec *end,
res->tv_nsec = end->tv_nsec - begin->tv_nsec;
}
}
+
+int
+timespec_cmp(const struct timespec *lhs_ts, const struct timespec *rhs_ts)
+{
+ if (lhs_ts->tv_sec < rhs_ts->tv_sec) {
+ return -1;
+ } else if (lhs_ts->tv_sec > rhs_ts->tv_sec) {
+ return 1;
+ } else if (lhs_ts->tv_nsec < rhs_ts->tv_nsec) {
+ return -1;
+ } else if (lhs_ts->tv_nsec > rhs_ts->tv_nsec) {
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/libglusterfs/src/timespec.h b/libglusterfs/src/timespec.h
index 9c393ee..aa37951 100644
--- a/libglusterfs/src/timespec.h
+++ b/libglusterfs/src/timespec.h
@@ -23,5 +23,6 @@ void timespec_adjust_delta (struct timespec *ts, struct timespec delta);
void timespec_sub (const struct timespec *begin,
const struct timespec *end,
struct timespec *res);
+int timespec_cmp(const struct timespec *lhs_ts, const struct timespec *rhs_ts);
#endif /* __INCLUDE_TIMESPEC_H__ */
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
index f3188d6..0d4b9db 100644
--- a/xlators/mount/fuse/src/fuse-bridge.c
+++ b/xlators/mount/fuse/src/fuse-bridge.c
@@ -15,6 +15,7 @@
#include "compat-errno.h"
#include "glusterfs-acl.h"
#include "syscall.h"
+#include "timespec.h"
#ifdef __NetBSD__
#undef open /* in perfuse.h, pulled from mount-gluster-compat.h */
@@ -426,6 +427,361 @@ fuse_inode_invalidate_fn(xlator_t *this, inode_t *inode)
}
#endif
+static fuse_timed_message_t *
+fuse_timed_message_new (void)
+{
+ fuse_timed_message_t *dmsg = NULL;
+
+ dmsg = GF_MALLOC (sizeof (*dmsg), gf_fuse_mt_timed_message_t);
+ if (!dmsg) {
+ return NULL;
+ }
+
+ /* should be NULL if not set */
+ dmsg->fuse_message_body = NULL;
+ INIT_LIST_HEAD (&dmsg->next);
+
+ return dmsg;
+}
+
+static void
+fuse_timed_message_free (fuse_timed_message_t *dmsg)
+{
+ GF_FREE (dmsg->fuse_message_body);
+ GF_FREE (dmsg);
+}
+
+static void
+send_fuse_timed (xlator_t *this, fuse_timed_message_t *dmsg)
+{
+ fuse_private_t *priv = NULL;
+
+ priv = this->private;
+
+ if (!priv->timed_response_fuse_thread_started) {
+ return;
+ }
+
+ pthread_mutex_lock (&priv->timed_mutex);
+ {
+ list_add_tail (&dmsg->next, &priv->timed_list);
+ pthread_cond_signal (&priv->timed_cond);
+ }
+ pthread_mutex_unlock (&priv->timed_mutex);
+}
+
+fuse_interrupt_record_t *
+fuse_interrupt_record_new (fuse_in_header_t *finh,
+ fuse_interrupt_handler_t handler)
+{
+ fuse_interrupt_record_t *fir = NULL;
+
+ fir = GF_MALLOC (sizeof (*fir), gf_fuse_mt_interrupt_record_t);
+ if (!fir) {
+ return NULL;
+ }
+
+ fir->hit = _gf_false;
+ fir->interrupt_state = INTERRUPT_NONE;
+ fir->data = NULL;
+
+ fir->interrupt_handler = handler;
+ memcpy (&fir->fuse_in_header, finh, sizeof (*finh));
+ pthread_cond_init (&fir->handler_cond, NULL);
+ pthread_mutex_init (&fir->handler_mutex, NULL);
+ INIT_LIST_HEAD (&fir->next);
+
+ return fir;
+}
+
+static void
+fuse_interrupt_record_free (fuse_interrupt_record_t *fir, void **datap)
+{
+ /*
+ * If caller wishes, we give back the private data to let them deal with it
+ * however they want; otherwise we take care of freeing it.
+ */
+ if (datap) {
+ *datap = fir->data;
+ } else {
+ GF_FREE (fir->data);
+ }
+
+ GF_FREE (fir);
+}
+
+void
+fuse_interrupt_record_insert (xlator_t *this, fuse_interrupt_record_t *fir)
+{
+ fuse_private_t *priv = NULL;
+
+ priv = this->private;
+ pthread_mutex_lock (&priv->interrupt_mutex);
+ {
+ list_add_tail (&fir->next, &priv->interrupt_list);
+ }
+ pthread_mutex_unlock (&priv->interrupt_mutex);
+}
+
+static fuse_interrupt_record_t *
+fuse_interrupt_record_fetch (xlator_t *this, uint64_t unique, gf_boolean_t reap)
+{
+ fuse_interrupt_record_t *fir = NULL;
+ gf_boolean_t found = _gf_false;
+ fuse_private_t *priv = NULL;
+
+ priv = this->private;
+ pthread_mutex_lock (&priv->interrupt_mutex);
+ {
+ list_for_each_entry (fir, &priv->interrupt_list, next)
+ {
+ if (fir->fuse_in_header.unique == unique) {
+ /*
+ * If we are to reap, we do it regardless the
+ * hit flag; otherwise we take the record only
+ * hasn't yet flagged hit.
+ */
+ if (reap || !fir->hit) {
+ found = _gf_true;
+ }
+ /*
+ * If we are not reaping (coming from handler
+ * context), we set the hit flag.
+ */
+ if (!reap) {
+ fir->hit = _gf_true;
+ }
+ break;
+ }
+ }
+ if (found && reap) {
+ list_del (&fir->next);
+ }
+ }
+ pthread_mutex_unlock (&priv->interrupt_mutex);
+
+ if (found) {
+ return fir;
+ }
+ return NULL;
+}
+
+static fuse_interrupt_record_t *
+fuse_interrupt_record_get (xlator_t *this, uint64_t unique)
+{
+ return fuse_interrupt_record_fetch (this, unique, _gf_false);
+}
+
+static fuse_interrupt_record_t *
+fuse_interrupt_record_reap (xlator_t *this, uint64_t unique)
+{
+ return fuse_interrupt_record_fetch (this, unique, _gf_true);
+}
+
+static void
+fuse_interrupt (xlator_t *this, fuse_in_header_t *finh, void *msg,
+ struct iobuf *iobuf)
+{
+ struct fuse_interrupt_in *fii = msg;
+ fuse_interrupt_record_t *fir = NULL;
+
+ gf_log ("glusterfs-fuse", GF_LOG_TRACE,
+ "unique %" PRIu64 " INTERRUPT for %" PRIu64, finh->unique,
+ fii->unique);
+
+ fir = fuse_interrupt_record_get (this, fii->unique);
+ if (fir) {
+ gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
+ "unique %" PRIu64 " INTERRUPT for %" PRIu64
+ ": handler triggered",
+ finh->unique, fii->unique);
+
+ fir->interrupt_handler (this, fir);
+ } else {
+ fuse_timed_message_t *dmsg = NULL;
+
+ /*
+ * No record found for this interrupt request.
+ *
+ * It's either because the handler for the interrupted message
+ * does not want to handle interrupt, or this interrupt
+ * message beat the interrupted which hasn't yet added a record
+ * to the interrupt queue. Either case we reply with error
+ * EAGAIN with some (0.01 sec) delay. That will have this
+ * interrupt request resent, unless the interrupted message
+ * has been already answered.
+ *
+ * So effectively we are looping in between kernel and
+ * userspace, which will be exited either when the interrupted
+ * message handler has added an interrupt record, or has
+ * replied to kernel. See
+ *
+ * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/
+ * linux.git/tree/Documentation/filesystems/fuse.txt?h=v4.18#n148
+ */
+
+ gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
+ "unique %" PRIu64 " INTERRUPT for %" PRIu64 ": no handler found",
+ finh->unique, fii->unique);
+
+ dmsg = fuse_timed_message_new ();
+ if (!dmsg) {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "unique %" PRIu64 " INTERRUPT for %" PRIu64
+ ":"
+ " failed to allocate timed message",
+ finh->unique, fii->unique);
+
+ return;
+ }
+
+ dmsg->fuse_out_header.unique = finh->unique;
+ dmsg->fuse_out_header.len = sizeof (dmsg->fuse_out_header);
+ dmsg->fuse_out_header.error = -EAGAIN;
+ timespec_now (&dmsg->scheduled_ts);
+ timespec_adjust_delta (&dmsg->scheduled_ts,
+ (struct timespec){0, 10000000});
+
+ send_fuse_timed (this, dmsg);
+ }
+}
+
+/*
+ * Function to be called in fop cbk context (if the fop engages
+ * with interrupt handling).
+ */
+gf_boolean_t
+fuse_interrupt_finish_fop (call_frame_t *frame, xlator_t *this,
+ gf_boolean_t sync, void **datap)
+{
+ fuse_interrupt_record_t *fir = NULL;
+ fuse_state_t *state = frame->root->state;
+ fuse_in_header_t *finh = state->finh;
+ gf_boolean_t hit = _gf_false;
+ gf_boolean_t handled = _gf_false;
+ fuse_interrupt_state_t intstat_orig = INTERRUPT_NONE;
+
+ fir = fuse_interrupt_record_reap (this, finh->unique);
+ if (!fir) {
+ /*
+ * No interrupt record was inserted (however, caller would usually know
+ * about that and there is no point then in calling this function).
+ */
+ return _gf_false;
+ }
+
+ /*
+ * The interrupt handler (if finds the record) modifies fir->hit; however,
+ * that could have occurred only before fuse_interrupt_record_reap (), so
+ * we are safe here with a lock-free access.
+ */
+ hit = fir->hit;
+ if (hit) {
+ pthread_mutex_lock (&fir->handler_mutex);
+ {
+ intstat_orig = fir->interrupt_state;
+ if (fir->interrupt_state == INTERRUPT_NONE) {
+ fir->interrupt_state = INTERRUPT_SQUELCHED;
+ if (sync) {
+ while (fir->interrupt_state == INTERRUPT_NONE) {
+ pthread_cond_wait (&fir->handler_cond,
+ &fir->handler_mutex);
+ }
+ }
+ }
+ }
+ pthread_mutex_unlock (&fir->handler_mutex);
+ }
+
+ gf_log ("glusterfs-fuse", GF_LOG_DEBUG, "intstat_orig=%d", intstat_orig);
+
+ /*
+ * From this on fir can only be referred under the conditions that imply
+ * we are to free it (otherwise interrupt handler might have already freed
+ * it).
+ */
+
+ if (/* there was no interrupt */
+ !hit ||
+ /* lost the race against interrupt handler */
+ intstat_orig != INTERRUPT_NONE ||
+ /* we took cleaning up on us */
+ sync) {
+ /* cleaning up */
+ fuse_interrupt_record_free (fir, datap);
+ } else if (datap) {
+ *datap = NULL;
+ }
+
+ handled = (intstat_orig == INTERRUPT_HANDLED);
+ if (handled) {
+ /*
+ * Fuse request was answered already from interrupt context, we can do
+ * away with the stack.
+ */
+ free_fuse_state (state);
+ STACK_DESTROY (frame->root);
+ }
+
+ /*
+ * Let caller know if they have to answer the fuse request.
+ */
+ return handled;
+}
+
+/*
+ * Function to be called in interrupt handler context.
+ */
+void
+fuse_interrupt_finish_interrupt (xlator_t *this, fuse_interrupt_record_t *fir,
+ fuse_interrupt_state_t intstat,
+ gf_boolean_t sync, void **datap)
+{
+ fuse_in_header_t finh = {
+ 0,
+ };
+ fuse_interrupt_state_t intstat_orig = INTERRUPT_NONE;
+
+ pthread_mutex_lock (&fir->handler_mutex);
+ {
+ intstat_orig = fir->interrupt_state;
+ if (fir->interrupt_state == INTERRUPT_NONE) {
+ fir->interrupt_state = intstat;
+ if (sync) {
+ pthread_cond_signal (&fir->handler_cond);
+ }
+ }
+ finh = fir->fuse_in_header;
+ }
+ pthread_mutex_unlock (&fir->handler_mutex);
+
+ gf_log ("glusterfs-fuse", GF_LOG_DEBUG, "intstat_orig=%d", intstat_orig);
+
+ /*
+ * From this on fir can only be referred under the conditions that imply
+ * we are to free it (otherwise fop handler might have already freed it).
+ */
+
+ if (/* we won the race, response is up to us */
+ intstat_orig == INTERRUPT_NONE &&
+ /* interrupt handling was successful, let the kernel know */
+ intstat == INTERRUPT_HANDLED) {
+ send_fuse_err (this, &finh, EINTR);
+ }
+
+ if (/* lost the race ... */
+ intstat_orig != INTERRUPT_NONE &&
+ /*
+ * ... and there is no contract with fop handler that it does the
+ * cleanup ...
+ */
+ !sync) {
+ /* ... so we do! */
+ fuse_interrupt_record_free (fir, datap);
+ } else if (datap) {
+ *datap = NULL;
+ }
+}
int
send_fuse_err (xlator_t *this, fuse_in_header_t *finh, int error)
@@ -4100,6 +4456,89 @@ notify_kernel_loop (void *data)
}
#endif
+static void *
+timed_response_loop (void *data)
+{
+ ssize_t rv = 0;
+ size_t len = 0;
+ xlator_t *this = NULL;
+ fuse_private_t *priv = NULL;
+ fuse_timed_message_t *dmsg = NULL;
+ fuse_timed_message_t *tmp = NULL;
+ struct timespec now = {0,};
+ struct timespec delta = {0,};
+ struct iovec iovs[2] = {{0,},};
+ fuse_in_header_t finh = {0,};
+
+ this = data;
+ priv = this->private;
+
+ for (;;) {
+ pthread_mutex_lock (&priv->timed_mutex);
+ {
+ while (list_empty (&priv->timed_list)) {
+ pthread_cond_wait (&priv->timed_cond, &priv->timed_mutex);
+ }
+
+ dmsg = list_entry (priv->timed_list.next, fuse_timed_message_t,
+ next);
+ list_for_each_entry (tmp, &priv->timed_list, next)
+ {
+ if (timespec_cmp (&tmp->scheduled_ts, &dmsg->scheduled_ts) < 0) {
+ dmsg = tmp;
+ }
+ }
+
+ list_del_init (&dmsg->next);
+ }
+ pthread_mutex_unlock (&priv->timed_mutex);
+
+ timespec_now (&now);
+ if (timespec_cmp (&now, &dmsg->scheduled_ts) < 0) {
+ timespec_sub (&now, &dmsg->scheduled_ts, &delta);
+ nanosleep (&delta, NULL);
+ }
+
+ gf_log ("glusterfs-fuse", GF_LOG_TRACE,
+ "sending timed message of unique %"PRIu64,
+ dmsg->fuse_out_header.unique);
+
+ len = dmsg->fuse_out_header.len;
+ iovs[0] = (struct iovec){&dmsg->fuse_out_header,
+ sizeof (struct fuse_out_header)};
+ iovs[1] = (struct iovec){dmsg->fuse_message_body,
+ len - sizeof (struct fuse_out_header)};
+ /*
+ * Nasty hack to allow us to use the send_fuse_iov API,
+ * which we resort to, as the API used in original upstream
+ * code used is not available in this codebase.
+ */
+ finh.unique = dmsg->fuse_out_header.unique;
+ rv = send_fuse_iov (this, &finh, iovs, 2);
+
+ fuse_timed_message_free (dmsg);
+
+ if (rv == EBADF) {
+ break;
+ }
+ }
+
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR, "timed response loop terminated");
+
+ pthread_mutex_lock (&priv->timed_mutex);
+ {
+ priv->timed_response_fuse_thread_started = _gf_false;
+ list_for_each_entry_safe (dmsg, tmp, &priv->timed_list, next)
+ {
+ list_del_init (&dmsg->next);
+ fuse_timed_message_free (dmsg);
+ }
+ }
+ pthread_mutex_unlock (&priv->timed_mutex);
+
+ return NULL;
+}
+
static void
fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg,
struct iobuf *iobuf)
@@ -4112,6 +4551,7 @@ fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg,
#if FUSE_KERNEL_MINOR_VERSION >= 9
pthread_t messenger;
#endif
+ pthread_t delayer;
priv = this->private;
@@ -4160,6 +4600,19 @@ fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg,
fino.flags |= FUSE_BIG_WRITES;
}
+ /* Start the thread processing timed responses */
+ ret = gf_thread_create (&delayer, NULL, timed_response_loop, this,
+ "fusedlyd");
+ if (ret != 0) {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "failed to start timed response thread (%s)",
+ strerror (errno));
+
+ sys_close (priv->fd);
+ goto out;
+ }
+ priv->timed_response_fuse_thread_started = _gf_true;
+
/* Used for 'reverse invalidation of inode' */
if (fini->minor >= 12) {
ret = gf_thread_create (&messenger, NULL, notify_kernel_loop,
@@ -5229,6 +5682,8 @@ fuse_priv_dump (xlator_t *this)
(int)private->init_recvd);
gf_proc_dump_write("strict_volfile_check", "%d",
(int)private->strict_volfile_check);
+ gf_proc_dump_write("timed_response_thread_started", "%d",
+ (int)private->timed_response_fuse_thread_started);
gf_proc_dump_write("reverse_thread_started", "%d",
(int)private->reverse_fuse_thread_started);
gf_proc_dump_write("use_readdirp", "%d", private->use_readdirp);
@@ -5486,7 +5941,7 @@ static fuse_handler_t *fuse_std_ops[FUSE_OP_HIGH] = {
[FUSE_SETLKW] = fuse_setlk,
[FUSE_ACCESS] = fuse_access,
[FUSE_CREATE] = fuse_create,
- /* [FUSE_INTERRUPT] */
+ [FUSE_INTERRUPT] = fuse_interrupt,
/* [FUSE_BMAP] */
[FUSE_DESTROY] = fuse_destroy,
/* [FUSE_IOCTL] */
@@ -5611,6 +6066,13 @@ init (xlator_t *this_xl)
pthread_cond_init (&priv->invalidate_cond, NULL);
pthread_mutex_init (&priv->invalidate_mutex, NULL);
+ INIT_LIST_HEAD (&priv->timed_list);
+ pthread_cond_init (&priv->timed_cond, NULL);
+ pthread_mutex_init (&priv->timed_mutex, NULL);
+
+ INIT_LIST_HEAD (&priv->interrupt_list);
+ pthread_mutex_init (&priv->interrupt_mutex, NULL);
+
/* get options from option dictionary */
ret = dict_get_str (options, ZR_MOUNTPOINT_OPT, &value_string);
if (ret == -1 || value_string == NULL) {
diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h
index 4e32a7f..ba3e000 100644
--- a/xlators/mount/fuse/src/fuse-bridge.h
+++ b/xlators/mount/fuse/src/fuse-bridge.h
@@ -147,6 +147,16 @@ struct fuse_private {
/* LRU Limit, if not set, default is 128k for now */
uint32_t lru_limit;
+
+ /* Delayed fuse response */
+ struct list_head timed_list;
+ pthread_cond_t timed_cond;
+ pthread_mutex_t timed_mutex;
+ gf_boolean_t timed_response_fuse_thread_started;
+
+ /* Interrupt subscription */
+ struct list_head interrupt_list;
+ pthread_mutex_t interrupt_mutex;
};
typedef struct fuse_private fuse_private_t;
@@ -162,6 +172,35 @@ struct fuse_invalidate_node {
};
typedef struct fuse_invalidate_node fuse_invalidate_node_t;
+struct fuse_timed_message {
+ struct fuse_out_header fuse_out_header;
+ void *fuse_message_body;
+ struct timespec scheduled_ts;
+ struct list_head next;
+};
+typedef struct fuse_timed_message fuse_timed_message_t;
+
+enum fuse_interrupt_state {
+ INTERRUPT_NONE,
+ INTERRUPT_SQUELCHED,
+ INTERRUPT_HANDLED,
+};
+typedef enum fuse_interrupt_state fuse_interrupt_state_t;
+struct fuse_interrupt_record;
+typedef struct fuse_interrupt_record fuse_interrupt_record_t;
+typedef void (*fuse_interrupt_handler_t) (xlator_t *this,
+ fuse_interrupt_record_t *);
+struct fuse_interrupt_record {
+ struct fuse_in_header fuse_in_header;
+ void *data;
+ gf_boolean_t hit;
+ fuse_interrupt_state_t interrupt_state;
+ fuse_interrupt_handler_t interrupt_handler;
+ pthread_cond_t handler_cond;
+ pthread_mutex_t handler_mutex;
+ struct list_head next;
+};
+
struct fuse_graph_switch_args {
xlator_t *this;
xlator_t *old_subvol;
diff --git a/xlators/mount/fuse/src/fuse-mem-types.h b/xlators/mount/fuse/src/fuse-mem-types.h
index 721b9a3..4ded879 100644
--- a/xlators/mount/fuse/src/fuse-mem-types.h
+++ b/xlators/mount/fuse/src/fuse-mem-types.h
@@ -24,6 +24,8 @@ enum gf_fuse_mem_types_ {
gf_fuse_mt_gids_t,
gf_fuse_mt_invalidate_node_t,
gf_fuse_mt_pthread_t,
+ gf_fuse_mt_timed_message_t,
+ gf_fuse_mt_interrupt_record_t,
gf_fuse_mt_end
};
#endif
--
1.8.3.1

View File

@ -0,0 +1,568 @@
From fc4bebd605b6a579a4d19c6640aca38057397c77 Mon Sep 17 00:00:00 2001
From: Csaba Henk <csaba@redhat.com>
Date: Tue, 21 Aug 2018 12:44:54 +0200
Subject: [PATCH 527/529] fuse: diagnostic FLUSH interrupt
We add dummy interrupt handling for the FLUSH
fuse message. It can be enabled by the
"--fuse-flush-handle-interrupt" hidden command line
option, or "-ofuse-flush-handle-interrupt=yes"
mount option.
It serves no other than diagnostic & demonstational
purposes -- to exercise the interrupt handling framework
a bit and to give an usage example.
Documentation is also provided that showcases interrupt
handling via FLUSH.
Upstream: https://review.gluster.org/20876
> Change-Id: I522f1e798501d06b74ac3592a5f73c1ab0590c60
> updates: #465
> Signed-off-by: Csaba Henk <csaba@redhat.com>
Change-Id: I510aff8895a3fe5858ab313c47514de7087d08c1
BUG: 1595246
Signed-off-by: Csaba Henk <csaba@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162550
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Amar Tumballi Suryanarayan <amarts@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
doc/developer-guide/Developers-Index.md | 5 ++
doc/developer-guide/fuse-interrupt.md | 130 ++++++++++++++++++++++++++++
glusterfsd/src/glusterfsd.c | 53 +++++++++++-
glusterfsd/src/glusterfsd.h | 1 +
libglusterfs/src/glusterfs.h | 2 +
tests/features/interrupt.t | 67 ++++++++++++++
tests/features/open_and_sleep.c | 27 ++++++
xlators/mount/fuse/src/fuse-bridge.c | 59 +++++++++++++
xlators/mount/fuse/src/fuse-bridge.h | 4 +-
xlators/mount/fuse/utils/mount.glusterfs.in | 7 ++
10 files changed, 353 insertions(+), 2 deletions(-)
create mode 100644 doc/developer-guide/fuse-interrupt.md
create mode 100644 tests/features/interrupt.t
create mode 100644 tests/features/open_and_sleep.c
diff --git a/doc/developer-guide/Developers-Index.md b/doc/developer-guide/Developers-Index.md
index 4c6346e..6c00a4a 100644
--- a/doc/developer-guide/Developers-Index.md
+++ b/doc/developer-guide/Developers-Index.md
@@ -59,6 +59,11 @@ Translators
- [Storage/posix Translator](./posix.md)
- [Compression translator](./network_compression.md)
+Fuse
+----
+
+- [Interrupt handling](./fuse-interrupt.md)
+
Testing/Debugging
-----------------
diff --git a/doc/developer-guide/fuse-interrupt.md b/doc/developer-guide/fuse-interrupt.md
new file mode 100644
index 0000000..f92b553
--- /dev/null
+++ b/doc/developer-guide/fuse-interrupt.md
@@ -0,0 +1,130 @@
+# Fuse interrupt handling
+
+## Conventions followed
+
+- *FUSE* refers to the "wire protocol" between kernel and userspace and
+ related specifications.
+- *fuse* refers to the kernel subsystem and also to the GlusterFs translator.
+
+## FUSE interrupt handling spec
+
+The [Linux kernel FUSE documentation](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/fuse.txt?h=v4.18#n148)
+desrcibes how interrupt handling happens in fuse.
+
+## Interrupt handling in the fuse translator
+
+### Declarations
+
+This document describes the internal API in the fuse translator with which
+interrupt can be handled.
+
+The API being internal (to be used only in fuse-bridge.c; the functions are
+not exported to a header file).
+
+```
+enum fuse_interrupt_state {
+ INTERRUPT_NONE,
+ INTERRUPT_SQUELCHED,
+ INTERRUPT_HANDLED,
+};
+typedef enum fuse_interrupt_state fuse_interrupt_state_t;
+struct fuse_interrupt_record;
+typedef struct fuse_interrupt_record fuse_interrupt_record_t;
+typedef void (*fuse_interrupt_handler_t)(xlator_t *this,
+ fuse_interrupt_record_t *);
+struct fuse_interrupt_record {
+ fuse_in_header_t fuse_in_header;
+ void *data;
+ /*
+ ...
+ */
+};
+
+fuse_interrupt_record_t *
+fuse_interrupt_record_new(fuse_in_header_t *finh,
+ fuse_interrupt_handler_t handler);
+
+void
+fuse_interrupt_record_insert(xlator_t *this, fuse_interrupt_record_t *fir);
+
+gf_boolean_t
+fuse_interrupt_finish_fop(call_frame_t *frame, xlator_t *this,
+ gf_boolean_t sync, void **datap);
+
+void
+fuse_interrupt_finish_interrupt(xlator_t *this, fuse_interrupt_record_t *fir,
+ fuse_interrupt_state_t intstat,
+ gf_boolean_t sync, void **datap);
+```
+
+The code demonstrates the usage of the API through `fuse_flush()`. (It's a
+dummy implementation only for demonstration purposes.) Flush is chosen
+because a `FLUSH` interrupt is easy to trigger (see
+*tests/features/interrupt.t*). Interrupt handling for flush is switched on
+by `--fuse-flush-handle-interrupt` (a hidden glusterfs command line flag).
+The flush interrupt handling code is guarded by the
+`flush_handle_interrupt` Boolean member of `fuse_private_t`.
+
+### Usage
+
+A given FUSE fop can be enabled to handle interrupts via the following
+steps:
+
+- Define a handler function (of type `fuse_interrupt_handler_t`).
+ It should implement the interrupt handling logic and in the end
+ call (directly or as async callback) `fuse_interrupt_finish_interrupt()`.
+ The `intstat` argument to `fuse_interrupt_finish_interrupt` should be
+ either `INTERRUPT_SQUELCHED` or `INTERRUPT_HANDLED`.
+ - `INTERRUPT_SQUELCHED` means that we choose not to handle the interrupt
+ and the fop is going on uninterrupted.
+ - `INTERRUPT_HANDLED` means that the interrupt was actually handled. In
+ this case the fop will be answered from interrupt context with errno
+ `EINTR` (that is, the fop should not send a response to the kernel).
+
+ We return to the `sync` and `datap` arguments later.
+- In the `fuse_<FOP>` function create an interrupt record using
+ `fuse_interrupt_record_new()`, passing the incoming `fuse_in_header` and
+ the above handler function to it.
+ - Arbitrary further data can be referred to via the `data` member of the
+ interrupt record that is to be passed on from fop context to
+ interrupt context.
+- When it's set up, pass the interrupt record to
+ `fuse_interrupt_record_insert()`.
+- In `fuse_<FOP>_cbk` call `fuse_interrupt_finish_fop()`.
+ - `fuse_interrupt_finish_fop()` returns a Boolean according to whether the
+ interrupt was handled. If it was, then the fuse request is already
+ answered and the stack gets destroyed in `fuse_interrupt_finish_fop` so
+ `fuse_<FOP>_cbk` can just return (zero). Otherwise follow the standard
+ cbk logic (answer the fuse request and destroy the stack -- these are
+ typically accomplished by `fuse_err_cbk()`).
+- The last two argument of `fuse_interrupt_finish_fop()` and
+ `fuse_interrupt_finish_interrupt()` are `gf_boolean_t sync` and
+ `void **datap`.
+ - `sync` represents the strategy for freeing the interrupt record. The
+ interrupt handler and the fop handler are in race to get at the interrupt
+ record first (interrupt handler for purposes of doing the interrupt
+ handling, fop handler for purposes of deactivating the interrupt record
+ upon completion of the fop handling).
+ - If `sync` is true, then the fop handler will wait for the interrupt
+ handler to finish and it takes care of freeing.
+ - If `sync` is false, the loser of the above race will perform freeing.
+
+ Freeing is done within the respective interrupt finish routines, except
+ for the `data` field of the interrupt record; with respect to that, see
+ the discussion of the `datap` parameter below. The strategy has to be
+ consensual, that is, `fuse_interrupt_finish_fop()` and
+ `fuse_interrupt_finish_interrupt()` must pass the same value for `sync`.
+ If dismantling the resources associated with the interrupt record is
+ simple, `sync = _gf_false` is the suggested choice; `sync = _gf_true` can
+ be useful in the opposite case, when dismantling those resources would
+ be inconvenient to implement in two places or to enact in non-fop context.
+ - If `datap` is `NULL`, the `data` member of the interrupt record will be
+ freed within the interrupt finish routine. If it points to a valid
+ `void *` pointer, and if caller is doing the cleanup (see `sync` above),
+ then that pointer will be directed to the `data` member of the interrupt
+ record and it's up to the caller what it's doing with it.
+ - If `sync` is true, interrupt handler can use `datap = NULL`, and
+ fop handler will have `datap` set.
+ - If `sync` is false, and handlers pass a pointer to a pointer for
+ `datap`, they should check if the pointed pointer is NULL before
+ attempting to deal with the data.
diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c
index 2e2cd77..9c536cd 100644
--- a/glusterfsd/src/glusterfsd.c
+++ b/glusterfsd/src/glusterfsd.c
@@ -243,6 +243,9 @@ static struct argp_option gf_options[] = {
OPTION_ARG_OPTIONAL, "disable/enable fuse event-history"},
{"reader-thread-count", ARGP_READER_THREAD_COUNT_KEY, "INTEGER",
OPTION_ARG_OPTIONAL, "set fuse reader thread count"},
+ {"fuse-flush-handle-interrupt", ARGP_FUSE_FLUSH_HANDLE_INTERRUPT_KEY,
+ "BOOL", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
+ "handle interrupt in fuse FLUSH handler"},
{0, 0, 0, 0, "Miscellaneous Options:"},
{0, }
};
@@ -581,6 +584,38 @@ set_fuse_mount_options (glusterfs_ctx_t *ctx, dict_t *options)
goto err;
}
}
+ switch (cmd_args->fuse_flush_handle_interrupt) {
+ case GF_OPTION_ENABLE:
+ ret = dict_set_static_ptr (options,
+ "flush-handle-interrupt",
+ "on");
+ if (ret < 0) {
+ gf_msg ("glusterfsd", GF_LOG_ERROR, 0,
+ glusterfsd_msg_4,
+ "failed to set dict value for key "
+ "flush-handle-interrupt");
+ goto err;
+ }
+ break;
+ case GF_OPTION_DISABLE:
+ ret = dict_set_static_ptr (options,
+ "flush-handle-interrupt",
+ "off");
+ if (ret < 0) {
+ gf_msg ("glusterfsd", GF_LOG_ERROR, 0,
+ glusterfsd_msg_4,
+ "failed to set dict value for key "
+ "flush-handle-interrupt");
+ goto err;
+ }
+ break;
+ case GF_OPTION_DEFERRED: /* default */
+ default:
+ gf_msg_debug ("glusterfsd", 0,
+ "fuse-flush-handle-interrupt mode %d",
+ cmd_args->fuse_flush_handle_interrupt);
+ break;
+ }
ret = 0;
err:
@@ -1352,7 +1387,22 @@ no_oom_api:
}
break;
- }
+ case ARGP_FUSE_FLUSH_HANDLE_INTERRUPT_KEY:
+ if (!arg)
+ arg = "yes";
+
+ if (gf_string2boolean(arg, &b) == 0) {
+ cmd_args->fuse_flush_handle_interrupt = b;
+
+ break;
+ }
+
+ argp_failure(state, -1, 0,
+ "unknown fuse flush handle interrupt "
+ "setting \"%s\"",
+ arg);
+ break;
+ }
return 0;
}
@@ -1648,6 +1698,7 @@ glusterfs_ctx_defaults_init (glusterfs_ctx_t *ctx)
cmd_args->fuse_attribute_timeout = -1;
cmd_args->fuse_entry_timeout = -1;
cmd_args->fopen_keep_cache = GF_OPTION_DEFERRED;
+ cmd_args->fuse_flush_handle_interrupt = GF_OPTION_DEFERRED;
if (ctx->mem_acct_enable)
cmd_args->mem_acct = 1;
diff --git a/glusterfsd/src/glusterfsd.h b/glusterfsd/src/glusterfsd.h
index 1550a30..28b514a 100644
--- a/glusterfsd/src/glusterfsd.h
+++ b/glusterfsd/src/glusterfsd.h
@@ -101,6 +101,7 @@ enum argp_option_keys {
ARGP_FUSE_EVENT_HISTORY_KEY = 179,
ARGP_READER_THREAD_COUNT_KEY = 180,
ARGP_FUSE_LRU_LIMIT_KEY = 190,
+ ARGP_FUSE_FLUSH_HANDLE_INTERRUPT_KEY = 191,
};
struct _gfd_vol_top_priv {
diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h
index 2690306..9fa066e 100644
--- a/libglusterfs/src/glusterfs.h
+++ b/libglusterfs/src/glusterfs.h
@@ -448,6 +448,8 @@ struct _cmd_args {
char *event_history;
uint32_t reader_thread_count;
+
+ int fuse_flush_handle_interrupt;
};
typedef struct _cmd_args cmd_args_t;
diff --git a/tests/features/interrupt.t b/tests/features/interrupt.t
new file mode 100644
index 0000000..476d875
--- /dev/null
+++ b/tests/features/interrupt.t
@@ -0,0 +1,67 @@
+#!/bin/bash
+
+##Copy this file to tests/bugs before running run.sh (cp extras/test/bug-920583.t tests/bugs/)
+
+. $(dirname $0)/../include.rc
+. $(dirname $0)/../volume.rc
+
+TESTS_EXPECTED_IN_LOOP=4
+
+cleanup;
+logdir=`gluster --print-logdir`
+
+TEST build_tester $(dirname $0)/open_and_sleep.c
+
+## Start and create a volume
+TEST glusterd;
+TEST pidof glusterd;
+
+TEST $CLI volume create $V0 replica 2 stripe 2 $H0:$B0/${V0}{1,2,3,4,5,6,7,8};
+
+## Verify volume is is created
+EXPECT "$V0" volinfo_field $V0 'Volume Name';
+EXPECT 'Created' volinfo_field $V0 'Status';
+
+## Start volume and verify
+TEST $CLI volume start $V0;
+EXPECT 'Started' volinfo_field $V0 'Status';
+
+function log-file-name()
+{
+ logfilename=$M0".log"
+ echo ${logfilename:1} | tr / -
+}
+
+log_file=$logdir"/"`log-file-name`
+
+function test_interrupt {
+ local handlebool="$1"
+ local logpattern="$2"
+
+ TEST $GFS --volfile-id=$V0 --volfile-server=$H0 --fuse-flush-handle-interrupt=$handlebool --log-level=DEBUG $M0
+
+ # If the test helper fails (which is considered a setup error, not failure of the test
+ # case itself), kill will be invoked without argument, and that will be the actual
+ # error which is caught.
+ TEST "./$(dirname $0)/open_and_sleep $M0/testfile | { sleep 0.1; xargs -n1 kill -INT; }"
+
+ TEST "grep -E '$logpattern' $log_file"
+ # Basic sanity check, making sure filesystem has not crashed.
+ TEST test -f $M0/testfile
+}
+
+# Theoretically FLUSH might finish before INTERRUPT is handled,
+# in which case we'd get the "no handler found" message (but it's unlikely).
+test_interrupt yes 'FLUSH.*interrupt handler triggered|INTERRUPT.*no handler found'
+EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
+test_interrupt no 'INTERRUPT.*no handler found'
+
+## Finish up
+TEST $CLI volume stop $V0;
+EXPECT 'Stopped' volinfo_field $V0 'Status';
+
+TEST $CLI volume delete $V0;
+TEST ! $CLI volume info $V0;
+
+cleanup_tester $(dirname $0)/open_and_sleep;
+cleanup;
diff --git a/tests/features/open_and_sleep.c b/tests/features/open_and_sleep.c
new file mode 100644
index 0000000..da089e9
--- /dev/null
+++ b/tests/features/open_and_sleep.c
@@ -0,0 +1,27 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+int
+main (int argc, char **argv)
+{
+ pid_t pid;
+ int fd;
+
+ if (argc >= 2) {
+ fd = open (argv[1], O_RDWR | O_CREAT, 0644);
+ if (fd == -1) {
+ fprintf (stderr, "cannot open/create %s\n", argv[1]);
+ return 1;
+ }
+ }
+
+ pid = getpid ();
+ printf ("%d\n", pid);
+ fflush (stdout);
+
+ for (;;)
+ sleep (1);
+
+ return 0;
+}
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
index 0d4b9db..44c39e4 100644
--- a/xlators/mount/fuse/src/fuse-bridge.c
+++ b/xlators/mount/fuse/src/fuse-bridge.c
@@ -1779,6 +1779,21 @@ fuse_err_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
}
static int
+fuse_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, dict_t *xdata)
+{
+ fuse_private_t *priv = this->private;
+
+ if (priv->flush_handle_interrupt) {
+ if (fuse_interrupt_finish_fop (frame, this, _gf_false, NULL)) {
+ return 0;
+ }
+ }
+
+ return fuse_err_cbk (frame, cookie, this, op_ret, op_errno, xdata);
+}
+
+static int
fuse_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
struct iatt *postbuf, dict_t *xdata)
@@ -2961,6 +2976,19 @@ fuse_flush_resume (fuse_state_t *state)
{
FUSE_FOP (state, fuse_err_cbk, GF_FOP_FLUSH,
flush, state->fd, state->xdata);
+ FUSE_FOP (state, fuse_flush_cbk, GF_FOP_FLUSH,
+ flush, state->fd, state->xdata);
+}
+
+static void
+fuse_flush_interrupt_handler (xlator_t *this, fuse_interrupt_record_t *fir)
+{
+ gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
+ "FLUSH unique %" PRIu64 ": interrupt handler triggered",
+ fir->fuse_in_header.unique);
+
+ fuse_interrupt_finish_interrupt (this, fir, INTERRUPT_HANDLED,
+ _gf_false, NULL);
}
static void
@@ -2968,6 +2996,7 @@ fuse_flush (xlator_t *this, fuse_in_header_t *finh, void *msg,
struct iobuf *iobuf)
{
struct fuse_flush_in *ffi = msg;
+ fuse_private_t *priv = NULL;
fuse_state_t *state = NULL;
fd_t *fd = NULL;
@@ -2976,6 +3005,27 @@ fuse_flush (xlator_t *this, fuse_in_header_t *finh, void *msg,
fd = FH_TO_FD (ffi->fh);
state->fd = fd;
+ priv = this->private;
+ if (priv->flush_handle_interrupt) {
+ fuse_interrupt_record_t *fir = NULL;
+
+ fir = fuse_interrupt_record_new (finh,
+ fuse_flush_interrupt_handler);
+ if (!fir) {
+ send_fuse_err (this, finh, ENOMEM);
+
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "FLUSH unique %" PRIu64
+ ":"
+ " interrupt record allocation failed",
+ finh->unique);
+ free_fuse_state (state);
+
+ return;
+ }
+ fuse_interrupt_record_insert (this, fir);
+ }
+
fuse_resolve_fd_init (state, &state->resolve, fd);
state->lk_owner = ffi->lock_owner;
@@ -6226,6 +6276,9 @@ init (xlator_t *this_xl)
GF_OPTION_INIT("event-history", priv->event_history, bool,
cleanup_exit);
+ GF_OPTION_INIT ("flush-handle-interrupt", priv->flush_handle_interrupt, bool,
+ cleanup_exit);
+
/* user has set only background-qlen, not congestion-threshold,
use the fuse kernel driver formula to set congestion. ie, 75% */
if (dict_get (this_xl->options, "background-qlen") &&
@@ -6552,5 +6605,11 @@ struct volume_options options[] = {
.description = "makes glusterfs invalidate kernel inodes after "
"reaching this limit (0 means 'unlimited')",
},
+ { .key = {"flush-handle-interrupt"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "false",
+ .description = "Handle iterrupts in FLUSH handler (for testing "
+ "purposes).",
+ },
{ .key = {NULL} },
};
diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h
index ba3e000..e18469d 100644
--- a/xlators/mount/fuse/src/fuse-bridge.h
+++ b/xlators/mount/fuse/src/fuse-bridge.h
@@ -157,6 +157,8 @@ struct fuse_private {
/* Interrupt subscription */
struct list_head interrupt_list;
pthread_mutex_t interrupt_mutex;
+
+ gf_boolean_t flush_handle_interrupt;
};
typedef struct fuse_private fuse_private_t;
@@ -191,7 +193,7 @@ typedef struct fuse_interrupt_record fuse_interrupt_record_t;
typedef void (*fuse_interrupt_handler_t) (xlator_t *this,
fuse_interrupt_record_t *);
struct fuse_interrupt_record {
- struct fuse_in_header fuse_in_header;
+ fuse_in_header_t fuse_in_header;
void *data;
gf_boolean_t hit;
fuse_interrupt_state_t interrupt_state;
diff --git a/xlators/mount/fuse/utils/mount.glusterfs.in b/xlators/mount/fuse/utils/mount.glusterfs.in
index 9a0404f..a3a9fbd 100755
--- a/xlators/mount/fuse/utils/mount.glusterfs.in
+++ b/xlators/mount/fuse/utils/mount.glusterfs.in
@@ -273,6 +273,10 @@ start_glusterfs ()
cmd_line=$(echo "$cmd_line --dump-fuse=$dump_fuse");
fi
+ if [ -n "$fuse_flush_handle_interrupt" ]; then
+ cmd_line=$(echo "$cmd_line --fuse-flush-handle-interrupt=$fuse_flush_handle_interrupt");
+ fi
+
# if trasnport type is specified, we have to append it to
# volume name, so that it fetches the right client vol file
@@ -524,6 +528,9 @@ with_options()
[ $value = "false" ] ; then
no_root_squash=1;
fi ;;
+ "fuse-flush-handle-interrupt")
+ fuse_flush_handle_interrupt=$value
+ ;;
"context"|"fscontext"|"defcontext"|"rootcontext")
# standard SElinux mount options to pass to the kernel
[ -z "$fuse_mountopts" ] || fuse_mountopts="$fuse_mountopts,"
--
1.8.3.1

View File

@ -0,0 +1,250 @@
From 3c0f27fd697a8c977873d44fbdf3aa63c1065645 Mon Sep 17 00:00:00 2001
From: Csaba Henk <csaba@redhat.com>
Date: Thu, 6 Dec 2018 16:13:46 +0100
Subject: [PATCH 528/529] locks: handle "clear locks" xattr in fgetxattr too
The lock clearing procedure was kicked in only in
getxattr context. We need it to work the same way
if it's triggered via fgetxattr (as is the case
with interrupt handling).
Also cleaned up the instrumentation a bit (more logs,
proper management of allocated data).
Upstream: https://review.gluster.org/21820
> updates: #465
> Change-Id: Icfca26ee181da3b8e15ca3fcf61cd5702e2730c8
> Signed-off-by: Csaba Henk <csaba@redhat.com>
Change-Id: Ia15108fd6d92ea2bdb73cea5fb04126785b19663
BUG: 1595246
Signed-off-by: Csaba Henk <csaba@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162551
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Amar Tumballi Suryanarayan <amarts@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
xlators/features/locks/src/clear.c | 6 +++
xlators/features/locks/src/clear.h | 2 +
xlators/features/locks/src/posix.c | 107 ++++++++++++++++++++++++-------------
3 files changed, 77 insertions(+), 38 deletions(-)
diff --git a/xlators/features/locks/src/clear.c b/xlators/features/locks/src/clear.c
index 22c03b5..c3d5dd2 100644
--- a/xlators/features/locks/src/clear.c
+++ b/xlators/features/locks/src/clear.c
@@ -24,6 +24,12 @@
#include "statedump.h"
#include "clear.h"
+const char *clrlk_type_names[CLRLK_TYPE_MAX] = {
+ [CLRLK_INODE] = "inode",
+ [CLRLK_ENTRY] = "entry",
+ [CLRLK_POSIX] = "posix",
+};
+
int
clrlk_get_kind (char *kind)
{
diff --git a/xlators/features/locks/src/clear.h b/xlators/features/locks/src/clear.h
index 78fc5ae..1542953 100644
--- a/xlators/features/locks/src/clear.h
+++ b/xlators/features/locks/src/clear.h
@@ -22,6 +22,8 @@ typedef enum {
CLRLK_TYPE_MAX
} clrlk_type;
+extern const char *clrlk_type_names[];
+
typedef enum {
CLRLK_BLOCKED = 1,
CLRLK_GRANTED,
diff --git a/xlators/features/locks/src/posix.c b/xlators/features/locks/src/posix.c
index 2cc2837..142a5cc 100644
--- a/xlators/features/locks/src/posix.c
+++ b/xlators/features/locks/src/posix.c
@@ -1028,41 +1028,35 @@ pl_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
}
-int32_t
-pl_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
- const char *name, dict_t *xdata)
+static int32_t
+pl_getxattr_clrlk (xlator_t *this, const char *name, inode_t *inode,
+ dict_t **dict, int32_t *op_errno)
{
- int32_t op_errno = EINVAL;
- int op_ret = -1;
int32_t bcount = 0;
int32_t gcount = 0;
- char key[PATH_MAX] = {0, };
+ char *key = NULL;
char *lk_summary = NULL;
pl_inode_t *pl_inode = NULL;
- dict_t *dict = NULL;
clrlk_args args = {0,};
char *brickname = NULL;
+ int32_t op_ret = -1;
- if (!name)
- goto usual;
-
- if (strncmp (name, GF_XATTR_CLRLK_CMD, strlen (GF_XATTR_CLRLK_CMD)))
- goto usual;
+ *op_errno = EINVAL;
if (clrlk_parse_args (name, &args)) {
- op_errno = EINVAL;
+ *op_errno = EINVAL;
goto out;
}
- dict = dict_new ();
- if (!dict) {
- op_errno = ENOMEM;
+ *dict = dict_new ();
+ if (!*dict) {
+ *op_errno = ENOMEM;
goto out;
}
- pl_inode = pl_inode_get (this, loc->inode);
+ pl_inode = pl_inode_get (this, inode);
if (!pl_inode) {
- op_errno = ENOMEM;
+ *op_errno = ENOMEM;
goto out;
}
@@ -1072,23 +1066,31 @@ pl_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
op_ret = clrlk_clear_lks_in_all_domains (this, pl_inode,
&args, &bcount,
&gcount,
- &op_errno);
- if (op_ret)
- goto out;
+ op_errno);
break;
case CLRLK_POSIX:
op_ret = clrlk_clear_posixlk (this, pl_inode, &args,
&bcount, &gcount,
- &op_errno);
- if (op_ret)
- goto out;
+ op_errno);
break;
- case CLRLK_TYPE_MAX:
- op_errno = EINVAL;
- goto out;
+ default:
+ op_ret = -1;
+ *op_errno = EINVAL;
+ }
+ if (op_ret) {
+ if (args.type >= CLRLK_TYPE_MAX) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "clear locks: invalid lock type %d", args.type);
+ } else {
+ gf_log (this->name, GF_LOG_ERROR,
+ "clear locks of type %s failed: %s",
+ clrlk_type_names[args.type], strerror (*op_errno));
+ }
+
+ goto out;
}
- op_ret = fetch_pathinfo (this, loc->inode, &op_errno, &brickname);
+ op_ret = fetch_pathinfo (this, inode, op_errno, &brickname);
if (op_ret) {
gf_log (this->name, GF_LOG_WARNING,
"Couldn't get brickname");
@@ -1105,39 +1107,62 @@ pl_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
if (!gcount && !bcount) {
if (gf_asprintf (&lk_summary, "No locks cleared.") == -1) {
op_ret = -1;
- op_errno = ENOMEM;
+ *op_errno = ENOMEM;
goto out;
}
} else if (gf_asprintf (&lk_summary, "%s: %s blocked locks=%d "
"granted locks=%d",
(brickname == NULL)? this->name : brickname,
- (args.type == CLRLK_INODE)? "inode":
- (args.type == CLRLK_ENTRY)? "entry":
- (args.type == CLRLK_POSIX)? "posix": " ",
+ clrlk_type_names[args.type],
bcount, gcount) == -1) {
op_ret = -1;
- op_errno = ENOMEM;
+ *op_errno = ENOMEM;
goto out;
}
+ gf_log (this->name, GF_LOG_DEBUG, "%s", lk_summary);
- if (snprintf(key, sizeof(key), "%s", name) >= sizeof(key)) {
+ key = gf_strdup (name);
+ if (!key) {
op_ret = -1;
goto out;
}
- if (dict_set_dynstr (dict, key, lk_summary)) {
+ if (dict_set_dynstr (*dict, key, lk_summary)) {
op_ret = -1;
- op_errno = ENOMEM;
+ *op_errno = ENOMEM;
goto out;
}
op_ret = 0;
out:
GF_FREE(brickname);
- STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict, xdata);
GF_FREE (args.opts);
- if (op_ret && lk_summary)
+ if (op_ret) {
GF_FREE (lk_summary);
+ GF_FREE (key);
+ }
+
+ return op_ret;
+}
+
+int32_t
+pl_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name,
+ dict_t *xdata)
+{
+ int32_t op_errno = EINVAL;
+ int32_t op_ret = -1;
+ dict_t *dict = NULL;
+
+ if (!name)
+ goto usual;
+
+ if (strncmp (name, GF_XATTR_CLRLK_CMD, strlen (GF_XATTR_CLRLK_CMD)))
+ goto usual;
+
+ op_ret = pl_getxattr_clrlk (this, name, loc->inode, &dict, &op_errno);
+
+ STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict, xdata);
+
if (dict)
dict_unref (dict);
return 0;
@@ -1415,6 +1440,12 @@ pl_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd,
}
goto unwind;
+ } else if (strncmp (name, GF_XATTR_CLRLK_CMD,
+ strlen (GF_XATTR_CLRLK_CMD)) == 0) {
+ op_ret = pl_getxattr_clrlk (this, name, fd->inode, &dict,
+ &op_errno);
+
+ goto unwind;
} else {
goto usual;
}
--
1.8.3.1

View File

@ -0,0 +1,222 @@
From 5f2e017ce7875de1906eb319339f11c4ef321208 Mon Sep 17 00:00:00 2001
From: Csaba Henk <csaba@redhat.com>
Date: Mon, 22 Oct 2018 00:59:05 +0200
Subject: [PATCH 529/529] fuse: SETLKW interrupt
Use the (f)getxattr based clearlocks interface to
interrupt a pending lock request.
Upstream: https://review.gluster.org/21472
> updates: #465
> Change-Id: I4e91a4d8791fc688fed400a02de4c53487e61be2
> Signed-off-by: Csaba Henk <csaba@redhat.com>
Change-Id: Ib436f1524cda6ade24c6970caee3dbd7d5f452d4
BUG: 1595246
Signed-off-by: Csaba Henk <csaba@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/162552
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Amar Tumballi Suryanarayan <amarts@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
tests/features/flock_interrupt.t | 33 +++++++++
xlators/mount/fuse/src/fuse-bridge.c | 132 +++++++++++++++++++++++++++++++++++
2 files changed, 165 insertions(+)
create mode 100644 tests/features/flock_interrupt.t
diff --git a/tests/features/flock_interrupt.t b/tests/features/flock_interrupt.t
new file mode 100644
index 0000000..8603b65
--- /dev/null
+++ b/tests/features/flock_interrupt.t
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+. $(dirname $0)/../include.rc
+. $(dirname $0)/../volume.rc
+
+cleanup;
+
+## Start and create a volume
+TEST glusterd;
+TEST pidof glusterd;
+
+TEST $CLI volume create $V0 $H0:$B0/${V0}0;
+
+## Verify volume is is created
+EXPECT "$V0" volinfo_field $V0 'Volume Name';
+EXPECT 'Created' volinfo_field $V0 'Status';
+
+## Start volume and verify
+TEST $CLI volume start $V0;
+EXPECT 'Started' volinfo_field $V0 'Status';
+
+TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0;
+TEST touch $M0/testfile;
+
+function flock_interrupt {
+ flock $MO/testfile sleep 3 & flock -w 1 $M0/testfile true;
+ echo ok;
+}
+
+EXPECT_WITHIN 2 ok flock_interrupt;
+
+## Finish up
+cleanup;
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
index 44c39e4..deaf533 100644
--- a/xlators/mount/fuse/src/fuse-bridge.c
+++ b/xlators/mount/fuse/src/fuse-bridge.c
@@ -4346,6 +4346,18 @@ fuse_setlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
{
uint32_t op = 0;
fuse_state_t *state = NULL;
+ int ret = 0;
+
+ ret = fuse_interrupt_finish_fop (frame, this, _gf_false,
+ (void **)&state);
+ if (state) {
+ GF_FREE (state->name);
+ dict_unref (state->xdata);
+ GF_FREE (state);
+ }
+ if (ret) {
+ return 0;
+ }
state = frame->root->state;
op = state->finh->opcode;
@@ -4392,10 +4404,130 @@ fuse_setlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
+static int
+fuse_setlk_interrupt_handler_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret,
+ int32_t op_errno, dict_t *dict,
+ dict_t *xdata)
+{
+ fuse_interrupt_state_t intstat = INTERRUPT_NONE;
+ fuse_interrupt_record_t *fir;
+ fuse_state_t *state = NULL;
+ int ret = 0;
+
+ ret = dict_get_bin (xdata, "fuse-interrupt-record", (void **)&fir);
+ if (ret < 0) {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "interrupt record not found");
+
+ goto out;
+ }
+
+ intstat = op_ret >= 0 ? INTERRUPT_HANDLED : INTERRUPT_SQUELCHED;
+
+ fuse_interrupt_finish_interrupt (this, fir, intstat, _gf_false,
+ (void **)&state);
+ if (state) {
+ GF_FREE (state->name);
+ dict_unref (state->xdata);
+ GF_FREE (state);
+ }
+
+out:
+ STACK_DESTROY (frame->root);
+
+ return 0;
+}
+
+static void
+fuse_setlk_interrupt_handler (xlator_t *this, fuse_interrupt_record_t *fir)
+{
+ fuse_state_t *state = NULL;
+ call_frame_t *frame = NULL;
+ char *xattr_name = NULL;
+ int ret = 0;
+
+ gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
+ "SETLK%s unique %" PRIu64 ": interrupt handler triggered",
+ fir->fuse_in_header.opcode == FUSE_SETLK ? "" : "W",
+ fir->fuse_in_header.unique);
+
+ state = fir->data;
+
+ ret = gf_asprintf (
+ &xattr_name, GF_XATTR_CLRLK_CMD ".tposix.kblocked.%hd,%jd-%jd",
+ state->lk_lock.l_whence, state->lk_lock.l_start,
+ state->lk_lock.l_len);
+ if (ret == -1) {
+ xattr_name = NULL;
+ goto err;
+ }
+
+ frame = get_call_frame_for_req (state);
+ if (!frame) {
+ goto err;
+ }
+ frame->root->state = state;
+ frame->root->op = GF_FOP_GETXATTR;
+ frame->op = GF_FOP_GETXATTR;
+ state->name = xattr_name;
+
+ STACK_WIND (frame, fuse_setlk_interrupt_handler_cbk, state->active_subvol,
+ state->active_subvol->fops->fgetxattr, state->fd, xattr_name,
+ state->xdata);
+
+ return;
+
+err:
+ GF_FREE (xattr_name);
+ fuse_interrupt_finish_interrupt (this, fir, INTERRUPT_SQUELCHED,
+ _gf_false, (void **)&state);
+ if (state) {
+ dict_unref (state->xdata);
+ GF_FREE (state);
+ }
+}
void
fuse_setlk_resume (fuse_state_t *state)
{
+ fuse_interrupt_record_t *fir = NULL;
+ fuse_state_t *state_clone = NULL;
+
+ fir = fuse_interrupt_record_new (state->finh, fuse_setlk_interrupt_handler);
+ state_clone = gf_memdup (state, sizeof (*state));
+ if (state_clone) {
+ /*
+ * Calling this allocator with fir casted to (char *) seems like
+ * an abuse of this API, but in fact the API is stupid to assume
+ * a (char *) argument (in the funcion it's casted to (void *)
+ * anyway).
+ */
+ state_clone->xdata = dict_for_key_value (
+ "fuse-interrupt-record", (char *)fir, sizeof (*fir), _gf_true);
+ }
+ if (!fir || !state_clone || !state_clone->xdata) {
+ if (fir) {
+ GF_FREE (fir);
+ }
+ if (state_clone) {
+ GF_FREE (state_clone);
+ }
+ send_fuse_err (state->this, state->finh, ENOMEM);
+
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "SETLK%s unique %"PRIu64":"
+ " interrupt record allocation failed",
+ state->finh->opcode == FUSE_SETLK ? "" : "W",
+ state->finh->unique);
+ free_fuse_state (state);
+
+ return;
+ }
+ state_clone->name = NULL;
+ fir->data = state_clone;
+ fuse_interrupt_record_insert (state->this, fir);
+
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
"%"PRIu64": SETLK%s %p", state->finh->unique,
state->finh->opcode == FUSE_SETLK ? "" : "W", state->fd);
--
1.8.3.1

View File

@ -192,7 +192,7 @@ Release: 0.1%{?prereltag:.%{prereltag}}%{?dist}
%else
Name: glusterfs
Version: 3.12.2
Release: 40%{?dist}
Release: 41%{?dist}
%endif
License: GPLv2 or LGPLv3+
Group: System Environment/Base
@ -775,6 +775,25 @@ Patch0507: 0507-geo-rep-fix-rename-sync-on-hybrid-crawl.patch
Patch0508: 0508-glusterd-Resolve-multiple-leaks-in-glusterd-code-pat.patch
Patch0509: 0509-core-heketi-cli-is-throwing-error-target-is-busy.patch
Patch0510: 0510-features-shard-Ref-shard-inode-while-adding-to-fsync.patch
Patch0511: 0511-Update-rfc.sh-to-rhgs-3.4.4.patch
Patch0512: 0512-Test-fixes-for-rhgs-3.4-downstream.patch
Patch0513: 0513-core-heketi-cli-is-throwing-error-target-is-busy.patch
Patch0514: 0514-glusterd-display-gluster-volume-status-when-quorum-t.patch
Patch0515: 0515-cli-change-the-warning-message.patch
Patch0516: 0516-geo-rep-Fix-permissions-with-non-root-setup.patch
Patch0517: 0517-geo-rep-validate-the-config-checkpoint-date-format.patch
Patch0518: 0518-logging-create-parent-dir-if-not-available.patch
Patch0519: 0519-cluster-dht-Delete-invalid-linkto-files-in-rmdir.patch
Patch0520: 0520-spec-avoid-creation-of-temp-file-in-lua-script.patch
Patch0521: 0521-rpc-use-address-family-option-from-vol-file.patch
Patch0522: 0522-fuse-add-lru-limit-option.patch
Patch0523: 0523-libglusterfs-rename-macros-roof-and-floor-to-not-con.patch
Patch0524: 0524-program-GF-DUMP-Shield-ping-processing-from-traffic-.patch
Patch0525: 0525-rpcsvc-provide-each-request-handler-thread-its-own-q.patch
Patch0526: 0526-fuse-interrupt-handling-framework.patch
Patch0527: 0527-fuse-diagnostic-FLUSH-interrupt.patch
Patch0528: 0528-locks-handle-clear-locks-xattr-in-fgetxattr-too.patch
Patch0529: 0529-fuse-SETLKW-interrupt.patch
%description
GlusterFS is a distributed file-system capable of scaling to several
@ -1225,7 +1244,7 @@ while read p
do
# if the destination file exists, its most probably stale
# so we must remove it
rename_to=( $(egrep '^rename to' $p | cut -f 3 -d ' ') )
rename_to=( $(grep -i 'rename to' $p | cut -f 3 -d ' ') )
if [ ${#rename_to[*]} -gt 0 ]; then
for f in ${rename_to[*]}
do
@ -2205,12 +2224,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
tmpname = os.tmpname()
tmpfile = io.open(tmpname, "w")
tmpfile:write(script)
tmpfile:close()
ok, how, val = os.execute("/bin/bash " .. tmpname)
os.remove(tmpname)
ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@ -2247,12 +2261,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
tmpname = os.tmpname()
tmpfile = io.open(tmpname, "w")
tmpfile:write(script)
tmpfile:close()
ok, how, val = os.execute("/bin/bash " .. tmpname)
os.remove(tmpname)
ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@ -2289,12 +2298,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
tmpname = os.tmpname()
tmpfile = io.open(tmpname, "w")
tmpfile:write(script)
tmpfile:close()
ok, how, val = os.execute("/bin/bash " .. tmpname)
os.remove(tmpname)
ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@ -2331,12 +2335,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
tmpname = os.tmpname()
tmpfile = io.open(tmpname, "w")
tmpfile:write(script)
tmpfile:close()
ok, how, val = os.execute("/bin/bash " .. tmpname)
os.remove(tmpname)
ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@ -2373,12 +2372,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
tmpname = os.tmpname()
tmpfile = io.open(tmpname, "w")
tmpfile:write(script)
tmpfile:close()
ok, how, val = os.execute("/bin/bash " .. tmpname)
os.remove(tmpname)
ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@ -2415,12 +2409,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
tmpname = os.tmpname()
tmpfile = io.open(tmpname, "w")
tmpfile:write(script)
tmpfile:close()
ok, how, val = os.execute("/bin/bash " .. tmpname)
os.remove(tmpname)
ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@ -2457,12 +2446,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
tmpname = os.tmpname()
tmpfile = io.open(tmpname, "w")
tmpfile:write(script)
tmpfile:close()
ok, how, val = os.execute("/bin/bash " .. tmpname)
os.remove(tmpname)
ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@ -2500,12 +2484,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
tmpname = os.tmpname()
tmpfile = io.open(tmpname, "w")
tmpfile:write(script)
tmpfile:close()
ok, how, val = os.execute("/bin/bash " .. tmpname)
os.remove(tmpname)
ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@ -2543,12 +2522,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
tmpname = os.tmpname()
tmpfile = io.open(tmpname, "w")
tmpfile:write(script)
tmpfile:close()
ok, how, val = os.execute("/bin/bash " .. tmpname)
os.remove(tmpname)
ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@ -2586,12 +2560,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
tmpname = os.tmpname()
tmpfile = io.open(tmpname, "w")
tmpfile:write(script)
tmpfile:close()
ok, how, val = os.execute("/bin/bash " .. tmpname)
os.remove(tmpname)
ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@ -2630,12 +2599,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
tmpname = os.tmpname()
tmpfile = io.open(tmpname, "w")
tmpfile:write(script)
tmpfile:close()
ok, how, val = os.execute("/bin/bash " .. tmpname)
os.remove(tmpname)
ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@ -2673,12 +2637,7 @@ fi
-- Since we run pretrans scripts only for RPMs built for a server build,
-- we can now use os.tmpname() since it is available on RHEL6 and later
-- platforms which are server platforms.
tmpname = os.tmpname()
tmpfile = io.open(tmpname, "w")
tmpfile:write(script)
tmpfile:close()
ok, how, val = os.execute("/bin/bash " .. tmpname)
os.remove(tmpname)
ok, how, val = os.execute("/bin/bash -c \"" .. script .. "\"")
if not (ok == 0) then
error("Detected running glusterfs processes", ok)
end
@ -2735,6 +2694,10 @@ fi
%endif
%changelog
* Tue Feb 12 2019 Milind Changire <mchangir@redhat.com> - 3.12.2-41
- fixes bugs bz#1390151 bz#1410145 bz#1429190 bz#1510752 bz#1511779
bz#1570958 bz#1574490 bz#1595246 bz#1618669 bz#1661393 bz#1668989 bz#1669020
* Fri Jan 25 2019 Milind Changire <mchangir@redhat.com> - 3.12.2-40
- fixes bugs bz#1668304 bz#1669020