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: 6c8ca91c731b7bf2b081694bda85b7dadc2b7aff
14 diff --git a/options.c b/options.c
15 --- a/options.c
16 +++ b/options.c
17 @@ -24,6 +24,7 @@
18  #include "ifuncs.h"
19  #include <popt.h>
20  
21 +extern int direct_io;
22  extern int module_id;
23  extern int local_server;
24  extern int sanitize_paths;
25 @@ -764,6 +765,8 @@ static struct poptOption long_options[] = {
26    {"partial-dir",      0,  POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
27    {"delay-updates",    0,  POPT_ARG_VAL,    &delay_updates, 1, 0, 0 },
28    {"no-delay-updates", 0,  POPT_ARG_VAL,    &delay_updates, 0, 0, 0 },
29 +  {"direct-io",       'n', POPT_ARG_VAL,    &direct_io, 1, 0, 0 },
30 +  {"no-direct-io",     0,  POPT_ARG_VAL,    &direct_io, 0, 0, 0 },
31    {"prune-empty-dirs",'m', POPT_ARG_VAL,    &prune_empty_dirs, 1, 0, 0 },
32    {"no-prune-empty-dirs",0,POPT_ARG_VAL,    &prune_empty_dirs, 0, 0, 0 },
33    {"no-m",             0,  POPT_ARG_VAL,    &prune_empty_dirs, 0, 0, 0 },
34 diff --git a/rsync.1.md b/rsync.1.md
35 --- a/rsync.1.md
36 +++ b/rsync.1.md
37 @@ -495,6 +495,7 @@ has its own detailed description later in this manpage.
38  --partial                keep partially transferred files
39  --partial-dir=DIR        put a partially transferred file into DIR
40  --delay-updates          put all updated files into place at end
41 +--direct-io              don't use buffer cache for xfer file I/O
42  --prune-empty-dirs, -m   prune empty directory chains from file-list
43  --numeric-ids            don't map uid/gid values by user/group name
44  --usermap=STRING         custom username mapping
45 @@ -3433,6 +3434,17 @@ expand it.
46      update algorithm that is even more atomic (it uses [`--link-dest`](#opt)
47      and a parallel hierarchy of files).
48  
49 +0.  `--direct-io`
50 +
51 +    This option opens files with a direct-I/O flag that makes the file I/O
52 +    avoid the buffer cache.  The option only affects one side of the transfer
53 +    (unless the transfer is local).  If you want it to affect both sides, use
54 +    the [`--remote-option`](#opt) (`-M`) option to specify it for the remote
55 +    side.  For instance, this specifies it for both sides (via brace
56 +    expansion):
57 +
58 +    >     rsync -av {,-M}--direct-io /src/ host:/dest/
59 +
60  0.  `--prune-empty-dirs`, `-m`
61  
62      This option tells the receiving rsync to get rid of empty directories from
63 diff --git a/syscall.c b/syscall.c
64 --- a/syscall.c
65 +++ b/syscall.c
66 @@ -44,6 +44,8 @@ extern int preserve_perms;
67  extern int preserve_executability;
68  extern int open_noatime;
69  
70 +int direct_io = 0;
71 +
72  #ifndef S_BLKSIZE
73  # if defined hpux || defined __hpux__ || defined __hpux
74  #  define S_BLKSIZE 1024
75 @@ -95,7 +97,12 @@ int do_symlink(const char *lnk, const char *path)
76          * and write the lnk into it. */
77         if (am_root < 0) {
78                 int ok, len = strlen(lnk);
79 -               int fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
80 +               int flags = O_WRONLY|O_CREAT|O_TRUNC;
81 +
82 +               if (direct_io)
83 +                       flags |= O_DIRECT;
84 +
85 +               int fd = open(path, flags, S_IWUSR|S_IRUSR);
86                 if (fd < 0)
87                         return -1;
88                 ok = write(fd, lnk, len) == len;
89 @@ -224,6 +231,8 @@ int do_open(const char *pathname, int flags, mode_t mode)
90         if (open_noatime)
91                 flags |= O_NOATIME;
92  #endif
93 +       if (direct_io)
94 +               flags |= O_DIRECT;
95  
96         return open(pathname, flags | O_BINARY, mode);
97  }
98 @@ -684,6 +693,9 @@ int do_open_nofollow(const char *pathname, int flags)
99  #endif
100         }
101  
102 +       if (direct_io)
103 +               flags |= O_DIRECT;
104 +
105  #ifdef O_NOFOLLOW
106         fd = open(pathname, flags|O_NOFOLLOW);
107  #else