diff --git a/include/blksnap/SnapshotCtl.h b/include/blksnap/SnapshotCtl.h index c5e71bab..7357a08e 100644 --- a/include/blksnap/SnapshotCtl.h +++ b/include/blksnap/SnapshotCtl.h @@ -23,6 +23,7 @@ * flexibility. Uses structures that are directly passed to the kernel module. */ +#include #include #include #include @@ -102,20 +103,27 @@ namespace blksnap class CSnapshotCtl { public: - CSnapshotCtl(); - ~CSnapshotCtl(); + static void Collect(std::vector& ids); + static void Version(struct blksnap_version& version); + static std::shared_ptr Create(const std::string& filePath, const unsigned long long limit); + static std::shared_ptr Open(const CSnapshotId& id); - CSnapshotId Create(const std::string& filePath, const unsigned long long limit); - void Destroy(const CSnapshotId& id); - void Collect(std::vector& ids); - void AppendDiffStorage(const CSnapshotId& id, const std::string& filePath); - void Take(const CSnapshotId& id); - bool WaitEvent(const CSnapshotId& id, unsigned int timeoutMs, SBlksnapEvent& ev); + public: + virtual ~CSnapshotCtl() {}; - void Version(struct blksnap_version& version); + void Take(); + void Destroy(); + bool WaitEvent(unsigned int timeoutMs, SBlksnapEvent& ev); + const uuid_t& Id() const + { + return m_id.Get(); + } private: - int m_fd; + CSnapshotCtl(const CSnapshotId& id, const std::shared_ptr& ctl); + + CSnapshotId m_id; + std::shared_ptr m_ctl; }; } diff --git a/lib/blksnap/Service.cpp b/lib/blksnap/Service.cpp index 4b3a944d..924cc163 100644 --- a/lib/blksnap/Service.cpp +++ b/lib/blksnap/Service.cpp @@ -33,8 +33,7 @@ std::string blksnap::Version() { struct blksnap_version version; - CSnapshotCtl ctl; - ctl.Version(version); + CSnapshotCtl::Version(version); std::stringstream ss; ss << version.major << "." << version.minor << "." << version.revision << "." << version.build; diff --git a/lib/blksnap/Session.cpp b/lib/blksnap/Session.cpp index 32662324..e28c3acb 100644 --- a/lib/blksnap/Session.cpp +++ b/lib/blksnap/Session.cpp @@ -46,7 +46,6 @@ struct SState { std::atomic stop; std::string diffStorage; - CSnapshotId id; std::mutex lock; std::list errorMessage; }; @@ -87,7 +86,7 @@ static void BlksnapThread(std::shared_ptr ptrCtl, std::shared_ptr< { try { - is_eventReady = ptrCtl->WaitEvent(ptrState->id, 100, ev); + is_eventReady = ptrCtl->WaitEvent(100, ev); } catch (std::exception& ex) { @@ -122,26 +121,23 @@ static void BlksnapThread(std::shared_ptr ptrCtl, std::shared_ptr< CSession::CSession(const std::vector& devices, const std::string& diffStorageFilePath, const unsigned long long limit) { - m_ptrCtl = std::make_shared(); - for (const auto& name : devices) CTrackerCtl(name).Attach(); // Create snapshot - m_id = m_ptrCtl->Create(diffStorageFilePath, limit); + auto snapshot = CSnapshotCtl::Create(diffStorageFilePath, limit); // Add devices to snapshot for (const auto& name : devices) - CTrackerCtl(name).SnapshotAdd(m_id.Get()); + CTrackerCtl(name).SnapshotAdd(snapshot->Id()); // Prepare state structure for thread m_ptrState = std::make_shared(); m_ptrState->stop = false; - m_ptrState->id = m_id; // Append first portion for diff storage struct SBlksnapEvent ev; - if (m_ptrCtl->WaitEvent(m_id, 100, ev)) + if (snapshot->WaitEvent(100, ev)) { switch (ev.code) { @@ -162,8 +158,7 @@ CSession::CSession(const std::vector& devices, const std::string& d // Take snapshot - m_ptrCtl->Take(m_id); - + snapshot->Take(); } CSession::~CSession() @@ -177,7 +172,7 @@ CSession::~CSession() // Destroy snapshot try { - m_ptrCtl->Destroy(m_id); + m_ptrCtl->Destroy(); } catch (std::exception& ex) { diff --git a/lib/blksnap/SnapshotCtl.cpp b/lib/blksnap/SnapshotCtl.cpp index 9d05a27f..31fbd9c0 100644 --- a/lib/blksnap/SnapshotCtl.cpp +++ b/lib/blksnap/SnapshotCtl.cpp @@ -63,31 +63,25 @@ static inline bool isBlockFile(const std::string& path) return S_ISBLK(st.st_mode); } -CSnapshotCtl::CSnapshotCtl() - : m_fd(0) +static inline std::shared_ptr OpenBlksnapCtl() { - int fd = ::open(blksnap_filename, O_RDWR); - if (fd < 0) - throw std::system_error(errno, std::generic_category(), - "Failed to open file [" + std::string(blksnap_filename) + "]"); - - m_fd = fd; + return std::make_shared(blksnap_filename, O_RDWR); } -CSnapshotCtl::~CSnapshotCtl() -{ - if (m_fd) - ::close(m_fd); -} +CSnapshotCtl::CSnapshotCtl(const CSnapshotId& id, const std::shared_ptr& ctl) + : m_id(id) + , m_ctl(ctl) +{ } void CSnapshotCtl::Version(struct blksnap_version& version) { - if (::ioctl(m_fd, IOCTL_BLKSNAP_VERSION, &version)) + auto ctl = OpenBlksnapCtl(); + if (::ioctl(ctl->Get(), IOCTL_BLKSNAP_VERSION, &version)) throw std::system_error(errno, std::generic_category(), "Failed to get version."); } -CSnapshotId CSnapshotCtl::Create(const std::string& filePath, const unsigned long long limit) +std::shared_ptr CSnapshotCtl::Create(const std::string& filePath, const unsigned long long limit) { int flags = O_RDWR | O_EXCL; @@ -101,30 +95,27 @@ CSnapshotId CSnapshotCtl::Create(const std::string& filePath, const unsigned lon struct blksnap_snapshot_create param = {0}; param.diff_storage_limit_sect = limit / 512; param.diff_storage_fd = fd.Get(); - if (::ioctl(m_fd, IOCTL_BLKSNAP_SNAPSHOT_CREATE, ¶m)) + + auto ctl = OpenBlksnapCtl(); + if (::ioctl(ctl->Get(), IOCTL_BLKSNAP_SNAPSHOT_CREATE, ¶m)) throw std::system_error(errno, std::generic_category(), "Failed to create snapshot object."); - return CSnapshotId(param.id.b); + return std::shared_ptr(new CSnapshotCtl(CSnapshotId(param.id.b), ctl)); } -void CSnapshotCtl::Destroy(const CSnapshotId& id) +std::shared_ptr CSnapshotCtl::Open(const CSnapshotId& id) { - struct blksnap_uuid param; - - uuid_copy(param.b, id.Get()); - - if (::ioctl(m_fd, IOCTL_BLKSNAP_SNAPSHOT_DESTROY, ¶m)) - throw std::system_error(errno, std::generic_category(), - "Failed to destroy snapshot."); + return std::shared_ptr(new CSnapshotCtl(id, OpenBlksnapCtl())); } void CSnapshotCtl::Collect(std::vector& ids) { struct blksnap_snapshot_collect param = {0}; + auto ctl = OpenBlksnapCtl(); ids.clear(); - if (::ioctl(m_fd, IOCTL_BLKSNAP_SNAPSHOT_COLLECT, ¶m)) + if (::ioctl(ctl->Get(), IOCTL_BLKSNAP_SNAPSHOT_COLLECT, ¶m)) throw std::system_error(errno, std::generic_category(), "Failed to get list of active snapshots."); @@ -134,7 +125,7 @@ void CSnapshotCtl::Collect(std::vector& ids) std::vector id_array(param.count); param.ids = (__u64)id_array.data(); - if (::ioctl(m_fd, IOCTL_BLKSNAP_SNAPSHOT_COLLECT, ¶m)) + if (::ioctl(ctl->Get(), IOCTL_BLKSNAP_SNAPSHOT_COLLECT, ¶m)) throw std::system_error(errno, std::generic_category(), "Failed to get list of snapshots."); @@ -142,25 +133,34 @@ void CSnapshotCtl::Collect(std::vector& ids) ids.emplace_back(id_array[inx].b); } -void CSnapshotCtl::Take(const CSnapshotId& id) +void CSnapshotCtl::Take() { struct blksnap_uuid param; - uuid_copy(param.b, id.Get()); - - if (::ioctl(m_fd, IOCTL_BLKSNAP_SNAPSHOT_TAKE, ¶m)) + uuid_copy(param.b, m_id.Get()); + if (::ioctl(m_ctl->Get(), IOCTL_BLKSNAP_SNAPSHOT_TAKE, ¶m)) throw std::system_error(errno, std::generic_category(), "Failed to take snapshot."); } -bool CSnapshotCtl::WaitEvent(const CSnapshotId& id, unsigned int timeoutMs, SBlksnapEvent& ev) +void CSnapshotCtl::Destroy() +{ + struct blksnap_uuid param; + + uuid_copy(param.b, m_id.Get()); + if (::ioctl(m_ctl->Get(), IOCTL_BLKSNAP_SNAPSHOT_DESTROY, ¶m)) + throw std::system_error(errno, std::generic_category(), + "Failed to destroy snapshot."); +} + +bool CSnapshotCtl::WaitEvent(unsigned int timeoutMs, SBlksnapEvent& ev) { struct blksnap_snapshot_event param; - uuid_copy(param.id.b, id.Get()); + uuid_copy(param.id.b, m_id.Get()); param.timeout_ms = timeoutMs; - if (::ioctl(m_fd, IOCTL_BLKSNAP_SNAPSHOT_WAIT_EVENT, ¶m)) + if (::ioctl(m_ctl->Get(), IOCTL_BLKSNAP_SNAPSHOT_WAIT_EVENT, ¶m)) { if ((errno == ENOENT) || (errno == EINTR)) return false;