]> git.tuebingen.mpg.de Git - dss.git/commitdiff
Remove orphaned snapshots first if disk space is low.
authorAndre Noll <maan@systemlinux.org>
Fri, 29 May 2009 20:09:06 +0000 (22:09 +0200)
committerAndre Noll <maan@systemlinux.org>
Fri, 29 May 2009 20:09:06 +0000 (22:09 +0200)
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.

dss.c
snap.h

diff --git a/dss.c b/dss.c
index 3bcf60d4ba39d083f27bd26cb85998bb7a6eff69..61d5400ba925ae7e3171b7336ab51e21d11091f0 100644 (file)
--- 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 508bbf9312d9f2a343ac2af265799677a372c6a0..eca484a462b6d3ad77c23d75d5b0518058dd5057 100644 (file)
--- 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];
+}