]> git.tue.mpg.de Git - dss.git/commitdiff
Introduce --min-complete.
authorAndre Noll <maan@systemlinux.org>
Tue, 18 Feb 2014 13:16:02 +0000 (14:16 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Tue, 16 Sep 2014 16:26:36 +0000 (18:26 +0200)
Currently dss cowardly refuses to remove the last complete snapshot
even if disk space is low, and fails if there is not enough disk space
left for a second snapshot. However, in some situations it is more
important to have a recent snapshot and to to keep dss up and running.

This commit introduces a new integer option, --min-complete, which
defaults to one to resemble the old behaviour.

If it is set to zero, dss will happily remove the last complete
snapshot, even if it is used as the reference directory for rsync's
--link-dest option. This is dangerous, but it's the only way to keep
dss going.

Conversely, --min-complete may be set to a value greater than one
to guarantee there is always a certain number of complete snapshots
available.

dss.c
dss.ggo
snap.c
snap.h

diff --git a/dss.c b/dss.c
index 3a2f46886c310f23b987665854c99e75334e44b0..9f39324500ffa915af5e0c593ae7d56d40eb5062 100644 (file)
--- a/dss.c
+++ b/dss.c
@@ -531,17 +531,25 @@ static struct snapshot *find_outdated_snapshot(struct snapshot_list *sl)
 
 static struct snapshot *find_oldest_removable_snapshot(struct snapshot_list *sl)
 {
-       int i;
-       struct snapshot *s;
+       int i, num_complete;
+       struct snapshot *s, *ref = NULL;
+
+       num_complete = num_complete_snapshots(sl);
+       if (num_complete <= conf.min_complete_arg)
+               return NULL;
        FOR_EACH_SNAPSHOT(s, i, sl) {
                if (snapshot_is_being_created(s))
                        continue;
-               if (is_reference_snapshot(s))
+               if (is_reference_snapshot(s)) { /* avoid this one */
+                       ref = s;
                        continue;
+               }
                DSS_INFO_LOG(("oldest removable snapshot: %s\n", s->name));
                return s;
        }
-       return NULL;
+       assert(ref);
+       DSS_WARNING_LOG(("removing reference snapshot %s\n", ref->name));
+       return ref;
 }
 
 static int rename_incomplete_snapshot(int64_t start)
diff --git a/dss.ggo b/dss.ggo
index 2f50474f638b82dfe266a73ccb1870958c437a2a..d8b956e7e276fb5b9e0d4da75dab1351e9afe852 100644 (file)
--- a/dss.ggo
+++ b/dss.ggo
@@ -439,3 +439,23 @@ details="
        becomes low. Use this flag if the file system containing the
        destination directory is used for snapshots only.
 "
+
+option "min-complete" -
+#~~~~~~~~~~~~~~~~~~~~~~
+"Minimal number of complete snapshots to keep"
+int typestr = "num"
+default = "1"
+optional
+details = "
+       This option is only relevant if snapshots must be deleted
+       because disk space gets low.
+
+       dss refuses to remove old snapshots if there are fewer complete
+       snapshots left than the given number. The default value of one
+       guarantees that at least one complete snapshot is available
+       at all times.
+
+       If only <num> complete snapshot are left, and there is not
+       enough disk space available for another snapshot, the program
+       terminates with a \"No space left on device\" error.
+"
diff --git a/snap.c b/snap.c
index aef0c51203a26b35233ed811f0fb498aa5ec5967..ec0449d941c0296b5bb2b7f282a828b3c76d1196 100644 (file)
--- a/snap.c
+++ b/snap.c
@@ -232,3 +232,13 @@ __malloc char *name_of_newest_complete_snapshot(struct snapshot_list *sl)
        return name;
 }
 
+int num_complete_snapshots(struct snapshot_list *sl)
+{
+       struct snapshot *s;
+       int i, ret = 0;
+
+       FOR_EACH_SNAPSHOT(s, i, sl)
+               if (s->flags & SS_COMPLETE)
+                       ret++;
+       return ret;
+}
diff --git a/snap.h b/snap.h
index fc8285087c7a74e54353a5508b9f3b4458f7cb9b..c817de2b5ef75cb0ab0ad791362a9575844b524c 100644 (file)
--- a/snap.h
+++ b/snap.h
@@ -88,6 +88,7 @@ __malloc char *incomplete_name(int64_t start);
 __malloc char *being_deleted_name(struct snapshot *s);
 int complete_name(int64_t start, int64_t end, char **result);
 __malloc char *name_of_newest_complete_snapshot(struct snapshot_list *sl);
+int num_complete_snapshots(struct snapshot_list *sl);
 
 /**
  * Get the newest snapshot in a snapshot list.