]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
- extended space aware cleanup algorithm (fate#325774)
authorArvin Schnell <aschnell@suse.de>
Mon, 29 Oct 2018 09:48:28 +0000 (10:48 +0100)
committerArvin Schnell <aschnell@suse.de>
Mon, 29 Oct 2018 09:58:02 +0000 (10:58 +0100)
VERSION
client/cleanup.cc
client/snapper.cc
data/default-config
dists/debian/changelog
doc/snapper-configs.xml.in
doc/snapper.xml.in
package/snapper.changes

diff --git a/VERSION b/VERSION
index 7486fdbc50b3f93d9d04db440483984df5d1dcce..a3df0a6959e154733da89a5d6063742ce6d5b851 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.7.2
+0.8.0
index 1f630bd827815e3abac523762056c8ed61b825ff..07f27d8f53c07808a10b3d689652c38fdc4032ca 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "utils/Range.h"
 #include "utils/equal-date.h"
+#include "utils/HumanString.h"
 #include "cleanup.h"
 
 
@@ -46,6 +47,7 @@ struct Parameters
 
     time_t min_age;
     double space_limit;
+    double free_limit;
 
     template<typename Type>
     void read(const ProxyConfig& config, const char* name, Type& value)
@@ -59,11 +61,12 @@ struct Parameters
 
 
 Parameters::Parameters(const ProxySnapper* snapper)
-    : min_age(1800), space_limit(0.5)
+    : min_age(1800), space_limit(0.5), free_limit(0.2)
 {
     ProxyConfig config = snapper->getConfig();
 
     read(config, "SPACE_LIMIT", space_limit);
+    read(config, "FREE_LIMIT", free_limit);
 }
 
 
@@ -71,7 +74,8 @@ ostream&
 operator<<(ostream& s, const Parameters& parameters)
 {
     return s << "min-age:" << parameters.min_age << endl
-            << "space-limit:" << parameters.space_limit;
+            << "space-limit:" << parameters.space_limit
+            << "free-limit:" << parameters.free_limit;
 }
 
 
@@ -114,11 +118,20 @@ protected:
 
     void remove(const list<ProxySnapshots::iterator>& tmp);
 
+    // Should the cleanup with quota space be run?
     bool is_quota_aware() const;
+
+    // Is the quota space condition satisfied?
     bool is_quota_satisfied() const;
 
-    void cleanup_quota_unaware(ProxySnapshots& snapshots);
-    void cleanup_quota_aware(ProxySnapshots& snapshots);
+    // Should the cleanup with free space be run?
+    bool is_free_aware() const;
+
+    // Is the free space condition satisfied?
+    bool is_free_satisfied() const;
+
+    void cleanup(ProxySnapshots& snapshots);
+    void cleanup(ProxySnapshots& snapshots, std::function<bool()> condition);
 
     ProxySnapper* snapper;
     bool verbose;
@@ -223,41 +236,80 @@ Cleaner::is_quota_aware() const
     {
        snapper->prepareQuota();
     }
-    catch (const DBus::ErrorException& e)
+    catch (const QuotaException& e)
     {
        SN_CAUGHT(e);
 
-       if (strcmp(e.name(), "error.quota") == 0)
-       {
-           cerr << "quota not working (" << e.message() << ")" << endl;
-           return false;
-       }
+       cerr << "quota not working (" << e.what() << ")" << endl;
+       return false;
+    }
+
+    return parameters.space_limit < 1.0;
+}
+
+
+bool
+Cleaner::is_quota_satisfied() const
+{
+    QuotaData quota_data = snapper->queryQuotaData();
+
+    double fraction = (double)(quota_data.used) / (double)(quota_data.size);
+
+    bool satisfied = fraction < parameters.space_limit;
+
+#ifdef VERBOSE_LOGGING
+    cout << byte_to_humanstring(quota_data.size, 2) << ", "
+        << byte_to_humanstring(quota_data.used, 2) << ", "
+        << fraction << ", " << satisfied << endl;
+#endif
+
+    return satisfied;
+}
+
+
+bool
+Cleaner::is_free_aware() const
+{
+    if (parameters.is_degenerated())
+       return false;
 
-       SN_RETHROW(e);
+    try
+    {
+       snapper->queryFreeSpaceData();
     }
-    catch (const QuotaException& e)
+    catch (const FreeSpaceException& e)
     {
        SN_CAUGHT(e);
 
-       cerr << "quota not working (" << e.what() << ")" << endl;
+       cerr << "free space not working (" << e.what() << ")" << endl;
        return false;
     }
 
-    return true;
+    return parameters.free_limit > 0.0;
 }
 
 
 bool
