diff --git a/Makefile.am b/Makefile.am
index f82dfd56..cc6b6103 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -76,7 +76,7 @@ MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.sub \
configure depcomp install-sh ltmain.sh missing py-compile compile ar-lib \
m4/*.m4
-LIBDIRS = src/utils/.libs:src/plugins/.libs:src/plugins/fs/.libs:src/plugins/nvme/.libs:src/plugins/smart/.libs:src/lib/.libs
+LIBDIRS = src/utils/.libs:src/plugins/.libs:src/plugins/fs/.libs:src/plugins/lvm/.libs:src/plugins/nvme/.libs:src/plugins/smart/.libs:src/lib/.libs
GIDIR = src/lib
if WITH_PYTHON3
diff --git a/configure.ac b/configure.ac
index 98837611..15b0b3bd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,6 +21,7 @@ LT_INIT
AC_CONFIG_FILES([Makefile src/Makefile \
src/plugins/Makefile \
src/plugins/fs/Makefile \
+ src/plugins/lvm/Makefile \
src/plugins/nvme/Makefile \
src/plugins/smart/Makefile \
src/utils/Makefile \
diff --git a/include/blockdev/Makefile.am b/include/blockdev/Makefile.am
index a26bf60e..dc23aecb 100644
--- a/include/blockdev/Makefile.am
+++ b/include/blockdev/Makefile.am
@@ -1,5 +1,6 @@
all-local:
for header in ${srcdir}/../../src/plugins/*.h; do ln -sf $${header} ./; done
+ for header in ${srcdir}/../../src/plugins/lvm/lvm.h; do ln -sf $${header} ./; done
for header in ${srcdir}/../../src/plugins/nvme/nvme.h; do ln -sf $${header} ./; done
for header in ${srcdir}/../../src/plugins/smart/smart.h; do ln -sf $${header} ./; done
for header in ${srcdir}/../../src/utils/*.h; do ln -sf $${header} ./; done
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 4fa0d20e..52e89597 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -8,6 +8,7 @@ if WITH_NVME
SUBDIRS += nvme
endif
+SUBDIRS += lvm
SUBDIRS += smart
lib_LTLIBRARIES =
@@ -28,14 +29,6 @@ if WITH_LOOP
lib_LTLIBRARIES += libbd_loop.la
endif
-if WITH_LVM
-lib_LTLIBRARIES += libbd_lvm.la
-endif
-
-if WITH_LVM_DBUS
-lib_LTLIBRARIES += libbd_lvm-dbus.la
-endif
-
if WITH_MDRAID
lib_LTLIBRARIES += libbd_mdraid.la
endif
@@ -98,22 +91,6 @@ libbd_loop_la_CPPFLAGS = -I${builddir}/../../include/
libbd_loop_la_SOURCES = loop.c loop.h
endif
-if WITH_LVM
-libbd_lvm_la_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) $(DEVMAPPER_CFLAGS) $(YAML_CFLAGS) -Wall -Wextra -Werror
-libbd_lvm_la_LIBADD = ${builddir}/../utils/libbd_utils.la -lm $(GLIB_LIBS) $(GIO_LIBS) $(DEVMAPPER_LIBS) $(YAML_LIBS)
-libbd_lvm_la_LDFLAGS = -L${srcdir}/../utils/ -version-info 3:0:0 -Wl,--no-undefined -export-symbols-regex '^bd_.*'
-libbd_lvm_la_CPPFLAGS = -I${builddir}/../../include/
-libbd_lvm_la_SOURCES = lvm.c lvm.h check_deps.c check_deps.h dm_logging.c dm_logging.h vdo_stats.c vdo_stats.h
-endif
-
-if WITH_LVM_DBUS
-libbd_lvm_dbus_la_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) $(DEVMAPPER_CFLAGS) $(YAML_CFLAGS) -Wall -Wextra -Werror
-libbd_lvm_dbus_la_LIBADD = ${builddir}/../utils/libbd_utils.la -lm $(GLIB_LIBS) $(GIO_LIBS) $(DEVMAPPER_LIBS) $(YAML_LIBS)
-libbd_lvm_dbus_la_LDFLAGS = -L${srcdir}/../utils/ -version-info 3:0:0 -Wl,--no-undefined -export-symbols-regex '^bd_.*'
-libbd_lvm_dbus_la_CPPFLAGS = -I${builddir}/../../include/
-libbd_lvm_dbus_la_SOURCES = lvm-dbus.c lvm.h check_deps.c check_deps.h dm_logging.c dm_logging.h vdo_stats.c vdo_stats.h
-endif
-
if WITH_MDRAID
libbd_mdraid_la_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) $(BYTESIZE_CFLAGS) -Wall -Wextra -Werror
libbd_mdraid_la_LIBADD = ${builddir}/../utils/libbd_utils.la $(GLIB_LIBS) $(GIO_LIBS) $(BYTESIZE_LIBS)
@@ -182,14 +159,6 @@ if WITH_LOOP
libinclude_HEADERS += loop.h
endif
-if WITH_LVM
-libinclude_HEADERS += lvm.h
-else
-if WITH_LVM_DBUS
-libinclude_HEADERS += lvm.h
-endif
-endif
-
if WITH_MDRAID
libinclude_HEADERS += mdraid.h
endif
diff --git a/src/plugins/lvm/Makefile.am b/src/plugins/lvm/Makefile.am
new file mode 100644
index 00000000..3b7ba66f
--- /dev/null
+++ b/src/plugins/lvm/Makefile.am
@@ -0,0 +1,59 @@
+AUTOMAKE_OPTIONS = subdir-objects
+
+lib_LTLIBRARIES =
+libincludedir = $(includedir)/blockdev
+
+if WITH_LVM
+libinclude_HEADERS = lvm.h
+else
+if WITH_LVM_DBUS
+libinclude_HEADERS = lvm.h
+endif
+endif
+
+
+if WITH_LVM
+
+lib_LTLIBRARIES += libbd_lvm.la
+
+libbd_lvm_la_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) $(DEVMAPPER_CFLAGS) $(YAML_CFLAGS) -Wall -Wextra -Werror
+libbd_lvm_la_LIBADD = ${builddir}/../../utils/libbd_utils.la -lm $(GLIB_LIBS) $(GIO_LIBS) $(DEVMAPPER_LIBS) $(YAML_LIBS)
+libbd_lvm_la_LDFLAGS = -L${srcdir}/../../utils/ -version-info 3:0:0 -Wl,--no-undefined -export-symbols-regex '^bd_.*'
+libbd_lvm_la_CPPFLAGS = -I${builddir}/../../../include/ -I${srcdir}/../ -I. -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\"
+
+libbd_lvm_la_SOURCES = \
+ lvm.c \
+ lvm.h \
+ lvm-private.h \
+ lvm-common.c \
+ vdo_stats.c \
+ vdo_stats.h \
+ ../check_deps.c \
+ ../check_deps.h \
+ ../dm_logging.c \
+ ../dm_logging.h
+
+endif
+
+if WITH_LVM_DBUS
+
+lib_LTLIBRARIES += libbd_lvm-dbus.la
+
+libbd_lvm_dbus_la_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) $(DEVMAPPER_CFLAGS) $(YAML_CFLAGS) -Wall -Wextra -Werror
+libbd_lvm_dbus_la_LIBADD = ${builddir}/../../utils/libbd_utils.la -lm $(GLIB_LIBS) $(GIO_LIBS) $(DEVMAPPER_LIBS) $(YAML_LIBS)
+libbd_lvm_dbus_la_LDFLAGS = -L${srcdir}/../../utils/ -version-info 3:0:0 -Wl,--no-undefined -export-symbols-regex '^bd_.*'
+libbd_lvm_dbus_la_CPPFLAGS = -I${builddir}/../../../include/ -I${srcdir}/../ -I. -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\"
+
+libbd_lvm_dbus_la_SOURCES = \
+ lvm-dbus.c \
+ lvm.h \
+ lvm-private.h \
+ lvm-common.c \
+ vdo_stats.c \
+ vdo_stats.h \
+ ../check_deps.c \
+ ../check_deps.h \
+ ../dm_logging.c \
+ ../dm_logging.h
+
+endif
diff --git a/src/plugins/lvm/lvm-common.c b/src/plugins/lvm/lvm-common.c
new file mode 100644
index 00000000..d71984e5
--- /dev/null
+++ b/src/plugins/lvm/lvm-common.c
@@ -0,0 +1,789 @@
+/*
+ * Copyright (C) 2014-2025 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ *
+ */
+
+#include
+#include
+#include
+#include
+
+#include "lvm.h"
+#include "lvm-private.h"
+#include "check_deps.h"
+#include "dm_logging.h"
+#include "vdo_stats.h"
+
+
+#define INT_FLOAT_EPS 1e-5
+
+#define MIN_PE_SIZE (1 KiB)
+#define MAX_PE_SIZE (16 GiB)
+
+#define VDO_POOL_SUFFIX "vpool"
+
+#define THPOOL_MD_FACTOR_NEW (0.2)
+#define THPOOL_MD_FACTOR_EXISTS (1 / 6.0)
+
+#define MIN_THPOOL_MD_SIZE (4 MiB)
+/* DM_THIN_MAX_METADATA_SIZE is in 512 sectors */
+#define MAX_THPOOL_MD_SIZE (DM_THIN_MAX_METADATA_SIZE * 512)
+
+#define MIN_THPOOL_CHUNK_SIZE (64 KiB)
+#define MAX_THPOOL_CHUNK_SIZE (1 GiB)
+#define DEFAULT_CHUNK_SIZE (64 KiB)
+
+/* according to lvmcache (7) */
+#define MIN_CACHE_MD_SIZE (8 MiB)
+
+#ifdef __LP64__
+/* 64bit system */
+#define MAX_LV_SIZE (8 EiB)
+#else
+/* 32bit system */
+#define MAX_LV_SIZE (16 TiB)
+#endif
+
+GMutex global_config_lock;
+gchar *global_config_str = NULL;
+gchar *global_devices_str = NULL;
+
+/**
+ * bd_lvm_is_supported_pe_size:
+ * @size: size (in bytes) to test
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: whether the given size is supported physical extent size or not
+ *
+ * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
+ */
+gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error G_GNUC_UNUSED) {
+ return (((size % 2) == 0) && (size >= (MIN_PE_SIZE)) && (size <= (MAX_PE_SIZE)));
+}
+
+/**
+ * bd_lvm_get_supported_pe_sizes:
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: (transfer full) (array fixed-size=25): list of supported PE sizes
+ *
+ * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
+ */
+guint64 *bd_lvm_get_supported_pe_sizes (GError **error G_GNUC_UNUSED) {
+ guint8 i;
+ guint64 val = MIN_PE_SIZE;
+ guint8 num_items = ((guint8) round (log2 ((double) MAX_PE_SIZE))) - ((guint8) round (log2 ((double) MIN_PE_SIZE))) + 2;
+ guint64 *ret = g_new0 (guint64, num_items);
+
+ for (i=0; (val <= MAX_PE_SIZE); i++, val = val * 2)
+ ret[i] = val;
+
+ ret[num_items-1] = 0;
+
+ return ret;
+}
+
+/**
+ * bd_lvm_get_max_lv_size:
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: maximum LV size in bytes
+ *
+ * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
+ */
+guint64 bd_lvm_get_max_lv_size (GError **error G_GNUC_UNUSED) {
+ return MAX_LV_SIZE;
+}
+
+/**
+ * bd_lvm_round_size_to_pe:
+ * @size: size to be rounded
+ * @pe_size: physical extent (PE) size or 0 to use the default
+ * @roundup: whether to round up or down (ceil or floor)
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: @size rounded to @pe_size according to the @roundup
+ *
+ * Rounds given @size up/down to a multiple of @pe_size according to the value
+ * of the @roundup parameter. If the rounded value is too big to fit in the
+ * return type, the result is rounded down (floored) regardless of the @roundup
+ * parameter.
+ *
+ * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
+ */
+guint64 bd_lvm_round_size_to_pe (guint64 size, guint64 pe_size, gboolean roundup, GError **error G_GNUC_UNUSED) {
+ pe_size = RESOLVE_PE_SIZE (pe_size);
+ guint64 delta = size % pe_size;
+ if (delta == 0)
+ return size;
+
+ if (roundup && (((G_MAXUINT64 - (pe_size - delta)) >= size)))
+ return size + (pe_size - delta);
+ else
+ return size - delta;
+}
+
+/**
+ * bd_lvm_get_lv_physical_size:
+ * @lv_size: LV size
+ * @pe_size: PE size
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: space taken on disk(s) by the LV with given @size
+ *
+ * Gives number of bytes needed for an LV with the size @lv_size on an LVM stack
+ * using given @pe_size.
+ *
+ * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
+ */
+guint64 bd_lvm_get_lv_physical_size (guint64 lv_size, guint64 pe_size, GError **error) {
+ pe_size = RESOLVE_PE_SIZE (pe_size);
+
+ /* the LV just takes space rounded up to the multiple of extent size */
+ return bd_lvm_round_size_to_pe (lv_size, pe_size, TRUE, error);
+}
+
+/**
+ * bd_lvm_get_thpool_padding:
+ * @size: size of the thin pool
+ * @pe_size: PE size or 0 if the default value should be used
+ * @included: if padding is already included in the size
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: size of the padding needed for a thin pool with the given @size
+ * according to the @pe_size and @included
+ *
+ * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
+ */
+guint64 bd_lvm_get_thpool_padding (guint64 size, guint64 pe_size, gboolean included, GError **error) {
+ guint64 raw_md_size;
+ pe_size = RESOLVE_PE_SIZE (pe_size);
+
+ if (included)
+ raw_md_size = (guint64) ceil (size * THPOOL_MD_FACTOR_EXISTS);
+ else
+ raw_md_size = (guint64) ceil (size * THPOOL_MD_FACTOR_NEW);
+
+ return MIN (bd_lvm_round_size_to_pe (raw_md_size, pe_size, TRUE, error),
+ bd_lvm_round_size_to_pe (MAX_THPOOL_MD_SIZE, pe_size, TRUE, error));
+}
+
+/**
+ * bd_lvm_get_thpool_meta_size:
+ * @size: size of the thin pool
+ * @chunk_size: chunk size of the thin pool or 0 to use the default
+ * @n_snapshots: ignored
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Note: This function will be changed in 3.0: the @n_snapshots parameter
+ * is currently not used and will be removed.
+ *
+ * Returns: recommended size of the metadata space for the specified pool
+ *
+ * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
+ */
+guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n_snapshots G_GNUC_UNUSED, GError **error G_GNUC_UNUSED) {
+ guint64 md_size = 0;
+
+ /* based on lvcreate metadata size calculation */
+ md_size = UINT64_C (64) * size / (chunk_size ? chunk_size : DEFAULT_CHUNK_SIZE);
+
+ if (md_size > MAX_THPOOL_MD_SIZE)
+ md_size = MAX_THPOOL_MD_SIZE;
+ else if (md_size < MIN_THPOOL_MD_SIZE)
+ md_size = MIN_THPOOL_MD_SIZE;
+
+ return md_size;
+}
+
+/**
+ * bd_lvm_is_valid_thpool_md_size:
+ * @size: the size to be tested
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: whether the given size is a valid thin pool metadata size or not
+ *
+ * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
+ */
+gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error G_GNUC_UNUSED) {
+ return ((MIN_THPOOL_MD_SIZE <= size) && (size <= MAX_THPOOL_MD_SIZE));
+}
+
+/**
+ * bd_lvm_is_valid_thpool_chunk_size:
+ * @size: the size to be tested
+ * @discard: whether discard/TRIM is required to be supported or not
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: whether the given size is a valid thin pool chunk size or not
+ *
+ * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
+ */
+gboolean bd_lvm_is_valid_thpool_chunk_size (guint64 size, gboolean discard, GError **error G_GNUC_UNUSED) {
+ gdouble size_log2 = 0.0;
+
+ if ((size < MIN_THPOOL_CHUNK_SIZE) || (size > MAX_THPOOL_CHUNK_SIZE))
+ return FALSE;
+
+ /* To support discard, chunk size must be a power of two. Otherwise it must be a
+ multiple of 64 KiB. */
+ if (discard) {
+ size_log2 = log2 ((double) size);
+ return ABS (((int) round (size_log2)) - size_log2) <= INT_FLOAT_EPS;
+ } else
+ return (size % (64 KiB)) == 0;
+}
+
+/**
+ * bd_lvm_cache_get_default_md_size:
+ * @cache_size: size of the cache to determine MD size for
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: recommended default size of the cache metadata LV or 0 in case of error
+ *
+ * Tech category: %BD_LVM_TECH_CACHE_CALCS no mode (it is ignored)
+ */
+guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error G_GNUC_UNUSED) {
+ return MAX ((guint64) cache_size / 1000, MIN_CACHE_MD_SIZE);
+}
+
+/**
+ * bd_lvm_set_global_config:
+ * @new_config: (nullable): string representation of the new global libblockdev LVM
+ * configuration to set or %NULL to reset to default
+ * @error: (out) (optional): place to store error (if any)
+ *
+ *
+ * Note: This function sets configuration options for LVM calls internally
+ * in libblockdev, it doesn't change the global lvm.conf config file.
+ * Calling this function with `backup {backup=0 archive=0}` for example
+ * means `--config=backup {backup=0 archive=0}"` will be added to all
+ * calls libblockdev makes.
+ *
+ * Returns: whether the new requested global config @new_config was successfully
+ * set or not
+ *
+ * Tech category: %BD_LVM_TECH_GLOB_CONF no mode (it is ignored)
+ */
+gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error G_GNUC_UNUSED) {
+ /* XXX: the error attribute will likely be used in the future when
+ some validation comes into the game */
+
+ g_mutex_lock (&global_config_lock);
+
+ /* first free the old value */
+ g_free (global_config_str);
+
+ /* now store the new one */
+ if (!new_config || g_strcmp0 (new_config, "") == 0)
+ global_config_str = NULL;
+ else
+ global_config_str = g_strdup (new_config);
+
+ g_mutex_unlock (&global_config_lock);
+ return TRUE;
+}
+
+/**
+ * bd_lvm_get_global_config:
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: (transfer full): a copy of a string representation of the currently
+ * set libblockdev LVM global configuration
+ *
+ * Note: This function does not change the global `lvm.conf` config
+ * file, see %bd_lvm_set_global_config for details.
+ *
+ * Tech category: %BD_LVM_TECH_GLOB_CONF no mode (it is ignored)
+ */
+gchar* bd_lvm_get_global_config (GError **error G_GNUC_UNUSED) {
+ gchar *ret = NULL;
+
+ g_mutex_lock (&global_config_lock);
+ ret = g_strdup (global_config_str ? global_config_str : "");
+ g_mutex_unlock (&global_config_lock);
+
+ return ret;
+}
+
+/**
+ * bd_lvm_set_devices_filter:
+ * @devices: (nullable) (array zero-terminated=1): list of devices for lvm commands to work on
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: whether the devices filter was successfully set or not
+ *
+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored)
+ */
+gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error) {
+ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error))
+ return FALSE;
+
+ g_mutex_lock (&global_config_lock);
+
+ /* first free the old value */
+ g_free (global_devices_str);
+
+ /* now store the new one */
+ if (!devices || !(*devices))
+ global_devices_str = NULL;
+ else
+ global_devices_str = g_strjoinv (",", (gchar **) devices);
+
+ g_mutex_unlock (&global_config_lock);
+ return TRUE;
+}
+
+/**
+ * bd_lvm_get_devices_filter:
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: (transfer full) (array zero-terminated=1): a copy of a string representation of
+ * the currently set LVM devices filter
+ *
+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored)
+ */
+gchar** bd_lvm_get_devices_filter (GError **error G_GNUC_UNUSED) {
+ gchar **ret = NULL;
+
+ g_mutex_lock (&global_config_lock);
+
+ if (global_devices_str)
+ ret = g_strsplit (global_devices_str, ",", -1);
+ else
+ ret = NULL;
+
+ g_mutex_unlock (&global_config_lock);
+
+ return ret;
+}
+
+/**
+ * bd_lvm_cache_get_mode_str:
+ * @mode: mode to get the string representation for
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: string representation of @mode or %NULL in case of error
+ *
+ * Tech category: always provided/supported
+ */
+const gchar* bd_lvm_cache_get_mode_str (BDLVMCacheMode mode, GError **error) {
+ if (mode == BD_LVM_CACHE_MODE_WRITETHROUGH)
+ return "writethrough";
+ else if (mode == BD_LVM_CACHE_MODE_WRITEBACK)
+ return "writeback";
+ else if (mode == BD_LVM_CACHE_MODE_UNKNOWN)
+ return "unknown";
+ else {
+ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_CACHE_INVAL,
+ "Invalid mode given: %d", mode);
+ return NULL;
+ }
+}
+
+/**
+ * bd_lvm_cache_get_mode_from_str:
+ * @mode_str: string representation of a cache mode
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: cache mode for the @mode_str or %BD_LVM_CACHE_MODE_UNKNOWN if
+ * failed to determine
+ *
+ * Tech category: always provided/supported
+ */
+BDLVMCacheMode bd_lvm_cache_get_mode_from_str (const gchar *mode_str, GError **error) {
+ if (g_strcmp0 (mode_str, "writethrough") == 0)
+ return BD_LVM_CACHE_MODE_WRITETHROUGH;
+ else if (g_strcmp0 (mode_str, "writeback") == 0)
+ return BD_LVM_CACHE_MODE_WRITEBACK;
+ else if (g_strcmp0 (mode_str, "unknown") == 0)
+ return BD_LVM_CACHE_MODE_UNKNOWN;
+ else {
+ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_CACHE_INVAL,
+ "Invalid mode given: %s", mode_str);
+ return BD_LVM_CACHE_MODE_UNKNOWN;
+ }
+}
+
+/**
+ * bd_lvm_get_vdo_operating_mode_str:
+ * @mode: mode to get the string representation for
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: string representation of @mode or %NULL in case of error
+ *
+ * Tech category: always provided/supported
+ */
+const gchar* bd_lvm_get_vdo_operating_mode_str (BDLVMVDOOperatingMode mode, GError **error) {
+ switch (mode) {
+ case BD_LVM_VDO_MODE_RECOVERING:
+ return "recovering";
+ case BD_LVM_VDO_MODE_READ_ONLY:
+ return "read-only";
+ case BD_LVM_VDO_MODE_NORMAL:
+ return "normal";
+ case BD_LVM_VDO_MODE_UNKNOWN:
+ return "unknown";
+ default:
+ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
+ "Invalid LVM VDO operating mode.");
+ return NULL;
+ }
+}
+
+/**
+ * bd_lvm_get_vdo_compression_state_str:
+ * @state: state to get the string representation for
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: string representation of @state or %NULL in case of error
+ *
+ * Tech category: always provided/supported
+ */
+const gchar* bd_lvm_get_vdo_compression_state_str (BDLVMVDOCompressionState state, GError **error) {
+ switch (state) {
+ case BD_LVM_VDO_COMPRESSION_ONLINE:
+ return "online";
+ case BD_LVM_VDO_COMPRESSION_OFFLINE:
+ return "offline";
+ case BD_LVM_VDO_COMPRESSION_UNKNOWN:
+ return "unknown";
+ default:
+ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
+ "Invalid LVM VDO compression state.");
+ return NULL;
+ }
+}
+
+/**
+ * bd_lvm_get_vdo_index_state_str:
+ * @state: state to get the string representation for
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: string representation of @state or %NULL in case of error
+ *
+ * Tech category: always provided/supported
+ */
+const gchar* bd_lvm_get_vdo_index_state_str (BDLVMVDOIndexState state, GError **error) {
+ switch (state) {
+ case BD_LVM_VDO_INDEX_ERROR:
+ return "error";
+ case BD_LVM_VDO_INDEX_CLOSED:
+ return "closed";
+ case BD_LVM_VDO_INDEX_OPENING:
+ return "opening";
+ case BD_LVM_VDO_INDEX_CLOSING:
+ return "closing";
+ case BD_LVM_VDO_INDEX_OFFLINE:
+ return "offline";
+ case BD_LVM_VDO_INDEX_ONLINE:
+ return "online";
+ case BD_LVM_VDO_INDEX_UNKNOWN:
+ return "unknown";
+ default:
+ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
+ "Invalid LVM VDO index state.");
+ return NULL;
+ }
+}
+
+/**
+ * bd_lvm_get_vdo_write_policy_str:
+ * @policy: policy to get the string representation for
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: string representation of @policy or %NULL in case of error
+ *
+ * Tech category: always provided/supported
+ */
+const gchar* bd_lvm_get_vdo_write_policy_str (BDLVMVDOWritePolicy policy, GError **error) {
+ switch (policy) {
+ case BD_LVM_VDO_WRITE_POLICY_AUTO:
+ return "auto";
+ case BD_LVM_VDO_WRITE_POLICY_SYNC:
+ return "sync";
+ case BD_LVM_VDO_WRITE_POLICY_ASYNC:
+ return "async";
+ case BD_LVM_VDO_WRITE_POLICY_UNKNOWN:
+ return "unknown";
+ default:
+ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
+ "Invalid LVM VDO write policy.");
+ return NULL;
+ }
+}
+
+/**
+ * bd_lvm_get_vdo_write_policy_from_str:
+ * @policy_str: string representation of a policy
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: write policy for the @policy_str or %BD_LVM_VDO_WRITE_POLICY_UNKNOWN if
+ * failed to determine
+ *
+ * Tech category: always provided/supported
+ */
+BDLVMVDOWritePolicy bd_lvm_get_vdo_write_policy_from_str (const gchar *policy_str, GError **error) {
+ if (g_strcmp0 (policy_str, "auto") == 0)
+ return BD_LVM_VDO_WRITE_POLICY_AUTO;
+ else if (g_strcmp0 (policy_str, "sync") == 0)
+ return BD_LVM_VDO_WRITE_POLICY_SYNC;
+ else if (g_strcmp0 (policy_str, "async") == 0)
+ return BD_LVM_VDO_WRITE_POLICY_ASYNC;
+ else {
+ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_VDO_POLICY_INVAL,
+ "Invalid policy given: %s", policy_str);
+ return BD_LVM_VDO_WRITE_POLICY_UNKNOWN;
+ }
+}
+
+/**
+ * bd_lvm_vdo_get_stats_full:
+ * @vg_name: name of the VG that contains @pool_name VDO pool
+ * @pool_name: name of the VDO pool to get statistics for
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: (transfer full) (element-type utf8 utf8): hashtable of type string - string of available
+ * statistics or %NULL in case of error
+ * (@error gets populated in those cases)
+ *
+ * Statistics are collected from the values exposed by the kernel `dm-vdo` module.
+ *
+ * Some of the keys are computed to mimic the information produced by the vdo tools.
+ * Please note the contents of the hashtable may vary depending on the actual dm-vdo module version.
+ *
+ * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_QUERY
+ */
+GHashTable* bd_lvm_vdo_get_stats_full (const gchar *vg_name, const gchar *pool_name, GError **error) {
+ g_autofree gchar *kvdo_name = g_strdup_printf ("%s-%s-%s", vg_name, pool_name, VDO_POOL_SUFFIX);
+ return vdo_get_stats_full (kvdo_name, error);
+}
+
+/**
+ * bd_lvm_vdo_get_stats:
+ * @vg_name: name of the VG that contains @pool_name VDO pool
+ * @pool_name: name of the VDO pool to get statistics for
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: (transfer full): a structure containing selected statistics or %NULL in case of error
+ * (@error gets populated in those cases)
+ *
+ * In contrast to @bd_lvm_vdo_get_stats_full this function will only return selected statistics
+ * in a fixed structure. In case a value is not available, -1 would be returned.
+ *
+ * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_QUERY
+ */
+BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_name, GError **error) {
+ GHashTable *full_stats = NULL;
+ BDLVMVDOStats *stats = NULL;
+
+ full_stats = bd_lvm_vdo_get_stats_full (vg_name, pool_name, error);
+ if (!full_stats)
+ return NULL;
+
+ stats = g_new0 (BDLVMVDOStats, 1);
+ get_stat_val64_default (full_stats, "blockSize", &stats->block_size, -1);
+ get_stat_val64_default (full_stats, "logicalBlockSize", &stats->logical_block_size, -1);
+ get_stat_val64_default (full_stats, "physicalBlocks", &stats->physical_blocks, -1);
+ get_stat_val64_default (full_stats, "dataBlocksUsed", &stats->data_blocks_used, -1);
+ get_stat_val64_default (full_stats, "overheadBlocksUsed", &stats->overhead_blocks_used, -1);
+ get_stat_val64_default (full_stats, "logicalBlocksUsed", &stats->logical_blocks_used, -1);
+ get_stat_val64_default (full_stats, "usedPercent", &stats->used_percent, -1);
+ get_stat_val64_default (full_stats, "savingPercent", &stats->saving_percent, -1);
+ if (!get_stat_val_double (full_stats, "writeAmplificationRatio", &stats->write_amplification_ratio))
+ stats->write_amplification_ratio = -1;
+
+ g_hash_table_destroy (full_stats);
+
+ return stats;
+}
+
+/* check whether the LVM devices file is enabled by LVM
+ * we use the existence of the "lvmdevices" command to check whether the feature is available
+ * or not, but this can still be disabled either in LVM or in lvm.conf
+ */
+static gboolean _lvm_devices_enabled () {
+ const gchar *args[6] = {"lvmconfig", "--typeconfig", NULL, "devices/use_devicesfile", NULL, NULL};
+ gboolean ret = FALSE;
+ GError *loc_error = NULL;
+ gchar *output = NULL;
+ gboolean enabled = FALSE;
+ gint scanned = 0;
+ g_autofree gchar *config_arg = NULL;
+
+ /* try full config first -- if we get something from this it means the feature is
+ explicitly enabled or disabled by system lvm.conf or using the --config option */
+ args[2] = "full";
+
+ /* make sure to include the global config from us when getting the current config value */
+ g_mutex_lock (&global_config_lock);
+ if (global_config_str) {
+ config_arg = g_strdup_printf ("--config=%s", global_config_str);
+ args[4] = config_arg;
+ }
+
+ ret = bd_utils_exec_and_capture_output (args, NULL, &output, &loc_error);
+ g_mutex_unlock (&global_config_lock);
+ if (ret) {
+ scanned = sscanf (output, "use_devicesfile=%u", &enabled);
+ g_free (output);
+ if (scanned != 1)
+ return FALSE;
+
+ return enabled;
+ } else {
+ g_clear_error (&loc_error);
+ g_free (output);
+ }
+
+ output = NULL;
+
+ /* now try default */
+ args[2] = "default";
+ ret = bd_utils_exec_and_capture_output (args, NULL, &output, &loc_error);
+ if (ret) {
+ scanned = sscanf (output, "# use_devicesfile=%u", &enabled);
+ g_free (output);
+ if (scanned != 1)
+ return FALSE;
+
+ return enabled;
+ } else {
+ g_clear_error (&loc_error);
+ g_free (output);
+ }
+
+ return FALSE;
+}
+
+/**
+ * bd_lvm_devices_add:
+ * @device: device (PV) to add to the devices file
+ * @devices_file: (nullable): LVM devices file or %NULL for default
+ * @extra: (nullable) (array zero-terminated=1): extra options for the lvmdevices command
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: whether the @device was successfully added to @devices_file or not
+ *
+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored)
+ */
+gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) {
+ const gchar *args[5] = {"lvmdevices", "--adddev", device, NULL, NULL};
+ g_autofree gchar *devfile = NULL;
+
+ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error))
+ return FALSE;
+
+ if (!_lvm_devices_enabled ()) {
+ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED,
+ "LVM devices file not enabled.");
+ return FALSE;
+ }
+
+ if (devices_file) {
+ devfile = g_strdup_printf ("--devicesfile=%s", devices_file);
+ args[3] = devfile;
+ }
+
+ return bd_utils_exec_and_report_error (args, extra, error);
+}
+
+/**
+ * bd_lvm_devices_delete:
+ * @device: device (PV) to delete from the devices file
+ * @devices_file: (nullable): LVM devices file or %NULL for default
+ * @extra: (nullable) (array zero-terminated=1): extra options for the lvmdevices command
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: whether the @device was successfully removed from @devices_file or not
+ *
+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored)
+ */
+gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) {
+ const gchar *args[5] = {"lvmdevices", "--deldev", device, NULL, NULL};
+ g_autofree gchar *devfile = NULL;
+
+ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error))
+ return FALSE;
+
+ if (!_lvm_devices_enabled ()) {
+ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED,
+ "LVM devices file not enabled.");
+ return FALSE;
+ }
+
+ if (devices_file) {
+ devfile = g_strdup_printf ("--devicesfile=%s", devices_file);
+ args[3] = devfile;
+ }
+
+ return bd_utils_exec_and_report_error (args, extra, error);
+}
+
+/**
+ * bd_lvm_config_get:
+ * @section: (nullable): LVM config section, e.g. 'global' or %NULL to print the entire config
+ * @setting: (nullable): name of the specific setting, e.g. 'umask' or %NULL to print the entire @section
+ * @type: type of the config, e.g. 'full' or 'current'
+ * @values_only: whether to include only values without keys in the output
+ * @global_config: whether to include our internal global config in the call or not
+ * @extra: (nullable) (array zero-terminated=1): extra options for the lvmconfig command
+ * (just passed to LVM as is)
+ * @error: (out) (optional): place to store error (if any)
+ *
+ * Returns: (transfer full): Requested LVM config @section and @setting configuration or %NULL in case of error.
+ *
+ * Tech category: %BD_LVM_TECH_CONFIG no mode (it is ignored)
+ */
+gchar* bd_lvm_config_get (const gchar *section, const gchar *setting, const gchar *type, gboolean values_only, gboolean global_config, const BDExtraArg **extra, GError **error) {
+ g_autofree gchar *conf_spec = NULL;
+ g_autofree gchar *config_arg = NULL;
+ const gchar *args[7] = {"lvmconfig", "--typeconfig", NULL, NULL, NULL, NULL, NULL};
+ guint next_arg = 2;
+ gchar *output = NULL;
+ gboolean success = FALSE;
+
+ if (!section && setting) {
+ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
+ "Specifying setting without section is not supported.");
+ return NULL;
+ }
+
+ if (section)
+ if (setting)
+ conf_spec = g_strdup_printf ("%s/%s", section, setting);
+ else
+ conf_spec = g_strdup (section);
+ else
+ conf_spec = NULL;
+
+ args[next_arg++] = type;
+ args[next_arg++] = conf_spec;
+ if (values_only)
+ args[next_arg++] = "--valuesonly";
+
+ g_mutex_lock (&global_config_lock);
+ if (global_config && global_config_str) {
+ config_arg = g_strdup_printf ("--config=%s", global_config_str);
+ args[next_arg++] = config_arg;
+ }
+ g_mutex_unlock (&global_config_lock);
+
+ success = bd_utils_exec_and_capture_output (args, extra, &output, error);
+ if (!success)
+ return NULL;
+ return g_strchomp (output);
+}
diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm/lvm-dbus.c
similarity index 85%
rename from src/plugins/lvm-dbus.c
rename to src/plugins/lvm/lvm-dbus.c
index 01ba5c44..a2e54e92 100644
--- a/src/plugins/lvm-dbus.c
+++ b/src/plugins/lvm/lvm-dbus.c
@@ -26,49 +26,11 @@
#include
#include "lvm.h"
+#include "lvm-private.h"
#include "check_deps.h"
#include "dm_logging.h"
#include "vdo_stats.h"
-#define INT_FLOAT_EPS 1e-5
-#define SECTOR_SIZE 512
-#define VDO_POOL_SUFFIX "vpool"
-#define DEFAULT_PE_SIZE (4 MiB)
-#define USE_DEFAULT_PE_SIZE 0
-#define RESOLVE_PE_SIZE(size) ((size) == USE_DEFAULT_PE_SIZE ? DEFAULT_PE_SIZE : (size))
-#define THPOOL_MD_FACTOR_NEW (0.2)
-#define THPOOL_MD_FACTOR_EXISTS (1 / 6.0)
-
-#define MIN_PE_SIZE (1 KiB)
-#define MAX_PE_SIZE (16 GiB)
-
-#define MIN_THPOOL_MD_SIZE (4 MiB)
-/* DM_THIN_MAX_METADATA_SIZE is in 512 sectors */
-#define MAX_THPOOL_MD_SIZE (DM_THIN_MAX_METADATA_SIZE * 512)
-
-#define MIN_THPOOL_CHUNK_SIZE (64 KiB)
-#define MAX_THPOOL_CHUNK_SIZE (1 GiB)
-#define DEFAULT_CHUNK_SIZE (64 KiB)
-
-/* according to lvmcache (7) */
-#define MIN_CACHE_MD_SIZE (8 MiB)
-
-#define LVM_MIN_VERSION "2.02.116"
-#define LVM_VERSION_FSRESIZE "2.03.19"
-
-#ifdef __LP64__
-/* 64bit system */
-#define MAX_LV_SIZE (8 EiB)
-#else
-/* 32bit system */
-#define MAX_LV_SIZE (16 TiB)
-#endif
-
-static GMutex global_config_lock;
-static gchar *global_config_str = NULL;
-
-static gchar *global_devices_str = NULL;
-
#define LVM_BUS_NAME "com.redhat.lvmdbus1"
#define LVM_OBJ_PREFIX "/com/redhat/lvmdbus1"
#define MANAGER_OBJ "/com/redhat/lvmdbus1/Manager"
@@ -1541,192 +1503,6 @@ static GVariant* create_size_str_param (guint64 size, const gchar *unit) {
return g_variant_new_take_string (str);
}
-/**
- * bd_lvm_is_supported_pe_size:
- * @size: size (in bytes) to test
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: whether the given size is supported physical extent size or not
- *
- * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
- */
-gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error G_GNUC_UNUSED) {
- return (((size % 2) == 0) && (size >= (MIN_PE_SIZE)) && (size <= (MAX_PE_SIZE)));
-}
-
-/**
- * bd_lvm_get_supported_pe_sizes:
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: (transfer full) (array fixed-size=25): list of supported PE sizes
- *
- * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
- */
-guint64 *bd_lvm_get_supported_pe_sizes (GError **error G_GNUC_UNUSED) {
- guint8 i;
- guint64 val = MIN_PE_SIZE;
- guint8 num_items = ((guint8) round (log2 ((double) MAX_PE_SIZE))) - ((guint8) round (log2 ((double) MIN_PE_SIZE))) + 2;
- guint64 *ret = g_new0 (guint64, num_items);
-
- for (i=0; (val <= MAX_PE_SIZE); i++, val = val * 2)
- ret[i] = val;
-
- ret[num_items-1] = 0;
-
- return ret;
-}
-
-/**
- * bd_lvm_get_max_lv_size:
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: maximum LV size in bytes
- *
- * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
- */
-guint64 bd_lvm_get_max_lv_size (GError **error G_GNUC_UNUSED) {
- return MAX_LV_SIZE;
-}
-
-/**
- * bd_lvm_round_size_to_pe:
- * @size: size to be rounded
- * @pe_size: physical extent (PE) size or 0 to use the default
- * @roundup: whether to round up or down (ceil or floor)
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: @size rounded to @pe_size according to the @roundup
- *
- * Rounds given @size up/down to a multiple of @pe_size according to the value
- * of the @roundup parameter. If the rounded value is too big to fit in the
- * return type, the result is rounded down (floored) regardless of the @roundup
- * parameter.
- *
- * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
- */
-guint64 bd_lvm_round_size_to_pe (guint64 size, guint64 pe_size, gboolean roundup, GError **error G_GNUC_UNUSED) {
- pe_size = RESOLVE_PE_SIZE (pe_size);
- guint64 delta = size % pe_size;
- if (delta == 0)
- return size;
-
- if (roundup && (((G_MAXUINT64 - (pe_size - delta)) >= size)))
- return size + (pe_size - delta);
- else
- return size - delta;
-}
-
-/**
- * bd_lvm_get_lv_physical_size:
- * @lv_size: LV size
- * @pe_size: PE size
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: space taken on disk(s) by the LV with given @size
- *
- * Gives number of bytes needed for an LV with the size @lv_size on an LVM stack
- * using given @pe_size.
- *
- * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
- */
-guint64 bd_lvm_get_lv_physical_size (guint64 lv_size, guint64 pe_size, GError **error) {
- pe_size = RESOLVE_PE_SIZE (pe_size);
-
- /* the LV just takes space rounded up to the multiple of extent size */
- return bd_lvm_round_size_to_pe (lv_size, pe_size, TRUE, error);
-}
-
-/**
- * bd_lvm_get_thpool_padding:
- * @size: size of the thin pool
- * @pe_size: PE size or 0 if the default value should be used
- * @included: if padding is already included in the size
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: size of the padding needed for a thin pool with the given @size
- * according to the @pe_size and @included
- *
- * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
- */
-guint64 bd_lvm_get_thpool_padding (guint64 size, guint64 pe_size, gboolean included, GError **error G_GNUC_UNUSED) {
- guint64 raw_md_size;
- pe_size = RESOLVE_PE_SIZE (pe_size);
-
- if (included)
- raw_md_size = (guint64) ceil (size * THPOOL_MD_FACTOR_EXISTS);
- else
- raw_md_size = (guint64) ceil (size * THPOOL_MD_FACTOR_NEW);
-
- return MIN (bd_lvm_round_size_to_pe (raw_md_size, pe_size, TRUE, NULL),
- bd_lvm_round_size_to_pe (MAX_THPOOL_MD_SIZE, pe_size, TRUE, NULL));
-}
-
-/**
- * bd_lvm_get_thpool_meta_size:
- * @size: size of the thin pool
- * @chunk_size: chunk size of the thin pool or 0 to use the default
- * @n_snapshots: ignored
- * @error: (out) (optional): place to store error (if any)
- *
- * Note: This function will be changed in 3.0: the @n_snapshots parameter
- * is currently not used and will be removed.
- *
- * Returns: recommended size of the metadata space for the specified pool
- *
- * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
- */
-guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n_snapshots G_GNUC_UNUSED, GError **error G_GNUC_UNUSED) {
- guint64 md_size = 0;
-
- /* based on lvcreate metadata size calculation */
- md_size = UINT64_C (64) * size / (chunk_size ? chunk_size : DEFAULT_CHUNK_SIZE);
-
- if (md_size > MAX_THPOOL_MD_SIZE)
- md_size = MAX_THPOOL_MD_SIZE;
- else if (md_size < MIN_THPOOL_MD_SIZE)
- md_size = MIN_THPOOL_MD_SIZE;
-
- return md_size;
-}
-
-/**
- * bd_lvm_is_valid_thpool_md_size:
- * @size: the size to be tested
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: whether the given size is a valid thin pool metadata size or not
- *
- * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
- */
-gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error G_GNUC_UNUSED) {
- return ((MIN_THPOOL_MD_SIZE <= size) && (size <= MAX_THPOOL_MD_SIZE));
-}
-
-/**
- * bd_lvm_is_valid_thpool_chunk_size:
- * @size: the size to be tested
- * @discard: whether discard/TRIM is required to be supported or not
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: whether the given size is a valid thin pool chunk size or not
- *
- * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
- */
-gboolean bd_lvm_is_valid_thpool_chunk_size (guint64 size, gboolean discard, GError **error G_GNUC_UNUSED) {
- gdouble size_log2 = 0.0;
-
- if ((size < MIN_THPOOL_CHUNK_SIZE) || (size > MAX_THPOOL_CHUNK_SIZE))
- return FALSE;
-
- /* To support discard, chunk size must be a power of two. Otherwise it must be a
- multiple of 64 KiB. */
- if (discard) {
- size_log2 = log2 ((double) size);
- return ABS (((int) round (size_log2)) - size_log2) <= INT_FLOAT_EPS;
- } else
- return (size % (64 KiB)) == 0;
-}
-
/**
* bd_lvm_pvcreate:
* @device: the device to make PV from
@@ -3445,130 +3221,6 @@ gboolean bd_lvm_thsnapshotcreate (const gchar *vg_name, const gchar *origin_name
return call_lv_method_sync (vg_name, origin_name, "Snapshot", params, extra_params, extra, TRUE, error);
}
-/**
- * bd_lvm_set_global_config:
- * @new_config: (nullable): string representation of the new global libblockdev LVM
- * configuration to set or %NULL to reset to default
- * @error: (out) (optional): place to store error (if any)
- *
- *
- * Note: This function sets configuration options for LVM calls internally
- * in libblockdev, it doesn't change the global lvm.conf config file.
- * Calling this function with `backup {backup=0 archive=0}` for example
- * means `--config=backup {backup=0 archive=0}"` will be added to all
- * calls libblockdev makes.
- *
- * Returns: whether the new requested global config @new_config was successfully
- * set or not
- *
- * Tech category: %BD_LVM_TECH_GLOB_CONF no mode (it is ignored)
- */
-gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error G_GNUC_UNUSED) {
- /* XXX: the error attribute will likely be used in the future when
- some validation comes into the game */
-
- g_mutex_lock (&global_config_lock);
-
- /* first free the old value */
- g_free (global_config_str);
-
- /* now store the new one */
- if (!new_config || g_strcmp0 (new_config, "") == 0)
- global_config_str = NULL;
- else
- global_config_str = g_strdup (new_config);
-
- g_mutex_unlock (&global_config_lock);
- return TRUE;
-}
-
-/**
- * bd_lvm_get_global_config:
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: (transfer full): a copy of a string representation of the currently
- * set libblockdev LVM global configuration
- *
- * Note: This function does not change the global `lvm.conf` config
- * file, see %bd_lvm_set_global_config for details.
- *
- * Tech category: %BD_LVM_TECH_GLOB_CONF no mode (it is ignored)
- */
-gchar* bd_lvm_get_global_config (GError **error G_GNUC_UNUSED) {
- gchar *ret = NULL;
-
- g_mutex_lock (&global_config_lock);
- ret = g_strdup (global_config_str ? global_config_str : "");
- g_mutex_unlock (&global_config_lock);
-
- return ret;
-}
-
-/**
- * bd_lvm_set_devices_filter:
- * @devices: (nullable) (array zero-terminated=1): list of devices for lvm commands to work on
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: whether the devices filter was successfully set or not
- *
- * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored)
- */
-gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error) {
- if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error))
- return FALSE;
-
- g_mutex_lock (&global_config_lock);
-
- /* first free the old value */
- g_free (global_devices_str);
-
- /* now store the new one */
- if (!devices || !(*devices))
- global_devices_str = NULL;
- else
- global_devices_str = g_strjoinv (",", (gchar **) devices);
-
- g_mutex_unlock (&global_config_lock);
- return TRUE;
-}
-
-/**
- * bd_lvm_get_devices_filter:
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: (transfer full) (array zero-terminated=1): a copy of a string representation of
- * the currently set LVM devices filter
- *
- * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored)
- */
-gchar** bd_lvm_get_devices_filter (GError **error G_GNUC_UNUSED) {
- gchar **ret = NULL;
-
- g_mutex_lock (&global_config_lock);
-
- if (global_devices_str)
- ret = g_strsplit (global_devices_str, ",", -1);
- else
- ret = NULL;
-
- g_mutex_unlock (&global_config_lock);
-
- return ret;
-}
-
-/**
- * bd_lvm_cache_get_default_md_size:
- * @cache_size: size of the cache to determine MD size for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: recommended default size of the cache metadata LV or 0 in case of error
- *
- * Tech category: %BD_LVM_TECH_CACHE_CALCS no mode (it is ignored)
- */
-guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error G_GNUC_UNUSED) {
- return MAX ((guint64) cache_size / 1000, MIN_CACHE_MD_SIZE);
-}
-
/**
* get_lv_type_from_flags: (skip)
* @meta: getting type for a (future) metadata LV
@@ -3605,53 +3257,6 @@ static const gchar* get_lv_type_from_flags (BDLVMCachePoolFlags flags, gboolean
}
}
-/**
- * bd_lvm_cache_get_mode_str:
- * @mode: mode to get the string representation for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: string representation of @mode or %NULL in case of error
- *
- * Tech category: always provided/supported
- */
-const gchar* bd_lvm_cache_get_mode_str (BDLVMCacheMode mode, GError **error) {
- if (mode == BD_LVM_CACHE_MODE_WRITETHROUGH)
- return "writethrough";
- else if (mode == BD_LVM_CACHE_MODE_WRITEBACK)
- return "writeback";
- else if (mode == BD_LVM_CACHE_MODE_UNKNOWN)
- return "unknown";
- else {
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_CACHE_INVAL,
- "Invalid mode given: %d", mode);
- return NULL;
- }
-}
-
-/**
- * bd_lvm_cache_get_mode_from_str:
- * @mode_str: string representation of a cache mode
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: cache mode for the @mode_str or %BD_LVM_CACHE_MODE_UNKNOWN if
- * failed to determine
- *
- * Tech category: always provided/supported
- */
-BDLVMCacheMode bd_lvm_cache_get_mode_from_str (const gchar *mode_str, GError **error) {
- if (g_strcmp0 (mode_str, "writethrough") == 0)
- return BD_LVM_CACHE_MODE_WRITETHROUGH;
- else if (g_strcmp0 (mode_str, "writeback") == 0)
- return BD_LVM_CACHE_MODE_WRITEBACK;
- else if (g_strcmp0 (mode_str, "unknown") == 0)
- return BD_LVM_CACHE_MODE_UNKNOWN;
- else {
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_CACHE_INVAL,
- "Invalid mode given: %s", mode_str);
- return BD_LVM_CACHE_MODE_UNKNOWN;
- }
-}
-
/**
* bd_lvm_cache_create_pool:
* @vg_name: name of the VG to create @pool_name in
@@ -4608,372 +4213,15 @@ gchar* bd_lvm_vdolvpoolname (const gchar *vg_name, const gchar *lv_name, GError
return ret;
}
-/**
- * bd_lvm_get_vdo_operating_mode_str:
- * @mode: mode to get the string representation for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: string representation of @mode or %NULL in case of error
- *
- * Tech category: always provided/supported
- */
-const gchar* bd_lvm_get_vdo_operating_mode_str (BDLVMVDOOperatingMode mode, GError **error) {
- switch (mode) {
- case BD_LVM_VDO_MODE_RECOVERING:
- return "recovering";
- case BD_LVM_VDO_MODE_READ_ONLY:
- return "read-only";
- case BD_LVM_VDO_MODE_NORMAL:
- return "normal";
- case BD_LVM_VDO_MODE_UNKNOWN:
- return "unknown";
- default:
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
- "Invalid LVM VDO operating mode.");
- return NULL;
- }
-}
-
-/**
- * bd_lvm_get_vdo_compression_state_str:
- * @state: state to get the string representation for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: string representation of @state or %NULL in case of error
- *
- * Tech category: always provided/supported
- */
-const gchar* bd_lvm_get_vdo_compression_state_str (BDLVMVDOCompressionState state, GError **error) {
- switch (state) {
- case BD_LVM_VDO_COMPRESSION_ONLINE:
- return "online";
- case BD_LVM_VDO_COMPRESSION_OFFLINE:
- return "offline";
- case BD_LVM_VDO_COMPRESSION_UNKNOWN:
- return "unknown";
- default:
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
- "Invalid LVM VDO compression state.");
- return NULL;
- }
-}
-
-/**
- * bd_lvm_get_vdo_index_state_str:
- * @state: state to get the string representation for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: string representation of @state or %NULL in case of error
- *
- * Tech category: always provided/supported
- */
-const gchar* bd_lvm_get_vdo_index_state_str (BDLVMVDOIndexState state, GError **error) {
- switch (state) {
- case BD_LVM_VDO_INDEX_ERROR:
- return "error";
- case BD_LVM_VDO_INDEX_CLOSED:
- return "closed";
- case BD_LVM_VDO_INDEX_OPENING:
- return "opening";
- case BD_LVM_VDO_INDEX_CLOSING:
- return "closing";
- case BD_LVM_VDO_INDEX_OFFLINE:
- return "offline";
- case BD_LVM_VDO_INDEX_ONLINE:
- return "online";
- case BD_LVM_VDO_INDEX_UNKNOWN:
- return "unknown";
- default:
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
- "Invalid LVM VDO index state.");
- return NULL;
- }
-}
-
-/**
- * bd_lvm_get_vdo_write_policy_str:
- * @policy: policy to get the string representation for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: string representation of @policy or %NULL in case of error
- *
- * Tech category: always provided/supported
- */
-const gchar* bd_lvm_get_vdo_write_policy_str (BDLVMVDOWritePolicy policy, GError **error) {
- switch (policy) {
- case BD_LVM_VDO_WRITE_POLICY_AUTO:
- return "auto";
- case BD_LVM_VDO_WRITE_POLICY_SYNC:
- return "sync";
- case BD_LVM_VDO_WRITE_POLICY_ASYNC:
- return "async";
- case BD_LVM_VDO_WRITE_POLICY_UNKNOWN:
- return "unknown";
- default:
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
- "Invalid LVM VDO write policy.");
- return NULL;
- }
-}
-
-/**
- * bd_lvm_get_vdo_write_policy_from_str:
- * @policy_str: string representation of a policy
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: write policy for the @policy_str or %BD_LVM_VDO_WRITE_POLICY_UNKNOWN if
- * failed to determine
- *
- * Tech category: always provided/supported
- */
-BDLVMVDOWritePolicy bd_lvm_get_vdo_write_policy_from_str (const gchar *policy_str, GError **error) {
- if (g_strcmp0 (policy_str, "auto") == 0)
- return BD_LVM_VDO_WRITE_POLICY_AUTO;
- else if (g_strcmp0 (policy_str, "sync") == 0)
- return BD_LVM_VDO_WRITE_POLICY_SYNC;
- else if (g_strcmp0 (policy_str, "async") == 0)
- return BD_LVM_VDO_WRITE_POLICY_ASYNC;
- else {
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_VDO_POLICY_INVAL,
- "Invalid policy given: %s", policy_str);
- return BD_LVM_VDO_WRITE_POLICY_UNKNOWN;
- }
-}
-
-/**
- * bd_lvm_vdo_get_stats_full:
- * @vg_name: name of the VG that contains @pool_name VDO pool
- * @pool_name: name of the VDO pool to get statistics for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: (transfer full) (element-type utf8 utf8): hashtable of type string - string of available
- * statistics or %NULL in case of error
- * (@error gets populated in those cases)
- *
- * Statistics are collected from the values exposed by the kernel `dm-vdo` module.
- *
- * Some of the keys are computed to mimic the information produced by the vdo tools.
- * Please note the contents of the hashtable may vary depending on the actual dm-vdo module version.
- *
- * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_QUERY
- */
-GHashTable* bd_lvm_vdo_get_stats_full (const gchar *vg_name, const gchar *pool_name, GError **error) {
- g_autofree gchar *kvdo_name = g_strdup_printf ("%s-%s-%s", vg_name, pool_name, VDO_POOL_SUFFIX);
- return vdo_get_stats_full (kvdo_name, error);
-}
-
-/**
- * bd_lvm_vdo_get_stats:
- * @vg_name: name of the VG that contains @pool_name VDO pool
- * @pool_name: name of the VDO pool to get statistics for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: (transfer full): a structure containing selected statistics or %NULL in case of error
- * (@error gets populated in those cases)
- *
- * In contrast to @bd_lvm_vdo_get_stats_full this function will only return selected statistics
- * in a fixed structure. In case a value is not available, -1 would be returned.
- *
- * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_QUERY
- */
-BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_name, GError **error) {
- GHashTable *full_stats = NULL;
- BDLVMVDOStats *stats = NULL;
-
- full_stats = bd_lvm_vdo_get_stats_full (vg_name, pool_name, error);
- if (!full_stats)
- return NULL;
-
- stats = g_new0 (BDLVMVDOStats, 1);
- get_stat_val64_default (full_stats, "blockSize", &stats->block_size, -1);
- get_stat_val64_default (full_stats, "logicalBlockSize", &stats->logical_block_size, -1);
- get_stat_val64_default (full_stats, "physicalBlocks", &stats->physical_blocks, -1);
- get_stat_val64_default (full_stats, "dataBlocksUsed", &stats->data_blocks_used, -1);
- get_stat_val64_default (full_stats, "overheadBlocksUsed", &stats->overhead_blocks_used, -1);
- get_stat_val64_default (full_stats, "logicalBlocksUsed", &stats->logical_blocks_used, -1);
- get_stat_val64_default (full_stats, "usedPercent", &stats->used_percent, -1);
- get_stat_val64_default (full_stats, "savingPercent", &stats->saving_percent, -1);
- if (!get_stat_val_double (full_stats, "writeAmplificationRatio", &stats->write_amplification_ratio))
- stats->write_amplification_ratio = -1;
-
- g_hash_table_destroy (full_stats);
-
- return stats;
-}
-
-/* check whether the LVM devices file is enabled by LVM
- * we use the existence of the "lvmdevices" command to check whether the feature is available
- * or not, but this can still be disabled either in LVM or in lvm.conf
- */
-static gboolean _lvm_devices_enabled () {
- const gchar *args[6] = {"lvmconfig", "--typeconfig", NULL, "devices/use_devicesfile", NULL, NULL};
- gboolean ret = FALSE;
- GError *loc_error = NULL;
- gchar *output = NULL;
- gboolean enabled = FALSE;
- gint scanned = 0;
- g_autofree gchar *config_arg = NULL;
-
- /* try full config first -- if we get something from this it means the feature is
- explicitly enabled or disabled by system lvm.conf or using the --config option */
- args[2] = "full";
-
- /* make sure to include the global config from us when getting the current config value */
- g_mutex_lock (&global_config_lock);
- if (global_config_str) {
- config_arg = g_strdup_printf ("--config=%s", global_config_str);
- args[4] = config_arg;
- }
-
- ret = bd_utils_exec_and_capture_output (args, NULL, &output, &loc_error);
- g_mutex_unlock (&global_config_lock);
- if (ret) {
- scanned = sscanf (output, "use_devicesfile=%u", &enabled);
- g_free (output);
- if (scanned != 1)
- return FALSE;
-
- return enabled;
- } else {
- g_clear_error (&loc_error);
- g_free (output);
- }
-
- output = NULL;
-
- /* now try default */
- args[2] = "default";
- ret = bd_utils_exec_and_capture_output (args, NULL, &output, &loc_error);
- if (ret) {
- scanned = sscanf (output, "# use_devicesfile=%u", &enabled);
- g_free (output);
- if (scanned != 1)
- return FALSE;
-
- return enabled;
- } else {
- g_clear_error (&loc_error);
- g_free (output);
- }
-
- return FALSE;
-}
-
-/**
- * bd_lvm_devices_add:
- * @device: device (PV) to add to the devices file
- * @devices_file: (nullable): LVM devices file or %NULL for default
- * @extra: (nullable) (array zero-terminated=1): extra options for the lvmdevices command
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: whether the @device was successfully added to @devices_file or not
- *
- * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored)
- */
-gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) {
- const gchar *args[5] = {"lvmdevices", "--adddev", device, NULL, NULL};
- g_autofree gchar *devfile = NULL;
- if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error))
- return FALSE;
- if (!_lvm_devices_enabled ()) {
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED,
- "LVM devices file not enabled.");
- return FALSE;
- }
- if (devices_file) {
- devfile = g_strdup_printf ("--devicesfile=%s", devices_file);
- args[3] = devfile;
- }
- return bd_utils_exec_and_report_error (args, extra, error);
-}
-/**
- * bd_lvm_devices_delete:
- * @device: device (PV) to delete from the devices file
- * @devices_file: (nullable): LVM devices file or %NULL for default
- * @extra: (nullable) (array zero-terminated=1): extra options for the lvmdevices command
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: whether the @device was successfully removed from @devices_file or not
- *
- * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored)
- */
-gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) {
- const gchar *args[5] = {"lvmdevices", "--deldev", device, NULL, NULL};
- g_autofree gchar *devfile = NULL;
- if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error))
- return FALSE;
- if (!_lvm_devices_enabled ()) {
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED,
- "LVM devices file not enabled.");
- return FALSE;
- }
- if (devices_file) {
- devfile = g_strdup_printf ("--devicesfile=%s", devices_file);
- args[3] = devfile;
- }
- return bd_utils_exec_and_report_error (args, extra, error);
-}
-/**
- * bd_lvm_config_get:
- * @section: (nullable): LVM config section, e.g. 'global' or %NULL to print the entire config
- * @setting: (nullable): name of the specific setting, e.g. 'umask' or %NULL to print the entire @section
- * @type: type of the config, e.g. 'full' or 'current'
- * @values_only: whether to include only values without keys in the output
- * @global_config: whether to include our internal global config in the call or not
- * @extra: (nullable) (array zero-terminated=1): extra options for the lvmconfig command
- * (just passed to LVM as is)
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: Requested LVM config @section and @setting configuration or %NULL in case of error.
- *
- * Tech category: (transfer full): %BD_LVM_TECH_CONFIG no mode (it is ignored)
- */
-gchar* bd_lvm_config_get (const gchar *section, const gchar *setting, const gchar *type, gboolean values_only, gboolean global_config, const BDExtraArg **extra, GError **error) {
- g_autofree gchar *conf_spec = NULL;
- g_autofree gchar *config_arg = NULL;
- const gchar *args[7] = {"lvmconfig", "--typeconfig", NULL, NULL, NULL, NULL, NULL};
- guint next_arg = 2;
- gchar *output = NULL;
- gboolean success = FALSE;
-
- if (!section && setting) {
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
- "Specifying setting without section is not supported.");
- return NULL;
- }
- if (section)
- if (setting)
- conf_spec = g_strdup_printf ("%s/%s", section, setting);
- else
- conf_spec = g_strdup (section);
- else
- conf_spec = NULL;
-
- args[next_arg++] = type;
- args[next_arg++] = conf_spec;
- if (values_only)
- args[next_arg++] = "--valuesonly";
-
- g_mutex_lock (&global_config_lock);
- if (global_config && global_config_str) {
- config_arg = g_strdup_printf ("--config=%s", global_config_str);
- args[next_arg++] = config_arg;
- }
- g_mutex_unlock (&global_config_lock);
- success = bd_utils_exec_and_capture_output (args, extra, &output, error);
- if (!success)
- return NULL;
- return g_strchomp (output);
-}
diff --git a/src/plugins/lvm/lvm-private.h b/src/plugins/lvm/lvm-private.h
new file mode 100644
index 00000000..bcb5d8f7
--- /dev/null
+++ b/src/plugins/lvm/lvm-private.h
@@ -0,0 +1,17 @@
+#ifndef BD_LVM_PRIVATE
+#define BD_LVM_PRIVATE
+
+#define SECTOR_SIZE 512
+#define DEFAULT_PE_SIZE (4 MiB)
+#define USE_DEFAULT_PE_SIZE 0
+#define RESOLVE_PE_SIZE(size) ((size) == USE_DEFAULT_PE_SIZE ? DEFAULT_PE_SIZE : (size))
+
+#define LVM_MIN_VERSION "2.02.116"
+#define LVM_VERSION_FSRESIZE "2.03.19"
+
+extern GMutex global_config_lock;
+extern gchar *global_config_str;
+
+extern gchar *global_devices_str;
+
+#endif /* BD_LVM_PRIVATE */
diff --git a/src/plugins/lvm.c b/src/plugins/lvm/lvm.c
similarity index 82%
rename from src/plugins/lvm.c
rename to src/plugins/lvm/lvm.c
index f050e343..ce31f719 100644
--- a/src/plugins/lvm.c
+++ b/src/plugins/lvm/lvm.c
@@ -25,49 +25,11 @@
#include
#include "lvm.h"
+#include "lvm-private.h"
#include "check_deps.h"
#include "dm_logging.h"
#include "vdo_stats.h"
-#define INT_FLOAT_EPS 1e-5
-#define SECTOR_SIZE 512
-#define VDO_POOL_SUFFIX "vpool"
-#define DEFAULT_PE_SIZE (4 MiB)
-#define USE_DEFAULT_PE_SIZE 0
-#define RESOLVE_PE_SIZE(size) ((size) == USE_DEFAULT_PE_SIZE ? DEFAULT_PE_SIZE : (size))
-#define THPOOL_MD_FACTOR_NEW (0.2)
-#define THPOOL_MD_FACTOR_EXISTS (1 / 6.0)
-
-#define MIN_PE_SIZE (1 KiB)
-#define MAX_PE_SIZE (16 GiB)
-
-#define MIN_THPOOL_MD_SIZE (4 MiB)
-/* DM_THIN_MAX_METADATA_SIZE is in 512 sectors */
-#define MAX_THPOOL_MD_SIZE (DM_THIN_MAX_METADATA_SIZE * 512)
-
-#define MIN_THPOOL_CHUNK_SIZE (64 KiB)
-#define MAX_THPOOL_CHUNK_SIZE (1 GiB)
-#define DEFAULT_CHUNK_SIZE (64 KiB)
-
-/* according to lvmcache (7) */
-#define MIN_CACHE_MD_SIZE (8 MiB)
-
-#ifdef __LP64__
-/* 64bit system */
-#define MAX_LV_SIZE (8 EiB)
-#else
-/* 32bit system */
-#define MAX_LV_SIZE (16 TiB)
-#endif
-
-#define LVM_MIN_VERSION "2.02.116"
-#define LVM_VERSION_FSRESIZE "2.03.19"
-
-static GMutex global_config_lock;
-static gchar *global_config_str = NULL;
-
-static gchar *global_devices_str = NULL;
-
/**
* SECTION: lvm
* @short_description: plugin for operations with LVM
@@ -911,192 +873,6 @@ static BDLVMVDOPooldata* get_vdo_data_from_table (GHashTable *table, gboolean fr
return data;
}
-/**
- * bd_lvm_is_supported_pe_size:
- * @size: size (in bytes) to test
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: whether the given size is supported physical extent size or not
- *
- * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
- */
-gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error G_GNUC_UNUSED) {
- return (((size % 2) == 0) && (size >= (MIN_PE_SIZE)) && (size <= (MAX_PE_SIZE)));
-}
-
-/**
- * bd_lvm_get_supported_pe_sizes:
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: (transfer full) (array fixed-size=25): list of supported PE sizes
- *
- * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
- */
-guint64 *bd_lvm_get_supported_pe_sizes (GError **error G_GNUC_UNUSED) {
- guint8 i;
- guint64 val = MIN_PE_SIZE;
- guint8 num_items = ((guint8) round (log2 ((double) MAX_PE_SIZE))) - ((guint8) round (log2 ((double) MIN_PE_SIZE))) + 2;
- guint64 *ret = g_new0 (guint64, num_items);
-
- for (i=0; (val <= MAX_PE_SIZE); i++, val = val * 2)
- ret[i] = val;
-
- ret[num_items-1] = 0;
-
- return ret;
-}
-
-/**
- * bd_lvm_get_max_lv_size:
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: maximum LV size in bytes
- *
- * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
- */
-guint64 bd_lvm_get_max_lv_size (GError **error G_GNUC_UNUSED) {
- return MAX_LV_SIZE;
-}
-
-/**
- * bd_lvm_round_size_to_pe:
- * @size: size to be rounded
- * @pe_size: physical extent (PE) size or 0 to use the default
- * @roundup: whether to round up or down (ceil or floor)
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: @size rounded to @pe_size according to the @roundup
- *
- * Rounds given @size up/down to a multiple of @pe_size according to the value
- * of the @roundup parameter. If the rounded value is too big to fit in the
- * return type, the result is rounded down (floored) regardless of the @roundup
- * parameter.
- *
- * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
- */
-guint64 bd_lvm_round_size_to_pe (guint64 size, guint64 pe_size, gboolean roundup, GError **error G_GNUC_UNUSED) {
- pe_size = RESOLVE_PE_SIZE (pe_size);
- guint64 delta = size % pe_size;
- if (delta == 0)
- return size;
-
- if (roundup && (((G_MAXUINT64 - (pe_size - delta)) >= size)))
- return size + (pe_size - delta);
- else
- return size - delta;
-}
-
-/**
- * bd_lvm_get_lv_physical_size:
- * @lv_size: LV size
- * @pe_size: PE size
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: space taken on disk(s) by the LV with given @size
- *
- * Gives number of bytes needed for an LV with the size @lv_size on an LVM stack
- * using given @pe_size.
- *
- * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored)
- */
-guint64 bd_lvm_get_lv_physical_size (guint64 lv_size, guint64 pe_size, GError **error) {
- pe_size = RESOLVE_PE_SIZE (pe_size);
-
- /* the LV just takes space rounded up to the multiple of extent size */
- return bd_lvm_round_size_to_pe (lv_size, pe_size, TRUE, error);
-}
-
-/**
- * bd_lvm_get_thpool_padding:
- * @size: size of the thin pool
- * @pe_size: PE size or 0 if the default value should be used
- * @included: if padding is already included in the size
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: size of the padding needed for a thin pool with the given @size
- * according to the @pe_size and @included
- *
- * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
- */
-guint64 bd_lvm_get_thpool_padding (guint64 size, guint64 pe_size, gboolean included, GError **error) {
- guint64 raw_md_size;
- pe_size = RESOLVE_PE_SIZE (pe_size);
-
- if (included)
- raw_md_size = (guint64) ceil (size * THPOOL_MD_FACTOR_EXISTS);
- else
- raw_md_size = (guint64) ceil (size * THPOOL_MD_FACTOR_NEW);
-
- return MIN (bd_lvm_round_size_to_pe (raw_md_size, pe_size, TRUE, error),
- bd_lvm_round_size_to_pe (MAX_THPOOL_MD_SIZE, pe_size, TRUE, error));
-}
-
-/**
- * bd_lvm_get_thpool_meta_size:
- * @size: size of the thin pool
- * @chunk_size: chunk size of the thin pool or 0 to use the default
- * @n_snapshots: ignored
- * @error: (out) (optional): place to store error (if any)
- *
- * Note: This function will be changed in 3.0: the @n_snapshots parameter
- * is currently not used and will be removed.
- *
- * Returns: recommended size of the metadata space for the specified pool
- *
- * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
- */
-guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n_snapshots G_GNUC_UNUSED, GError **error G_GNUC_UNUSED) {
- guint64 md_size = 0;
-
- /* based on lvcreate metadata size calculation */
- md_size = UINT64_C (64) * size / (chunk_size ? chunk_size : DEFAULT_CHUNK_SIZE);
-
- if (md_size > MAX_THPOOL_MD_SIZE)
- md_size = MAX_THPOOL_MD_SIZE;
- else if (md_size < MIN_THPOOL_MD_SIZE)
- md_size = MIN_THPOOL_MD_SIZE;
-
- return md_size;
-}
-
-/**
- * bd_lvm_is_valid_thpool_md_size:
- * @size: the size to be tested
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: whether the given size is a valid thin pool metadata size or not
- *
- * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
- */
-gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error G_GNUC_UNUSED) {
- return ((MIN_THPOOL_MD_SIZE <= size) && (size <= MAX_THPOOL_MD_SIZE));
-}
-
-/**
- * bd_lvm_is_valid_thpool_chunk_size:
- * @size: the size to be tested
- * @discard: whether discard/TRIM is required to be supported or not
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: whether the given size is a valid thin pool chunk size or not
- *
- * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored)
- */
-gboolean bd_lvm_is_valid_thpool_chunk_size (guint64 size, gboolean discard, GError **error G_GNUC_UNUSED) {
- gdouble size_log2 = 0.0;
-
- if ((size < MIN_THPOOL_CHUNK_SIZE) || (size > MAX_THPOOL_CHUNK_SIZE))
- return FALSE;
-
- /* To support discard, chunk size must be a power of two. Otherwise it must be a
- multiple of 64 KiB. */
- if (discard) {
- size_log2 = log2 ((double) size);
- return ABS (((int) round (size_log2)) - size_log2) <= INT_FLOAT_EPS;
- } else
- return (size % (64 KiB)) == 0;
-}
-
/**
* bd_lvm_pvcreate:
* @device: the device to make PV from
@@ -2539,130 +2315,6 @@ gboolean bd_lvm_thsnapshotcreate (const gchar *vg_name, const gchar *origin_name
return success;
}
-/**
- * bd_lvm_set_global_config:
- * @new_config: (nullable): string representation of the new global libblockdev LVM
- * configuration to set or %NULL to reset to default
- * @error: (out) (optional): place to store error (if any)
- *
- *
- * Note: This functions sets configuration options for LVM calls internally
- * in libblockdev, it doesn't change the global lvm.conf config file.
- * Calling this function with `backup {backup=0 archive=0}` for example
- * means `--config=backup {backup=0 archive=0}"` will be added to all
- * calls libblockdev makes.
- *
- * Returns: whether the new requested global config @new_config was successfully
- * set or not
- *
- * Tech category: %BD_LVM_TECH_GLOB_CONF no mode (it is ignored)
- */
-gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error G_GNUC_UNUSED) {
- /* XXX: the error attribute will likely be used in the future when
- some validation comes into the game */
-
- g_mutex_lock (&global_config_lock);
-
- /* first free the old value */
- g_free (global_config_str);
-
- /* now store the new one */
- if (!new_config || g_strcmp0 (new_config, "") == 0)
- global_config_str = NULL;
- else
- global_config_str = g_strdup (new_config);
-
- g_mutex_unlock (&global_config_lock);
- return TRUE;
-}
-
-/**
- * bd_lvm_get_global_config:
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: (transfer full): a copy of a string representation of the currently
- * set libblockdev LVM global configuration
- *
- * Note: This function does not change the global `lvm.conf` config
- * file, see %bd_lvm_set_global_config for details.
- *
- * Tech category: %BD_LVM_TECH_GLOB_CONF no mode (it is ignored)
- */
-gchar* bd_lvm_get_global_config (GError **error G_GNUC_UNUSED) {
- gchar *ret = NULL;
-
- g_mutex_lock (&global_config_lock);
- ret = g_strdup (global_config_str ? global_config_str : "");
- g_mutex_unlock (&global_config_lock);
-
- return ret;
-}
-
-/**
- * bd_lvm_set_devices_filter:
- * @devices: (nullable) (array zero-terminated=1): list of devices for lvm commands to work on
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: whether the devices filter was successfully set or not
- *
- * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored)
- */
-gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error) {
- if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error))
- return FALSE;
-
- g_mutex_lock (&global_config_lock);
-
- /* first free the old value */
- g_free (global_devices_str);
-
- /* now store the new one */
- if (!devices || !(*devices))
- global_devices_str = NULL;
- else
- global_devices_str = g_strjoinv (",", (gchar **) devices);
-
- g_mutex_unlock (&global_config_lock);
- return TRUE;
-}
-
-/**
- * bd_lvm_get_devices_filter:
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: (transfer full) (array zero-terminated=1): a copy of a string representation of
- * the currently set LVM devices filter
- *
- * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored)
- */
-gchar** bd_lvm_get_devices_filter (GError **error G_GNUC_UNUSED) {
- gchar **ret = NULL;
-
- g_mutex_lock (&global_config_lock);
-
- if (global_devices_str)
- ret = g_strsplit (global_devices_str, ",", -1);
- else
- ret = NULL;
-
- g_mutex_unlock (&global_config_lock);
-
- return ret;
-}
-
-/**
- * bd_lvm_cache_get_default_md_size:
- * @cache_size: size of the cache to determine MD size for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: recommended default size of the cache metadata LV or 0 in case of error
- *
- * Tech category: %BD_LVM_TECH_CACHE_CALCS no mode (it is ignored)
- */
-guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error G_GNUC_UNUSED) {
- return MAX ((guint64) cache_size / 1000, MIN_CACHE_MD_SIZE);
-}
-
/**
* get_lv_type_from_flags: (skip)
* @meta: getting type for a (future) metadata LV
@@ -2699,53 +2351,6 @@ static const gchar* get_lv_type_from_flags (BDLVMCachePoolFlags flags, gboolean
}
}
-/**
- * bd_lvm_cache_get_mode_str:
- * @mode: mode to get the string representation for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: string representation of @mode or %NULL in case of error
- *
- * Tech category: always provided/supported
- */
-const gchar* bd_lvm_cache_get_mode_str (BDLVMCacheMode mode, GError **error) {
- if (mode == BD_LVM_CACHE_MODE_WRITETHROUGH)
- return "writethrough";
- else if (mode == BD_LVM_CACHE_MODE_WRITEBACK)
- return "writeback";
- else if (mode == BD_LVM_CACHE_MODE_UNKNOWN)
- return "unknown";
- else {
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_CACHE_INVAL,
- "Invalid mode given: %d", mode);
- return NULL;
- }
-}
-
-/**
- * bd_lvm_cache_get_mode_from_str:
- * @mode_str: string representation of a cache mode
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: cache mode for the @mode_str or %BD_LVM_CACHE_MODE_UNKNOWN if
- * failed to determine
- *
- * Tech category: always provided/supported
- */
-BDLVMCacheMode bd_lvm_cache_get_mode_from_str (const gchar *mode_str, GError **error) {
- if (g_strcmp0 (mode_str, "writethrough") == 0)
- return BD_LVM_CACHE_MODE_WRITETHROUGH;
- else if (g_strcmp0 (mode_str, "writeback") == 0)
- return BD_LVM_CACHE_MODE_WRITEBACK;
- else if (g_strcmp0 (mode_str, "unknown") == 0)
- return BD_LVM_CACHE_MODE_UNKNOWN;
- else {
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_CACHE_INVAL,
- "Invalid mode given: %s", mode_str);
- return BD_LVM_CACHE_MODE_UNKNOWN;
- }
-}
-
/**
* bd_lvm_cache_create_pool:
* @vg_name: name of the VG to create @pool_name in
@@ -3670,363 +3275,3 @@ gchar* bd_lvm_vdolvpoolname (const gchar *vg_name, const gchar *lv_name, GError
return g_strstrip (output);
}
-
-/**
- * bd_lvm_get_vdo_operating_mode_str:
- * @mode: mode to get the string representation for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: string representation of @mode or %NULL in case of error
- *
- * Tech category: always provided/supported
- */
-const gchar* bd_lvm_get_vdo_operating_mode_str (BDLVMVDOOperatingMode mode, GError **error) {
- switch (mode) {
- case BD_LVM_VDO_MODE_RECOVERING:
- return "recovering";
- case BD_LVM_VDO_MODE_READ_ONLY:
- return "read-only";
- case BD_LVM_VDO_MODE_NORMAL:
- return "normal";
- case BD_LVM_VDO_MODE_UNKNOWN:
- return "unknown";
- default:
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
- "Invalid LVM VDO operating mode.");
- return NULL;
- }
-}
-
-/**
- * bd_lvm_get_vdo_compression_state_str:
- * @state: state to get the string representation for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: string representation of @state or %NULL in case of error
- *
- * Tech category: always provided/supported
- */
-const gchar* bd_lvm_get_vdo_compression_state_str (BDLVMVDOCompressionState state, GError **error) {
- switch (state) {
- case BD_LVM_VDO_COMPRESSION_ONLINE:
- return "online";
- case BD_LVM_VDO_COMPRESSION_OFFLINE:
- return "offline";
- case BD_LVM_VDO_COMPRESSION_UNKNOWN:
- return "unknown";
- default:
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
- "Invalid LVM VDO compression state.");
- return NULL;
- }
-}
-
-/**
- * bd_lvm_get_vdo_index_state_str:
- * @state: state to get the string representation for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: string representation of @state or %NULL in case of error
- *
- * Tech category: always provided/supported
- */
-const gchar* bd_lvm_get_vdo_index_state_str (BDLVMVDOIndexState state, GError **error) {
- switch (state) {
- case BD_LVM_VDO_INDEX_ERROR:
- return "error";
- case BD_LVM_VDO_INDEX_CLOSED:
- return "closed";
- case BD_LVM_VDO_INDEX_OPENING:
- return "opening";
- case BD_LVM_VDO_INDEX_CLOSING:
- return "closing";
- case BD_LVM_VDO_INDEX_OFFLINE:
- return "offline";
- case BD_LVM_VDO_INDEX_ONLINE:
- return "online";
- case BD_LVM_VDO_INDEX_UNKNOWN:
- return "unknown";
- default:
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
- "Invalid LVM VDO index state.");
- return NULL;
- }
-}
-
-/**
- * bd_lvm_get_vdo_write_policy_str:
- * @policy: policy to get the string representation for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: string representation of @policy or %NULL in case of error
- *
- * Tech category: always provided/supported
- */
-const gchar* bd_lvm_get_vdo_write_policy_str (BDLVMVDOWritePolicy policy, GError **error) {
- switch (policy) {
- case BD_LVM_VDO_WRITE_POLICY_AUTO:
- return "auto";
- case BD_LVM_VDO_WRITE_POLICY_SYNC:
- return "sync";
- case BD_LVM_VDO_WRITE_POLICY_ASYNC:
- return "async";
- case BD_LVM_VDO_WRITE_POLICY_UNKNOWN:
- return "unknown";
- default:
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
- "Invalid LVM VDO write policy.");
- return NULL;
- }
-}
-
-/**
- * bd_lvm_get_vdo_write_policy_from_str:
- * @policy_str: string representation of a policy
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: write policy for the @policy_str or %BD_LVM_VDO_WRITE_POLICY_UNKNOWN if
- * failed to determine
- *
- * Tech category: always provided/supported
- */
-BDLVMVDOWritePolicy bd_lvm_get_vdo_write_policy_from_str (const gchar *policy_str, GError **error) {
- if (g_strcmp0 (policy_str, "auto") == 0)
- return BD_LVM_VDO_WRITE_POLICY_AUTO;
- else if (g_strcmp0 (policy_str, "sync") == 0)
- return BD_LVM_VDO_WRITE_POLICY_SYNC;
- else if (g_strcmp0 (policy_str, "async") == 0)
- return BD_LVM_VDO_WRITE_POLICY_ASYNC;
- else {
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_VDO_POLICY_INVAL,
- "Invalid policy given: %s", policy_str);
- return BD_LVM_VDO_WRITE_POLICY_UNKNOWN;
- }
-}
-
-/**
- * bd_lvm_vdo_get_stats_full:
- * @vg_name: name of the VG that contains @pool_name VDO pool
- * @pool_name: name of the VDO pool to get statistics for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: (transfer full) (element-type utf8 utf8): hashtable of type string - string of available
- * statistics or %NULL in case of error
- * (@error gets populated in those cases)
- *
- * Statistics are collected from the values exposed by the kernel `dm-vdo` module.
- *
- * Some of the keys are computed to mimic the information produced by the vdo tools.
- * Please note the contents of the hashtable may vary depending on the actual dm-vdo module version.
- *
- * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_QUERY
- */
-GHashTable* bd_lvm_vdo_get_stats_full (const gchar *vg_name, const gchar *pool_name, GError **error) {
- g_autofree gchar *kvdo_name = g_strdup_printf ("%s-%s-%s", vg_name, pool_name, VDO_POOL_SUFFIX);
- return vdo_get_stats_full (kvdo_name, error);
-}
-
-/**
- * bd_lvm_vdo_get_stats:
- * @vg_name: name of the VG that contains @pool_name VDO pool
- * @pool_name: name of the VDO pool to get statistics for
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: (transfer full): a structure containing selected statistics or %NULL in case of error
- * (@error gets populated in those cases)
- *
- * In contrast to @bd_lvm_vdo_get_stats_full this function will only return selected statistics
- * in a fixed structure. In case a value is not available, -1 would be returned.
- *
- * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_QUERY
- */
-BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_name, GError **error) {
- GHashTable *full_stats = NULL;
- BDLVMVDOStats *stats = NULL;
-
- full_stats = bd_lvm_vdo_get_stats_full (vg_name, pool_name, error);
- if (!full_stats)
- return NULL;
-
- stats = g_new0 (BDLVMVDOStats, 1);
- get_stat_val64_default (full_stats, "blockSize", &stats->block_size, -1);
- get_stat_val64_default (full_stats, "logicalBlockSize", &stats->logical_block_size, -1);
- get_stat_val64_default (full_stats, "physicalBlocks", &stats->physical_blocks, -1);
- get_stat_val64_default (full_stats, "dataBlocksUsed", &stats->data_blocks_used, -1);
- get_stat_val64_default (full_stats, "overheadBlocksUsed", &stats->overhead_blocks_used, -1);
- get_stat_val64_default (full_stats, "logicalBlocksUsed", &stats->logical_blocks_used, -1);
- get_stat_val64_default (full_stats, "usedPercent", &stats->used_percent, -1);
- get_stat_val64_default (full_stats, "savingPercent", &stats->saving_percent, -1);
- if (!get_stat_val_double (full_stats, "writeAmplificationRatio", &stats->write_amplification_ratio))
- stats->write_amplification_ratio = -1;
-
- g_hash_table_destroy (full_stats);
-
- return stats;
-}
-
-/* check whether the LVM devices file is enabled by LVM
- * we use the existence of the "lvmdevices" command to check whether the feature is available
- * or not, but this can still be disabled either in LVM or in lvm.conf
- */
-static gboolean _lvm_devices_enabled () {
- const gchar *args[5] = {"config", "--typeconfig", NULL, "devices/use_devicesfile", NULL};
- gboolean ret = FALSE;
- GError *loc_error = NULL;
- gchar *output = NULL;
- gboolean enabled = FALSE;
- gint scanned = 0;
-
- /* try full config first -- if we get something from this it means the feature is
- explicitly enabled or disabled by system lvm.conf or using the --config option */
- args[2] = "full";
- ret = call_lvm_and_capture_output (args, NULL, &output, &loc_error);
- if (ret) {
- scanned = sscanf (output, "use_devicesfile=%u", &enabled);
- g_free (output);
- if (scanned != 1)
- return FALSE;
-
- return enabled;
- } else {
- g_clear_error (&loc_error);
- g_free (output);
- }
-
- output = NULL;
-
- /* now try default */
- args[2] = "default";
- ret = call_lvm_and_capture_output (args, NULL, &output, &loc_error);
- if (ret) {
- scanned = sscanf (output, "# use_devicesfile=%u", &enabled);
- g_free (output);
- if (scanned != 1)
- return FALSE;
-
- return enabled;
- } else {
- g_clear_error (&loc_error);
- g_free (output);
- }
-
- return FALSE;
-}
-
-/**
- * bd_lvm_devices_add:
- * @device: device (PV) to add to the devices file
- * @devices_file: (nullable): LVM devices file or %NULL for default
- * @extra: (nullable) (array zero-terminated=1): extra options for the lvmdevices command
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: whether the @device was successfully added to @devices_file or not
- *
- * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored)
- */
-gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) {
- const gchar *args[5] = {"lvmdevices", "--adddev", device, NULL, NULL};
- g_autofree gchar *devfile = NULL;
-
- if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error))
- return FALSE;
-
- if (!_lvm_devices_enabled ()) {
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED,
- "LVM devices file not enabled.");
- return FALSE;
- }
-
- if (devices_file) {
- devfile = g_strdup_printf ("--devicesfile=%s", devices_file);
- args[3] = devfile;
- }
-
- return bd_utils_exec_and_report_error (args, extra, error);
-}
-
-/**
- * bd_lvm_devices_delete:
- * @device: device (PV) to delete from the devices file
- * @devices_file: (nullable): LVM devices file or %NULL for default
- * @extra: (nullable) (array zero-terminated=1): extra options for the lvmdevices command
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: whether the @device was successfully removed from @devices_file or not
- *
- * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored)
- */
-gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) {
- const gchar *args[5] = {"lvmdevices", "--deldev", device, NULL, NULL};
- g_autofree gchar *devfile = NULL;
-
- if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error))
- return FALSE;
-
- if (!_lvm_devices_enabled ()) {
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED,
- "LVM devices file not enabled.");
- return FALSE;
- }
-
- if (devices_file) {
- devfile = g_strdup_printf ("--devicesfile=%s", devices_file);
- args[3] = devfile;
- }
-
- return bd_utils_exec_and_report_error (args, extra, error);
-}
-
-/**
- * bd_lvm_config_get:
- * @section: (nullable): LVM config section, e.g. 'global' or %NULL to print the entire config
- * @setting: (nullable): name of the specific setting, e.g. 'umask' or %NULL to print the entire @section
- * @type: type of the config, e.g. 'full' or 'current'
- * @values_only: whether to include only values without keys in the output
- * @global_config: whether to include our internal global config in the call or not
- * @extra: (nullable) (array zero-terminated=1): extra options for the lvmconfig command
- * (just passed to LVM as is)
- * @error: (out) (optional): place to store error (if any)
- *
- * Returns: (transfer full): Requested LVM config @section and @setting configuration or %NULL in case of error.
- *
- * Tech category: %BD_LVM_TECH_CONFIG no mode (it is ignored)
- */
-gchar* bd_lvm_config_get (const gchar *section, const gchar *setting, const gchar *type, gboolean values_only, gboolean global_config, const BDExtraArg **extra, GError **error) {
- g_autofree gchar *conf_spec = NULL;
- g_autofree gchar *config_arg = NULL;
- const gchar *args[7] = {"lvmconfig", "--typeconfig", NULL, NULL, NULL, NULL, NULL};
- guint next_arg = 2;
- gchar *output = NULL;
- gboolean success = FALSE;
-
- if (!section && setting) {
- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
- "Specifying setting without section is not supported.");
- return NULL;
- }
-
- if (section)
- if (setting)
- conf_spec = g_strdup_printf ("%s/%s", section, setting);
- else
- conf_spec = g_strdup (section);
- else
- conf_spec = NULL;
-
- args[next_arg++] = type;
- args[next_arg++] = conf_spec;
- if (values_only)
- args[next_arg++] = "--valuesonly";
-
- g_mutex_lock (&global_config_lock);
- if (global_config && global_config_str) {
- config_arg = g_strdup_printf ("--config=%s", global_config_str);
- args[next_arg++] = config_arg;
- }
- g_mutex_unlock (&global_config_lock);
-
- success = bd_utils_exec_and_capture_output (args, extra, &output, error);
- if (!success)
- return NULL;
- return g_strchomp (output);
-}
diff --git a/src/plugins/lvm.h b/src/plugins/lvm/lvm.h
similarity index 100%
rename from src/plugins/lvm.h
rename to src/plugins/lvm/lvm.h
diff --git a/src/plugins/vdo_stats.c b/src/plugins/lvm/vdo_stats.c
similarity index 100%
rename from src/plugins/vdo_stats.c
rename to src/plugins/lvm/vdo_stats.c
diff --git a/src/plugins/vdo_stats.h b/src/plugins/lvm/vdo_stats.h
similarity index 100%
rename from src/plugins/vdo_stats.h
rename to src/plugins/lvm/vdo_stats.h
diff --git a/tests/library_test.py b/tests/library_test.py
index 8f13116e..86180fa3 100644
--- a/tests/library_test.py
+++ b/tests/library_test.py
@@ -164,8 +164,8 @@ def setUp(self):
def _clean_up(self):
# change the sources back and recompile
- os.system("sed -ri 's?1024;//test-change?MAX_LV_SIZE;?' src/plugins/lvm.c > /dev/null")
- os.system("make -C src/plugins/ libbd_lvm.la >/dev/null 2>&1")
+ os.system("sed -ri 's?1024;//test-change?MAX_LV_SIZE;?' src/plugins/lvm/lvm-common.c > /dev/null")
+ os.system("make -C src/plugins/lvm/ libbd_lvm.la >/dev/null 2>&1")
os.environ["LIBBLOCKDEV_CONFIG_DIR"] = self.orig_config_dir
@@ -182,8 +182,8 @@ def test_reload(self):
self.assertNotEqual(orig_max_size, 1024)
# change the sources and recompile
- os.system("sed -ri 's?MAX_LV_SIZE;?1024;//test-change?' src/plugins/lvm.c > /dev/null")
- ret = os.system("make -C src/plugins/ libbd_lvm.la >/dev/null 2>&1")
+ os.system("sed -ri 's?MAX_LV_SIZE;?1024;//test-change?' src/plugins/lvm/lvm-common.c > /dev/null")
+ ret = os.system("make -C src/plugins/lvm/ libbd_lvm.la >/dev/null 2>&1")
self.assertEqual(ret, 0, "Failed to recompile libblockdev for reload test")
# library should successfully reinitialize without reloading plugins
@@ -199,8 +199,8 @@ def test_reload(self):
self.assertEqual(BlockDev.lvm_get_max_lv_size(), 1024)
# change the sources back and recompile
- os.system("sed -ri 's?1024;//test-change?MAX_LV_SIZE;?' src/plugins/lvm.c > /dev/null")
- os.system("make -C src/plugins/ libbd_lvm.la >/dev/null 2>&1")
+ os.system("sed -ri 's?1024;//test-change?MAX_LV_SIZE;?' src/plugins/lvm/lvm-common.c > /dev/null")
+ os.system("make -C src/plugins/lvm/ libbd_lvm.la >/dev/null 2>&1")
# library should successfully reinitialize reloading original plugins
self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
@@ -221,16 +221,16 @@ def test_force_plugin(self):
self.assertNotEqual(orig_max_size, 1024)
# change the sources and recompile
- os.system("sed -ri 's?MAX_LV_SIZE;?1024;//test-change?' src/plugins/lvm.c > /dev/null")
- ret = os.system("make -C src/plugins/ libbd_lvm.la >/dev/null 2>&1")
+ os.system("sed -ri 's?MAX_LV_SIZE;?1024;//test-change?' src/plugins/lvm/lvm-common.c > /dev/null")
+ ret = os.system("make -C src/plugins/lvm/ libbd_lvm.la >/dev/null 2>&1")
self.assertEqual(ret, 0, "Failed to recompile libblockdev for force plugin test")
# proclaim the new build a different plugin
- os.system("cp src/plugins/.libs/libbd_lvm.so src/plugins/.libs/libbd_lvm2.so")
+ os.system("cp src/plugins/lvm/.libs/libbd_lvm.so src/plugins/lvm/.libs/libbd_lvm2.so")
# change the sources back and recompile
- os.system("sed -ri 's?1024;//test-change?MAX_LV_SIZE;?' src/plugins/lvm.c > /dev/null")
- ret = os.system("make -C src/plugins/ libbd_lvm.la >/dev/null 2>&1")
+ os.system("sed -ri 's?1024;//test-change?MAX_LV_SIZE;?' src/plugins/lvm/lvm-common.c > /dev/null")
+ ret = os.system("make -C src/plugins/lvm/ libbd_lvm.la >/dev/null 2>&1")
self.assertEqual(ret, 0, "Failed to recompile libblockdev for force plugin test")
# force the new plugin to be used
@@ -241,7 +241,7 @@ def test_force_plugin(self):
self.assertEqual(BlockDev.lvm_get_max_lv_size(), 1024)
# clean after ourselves
- os.system ("rm -f src/plugins/.libs/libbd_lvm2.so")
+ os.system ("rm -f src/plugins/lvm/.libs/libbd_lvm2.so")
# force the old plugin to be used
ps = BlockDev.PluginSpec(name=BlockDev.Plugin.LVM, so_name="libbd_lvm.so")
@@ -262,16 +262,16 @@ def test_plugin_priority(self):
self.assertNotEqual(orig_max_size, 1024)
# change the sources and recompile
- os.system("sed -ri 's?MAX_LV_SIZE;?1024;//test-change?' src/plugins/lvm.c > /dev/null")
- ret = os.system("make -C src/plugins/ libbd_lvm.la >/dev/null 2>&1")
+ os.system("sed -ri 's?MAX_LV_SIZE;?1024;//test-change?' src/plugins/lvm/lvm-common.c > /dev/null")
+ ret = os.system("make -C src/plugins/lvm/ libbd_lvm.la >/dev/null 2>&1")
self.assertEqual(ret, 0, "Failed to recompile libblockdev for plugin priority test")
# proclaim the new build a different plugin
- os.system("cp src/plugins/.libs/libbd_lvm.so src/plugins/.libs/libbd_lvm2.so.3")
+ os.system("cp src/plugins/lvm/.libs/libbd_lvm.so src/plugins/lvm/.libs/libbd_lvm2.so.3")
# change the sources back and recompile
- os.system("sed -ri 's?1024;//test-change?MAX_LV_SIZE;?' src/plugins/lvm.c > /dev/null")
- ret = os.system("make -C src/plugins/ libbd_lvm.la >/dev/null 2>&1")
+ os.system("sed -ri 's?1024;//test-change?MAX_LV_SIZE;?' src/plugins/lvm/lvm-common.c > /dev/null")
+ ret = os.system("make -C src/plugins/lvm/ libbd_lvm.la >/dev/null 2>&1")
self.assertEqual(ret, 0, "Failed to recompile libblockdev for plugin priority test")
# now reinit the library with the config preferring the new build
@@ -312,4 +312,4 @@ def test_plugin_priority(self):
self.assertEqual(BlockDev.lvm_get_max_lv_size(), orig_max_size)
# clean after ourselves
- os.system ("rm -f src/plugins/.libs/libbd_lvm2.so")
+ os.system ("rm -f src/plugins/lvm/.libs/libbd_lvm2.so")
diff --git a/tests/run_tests.py b/tests/run_tests.py
index b1e5c398..f1b7e5a8 100644
--- a/tests/run_tests.py
+++ b/tests/run_tests.py
@@ -17,7 +17,7 @@
from utils import TestTags, get_version
-LIBDIRS = 'src/utils/.libs:src/plugins/.libs:src/plugins/fs/.libs:src/lib/.libs:src/plugins/nvme/.libs:src/plugins/smart/.libs'
+LIBDIRS = 'src/utils/.libs:src/plugins/.libs:src/plugins/fs/.libs:src/lib/.libs:src/plugins/lvm/.libs:src/plugins/nvme/.libs:src/plugins/smart/.libs'
GIDIR = 'src/lib'
SKIP_CONFIG = 'skip.yml'