| 1 | This patch from Sami Farin lets you specify --fsync if you want fsync() |
| 2 | to be called on every file we write. |
| 3 | |
| 4 | To use this patch, run these commands for a successful build: |
| 5 | |
| 6 | patch -p1 <patches/fsync.diff |
| 7 | ./configure (optional if already run) |
| 8 | make |
| 9 | |
| 10 | based-on: a01e3b490eb36ccf9e704840e1b6683dab867550 |
| 11 | diff --git a/options.c b/options.c |
| 12 | --- a/options.c |
| 13 | +++ b/options.c |
| 14 | @@ -48,6 +48,7 @@ int append_mode = 0; |
| 15 | int keep_dirlinks = 0; |
| 16 | int copy_dirlinks = 0; |
| 17 | int copy_links = 0; |
| 18 | +int do_fsync = 0; |
| 19 | int preserve_links = 0; |
| 20 | int preserve_hard_links = 0; |
| 21 | int preserve_acls = 0; |
| 22 | @@ -731,6 +732,7 @@ void usage(enum logcode F) |
| 23 | rprintf(F," --partial-dir=DIR put a partially transferred file into DIR\n"); |
| 24 | rprintf(F," --delay-updates put all updated files into place at transfer's end\n"); |
| 25 | rprintf(F," -m, --prune-empty-dirs prune empty directory chains from the file-list\n"); |
| 26 | + rprintf(F," --fsync fsync every written file\n"); |
| 27 | rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n"); |
| 28 | rprintf(F," --usermap=STRING custom username mapping\n"); |
| 29 | rprintf(F," --groupmap=STRING custom groupname mapping\n"); |
| 30 | @@ -989,6 +991,7 @@ static struct poptOption long_options[] = { |
| 31 | {"no-timeout", 0, POPT_ARG_VAL, &io_timeout, 0, 0, 0 }, |
| 32 | {"contimeout", 0, POPT_ARG_INT, &connect_timeout, 0, 0, 0 }, |
| 33 | {"no-contimeout", 0, POPT_ARG_VAL, &connect_timeout, 0, 0, 0 }, |
| 34 | + {"fsync", 0, POPT_ARG_NONE, &do_fsync, 0, 0, 0 }, |
| 35 | {"rsh", 'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 }, |
| 36 | {"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 }, |
| 37 | {"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 }, |
| 38 | @@ -2607,6 +2610,9 @@ void server_options(char **args, int *argc_p) |
| 39 | args[ac++] = tmpdir; |
| 40 | } |
| 41 | |
| 42 | + if (do_fsync) |
| 43 | + args[ac++] = "--fsync"; |
| 44 | + |
| 45 | if (basis_dir[0]) { |
| 46 | /* the server only needs this option if it is not the sender, |
| 47 | * and it may be an older version that doesn't know this |
| 48 | diff --git a/receiver.c b/receiver.c |
| 49 | --- a/receiver.c |
| 50 | +++ b/receiver.c |
| 51 | @@ -38,6 +38,7 @@ extern int relative_paths; |
| 52 | extern int preserve_hard_links; |
| 53 | extern int preserve_perms; |
| 54 | extern int preserve_xattrs; |
| 55 | +extern int do_fsync; |
| 56 | extern int basis_dir_cnt; |
| 57 | extern int make_backups; |
| 58 | extern int cleanup_got_literal; |
| 59 | @@ -337,6 +338,12 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, |
| 60 | if (sum_end(file_sum1) != checksum_len) |
| 61 | overflow_exit("checksum_len"); /* Impossible... */ |
| 62 | |
| 63 | + if (do_fsync && fd != -1 && fsync(fd) != 0) { |
| 64 | + rsyserr(FERROR, errno, "fsync failed on %s", |
| 65 | + full_fname(fname)); |
| 66 | + exit_cleanup(RERR_FILEIO); |
| 67 | + } |
| 68 | + |
| 69 | if (mapbuf) |
| 70 | unmap_file(mapbuf); |
| 71 | |
| 72 | diff --git a/t_stub.c b/t_stub.c |
| 73 | --- a/t_stub.c |
| 74 | +++ b/t_stub.c |
| 75 | @@ -21,6 +21,7 @@ |
| 76 | |
| 77 | #include "rsync.h" |
| 78 | |
| 79 | +int do_fsync = 0; |
| 80 | int modify_window = 0; |
| 81 | int module_id = -1; |
| 82 | int relative_paths = 0; |
| 83 | diff --git a/util.c b/util.c |
| 84 | --- a/util.c |
| 85 | +++ b/util.c |
| 86 | @@ -27,6 +27,7 @@ |
| 87 | |
| 88 | extern int dry_run; |
| 89 | extern int module_id; |
| 90 | +extern int do_fsync; |
| 91 | extern int modify_window; |
| 92 | extern int relative_paths; |
| 93 | extern int preserve_xattrs; |
| 94 | @@ -382,6 +383,13 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode) |
| 95 | full_fname(source)); |
| 96 | } |
| 97 | |
| 98 | + if (do_fsync && fsync(ofd) < 0) { |
| 99 | + rsyserr(FERROR, errno, "fsync failed on %s", |
| 100 | + full_fname(dest)); |
| 101 | + close(ofd); |
| 102 | + return -1; |
| 103 | + } |
| 104 | + |
| 105 | if (close(ofd) < 0) { |
| 106 | int save_errno = errno; |
| 107 | rsyserr(FERROR_XFER, errno, "close failed on %s", |