AC_PATH_PROG([LVCREATEBIN], [lvcreate], [/sbin/lvcreate])
AC_PATH_PROG([LVREMOVEBIN], [lvremove], [/sbin/lvremove])
AC_PATH_PROG([LVSBIN], [lvs], [/sbin/lvs])
+AC_PATH_PROG([LVCHANGEBIN], [lvchange], [/sbin/lvchange])
AC_DEFINE_UNQUOTED([CHSNAPBIN], ["$CHSNAPBIN"], [Path of chsnap program.])
AC_DEFINE_UNQUOTED([CPBIN], ["$CPBIN"], [Path of cp program.])
AC_DEFINE_UNQUOTED([LVCREATEBIN], ["$LVCREATEBIN"], [Path of lvcreate program.])
AC_DEFINE_UNQUOTED([LVREMOVEBIN], ["$LVREMOVEBIN"], [Path of lvremove program.])
AC_DEFINE_UNQUOTED([LVSBIN], ["$LVSBIN"], [Path of lvs program.])
+AC_DEFINE_UNQUOTED([LVCHANGEBIN], ["$LVCHANGEBIN"], [Path of lvchange program.])
dnl Automake 1.11 enables silent compilation
dnl Disable it by "configure --disable-silent-rules" or "make V=1"
if (isSnapshotMounted(num))
return;
+ try
+ {
+ activateSnapshot(vg_name, snapshotLvName(num));
+ }
+ catch (const LvmActivationException& e)
+ {
+ y2err("Couldn't mount snapshot " << num);
+ throw MountSnapshotFailedException();
+ }
+
SDir snapshot_dir = openSnapshotDir(num);
if (!mount(getDevice(num), snapshot_dir, mount_type, mount_options))
if (!umount(info_dir, "snapshot"))
throw UmountSnapshotFailedException();
+
+ try
+ {
+ deactivateSnapshot(vg_name, snapshotLvName(num));
+ }
+ catch (const LvmDeactivatationException& e)
+ {
+ y2war("Snapshot #" << num << "deactivation failed");
+ }
}
{
struct stat stat;
int r1 = ::stat(getDevice(num).c_str(), &stat);
- return r1 == 0 && S_ISBLK(stat.st_mode);
+
+ return (r1 == 0 && S_ISBLK(stat.st_mode)) || detectInactiveSnapshot(vg_name, snapshotLvName(num));
}
boost::replace_all_copy(snapshotLvName(num), "-", "--");
}
+
+ void
+ Lvm::activateSnapshot(const string& vg_name, const string& lv_name) const
+ {
+ SystemCmd cmd(LVCHANGEBIN " -ay -K " + quote(vg_name + "/" + lv_name));
+ switch (cmd.retcode())
+ {
+ case 0:
+ break;
+ case EINVALID_CMD_LINE:
+ {
+ SystemCmd retry_cmd(LVCHANGEBIN " -ay " + quote(vg_name + "/" + lv_name));
+ if (retry_cmd.retcode() == 0)
+ break;
+ }
+ default:
+ y2err("Couldn't activate snapshot " << vg_name << "/" << lv_name);
+ throw LvmActivationException();
+ }
+ }
+
+
+ void
+ Lvm::deactivateSnapshot(const string& vg_name, const string& lv_name) const
+ {
+ SystemCmd cmd(LVCHANGEBIN " -an " + quote(vg_name + "/" + lv_name));
+ if (cmd.retcode())
+ throw LvmDeactivatationException();
+ }
+
+
+ bool
+ Lvm::detectInactiveSnapshot(const string& vg_name, const string& lv_name) const
+ {
+ SystemCmd cmd(LVSBIN " " + quote(vg_name + "/" + lv_name));
+ return cmd.retcode() == 0;
+ }
+
}
#ifndef SNAPPER_LVM_H
#define SNAPPER_LVM_H
+/*
+ * tools/errors.h from lvm2 source
+ *
+ * consider adding lvm2-devel dep for lvm2 enabled snapper
+ */
+#define EINVALID_CMD_LINE 3
#include "snapper/Filesystem.h"
namespace snapper
{
+ struct LvmActivationException : public std::exception
+ {
+ explicit LvmActivationException() throw() {}
+ virtual const char* what() const throw() { return "lvm snapshot activation exception"; }
+ };
+
+
+ struct LvmDeactivatationException : public std::exception
+ {
+ explicit LvmDeactivatationException() throw() {}
+ virtual const char* what() const throw() { return "lvm snapshot deactivation exception"; }
+ };
+
class Lvm : public Filesystem
{
bool detectThinVolumeNames(const MtabData& mtab_data);
+ void activateSnapshot(const string& vg_name, const string& lv_name) const;
+ void deactivateSnapshot(const string& vg_name, const string& lv_name) const;
+ bool detectInactiveSnapshot(const string& vg_name, const string& lv_name) const;
+
string getDevice(unsigned int num) const;
string vg_name;