From b76728084d7b36d55e08764c9de42ad59fd6f6fd Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Tue, 18 Feb 2014 14:16:02 +0100 Subject: [PATCH 1/1] Introduce --min-complete. 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 | 16 ++++++++++++---- dss.ggo | 20 ++++++++++++++++++++ snap.c | 10 ++++++++++ snap.h | 1 + 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/dss.c b/dss.c index 3a2f468..9f39324 100644 --- 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 2f50474..d8b956e 100644 --- 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 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 aef0c51..ec0449d 100644 --- 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 fc82850..c817de2 100644 --- 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. -- 2.39.2