This patch adds the --direct-io option, which opens files with O_DIRECT. TODO: we probably need to make our I/O aligned on 512-byte boundaries. Written by: Dag Wieers To use this patch, run these commands for a successful build: patch -p1 #include +extern int direct_io; extern int module_id; extern int local_server; extern int sanitize_paths; @@ -747,6 +748,7 @@ void usage(enum logcode F) rprintf(F," --partial keep partially transferred files\n"); rprintf(F," --partial-dir=DIR put a partially transferred file into DIR\n"); rprintf(F," --delay-updates put all updated files into place at transfer's end\n"); + rprintf(F," --direct-io don't use buffer cache for xfer file I/O\n"); rprintf(F," -m, --prune-empty-dirs prune empty directory chains from the file-list\n"); rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n"); rprintf(F," --usermap=STRING custom username mapping\n"); @@ -982,6 +984,8 @@ static struct poptOption long_options[] = { {"partial-dir", 0, POPT_ARG_STRING, &partial_dir, 0, 0, 0 }, {"delay-updates", 0, POPT_ARG_VAL, &delay_updates, 1, 0, 0 }, {"no-delay-updates", 0, POPT_ARG_VAL, &delay_updates, 0, 0, 0 }, + {"direct-io", 'n', POPT_ARG_VAL, &direct_io, 1, 0, 0 }, + {"no-direct-io", 0, POPT_ARG_VAL, &direct_io, 0, 0, 0 }, {"prune-empty-dirs",'m', POPT_ARG_VAL, &prune_empty_dirs, 1, 0, 0 }, {"no-prune-empty-dirs",0,POPT_ARG_VAL, &prune_empty_dirs, 0, 0, 0 }, {"no-m", 0, POPT_ARG_VAL, &prune_empty_dirs, 0, 0, 0 }, diff --git a/rsync.yo b/rsync.yo --- a/rsync.yo +++ b/rsync.yo @@ -405,6 +405,7 @@ to the detailed description below for a complete description. verb( --partial keep partially transferred files --partial-dir=DIR put a partially transferred file into DIR --delay-updates put all updated files into place at end + --direct-io don't use buffer cache for xfer file I/O -m, --prune-empty-dirs prune empty directory chains from file-list --numeric-ids don't map uid/gid values by user/group name --usermap=STRING custom username mapping @@ -2435,6 +2436,14 @@ See also the "atomic-rsync" perl script in the "support" subdir for an update algorithm that is even more atomic (it uses bf(--link-dest) and a parallel hierarchy of files). +dit(bf(--direct-io)) This option opens files with a direct-I/O flag that +makes the file I/O avoid the buffer cache. The option only affects one +side of the transfer (unless the transfer is local). If you want it to +affect both sides, use the bf(--remote-option) (bf(-M)) option to specify +it for the remote side. For instance, this specifies it for both sides: + +quote(tt( rsync -av {,-M}--direct-io /src/ host:/dest/)) + dit(bf(-m, --prune-empty-dirs)) This option tells the receiving rsync to get rid of empty directories from the file-list, including nested directories that have no non-directory children. This is useful for avoiding the diff --git a/syscall.c b/syscall.c --- a/syscall.c +++ b/syscall.c @@ -43,6 +43,8 @@ extern int preallocate_files; extern int preserve_perms; extern int preserve_executability; +int direct_io = 0; + #ifndef S_BLKSIZE # if defined hpux || defined __hpux__ || defined __hpux # define S_BLKSIZE 1024 @@ -81,7 +83,12 @@ int do_symlink(const char *lnk, const char *fname) * and write the lnk into it. */ if (am_root < 0) { int ok, len = strlen(lnk); - int fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR); + int flags = O_WRONLY|O_CREAT|O_TRUNC; + + if (direct_io) + flags |= O_DIRECT; + + int fd = open(fname, flags, S_IWUSR|S_IRUSR); if (fd < 0) return -1; ok = write(fd, lnk, len) == len; @@ -202,6 +209,9 @@ int do_open(const char *pathname, int flags, mode_t mode) RETURN_ERROR_IF_RO_OR_LO; } + if (direct_io) + flags |= O_DIRECT; + return open(pathname, flags | O_BINARY, mode); } @@ -545,6 +555,9 @@ int do_open_nofollow(const char *pathname, int flags) #endif } + if (direct_io) + flags |= O_DIRECT; + #ifdef O_NOFOLLOW fd = open(pathname, flags|O_NOFOLLOW); #else diff -Nurp a/rsync.1 b/rsync.1 --- a/rsync.1 +++ b/rsync.1 @@ -481,6 +481,7 @@ to the detailed description below for a \-\-partial keep partially transferred files \-\-partial\-dir=DIR put a partially transferred file into DIR \-\-delay\-updates put all updated files into place at end + \-\-direct\-io don'\&t use buffer cache for xfer file I/O \-m, \-\-prune\-empty\-dirs prune empty directory chains from file\-list \-\-numeric\-ids don'\&t map uid/gid values by user/group name \-\-usermap=STRING custom username mapping @@ -2761,6 +2762,18 @@ See also the \(dq\&atomic\-rsync\(dq\& p update algorithm that is even more atomic (it uses \fB\-\-link\-dest\fP and a parallel hierarchy of files). .IP +.IP "\fB\-\-direct\-io\fP" +This option opens files with a direct\-I/O flag that +makes the file I/O avoid the buffer cache. The option only affects one +side of the transfer (unless the transfer is local). If you want it to +affect both sides, use the \fB\-\-remote\-option\fP (\fB\-M\fP) option to specify +it for the remote side. For instance, this specifies it for both sides: +.IP +.RS +\f(CW rsync \-av {,\-M}\-\-direct\-io /src/ host:/dest/\fP +.RE + +.IP .IP "\fB\-m, \-\-prune\-empty\-dirs\fP" This option tells the receiving rsync to get rid of empty directories from the file\-list, including nested directories