Lvm::Lvm(const string& subvolume, const string& mount_type)
: Filesystem(subvolume), mount_type(mount_type),
- version(getLvmVersion())
+ caps(LvmCapabilities::get_lvm_capabilities())
{
if (access(LVCREATEBIN, X_OK) != 0)
{
throw ProgramNotInstalledException(LVCHANGEBIN " not installed");
}
- if (!version.valid())
- y2war("Couldn't get proper LVM version");
-
- if (version >= lvm_version(2, 2, 99))
- ignoreactivationskip = " -K";
-
bool found = false;
MtabData mtab_data;
void
Lvm::activateSnapshot(const string& vg_name, const string& lv_name) const
{
- SystemCmd cmd(LVCHANGEBIN + ignoreactivationskip + " -ay " + quote(vg_name + "/" + lv_name));
+ SystemCmd cmd(LVCHANGEBIN + caps->get_ignoreactivationskip() + " -ay " + quote(vg_name + "/" + lv_name));
if (cmd.retcode() != 0)
{
y2err("Couldn't activate snapshot " << vg_name << "/" << lv_name);
}
- lvm_version
- Lvm::getLvmVersion()
+ LvmCapabilities::LvmCapabilities()
+ : ignoreactivationskip(), time_support(false)
{
- uint16_t maj, min, rev;
-
SystemCmd cmd(string(LVSBIN " --version"));
if (cmd.retcode() != 0)
{
- return lvm_version::invalid_version();
+ y2war("Couldn't get LVM version info");
}
else
{
Regex rx(".*LVM[[:space:]]+version:[[:space:]]+([0-9]+)\\.([0-9]+)\\.([0-9]+).*$");
if (!rx.match(cmd.getLine(0)))
- return lvm_version::invalid_version();
+ {
+ y2war("LVM version format didn't match");
+ }
else
{
+ uint16_t maj, min, rev;
+
rx.cap(1) >> maj;
rx.cap(2) >> min;
rx.cap(3) >> rev;
+
+ lvm_version version(maj, min, rev);
+
+ if (version >= lvm_version(2,2,99))
+ {
+ ignoreactivationskip = " -K";
+ }
+
+ time_support = (version >= lvm_version(2,2,88));
}
}
-
- return lvm_version(maj, min, rev);
}
return a.version >= b.version;
}
+
+ LvmCapabilities*
+ LvmCapabilities::get_lvm_capabilities()
+ {
+ /*
+ * NOTE: verify only one thread can access
+ * this section at the same time!
+ */
+ static LvmCapabilities caps;
+
+ return ∩︀
+ }
+
+
+ string
+ LvmCapabilities::get_ignoreactivationskip() const
+ {
+ return ignoreactivationskip;
+ }
+
+
+ bool
+ LvmCapabilities::get_time_support() const
+ {
+ return time_support;
+ }
+
}
#ifndef SNAPPER_LVM_H
#define SNAPPER_LVM_H
+#include <boost/noncopyable.hpp>
#include "snapper/Filesystem.h"
};
- class lvm_version
+ struct lvm_version
{
- public:
- static lvm_version invalid_version() { return lvm_version(0, 0, 0); }
-
lvm_version(uint16_t maj, uint16_t min, uint16_t rev)
- : version(rev | ((uint32_t) min << 16) | ((uint64_t) maj << 32)) {}
+ : version(rev | ((uint32_t)min << 16) | ((uint64_t)maj << 32)) {}
+
+ const uint64_t version;
+ };
+
+ bool operator>=(const lvm_version& a, const lvm_version& b);
+
+ class LvmCapabilities : public boost::noncopyable
+ {
+ public:
+ static LvmCapabilities* get_lvm_capabilities();
- bool valid() const { return version != 0; }
+ bool get_time_support() const;
+ string get_ignoreactivationskip() const;
- friend bool operator>=(const lvm_version& a, const lvm_version& b);
private:
- const uint64_t version;
+ LvmCapabilities();
+
+ // empty or " -K" if lvm supports ignore activation skip flag
+ string ignoreactivationskip;
+ // true if lvm2 supports time info stored in metadata
+ bool time_support;
};
private:
- static lvm_version getLvmVersion();
-
const string mount_type;
- const lvm_version version;
+ const LvmCapabilities* caps;
bool detectThinVolumeNames(const MtabData& mtab_data);
void activateSnapshot(const string& vg_name, const string& lv_name) const;
vector<string> mount_options;
- string ignoreactivationskip;
};
}