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)
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.
+"
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;
+}
__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.