From 0b83b8af60916dcdb850f15da7e7b406809dd1d5 Mon Sep 17 00:00:00 2001 From: Pranith Kumar K Date: Mon, 6 May 2019 15:27:44 +0530 Subject: tests: Test openfd heal doesn't truncate files fixes bz#1706603 Change-Id: I0bfd30f787f157b7a54f71088f767ccfd7621208 Signed-off-by: Pranith Kumar K --- tests/basic/ec/gfapi-ec-open-truncate.c | 170 ++++++++++++++++++++++++++++++++ tests/basic/ec/gfapi-ec-open-truncate.t | 48 +++++++++ 2 files changed, 218 insertions(+) create mode 100644 tests/basic/ec/gfapi-ec-open-truncate.c create mode 100644 tests/basic/ec/gfapi-ec-open-truncate.t (limited to 'tests/basic') diff --git a/tests/basic/ec/gfapi-ec-open-truncate.c b/tests/basic/ec/gfapi-ec-open-truncate.c new file mode 100644 index 00000000000..22f17f436b6 --- /dev/null +++ b/tests/basic/ec/gfapi-ec-open-truncate.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOG_ERR(msg) \ + do { \ + fprintf(stderr, "%s : Error (%s)\n", msg, strerror(errno)); \ + } while (0) + +int +fill_iov(struct iovec *iov, char fillchar, int count) +{ + int ret = -1; + + iov->iov_base = calloc(count + 1, sizeof(fillchar)); + if (iov->iov_base == NULL) { + return ret; + } else { + iov->iov_len = count; + ret = 0; + } + memset(iov->iov_base, fillchar, count); + memset(iov->iov_base + count, '\0', 1); + + return ret; +} + +glfs_t * +init_glfs(const char *hostname, const char *volname, const char *logfile) +{ + int ret = -1; + glfs_t *fs = NULL; + + fs = glfs_new(volname); + if (!fs) { + LOG_ERR("glfs_new failed"); + return NULL; + } + + ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); + if (ret < 0) { + LOG_ERR("glfs_set_volfile_server failed"); + goto out; + } + + ret = glfs_set_logging(fs, logfile, 7); + if (ret < 0) { + LOG_ERR("glfs_set_logging failed"); + goto out; + } + + ret = glfs_init(fs); + if (ret < 0) { + LOG_ERR("glfs_init failed"); + goto out; + } + + ret = 0; +out: + if (ret) { + glfs_fini(fs); + fs = NULL; + } + + return fs; +} + +int +main(int argc, char *argv[]) +{ + char *hostname = NULL; + char *volname = NULL; + char *logfile = NULL; + glfs_t *fs = NULL; + glfs_fd_t *glfd = NULL; + int ret = 0; + int i = 0; + int count = 200; + struct iovec iov = {0}; + int flags = O_RDWR; + int bricksup = 0; + int fdopen = 0; + + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + exit(1); + } + + hostname = argv[1]; + volname = argv[2]; + logfile = argv[3]; + + fs = init_glfs(hostname, volname, logfile); + if (fs == NULL) { + LOG_ERR("init_glfs failed"); + return -1; + } + + /* Brick is down and we are opening a file to trigger fd heal. */ + /* Bypass Write-behind */ + glfd = glfs_open(fs, "a", O_WRONLY | O_TRUNC | O_SYNC); + if (glfd == NULL) { + LOG_ERR("glfs_open_truncate failed"); + exit(1); + } + system("gluster --mode=script volume start patchy force"); + /*CHILD_UP_TIMEOUT is 20 seconds*/ + for (i = 0; i < 20; i++) { + ret = system( + "[ $(gluster --mode=script volume status patchy | " + "grep \" Y \" | awk '{print $(NF-1)}' | wc -l) == 3 ]"); + if (WIFEXITED(ret) && WEXITSTATUS(ret)) { + printf("Ret value of system: %d\n, ifexited: %d, exitstatus: %d", + ret, WIFEXITED(ret), WEXITSTATUS(ret)); + sleep(1); + continue; + } + printf("Number of loops: %d\n", i); + bricksup = 1; + break; + } + if (!bricksup) { + system("gluster --mode=script volume status patchy"); + LOG_ERR("Bricks didn't come up\n"); + exit(1); + } + + /*Not sure how to check that the child-up reached EC, so sleep 3 for now*/ + sleep(3); + ret = fill_iov(&iov, 'a', 200); + if (ret) { + LOG_ERR("failed to create iov"); + exit(1); + } + + /*write will trigger re-open*/ + ret = glfs_pwritev(glfd, &iov, 1, 0, flags); + if (ret < 0) { + LOG_ERR("glfs_test_function failed"); + exit(1); + } + /*Check reopen happened by checking for open-fds on the brick*/ + for (i = 0; i < 20; i++) { + ret = system( + "[ $(for i in $(pgrep glusterfsd); do ls -l /proc/$i/fd | grep " + "\"[.]glusterfs\" | grep -v health_check; done | wc -l) == 3 ]"); + if (WIFEXITED(ret) && WEXITSTATUS(ret)) { + printf("Ret value of system: %d\n, ifexited: %d, exitstatus: %d", + ret, WIFEXITED(ret), WEXITSTATUS(ret)); + sleep(1); + continue; + } + fdopen = 1; + break; + } + + if (!fdopen) { + LOG_ERR("fd reopen didn't succeed"); + exit(1); + } + + return 0; +} diff --git a/tests/basic/ec/gfapi-ec-open-truncate.t b/tests/basic/ec/gfapi-ec-open-truncate.t new file mode 100644 index 00000000000..e22562c6ea3 --- /dev/null +++ b/tests/basic/ec/gfapi-ec-open-truncate.t @@ -0,0 +1,48 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +#This .t tests the functionality of open-fd-heal when opened with O_TRUNC. +#If re-open is not done with O_TRUNC then the test will pass. + +cleanup + +TEST glusterd + +TEST $CLI volume create $V0 disperse 3 ${H0}:$B0/brick{1,2,3} +EXPECT 'Created' volinfo_field $V0 'Status' +#Disable heals to prevent any chance of heals masking the problem +TEST $CLI volume set $V0 disperse.background-heals 0 +TEST $CLI volume set $V0 disperse.heal-wait-qlength 0 +TEST $CLI volume set $V0 performance.write-behind off + +#We need truncate fop to go through before pre-op completes for the write-fop +#which triggers open-fd heal. Otherwise truncate won't be allowed on 'bad' brick +TEST $CLI volume set $V0 delay-gen posix +TEST $CLI volume set $V0 delay-gen.enable fxattrop +TEST $CLI volume set $V0 delay-gen.delay-percentage 100 +TEST $CLI volume set $V0 delay-gen.delay-duration 1000000 + +TEST $CLI volume heal $V0 disable + +TEST $CLI volume start $V0 +TEST $CLI volume profile $V0 start +EXPECT 'Started' volinfo_field $V0 'Status' +TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0 +TEST touch $M0/a +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +TEST kill_brick $V0 $H0 $B0/brick1 +logdir=`gluster --print-logdir` + +TEST build_tester $(dirname $0)/gfapi-ec-open-truncate.c -lgfapi + +TEST $CLI volume profile $V0 info clear +TEST ./$(dirname $0)/gfapi-ec-open-truncate ${H0} $V0 $logdir/gfapi-ec-open-truncate.log + +EXPECT "^2$" echo $($CLI volume profile $V0 info incremental | grep -i truncate | wc -l) +cleanup_tester $(dirname $0)/gfapi-ec-open-truncate + +cleanup -- cgit