The patches for 3.3.0.
[rsync-patches.git] / direct-io.diff
1 This patch adds the --direct-io option, which opens files with O_DIRECT.
2
3 TODO: we probably need to make our I/O aligned on 512-byte boundaries.
4
5 Written by: Dag Wieers
6
7 To use this patch, run these commands for a successful build:
8
9     patch -p1 <patches/direct-io.diff
10     ./configure                         (optional if already run)
11     make
12
13 based-on: 16b49716d55a50f2e985b879b720b2c53c892a3a
14 diff --git a/options.c b/options.c
15 --- a/options.c
16 +++ b/options.c
17 @@ -24,6 +24,7 @@
18  #include <popt.h>
19  #include <zlib.h>
20  
21 +extern int direct_io;
22  extern int module_id;
23  extern int local_server;
24  extern int sanitize_paths;
25 @@ -745,6 +746,7 @@ void usage(enum logcode F)
26    rprintf(F,"     --partial               keep partially transferred files\n");
27    rprintf(F,"     --partial-dir=DIR       put a partially transferred file into DIR\n");
28    rprintf(F,"     --delay-updates         put all updated files into place at transfer's end\n");
29 +  rprintf(F,"     --direct-io             don't use buffer cache for xfer file I/O\n");
30    rprintf(F," -m, --prune-empty-dirs      prune empty directory chains from the file-list\n");
31    rprintf(F,"     --numeric-ids           don't map uid/gid values by user/group name\n");
32    rprintf(F,"     --usermap=STRING        custom username mapping\n");
33 @@ -979,6 +981,8 @@ static struct poptOption long_options[] = {
34    {"partial-dir",      0,  POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
35    {"delay-updates",    0,  POPT_ARG_VAL,    &delay_updates, 1, 0, 0 },
36    {"no-delay-updates", 0,  POPT_ARG_VAL,    &delay_updates, 0, 0, 0 },
37 +  {"direct-io",       'n', POPT_ARG_VAL,    &direct_io, 1, 0, 0 },
38 +  {"no-direct-io",     0,  POPT_ARG_VAL,    &direct_io, 0, 0, 0 },
39    {"prune-empty-dirs",'m', POPT_ARG_VAL,    &prune_empty_dirs, 1, 0, 0 },
40    {"no-prune-empty-dirs",0,POPT_ARG_VAL,    &prune_empty_dirs, 0, 0, 0 },
41    {"no-m",             0,  POPT_ARG_VAL,    &prune_empty_dirs, 0, 0, 0 },
42 diff --git a/rsync.yo b/rsync.yo
43 --- a/rsync.yo
44 +++ b/rsync.yo
45 @@ -404,6 +404,7 @@ to the detailed description below for a complete description.  verb(
46       --partial               keep partially transferred files
47       --partial-dir=DIR       put a partially transferred file into DIR
48       --delay-updates         put all updated files into place at end
49 +     --direct-io             don't use buffer cache for xfer file I/O
50   -m, --prune-empty-dirs      prune empty directory chains from file-list
51       --numeric-ids           don't map uid/gid values by user/group name
52       --usermap=STRING        custom username mapping
53 @@ -2369,6 +2370,14 @@ See also the "atomic-rsync" perl script in the "support" subdir for an
54  update algorithm that is even more atomic (it uses bf(--link-dest) and a
55  parallel hierarchy of files).
56  
57 +dit(bf(--direct-io)) This option opens files with a direct-I/O flag that
58 +makes the file I/O avoid the buffer cache.  The option only affects one
59 +side of the transfer (unless the transfer is local).  If you want it to
60 +affect both sides, use the bf(--remote-option) (bf(-M)) option to specify
61 +it for the remote side.  For instance, this specifies it for both sides:
62 +
63 +quote(tt(  rsync -av {,-M}--direct-io /src/ host:/dest/))
64 +
65  dit(bf(-m, --prune-empty-dirs)) This option tells the receiving rsync to get
66  rid of empty directories from the file-list, including nested directories
67  that have no non-directory children.  This is useful for avoiding the
68 diff --git a/syscall.c b/syscall.c
69 --- a/syscall.c
70 +++ b/syscall.c
71 @@ -41,6 +41,8 @@ extern int list_only;
72  extern int preserve_perms;
73  extern int preserve_executability;
74  
75 +int direct_io = 0;
76 +
77  #define RETURN_ERROR_IF(x,e) \
78         do { \
79                 if (x) { \
80 @@ -69,7 +71,12 @@ int do_symlink(const char *lnk, const char *fname)
81          * and write the lnk into it. */
82         if (am_root < 0) {
83                 int ok, len = strlen(lnk);
84 -               int fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
85 +               int flags = O_WRONLY|O_CREAT|O_TRUNC;
86 +
87 +               if (direct_io)
88 +                       flags |= O_DIRECT;
89 +
90 +               int fd = open(fname, flags, S_IWUSR|S_IRUSR);
91                 if (fd < 0)
92                         return -1;
93                 ok = write(fd, lnk, len) == len;
94 @@ -190,6 +197,9 @@ int do_open(const char *pathname, int flags, mode_t mode)
95                 RETURN_ERROR_IF_RO_OR_LO;
96         }
97  
98 +       if (direct_io)
99 +               flags |= O_DIRECT;
100 +
101         return open(pathname, flags | O_BINARY, mode);
102  }
103  
104 @@ -461,6 +471,9 @@ int do_open_nofollow(const char *pathname, int flags)
105  #endif
106         }
107  
108 +       if (direct_io)
109 +               flags |= O_DIRECT;
110 +
111  #ifdef O_NOFOLLOW
112         fd = open(pathname, flags|O_NOFOLLOW);
113  #else