return ref;
}
+/* returns NULL <==> *reason is set to NULL */
+static struct snapshot *find_removable_snapshot(struct snapshot_list *sl,
+ bool try_hard, char **reason)
+{
+ struct snapshot *victim;
+
+ /*
+ * Don't remove anything if there is free space and we have fewer
+ * snapshots than configured, plus one. This way there is always one
+ * snapshot that can be recycled.
+ */
+ if (!try_hard && sl->num_snapshots <=
+ 1 << OPT_UINT32_VAL(DSS, NUM_INTERVALS))
+ goto nope;
+ victim = find_orphaned_snapshot(sl);
+ if (victim) {
+ *reason = make_message("orphaned");
+ return victim;
+ }
+ victim = find_outdated_snapshot(sl);
+ if (victim) {
+ *reason = make_message("outdated");
+ return victim;
+ }
+ if (!OPT_GIVEN(DSS, KEEP_REDUNDANT)) {
+ victim = find_redundant_snapshot(sl);
+ if (victim) {
+ *reason = make_message("redundant");
+ return victim;
+ }
+ }
+ if (!try_hard)
+ goto nope;
+ DSS_WARNING_LOG(("nothing obvious to remove\n"));
+ victim = find_oldest_removable_snapshot(sl);
+ if (victim) {
+ *reason = make_message("oldest");
+ return victim;
+ }
+nope:
+ *reason = NULL;
+ return NULL;
+}
+
static int rename_incomplete_snapshot(int64_t start)
{
char *old_name;
struct snapshot_list sl;
struct snapshot *victim;
struct timeval now;
- const char *why;
+ char *why;
int low_disk_space;
ret = disk_space_low(NULL);
if (tv_diff(&next_removal_check, &now, NULL) > 0)
return 0;
if (!low_disk_space) {
- if (OPT_GIVEN(DSS, KEEP_REDUNDANT))
- return 0;
if (snapshot_creation_status != HS_READY)
return 0;
if (next_snapshot_is_due())
return 0;
}
- /*
- * Idle and --keep_redundant not given, or low disk space. Look at
- * existing snapshots.
- */
+ /* Idle or low disk space, look at existing snapshots. */
dss_get_snapshot_list(&sl);
- ret = 0;
- /*
- * Don't remove anything if there is free space and we have fewer
- * snapshots than configured, plus one. This way there is always one
- * snapshot that can be recycled.
- */
- if (!low_disk_space && sl.num_snapshots <=
- 1 << OPT_UINT32_VAL(DSS, NUM_INTERVALS))
- goto out;
- why = "outdated";
- victim = find_outdated_snapshot(&sl);
- if (victim)
- goto remove;
- why = "redundant";
- victim = find_redundant_snapshot(&sl);
- if (victim)
- goto remove;
- why = "orphaned";
- victim = find_orphaned_snapshot(&sl);
+ victim = find_removable_snapshot(&sl, low_disk_space, &why);
+ if (victim) {
+ pre_remove_hook(victim, why);
+ free(why);
+ }
+ free_snapshot_list(&sl);
if (victim)
- goto remove;
- /* try harder only if disk space is low */
+ return 1;
if (!low_disk_space)
- goto out;
- DSS_WARNING_LOG(("disk space low and nothing obvious to remove\n"));
- why = "oldest";
- victim = find_oldest_removable_snapshot(&sl);
- if (victim)
- goto remove;
+ return 0;
DSS_CRIT_LOG(("uhuhu: disk space low and nothing to remove\n"));
- ret = -ERRNO_TO_DSS_ERROR(ENOSPC);
- goto out;
-remove:
- pre_remove_hook(victim, why);
-out:
- free_snapshot_list(&sl);
- return ret;
+ return -ERRNO_TO_DSS_ERROR(ENOSPC);
}
static void post_create_hook(void)