-Cleaner::is_quota_satisfied() const
+Cleaner::is_free_satisfied() const
 {
-    QuotaData quota_data = snapper->queryQuotaData();
+    FreeSpaceData free_space_data = snapper->queryFreeSpaceData();
+
+    double fraction = (double)(free_space_data.free) / (double)(free_space_data.size);
 
-    return quota_data.used < parameters.space_limit * quota_data.size;
+    bool satisfied = fraction > parameters.free_limit;
+
+#ifdef VERBOSE_LOGGING
+    cout << byte_to_humanstring(free_space_data.size, 2) << ", "
+        << byte_to_humanstring(free_space_data.free, 2) << ", "
+        << fraction << ", " << satisfied << endl;
+#endif
+
+    return satisfied;
 }
 
 
 void
-Cleaner::cleanup_quota_unaware(ProxySnapshots& snapshots)
+Cleaner::cleanup(ProxySnapshots& snapshots)
 {
     list<ProxySnapshots::iterator> candidates = calculate_candidates(snapshots, Range::MAX);
 
@@ -268,14 +320,19 @@ Cleaner::cleanup_quota_unaware(ProxySnapshots& snapshots)
 
 
 void
-Cleaner::cleanup_quota_aware(ProxySnapshots& snapshots)
+Cleaner::cleanup(ProxySnapshots& snapshots, std::function<bool()> condition)
 {
-    while (!is_quota_satisfied())
+    while (!condition())
     {
        list<ProxySnapshots::iterator> candidates = calculate_candidates(snapshots, Range::MIN);
        if (candidates.empty())
        {
-           // not enough candidates to satisfy quota
+           // not enough candidates to satisfy the condition
+
+#ifdef VERBOSE_LOGGING
+           cout << "condition not satisfied" << endl;
+#endif
+
            return;
        }
 
@@ -293,17 +350,27 @@ Cleaner::cleanup_quota_aware(ProxySnapshots& snapshots)
            if (!tmp.empty())
            {
                remove(tmp);
-               // after removing snapshots is_quota_satisfied must be reevaluated
+
+               // after removing snapshots the condition must be reevaluated
                break;
            }
 
            if (next(e) == candidates.end())
            {
-               // not enough candidates to satisfy quota
+               // not enough candidates to satisfy the condition
+
+#ifdef VERBOSE_LOGGING
+               cout << "condition not satisfied" << endl;
+#endif
+
                return;
            }
        }
     }
+
+#ifdef VERBOSE_LOGGING
+    cout << "condition satisfied" << endl;
+#endif
 }
 
 
@@ -312,10 +379,41 @@ Cleaner::cleanup()
 {
     ProxySnapshots& snapshots = snapper->getSnapshots();
 
-    cleanup_quota_unaware(snapshots);
+#ifdef VERBOSE_LOGGING
+    cout << "cleanup without condition" << endl;
+#endif
+
+    cleanup(snapshots);
 
     if (is_quota_aware())
-       cleanup_quota_aware(snapshots);
+    {
+#ifdef VERBOSE_LOGGING
+       cout << "cleanup with quota condition" << endl;
+#endif
+
+       cleanup(snapshots, std::bind(&Cleaner::is_quota_satisfied, this));
+    }
+    else
+    {
+#ifdef VERBOSE_LOGGING
+       cout << "no cleanup with quota condition" << endl;
+#endif
+    }
+
+    if (is_free_aware())
+    {
+#ifdef VERBOSE_LOGGING
+       cout << "cleanup with free condition" << endl;
+#endif
+
+       cleanup(snapshots, std::bind(&Cleaner::is_free_satisfied, this));
+    }
+    else
+    {
+#ifdef VERBOSE_LOGGING
+       cout << "no cleanup with free condition" << endl;
+#endif
+    }
 }
 
 
index 31587c7732d5c8656a9a92b849f6b3ecb853d451..d809677d094a5a19df3782b3080bf10e8a0faae9 100644 (file)
@@ -1833,6 +1833,12 @@ main(int argc, char** argv)
        cerr << sformat(_("Quota error (%s)."), e.what()) << endl;
        exit(EXIT_FAILURE);
     }
