]> git.tuebingen.mpg.de Git - dss.git/blobdiff - dss.c
Remove orphaned snapshots first if disk space is low.
[dss.git] / dss.c
diff --git a/dss.c b/dss.c
index 27c14b6720d47fc88721c7bd25765affc791daa9..61d5400ba925ae7e3171b7336ab51e21d11091f0 100644 (file)
--- a/dss.c
+++ b/dss.c
@@ -185,8 +185,8 @@ static int next_snapshot_is_due(void)
                goto out;
        }
 
-       tv_divide(wanted, &diff, &tmp); /* sleep time betweeen two snapshots */
-       diff.tv_sec = s->completion_time; /* completion time of the the latest snaphot */
+       tv_divide(wanted, &diff, &tmp); /* sleep time between two snapshots */
+       diff.tv_sec = s->completion_time; /* completion time of the latest snapshot */
        diff.tv_usec = 0;
        tv_add(&diff, &tmp, &next_snapshot_time);
        ret = (tv_diff(&now, &next_snapshot_time, &diff) < 0)? 0 : 1;
@@ -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)
@@ -641,7 +682,12 @@ static int handle_rsync_exit(int status)
                goto out;
        }
        es = WEXITSTATUS(status);
-       if (es == 13) { /* Errors with program diagnostics */
+       /*
+        * Restart rsync on non-fatal errors:
+        * 12: Error in rsync protocol data stream
+        * 13: Errors with program diagnostics
+        */
+       if (es == 12 || es == 13) {
                DSS_WARNING_LOG("rsync process %d returned %d -- restarting\n",
                        (int)create_pid, es);
                snapshot_creation_status = HS_NEEDS_RESTART;