From: Arvin Schnell Date: Tue, 5 May 2015 13:00:37 +0000 (+0200) Subject: - added option --sync to delete command (fate#317066) X-Git-Tag: v0.2.8~12^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3aa3cfaf989a907f79dc813a6097d30c4176f246;p=thirdparty%2Fsnapper.git - added option --sync to delete command (fate#317066) --- diff --git a/client/commands.cc b/client/commands.cc index c046ab17..b45eb45a 100644 --- a/client/commands.cc +++ b/client/commands.cc @@ -381,6 +381,18 @@ command_get_xfiles(DBus::Connection& conn, const string& config_name, unsigned i } +void +command_xsync(DBus::Connection& conn, const string& config_name) +{ + DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "Sync"); + + DBus::Hoho hoho(call); + hoho << config_name; + + conn.send_with_reply_and_block(call); +} + + vector command_xdebug(DBus::Connection& conn) { diff --git a/client/commands.h b/client/commands.h index 1805c4b9..f7d799cd 100644 --- a/client/commands.h +++ b/client/commands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2012-2014] Novell, Inc. + * Copyright (c) [2012-2015] Novell, Inc. * * All Rights Reserved. * @@ -115,5 +115,8 @@ list command_get_xfiles(DBus::Connection& conn, const string& config_name, unsigned int number1, unsigned int number2); +void +command_xsync(DBus::Connection& conn, const string& config_name); + vector command_xdebug(DBus::Connection& conn); diff --git a/client/snapper.cc b/client/snapper.cc index 51b3534a..f7bd59a4 100644 --- a/client/snapper.cc +++ b/client/snapper.cc @@ -844,7 +844,6 @@ command_modify(DBus::Connection* conn, Snapper* snapper) }; GetOpts::parsed_opts opts = getopts.parse("modify", options); - if (!getopts.hasArgs()) { cerr << _("Command 'modify' needs at least one argument.") << endl; @@ -878,6 +877,9 @@ help_delete() { cout << _(" Delete snapshot:") << endl << _("\tsnapper delete ") << endl + << endl + << _(" Options for 'delete' command:") << endl + << _("\t--sync, -s\t\t\tSync after deletion.") << endl << endl; } @@ -885,13 +887,25 @@ help_delete() void command_delete(DBus::Connection* conn, Snapper* snapper) { - getopts.parse("delete", GetOpts::no_options); + const struct option options[] = { + { "sync", no_argument, 0, 's' }, + { 0, 0, 0, 0 } + }; + + GetOpts::parsed_opts opts = getopts.parse("delete", options); if (!getopts.hasArgs()) { cerr << _("Command 'delete' needs at least one argument.") << endl; exit(EXIT_FAILURE); } + bool sync = false; + + GetOpts::parsed_opts::const_iterator opt; + + if ((opt = opts.find("sync")) != opts.end()) + sync = true; + XSnapshots snapshots = command_list_xsnapshots(*conn, config_name); list nums; @@ -924,6 +938,9 @@ command_delete(DBus::Connection* conn, Snapper* snapper) } command_delete_xsnapshots(*conn, config_name, nums); + + if (sync) + command_xsync(*conn, config_name); } @@ -1088,7 +1105,6 @@ command_diff(DBus::Connection* conn, Snapper* snapper) }; GetOpts::parsed_opts opts = getopts.parse("diff", options); - if (getopts.numArgs() < 1) { cerr << _("Command 'diff' needs at least one argument.") << endl; @@ -1472,7 +1488,6 @@ void command_xa_diff(DBus::Connection* conn, Snapper* snapper) { GetOpts::parsed_opts opts = getopts.parse("xadiff", GetOpts::no_options); - if (getopts.numArgs() < 1) { cerr << _("Command 'xadiff' needs at least one argument.") << endl; diff --git a/doc/dbus-protocol.txt b/doc/dbus-protocol.txt index dfbf41e6..8df609be 100644 --- a/doc/dbus-protocol.txt +++ b/doc/dbus-protocol.txt @@ -42,6 +42,8 @@ method GetMountPoint config-name number Snapshots mounted with user-request set to false will be unmounted (delayed) after the client disconnects. +method Sync config-name + method CreateComparison config-name number1 number2 method DeleteComparison config-name number1 number2 diff --git a/doc/snapper.xml.in b/doc/snapper.xml.in index 3b0061dc..4b000d04 100644 --- a/doc/snapper.xml.in +++ b/doc/snapper.xml.in @@ -409,6 +409,18 @@ number1-number2 Delete a snapshot or a range of snapshots. + + + + + Sync the filesystem after deleting the snapshots. The + details depend on the filesystem type. + Btrfs normally asynchronously frees space after deleting + snapshots. With this option snapper will wait until the space once used by the + deleted snapshots is actually available again. + + + diff --git a/package/snapper.changes b/package/snapper.changes index c00311df..c6adbf79 100644 --- a/package/snapper.changes +++ b/package/snapper.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Tue May 05 14:08:03 CEST 2015 - aschnell@suse.de + +- added option --sync to delete command (fate#317066) + ------------------------------------------------------------------- Tue Apr 14 17:58:17 CEST 2015 - aschnell@suse.de diff --git a/server/Client.cc b/server/Client.cc index ab6b803a..dccf6418 100644 --- a/server/Client.cc +++ b/server/Client.cc @@ -1287,6 +1287,30 @@ Client::get_files(DBus::Connection& conn, DBus::Message& msg) } +void +Client::sync(DBus::Connection& conn, DBus::Message& msg) +{ + string config_name; + + DBus::Hihi hihi(msg); + hihi >> config_name; + + y2deb("Sync config_name:" << config_name); + + MetaSnappers::iterator it = meta_snappers.find(config_name); + + check_permission(conn, msg, *it); + + Snapper* snapper = it->getSnapper(); + + snapper->syncFilesystem(); + + DBus::MessageMethodReturn reply(msg); + + conn.send(reply); +} + + void Client::debug(DBus::Connection& conn, DBus::Message& msg) const { @@ -1403,6 +1427,8 @@ Client::dispatch(DBus::Connection& conn, DBus::Message& msg) delete_comparison(conn, msg); else if (msg.is_method_call(INTERFACE, "GetFiles")) get_files(conn, msg); + else if (msg.is_method_call(INTERFACE, "Sync")) + sync(conn, msg); else if (msg.is_method_call(INTERFACE, "Debug")) debug(conn, msg); else diff --git a/server/Client.h b/server/Client.h index 267d0d94..b24e66f2 100644 --- a/server/Client.h +++ b/server/Client.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2012-2014] Novell, Inc. + * Copyright (c) [2012-2015] Novell, Inc. * * All Rights Reserved. * @@ -104,6 +104,7 @@ public: void create_comparison(DBus::Connection& conn, DBus::Message& msg); void delete_comparison(DBus::Connection& conn, DBus::Message& msg); void get_files(DBus::Connection& conn, DBus::Message& msg); + void sync(DBus::Connection& conn, DBus::Message& msg); void debug(DBus::Connection& conn, DBus::Message& msg) const; void dispatch(DBus::Connection& conn, DBus::Message& msg); diff --git a/snapper/Btrfs.cc b/snapper/Btrfs.cc index 83510b78..bf5560ed 100644 --- a/snapper/Btrfs.cc +++ b/snapper/Btrfs.cc @@ -305,7 +305,7 @@ namespace snapper Btrfs::createSnapshotOfDefault(unsigned int num, bool read_only) const { SDir subvolume_dir = openSubvolumeDir(); - unsigned long long id = get_default_id(subvolume_dir.fd()); + subvolid_t id = get_default_id(subvolume_dir.fd()); string name = get_subvolume(subvolume_dir.fd(), id); bool found = false; @@ -352,7 +352,11 @@ namespace snapper try { + subvolid_t subvolid = get_id(openSnapshotDir(num).fd()); + delete_subvolume(info_dir.fd(), "snapshot"); + + deleted_subvolids.push_back(subvolid); } catch (const runtime_error& e) { @@ -1359,13 +1363,13 @@ namespace snapper if (num == 0) { SDir subvolume_dir = openSubvolumeDir(); - unsigned long long id = get_id(subvolume_dir.fd()); + subvolid_t 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()); + subvolid_t id = get_id(snapshot_dir.fd()); SDir subvolume_dir = openSubvolumeDir(); set_default_id(subvolume_dir.fd(), id); @@ -1389,6 +1393,28 @@ namespace snapper #endif + void + Btrfs::sync() const + { + SDir subvolume_dir = openSubvolumeDir(); + + BtrfsUtils::sync(subvolume_dir.fd()); + + if (!deleted_subvolids.empty()) + { + for (subvolid_t subvolid : deleted_subvolids) + { + while (!does_subvolume_exist(subvolume_dir.fd(), subvolid)) + sleep(1); + } + + deleted_subvolids.clear(); + + BtrfsUtils::sync(subvolume_dir.fd()); + } + } + + #ifdef ENABLE_ROLLBACK class MntTable diff --git a/snapper/Btrfs.h b/snapper/Btrfs.h index b0e10014..2d45e25e 100644 --- a/snapper/Btrfs.h +++ b/snapper/Btrfs.h @@ -31,6 +31,9 @@ namespace snapper { + using namespace BtrfsUtils; + + class Btrfs : public Filesystem { public: @@ -73,10 +76,14 @@ namespace snapper virtual void setDefault(unsigned int num) const; + virtual void sync() const; + private: qgroup_t qgroup; + mutable vector deleted_subvolids; + void addToFstabHelper(const string& default_subvolume_name) const; void removeFromFstabHelper() const; diff --git a/snapper/BtrfsUtils.cc b/snapper/BtrfsUtils.cc index 7dd0e79d..b89553fb 100644 --- a/snapper/BtrfsUtils.cc +++ b/snapper/BtrfsUtils.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) [2011-2014] Novell, Inc. + * Copyright (c) [2011-2015] Novell, Inc. * * All Rights Reserved. * @@ -77,200 +77,237 @@ struct btrfs_ioctl_vol_args_v2 namespace snapper { - // See btrfsprogs source code for references. + namespace BtrfsUtils + { + // See btrfsprogs source code for references. - bool - is_subvolume(const struct stat& stat) - { - return stat.st_ino == 256 && S_ISDIR(stat.st_mode); - } + bool + is_subvolume(const struct stat& stat) + { + return stat.st_ino == 256 && S_ISDIR(stat.st_mode); + } - bool - is_subvolume_read_only(int fd) - { - __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; - } + bool + is_subvolume_read_only(int fd) + { + __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; - memset(&args, 0, sizeof(args)); - strncpy(args.name, name.c_str(), sizeof(args.name) - 1); + void + create_subvolume(int fddst, const string& name) + { + struct btrfs_ioctl_vol_args args; + memset(&args, 0, sizeof(args)); - if (ioctl(fddst, BTRFS_IOC_SUBVOL_CREATE, &args) != 0) - throw runtime_error_with_errno("ioctl(BTRFS_IOC_SUBVOL_CREATE) failed", errno); - } + strncpy(args.name, name.c_str(), sizeof(args.name) - 1); + if (ioctl(fddst, BTRFS_IOC_SUBVOL_CREATE, &args) != 0) + throw runtime_error_with_errno("ioctl(BTRFS_IOC_SUBVOL_CREATE) failed", errno); + } - void - create_snapshot(int fd, int fddst, const string& name, bool read_only, qgroup_t qgroup) - { - struct btrfs_ioctl_vol_args_v2 args_v2; - memset(&args_v2, 0, sizeof(args_v2)); - args_v2.fd = fd; - args_v2.flags = read_only ? BTRFS_SUBVOL_RDONLY : 0; - strncpy(args_v2.name, name.c_str(), sizeof(args_v2.name) - 1); + void + create_snapshot(int fd, int fddst, const string& name, bool read_only, qgroup_t qgroup) + { + struct btrfs_ioctl_vol_args_v2 args_v2; + memset(&args_v2, 0, sizeof(args_v2)); + + args_v2.fd = fd; + args_v2.flags = read_only ? BTRFS_SUBVOL_RDONLY : 0; + strncpy(args_v2.name, name.c_str(), sizeof(args_v2.name) - 1); #ifdef ENABLE_BTRFS_QUOTA - if (qgroup != no_qgroup) - { - size_t size = sizeof(btrfs_qgroup_inherit) + sizeof(((btrfs_qgroup_inherit*) 0)->qgroups[0]); - vector buffer(size, 0); - struct btrfs_qgroup_inherit* inherit = (btrfs_qgroup_inherit*) &buffer[0]; - - inherit->num_qgroups = 1; - inherit->num_ref_copies = 0; - inherit->num_excl_copies = 0; - inherit->qgroups[0] = qgroup; - - args_v2.flags |= BTRFS_SUBVOL_QGROUP_INHERIT; - args_v2.size = size; - args_v2.qgroup_inherit = inherit; - } + if (qgroup != no_qgroup) + { + size_t size = sizeof(btrfs_qgroup_inherit) + sizeof(((btrfs_qgroup_inherit*) 0)->qgroups[0]); + vector buffer(size, 0); + struct btrfs_qgroup_inherit* inherit = (btrfs_qgroup_inherit*) &buffer[0]; + + inherit->num_qgroups = 1; + inherit->num_ref_copies = 0; + inherit->num_excl_copies = 0; + inherit->qgroups[0] = qgroup; + + args_v2.flags |= BTRFS_SUBVOL_QGROUP_INHERIT; + args_v2.size = size; + args_v2.qgroup_inherit = inherit; + } #endif - if (ioctl(fddst, BTRFS_IOC_SNAP_CREATE_V2, &args_v2) == 0) - return; - else if (errno != ENOTTY && errno != EINVAL) - throw runtime_error_with_errno("ioctl(BTRFS_IOC_SNAP_CREATE_V2) failed", errno); + if (ioctl(fddst, BTRFS_IOC_SNAP_CREATE_V2, &args_v2) == 0) + return; + else if (errno != ENOTTY && errno != EINVAL) + throw runtime_error_with_errno("ioctl(BTRFS_IOC_SNAP_CREATE_V2) failed", errno); - struct btrfs_ioctl_vol_args args; - memset(&args, 0, sizeof(args)); + struct btrfs_ioctl_vol_args args; + memset(&args, 0, sizeof(args)); - args.fd = fd; - strncpy(args.name, name.c_str(), sizeof(args.name) - 1); + args.fd = fd; + strncpy(args.name, name.c_str(), sizeof(args.name) - 1); - if (ioctl(fddst, BTRFS_IOC_SNAP_CREATE, &args) != 0) - throw runtime_error_with_errno("ioctl(BTRFS_IOC_SNAP_CREATE) failed", errno); - } + if (ioctl(fddst, BTRFS_IOC_SNAP_CREATE, &args) != 0) + throw runtime_error_with_errno("ioctl(BTRFS_IOC_SNAP_CREATE) failed", errno); + } - void - delete_subvolume(int fd, const string& name) - { - struct btrfs_ioctl_vol_args args; - memset(&args, 0, sizeof(args)); + void + delete_subvolume(int fd, const string& name) + { + struct btrfs_ioctl_vol_args args; + memset(&args, 0, sizeof(args)); - strncpy(args.name, name.c_str(), sizeof(args.name) - 1); + strncpy(args.name, name.c_str(), sizeof(args.name) - 1); - if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args) != 0) - throw runtime_error_with_errno("ioctl(BTRFS_IOC_SNAP_DESTROY) failed", errno); - } + if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args) != 0) + throw runtime_error_with_errno("ioctl(BTRFS_IOC_SNAP_DESTROY) failed", errno); + } #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); - } + void + set_default_id(int fd, subvolid_t 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); - } + subvolid_t + 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) - { - char path[BTRFS_PATH_NAME_MAX + 1]; + string + get_subvolume(int fd, subvolid_t id) + { + char path[BTRFS_PATH_NAME_MAX + 1]; - if (btrfs_subvolid_resolve(fd, path, sizeof(path), id) != 0) - throw std::runtime_error("btrfs_subvolid_resolve failed"); + if (btrfs_subvolid_resolve(fd, path, sizeof(path), id) != 0) + throw std::runtime_error("btrfs_subvolid_resolve failed"); - path[BTRFS_PATH_NAME_MAX] = '\0'; - return path; - } + path[BTRFS_PATH_NAME_MAX] = '\0'; + return path; + } +#endif - unsigned long long - get_id(int fd) - { - struct btrfs_ioctl_ino_lookup_args args; - memset(&args, 0, sizeof(args)); - args.treeid = 0; - args.objectid = BTRFS_FIRST_FREE_OBJECTID; - if (ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args) != 0) - throw runtime_error_with_errno("ioctl(BTRFS_IOC_INO_LOOKUP) failed", errno); + subvolid_t + get_id(int fd) + { + struct btrfs_ioctl_ino_lookup_args args; + memset(&args, 0, sizeof(args)); + args.treeid = 0; + args.objectid = BTRFS_FIRST_FREE_OBJECTID; - return args.treeid; - } + if (ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args) != 0) + throw runtime_error_with_errno("ioctl(BTRFS_IOC_INO_LOOKUP) failed", errno); -#endif + return args.treeid; + } - qgroup_t - make_qgroup(uint64_t level, uint64_t id) - { - return (level << 48) | id; - } + qgroup_t + make_qgroup(uint64_t level, subvolid_t id) + { + return (level << 48) | id; + } - qgroup_t - make_qgroup(const string& str) - { - string::size_type pos = str.find('/'); - if (pos == string::npos) - throw std::runtime_error("parsing qgroup failed"); - - std::istringstream a(str.substr(0, pos)); - uint64_t level = 0; - a >> level; - if (a.fail() || !a.eof()) - throw std::runtime_error("parsing qgroup failed"); - - std::istringstream b(str.substr(pos + 1)); - uint64_t id = 0; - b >> id; - if (b.fail() || !b.eof()) - throw std::runtime_error("parsing qgroup failed"); - - return make_qgroup(level, id); + qgroup_t + make_qgroup(const string& str) + { + string::size_type pos = str.find('/'); + if (pos == string::npos) + throw std::runtime_error("parsing qgroup failed"); + + std::istringstream a(str.substr(0, pos)); + uint64_t level = 0; + a >> level; + if (a.fail() || !a.eof()) + throw std::runtime_error("parsing qgroup failed"); + + std::istringstream b(str.substr(pos + 1)); + subvolid_t id = 0; + b >> id; + if (b.fail() || !b.eof()) + throw std::runtime_error("parsing qgroup failed"); + + return make_qgroup(level, id); + } + + + bool + does_subvolume_exist(int fd, subvolid_t subvolid) + { + struct btrfs_ioctl_search_args args; + struct btrfs_ioctl_search_key* sk = &args.key; + + sk->tree_id = BTRFS_ROOT_TREE_OBJECTID; + sk->min_objectid = subvolid; + sk->max_objectid = subvolid; + sk->min_type = BTRFS_ROOT_ITEM_KEY; + sk->max_type = BTRFS_ROOT_ITEM_KEY; + sk->min_offset = 0; + sk->max_offset = (u64) -1; + sk->min_transid = 0; + sk->max_transid = (u64) -1; + sk->nr_items = 1; + + if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) != 0) + throw runtime_error_with_errno("ioctl(BTRFS_IOC_TREE_SEARCH) failed", errno); + + return sk->nr_items == 0; + } + + + void + sync(int fd) + { + if (ioctl(fd, BTRFS_IOC_SYNC) != 0) + throw runtime_error_with_errno("ioctl(BTRFS_IOC_SYNC) failed", errno); + } + } } diff --git a/snapper/BtrfsUtils.h b/snapper/BtrfsUtils.h index 4f1dd211..5e9eb494 100644 --- a/snapper/BtrfsUtils.h +++ b/snapper/BtrfsUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2011-2014] Novell, Inc. + * Copyright (c) [2011-2015] Novell, Inc. * * All Rights Reserved. * @@ -32,26 +32,37 @@ namespace snapper using std::string; - typedef uint64_t qgroup_t; - const qgroup_t no_qgroup = 0; + namespace BtrfsUtils + { - bool is_subvolume(const struct stat& stat); + typedef uint64_t subvolid_t; - bool is_subvolume_read_only(int fd); + typedef uint64_t qgroup_t; + const qgroup_t no_qgroup = 0; - void create_subvolume(int fddst, const string& name); - void create_snapshot(int fd, int fddst, const string& name, bool read_only, - qgroup_t qgroup); - void delete_subvolume(int fd, const string& name); + bool is_subvolume(const struct stat& stat); - void set_default_id(int fd, unsigned long long id); - unsigned long long get_default_id(int fd); + bool is_subvolume_read_only(int fd); - string get_subvolume(int fd, unsigned long long id); - unsigned long long get_id(int fd); + bool does_subvolume_exist(int fd, subvolid_t id); - qgroup_t make_qgroup(uint64_t level, uint64_t id); - qgroup_t make_qgroup(const string& str); + void create_subvolume(int fddst, const string& name); + void create_snapshot(int fd, int fddst, const string& name, bool read_only, + qgroup_t qgroup); + void delete_subvolume(int fd, const string& name); + + void set_default_id(int fd, subvolid_t id); + subvolid_t get_default_id(int fd); + + string get_subvolume(int fd, subvolid_t id); + subvolid_t get_id(int fd); + + qgroup_t make_qgroup(uint64_t level, subvolid_t id); + qgroup_t make_qgroup(const string& str); + + void sync(int fd); + + } } diff --git a/snapper/Filesystem.cc b/snapper/Filesystem.cc index e24f29ec..045cb83a 100644 --- a/snapper/Filesystem.cc +++ b/snapper/Filesystem.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) [2011-2013] Novell, Inc. + * Copyright (c) [2011-2015] Novell, Inc. * * All Rights Reserved. * @@ -174,4 +174,10 @@ namespace snapper throw std::logic_error("not implemented"); } + + void + Filesystem::sync() const + { + } + } diff --git a/snapper/Filesystem.h b/snapper/Filesystem.h index 23e2a949..62fdad5a 100644 --- a/snapper/Filesystem.h +++ b/snapper/Filesystem.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2011-2014] Novell, Inc. + * Copyright (c) [2011-2015] Novell, Inc. * * All Rights Reserved. * @@ -83,6 +83,8 @@ namespace snapper virtual void setDefault(unsigned int num) const; + virtual void sync() const; + protected: const string subvolume; diff --git a/snapper/Snapper.cc b/snapper/Snapper.cc index b6d61f94..955155d4 100644 --- a/snapper/Snapper.cc +++ b/snapper/Snapper.cc @@ -492,6 +492,13 @@ namespace snapper } + void + Snapper::syncFilesystem() const + { + filesystem->sync(); + } + + static void set_acl_permissions(acl_entry_t entry) { diff --git a/snapper/Snapper.h b/snapper/Snapper.h index bc5ea1b8..e942b310 100644 --- a/snapper/Snapper.h +++ b/snapper/Snapper.h @@ -153,6 +153,8 @@ namespace snapper void syncAcl() const; + void syncFilesystem() const; + static const char* compileVersion(); static const char* compileFlags();