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'