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