From: Jeff M. <jm...@re...> - 2009-03-23 19:07:10
|
Jeff Moyer <jm...@re...> writes: > Marc Thomas <ma...@dr...> writes: > >> Hi Jeff, >> >> Patch applies cleanly to dump-0.4b41, but it doesn't then compile on >> my system (Slackware 12.2, kernel 2.6.27.7, CFQ scheduler): >> >> tape.c: In function 'fork_clone_io': >> tape.c:797: error: 'CLONE_IO' undeclared (first use in this function) >> tape.c:797: error: (Each undeclared identifier is reported only once >> tape.c:797: error: for each function it appears in.) >> >> I'm no programmer, but I did find that changing the include for >> <sched.h> to <linux/sched.h> fixed that. > > Hi, Marc. Thanks for testing, and for the suggested fix. There is > another problem with compiling the patch on systems that don't have the > CLONE_IO flag at all, and I need to address that. Here is a follow-up patch that should work everywhere. Comments and suggestions are welcome. I'd love to hear at least *some* feedback from the dump maintainer on this. Thanks, Jeff Index: dump/tape.c =================================================================== RCS file: /cvsroot/dump/dump/dump/tape.c,v retrieving revision 1.90 diff -u -p -r1.90 tape.c --- dump/tape.c 4 Jun 2008 19:27:48 -0000 1.90 +++ dump/tape.c 23 Mar 2009 19:05:00 -0000 @@ -187,6 +187,41 @@ static sigjmp_buf jmpbuf; /* where to ju 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) { @@ -755,6 +790,16 @@ rollforward(void) #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 @@ -801,7 +846,7 @@ restore_check_point: /* * 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); @@ -1017,7 +1062,7 @@ enslave(void) } 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)); |