From: Andre Noll Date: Fri, 29 May 2009 20:09:06 +0000 (+0200) Subject: Remove orphaned snapshots first if disk space is low. X-Git-Tag: v0.1.3~8 X-Git-Url: http://git.tuebingen.mpg.de/?p=dss.git;a=commitdiff_plain;h=0cea2bfa14a7641e6e8e88c177cdb3d10099596d Remove orphaned snapshots first if disk space is low. If the dss process gets killed, an orphaned snapshot might result. Detect this case and prefer to remove such orphaned snapshots before resorting to remove the oldest snapshot. --- diff --git a/dss.c b/dss.c index 3bcf60d..61d5400 100644 --- a/dss.c +++ b/dss.c @@ -277,6 +277,44 @@ static int snapshot_is_being_created(struct snapshot *s) return s->creation_time == current_snapshot_creation_time; } +static int remove_orphaned_snapshot(struct snapshot_list *sl) +{ + struct snapshot *s; + int i, ret; + + DSS_DEBUG_LOG("looking for orphaned snapshots\n"); + FOR_EACH_SNAPSHOT(s, i, sl) { + if (snapshot_is_being_created(s)) + continue; + /* + * We know that no rm is currently running, so if s is marked + * as being deleted, a previously started rm must have failed. + */ + if (s->flags & SS_BEING_DELETED) + goto remove; + + if (s->flags & SS_COMPLETE) /* good snapshot */ + continue; + /* + * This snapshot is incomplete and it is not the snapshot + * currently being created. However, we must not remove it if + * rsync is about to be restarted. As only the newest snapshot + * can be restarted, this snapshot is orphaned if it is not the + * newest snapshot or if we are not about to restart rsync. + */ + if (get_newest_snapshot(sl) != s) + goto remove; + if (snapshot_creation_status != HS_NEEDS_RESTART) + goto remove; + } + return 0; /* no orphaned snapshots */ +remove: + ret = pre_remove_hook(s, "orphaned"); + if (ret < 0) + return ret; + return 1; +} + /* * return: 0: no redundant snapshots, 1: rm process started, negative: error */ @@ -422,6 +460,9 @@ static int try_to_free_disk_space(int low_disk_space) ret = 0; if (!low_disk_space) goto out; + ret = remove_orphaned_snapshot(&sl); + if (ret) + goto out; DSS_WARNING_LOG("disk space low and nothing obvious to remove\n"); ret = remove_oldest_snapshot(&sl); if (ret) diff --git a/snap.h b/snap.h index 508bbf9..eca484a 100644 --- a/snap.h +++ b/snap.h @@ -98,3 +98,13 @@ _static_inline_ struct snapshot *get_oldest_snapshot(struct snapshot_list *sl) return NULL; return sl->snapshots[0]; } + +/** + * Get the newest snapshot in a snapshot list. + */ +_static_inline_ struct snapshot *get_newest_snapshot(struct snapshot_list *sl) +{ + if (!sl->num_snapshots) + return NULL; + return sl->snapshots[sl->num_snapshots - 1]; +}