From: Arvin Schnell Date: Wed, 2 Apr 2014 09:59:35 +0000 (+0200) Subject: - added some functions for rollback (fate #317062) X-Git-Tag: v0.2.2~11^2~1 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=8815ea07c12e4224a0f8d4497f2bb4e3a60de328;p=thirdparty%2Fsnapper.git - added some functions for rollback (fate #317062) --- diff --git a/snapper/Btrfs.cc b/snapper/Btrfs.cc index 8bfc8752..695bd662 100644 --- a/snapper/Btrfs.cc +++ b/snapper/Btrfs.cc @@ -51,6 +51,7 @@ #include "snapper/SnapperTmpl.h" #include "snapper/SnapperDefines.h" #include "snapper/Acls.h" +#include "snapper/Regex.h" namespace snapper @@ -1225,6 +1226,79 @@ namespace snapper #endif +#ifdef ENABLE_ROLLBACK + + unsigned int + Btrfs::getDefault() const + { + try + { + SDir subvolume_dir = openSubvolumeDir(); + unsigned long long id = get_default_id(subvolume_dir.fd()); + string name = get_subvolume(subvolume_dir.fd(), id); + + if (name.empty()) + return 0; + + Regex rx("^.snapshots/([0-9]*)/snapshot"); + if (!rx.match(name)) + throw IOErrorException(); + + int num = 0; + rx.cap(1) >> num; + return num; + } + catch (const runtime_error& e) + { + throw IOErrorException(); + } + } + + + void + Btrfs::setDefault(unsigned int num) const + { + try + { + if (num == 0) + { + SDir subvolume_dir = openSubvolumeDir(); + unsigned long long id = get_id(subvolume_dir.fd()); + set_default_id(subvolume_dir.fd(), id); + } + else + { + SDir snapshot_dir = openSnapshotDir(num); + unsigned long long id = get_id(snapshot_dir.fd()); + + SDir subvolume_dir = openSubvolumeDir(); + set_default_id(subvolume_dir.fd(), id); + } + } + catch (const runtime_error& e) + { + throw IOErrorException(); + } + } + +#else + + unsigned int + Btrfs::getDefault() const + { + throw std::logic_error("not implemented"); + } + + + void + Btrfs::setDefault(unsigned int num) const + { + throw std::logic_error("not implemented"); + } + +#endif + + #ifdef ENABLE_ROLLBACK void diff --git a/snapper/Btrfs.h b/snapper/Btrfs.h index fe779107..bcfe153a 100644 --- a/snapper/Btrfs.h +++ b/snapper/Btrfs.h @@ -60,6 +60,9 @@ namespace snapper virtual void cmpDirs(const SDir& dir1, const SDir& dir2, cmpdirs_cb_t cb) const; + virtual unsigned int getDefault() const; + virtual void setDefault(unsigned int num) const; + private: void addToFstab() const; diff --git a/snapper/BtrfsUtils.cc b/snapper/BtrfsUtils.cc index c0b9e99f..fb44cb6d 100644 --- a/snapper/BtrfsUtils.cc +++ b/snapper/BtrfsUtils.cc @@ -69,10 +69,15 @@ struct btrfs_ioctl_vol_args_v2 #endif +#ifndef BTRFS_IOC_SUBVOL_GETFLAGS +#define BTRFS_IOC_SUBVOL_GETFLAGS _IOR(BTRFS_IOCTL_MAGIC, 25, __u64) +#endif + namespace snapper { + // See btrfsprogs source code for references. @@ -84,6 +89,17 @@ namespace snapper bool + is_subvolume_read_only(int fd, bool& read_only) + { + __u64 flags; + if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) != 0) + throw runtime_error_with_errno("ioctl(BTRFS_IOC_SUBVOL_GETFLAGS) failed", errno); + + return flags & BTRFS_SUBVOL_RDONLY; + } + + + void create_subvolume(int fddst, const string& name) { struct btrfs_ioctl_vol_args args; @@ -137,6 +153,50 @@ namespace snapper #ifdef ENABLE_ROLLBACK + void + set_default_id(int fd, unsigned long long id) + { + if (ioctl(fd, BTRFS_IOC_DEFAULT_SUBVOL, &id) != 0) + throw runtime_error_with_errno("ioctl(BTRFS_IOC_DEFAULT_SUBVOL) failed", errno); + } + + + unsigned long long + get_default_id(int fd) + { + struct btrfs_ioctl_search_args args; + memset(&args, 0, sizeof(args)); + + struct btrfs_ioctl_search_key* sk = &args.key; + sk->tree_id = BTRFS_ROOT_TREE_OBJECTID; + sk->nr_items = 1; + sk->max_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID; + sk->min_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID; + sk->max_type = BTRFS_DIR_ITEM_KEY; + sk->min_type = BTRFS_DIR_ITEM_KEY; + sk->max_offset = (__u64) -1; + sk->max_transid = (__u64) -1; + + if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) != 0) + throw runtime_error_with_errno("ioctl(BTRFS_IOC_TREE_SEARCH) failed", errno); + + if (sk->nr_items == 0) + throw std::runtime_error("sk->nr_items == 0"); + + struct btrfs_ioctl_search_header* sh = (struct btrfs_ioctl_search_header*) args.buf; + if (sh->type != BTRFS_DIR_ITEM_KEY) + throw std::runtime_error("sh->type != BTRFS_DIR_ITEM_KEY"); + + struct btrfs_dir_item* di = (struct btrfs_dir_item*)(sh + 1); + int name_len = btrfs_stack_dir_name_len(di); + const char* name = (const char*)(di + 1); + if (strncmp("default", name, name_len) != 0) + throw std::runtime_error("name != default"); + + return btrfs_disk_key_objectid(&di->location); + } + + string get_subvolume(int fd, unsigned long long id) { diff --git a/snapper/BtrfsUtils.h b/snapper/BtrfsUtils.h index f12ad113..cb49702f 100644 --- a/snapper/BtrfsUtils.h +++ b/snapper/BtrfsUtils.h @@ -34,10 +34,15 @@ namespace snapper bool is_subvolume(const struct stat& stat); + bool is_subvolume_read_only(int fd); + void create_subvolume(int fddst, const string& name); void create_snapshot(int fd, int fddst, const string& name, bool read_only); void delete_subvolume(int fd, const string& name); + void set_default_id(int fd, unsigned long long id); + unsigned long long get_default_id(int fd); + string get_subvolume(int fd, unsigned long long id); unsigned long long get_id(int fd); diff --git a/snapper/Filesystem.cc b/snapper/Filesystem.cc index 8e6bfa39..a56c5015 100644 --- a/snapper/Filesystem.cc +++ b/snapper/Filesystem.cc @@ -144,4 +144,18 @@ namespace snapper snapper::cmpDirs(dir1, dir2, cb); } + + unsigned int + Filesystem::getDefault() const + { + throw std::logic_error("not implemented"); + } + + + void + Filesystem::setDefault(unsigned int num) const + { + throw std::logic_error("not implemented"); + } + } diff --git a/snapper/Filesystem.h b/snapper/Filesystem.h index 3958f551..6521abc7 100644 --- a/snapper/Filesystem.h +++ b/snapper/Filesystem.h @@ -72,6 +72,9 @@ namespace snapper virtual void cmpDirs(const SDir& dir1, const SDir& dir2, cmpdirs_cb_t cb) const; + virtual unsigned int getDefault() const; + virtual void setDefault(unsigned int num) const; + protected: const string subvolume;