Use sys_clone under Linux to share I/O contexts between dump processes.
authorStelian Pop <stelian@popies.net>
Thu, 18 Jun 2009 09:50:54 +0000 (09:50 +0000)
committerStelian Pop <stelian@popies.net>
Thu, 18 Jun 2009 09:50:54 +0000 (09:50 +0000)
CHANGES
dump/tape.c

diff --git a/CHANGES b/CHANGES
index 4b117b26cd620bfb8ffb6c4771023077e20f865c..b0d3831aae48dffc7b18541e51d4497e0485f8a3 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,4 @@
-$Id: CHANGES,v 1.299 2009/06/18 09:42:11 stelian Exp $
+$Id: CHANGES,v 1.300 2009/06/18 09:50:54 stelian Exp $
 
 Changes between versions 0.4b41 and 0.4b42 (released xxxxxxxxxxxxxxx)
 =====================================================================
 
 Changes between versions 0.4b41 and 0.4b42 (released xxxxxxxxxxxxxxx)
 =====================================================================
@@ -70,6 +70,12 @@ Changes between versions 0.4b41 and 0.4b42 (released xxxxxxxxxxxxxxx)
        that -P and -A were both allowed in the same invocation (RedHat
        bug #490627). Thanks to Adam Tkac <atkac@redhat.com> for the patch.
 
        that -P and -A were both allowed in the same invocation (RedHat
        bug #490627). Thanks to Adam Tkac <atkac@redhat.com> for the patch.
 
+17.    Use sys_clone under Linux to share I/O contexts between dump
+       processes, thus drastically increasing the performance of dump
+       under CFQ (which is the default I/O scheduler used in a number of
+       distributions). Thanks to Jeff Moyer <jmoyer@redhat.com> for the
+       patch.
+
 Changes between versions 0.4b40 and 0.4b41 (released January 2, 2006)
 =====================================================================
 
 Changes between versions 0.4b40 and 0.4b41 (released January 2, 2006)
 =====================================================================
 
index 3e41622b3f51057daa35ac73855ae17245f250f9..edcf5d691925a6532dd71e8b30f75514d8190109 100644 (file)
@@ -37,7 +37,7 @@
 
 #ifndef lint
 static const char rcsid[] =
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: tape.c,v 1.90 2008/06/04 19:27:48 stelian Exp $";
+       "$Id: tape.c,v 1.91 2009/06/18 09:50:54 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
 #endif /* not lint */
 
 #include <config.h>
@@ -187,6 +187,41 @@ static sigjmp_buf jmpbuf;  /* where to jump to if we are ready when the */
 static int gtperr = 0;
 #endif
 
 static int gtperr = 0;
 #endif
 
+/*
+ * Determine if we can use Linux' clone system call.  If so, call it
+ * with the CLONE_IO flag so that all processes will share the same I/O
+ * context, allowing the I/O schedulers to make better scheduling decisions.
+ */
+#ifdef __linux__
+/* first, pull in the header files that define sys_clone and CLONE_IO */
+#include <syscall.h>
+#define _GNU_SOURCE
+#include <sched.h>
+#include <unistd.h>
+#undef _GNU_SOURCE
+
+/* If either is not present, fall back on the fork behaviour */
+#if ! defined(SYS_clone) || ! defined (CLONE_IO)
+#define fork_clone_io fork
+#else /* SYS_clone */
+/* CLONE_IO is available, determine which version of sys_clone to use */
+#include <linux/version.h>
+/*
+ * Kernel 2.5.49 introduced two extra parameters to the clone system call.
+ * Neither is useful in our case, so this is easy to handle.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,49)
+/* clone_flags, child_stack, parent_tidptr, child_tidptr */
+#define CLONE_ARGS SIGCHLD|CLONE_IO, 0, NULL, NULL
+#else
+#define CLONE_ARGS SIGCHLD|CLONE_IO, 0
+#endif /* LINUX_VERSION_CODE */
+pid_t fork_clone_io(void);
+#endif /* SYS_clone */
+#else /* __linux__ not defined */
+#define fork_clone_io fork
+#endif /* __linux__ */
+
 int
 alloctape(void)
 {
 int
 alloctape(void)
 {
@@ -755,6 +790,16 @@ rollforward(void)
 #endif
 }
 
 #endif
 }
 
+#ifdef __linux__
+#if defined(SYS_clone) && defined(CLONE_IO)
+pid_t
+fork_clone_io(void)
+{
+       return syscall(SYS_clone, CLONE_ARGS);
+}
+#endif
+#endif
+
 /*
  * We implement taking and restoring checkpoints on the tape level.
  * When each tape is opened, a new process is created by forking; this
 /*
  * We implement taking and restoring checkpoints on the tape level.
  * When each tape is opened, a new process is created by forking; this
@@ -801,7 +846,7 @@ restore_check_point:
        /*
         *      All signals are inherited...
         */
        /*
         *      All signals are inherited...
         */
-       childpid = fork();
+       childpid = fork_clone_io();
        if (childpid < 0) {
                msg("Context save fork fails in parent %d\n", parentpid);
                Exit(X_ABORT);
        if (childpid < 0) {
                msg("Context save fork fails in parent %d\n", parentpid);
                Exit(X_ABORT);
@@ -1017,7 +1062,7 @@ enslave(void)
                }
 
                if (socketpair(AF_UNIX, SOCK_STREAM, 0, cmd) < 0 ||
                }
 
                if (socketpair(AF_UNIX, SOCK_STREAM, 0, cmd) < 0 ||
-                   (slaves[i].pid = fork()) < 0)
+                   (slaves[i].pid = fork_clone_io()) < 0)
                        quit("too many slaves, %d (recompile smaller): %s\n",
                            i, strerror(errno));
 
                        quit("too many slaves, %d (recompile smaller): %s\n",
                            i, strerror(errno));