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 +extern int direct_io; extern int module_id; extern int local_server; extern int sanitize_paths; @@ -754,6 +755,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.1.md b/rsync.1.md --- a/rsync.1.md +++ b/rsync.1.md @@ -409,6 +409,7 @@ detailed description below for a complete description. --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 --prune-empty-dirs, -m prune empty directory chains from file-list --numeric-ids don't map uid/gid values by user/group name --usermap=STRING custom username mapping @@ -3012,6 +3013,16 @@ your home directory (remove the '=' for that). update algorithm that is even more atomic (it uses `--link-dest` and a parallel hierarchy of files). +0. `--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 `--remote-option` (`-M`) option to specify it for the remote side. For + instance, this specifies it for both sides: + + > rsync -av {,-M}--direct-io /src/ host:/dest/ + 0. `--prune-empty-dirs`, `-m` This option tells the receiving rsync to get rid of empty directories from diff --git a/syscall.c b/syscall.c --- a/syscall.c +++ b/syscall.c @@ -44,6 +44,8 @@ extern int preserve_perms; extern int preserve_executability; extern int open_noatime; +int direct_io = 0; + #ifndef S_BLKSIZE # if defined hpux || defined __hpux__ || defined __hpux # define S_BLKSIZE 1024 @@ -91,7 +93,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; @@ -220,6 +227,8 @@ int do_open(const char *pathname, int flags, mode_t mode) if (open_noatime) flags |= O_NOATIME; #endif + if (direct_io) + flags |= O_DIRECT; return open(pathname, flags | O_BINARY, mode); } @@ -624,6 +633,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 @@ -485,6 +485,7 @@ detailed description below for a complet --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 --prune-empty-dirs, -m prune empty directory chains from file-list --numeric-ids don't map uid/gid values by user/group name --usermap=STRING custom username mapping @@ -3073,6 +3074,18 @@ delayed updates will fail if they can't See also the "atomic-rsync" perl script in the "support" subdir for an update algorithm that is even more atomic (it uses \fB\-\-link-dest\fP and a parallel hierarchy of files). +.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: +.RS 4 +.IP +.nf +rsync -av {,-M}--direct-io /src/ host:/dest/ +.fi +.RE .IP "\fB\-\-prune-empty-dirs\fP, \fB\-m\fP" This option tells the receiving rsync to get rid of empty directories from the file-list, including nested directories that have no non-directory diff -Nurp a/rsync.1.html b/rsync.1.html --- a/rsync.1.html +++ b/rsync.1.html @@ -400,6 +400,7 @@ detailed description below for a complet --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 --prune-empty-dirs, -m prune empty directory chains from file-list --numeric-ids don't map uid/gid values by user/group name --usermap=STRING custom username mapping @@ -2845,6 +2846,18 @@ update algorithm that is even more atomi parallel hierarchy of files).

+
--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 --remote-option (-M) option to specify it for the remote side. For +instance, this specifies it for both sides:

+
+
rsync -av {,-M}--direct-io /src/ host:/dest/
+
+
+
+
--prune-empty-dirs, -m

This option tells the receiving rsync to get rid of empty directories from the file-list, including nested directories that have no non-directory