+    catch (const FreeSpaceException& e)
+    {
+       SN_CAUGHT(e);
+       cerr << sformat(_("Free space error (%s)."), e.what()) << endl;
+       exit(EXIT_FAILURE);
+    }
     catch (const Exception& e)
     {
        SN_CAUGHT(e);
index 16c11f9cbce73246c483af5a92cb57602b659060..a1e1900a394969d5de851383c4630a31b5209446 100644 (file)
@@ -13,6 +13,9 @@ QGROUP=""
 # fraction of the filesystems space the snapshots may use
 SPACE_LIMIT="0.5"
 
+# fraction of the filesystems space that should be free
+FREE_LIMIT="0.2"
+
 
 # users and groups allowed to work with config
 ALLOW_USERS=""
index 1dd9c9f44d91b2ccec462b5b916d6394786ea611..ae49a12647d28b781f82da71c898d3c8bf5f4861 100644 (file)
@@ -1,3 +1,9 @@
+snapper (0.8.0) stable; urgency=low
+
+  * Updated to version 0.8.0
+
+ -- Arvin Schnell <aschnell@suse.com>  Mon, 29 Oct 2018 09:02:13 +0100
+
 snapper (0.7.2) stable; urgency=low
 
   * Updated to version 0.7.2
index 3ee8293e7b410d5833276f7d34d8d8547320097b..e81f101aeaa6075a5b8c1005255f1d295dfceb08 100644 (file)
@@ -2,13 +2,13 @@
 <refentry id='snapper-configs5'>
 
   <refentryinfo>
-    <date>2014-05-20</date>
+    <date>2018-10-29</date>
   </refentryinfo>
 
   <refmeta>
     <refentrytitle>snapper-configs</refentrytitle>
     <manvolnum>5</manvolnum>
-    <refmiscinfo class='date'>2013-07-09</refmiscinfo>
+    <refmiscinfo class='date'>2018-10-29</refmiscinfo>
     <refmiscinfo class='version'>@VERSION@</refmiscinfo>
     <refmiscinfo class='manual'>Filesystem Snapshot Management</refmiscinfo>
   </refmeta>
        </listitem>
       </varlistentry>
 
+      <varlistentry>
+       <term><option>FREE_LIMIT=<replaceable>float</replaceable></option></term>
+       <listitem>
+         <para>Limit for the fraction of the filesystem space that
+         should be free.</para>
+         <para>Only supported for btrfs.</para>
+         <para>Default value is &quot;0.2&quot;.</para>
+         <para>New in version 0.8.0.</para>
+       </listitem>
+      </varlistentry>
+
       <varlistentry>
        <term><option>ALLOW_USERS=<replaceable>users</replaceable></option></term>
        <listitem>
index 5be5074d29001dbc5647c69104f94c19d43c3b9d..87942a0774bd2fffeee557f9a658fe5a78f90834 100644 (file)
@@ -2,13 +2,13 @@
 <refentry id='snapper8'>
 
   <refentryinfo>
-    <date>2018-10-16</date>
+    <date>2018-10-29</date>
   </refentryinfo>
 
   <refmeta>
     <refentrytitle>snapper</refentrytitle>
     <manvolnum>8</manvolnum>
-    <refmiscinfo class='date'>2018-10-16</refmiscinfo>
+    <refmiscinfo class='date'>2018-10-29</refmiscinfo>
     <refmiscinfo class='version'>@VERSION@</refmiscinfo>
     <refmiscinfo class='manual'>Filesystem Snapshot Management</refmiscinfo>
   </refmeta>
        </glossentry>
       </glosslist>
 
-      <para>The number and timeline cleanup algorithm can also try to keep the
-      space used by snapshots below a limit. For that quota must be setup, see
-      command setup-quota, and the LIMIT variables in the config file must
-      have ranges (min- and max-value). The algorithms will then make two
-      passes:
+      <para>The number and timeline cleanup algorithms can also try to
+      keep the space used by snapshots below a limit and the free space of
+      the filesystem above a limit. For the first condition quota must be
+      setup, see command setup-quota. Additional the NUMBER_LIMIT and
+      TIMELINE_LIMIT variables in the config file must have ranges (min- and
+      max-value). The algorithms will then make two passes:
+
       <orderedlist>
        <listitem>
-         <para>Delete snapshots above the max-value independent of the used
-         space.</para>
+         <para>Delete snapshots above the max-value independent of
+         the snapshot and filesystem space.</para>
        </listitem>
        <listitem>
-         <para>Delete snapshots above the min-value until the limit for
-         the used space is reached.</para>
+         <para>Delete snapshots above the min-value until the limits for
+         the snapshot and filesystem are reached.</para>
        </listitem>
       </orderedlist>
-      The limit for the used space can be configured via the SPACE_LIMIT
-      variable. Note: Only snapshots that have a cleanup algorithm set are
-      taken into account when calculating the used space.
+
+      The limit for the used space can be configured via the
+      SPACE_LIMIT variable. Note: Only snapshots that have a cleanup
+      algorithm set are taken into account when calculating the space
+      used by snapshots.
+
+      The limit for the free space can be configured via the
+      FREE_LIMIT variable.
+
       </para>
 
     </refsect2>
index bb25f365a8a30f02f6676b1c222dbcb665f15b88..2b8ffcff86159d17c0ceb8159ddba9b48265f836 100644 (file)
@@ -1,3 +1,10 @@
+-------------------------------------------------------------------
+Mon Oct 29 10:38:59 CET 2018 - aschnell@suse.com
+
+- extended space aware cleanup algorithm to ensure minimal
+  free space for btrfs (within known ranges) (fate#325774)
+- version 0.8.0
+
 -------------------------------------------------------------------
 Mon Oct 22 09:52:01 CEST 2018 - aschnell@suse.com