From: Arvin Schnell Date: Wed, 29 Aug 2012 10:50:23 +0000 (+0200) Subject: - use ioctl instead of btrfs program X-Git-Tag: v0.1.3~137 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=55801e934181d7e32fcd384cb70853ae734fab37;p=thirdparty%2Fsnapper.git - use ioctl instead of btrfs program --- diff --git a/snapper/FileUtils.h b/snapper/FileUtils.h index ab1e3837..1a442927 100644 --- a/snapper/FileUtils.h +++ b/snapper/FileUtils.h @@ -46,6 +46,8 @@ namespace snapper SDir& operator=(const SDir&); ~SDir(); + int fd() const { return dirfd; } + string fullname(bool with_base_path = true) const; string fullname(const string& name, bool with_base_path = true) const; diff --git a/snapper/Filesystem.cc b/snapper/Filesystem.cc index aba18c7d..33986bce 100644 --- a/snapper/Filesystem.cc +++ b/snapper/Filesystem.cc @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include "snapper/Log.h" #include "snapper/Filesystem.h" @@ -36,6 +38,31 @@ #include "snapper/SnapperDefines.h" +#define BTRFS_IOCTL_MAGIC 0x94 +#define BTRFS_PATH_NAME_MAX 4087 +#define BTRFS_SUBVOL_NAME_MAX 4039 +#define BTRFS_SUBVOL_RDONLY (1ULL << 1) + +#define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_SNAP_DESTROY _IOW(BTRFS_IOCTL_MAGIC, 15, struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, struct btrfs_ioctl_vol_args_v2) + +struct btrfs_ioctl_vol_args +{ + __s64 fd; + char name[BTRFS_PATH_NAME_MAX + 1]; +}; + +struct btrfs_ioctl_vol_args_v2 +{ + __s64 fd; + __u64 transid; + __u64 flags; + __u64 unused[4]; + char name[BTRFS_SUBVOL_NAME_MAX + 1]; +}; + + namespace snapper { @@ -65,18 +92,26 @@ namespace snapper void Btrfs::createConfig() const { - SystemCmd cmd2(BTRFSBIN " subvolume create " + quote(subvolume + "/.snapshots")); - if (cmd2.retcode() != 0) + SDir subvolume_dir = openSubvolumeDir(); + + if (!create_subvolume(subvolume_dir.fd(), ".snapshots")) + { + y2err("create subvolume failed errno:" << errno << " (" << stringerror(errno) << ")"); throw CreateConfigFailedException("creating btrfs snapshot failed"); + } } void Btrfs::deleteConfig() const { - SystemCmd cmd2(BTRFSBIN " subvolume delete " + quote(subvolume + "/.snapshots")); - if (cmd2.retcode() != 0) + SDir subvolume_dir = openSubvolumeDir(); + + if (!delete_subvolume(subvolume_dir.fd(), ".snapshots")) + { + y2err("delete subvolume failed errno:" << errno << " (" << stringerror(errno) << ")"); throw DeleteConfigFailedException("deleting btrfs snapshot failed"); + } } @@ -95,10 +130,17 @@ namespace snapper } + SDir + Btrfs::openSubvolumeDir() const + { + return SDir(subvolume); + } + + SDir Btrfs::openInfosDir() const { - SDir subvolume_dir(subvolume); + SDir subvolume_dir = openSubvolumeDir(); SDir infos_dir(subvolume_dir, ".snapshots"); struct stat stat; @@ -140,19 +182,27 @@ namespace snapper void Btrfs::createSnapshot(unsigned int num) const { - SystemCmd cmd(BTRFSBIN " subvolume snapshot -r " + quote(subvolume) + " " + - quote(snapshotDir(num))); - if (cmd.retcode() != 0) + SDir subvolume_dir = openSubvolumeDir(); + SDir info_dir = openInfoDir(num); + + if (!create_snapshot(subvolume_dir.fd(), info_dir.fd(), "snapshot")) + { + y2err("create snapshot failed errno:" << errno << " (" << stringerror(errno) << ")"); throw CreateSnapshotFailedException(); + } } void Btrfs::deleteSnapshot(unsigned int num) const { - SystemCmd cmd(BTRFSBIN " subvolume delete " + quote(snapshotDir(num))); - if (cmd.retcode() != 0) + SDir info_dir = openInfoDir(num); + + if (!delete_subvolume(info_dir.fd(), "snapshot")) + { + y2err("delete snapshot failed errno:" << errno << " (" << stringerror(errno) << ")"); throw DeleteSnapshotFailedException(); + } } @@ -184,7 +234,8 @@ namespace snapper struct stat stat; int r = info_dir.stat("snapshot", &stat, AT_SYMLINK_NOFOLLOW); - return r == 0 && S_ISDIR(stat.st_mode); + // check st_ino == 256 is copied from btrfsprogs + return r == 0 && stat.st_ino == 256 && S_ISDIR(stat.st_mode); } catch (const IOErrorException& e) { @@ -193,6 +244,44 @@ namespace snapper } + bool + Btrfs::create_subvolume(int fddst, const string& name) const + { + struct btrfs_ioctl_vol_args args; + memset(&args, 0, sizeof(args)); + + strncpy(args.name, name.c_str(), BTRFS_PATH_NAME_MAX); + + return ioctl(fddst, BTRFS_IOC_SUBVOL_CREATE, &args) == 0; + } + + + bool + Btrfs::create_snapshot(int fd, int fddst, const string& name) const + { + struct btrfs_ioctl_vol_args_v2 args; + memset(&args, 0, sizeof(args)); + + args.fd = fd; + args.flags |= BTRFS_SUBVOL_RDONLY; + strncpy(args.name, name.c_str(), BTRFS_SUBVOL_NAME_MAX); + + return ioctl(fddst, BTRFS_IOC_SNAP_CREATE_V2, &args) == 0; + } + + + bool + Btrfs::delete_subvolume(int fd, const string& name) const + { + struct btrfs_ioctl_vol_args args; + memset(&args, 0, sizeof(args)); + + strncpy(args.name, name.c_str(), BTRFS_PATH_NAME_MAX); + + return ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args) == 0; + } + + Ext4::Ext4(const string& subvolume) : Filesystem(subvolume) { diff --git a/snapper/Filesystem.h b/snapper/Filesystem.h index 872c10a2..4d0c876c 100644 --- a/snapper/Filesystem.h +++ b/snapper/Filesystem.h @@ -87,6 +87,7 @@ namespace snapper virtual string infosDir() const; virtual string snapshotDir(unsigned int num) const; + virtual SDir openSubvolumeDir() const; virtual SDir openInfosDir() const; virtual SDir openInfoDir(unsigned int num) const; virtual SDir openSnapshotDir(unsigned int num) const; @@ -100,6 +101,12 @@ namespace snapper virtual bool checkSnapshot(unsigned int num) const; + private: + + bool create_subvolume(int fddst, const string& name) const; + bool create_snapshot(int fd, int fddst, const string& name) const; + bool delete_subvolume(int fd, const string& name) const; + };