]> git.ipfire.org Git - thirdparty/rsync.git/commitdiff
Add --fsync option (promoted from patches).
authorWayne Davison <wayne@opencoder.net>
Mon, 27 Sep 2021 17:30:00 +0000 (10:30 -0700)
committerWayne Davison <wayne@opencoder.net>
Mon, 27 Sep 2021 17:30:00 +0000 (10:30 -0700)
options.c
receiver.c
rsync.1.md
t_stub.c
util1.c

index 54998661021997ec470cef1c065b1497b2ceafd4..98676d1789edf548aabcc58331fb1dad7f76965c 100644 (file)
--- a/options.c
+++ b/options.c
@@ -66,6 +66,7 @@ int open_noatime = 0;
 int cvs_exclude = 0;
 int dry_run = 0;
 int do_xfers = 1;
+int do_fsync = 0;
 int ignore_times = 0;
 int delete_mode = 0;
 int delete_during = 0;
@@ -789,6 +790,7 @@ static struct poptOption long_options[] = {
   {"no-timeout",       0,  POPT_ARG_VAL,    &io_timeout, 0, 0, 0 },
   {"contimeout",       0,  POPT_ARG_INT,    &connect_timeout, 0, 0, 0 },
   {"no-contimeout",    0,  POPT_ARG_VAL,    &connect_timeout, 0, 0, 0 },
+  {"fsync",            0,  POPT_ARG_NONE,   &do_fsync, 0, 0, 0 },
   {"stop-after",       0,  POPT_ARG_STRING, 0, OPT_STOP_AFTER, 0, 0 },
   {"time-limit",       0,  POPT_ARG_STRING, 0, OPT_STOP_AFTER, 0, 0 }, /* earlier stop-after name */
   {"stop-at",          0,  POPT_ARG_STRING, 0, OPT_STOP_AT, 0, 0 },
@@ -2806,6 +2808,9 @@ void server_options(char **args, int *argc_p)
                        args[ac++] = tmpdir;
                }
 
+               if (do_fsync)
+                       args[ac++] = "--fsync";
+
                if (basis_dir[0]) {
                        /* the server only needs this option if it is not the sender,
                         *   and it may be an older version that doesn't know this
index b5020d0744b141f9ac3e367bd35ca684e9dbba7e..091fcd6fb185b19a6047b735938428dbdf1c1a3e 100644 (file)
@@ -41,6 +41,7 @@ extern int preserve_hard_links;
 extern int preserve_perms;
 extern int write_devices;
 extern int preserve_xattrs;
+extern int do_fsync;
 extern int basis_dir_cnt;
 extern int make_backups;
 extern int cleanup_got_literal;
@@ -394,6 +395,11 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
 
        sum_len = sum_end(file_sum1);
 
+       if (do_fsync && fd != -1 && fsync(fd) != 0) {
+               rsyserr(FERROR, errno, "fsync failed on %s", full_fname(fname));
+               exit_cleanup(RERR_FILEIO);
+       }
+
        if (mapbuf)
                unmap_file(mapbuf);
 
index 72026dfd75767d407983282dc4420dd945d8b500..9bfda865a3dbbbc603065048bdd99ebfb24345bd 100644 (file)
@@ -461,6 +461,7 @@ detailed description below for a complete description.
 --bwlimit=RATE           limit socket I/O bandwidth
 --stop-after=MINS        Stop rsync after MINS minutes have elapsed
 --stop-at=y-m-dTh:m      Stop rsync at the specified point in time
+--fsync                  fsync every written file
 --write-batch=FILE       write a batched update to FILE
 --only-write-batch=FILE  like --write-batch but w/o updating dest
 --read-batch=FILE        read a batched update from FILE
@@ -3257,6 +3258,12 @@ your home directory (remove the '=' for that).
     mind that the remote host may have a different default timezone than your
     local host.
 
+0.  `--fsync`
+
+    Cause the receiving side to fsync each finished file.  This may slow down
+    the transfer, but can help to provide peace of mind when updating critical
+    files.
+
 0.  `--write-batch=FILE`
 
     Record a file that can later be applied to another identical destination
index 1e1e40462430e6be8ae6e8a3b55e16110503fdba..ea2013d3cdcf589c313fe2e39885abcb7bd02863 100644 (file)
--- a/t_stub.c
+++ b/t_stub.c
@@ -21,6 +21,7 @@
 
 #include "rsync.h"
 
+int do_fsync = 0;
 int inplace = 0;
 int modify_window = 0;
 int preallocate_files = 0;
diff --git a/util1.c b/util1.c
index ef78a82d454c13320c05f04fa1fff27fba3635b0..1cff973ff6e4006edac231a4345946628d48f386 100644 (file)
--- a/util1.c
+++ b/util1.c
@@ -27,6 +27,7 @@
 
 extern int dry_run;
 extern int module_id;
+extern int do_fsync;
 extern int protect_args;
 extern int modify_window;
 extern int relative_paths;
@@ -417,10 +418,17 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode)
 #endif
        }
 
+       if (do_fsync && fsync(ofd) < 0) {
+               int save_errno = errno;
+               rsyserr(FERROR, errno, "fsync failed on %s", full_fname(dest));
+               close(ofd);
+               errno = save_errno;
+               return -1;
+       }
+
        if (close(ofd) < 0) {
                int save_errno = errno;
-               rsyserr(FERROR_XFER, errno, "close failed on %s",
-                       full_fname(dest));
+               rsyserr(FERROR_XFER, errno, "close failed on %s", full_fname(dest));
                errno = save_errno;
                return -1;
        }