summaryrefslogtreecommitdiffstats
path: root/tests/bugs
diff options
context:
space:
mode:
authorPoornima G <pgurusid@redhat.com>2015-02-19 21:29:02 +0530
committerShyamsundar Ranganathan <srangana@redhat.com>2015-03-04 07:15:12 -0800
commit9c5011b8e49e34d736ba7cfadc0802e8b80682a7 (patch)
treecacffa0ab6ba732d72a9c6f9eadd050c60cbae15 /tests/bugs
parentf82756b4909cebaf533570aec2b05ba55a7dcc95 (diff)
glfs_fini: Clean up all the resources allocated in glfs_new.
Initially even after calling glfs_fini(), all the threads created during init and many other resources like memory pool, iobuf pool, event pool and other memory allocs were not being freed. With this patch these resources are freed in glfs_fini(). The two thumb rules followed in this patch are: - The threads are not killed, they are made to exit voluntarily, once the queued tasks are completed. The main thread waits for the other threads to exit. - Free the memory pools and destroy the graphs only after all the other threads are stopped, so that there are less chances of hitting access after free. Resources freed and its order: 1. Destroy the inode table of all the graphs - Call forget on all the inodes. This will not be required when the cleanup during graph switch is implemented to perform inode table destroy. 2. Deactivate the current graph, call fini of all the xlators. 3. Syncenv destroy - Join the synctask threads and cleanup syncenv resources Sets the destroy mode, complete the existing synctasks, then join the synctask threads. After entering the destroy mode, -if a new synctask is submitted, it fails. -if syncenv_new() is called, it will end up creating new threads, but this is called only during init. 4. Poller thread destroy Register an event handler which sets the destroy mode for the poller. Once the poller is done processing all the events, it exits. 5. Tear down the logging framework The log file is closed and the log level is set to none, after this point no log messages appear either in log file or in stderr. 6. Destroy the timer thread Set the destroy bit, once the pending timer events are processed the timer thread exits. Note: Log infrastructure should be shutdown before destroying the timer thread as gf_log uses timers. 7. Destroy the glusterfs_ctx_t For all the graphs(active and passive), free graph, xlator structs and few other lists. Free the memory pools - iobuf pool, event pool, dict, logbuf pool, stub mem pool, stack mem pool, frame mem pool. Few things not addressed in this patch: 1. rpc_transport object not destroyed, the PARENT_DOWN should have destroyed this object but has not, needs to be addressed as a part of different patch 2. Each xlator fini should clean up the local pool allocated by its xlator. Needs to be addresses as a part of different patch. 3. Each xlator should implement forget to free its inode_ctx. Needs to be addresses as a part of different patch. 3. Few other leaks reported by valgrind. 4. fd and fd contexts The numbers: The resource usage by the test case in this patch: Without the fix, Memory: ~3GB; Threads: ~81 With this fix, Memory: 300MB; Threads: 1(main thread) Change-Id: I96b9277541737aa8372b4e6c9eed380cb871e7c2 BUG: 1093594 Signed-off-by: Poornima G <pgurusid@redhat.com> Reviewed-on: http://review.gluster.org/7642 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Rajesh Joseph <rjoseph@redhat.com> Reviewed-by: Raghavendra Talur <rtalur@redhat.com> Reviewed-by: Krishnan Parthasarathi <kparthas@redhat.com> Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com> Reviewed-by: Shyamsundar Ranganathan <srangana@redhat.com>
Diffstat (limited to 'tests/bugs')
-rw-r--r--tests/bugs/bug-1093594.c315
-rw-r--r--tests/bugs/bug-1093594.t20
2 files changed, 335 insertions, 0 deletions
diff --git a/tests/bugs/bug-1093594.c b/tests/bugs/bug-1093594.c
new file mode 100644
index 00000000000..8f5aa9be66c
--- /dev/null
+++ b/tests/bugs/bug-1093594.c
@@ -0,0 +1,315 @@
+#include "../../api/src/glfs.h"
+#include "../../api/src/glfs-handles.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <Vol> <log file>\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/bug-1093594.t b/tests/bugs/bug-1093594.t
new file mode 100644
index 00000000000..524c6240344
--- /dev/null
+++ b/tests/bugs/bug-1093594.t
@@ -0,0 +1,20 @@
+#!/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;