Don't create two snapshots in the same second.
authorAndre Noll <maan@systemlinux.org>
Mon, 1 Oct 2012 17:10:02 +0000 (19:10 +0200)
committerAndre Noll <maan@systemlinux.org>
Mon, 1 Oct 2012 17:10:02 +0000 (19:10 +0200)
This can only happen if all of the follwing are true:

(a) source and destination directories are small
(b) rsync completes successfully within one second
(c) At most two snapshots are missing

In this case the rename() call which changes the snapshot name from
*-incomplete to the proper name fails for the second snapshot with
EEXIST. This is because the previous snapshot name coincides with
the name of the second snapshot.

The fix is a bit ugly but also non-invasive and simple: Just sleep
one second in this case.

dss.c

diff --git a/dss.c b/dss.c
index 7620cfee1733d55ef99baaf956e11089db9b40d6..354bdb847095d0dd2b6a2346b9bdceaae7977d0d 100644 (file)
--- a/dss.c
+++ b/dss.c
@@ -548,10 +548,17 @@ static int rename_incomplete_snapshot(int64_t start)
 {
        char *old_name;
        int ret;
 {
        char *old_name;
        int ret;
+       int64_t now;
 
 
+       /*
+        * We don't want the dss_rename() below to fail with EEXIST because the
+        * last complete snapshot was created (and completed) in the same
+        * second as this one.
+        */
+       while ((now = get_current_time()) == start)
+               sleep(1);
        free(path_to_last_complete_snapshot);
        free(path_to_last_complete_snapshot);
-       ret = complete_name(start, get_current_time(),
-               &path_to_last_complete_snapshot);
+       ret = complete_name(start, now, &path_to_last_complete_snapshot);
        if (ret < 0)
                return ret;
        old_name = incomplete_name(start);
        if (ret < 0)
                return ret;
        old_name = incomplete_name(start);