]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
- moved filesystem depended code new classes
authorArvin Schnell <aschnell@suse.de>
Fri, 29 Jul 2011 14:33:06 +0000 (16:33 +0200)
committerArvin Schnell <aschnell@suse.de>
Fri, 29 Jul 2011 14:33:06 +0000 (16:33 +0200)
- renamed baseDir to infoDir
- added some code for ext4 snapshots

12 files changed:
LIBVERSION
snapper/Compare.cc
snapper/File.cc
snapper/Filesystem.cc [new file with mode: 0644]
snapper/Filesystem.h [new file with mode: 0644]
snapper/Makefile.am
snapper/Snapper.cc
snapper/Snapper.h
snapper/SnapperDefines.h
snapper/Snapshot.cc
snapper/Snapshot.h
testsuite-real/common.cc

index 7dea76edb3dc51b6e5e8223e9f941a35c1e364d6..9084fa2f716a7117829f3f32a5f4cef400e02903 100644 (file)
@@ -1 +1 @@
-1.0.1
+1.1.0
index 02b6c1455d41385dc06f02c37be3aeccb7826076..9bb81a3603d5be170ba8b369c453632ac146a307 100644 (file)
@@ -238,7 +238,7 @@ namespace snapper
     bool
     filter(const string& name)
     {
-       if (name == "/snapshots")
+       if (name == "/.snapshots" || name == "/.snapshots-info")
            return true;
 
        return false;
index a4bf2c55561eccdd1cd3cbf1a581f87ec9f22174..da205120afe0c7bbd1765807bfa51c18129e182e 100644 (file)
@@ -119,6 +119,9 @@ namespace snapper
        if (getSnapper()->getCompareCallback())
            getSnapper()->getCompareCallback()->start();
 
+       comparison->getSnapshot1()->mountFilesystemSnapshot();
+       comparison->getSnapshot2()->mountFilesystemSnapshot();
+
 #if 1
        cmpdirs_cb_t cb = AppendHelper(comparison, entries);
 #else
@@ -154,7 +157,7 @@ namespace snapper
        if (invert)
            swap(num1, num2);
 
-       string input = getSnapper()->snapshotsDir() + "/" + decString(num2) + "/filelist-" +
+       string input = getSnapper()->infosDir() + "/" + decString(num2) + "/filelist-" +
            decString(num1) + ".txt";
 
        try
@@ -209,7 +212,7 @@ namespace snapper
        if (invert)
            swap(num1, num2);
 
-       string output = getSnapper()->snapshotsDir() + "/" + decString(num2) + "/filelist-" +
+       string output = getSnapper()->infosDir() + "/" + decString(num2) + "/filelist-" +
            decString(num1) + ".txt";
 
        string tmp_name = output + ".tmp-XXXXXX";
diff --git a/snapper/Filesystem.cc b/snapper/Filesystem.cc
new file mode 100644 (file)
index 0000000..d74fcda
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2011 Novell, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact Novell, Inc.
+ *
+ * To contact Novell about this file by physical or electronic mail, you may
+ * find current contact information at www.novell.com.
+ */
+
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "snapper/Filesystem.h"
+#include "snapper/Snapper.h"
+#include "snapper/SnapperTmpl.h"
+#include "snapper/SystemCmd.h"
+#include "snapper/SnapperDefines.h"
+
+
+namespace snapper
+{
+
+    string
+    Btrfs::infosDir() const
+    {
+       return snapper->subvolumeDir() + "/.snapshots";
+    }
+
+
+    string
+    Ext4::infosDir() const
+    {
+       return snapper->subvolumeDir() + "/.snapshots-info";
+    }
+
+
+    string
+    Btrfs::snapshotDir(unsigned int num) const
+    {
+       return snapper->subvolumeDir() + "/.snapshots/" + decString(num) + "/snapshot";
+    }
+
+
+    string
+    Ext4::snapshotDir(unsigned int num) const
+    {
+       return snapper->subvolumeDir() + "@" + decString(num);
+    }
+
+
+    void
+    Btrfs::createFilesystemSnapshot(unsigned int num) const
+    {
+       SystemCmd cmd(BTRFSBIN " subvolume snapshot " + snapper->subvolumeDir() + " " + snapshotDir(num));
+       if (cmd.retcode() != 0)
+           throw CreateSnapshotFailedException();
+    }
+
+
+    void
+    Ext4::createFilesystemSnapshot(unsigned int num) const
+    {
+       SystemCmd cmd1(TOUCHBIN " " "/mnt/.snapshots/" + decString(num));
+       if (cmd1.retcode() != 0)
+           throw CreateSnapshotFailedException();
+
+       SystemCmd cmd2(CHSNAPBIN " +S " "/mnt/.snapshots/" + decString(num));
+       if (cmd2.retcode() != 0)
+           throw CreateSnapshotFailedException();
+    }
+
+
+    void
+    Btrfs::deleteFilesystemSnapshot(unsigned int num) const
+    {
+       SystemCmd cmd(BTRFSBIN " subvolume delete " + snapshotDir(num));
+       if (cmd.retcode() != 0)
+           throw DeleteSnapshotFailedException();
+    }
+
+
+    void
+    Ext4::deleteFilesystemSnapshot(unsigned int num) const
+    {
+       // TODO
+    }
+
+
+    void
+    Btrfs::mountFilesystemSnapshot(unsigned int num) const
+    {
+    }
+
+
+    void
+    Ext4::mountFilesystemSnapshot(unsigned int num) const
+    {
+       SystemCmd cmd1(CHSNAPBIN " +n " "/mnt/.snapshots/" + decString(num));
+       if (cmd1.retcode() != 0)
+           throw CreateSnapshotFailedException();
+
+       mkdir(("/mnt@" + decString(num)).c_str(), 0666);
+
+       SystemCmd cmd2(MOUNTBIN " -t ext4 -r -o loop,noload " "/mnt/.snapshots/" + decString(num) + " "
+                      "/mnt@" + decString(num));
+       if (cmd2.retcode() != 0)
+           throw CreateSnapshotFailedException();
+    }
+
+
+    void
+    Btrfs::umountFilesystemSnapshot(unsigned int num) const
+    {
+    }
+
+
+    void
+    Ext4::umountFilesystemSnapshot(unsigned int num) const
+    {
+       // TODO
+    }
+
+
+    bool
+    Btrfs::checkFilesystemSnapshot(unsigned int num) const
+    {
+       return checkDir(snapshotDir(num));
+    }
+
+
+    bool
+    Ext4::checkFilesystemSnapshot(unsigned int num) const
+    {
+       // TODO
+
+       return true;
+    }
+
+}
diff --git a/snapper/Filesystem.h b/snapper/Filesystem.h
new file mode 100644 (file)
index 0000000..9afd969
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2011 Novell, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact Novell, Inc.
+ *
+ * To contact Novell about this file by physical or electronic mail, you may
+ * find current contact information at www.novell.com.
+ */
+
+
+#ifndef FILESYSTEM_H
+#define FILESYSTEM_H
+
+
+#include <string>
+
+
+namespace snapper
+{
+    using std::string;
+
+
+    class Snapper;
+
+
+    class Filesystem
+    {
+    public:
+
+       Filesystem(Snapper* snapper) : snapper(snapper) {}
+       virtual ~Filesystem() {}
+
+       virtual string name() const = 0;
+
+       virtual string infosDir() const = 0;
+       virtual string snapshotDir(unsigned int num) const = 0;
+
+       virtual void createFilesystemSnapshot(unsigned int num) const = 0;
+       virtual void deleteFilesystemSnapshot(unsigned int num) const = 0;
+
+       virtual void mountFilesystemSnapshot(unsigned int num) const = 0;
+       virtual void umountFilesystemSnapshot(unsigned int num) const = 0;
+
+       virtual bool checkFilesystemSnapshot(unsigned int num) const = 0;
+
+    protected:
+
+       Snapper* snapper;
+
+    };
+
+
+    class Btrfs : public Filesystem
+    {
+    public:
+
+       Btrfs(Snapper* snapper) : Filesystem(snapper) {}
+
+       virtual string name() const { return "btrfs"; }
+
+       virtual string infosDir() const;
+       virtual string snapshotDir(unsigned int num) const;
+
+       virtual void createFilesystemSnapshot(unsigned int num) const;
+       virtual void deleteFilesystemSnapshot(unsigned int num) const;
+
+       virtual void mountFilesystemSnapshot(unsigned int num) const;
+       virtual void umountFilesystemSnapshot(unsigned int num) const;
+
+       virtual bool checkFilesystemSnapshot(unsigned int num) const;
+
+    };
+
+
+    class Ext4 : public Filesystem
+    {
+    public:
+
+       Ext4(Snapper* snapper) : Filesystem(snapper) {}
+
+       virtual string name() const { return "ext4"; }
+
+       virtual string infosDir() const;
+       virtual string snapshotDir(unsigned int num) const;
+
+       virtual void createFilesystemSnapshot(unsigned int num) const;
+       virtual void deleteFilesystemSnapshot(unsigned int num) const;
+
+       virtual void mountFilesystemSnapshot(unsigned int num) const;
+       virtual void umountFilesystemSnapshot(unsigned int num) const;
+
+       virtual bool checkFilesystemSnapshot(unsigned int num) const;
+
+    };
+
+}
+
+
+#endif
index 8fd1d93a32aa4fae3ce96465f41e8c5d7adcbab2..a5e8252ae4c3abc0adbf41fbc0de439179d07254 100644 (file)
@@ -11,6 +11,7 @@ libsnapper_la_SOURCES =                                       \
        Snapper.cc              Snapper.h               \
        Snapshot.cc             Snapshot.h              \
        Comparison.cc           Comparison.h            \
+       Filesystem.cc           Filesystem.h            \
        File.cc                 File.h                  \
        XmlFile.cc              XmlFile.h               \
        Enum.cc                 Enum.h                  \
index 32086578f54e6d9d6d7ca9f2afac65d711a70be9..2099e068dc3f42a8b7379948cc30cc8d4b1edc77 100644 (file)
@@ -30,8 +30,8 @@
 #include "snapper/Snapper.h"
 #include "snapper/Comparison.h"
 #include "snapper/AppUtil.h"
-#include "snapper/XmlFile.h"
 #include "snapper/Enum.h"
+#include "snapper/Filesystem.h"
 #include "snapper/SnapperTmpl.h"
 #include "snapper/SystemCmd.h"
 #include "snapper/SnapperDefines.h"
@@ -46,8 +46,8 @@ namespace snapper
 
 
     Snapper::Snapper(const string& config_name, bool disable_filters)
-       : config_name(config_name), config(NULL), subvolume("/"), snapshots(this),
-         compare_callback(NULL), rollback_callback(NULL)
+       : config_name(config_name), config(NULL), subvolume("/"), filesystem(NULL),
+         snapshots(this), compare_callback(NULL), rollback_callback(NULL)
     {
        y2mil("Snapper constructor");
        y2mil("libsnapper version " VERSION);
@@ -69,6 +69,10 @@ namespace snapper
 
        y2mil("subvolume:" << subvolume);
 
+       filesystem = new Btrfs(this);
+
+       y2mil("filesystem:" << filesystem->name());
+
        if (!disable_filters)
            loadIgnorePatterns();
 
@@ -80,6 +84,7 @@ namespace snapper
     {
        y2mil("Snapper destructor");
 
+       delete filesystem;
        delete config;
     }
 
@@ -115,15 +120,13 @@ namespace snapper
     }
 
 
-    // Directory containing directories for all snapshots, e.g. "/snapshots"
-    // or "/home/snapshots".
+    // Directory that contains the per snapshot directory with info files.
+    // For btrfs e.g. "/.snapshots" or "/home/.snapshots".
+    // For ext4 e.g. "/.snapshots-info" or "/home/.snapshots-info".
     string
-    Snapper::snapshotsDir() const
+    Snapper::infosDir() const
     {
-       if (subvolumeDir() == "/")
-           return SNAPSHOTSDIR;
-       else
-           return subvolumeDir() + SNAPSHOTSDIR;
+       return filesystem->infosDir();
     }
 
 
@@ -174,6 +177,9 @@ namespace snapper
 
        y2mil("num1:" << snapshot1->getNum() << " num2:" << snapshot2->getNum());
 
+       snapshot1->mountFilesystemSnapshot();
+       snapshot2->mountFilesystemSnapshot();
+
        bool invert = snapshot1->getNum() > snapshot2->getNum();
 
        if (invert)
@@ -182,7 +188,7 @@ namespace snapper
        string dir1 = snapshot1->snapshotDir();
        string dir2 = snapshot2->snapshotDir();
 
-       string output = snapshot2->baseDir() + "/filelist-" + decString(snapshot1->getNum()) +
+       string output = snapshot2->infoDir() + "/filelist-" + decString(snapshot1->getNum()) +
            ".txt";
 
        SystemCmd(NICEBIN " -n 19 " IONICEBIN " -c 3 " COMPAREDIRSBIN " " + quote(dir1) + " " +
@@ -595,7 +601,7 @@ namespace snapper
            throw AddConfigFailedException("modifying config failed");
        }
 
-       SystemCmd cmd2(BTRFSBIN " subvolume create " + subvolume + SNAPSHOTSDIR);
+       SystemCmd cmd2(BTRFSBIN " subvolume create " + subvolume + "/.snapshots");
        if (cmd2.retcode() != 0)
        {
            throw AddConfigFailedException("creating snapshot failed");
index 53b4334377cb6d9c4461c52cea8267b07da114be..2f8eee00aa37b8752cf1632169df913c2a3d6cee 100644 (file)
@@ -35,6 +35,7 @@ namespace snapper
 
 
     class SysconfigFile;
+    class Filesystem;
 
 
     struct CompareCallback
@@ -109,7 +110,7 @@ namespace snapper
        ~Snapper();
 
        string subvolumeDir() const;
-       string snapshotsDir() const;
+       string infosDir() const;
 
        Snapshots& getSnapshots() { return snapshots; }
        const Snapshots& getSnapshots() const { return snapshots; }
@@ -141,6 +142,8 @@ namespace snapper
        static void addConfig(const string& config_name, const string& subvolume,
                              const string& template_name);
 
+       const Filesystem* getFilesystem() const { return filesystem; }
+
     private:
 
        void filter1(list<Snapshots::iterator>& tmp, time_t min_age);
@@ -154,6 +157,8 @@ namespace snapper
 
        string subvolume;
 
+       Filesystem* filesystem;
+
        vector<string> ignore_patterns;
 
        Snapshots snapshots;
index 51a2ba0dc38dfb095aada7d8dca4a28a21109816..e379142e2da32e0bd4f06397d8855e65dcaa6782 100644 (file)
 
 #define FILTERSDIR "/etc/snapper/filters"
 
-#define SNAPSHOTDIR "/snapshot"
-#define SNAPSHOTSDIR "/.snapshots"
-
 #define BTRFSBIN "/sbin/btrfs"
 
+#define CHSNAPBIN "/sbin/chsnap"
+
 #define COMPAREDIRSBIN "/usr/lib/snapper/bin/compare-dirs"
 
 #define NICEBIN "/usr/bin/nice"
 #define IONICEBIN "/usr/bin/ionice"
 
 #define CPBIN "/bin/cp"
-
+#define TOUCHBIN "/usr/bin/touch"
 #define DIFFBIN "/usr/bin/diff"
 
+#define MOUNTBIN "/bin/mount"
+
 
 #endif
index 3aed2ab7e3c512399b90cfe9ca31daf9515bacf3..73629633bed84c015a783256d4da9c826442d74a 100644 (file)
@@ -31,6 +31,7 @@
 #include "snapper/Snapper.h"
 #include "snapper/AppUtil.h"
 #include "snapper/XmlFile.h"
+#include "snapper/Filesystem.h"
 #include "snapper/Enum.h"
 #include "snapper/SnapperTmpl.h"
 #include "snapper/SystemCmd.h"
@@ -62,28 +63,32 @@ namespace snapper
     }
 
 
-    // Directory where the info file is saved, e.g. "/snapshots/1" or
-    // "/home/snapshots/1". Obviously not available for current.
+    // Directory where the info file is saved. Obviously not available for
+    // current.
+    // For btrfs e.g. "/.snapshots/1" or "/home/.snapshots/1".
+    // For ext4 e.g. "/.snapshots-info/1" or "/home/.snapshots-info/1".
     string
-    Snapshot::baseDir() const
+    Snapshot::infoDir() const
     {
        if (isCurrent())
            throw IllegalSnapshotException();
 
-       return snapper->snapshotsDir() + "/" + decString(num);
+       return snapper->infosDir() + "/" + decString(num);
     }
 
 
-    // Directory containing the actual snapshot, e.g. "/" or "/home" for
-    // current and "/snapshots/1/snapshot" or "/home/snapshots/1/snapshot"
+    // Directory containing the actual content of the snapshot.
+    // For btrfs , e.g. "/" or "/home" for current and
+    // "/.snapshots/1/snapshot" or "/home/.snapshots/1/snapshot" otherwise.
+    // For ext4 , e.g. "/" or "/home" for current and "/@1" or "/home@1"
     // otherwise.
     string
     Snapshot::snapshotDir() const
     {
-       if (num == 0)
+       if (isCurrent())
            return snapper->subvolumeDir();
-       else
-           return baseDir() + SNAPSHOTDIR;
+
+       return snapper->getFilesystem()->snapshotDir(num);
     }
 
 
@@ -106,11 +111,11 @@ namespace snapper
     void
     Snapshots::read()
     {
-       list<string> infos = glob(snapper->snapshotsDir() + "/*/info.xml", GLOB_NOSORT);
+       list<string> infos = glob(snapper->infosDir() + "/*/info.xml", GLOB_NOSORT);
        for (list<string>::const_iterator it = infos.begin(); it != infos.end(); ++it)
        {
            unsigned int num;
-           it->substr(snapper->snapshotsDir().length() + 1) >> num;
+           it->substr(snapper->infosDir().length() + 1) >> num;
 
            XmlFile file(*it);
            const xmlNode* root = file.getRootElement();
@@ -144,9 +149,9 @@ namespace snapper
 
            getChildValue(node, "cleanup", snapshot.cleanup);
 
-           if (!checkDir(snapshot.snapshotDir()))
+           if (!snapper->getFilesystem()->checkFilesystemSnapshot(num))
            {
-               y2err("snapshot directory does not exist. not adding snapshot " << num);
+               y2err("snapshot check failed. not adding snapshot " << num);
                continue;
            }
 
@@ -275,7 +280,7 @@ namespace snapper
            num = entries.rbegin()->num + 1;
 
        int r;
-       while ((r = mkdir((snapper->snapshotsDir() + "/" + decString(num)).c_str(), 0777)) == -1 &&
+       while ((r = mkdir((snapper->infosDir() + "/" + decString(num)).c_str(), 0777)) == -1 &&
               errno == EEXIST)
            ++num;
 
@@ -311,27 +316,37 @@ namespace snapper
        if (!cleanup.empty())
            setChildValue(node, "cleanup", cleanup);
 
-       xml.save(baseDir() + "/info.xml");
+       xml.save(infoDir() + "/info.xml");
 
        return true;
     }
 
 
+    void
+    Snapshot::mountFilesystemSnapshot() const
+    {
+       snapper->getFilesystem()->mountFilesystemSnapshot(num);
+    }
+
+
+    void
+    Snapshot::umountFilesystemSnapshot() const
+    {
+       snapper->getFilesystem()->umountFilesystemSnapshot(num);
+    }
+
+
     void
     Snapshot::createFilesystemSnapshot() const
     {
-       SystemCmd cmd(BTRFSBIN " subvolume snapshot " + snapper->subvolumeDir() + " " + snapshotDir());
-       if (cmd.retcode() != 0)
-           throw CreateSnapshotFailedException();
+       snapper->getFilesystem()->createFilesystemSnapshot(num);
     }
 
 
     void
     Snapshot::deleteFilesystemSnapshot() const
     {
-       SystemCmd cmd(BTRFSBIN " subvolume delete " + snapshotDir());
-       if (cmd.retcode() != 0)
-           throw DeleteSnapshotFailedException();
+       snapper->getFilesystem()->deleteFilesystemSnapshot(num);
     }
 
 
@@ -394,18 +409,18 @@ namespace snapper
 
        snapshot->deleteFilesystemSnapshot();
 
-       unlink((snapshot->baseDir() + "/info.xml").c_str());
+       unlink((snapshot->infoDir() + "/info.xml").c_str());
 
-       list<string> tmp1 = glob(snapshot->baseDir() + "/filelist-*.txt", GLOB_NOSORT);
+       list<string> tmp1 = glob(snapshot->infoDir() + "/filelist-*.txt", GLOB_NOSORT);
        for (list<string>::const_iterator it = tmp1.begin(); it != tmp1.end(); ++it)
            unlink(it->c_str());
 
-       list<string> tmp2 = glob(snapper->snapshotsDir() + "/*/filelist-" +
+       list<string> tmp2 = glob(snapper->infosDir() + "/*/filelist-" +
                                 decString(snapshot->getNum()) + ".txt", GLOB_NOSORT);
        for (list<string>::const_iterator it = tmp2.begin(); it != tmp2.end(); ++it)
            unlink(it->c_str());
 
-       rmdir(snapshot->baseDir().c_str());
+       rmdir(snapshot->infoDir().c_str());
 
        entries.erase(snapshot);
     }
index 82a11ee0ebc8101a89755ba4de6a723ac91a2f4e..c361e1435e7e2d2e584da8ee9d91885b63effab3 100644 (file)
@@ -78,9 +78,12 @@ namespace snapper
        void setCleanup(const string& cleanup);
        string getCleanup() const { return cleanup; }
 
-       string baseDir() const;
+       string infoDir() const;
        string snapshotDir() const;
 
+       void mountFilesystemSnapshot() const;
+       void umountFilesystemSnapshot() const;
+
        friend std::ostream& operator<<(std::ostream& s, const Snapshot& snapshot);
 
     private:
@@ -100,6 +103,7 @@ namespace snapper
        string cleanup;
 
        bool writeInfo() const;
+
        void createFilesystemSnapshot() const;
        void deleteFilesystemSnapshot() const;
 
index 3052a0e82478e7d280c937ca8bfa8166cff863b4..6e35ff32582d7b547ca91e988c1e7b65442928ec 100644 (file)
@@ -60,7 +60,7 @@ RollbackCallbackImpl rollback_callback_impl;
 void
 setup()
 {
-    system("/usr/bin/find " SUBVOLUME " -mindepth 1 -maxdepth 1 -not -path " SUBVOLUME SNAPSHOTSDIR " "
+    system("/usr/bin/find " SUBVOLUME " -mindepth 1 -maxdepth 1 -not -path " SUBVOLUME "/.snapshots "
           "-exec rm -r {} \\;");
 
     initDefaultLogger();