X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=dss.c;fp=dss.c;h=b09fc961f28328eb9c7c6e95726fffa3b706de32;hb=e3f9c1dcc861be14fc9a3f33057a905047e9a926;hp=126c366d99f89b1c9ae5c1e5fb89672fd14f87b9;hpb=8255344c3fe023bde18aa06e0f860752445d0735;p=dss.git diff --git a/dss.c b/dss.c index 126c366..b09fc96 100644 --- a/dss.c +++ b/dss.c @@ -669,6 +669,50 @@ static struct snapshot *find_oldest_removable_snapshot(struct snapshot_list *sl) 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; @@ -701,7 +745,7 @@ static int try_to_free_disk_space(void) struct snapshot_list sl; struct snapshot *victim; struct timeval now; - const char *why; + char *why; int low_disk_space; ret = disk_space_low(NULL); @@ -712,55 +756,25 @@ static int try_to_free_disk_space(void) 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)