From b8ac20e888fbacad9d90cd8f1c6ff8579a5cefe9 Mon Sep 17 00:00:00 2001 From: Poornima G Date: Mon, 6 Jun 2016 06:29:40 -0400 Subject: gfapi: Fix IO error caused when there is consecutive graph switches Issue: Consider a simple situation, where glfs_init() is done, i.e. initial graph is up. Now perform 2 volume sets that results in 2 client side graph changes. After this perform some IO, the IO fails with ENOTCON. The only way to recover this client is i guess another graph switch or restart. What actually is happening from code perspective: Initial graph lets say A, followed by 2 consecutive graph switches to B and C without any IO those two switches. - graph_setup (A) as a result of GF_EVENT_CHILD_UP, and fs->next_subvol = A - glfs_init() results in fs->active_subvol = A, fs->next_subvol = NULL - graph_setup (B) as a result of GF_EVENT_CHILD_UP, and fs->next_subvol = B - graph_setup (C) as a result of GF_EVENT_CHILD_UP, and fs->next_subvol = C. It also sees that the previous graph B was never set as fs->active_subvol, i.e. no IO or anything happened on B, so can safely send GF_EVENT_PARENT_DOWN (by calling glfs_subvol_done(B)). This parent down on B, results in child_down(B), which is fine. But child_down also triggers graph_setup(B). - graph_setup(B) as a result of GF_EVENT_CHILD_DOWN, and fs->next_subvol = B, and GF_EVENT_PARENT_DOWN on C as explained above. This again leads to GF_EVENT_CHILD_DOWN on C. - graph_setup(C) as a result of GF_EVENT_CHILD_DOWN, and fs->next_subvol = C, and GF_EVENT_PARENT_DOWN on B as explained above. Thus both the graphs B and C are disconnected, and hence the ENOTCON Solution: Remove the call to graph_setup() when the event is GF_EVENT_CHILD_DOWN. It don't see any reason why graph_setup should be called when there is child_down. Not sure what the original reason was, to have graph_setup in child_down. git hostory shows the first patch itself had this call. Change-Id: I9de86555f66cc94a05649ac863b40ed3426ffd4b BUG: 1343038 Signed-off-by: Poornima G Reviewed-on: http://review.gluster.org/14656 Smoke: Gluster Build System NetBSD-regression: NetBSD Build System CentOS-regression: Gluster Build System Reviewed-by: Jeff Darcy --- tests/bugs/gfapi/bug-1093594.c | 315 ---------------------------------------- tests/bugs/gfapi/bug-1093594.sh | 20 --- 2 files changed, 335 deletions(-) delete mode 100644 tests/bugs/gfapi/bug-1093594.c delete mode 100755 tests/bugs/gfapi/bug-1093594.sh (limited to 'tests/bugs/gfapi') diff --git a/tests/bugs/gfapi/bug-1093594.c b/tests/bugs/gfapi/bug-1093594.c deleted file mode 100644 index 8f5aa9be66c..00000000000 --- a/tests/bugs/gfapi/bug-1093594.c +++ /dev/null @@ -1,315 +0,0 @@ -#include "../../api/src/glfs.h" -#include "../../api/src/glfs-handles.h" -#include -#include -#include -#include - -#define WRITE_SIZE (128*1024) -#define READ_WRITE_LOOP 100 -#define FOP_LOOP_COUNT 20 -#define TEST_CASE_LOOP 20 - -int gfapi = 1; -static int extension = 1; - -static int -large_number_of_fops (glfs_t *fs) { - int ret = 0; - int i = 0; - glfs_fd_t *fd = NULL; - glfs_fd_t *fd1 = NULL; - char *dir1 = NULL, *dir2 = NULL, *filename1 = NULL, *filename2 = NULL; - char *buf = NULL; - struct stat sb = {0, }; - - for (i = 0 ; i < FOP_LOOP_COUNT ; i++) { - ret = asprintf (&dir1, "dir%d", extension); - if (ret < 0) { - fprintf (stderr, "cannot construct filename (%s)", - strerror (errno)); - return ret; - } - - extension++; - - ret = glfs_mkdir (fs, dir1, 0755); - if (ret < 0) { - fprintf (stderr, "mkdir(%s): %s\n", dir1, strerror (errno)); - return -1; - } - - fd = glfs_opendir (fs, dir1); - if (!fd) { - fprintf (stderr, "/: %s\n", strerror (errno)); - return -1; - } - - ret = glfs_fsetxattr (fd, "user.dirfattr", "fsetxattr", 8, 0); - if (ret < 0) { - fprintf (stderr, "fsetxattr(%s): %d (%s)\n", dir1, ret, - strerror (errno)); - return -1; - } - - ret = glfs_closedir (fd); - if (ret < 0) { - fprintf (stderr, "glfs_closedir failed with ret: %d (%s)\n", - ret, strerror (errno)); - return -1; - } - - ret = glfs_rmdir (fs, dir1); - if (ret < 0) { - fprintf (stderr, "glfs_unlink failed with ret: %d (%s)\n", - ret, strerror (errno)); - return -1; - } - - ret = asprintf (&filename1, "file%d", extension); - if (ret < 0) { - fprintf (stderr, "cannot construct filename (%s)", - strerror (errno)); - return ret; - } - - ret = asprintf (&filename2, "file-%d", extension); - if (ret < 0) { - fprintf (stderr, "cannot construct filename (%s)", - strerror (errno)); - return ret; - } - - extension++; - - fd = glfs_creat (fs, filename1, O_RDWR, 0644); - if (!fd) { - fprintf (stderr, "%s: (%p) %s\n", filename1, fd, - strerror (errno)); - return -1; - } - - ret = glfs_rename (fs, filename1, filename2); - if (ret < 0) { - fprintf (stderr, "glfs_rename failed with ret: %d (%s)\n", - ret, strerror (errno)); - return -1; - } - - ret = glfs_lstat (fs, filename2, &sb); - if (ret < 0) { - fprintf (stderr, "glfs_lstat failed with ret: %d (%s)\n", - ret, strerror (errno)); - return -1; - } - - ret = glfs_close (fd); - if (ret < 0) { - fprintf (stderr, "glfs_close failed with ret: %d (%s)\n", - ret, strerror (errno)); - return -1; - } - - ret = glfs_unlink (fs, filename2); - if (ret < 0) { - fprintf (stderr, "glfs_unlink failed with ret: %d (%s)\n", - ret, strerror (errno)); - return -1; - } - } -} - -static int -large_read_write (glfs_t *fs) { - - int ret = 0; - int j = 0; - glfs_fd_t *fd = NULL; - glfs_fd_t *fd1 = NULL; - char *filename = NULL; - char *buf = NULL; - - ret = asprintf (&filename, "filerw%d", extension); - if (ret < 0) { - fprintf (stderr, "cannot construct filename (%s)", - strerror (errno)); - return ret; - } - - extension++; - - fd = glfs_creat (fs, filename, O_RDWR, 0644); - if (!fd) { - fprintf (stderr, "%s: (%p) %s\n", filename, fd, - strerror (errno)); - return -1; - } - - buf = (char *) malloc (WRITE_SIZE); - memset (buf, '-', WRITE_SIZE); - - for (j = 0; j < READ_WRITE_LOOP; j++) { - ret = glfs_write (fd, buf, WRITE_SIZE, 0); - if (ret < 0) { - fprintf (stderr, "Write(%s): %d (%s)\n", filename, ret, - strerror (errno)); - return ret; - } - } - - fd1 = glfs_open (fs, filename, O_RDWR); - if (fd1 < 0) { - fprintf (stderr, "Open(%s): %d (%s)\n", filename, ret, - strerror (errno)); - return -1; - } - - glfs_lseek (fd1, 0, SEEK_SET); - for (j = 0; j < READ_WRITE_LOOP; j++) { - ret = glfs_read (fd1, buf, WRITE_SIZE, 0); - if (ret < 0) { - fprintf (stderr, "Read(%s): %d (%s)\n", filename, ret, - strerror (errno)); - return ret; - } - } - - for (j = 0; j < READ_WRITE_LOOP; j++) { - ret = glfs_write (fd1, buf, WRITE_SIZE, 0); - if (ret < 0) { - fprintf (stderr, "Write(%s): %d (%s)\n", filename, ret, - strerror (errno)); - return ret; - } - } - - glfs_close (fd); - glfs_close (fd1); - ret = glfs_unlink (fs, filename); - if (ret < 0) { - fprintf (stderr, "glfs_unlink failed with ret: %d (%s)\n", - ret, strerror (errno)); - return -1; - } - - free (buf); - free (filename); -} - -static int -volfile_change (const char *volname) { - int ret = 0; - char *cmd = NULL, *cmd1 = NULL; - - ret = asprintf (&cmd, "gluster volume set %s stat-prefetch off", - volname); - if (ret < 0) { - fprintf (stderr, "cannot construct cli command string (%s)", - strerror (errno)); - return ret; - } - - ret = asprintf (&cmd1, "gluster volume set %s stat-prefetch on", - volname); - if (ret < 0) { - fprintf (stderr, "cannot construct cli command string (%s)", - strerror (errno)); - return ret; - } - - ret = system (cmd); - if (ret < 0) { - fprintf (stderr, "stat-prefetch off on (%s) failed", volname); - return ret; - } - - ret = system (cmd1); - if (ret < 0) { - fprintf (stderr, "stat-prefetch on on (%s) failed", volname); - return ret; - } - - free (cmd); - free (cmd1); - return ret; -} - -int -main (int argc, char *argv[]) -{ - glfs_t *fs = NULL; - int ret = 0; - int i = 0; - glfs_fd_t *fd = NULL; - glfs_fd_t *fd1 = NULL; - char *topdir = "topdir", *filename = "file1"; - char *buf = NULL; - char *logfile = NULL; - - if (argc != 3) { - fprintf (stderr, - "Expect following args %s \n" - , argv[0]); - return -1; - } - - logfile = argv[2]; - - for (i = 0; i < TEST_CASE_LOOP; i++) { - fs = glfs_new (argv[1]); - if (!fs) { - fprintf (stderr, "glfs_new: returned NULL (%s)\n", - strerror (errno)); - return -1; - } - - ret = glfs_set_volfile_server (fs, "tcp", "localhost", 24007); - if (ret < 0) { - fprintf (stderr, "glfs_set_volfile_server failed ret:%d (%s)\n", - ret, strerror (errno)); - return -1; - } - - ret = glfs_set_logging (fs, logfile, 7); - if (ret < 0) { - fprintf (stderr, "glfs_set_logging failed with ret: %d (%s)\n", - ret, strerror (errno)); - return -1; - } - - ret = glfs_init (fs); - if (ret < 0) { - fprintf (stderr, "glfs_init failed with ret: %d (%s)\n", - ret, strerror (errno)); - return -1; - } - - ret = large_number_of_fops (fs); - if (ret < 0) - return -1; - - ret = large_read_write (fs); - if (ret < 0) - return -1; - - ret = volfile_change (argv[1]); - if (ret < 0) - return -1; - - ret = large_number_of_fops (fs); - if (ret < 0) - return -1; - - ret = large_read_write (fs); - if (ret < 0) - return -1; - - ret = glfs_fini (fs); - if (ret < 0) { - fprintf (stderr, "glfs_fini failed with ret: %d (%s)\n", - ret, strerror (errno)); - return -1; - } - } - return 0; -} diff --git a/tests/bugs/gfapi/bug-1093594.sh b/tests/bugs/gfapi/bug-1093594.sh deleted file mode 100755 index 444319b8e63..00000000000 --- a/tests/bugs/gfapi/bug-1093594.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc - -cleanup; - -## Start and create a volume -TEST glusterd; -TEST pidof glusterd; -TEST $CLI volume info; - -TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2}; -TEST $CLI volume start $V0; -logdir=`gluster --print-logdir` - -build_tester $(dirname $0)/bug-1093594.c -lgfapi -TEST $(dirname $0)/bug-1093594 $V0 $logdir/bug-1093594.log - -cleanup_tester $(dirname $0)/bug-1093594 -cleanup; -- cgit