LCOV - code coverage report
Current view: top level - plugins/lvm - lvm-dbus.c (source / functions) Coverage Total Hit
Test: libblockdev Coverage Report Lines: 75.7 % 2100 1590
Test Date: 2026-01-26 13:19:28 Functions: 87.9 % 107 94
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              :  * Copyright (C) 2015-2016  Red Hat, Inc.
       3              :  *
       4              :  * This library is free software; you can redistribute it and/or
       5              :  * modify it under the terms of the GNU Lesser General Public
       6              :  * License as published by the Free Software Foundation; either
       7              :  * version 2.1 of the License, or (at your option) any later version.
       8              :  *
       9              :  * This library is distributed in the hope that it will be useful,
      10              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12              :  * Lesser General Public License for more details.
      13              :  *
      14              :  * You should have received a copy of the GNU Lesser General Public
      15              :  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      16              :  *
      17              :  * Author: Vratislav Podzimek <vpodzime@redhat.com>
      18              :  */
      19              : 
      20              : #include <glib.h>
      21              : #include <math.h>
      22              : #include <string.h>
      23              : #include <unistd.h>
      24              : #include <blockdev/utils.h>
      25              : #include <gio/gio.h>
      26              : #include <libdevmapper.h>
      27              : 
      28              : #include "lvm.h"
      29              : #include "lvm-private.h"
      30              : #include "check_deps.h"
      31              : #include "dm_logging.h"
      32              : #include "vdo_stats.h"
      33              : 
      34              : #define LVM_BUS_NAME "com.redhat.lvmdbus1"
      35              : #define LVM_OBJ_PREFIX "/com/redhat/lvmdbus1"
      36              : #define MANAGER_OBJ "/com/redhat/lvmdbus1/Manager"
      37              : #define MANAGER_INTF "com.redhat.lvmdbus1.Manager"
      38              : #define JOB_OBJ_PREFIX "/com/redhat/lvmdbus1/Job/"
      39              : #define JOB_INTF "com.redhat.lvmdbus1.Job"
      40              : #define PV_OBJ_PREFIX LVM_OBJ_PREFIX"/Pv"
      41              : #define VG_OBJ_PREFIX LVM_OBJ_PREFIX"/Vg"
      42              : #define LV_OBJ_PREFIX LVM_OBJ_PREFIX"/Lv"
      43              : #define HIDDEN_LV_OBJ_PREFIX LVM_OBJ_PREFIX"/HiddenLv"
      44              : #define THIN_POOL_OBJ_PREFIX LVM_OBJ_PREFIX"/ThinPool"
      45              : #define CACHE_POOL_OBJ_PREFIX LVM_OBJ_PREFIX"/CachePool"
      46              : #define VDO_POOL_OBJ_PREFIX LVM_OBJ_PREFIX"/VdoPool"
      47              : #define PV_INTF LVM_BUS_NAME".Pv"
      48              : #define VG_INTF LVM_BUS_NAME".Vg"
      49              : #define VG_VDO_INTF LVM_BUS_NAME".VgVdo"
      50              : #define LV_CMN_INTF LVM_BUS_NAME".LvCommon"
      51              : #define LV_INTF LVM_BUS_NAME".Lv"
      52              : #define CACHED_LV_INTF LVM_BUS_NAME".CachedLv"
      53              : #define SNAP_INTF LVM_BUS_NAME".Snapshot"
      54              : #define THPOOL_INTF LVM_BUS_NAME".ThinPool"
      55              : #define CACHE_POOL_INTF LVM_BUS_NAME".CachePool"
      56              : #define VDO_POOL_INTF LVM_BUS_NAME".VdoPool"
      57              : #define DBUS_PROPS_IFACE "org.freedesktop.DBus.Properties"
      58              : #define DBUS_INTRO_IFACE "org.freedesktop.DBus.Introspectable"
      59              : #define METHOD_CALL_TIMEOUT 5000
      60              : #define PROGRESS_WAIT 500 * 1000 /* microseconds */
      61              : 
      62              : 
      63              : static GDBusConnection *bus = NULL;
      64              : 
      65              : /**
      66              :  * SECTION: lvm
      67              :  * @short_description: plugin for operations with LVM
      68              :  * @title: LVM
      69              :  * @include: lvm.h
      70              :  *
      71              :  * A plugin for operations with LVM. All sizes passed in/out to/from
      72              :  * the functions are in bytes.
      73              :  */
      74              : 
      75              : /**
      76              :  * bd_lvm_error_quark: (skip)
      77              :  */
      78            0 : GQuark bd_lvm_error_quark (void)
      79              : {
      80            0 :     return g_quark_from_static_string ("g-bd-lvm-error-quark");
      81              : }
      82              : 
      83            0 : BDLVMPVdata* bd_lvm_pvdata_copy (BDLVMPVdata *data) {
      84            0 :     if (data == NULL)
      85            0 :         return NULL;
      86              : 
      87            0 :     BDLVMPVdata *new_data = g_new0 (BDLVMPVdata, 1);
      88              : 
      89            0 :     new_data->pv_name = g_strdup (data->pv_name);
      90            0 :     new_data->pv_uuid = g_strdup (data->pv_uuid);
      91            0 :     new_data->pv_free = data->pv_free;
      92            0 :     new_data->pv_size = data->pv_size;
      93            0 :     new_data->pe_start = data->pe_start;
      94            0 :     new_data->vg_name = g_strdup (data->vg_name);
      95            0 :     new_data->vg_uuid = g_strdup (data->vg_uuid);
      96            0 :     new_data->vg_size = data->vg_size;
      97            0 :     new_data->vg_free = data->vg_free;
      98            0 :     new_data->vg_extent_size = data->vg_extent_size;
      99            0 :     new_data->vg_extent_count = data->vg_extent_count;
     100            0 :     new_data->vg_free_count = data->vg_free_count;
     101            0 :     new_data->vg_pv_count = data->vg_pv_count;
     102            0 :     new_data->pv_tags = g_strdupv (data->pv_tags);
     103              : 
     104            0 :     return new_data;
     105              : }
     106              : 
     107            0 : void bd_lvm_pvdata_free (BDLVMPVdata *data) {
     108            0 :     if (data == NULL)
     109            0 :         return;
     110              : 
     111            0 :     g_free (data->pv_name);
     112            0 :     g_free (data->pv_uuid);
     113            0 :     g_free (data->vg_name);
     114            0 :     g_free (data->vg_uuid);
     115            0 :     g_strfreev (data->pv_tags);
     116            0 :     g_free (data);
     117              : }
     118              : 
     119            0 : BDLVMVGdata* bd_lvm_vgdata_copy (BDLVMVGdata *data) {
     120            0 :     if (data == NULL)
     121            0 :         return NULL;
     122              : 
     123            0 :     BDLVMVGdata *new_data = g_new0 (BDLVMVGdata, 1);
     124              : 
     125            0 :     new_data->name = g_strdup (data->name);
     126            0 :     new_data->uuid = g_strdup (data->uuid);
     127            0 :     new_data->size = data->size;
     128            0 :     new_data->free = data->free;
     129            0 :     new_data->extent_size = data->extent_size;
     130            0 :     new_data->extent_count = data->extent_count;
     131            0 :     new_data->free_count = data->free_count;
     132            0 :     new_data->pv_count = data->pv_count;
     133            0 :     new_data->vg_tags = g_strdupv (data->vg_tags);
     134            0 :     return new_data;
     135              : }
     136              : 
     137            0 : void bd_lvm_vgdata_free (BDLVMVGdata *data) {
     138            0 :     if (data == NULL)
     139            0 :         return;
     140              : 
     141            0 :     g_free (data->name);
     142            0 :     g_free (data->uuid);
     143            0 :     g_strfreev (data->vg_tags);
     144            0 :     g_free (data);
     145              : }
     146              : 
     147            0 : BDLVMLVdata* bd_lvm_lvdata_copy (BDLVMLVdata *data) {
     148            0 :     if (data == NULL)
     149            0 :         return NULL;
     150              : 
     151            0 :     BDLVMLVdata *new_data = g_new0 (BDLVMLVdata, 1);
     152              : 
     153            0 :     new_data->lv_name = g_strdup (data->lv_name);
     154            0 :     new_data->vg_name = g_strdup (data->vg_name);
     155            0 :     new_data->uuid = g_strdup (data->uuid);
     156            0 :     new_data->size = data->size;
     157            0 :     new_data->attr = g_strdup (data->attr);
     158            0 :     new_data->segtype = g_strdup (data->segtype);
     159            0 :     new_data->origin = g_strdup (data->origin);
     160            0 :     new_data->pool_lv = g_strdup (data->pool_lv);
     161            0 :     new_data->data_lv = g_strdup (data->data_lv);
     162            0 :     new_data->metadata_lv = g_strdup (data->metadata_lv);
     163            0 :     new_data->roles = g_strdup (data->roles);
     164            0 :     new_data->move_pv = g_strdup (data->move_pv);
     165            0 :     new_data->data_percent = data->data_percent;
     166            0 :     new_data->metadata_percent = data->metadata_percent;
     167            0 :     new_data->copy_percent = data->copy_percent;
     168            0 :     new_data->lv_tags = g_strdupv (data->lv_tags);
     169            0 :     return new_data;
     170              : }
     171              : 
     172            0 : void bd_lvm_lvdata_free (BDLVMLVdata *data) {
     173            0 :     if (data == NULL)
     174            0 :         return;
     175              : 
     176            0 :     g_free (data->lv_name);
     177            0 :     g_free (data->vg_name);
     178            0 :     g_free (data->uuid);
     179            0 :     g_free (data->attr);
     180            0 :     g_free (data->segtype);
     181            0 :     g_free (data->origin);
     182            0 :     g_free (data->pool_lv);
     183            0 :     g_free (data->data_lv);
     184            0 :     g_free (data->metadata_lv);
     185            0 :     g_free (data->roles);
     186            0 :     g_free (data->move_pv);
     187            0 :     g_strfreev (data->lv_tags);
     188            0 :     g_free (data);
     189              : }
     190              : 
     191            0 : BDLVMCacheStats* bd_lvm_cache_stats_copy (BDLVMCacheStats *data) {
     192            0 :     if (data == NULL)
     193            0 :         return NULL;
     194              : 
     195            0 :     BDLVMCacheStats *new = g_new0 (BDLVMCacheStats, 1);
     196              : 
     197            0 :     new->block_size = data->block_size;
     198            0 :     new->cache_size = data->cache_size;
     199            0 :     new->cache_used = data->cache_used;
     200            0 :     new->md_block_size = data->md_block_size;
     201            0 :     new->md_size = data->md_size;
     202            0 :     new->md_used = data->md_used;
     203            0 :     new->read_hits = data->read_hits;
     204            0 :     new->read_misses = data->read_misses;
     205            0 :     new->write_hits = data->write_hits;
     206            0 :     new->write_misses = data->write_misses;
     207            0 :     new->mode = data->mode;
     208              : 
     209            0 :     return new;
     210              : }
     211              : 
     212            0 : void bd_lvm_cache_stats_free (BDLVMCacheStats *data) {
     213            0 :     g_free (data);
     214            0 : }
     215              : 
     216           13 : static gboolean setup_dbus_connection (GError **error) {
     217           13 :     gchar *addr = NULL;
     218              : 
     219           13 :     addr = g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SYSTEM, NULL, error);
     220           13 :     if (!addr) {
     221            0 :         g_prefix_error (error, "Failed to get system bus address: ");
     222            0 :         return FALSE;
     223              :     }
     224              : 
     225           13 :     bus = g_dbus_connection_new_for_address_sync (addr,
     226              :                                                   G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT|
     227              :                                                   G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
     228              :                                                   NULL, NULL, error);
     229              : 
     230           13 :     g_free (addr);
     231              : 
     232           13 :     if (!bus) {
     233            0 :         g_prefix_error (error, "Failed to create a new connection for the system bus: ");
     234            0 :         return FALSE;
     235              :     }
     236              : 
     237           13 :     if (g_dbus_connection_is_closed (bus)) {
     238            0 :         g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
     239              :                      "Connection is closed");
     240            0 :         return FALSE;
     241              :     }
     242              : 
     243           13 :     g_dbus_connection_set_exit_on_close (bus, FALSE);
     244              : 
     245           13 :     return TRUE;
     246              : }
     247              : 
     248              : static volatile guint avail_deps = 0;
     249              : static volatile guint avail_dbus_deps = 0;
     250              : static volatile guint avail_features = 0;
     251              : static volatile guint avail_module_deps = 0;
     252              : static GMutex deps_check_lock;
     253              : 
     254              : #define DEPS_LVM 0
     255              : #define DEPS_LVM_MASK (1 << DEPS_LVM)
     256              : #define DEPS_LVMDEVICES 1
     257              : #define DEPS_LVMDEVICES_MASK (1 << DEPS_LVMDEVICES)
     258              : #define DEPS_LVMCONFIG 2
     259              : #define DEPS_LVMCONFIG_MASK (1 << DEPS_LVMCONFIG)
     260              : #define DEPS_LAST 3
     261              : 
     262              : static const UtilDep deps[DEPS_LAST] = {
     263              :     {"lvm", LVM_MIN_VERSION, "version", "LVM version:\\s+([\\d\\.]+)"},
     264              :     {"lvmdevices", NULL, NULL, NULL},
     265              :     {"lvmconfig", "2.03.17", "--version", "LVM version:\\s+([\\d\\.]+)"},
     266              : };
     267              : 
     268              : #define DBUS_DEPS_LVMDBUSD 0
     269              : #define DBUS_DEPS_LVMDBUSD_MASK (1 << DBUS_DEPS_LVMDBUSD)
     270              : #define DBUS_DEPS_LVMDBUSD_WRITECACHE 1
     271              : #define DBUS_DEPS_LVMDBUSD_WRITECACHE_MASK (1 << DBUS_DEPS_LVMDBUSD_WRITECACHE)
     272              : #define DBUS_DEPS_LAST 2
     273              : 
     274              : static const DBusDep dbus_deps[DBUS_DEPS_LAST] = {
     275              :     {LVM_BUS_NAME, LVM_OBJ_PREFIX, G_BUS_TYPE_SYSTEM, NULL, NULL, NULL, NULL},
     276              :     {LVM_BUS_NAME, LVM_OBJ_PREFIX, G_BUS_TYPE_SYSTEM, "1.1.0", "Version", MANAGER_INTF, MANAGER_OBJ},
     277              : };
     278              : 
     279              : #define FEATURES_VDO 0
     280              : #define FEATURES_VDO_MASK (1 << FEATURES_VDO)
     281              : #define FEATURES_WRITECACHE 0
     282              : #define FEATURES_WRITECACHE_MASK (1 << FEATURES_WRITECACHE)
     283              : #define FEATURES_LAST 2
     284              : 
     285              : static const UtilFeatureDep features[FEATURES_LAST] = {
     286              :     {"lvm", "vdo", "segtypes", NULL},
     287              :     {"lvm", "writecache", "segtypes", NULL},
     288              : };
     289              : 
     290              : #define MODULE_DEPS_VDO 0
     291              : #define MODULE_DEPS_VDO_MASK (1 << MODULE_DEPS_VDO)
     292              : #define MODULE_DEPS_LAST 1
     293              : 
     294              : static const gchar*const module_deps[MODULE_DEPS_LAST] = { "dm-vdo" };
     295              : 
     296              : /**
     297              :  * bd_lvm_init:
     298              :  *
     299              :  * Initializes the plugin. **This function is called automatically by the
     300              :  * library's initialization functions.**
     301              :  *
     302              :  */
     303           13 : gboolean bd_lvm_init (void) {
     304           13 :     GError *error = NULL;
     305              : 
     306              :     /* the check() call should create the DBus connection for us, but let's not
     307              :        completely rely on it */
     308           13 :     if (G_UNLIKELY (!bus) && !setup_dbus_connection (&error)) {
     309            0 :         bd_utils_log_format (BD_UTILS_LOG_CRIT, "Failed to setup DBus connection: %s", error->message);
     310            0 :         g_clear_error (&error);
     311            0 :         return FALSE;
     312              :     }
     313              : 
     314           13 :     dm_log_with_errno_init ((dm_log_with_errno_fn) redirect_dm_log);
     315              : #ifdef DEBUG
     316              :     dm_log_init_verbose (LOG_DEBUG);
     317              : #else
     318           13 :     dm_log_init_verbose (LOG_INFO);
     319              : #endif
     320              : 
     321           13 :     return TRUE;
     322              : }
     323              : 
     324              : /**
     325              :  * bd_lvm_close:
     326              :  *
     327              :  * Cleans up after the plugin. **This function is called automatically by the
     328              :  * library's functions that unload it.**
     329              :  *
     330              :  */
     331           13 : void bd_lvm_close (void) {
     332           13 :     GError *error = NULL;
     333              : 
     334              :     /* the check() call should create the DBus connection for us, but let's not
     335              :        completely rely on it */
     336           13 :     if (!g_dbus_connection_flush_sync (bus, NULL, &error)) {
     337            0 :         bd_utils_log_format (BD_UTILS_LOG_CRIT, "Failed to flush DBus connection: %s", error->message);
     338            0 :         g_clear_error (&error);
     339              :     }
     340           13 :     if (!g_dbus_connection_close_sync (bus, NULL, &error)) {
     341            0 :         bd_utils_log_format (BD_UTILS_LOG_CRIT, "Failed to close DBus connection: %s", error->message);
     342            0 :         g_clear_error (&error);
     343              :     }
     344              : 
     345           13 :     dm_log_with_errno_init (NULL);
     346           13 :     dm_log_init_verbose (0);
     347           13 : }
     348              : 
     349              : /**
     350              :  * bd_lvm_is_tech_avail:
     351              :  * @tech: the queried tech
     352              :  * @mode: a bit mask of queried modes of operation (#BDLVMTechMode) for @tech
     353              :  * @error: (out) (optional): place to store error (details about why the @tech-@mode combination is not available)
     354              :  *
     355              :  * Returns: whether the @tech-@mode combination is available -- supported by the
     356              :  *          plugin implementation and having all the runtime dependencies available
     357              :  */
     358          164 : gboolean bd_lvm_is_tech_avail (BDLVMTech tech, guint64 mode, GError **error) {
     359          164 :     switch (tech) {
     360            1 :     case BD_LVM_TECH_THIN_CALCS:
     361            1 :         if (mode & ~BD_LVM_TECH_MODE_QUERY) {
     362            1 :             g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_TECH_UNAVAIL,
     363              :                          "Only 'query' supported for thin calculations");
     364            1 :             return FALSE;
     365              :         } else
     366            0 :             return TRUE;
     367            0 :     case BD_LVM_TECH_CALCS:
     368            0 :         if (mode & ~BD_LVM_TECH_MODE_QUERY) {
     369            0 :             g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_TECH_UNAVAIL,
     370              :                          "Only 'query' supported for calculations");
     371            0 :             return FALSE;
     372              :         } else
     373            0 :             return TRUE;
     374            0 :     case BD_LVM_TECH_VDO:
     375            0 :         return check_dbus_deps (&avail_dbus_deps, DBUS_DEPS_LVMDBUSD_MASK, dbus_deps, DBUS_DEPS_LAST, &deps_check_lock, error) &&
     376            0 :                check_features (&avail_features, FEATURES_VDO_MASK, features, FEATURES_LAST, &deps_check_lock, error) &&
     377            0 :                check_module_deps (&avail_module_deps, MODULE_DEPS_VDO_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error);
     378            0 :     case BD_LVM_TECH_WRITECACHE:
     379            0 :         return check_dbus_deps (&avail_dbus_deps, DBUS_DEPS_LVMDBUSD_MASK|DBUS_DEPS_LVMDBUSD_WRITECACHE_MASK, dbus_deps, DBUS_DEPS_LAST, &deps_check_lock, error) &&
     380            0 :                check_features (&avail_features, FEATURES_WRITECACHE_MASK, features, FEATURES_LAST, &deps_check_lock, error);
     381          161 :     case BD_LVM_TECH_DEVICES:
     382          161 :         return check_deps (&avail_deps, DEPS_LVMDEVICES_MASK, deps, DEPS_LAST, &deps_check_lock, error);
     383            1 :     case BD_LVM_TECH_CONFIG:
     384            1 :         return check_deps (&avail_deps, DEPS_LVMCONFIG_MASK, deps, DEPS_LAST, &deps_check_lock, error);
     385            0 :     case BD_LVM_TECH_VG_CFG_BACKUP_RESTORE:
     386            0 :         return check_deps (&avail_deps, DEPS_LVM_MASK, deps, DEPS_LAST, &deps_check_lock, error);
     387            1 :     default:
     388              :         /* everything is supported by this implementation of the plugin */
     389            1 :         return check_dbus_deps (&avail_dbus_deps, DBUS_DEPS_LVMDBUSD_MASK, dbus_deps, DBUS_DEPS_LAST, &deps_check_lock, error);
     390              :     }
     391              : }
     392              : 
     393           96 : static gchar** get_existing_objects (const gchar *obj_prefix, GError **error) {
     394           96 :     GVariant *intro_v = NULL;
     395           96 :     gchar *intro_data = NULL;
     396           96 :     GDBusNodeInfo *info = NULL;
     397           96 :     gchar **ret = NULL;
     398              :     GDBusNodeInfo **nodes;
     399           96 :     guint64 n_nodes = 0;
     400           96 :     guint64 i = 0;
     401              : 
     402           96 :     intro_v = g_dbus_connection_call_sync (bus, LVM_BUS_NAME, obj_prefix, DBUS_INTRO_IFACE,
     403              :                                            "Introspect", NULL, NULL, G_DBUS_CALL_FLAGS_NONE,
     404              :                                            -1, NULL, error);
     405           96 :     if (!intro_v)
     406              :         /* no introspection data, something went wrong (error must be set) */
     407            0 :         return NULL;
     408              : 
     409           96 :     g_variant_get (intro_v, "(s)", &intro_data);
     410           96 :     g_variant_unref (intro_v);
     411           96 :     info = g_dbus_node_info_new_for_xml (intro_data, error);
     412           96 :     g_free (intro_data);
     413              : 
     414          150 :     for (nodes = info->nodes; (*nodes); nodes++)
     415           54 :         n_nodes++;
     416              : 
     417           96 :     ret = g_new0 (gchar*, n_nodes + 1);
     418          150 :     for (nodes = info->nodes, i=0; (*nodes); nodes++, i++) {
     419           54 :         ret[i] = g_strdup_printf ("%s/%s", obj_prefix, ((*nodes)->path));
     420              :     }
     421           96 :     ret[i] = NULL;
     422              : 
     423           96 :     g_dbus_node_info_unref (info);
     424              : 
     425           96 :     return ret;
     426              : }
     427              : 
     428              : 
     429              : /**
     430              :  * get_object_path:
     431              :  * @obj_id: get object path for an LVM object (vgname/lvname)
     432              :  * @error: (out) (optional): place to store error (if any)
     433              :  *
     434              :  * Returns: (transfer full): object path
     435              :  */
     436          683 : static gchar* get_object_path (const gchar *obj_id, GError **error) {
     437          683 :     GVariant *args = NULL;
     438          683 :     GVariant *ret = NULL;
     439          683 :     gchar *obj_path = NULL;
     440              : 
     441          683 :     args = g_variant_new ("(s)", obj_id);
     442              :     /* consumes (frees) the 'args' parameter */
     443          683 :     ret = g_dbus_connection_call_sync (bus, LVM_BUS_NAME, MANAGER_OBJ, MANAGER_INTF,
     444              :                                        "LookUpByLvmId", args, NULL, G_DBUS_CALL_FLAGS_NONE,
     445              :                                        -1, NULL, error);
     446          683 :     if (!ret)
     447              :         /* error is already set */
     448            0 :         return NULL;
     449              : 
     450          683 :     g_variant_get (ret, "(o)", &obj_path);
     451          683 :     g_variant_unref (ret);
     452              : 
     453          683 :     if (g_strcmp0 (obj_path, "/") == 0) {
     454              :         /* not a valid path (at least for us) */
     455          110 :         g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_NOEXIST,
     456              :                      "The object with LVM ID '%s' doesn't exist", obj_id);
     457          110 :         g_free (obj_path);
     458          110 :         return NULL;
     459              :     }
     460              : 
     461          573 :     return obj_path;
     462              : }
     463              : 
     464              : /**
     465              :  * get_object_property:
     466              :  * @obj_path: lvmdbusd object path
     467              :  * @iface: interface on @obj_path object
     468              :  * @property: property to get from @obj_path and @iface
     469              :  * @error: (out) (optional): place to store error (if any)
     470              :  *
     471              :  * Returns: (transfer full): object path
     472              :  */
     473          394 : static GVariant* get_object_property (const gchar *obj_path, const gchar *iface, const gchar *property, GError **error) {
     474          394 :     GVariant *args = NULL;
     475          394 :     GVariant *ret = NULL;
     476          394 :     GVariant *real_ret = NULL;
     477              : 
     478          394 :     args = g_variant_new ("(ss)", iface, property);
     479              : 
     480              :     /* consumes (frees) the 'args' parameter */
     481          394 :     ret = g_dbus_connection_call_sync (bus, LVM_BUS_NAME, obj_path, DBUS_PROPS_IFACE,
     482              :                                        "Get", args, NULL, G_DBUS_CALL_FLAGS_NONE,
     483              :                                        -1, NULL, error);
     484          394 :     if (!ret) {
     485            0 :         g_prefix_error (error, "Failed to get %s property of the %s object: ", property, obj_path);
     486            0 :         return NULL;
     487              :     }
     488              : 
     489          394 :     g_variant_get (ret, "(v)", &real_ret);
     490          394 :     g_variant_unref (ret);
     491              : 
     492          394 :     return real_ret;
     493              : }
     494              : 
     495              : /**
     496              :  * get_lvm_object_property:
     497              :  * @obj_id: LVM object to get the property for (vgname/lvname)
     498              :  * @iface: interface where @property is defined
     499              :  * @property: property to get from @obj_id and @iface
     500              :  * @error: (out) (optional): place to store error (if any)
     501              :  *
     502              :  * Returns: (transfer full): property variant
     503              :  */
     504           76 : static GVariant* get_lvm_object_property (const gchar *obj_id, const gchar *iface, const gchar *property, GError **error) {
     505           76 :     gchar *obj_path = NULL;
     506           76 :     GVariant *ret = NULL;
     507              : 
     508           76 :     obj_path = get_object_path (obj_id, error);
     509           76 :     if (!obj_path)
     510              :         /* error is already set */
     511            0 :         return NULL;
     512              :     else {
     513           76 :         ret = get_object_property (obj_path, iface, property, error);
     514           76 :         g_free (obj_path);
     515           76 :         return ret;
     516              :     }
     517              : }
     518              : 
     519           12 : static gboolean unbox_params_and_add (GVariant *params, GVariantBuilder *builder) {
     520              :     GVariantIter iter;
     521           12 :     GVariant *param = NULL;
     522           12 :     gboolean ret = FALSE;
     523              : 
     524           12 :     if (g_variant_is_of_type (params, G_VARIANT_TYPE_DICTIONARY)) {
     525           12 :         g_variant_iter_init (&iter, params);
     526           34 :         while ((param = g_variant_iter_next_value (&iter))) {
     527           22 :             g_variant_builder_add_value (builder, param);
     528           22 :             ret = TRUE;
     529              :         }
     530           12 :         return ret;
     531              :     }
     532              : 
     533            0 :     if (g_variant_is_of_type (params, G_VARIANT_TYPE_VARIANT)) {
     534            0 :         param = g_variant_get_variant (params);
     535            0 :         return unbox_params_and_add (param, builder);
     536              :     }
     537              : 
     538            0 :     if (g_variant_is_container (params)) {
     539            0 :         g_variant_iter_init (&iter, params);
     540            0 :         while ((param = g_variant_iter_next_value (&iter)))
     541            0 :             ret = unbox_params_and_add (param, builder);
     542            0 :         return ret;
     543              :     }
     544              : 
     545            0 :     return FALSE;
     546              : }
     547              : 
     548              : /**
     549              :  * call_lvm_method
     550              :  * @obj: lvmdbusd object path
     551              :  * @intf: interface to call @method on
     552              :  * @method: method to call
     553              :  * @params: parameters for @method
     554              :  * @extra_params: extra parameters for @method
     555              :  * @extra_args: extra command line argument to be passed to the LVM command
     556              :  * @task_id: (out): task ID to watch progress of the operation
     557              :  * @progress_id: (out): progress ID to watch progress of the operation
     558              :  * @lock_config: whether to lock %global_config_lock or not (if %FALSE is given, caller is responsible
     559              :  *               for holding the lock for this call)
     560              :  * @error: (out) (optional): place to store error (if any)
     561              :  *
     562              :  * Returns: (transfer full): return value of @method (variant)
     563              :  */
     564          441 : static GVariant* call_lvm_method (const gchar *obj, const gchar *intf, const gchar *method, GVariant *params, GVariant *extra_params, const BDExtraArg **extra_args, guint64 *task_id, guint64 *progress_id, gboolean lock_config, GError **error) {
     565          441 :     GVariant *config = NULL;
     566          441 :     GVariant *devices = NULL;
     567          441 :     GVariant *param = NULL;
     568              :     GVariantIter iter;
     569              :     GVariantBuilder builder;
     570              :     GVariantBuilder extra_builder;
     571          441 :     GVariant *config_extra_params = NULL;
     572          441 :     GVariant *tmo = NULL;
     573          441 :     GVariant *all_params = NULL;
     574          441 :     GVariant *ret = NULL;
     575          441 :     gchar *params_str = NULL;
     576          441 :     gchar *log_msg = NULL;
     577          441 :     gchar *prog_msg = NULL;
     578          441 :     const BDExtraArg **extra_p = NULL;
     579          441 :     gboolean added_extra = FALSE;
     580              : 
     581          441 :     if (!check_dbus_deps (&avail_dbus_deps, DBUS_DEPS_LVMDBUSD_MASK, dbus_deps, DBUS_DEPS_LAST, &deps_check_lock, error))
     582            0 :         return NULL;
     583              : 
     584              :     /* don't allow global config string changes during the run */
     585          441 :     if (lock_config)
     586          434 :         g_mutex_lock (&global_config_lock);
     587              : 
     588          441 :     if (global_config_str || global_devices_str || extra_params || extra_args) {
     589          213 :         if (global_config_str || global_devices_str || extra_args) {
     590              :             /* add the global config to the extra_params */
     591           17 :             g_variant_builder_init (&extra_builder, G_VARIANT_TYPE_DICTIONARY);
     592              : 
     593           17 :             if (extra_params)
     594           12 :                 added_extra = unbox_params_and_add (extra_params, &extra_builder);
     595              : 
     596           17 :             if (extra_args) {
     597            4 :                 for (extra_p=extra_args; *extra_p; extra_p++) {
     598            4 :                     g_variant_builder_add (&extra_builder, "{sv}",
     599            2 :                                            (*extra_p)->opt ? (*extra_p)->opt : "",
     600              :                                            g_variant_new ("s",
     601            2 :                                                           (*extra_p)->val ? (*extra_p)->val : ""));
     602            2 :                     added_extra = TRUE;
     603              :                 }
     604              :             }
     605           17 :             if (global_config_str) {
     606           14 :                 config = g_variant_new ("s", global_config_str);
     607           14 :                 g_variant_builder_add (&extra_builder, "{sv}", "--config", config);
     608           14 :                 added_extra = TRUE;
     609              :             }
     610           17 :             if (global_devices_str) {
     611            1 :                 devices = g_variant_new ("s", global_devices_str);
     612            1 :                 g_variant_builder_add (&extra_builder, "{sv}", "--devices", devices);
     613            1 :                 added_extra = TRUE;
     614              :             }
     615              : 
     616           17 :             if (added_extra)
     617           17 :                 config_extra_params = g_variant_builder_end (&extra_builder);
     618           17 :             g_variant_builder_clear (&extra_builder);
     619              :         } else
     620              :             /* just use the extra_params */
     621          196 :             config_extra_params = extra_params;
     622              :     }
     623              : 
     624          441 :     if (!config_extra_params)
     625              :         /* create an empty dictionary with the extra arguments */
     626          228 :         config_extra_params = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
     627              : 
     628              :     /* create new GVariant holding the given parameters with the global
     629              :        config and extra_params merged together appended */
     630          441 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
     631              : 
     632          441 :     if (params) {
     633              :         /* add parameters */
     634          269 :         g_variant_iter_init (&iter, params);
     635          753 :         while ((param = g_variant_iter_next_value (&iter))) {
     636          484 :             g_variant_builder_add_value (&builder, param);
     637          484 :             g_variant_unref (param);
     638              :         }
     639              :     }
     640              : 
     641              :     /* add the timeout spec (in seconds) */
     642          441 :     tmo = g_variant_new ("i", 1);
     643          441 :     g_variant_builder_add_value (&builder, tmo);
     644              : 
     645              :     /* add extra parameters including config */
     646          441 :     g_variant_builder_add_value (&builder, config_extra_params);
     647              : 
     648          441 :     all_params = g_variant_builder_end (&builder);
     649          441 :     g_variant_builder_clear (&builder);
     650              : 
     651          441 :     params_str = g_variant_print (all_params, FALSE);
     652              : 
     653          441 :     *task_id = bd_utils_get_next_task_id ();
     654          441 :     log_msg = g_strdup_printf ("Calling the '%s.%s' method on the '%s' object with the following parameters: '%s'",
     655              :                                intf, method, obj, params_str);
     656          441 :     bd_utils_log_task_status (*task_id, log_msg);
     657          441 :     g_free (log_msg);
     658              : 
     659              :     /* now do the call with all the parameters */
     660          441 :     ret = g_dbus_connection_call_sync (bus, LVM_BUS_NAME, obj, intf, method, all_params,
     661              :                                        NULL, G_DBUS_CALL_FLAGS_NONE, METHOD_CALL_TIMEOUT, NULL, error);
     662              : 
     663          441 :     if (lock_config)
     664          434 :          g_mutex_unlock (&global_config_lock);
     665          441 :     prog_msg = g_strdup_printf ("Started the '%s.%s' method on the '%s' object with the following parameters: '%s'",
     666              :                                intf, method, obj, params_str);
     667          441 :     g_free (params_str);
     668          441 :     *progress_id = bd_utils_report_started (prog_msg);
     669          441 :     g_free (prog_msg);
     670              : 
     671          441 :     if (!ret) {
     672            5 :         g_prefix_error (error, "Failed to call the '%s' method on the '%s' object: ", method, obj);
     673            5 :         return NULL;
     674              :     }
     675              : 
     676          436 :     return ret;
     677              : }
     678              : 
     679              : /**
     680              :  * call_lvm_method_sync
     681              :  * @obj: lvmdbusd object path
     682              :  * @intf: interface to call @method on
     683              :  * @method: method to call
     684              :  * @params: parameters for @method
     685              :  * @extra_params: extra parameters for @method
     686              :  * @extra_args: extra command line argument to be passed to the LVM command
     687              :  * @lock_config: whether to lock %global_config_lock or not (if %FALSE is given, caller is responsible
     688              :  *               for holding the lock for this call)
     689              :  * @error: (out) (optional): place to store error (if any)
     690              :  *
     691              :  * Returns: whether calling the method was successful or not
     692              :  */
     693          441 : static gboolean call_lvm_method_sync (const gchar *obj, const gchar *intf, const gchar *method, GVariant *params, GVariant *extra_params, const BDExtraArg **extra_args, gboolean lock_config, GError **error) {
     694          441 :     GVariant *ret = NULL;
     695          441 :     gchar *obj_path = NULL;
     696          441 :     g_autofree gchar *task_path = NULL;
     697          441 :     guint64 log_task_id = 0;
     698          441 :     guint64 prog_id = 0;
     699          441 :     gdouble progress = 0.0;
     700          441 :     gchar *log_msg = NULL;
     701          441 :     gboolean completed = FALSE;
     702          441 :     gint64 error_code = 0;
     703          441 :     gchar *error_msg = NULL;
     704          441 :     GError *l_error = NULL;
     705              : 
     706          441 :     ret = call_lvm_method (obj, intf, method, params, extra_params, extra_args, &log_task_id, &prog_id, lock_config, &l_error);
     707          441 :     bd_utils_log_task_status (log_task_id, "Done.");
     708          441 :     if (!ret) {
     709            5 :         if (l_error) {
     710            5 :             log_msg = g_strdup_printf ("Got error: %s", l_error->message);
     711            5 :             bd_utils_log_task_status (log_task_id, log_msg);
     712            5 :             bd_utils_report_finished (prog_id, log_msg);
     713            5 :             g_free (log_msg);
     714            5 :             g_propagate_error (error, l_error);
     715              :         } else {
     716            0 :             bd_utils_log_task_status (log_task_id, "Got unknown error");
     717            0 :             bd_utils_report_finished (prog_id, "Got unknown error");
     718              :         }
     719            5 :         return FALSE;
     720              :     }
     721          436 :     if (g_variant_check_format_string (ret, "((oo))", TRUE)) {
     722          211 :         g_variant_get (ret, "((oo))", &obj_path, &task_path);
     723          211 :         if (g_strcmp0 (obj_path, "/") != 0) {
     724          209 :             log_msg = g_strdup_printf ("Got result: %s", obj_path);
     725          209 :             bd_utils_log_task_status (log_task_id, log_msg);
     726          209 :             g_free (log_msg);
     727              :             /* got a valid result, just return */
     728          209 :             g_variant_unref (ret);
     729          209 :             g_free (obj_path);
     730          209 :             bd_utils_report_finished (prog_id, "Completed");
     731          209 :             return TRUE;
     732              :         } else {
     733            2 :             g_variant_unref (ret);
     734            2 :             g_free (obj_path);
     735            2 :             if (g_strcmp0 (task_path, "/") == 0) {
     736            0 :                 log_msg = g_strdup_printf ("Task finished without result and without job started");
     737            0 :                 g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
     738              :                              "Running '%s' method on the '%s' object failed: %s",
     739              :                              method, obj, log_msg);
     740            0 :                 bd_utils_log_task_status (log_task_id, log_msg);
     741            0 :                 bd_utils_report_finished (prog_id, log_msg);
     742            0 :                 g_free (log_msg);
     743            0 :                 return FALSE;
     744              :             }
     745              :         }
     746          225 :     } else if (g_variant_check_format_string (ret, "(o)", TRUE)) {
     747          225 :         g_variant_get (ret, "(o)", &task_path);
     748          225 :         if (g_strcmp0 (task_path, "/") != 0) {
     749            2 :             g_variant_unref (ret);
     750              :         } else {
     751          223 :             bd_utils_log_task_status (log_task_id, "No result, no job started");
     752          223 :             bd_utils_report_finished (prog_id, "Completed");
     753          223 :             g_variant_unref (ret);
     754          223 :             return TRUE;
     755              :         }
     756              :     } else {
     757            0 :         g_variant_unref (ret);
     758            0 :         bd_utils_log_task_status (log_task_id, "Failed to parse the returned value!");
     759            0 :         g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_PARSE,
     760              :                      "Failed to parse the returned value!");
     761            0 :         bd_utils_report_finished (prog_id, "Failed to parse the returned value!");
     762            0 :         return FALSE;
     763              :     }
     764              : 
     765            4 :     log_msg = g_strdup_printf ("Waiting for job '%s' to finish", task_path);
     766            4 :     bd_utils_log_task_status (log_task_id, log_msg);
     767            4 :     g_free (log_msg);
     768              : 
     769            4 :     ret = NULL;
     770            8 :     while (!completed && !l_error) {
     771            4 :         g_usleep (PROGRESS_WAIT);
     772            4 :         ret = get_object_property (task_path, JOB_INTF, "Complete", &l_error);
     773            4 :         if (ret) {
     774            4 :             g_variant_get (ret, "b", &completed);
     775            4 :             g_variant_unref (ret);
     776            4 :             ret = NULL;
     777              :         }
     778            4 :         if (!completed && !l_error) {
     779              :             /* let's report progress and wait longer */
     780            0 :             ret = get_object_property (task_path, JOB_INTF, "Percent", &l_error);
     781            0 :             if (ret) {
     782            0 :                 g_variant_get (ret, "d", &progress);
     783            0 :                 bd_utils_report_progress (prog_id, (gint) progress, NULL);
     784            0 :                 g_variant_unref (ret);
     785            0 :                 ret = NULL;
     786              :             } else {
     787            0 :                 bd_utils_log_format (BD_UTILS_LOG_DEBUG, "Got error when getting progress: %s", l_error->message);
     788            0 :                 g_clear_error (&l_error);
     789              :             }
     790            0 :             log_msg = g_strdup_printf ("Still waiting for job '%s' to finish", task_path);
     791            0 :             bd_utils_log_task_status (log_task_id, log_msg);
     792            0 :             g_free (log_msg);
     793              :         }
     794              : 
     795              :     }
     796            4 :     log_msg = g_strdup_printf ("Job '%s' finished", task_path);
     797            4 :     bd_utils_log_task_status (log_task_id, log_msg);
     798            4 :     g_free (log_msg);
     799              : 
     800            4 :     obj_path = NULL;
     801            4 :     if (!l_error) {
     802            4 :         ret = get_object_property (task_path, JOB_INTF, "Result", &l_error);
     803            4 :         if (!ret) {
     804            0 :             g_prefix_error (&l_error, "Getting result after waiting for '%s' method of the '%s' object failed: ",
     805              :                             method, obj);
     806            0 :             bd_utils_report_finished (prog_id, l_error->message);
     807            0 :             g_propagate_error (error, l_error);
     808            0 :             return FALSE;
     809              :         } else {
     810            4 :             g_variant_get (ret, "o", &obj_path);
     811            4 :             g_variant_unref (ret);
     812            4 :             if (g_strcmp0 (obj_path, "/") != 0) {
     813            2 :                 log_msg = g_strdup_printf ("Got result: %s", obj_path);
     814            2 :                 bd_utils_log_task_status (log_task_id, log_msg);
     815            2 :                 g_free (log_msg);
     816              :             } else {
     817            2 :                 ret = get_object_property (task_path, JOB_INTF, "GetError", &l_error);
     818            2 :                 g_variant_get (ret, "(is)", &error_code, &error_msg);
     819            2 :                 if (error_code != 0) {
     820            0 :                     if (error_msg) {
     821            0 :                         log_msg = g_strdup_printf ("Got error: %s", error_msg);
     822            0 :                         bd_utils_log_task_status (log_task_id, log_msg);
     823            0 :                         bd_utils_report_finished (prog_id, log_msg);
     824            0 :                         g_set_error (&l_error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
     825              :                                      "Running '%s' method on the '%s' object failed: %s",
     826              :                                      method, obj, error_msg);
     827            0 :                         g_free (log_msg);
     828            0 :                         g_free (error_msg);
     829              :                     } else {
     830            0 :                         bd_utils_log_task_status (log_task_id, "Got unknown error");
     831            0 :                         bd_utils_report_finished (prog_id, "Got unknown error");
     832            0 :                         g_set_error (&l_error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
     833              :                                      "Got unknown error when running '%s' method on the '%s' object.",
     834              :                                      method, obj);
     835              :                     }
     836            0 :                     g_propagate_error (error, l_error);
     837            0 :                     return FALSE;
     838              :                 } else
     839            2 :                     bd_utils_log_task_status (log_task_id, "No result");
     840              :             }
     841            4 :             bd_utils_report_finished (prog_id, "Completed");
     842            4 :             g_free (obj_path);
     843              : 
     844              :             /* remove the job object and clean after ourselves */
     845            4 :             ret = g_dbus_connection_call_sync (bus, LVM_BUS_NAME, task_path, JOB_INTF, "Remove", NULL,
     846              :                                                NULL, G_DBUS_CALL_FLAGS_NONE, METHOD_CALL_TIMEOUT, NULL, NULL);
     847            4 :             if (ret)
     848            4 :                 g_variant_unref (ret);
     849              : 
     850            4 :             return TRUE;
     851              :         }
     852              :     } else {
     853              :         /* some real error */
     854            0 :         g_prefix_error (&l_error, "Waiting for '%s' method of the '%s' object to finish failed: ",
     855              :                         method, obj);
     856            0 :         g_propagate_error (error, l_error);
     857            0 :         bd_utils_report_finished (prog_id, "Completed");
     858            0 :         return FALSE;
     859              :     }
     860              : }
     861              : 
     862          399 : static gboolean call_lvm_obj_method_sync (const gchar *obj_id, const gchar *intf, const gchar *method, GVariant *params, GVariant *extra_params, const BDExtraArg **extra_args, gboolean lock_config, GError **error) {
     863          798 :     g_autofree gchar *obj_path = get_object_path (obj_id, error);
     864          399 :     if (!obj_path)
     865          105 :         return FALSE;
     866              : 
     867          294 :     return call_lvm_method_sync (obj_path, intf, method, params, extra_params, extra_args, lock_config, error);
     868              : }
     869              : 
     870           93 : static gboolean call_lv_method_sync (const gchar *vg_name, const gchar *lv_name, const gchar *method, GVariant *params, GVariant *extra_params, const BDExtraArg **extra_args, gboolean lock_config, GError **error) {
     871          186 :     g_autofree gchar *obj_id = g_strdup_printf ("%s/%s", vg_name, lv_name);
     872              : 
     873           93 :     return call_lvm_obj_method_sync (obj_id, LV_INTF, method, params, extra_params, extra_args, lock_config, error);
     874              : }
     875              : 
     876            2 : static gboolean call_thpool_method_sync (const gchar *vg_name, const gchar *pool_name, const gchar *method, GVariant *params, GVariant *extra_params, const BDExtraArg **extra_args, gboolean lock_config, GError **error) {
     877            4 :     g_autofree gchar *obj_id = g_strdup_printf ("%s/%s", vg_name, pool_name);
     878              : 
     879            2 :     return call_lvm_obj_method_sync (obj_id, THPOOL_INTF, method, params, extra_params, extra_args, lock_config, error);
     880              : }
     881              : 
     882            4 : static gboolean call_vdopool_method_sync (const gchar *vg_name, const gchar *pool_name, const gchar *method, GVariant *params, GVariant *extra_params, const BDExtraArg **extra_args, gboolean lock_config, GError **error) {
     883            8 :     g_autofree gchar *obj_id = g_strdup_printf ("%s/%s", vg_name, pool_name);
     884              : 
     885            4 :     return call_lvm_obj_method_sync (obj_id, VDO_POOL_INTF, method, params, extra_params, extra_args, lock_config, error);
     886              : }
     887              : 
     888           71 : static GVariant* get_lv_property (const gchar *vg_name, const gchar *lv_name, const gchar *property, GError **error) {
     889           71 :     gchar *lv_spec = NULL;
     890           71 :     GVariant *ret = NULL;
     891              : 
     892           71 :     lv_spec = g_strdup_printf ("%s/%s", vg_name, lv_name);
     893              : 
     894           71 :     ret = get_lvm_object_property (lv_spec, LV_CMN_INTF, property, error);
     895           71 :     g_free (lv_spec);
     896              : 
     897           71 :     return ret;
     898              : }
     899              : 
     900          137 : static GVariant* get_object_properties (const gchar *obj_path, const gchar *iface, GError **error) {
     901          137 :     GVariant *args = NULL;
     902          137 :     GVariant *ret = NULL;
     903          137 :     GVariant *real_ret = NULL;
     904              : 
     905          137 :     args = g_variant_new ("(s)", iface);
     906              : 
     907              :     /* consumes (frees) the 'args' parameter */
     908          137 :     ret = g_dbus_connection_call_sync (bus, LVM_BUS_NAME, obj_path, DBUS_PROPS_IFACE,
     909              :                                        "GetAll", args, NULL, G_DBUS_CALL_FLAGS_NONE,
     910              :                                        -1, NULL, error);
     911          137 :     if (!ret) {
     912            0 :         g_prefix_error (error, "Failed to get properties of the %s object: ", obj_path);
     913            0 :         return NULL;
     914              :     }
     915              : 
     916          137 :     real_ret = g_variant_get_child_value (ret, 0);
     917          137 :     g_variant_unref (ret);
     918              : 
     919          137 :     return real_ret;
     920              : }
     921              : 
     922           70 : static GVariant* get_lvm_object_properties (const gchar *obj_id, const gchar *iface, GError **error) {
     923           70 :     GVariant *args = NULL;
     924           70 :     GVariant *ret = NULL;
     925           70 :     gchar *obj_path = NULL;
     926              : 
     927           70 :     if (!obj_id || g_strcmp0 (obj_id, "") == 0) {
     928            0 :         g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_NOEXIST,
     929              :                      "Invalid LVM ID specified");
     930            0 :         return NULL;
     931              :     }
     932              : 
     933           70 :     args = g_variant_new ("(s)", obj_id);
     934              :     /* consumes (frees) the 'args' parameter */
     935           70 :     ret = g_dbus_connection_call_sync (bus, LVM_BUS_NAME, MANAGER_OBJ, MANAGER_INTF,
     936              :                                        "LookUpByLvmId", args, NULL, G_DBUS_CALL_FLAGS_NONE,
     937              :                                        -1, NULL, error);
     938           70 :     g_variant_get (ret, "(o)", &obj_path);
     939           70 :     g_variant_unref (ret);
     940              : 
     941           70 :     if (g_strcmp0 (obj_path, "/") == 0) {
     942            0 :         g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_NOEXIST,
     943              :                      "The object with LVM ID '%s' doesn't exist", obj_id);
     944            0 :         g_free (obj_path);
     945            0 :         return NULL;
     946              :     }
     947              : 
     948           70 :     ret = get_object_properties (obj_path, iface, error);
     949           70 :     g_free (obj_path);
     950           70 :     return ret;
     951              : }
     952              : 
     953              : 
     954           14 : static GVariant* get_pv_properties (const gchar *pv_name, GError **error) {
     955           14 :     gchar *obj_id = NULL;
     956           14 :     GVariant *ret = NULL;
     957              : 
     958           14 :     if (!g_str_has_prefix (pv_name, "/dev/")) {
     959            0 :         obj_id = g_strdup_printf ("/dev/%s", pv_name);
     960            0 :         ret = get_lvm_object_properties (obj_id, PV_INTF, error);
     961            0 :         g_free (obj_id);
     962              :     } else
     963           14 :         ret = get_lvm_object_properties (pv_name, PV_INTF, error);
     964              : 
     965           14 :     return ret;
     966              : }
     967              : 
     968            6 : static GVariant* get_vg_properties (const gchar *vg_name, GError **error) {
     969            6 :     GVariant *ret = NULL;
     970              : 
     971            6 :     ret = get_lvm_object_properties (vg_name, VG_INTF, error);
     972              : 
     973            6 :     return ret;
     974              : }
     975              : 
     976           41 : static GVariant* get_lv_properties (const gchar *vg_name, const gchar *lv_name, GError **error) {
     977           41 :     gchar *lvm_spec = NULL;
     978           41 :     GVariant *ret = NULL;
     979              : 
     980           41 :     lvm_spec = g_strdup_printf ("%s/%s", vg_name, lv_name);
     981              : 
     982           41 :     ret = get_lvm_object_properties (lvm_spec, LV_CMN_INTF, error);
     983           41 :     g_free (lvm_spec);
     984              : 
     985           41 :     return ret;
     986              : }
     987              : 
     988            9 : static GVariant* get_vdo_properties (const gchar *vg_name, const gchar *pool_name, GError **error) {
     989            9 :     gchar *lvm_spec = NULL;
     990            9 :     GVariant *ret = NULL;
     991              : 
     992            9 :     lvm_spec = g_strdup_printf ("%s/%s", vg_name, pool_name);
     993              : 
     994            9 :     ret = get_lvm_object_properties (lvm_spec, VDO_POOL_INTF, error);
     995            9 :     g_free (lvm_spec);
     996              : 
     997            9 :     return ret;
     998              : }
     999              : 
    1000           20 : static BDLVMPVdata* get_pv_data_from_props (GVariant *props, GError **error G_GNUC_UNUSED) {
    1001           20 :     BDLVMPVdata *data = g_new0 (BDLVMPVdata, 1);
    1002              :     GVariantDict dict;
    1003           20 :     gchar *path = NULL;
    1004           20 :     GVariant *vg_props = NULL;
    1005           20 :     GVariant *value = NULL;
    1006           20 :     gsize n_children = 0;
    1007           20 :     gsize i = 0;
    1008           20 :     gchar **tags = NULL;
    1009           20 :     GError *l_error = NULL;
    1010              : 
    1011           20 :     g_variant_dict_init (&dict, props);
    1012              : 
    1013           20 :     g_variant_dict_lookup (&dict, "Name", "s", &(data->pv_name));
    1014           20 :     g_variant_dict_lookup (&dict, "Uuid", "s", &(data->pv_uuid));
    1015           20 :     g_variant_dict_lookup (&dict, "FreeBytes", "t", &(data->pv_free));
    1016           20 :     g_variant_dict_lookup (&dict, "SizeBytes", "t", &(data->pv_size));
    1017           20 :     g_variant_dict_lookup (&dict, "PeStart", "t", &(data->pe_start));
    1018           20 :     g_variant_dict_lookup (&dict, "Missing", "b", &(data->missing));
    1019              : 
    1020           20 :     value = g_variant_dict_lookup_value (&dict, "Tags", (GVariantType*) "as");
    1021           20 :     if (value) {
    1022           20 :         n_children = g_variant_n_children (value);
    1023           20 :         tags = g_new0 (gchar*, n_children + 1);
    1024           30 :         for (i=0; i < n_children; i++) {
    1025           10 :             g_variant_get_child (value, i, "s", tags+i);
    1026              :         }
    1027           20 :         data->pv_tags = tags;
    1028           20 :         g_variant_unref (value);
    1029              :     }
    1030              : 
    1031              :     /* returns an object path for the VG */
    1032           20 :     g_variant_dict_lookup (&dict, "Vg", "&o", &path);
    1033           20 :     if (g_strcmp0 (path, "/") == 0) {
    1034              :         /* no VG, the PV is not part of any VG */
    1035            7 :         g_variant_dict_clear (&dict);
    1036            7 :         return data;
    1037              :     }
    1038              : 
    1039           13 :     vg_props = get_object_properties (path, VG_INTF, &l_error);
    1040           13 :     g_variant_dict_clear (&dict);
    1041           13 :     if (!vg_props) {
    1042            0 :         if (l_error) {
    1043            0 :             bd_utils_log_format (BD_UTILS_LOG_DEBUG, "Failed to get VG properties for PV %s: %s",
    1044            0 :                                  data->pv_name, l_error->message);
    1045            0 :             g_clear_error (&l_error);
    1046              :         }
    1047            0 :         return data;
    1048              :     }
    1049              : 
    1050           13 :     g_variant_dict_init (&dict, vg_props);
    1051           13 :     g_variant_dict_lookup (&dict, "Name", "s", &(data->vg_name));
    1052           13 :     g_variant_dict_lookup (&dict, "Uuid", "s", &(data->vg_uuid));
    1053           13 :     g_variant_dict_lookup (&dict, "SizeBytes", "t", &(data->vg_size));
    1054           13 :     g_variant_dict_lookup (&dict, "FreeBytes", "t", &(data->vg_free));
    1055           13 :     g_variant_dict_lookup (&dict, "ExtentSizeBytes", "t", &(data->vg_extent_size));
    1056           13 :     g_variant_dict_lookup (&dict, "ExtentCount", "t", &(data->vg_extent_count));
    1057           13 :     g_variant_dict_lookup (&dict, "FreeCount", "t", &(data->vg_free_count));
    1058           13 :     g_variant_dict_lookup (&dict, "PvCount", "t", &(data->vg_pv_count));
    1059              : 
    1060           13 :     g_variant_dict_clear (&dict);
    1061           13 :     g_variant_unref (vg_props);
    1062              : 
    1063           13 :     return data;
    1064              : }
    1065              : 
    1066            7 : static BDLVMVGdata* get_vg_data_from_props (GVariant *props, GError **error G_GNUC_UNUSED) {
    1067            7 :     BDLVMVGdata *data = g_new0 (BDLVMVGdata, 1);
    1068              :     GVariantDict dict;
    1069            7 :     GVariant *value = NULL;
    1070            7 :     gsize n_children = 0;
    1071            7 :     gsize i = 0;
    1072            7 :     gchar **tags = NULL;
    1073              : 
    1074            7 :     g_variant_dict_init (&dict, props);
    1075              : 
    1076            7 :     g_variant_dict_lookup (&dict, "Name", "s", &(data->name));
    1077            7 :     g_variant_dict_lookup (&dict, "Uuid", "s", &(data->uuid));
    1078              : 
    1079            7 :     g_variant_dict_lookup (&dict, "SizeBytes", "t", &(data->size));
    1080            7 :     g_variant_dict_lookup (&dict, "FreeBytes", "t", &(data->free));
    1081            7 :     g_variant_dict_lookup (&dict, "ExtentSizeBytes", "t", &(data->extent_size));
    1082            7 :     g_variant_dict_lookup (&dict, "ExtentCount", "t", &(data->extent_count));
    1083            7 :     g_variant_dict_lookup (&dict, "FreeCount", "t", &(data->free_count));
    1084            7 :     g_variant_dict_lookup (&dict, "PvCount", "t", &(data->pv_count));
    1085            7 :     g_variant_dict_lookup (&dict, "Exportable", "b", &(data->exported));
    1086              : 
    1087            7 :     value = g_variant_dict_lookup_value (&dict, "Tags", (GVariantType*) "as");
    1088            7 :     if (value) {
    1089            7 :         n_children = g_variant_n_children (value);
    1090            7 :         tags = g_new0 (gchar*, n_children + 1);
    1091           13 :         for (i=0; i < n_children; i++) {
    1092            6 :             g_variant_get_child (value, i, "s", tags+i);
    1093              :         }
    1094            7 :         data->vg_tags = tags;
    1095            7 :         g_variant_unref (value);
    1096              :     }
    1097              : 
    1098            7 :     g_variant_dict_clear (&dict);
    1099              : 
    1100            7 :     return data;
    1101              : }
    1102              : 
    1103           16 : static gchar* _lvm_data_lv_name (const gchar *vg_name, const gchar *lv_name, GError **error) {
    1104           16 :     GVariant *prop = NULL;
    1105           16 :     gchar *obj_id = NULL;
    1106           16 :     gchar *obj_path = NULL;
    1107           16 :     gchar *ret = NULL;
    1108           16 :     gchar *segtype = NULL;
    1109              : 
    1110           16 :     obj_id = g_strdup_printf ("%s/%s", vg_name, lv_name);
    1111           16 :     obj_path = get_object_path (obj_id, error);
    1112           16 :     g_free (obj_id);
    1113           16 :     if (!obj_path)
    1114            0 :         return NULL;
    1115              : 
    1116           16 :     prop = get_lv_property (vg_name, lv_name, "SegType", error);
    1117           16 :     if (!prop)
    1118            0 :         return NULL;
    1119           16 :     g_variant_get_child (prop, 0, "s", &segtype);
    1120           16 :     g_variant_unref (prop);
    1121              : 
    1122           16 :     if (g_strcmp0 (segtype, "thin-pool") == 0)
    1123            8 :         prop = get_object_property (obj_path, THPOOL_INTF, "DataLv", NULL);
    1124            8 :     else if (g_strcmp0 (segtype, "cache-pool") == 0)
    1125            2 :         prop = get_object_property (obj_path, CACHE_POOL_INTF, "DataLv", NULL);
    1126            6 :     else if (g_strcmp0 (segtype, "vdo-pool") == 0)
    1127            6 :         prop = get_object_property (obj_path, VDO_POOL_INTF, "DataLv", NULL);
    1128              : 
    1129           16 :     g_free (segtype);
    1130           16 :     g_free (obj_path);
    1131           16 :     if (!prop)
    1132            0 :         return NULL;
    1133           16 :     g_variant_get (prop, "o", &obj_path);
    1134           16 :     g_variant_unref (prop);
    1135              : 
    1136           16 :     if (g_strcmp0 (obj_path, "/") == 0) {
    1137              :         /* no origin LV */
    1138            0 :         g_free (obj_path);
    1139            0 :         return NULL;
    1140              :     }
    1141           16 :     prop = get_object_property (obj_path, LV_CMN_INTF, "Name", error);
    1142           16 :     if (!prop) {
    1143            0 :         g_free (obj_path);
    1144            0 :         return NULL;
    1145              :     }
    1146              : 
    1147           16 :     g_variant_get (prop, "s", &ret);
    1148           16 :     g_variant_unref (prop);
    1149              : 
    1150           16 :     return g_strstrip (g_strdelimit (ret, "[]", ' '));
    1151              : }
    1152              : 
    1153           10 : static gchar* _lvm_metadata_lv_name (const gchar *vg_name, const gchar *lv_name, GError **error) {
    1154           10 :     GVariant *prop = NULL;
    1155           10 :     gchar *obj_id = NULL;
    1156           10 :     gchar *obj_path = NULL;
    1157           10 :     gchar *ret = NULL;
    1158              : 
    1159           10 :     obj_id = g_strdup_printf ("%s/%s", vg_name, lv_name);
    1160           10 :     obj_path = get_object_path (obj_id, error);
    1161           10 :     g_free (obj_id);
    1162           10 :     if (!obj_path)
    1163            0 :         return NULL;
    1164              : 
    1165           10 :     prop = get_object_property (obj_path, THPOOL_INTF, "MetaDataLv", NULL);
    1166           10 :     if (!prop)
    1167            0 :         prop = get_object_property (obj_path, CACHE_POOL_INTF, "MetaDataLv", NULL);
    1168           10 :     g_free (obj_path);
    1169           10 :     if (!prop)
    1170            0 :         return NULL;
    1171           10 :     g_variant_get (prop, "o", &obj_path);
    1172           10 :     g_variant_unref (prop);
    1173              : 
    1174           10 :     if (g_strcmp0 (obj_path, "/") == 0) {
    1175              :         /* no origin LV */
    1176            0 :         g_free (obj_path);
    1177            0 :         return NULL;
    1178              :     }
    1179           10 :     prop = get_object_property (obj_path, LV_CMN_INTF, "Name", error);
    1180           10 :     if (!prop) {
    1181            0 :         g_free (obj_path);
    1182            0 :         return NULL;
    1183              :     }
    1184              : 
    1185           10 :     g_variant_get (prop, "s", &ret);
    1186           10 :     g_variant_unref (prop);
    1187              : 
    1188           10 :     return g_strstrip (g_strdelimit (ret, "[]", ' '));
    1189              : }
    1190              : 
    1191           24 : static BDLVMSEGdata** _lvm_segs (const gchar *vg_name, const gchar *lv_name, GError **error) {
    1192           24 :     GVariant *prop = NULL;
    1193              :     BDLVMSEGdata **segs;
    1194              :     gsize n_segs;
    1195              :     GVariantIter iter, iter2;
    1196              :     GVariant *pv_segs, *pv_name_prop;
    1197              :     const gchar *pv;
    1198              :     gchar *pv_name;
    1199              :     guint64 pv_first_pe, pv_last_pe;
    1200              :     int i;
    1201              : 
    1202           24 :     prop = get_lv_property (vg_name, lv_name, "Devices", error);
    1203           24 :     if (!prop)
    1204            0 :         return NULL;
    1205              : 
    1206              :     /* Count number of segments */
    1207           24 :     n_segs = 0;
    1208           24 :     g_variant_iter_init (&iter, prop);
    1209           40 :     while (g_variant_iter_next (&iter, "(&o@a(tts))", NULL, &pv_segs)) {
    1210           16 :       n_segs += g_variant_n_children (pv_segs);
    1211           16 :       g_variant_unref (pv_segs);
    1212              :     }
    1213              : 
    1214           24 :     if (n_segs == 0) {
    1215            8 :       g_variant_unref (prop);
    1216            8 :       return NULL;
    1217              :     }
    1218              : 
    1219              :     /* Build segments */
    1220           16 :     segs = g_new0 (BDLVMSEGdata *, n_segs+1);
    1221           16 :     i = 0;
    1222           16 :     g_variant_iter_init (&iter, prop);
    1223           32 :     while (g_variant_iter_next (&iter, "(&o@a(tts))", &pv, &pv_segs)) {
    1224           16 :       pv_name_prop = get_object_property (pv, PV_INTF, "Name", NULL);
    1225           16 :       if (pv_name_prop) {
    1226           16 :         g_variant_get (pv_name_prop, "&s", &pv_name);
    1227           16 :         g_variant_iter_init (&iter2, pv_segs);
    1228           33 :         while (g_variant_iter_next (&iter2, "(tt&s)", &pv_first_pe, &pv_last_pe, NULL)) {
    1229           17 :           BDLVMSEGdata *seg = g_new0(BDLVMSEGdata, 1);
    1230           17 :           seg->pv_start_pe = pv_first_pe;
    1231           17 :           seg->size_pe = pv_last_pe - pv_first_pe + 1;
    1232           17 :           seg->pvdev = g_strdup (pv_name);
    1233           17 :           segs[i++] = seg;
    1234              :         }
    1235           16 :         g_variant_unref (pv_name_prop);
    1236              :       }
    1237           16 :       g_variant_unref (pv_segs);
    1238              :     }
    1239              : 
    1240           16 :     g_variant_unref (prop);
    1241           16 :     return segs;
    1242              : }
    1243              : 
    1244           24 : static void _lvm_data_and_metadata_lvs (const gchar *vg_name, const gchar *lv_name,
    1245              :                                         gchar ***data_lvs_ret, gchar ***metadata_lvs_ret,
    1246              :                                         GError **error) {
    1247              :   GVariant *prop;
    1248              :   gsize n_hidden_lvs;
    1249              :   gchar **data_lvs;
    1250              :   gchar **metadata_lvs;
    1251              :   GVariantIter iter, iter2;
    1252              :   int i_data;
    1253              :   int i_metadata;
    1254              :   const gchar *sublv;
    1255              :   GVariant *sublv_roles_prop;
    1256              :   GVariant *sublv_name_prop;
    1257              :   gchar *sublv_name;
    1258              :   const gchar *role;
    1259              : 
    1260           24 :   prop = get_lv_property (vg_name, lv_name, "HiddenLvs", error);
    1261           24 :   if (!prop) {
    1262            0 :     *data_lvs_ret = NULL;
    1263            0 :     *metadata_lvs_ret = NULL;
    1264            0 :     return;
    1265              :   }
    1266              : 
    1267           24 :   n_hidden_lvs = g_variant_n_children (prop);
    1268           24 :   data_lvs = g_new0(gchar *, n_hidden_lvs + 1);
    1269           24 :   metadata_lvs = g_new0(gchar *, n_hidden_lvs + 1);
    1270              : 
    1271           24 :   i_data = 0;
    1272           24 :   i_metadata = 0;
    1273           24 :   g_variant_iter_init (&iter, prop);
    1274           64 :   while (g_variant_iter_next (&iter, "&o", &sublv)) {
    1275           16 :     sublv_roles_prop = get_object_property (sublv, LV_INTF, "Roles", NULL);
    1276           16 :     if (sublv_roles_prop) {
    1277           16 :       sublv_name_prop = get_object_property (sublv, LV_INTF, "Name", NULL);
    1278           16 :       if (sublv_name_prop) {
    1279           16 :         g_variant_get (sublv_name_prop, "s", &sublv_name);
    1280           16 :         if (sublv_name) {
    1281           16 :           sublv_name = g_strstrip (g_strdelimit (sublv_name, "[]", ' '));
    1282           16 :           g_variant_iter_init (&iter2, sublv_roles_prop);
    1283           48 :           while (g_variant_iter_next (&iter2, "&s", &role)) {
    1284           48 :             if (g_strcmp0 (role, "image") == 0) {
    1285            8 :               data_lvs[i_data++] = sublv_name;
    1286            8 :               sublv_name = NULL;
    1287            8 :               break;
    1288           40 :             } else if (g_strcmp0 (role, "metadata") == 0) {
    1289            8 :               metadata_lvs[i_metadata++] = sublv_name;
    1290            8 :               sublv_name = NULL;
    1291            8 :               break;
    1292              :             }
    1293              :           }
    1294           16 :           g_free (sublv_name);
    1295              :         }
    1296           16 :         g_variant_unref (sublv_name_prop);
    1297              :       }
    1298           16 :       g_variant_unref (sublv_roles_prop);
    1299              :     }
    1300              :   }
    1301              : 
    1302           24 :   *data_lvs_ret = data_lvs;
    1303           24 :   *metadata_lvs_ret = metadata_lvs;
    1304              : 
    1305           24 :   g_variant_unref (prop);
    1306           24 :   return;
    1307              : }
    1308              : 
    1309           88 : static BDLVMLVdata* get_lv_data_from_props (GVariant *props, GError **error G_GNUC_UNUSED) {
    1310           88 :     BDLVMLVdata *data = g_new0 (BDLVMLVdata, 1);
    1311              :     GVariantDict dict;
    1312           88 :     GVariant *value = NULL;
    1313           88 :     gchar *path = NULL;
    1314           88 :     GVariant *name = NULL;
    1315           88 :     gsize n_children = 0;
    1316           88 :     gsize i = 0;
    1317           88 :     gchar **roles = NULL;
    1318           88 :     gchar **tags = NULL;
    1319              : 
    1320           88 :     g_variant_dict_init (&dict, props);
    1321              : 
    1322           88 :     g_variant_dict_lookup (&dict, "Name", "s", &(data->lv_name));
    1323           88 :     g_variant_dict_lookup (&dict, "Uuid", "s", &(data->uuid));
    1324           88 :     g_variant_dict_lookup (&dict, "Attr", "s", &(data->attr));
    1325           88 :     g_variant_dict_lookup (&dict, "SizeBytes", "t", &(data->size));
    1326           88 :     g_variant_dict_lookup (&dict, "DataPercent", "u", &(data->data_percent));
    1327           88 :     g_variant_dict_lookup (&dict, "MetaDataPercent", "u", &(data->metadata_percent));
    1328           88 :     g_variant_dict_lookup (&dict, "CopyPercent", "u", &(data->copy_percent));
    1329              : 
    1330              :     /* XXX: how to deal with LVs with multiple segment types? We are just taking
    1331              :             the first one now. */
    1332           88 :     value = g_variant_dict_lookup_value (&dict, "SegType", (GVariantType*) "as");
    1333           88 :     if (value) {
    1334              :         const gchar *st;
    1335           88 :         g_variant_get_child (value, 0, "&s", &st);
    1336           88 :         if (g_strcmp0 (st, "error") == 0)
    1337            2 :           st = "linear";
    1338           88 :         data->segtype = g_strdup (st);
    1339           88 :         g_variant_unref (value);
    1340              :     }
    1341              : 
    1342           88 :     value = g_variant_dict_lookup_value (&dict, "Roles", (GVariantType*) "as");
    1343           88 :     if (value) {
    1344           88 :         n_children = g_variant_n_children (value);
    1345           88 :         roles = g_new0 (gchar*, n_children + 1);
    1346          248 :         for (i=0; i < n_children; i++)
    1347          160 :             g_variant_get_child (value, i, "&s", roles+i);
    1348           88 :         data->roles = g_strjoinv (",", roles);
    1349           88 :         g_free (roles);
    1350           88 :         g_variant_unref (value);
    1351              :     }
    1352              : 
    1353              :     /* returns an object path for the VG */
    1354           88 :     g_variant_dict_lookup (&dict, "Vg", "o", &path);
    1355           88 :     name = get_object_property (path, VG_INTF, "Name", NULL);
    1356           88 :     g_free (path);
    1357           88 :     g_variant_get (name, "s", &(data->vg_name));
    1358           88 :     g_variant_unref (name);
    1359              : 
    1360           88 :     g_variant_dict_lookup (&dict, "OriginLv", "o", &path);
    1361           88 :     if (g_strcmp0 (path, "/") != 0) {
    1362            6 :         name = get_object_property (path, LV_CMN_INTF, "Name", NULL);
    1363            6 :         g_variant_get (name, "s", &(data->origin));
    1364            6 :         g_variant_unref (name);
    1365              :     }
    1366           88 :     g_free (path);
    1367           88 :     path = NULL;
    1368              : 
    1369           88 :     g_variant_dict_lookup (&dict, "PoolLv", "o", &path);
    1370           88 :     if (g_strcmp0 (path, "/") != 0) {
    1371           12 :         name = get_object_property (path, LV_CMN_INTF, "Name", NULL);
    1372           12 :         g_variant_get (name, "s", &(data->pool_lv));
    1373           12 :         g_variant_unref (name);
    1374              :     }
    1375           88 :     g_free (path);
    1376           88 :     path = NULL;
    1377              : 
    1378           88 :     g_variant_dict_lookup (&dict, "MovePv", "o", &path);
    1379           88 :     if (path && g_strcmp0 (path, "/") != 0) {
    1380            0 :         name = get_object_property (path, PV_INTF, "Name", NULL);
    1381            0 :         g_variant_get (name, "s", &(data->move_pv));
    1382            0 :         g_variant_unref (name);
    1383              :     }
    1384           88 :     g_free (path);
    1385           88 :     path = NULL;
    1386              : 
    1387           88 :     value = g_variant_dict_lookup_value (&dict, "Tags", (GVariantType*) "as");
    1388           88 :     if (value) {
    1389           88 :         n_children = g_variant_n_children (value);
    1390           88 :         tags = g_new0 (gchar*, n_children + 1);
    1391           94 :         for (i=0; i < n_children; i++) {
    1392            6 :             g_variant_get_child (value, i, "s", tags+i);
    1393              :         }
    1394           88 :         data->lv_tags = tags;
    1395           88 :         g_variant_unref (value);
    1396              :     }
    1397              : 
    1398           88 :     g_variant_dict_clear (&dict);
    1399           88 :     g_variant_unref (props);
    1400              : 
    1401           88 :     return data;
    1402              : }
    1403              : 
    1404            9 : static BDLVMVDOPooldata* get_vdo_data_from_props (GVariant *props, GError **error G_GNUC_UNUSED) {
    1405            9 :     BDLVMVDOPooldata *data = g_new0 (BDLVMVDOPooldata, 1);
    1406              :     GVariantDict dict;
    1407            9 :     gchar *value = NULL;
    1408              : 
    1409            9 :     g_variant_dict_init (&dict, props);
    1410              : 
    1411            9 :     g_variant_dict_lookup (&dict, "OperatingMode", "s", &value);
    1412            9 :     if (g_strcmp0 (value, "recovering") == 0)
    1413            0 :         data->operating_mode = BD_LVM_VDO_MODE_RECOVERING;
    1414            9 :     else if (g_strcmp0 (value, "read-only") == 0)
    1415            0 :         data->operating_mode = BD_LVM_VDO_MODE_READ_ONLY;
    1416            9 :     else if (g_strcmp0 (value, "normal") == 0)
    1417            9 :         data->operating_mode = BD_LVM_VDO_MODE_NORMAL;
    1418              :     else {
    1419            0 :         bd_utils_log_format (BD_UTILS_LOG_DEBUG, "Unknown VDO operating mode: %s", value);
    1420            0 :         data->operating_mode = BD_LVM_VDO_MODE_UNKNOWN;
    1421              :     }
    1422            9 :     g_free (value);
    1423            9 :     value = NULL;
    1424              : 
    1425            9 :     g_variant_dict_lookup (&dict, "CompressionState", "s", &value);
    1426            9 :     if (g_strcmp0 (value, "online") == 0)
    1427            7 :         data->compression_state = BD_LVM_VDO_COMPRESSION_ONLINE;
    1428            2 :     else if (g_strcmp0 (value, "offline") == 0)
    1429            2 :         data->compression_state = BD_LVM_VDO_COMPRESSION_OFFLINE;
    1430              :     else {
    1431            0 :         bd_utils_log_format (BD_UTILS_LOG_DEBUG, "Unknown VDO compression state: %s", value);
    1432            0 :         data->compression_state = BD_LVM_VDO_COMPRESSION_UNKNOWN;
    1433              :     }
    1434            9 :     g_free (value);
    1435            9 :     value = NULL;
    1436              : 
    1437            9 :     g_variant_dict_lookup (&dict, "IndexState", "s", &value);
    1438            9 :     if (g_strcmp0 (value, "error") == 0)
    1439            0 :         data->index_state = BD_LVM_VDO_INDEX_ERROR;
    1440            9 :     else if (g_strcmp0 (value, "closed") == 0)
    1441            0 :         data->index_state = BD_LVM_VDO_INDEX_CLOSED;
    1442            9 :     else if (g_strcmp0 (value, "opening") == 0)
    1443            6 :         data->index_state = BD_LVM_VDO_INDEX_OPENING;
    1444            3 :     else if (g_strcmp0 (value, "closing") == 0)
    1445            1 :         data->index_state = BD_LVM_VDO_INDEX_CLOSING;
    1446            2 :     else if (g_strcmp0 (value, "offline") == 0)
    1447            0 :         data->index_state = BD_LVM_VDO_INDEX_OFFLINE;
    1448            2 :     else if (g_strcmp0 (value, "online") == 0)
    1449            2 :         data->index_state = BD_LVM_VDO_INDEX_ONLINE;
    1450              :     else {
    1451            0 :         bd_utils_log_format (BD_UTILS_LOG_DEBUG, "Unknown VDO index state: %s", value);
    1452            0 :         data->index_state = BD_LVM_VDO_INDEX_UNKNOWN;
    1453              :     }
    1454            9 :     g_free (value);
    1455            9 :     value = NULL;
    1456              : 
    1457            9 :     g_variant_dict_lookup (&dict, "WritePolicy", "s", &value);
    1458            9 :     if (g_strcmp0 (value, "auto") == 0)
    1459            8 :         data->write_policy = BD_LVM_VDO_WRITE_POLICY_AUTO;
    1460            1 :     else if (g_strcmp0 (value, "sync") == 0)
    1461            1 :         data->write_policy = BD_LVM_VDO_WRITE_POLICY_SYNC;
    1462            0 :     else if (g_strcmp0 (value, "async") == 0)
    1463            0 :         data->write_policy = BD_LVM_VDO_WRITE_POLICY_ASYNC;
    1464              :     else {
    1465            0 :         bd_utils_log_format (BD_UTILS_LOG_DEBUG, "Unknown VDO write policy: %s", value);
    1466            0 :         data->write_policy = BD_LVM_VDO_WRITE_POLICY_UNKNOWN;
    1467              :     }
    1468            9 :     g_free (value);
    1469            9 :     value = NULL;
    1470              : 
    1471            9 :     g_variant_dict_lookup (&dict, "UsedSize", "t", &(data->used_size));
    1472            9 :     g_variant_dict_lookup (&dict, "SavingPercent", "d", &(data->saving_percent));
    1473              : 
    1474            9 :     g_variant_dict_lookup (&dict, "IndexMemorySize", "t", &(data->index_memory_size));
    1475              : 
    1476            9 :     g_variant_dict_lookup (&dict, "Compression", "s", &value);
    1477            9 :     if (value && g_strcmp0 (value, "enabled") == 0)
    1478            7 :         data->compression = TRUE;
    1479              :     else
    1480            2 :         data->compression = FALSE;
    1481            9 :     g_free (value);
    1482            9 :     value = NULL;
    1483              : 
    1484            9 :     g_variant_dict_lookup (&dict, "Deduplication", "s", &value);
    1485            9 :     if (value && g_strcmp0 (value, "enabled") == 0)
    1486            8 :         data->deduplication = TRUE;
    1487              :     else
    1488            1 :         data->deduplication = FALSE;
    1489            9 :     g_free (value);
    1490            9 :     value = NULL;
    1491              : 
    1492            9 :     g_variant_dict_clear (&dict);
    1493            9 :     g_variant_unref (props);
    1494              : 
    1495            9 :     return data;
    1496              : }
    1497              : 
    1498           60 : static GVariant* create_size_str_param (guint64 size, const gchar *unit) {
    1499           60 :     gchar *str = NULL;
    1500              : 
    1501           60 :     str = g_strdup_printf ("%"G_GUINT64_FORMAT"%s", size, unit ? unit : "");
    1502           60 :     return g_variant_new_take_string (str);
    1503              : }
    1504              : 
    1505              : /**
    1506              :  * bd_lvm_pvcreate:
    1507              :  * @device: the device to make PV from
    1508              :  * @data_alignment: data (first PE) alignment or 0 to use the default
    1509              :  * @metadata_size: size of the area reserved for metadata or 0 to use the default
    1510              :  * @extra: (nullable) (array zero-terminated=1): extra options for the PV creation
    1511              :  *                                                 (just passed to LVM as is)
    1512              :  * @error: (out) (optional): place to store error (if any)
    1513              :  *
    1514              :  * Returns: whether the PV was successfully created or not
    1515              :  *
    1516              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_CREATE
    1517              :  */
    1518           83 : gboolean bd_lvm_pvcreate (const gchar *device, guint64 data_alignment, guint64 metadata_size, const BDExtraArg **extra, GError **error) {
    1519              :     GVariantBuilder builder;
    1520           83 :     GVariant *param = NULL;
    1521           83 :     GVariant *params = NULL;
    1522           83 :     GVariant *extra_params = NULL;
    1523              : 
    1524           83 :     if (data_alignment != 0 || metadata_size != 0) {
    1525            1 :         g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
    1526            1 :         if (data_alignment != 0) {
    1527            1 :             param = create_size_str_param (data_alignment, "b");
    1528            1 :             g_variant_builder_add (&builder, "{sv}", "dataalignment", param);
    1529              :         }
    1530              : 
    1531            1 :         if (metadata_size != 0) {
    1532            1 :             param = create_size_str_param (metadata_size, "b");
    1533            1 :             g_variant_builder_add (&builder, "{sv}", "metadatasize", param);
    1534              :         }
    1535            1 :         extra_params = g_variant_builder_end (&builder);
    1536            1 :         g_variant_builder_clear (&builder);
    1537              :     }
    1538              : 
    1539           83 :     params = g_variant_new ("(s)", device);
    1540              : 
    1541           83 :     return call_lvm_method_sync (MANAGER_OBJ, MANAGER_INTF, "PvCreate", params, extra_params, extra, TRUE, error);
    1542              : }
    1543              : 
    1544              : /**
    1545              :  * bd_lvm_pvresize:
    1546              :  * @device: the device to resize
    1547              :  * @size: the new requested size of the PV or 0 if it should be adjusted to device's size
    1548              :  * @extra: (nullable) (array zero-terminated=1): extra options for the PV resize
    1549              :  *                                                 (just passed to LVM as is)
    1550              :  * @error: (out) (optional): place to store error (if any)
    1551              :  *
    1552              :  * Returns: whether the PV's size was successfully changed or not
    1553              :  *
    1554              :  * If given @size different from 0, sets the PV's size to the given value (see
    1555              :  * pvresize(8)). If given @size 0, adjusts the PV's size to the underlying
    1556              :  * block device's size.
    1557              :  *
    1558              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
    1559              :  */
    1560            4 : gboolean bd_lvm_pvresize (const gchar *device, guint64 size, const BDExtraArg **extra, GError **error) {
    1561            4 :     GVariant *params = NULL;
    1562            4 :     gchar *obj_path = get_object_path (device, error);
    1563            4 :     if (!obj_path)
    1564            2 :         return FALSE;
    1565              : 
    1566            2 :     params = g_variant_new ("(t)", size);
    1567            2 :     return call_lvm_method_sync (obj_path, PV_INTF, "ReSize", params, NULL, extra, TRUE, error);
    1568              : }
    1569              : 
    1570              : /**
    1571              :  * bd_lvm_pvremove:
    1572              :  * @device: the PV device to be removed/destroyed
    1573              :  * @extra: (nullable) (array zero-terminated=1): extra options for the PV removal
    1574              :  *                                                 (just passed to LVM as is)
    1575              :  * @error: (out) (optional): place to store error (if any)
    1576              :  *
    1577              :  * Returns: whether the PV was successfully removed/destroyed or not
    1578              :  *
    1579              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_REMOVE
    1580              :  */
    1581          154 : gboolean bd_lvm_pvremove (const gchar *device, const BDExtraArg **extra, GError **error) {
    1582              :     GVariantBuilder builder;
    1583          154 :     GVariant *params = NULL;
    1584          154 :     GError *l_error = NULL;
    1585          154 :     gboolean ret = FALSE;
    1586              : 
    1587          154 :     if (access (device, F_OK) != 0) {
    1588            2 :         g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_NOEXIST,
    1589              :                      "The device '%s' doesn't exist", device);
    1590            2 :         return FALSE;
    1591              :     }
    1592              : 
    1593              :     /* one has to be really persuasive to remove a PV (the double --force is not
    1594              :        bug, at least not in this code) */
    1595          152 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
    1596          152 :     g_variant_builder_add (&builder, "{sv}", "-ff", g_variant_new ("s", ""));
    1597          152 :     g_variant_builder_add (&builder, "{sv}", "--yes", g_variant_new ("s", ""));
    1598              : 
    1599          152 :     params = g_variant_builder_end (&builder);
    1600          152 :     g_variant_builder_clear (&builder);
    1601          152 :     ret = call_lvm_obj_method_sync (device, PV_INTF, "Remove", NULL, params, extra, TRUE, &l_error);
    1602          152 :     if (!ret && l_error && g_error_matches (l_error, BD_LVM_ERROR, BD_LVM_ERROR_NOEXIST)) {
    1603              :         /* if the object doesn't exist, the given device is not a PV and thus
    1604              :            this function should be a noop */
    1605           71 :         g_clear_error (&l_error);
    1606           71 :         ret = TRUE;
    1607              :     }
    1608              : 
    1609          152 :     if (l_error)
    1610            0 :         g_propagate_error (error, l_error);
    1611          152 :     return ret;
    1612              : }
    1613              : 
    1614              : /**
    1615              :  * bd_lvm_pvmove:
    1616              :  * @src: the PV device to move extents off of
    1617              :  * @dest: (nullable): the PV device to move extents onto or %NULL
    1618              :  * @extra: (nullable) (array zero-terminated=1): extra options for the PV move
    1619              :  *                                                 (just passed to LVM as is)
    1620              :  * @error: (out) (optional): place to store error (if any)
    1621              :  *
    1622              :  * Returns: whether the extents from the @src PV where successfully moved or not
    1623              :  *
    1624              :  * If @dest is %NULL, VG allocation rules are used for the extents from the @src
    1625              :  * PV (see pvmove(8)).
    1626              :  *
    1627              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
    1628              :  */
    1629            1 : gboolean bd_lvm_pvmove (const gchar *src, const gchar *dest, const BDExtraArg **extra, GError **error) {
    1630            1 :     GVariant *prop = NULL;
    1631            1 :     gchar *src_path = NULL;
    1632            1 :     gchar *dest_path = NULL;
    1633            1 :     gchar *vg_obj_path = NULL;
    1634              :     GVariantBuilder builder;
    1635            1 :     GVariantType *type = NULL;
    1636            1 :     GVariant *dest_var = NULL;
    1637            1 :     GVariant *params = NULL;
    1638            1 :     GError *l_error = NULL;
    1639            1 :     gboolean ret = FALSE;
    1640              : 
    1641            1 :     src_path = get_object_path (src, &l_error);
    1642            1 :     if (!src_path || (g_strcmp0 (src_path, "/") == 0)) {
    1643            0 :         if (!l_error)
    1644            0 :             g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_NOEXIST,
    1645              :                          "The source PV '%s' doesn't exist", src);
    1646              :         else
    1647            0 :             g_propagate_error (error, l_error);
    1648            0 :         return FALSE;
    1649              :     }
    1650            1 :     if (dest) {
    1651            1 :         dest_path = get_object_path (dest, &l_error);
    1652            1 :         if (!dest_path || (g_strcmp0 (dest_path, "/") == 0)) {
    1653            0 :             if (!l_error)
    1654            0 :                 g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_NOEXIST,
    1655              :                              "The destination PV '%s' doesn't exist", dest);
    1656              :             else
    1657            0 :                 g_propagate_error (error, l_error);
    1658            0 :             return FALSE;
    1659              :         }
    1660              :     }
    1661            1 :     prop = get_object_property (src_path, PV_INTF, "Vg", error);
    1662            1 :     if (!prop) {
    1663            0 :         g_free (src_path);
    1664            0 :         return FALSE;
    1665              :     }
    1666            1 :     g_variant_get (prop, "o", &vg_obj_path);
    1667              : 
    1668            1 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    1669            1 :     g_variant_builder_add_value (&builder, g_variant_new ("o", src_path));
    1670            1 :     g_variant_builder_add_value (&builder, g_variant_new ("(tt)", (guint64) 0, (guint64) 0));
    1671            1 :     if (dest) {
    1672            1 :         dest_var = g_variant_new ("(ott)", dest_path, (guint64) 0, (guint64) 0);
    1673            1 :         g_variant_builder_add_value (&builder, g_variant_new_array (NULL, &dest_var, 1));
    1674              :     } else {
    1675            0 :         type = g_variant_type_new ("a(ott)");
    1676            0 :         g_variant_builder_add_value (&builder, g_variant_new_array (type, NULL, 0));
    1677            0 :         g_variant_type_free (type);
    1678              :     }
    1679            1 :     params = g_variant_builder_end (&builder);
    1680            1 :     g_variant_builder_clear (&builder);
    1681              : 
    1682            1 :     ret = call_lvm_method_sync (vg_obj_path, VG_INTF, "Move", params, NULL, extra, TRUE, error);
    1683              : 
    1684            1 :     g_free (src_path);
    1685            1 :     g_free (dest_path);
    1686            1 :     g_free (vg_obj_path);
    1687            1 :     return ret;
    1688              : }
    1689              : 
    1690              : /**
    1691              :  * bd_lvm_pvscan:
    1692              :  * @device: (nullable): the device to scan for PVs or %NULL
    1693              :  * @update_cache: whether to update the lvmetad cache or not
    1694              :  * @extra: (nullable) (array zero-terminated=1): extra options for the PV scan
    1695              :  *                                                 (just passed to LVM as is)
    1696              :  * @error: (out) (optional): place to store error (if any)
    1697              :  *
    1698              :  * Returns: whether the system or @device was successfully scanned for PVs or not
    1699              :  *
    1700              :  * The @device argument is used only if @update_cache is %TRUE. Otherwise the
    1701              :  * whole system is scanned for PVs.
    1702              :  *
    1703              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_QUERY
    1704              :  */
    1705            5 : gboolean bd_lvm_pvscan (const gchar *device, gboolean update_cache, const BDExtraArg **extra, GError **error) {
    1706              :     GVariantBuilder builder;
    1707            5 :     GVariantType *type = NULL;
    1708            5 :     GVariant *params = NULL;
    1709            5 :     GVariant *device_var = NULL;
    1710              : 
    1711            5 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    1712              :     /* update the cache and specify the device (if any) */
    1713            5 :     g_variant_builder_add_value (&builder, g_variant_new_boolean (FALSE));
    1714            5 :     g_variant_builder_add_value (&builder, g_variant_new_boolean (update_cache));
    1715            5 :     if (update_cache && device) {
    1716            1 :         device_var = g_variant_new ("s", device);
    1717            1 :         g_variant_builder_add_value (&builder, g_variant_new_array (NULL, &device_var, 1));
    1718              :     } else {
    1719            4 :         type = g_variant_type_new ("as");
    1720            4 :         g_variant_builder_add_value (&builder, g_variant_new_array (type, NULL, 0));
    1721            4 :         g_variant_type_free (type);
    1722              :     }
    1723              :     /* (major, minor)`s, we never specify them */
    1724            5 :     type = g_variant_type_new ("a(ii)");
    1725            5 :     g_variant_builder_add_value (&builder, g_variant_new_array (type, NULL, 0));
    1726            5 :     g_variant_type_free (type);
    1727              : 
    1728            5 :     params = g_variant_builder_end (&builder);
    1729            5 :     g_variant_builder_clear (&builder);
    1730              : 
    1731            5 :     return call_lvm_method_sync (MANAGER_OBJ, MANAGER_INTF, "PvScan", params, NULL, extra, TRUE, error);
    1732              : }
    1733              : 
    1734              : 
    1735            9 : static gboolean _manage_lvm_tags (const gchar *objpath, const gchar *pv_path, const gchar *intf, const gchar **tags, const gchar *func, GError **error) {
    1736            9 :     guint num_tags = g_strv_length ((gchar **) tags);
    1737            9 :     GVariant *params = NULL;
    1738            9 :     GVariant **tags_array = NULL;
    1739              :     GVariantBuilder builder;
    1740            9 :     GVariant *pv_var = NULL;
    1741            9 :     gboolean ret = FALSE;
    1742              : 
    1743            9 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    1744              : 
    1745            9 :     if (pv_path) {
    1746              :         /* PV tags are set from the VG interface so we need to add the PV as an argument here */
    1747            3 :         pv_var = g_variant_new ("o", pv_path);
    1748            3 :         g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_OBJECT_PATH, &pv_var, 1));
    1749              :     }
    1750              : 
    1751            9 :     tags_array = g_new0 (GVariant *, num_tags + 1);
    1752           27 :     for (guint i = 0; i < num_tags; i++)
    1753           18 :         tags_array[i] = g_variant_new_string (tags[i]);
    1754              : 
    1755            9 :     g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_STRING, tags_array, num_tags));
    1756              : 
    1757            9 :     params = g_variant_builder_end (&builder);
    1758            9 :     g_variant_builder_clear (&builder);
    1759              : 
    1760            9 :     ret = call_lvm_method_sync (objpath, intf, func, params, NULL, NULL, TRUE, error);
    1761            9 :     g_free (tags_array);
    1762            9 :     return ret;
    1763              : }
    1764              : 
    1765              : /**
    1766              :  * bd_lvm_add_pv_tags:
    1767              :  * @device: the device to set PV tags for
    1768              :  * @tags: (array zero-terminated=1): list of tags to add
    1769              :  * @error: (out) (optional): place to store error (if any)
    1770              :  *
    1771              :  * Returns: whether the tags were successfully added to @device or not
    1772              :  *
    1773              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_QUERY
    1774              :  */
    1775            3 : gboolean bd_lvm_add_pv_tags (const gchar *device, const gchar **tags, GError **error) {
    1776            3 :     BDLVMPVdata *pvinfo = NULL;
    1777            3 :     g_autofree gchar *vg_path = NULL;
    1778            3 :     g_autofree gchar *pv_path = NULL;
    1779              : 
    1780            3 :     pv_path = get_object_path (device, error);
    1781            3 :     if (!pv_path)
    1782            0 :         return FALSE;
    1783              : 
    1784            3 :     pvinfo = bd_lvm_pvinfo (device, error);
    1785            3 :     if (!pvinfo)
    1786            0 :         return FALSE;
    1787              : 
    1788            3 :     if (!pvinfo->vg_name) {
    1789            1 :         g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
    1790              :                      "Tags can't be added to PVs without a VG");
    1791            1 :         bd_lvm_pvdata_free (pvinfo);
    1792            1 :         return FALSE;
    1793              :     }
    1794              : 
    1795            2 :     vg_path = get_object_path (pvinfo->vg_name, error);
    1796            2 :     bd_lvm_pvdata_free (pvinfo);
    1797            2 :     if (!vg_path)
    1798            0 :         return FALSE;
    1799              : 
    1800            2 :     return _manage_lvm_tags (vg_path, pv_path, VG_INTF, tags, "PvTagsAdd", error);
    1801              : }
    1802              : 
    1803              : /**
    1804              :  * bd_lvm_delete_pv_tags:
    1805              :  * @device: the device to set PV tags for
    1806              :  * @tags: (array zero-terminated=1): list of tags to remove
    1807              :  * @error: (out) (optional): place to store error (if any)
    1808              :  *
    1809              :  * Returns: whether the tags were successfully removed from @device or not
    1810              :  *
    1811              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_QUERY
    1812              :  */
    1813            2 : gboolean bd_lvm_delete_pv_tags (const gchar *device, const gchar **tags, GError **error)  {
    1814            2 :     BDLVMPVdata *pvinfo = NULL;
    1815            2 :     g_autofree gchar *vg_path = NULL;
    1816            2 :     g_autofree gchar *pv_path = NULL;
    1817              : 
    1818            2 :     pv_path = get_object_path (device, error);
    1819            2 :     if (!pv_path)
    1820            0 :         return FALSE;
    1821              : 
    1822            2 :     pvinfo = bd_lvm_pvinfo (device, error);
    1823            2 :     if (!pvinfo)
    1824            0 :         return FALSE;
    1825              : 
    1826            2 :     if (!pvinfo->vg_name) {
    1827            1 :         g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_FAIL,
    1828              :                      "Tags can't be removed from PVs without a VG");
    1829            1 :         bd_lvm_pvdata_free (pvinfo);
    1830            1 :         return FALSE;
    1831              :     }
    1832              : 
    1833            1 :     vg_path = get_object_path (pvinfo->vg_name, error);
    1834            1 :     bd_lvm_pvdata_free (pvinfo);
    1835            1 :     if (!vg_path)
    1836            0 :         return FALSE;
    1837              : 
    1838            1 :     return _manage_lvm_tags (vg_path, pv_path, VG_INTF, tags, "PvTagsDel", error);
    1839              : }
    1840              : /**
    1841              :  * bd_lvm_pvinfo:
    1842              :  * @device: a PV to get information about or %NULL
    1843              :  * @error: (out) (optional): place to store error (if any)
    1844              :  *
    1845              :  * Returns: (transfer full): information about the PV on the given @device or
    1846              :  * %NULL in case of error (the @error) gets populated in those cases)
    1847              :  *
    1848              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_QUERY
    1849              :  */
    1850           14 : BDLVMPVdata* bd_lvm_pvinfo (const gchar *device, GError **error) {
    1851           14 :     GVariant *props = NULL;
    1852           14 :     BDLVMPVdata *ret = NULL;
    1853              : 
    1854           14 :     props = get_pv_properties (device, error);
    1855           14 :     if (!props)
    1856              :         /* the error is already populated */
    1857            0 :         return NULL;
    1858              : 
    1859           14 :     ret = get_pv_data_from_props (props, error);
    1860           14 :     g_variant_unref (props);
    1861              : 
    1862           14 :     return ret;
    1863              : }
    1864              : 
    1865              : /**
    1866              :  * bd_lvm_pvs:
    1867              :  * @error: (out) (optional): place to store error (if any)
    1868              :  *
    1869              :  * Returns: (array zero-terminated=1): information about PVs found in the system
    1870              :  *
    1871              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_QUERY
    1872              :  */
    1873            4 : BDLVMPVdata** bd_lvm_pvs (GError **error) {
    1874            4 :     gchar **objects = NULL;
    1875            4 :     guint64 n_pvs = 0;
    1876            4 :     GVariant *props = NULL;
    1877            4 :     BDLVMPVdata **ret = NULL;
    1878            4 :     guint64 i = 0;
    1879            4 :     GError *l_error = NULL;
    1880              : 
    1881            4 :     objects = get_existing_objects (PV_OBJ_PREFIX, &l_error);
    1882            4 :     if (!objects) {
    1883            0 :         if (!l_error) {
    1884              :             /* no PVs */
    1885            0 :             ret = g_new0 (BDLVMPVdata*, 1);
    1886            0 :             ret[0] = NULL;
    1887            0 :             return ret;
    1888              :         } else {
    1889            0 :             g_propagate_error (error, l_error);
    1890            0 :             return NULL;
    1891              :         }
    1892              :     }
    1893              : 
    1894            4 :     n_pvs = g_strv_length ((gchar **) objects);
    1895              : 
    1896              :     /* now create the return value -- NULL-terminated array of BDLVMPVdata */
    1897            4 :     ret = g_new0 (BDLVMPVdata*, n_pvs + 1);
    1898           10 :     for (i=0; i < n_pvs; i++) {
    1899            6 :         props = get_object_properties (objects[i], PV_INTF, error);
    1900            6 :         if (!props) {
    1901            0 :             g_strfreev (objects);
    1902            0 :             g_free (ret);
    1903            0 :             return NULL;
    1904              :         }
    1905            6 :         ret[i] = get_pv_data_from_props (props, error);
    1906            6 :         g_variant_unref (props);
    1907            6 :         if (!(ret[i])) {
    1908            0 :             g_strfreev (objects);
    1909            0 :             g_free (ret);
    1910            0 :             return NULL;
    1911              :         }
    1912              :     }
    1913            4 :     ret[i] = NULL;
    1914              : 
    1915            4 :     g_strfreev (objects);
    1916            4 :     return ret;
    1917              : }
    1918              : 
    1919              : /**
    1920              :  * bd_lvm_vgcreate:
    1921              :  * @name: name of the newly created VG
    1922              :  * @pv_list: (array zero-terminated=1): list of PVs the newly created VG should use
    1923              :  * @pe_size: PE size or 0 if the default value should be used
    1924              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VG creation
    1925              :  *                                                 (just passed to LVM as is)
    1926              :  * @error: (out) (optional): place to store error (if any)
    1927              :  *
    1928              :  * Returns: whether the VG @name was successfully created or not
    1929              :  *
    1930              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_CREATE
    1931              :  */
    1932           47 : gboolean bd_lvm_vgcreate (const gchar *name, const gchar **pv_list, guint64 pe_size, const BDExtraArg **extra, GError **error) {
    1933              :     GVariantBuilder builder;
    1934           47 :     gchar *path = NULL;
    1935           47 :     const gchar **pv = NULL;
    1936           47 :     GVariant *pvs = NULL;
    1937           47 :     GVariant *params = NULL;
    1938           47 :     GVariant *extra_params = NULL;
    1939              : 
    1940              :     /* build the array of PVs (object paths) */
    1941           47 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_OBJECT_PATH_ARRAY);
    1942          123 :     for (pv=pv_list; *pv; pv++) {
    1943           77 :         path = get_object_path (*pv, error);
    1944           77 :         if (!path) {
    1945            1 :             g_variant_builder_clear (&builder);
    1946            1 :             return FALSE;
    1947              :         }
    1948           76 :         g_variant_builder_add_value (&builder, g_variant_new ("o", path));
    1949              :     }
    1950           46 :     pvs = g_variant_builder_end (&builder);
    1951           46 :     g_variant_builder_clear (&builder);
    1952              : 
    1953              :     /* build the params tuple */
    1954           46 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    1955           46 :     g_variant_builder_add_value (&builder, g_variant_new ("s", name));
    1956           46 :     g_variant_builder_add_value (&builder, pvs);
    1957           46 :     params = g_variant_builder_end (&builder);
    1958           46 :     g_variant_builder_clear (&builder);
    1959              : 
    1960              :     /* pe_size needs to go to extra_params params */
    1961           46 :     pe_size = RESOLVE_PE_SIZE (pe_size);
    1962           46 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
    1963           46 :     g_variant_builder_add_value (&builder, g_variant_new ("{sv}", "--physicalextentsize", create_size_str_param (pe_size, "b")));
    1964           46 :     extra_params = g_variant_builder_end (&builder);
    1965           46 :     g_variant_builder_clear (&builder);
    1966              : 
    1967           46 :     return call_lvm_method_sync (MANAGER_OBJ, MANAGER_INTF, "VgCreate", params, extra_params, extra, TRUE, error);
    1968              : }
    1969              : 
    1970              : /**
    1971              :  * bd_lvm_vgremove:
    1972              :  * @vg_name: name of the to be removed VG
    1973              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VG removal
    1974              :  *                                                 (just passed to LVM as is)
    1975              :  * @error: (out) (optional): place to store error (if any)
    1976              :  *
    1977              :  * Returns: whether the VG was successfully removed or not
    1978              :  *
    1979              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_REMOVE
    1980              :  */
    1981           50 : gboolean bd_lvm_vgremove (const gchar *vg_name, const BDExtraArg **extra, GError **error) {
    1982           50 :     return call_lvm_obj_method_sync (vg_name, VG_INTF, "Remove", NULL, NULL, extra, TRUE, error);
    1983              : }
    1984              : 
    1985              : /**
    1986              :  * bd_lvm_vgrename:
    1987              :  * @old_vg_name: old name of the VG to rename
    1988              :  * @new_vg_name: new name for the @old_vg_name VG
    1989              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VG rename
    1990              :  *                                                 (just passed to LVM as is)
    1991              :  * @error: (out) (optional): place to store error (if any)
    1992              :  *
    1993              :  * Returns: whether the VG was successfully renamed or not
    1994              :  *
    1995              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
    1996              :  */
    1997            3 : gboolean bd_lvm_vgrename (const gchar *old_vg_name, const gchar *new_vg_name, const BDExtraArg **extra, GError **error) {
    1998            3 :     GVariant *params = g_variant_new ("(s)", new_vg_name);
    1999            3 :     return call_lvm_obj_method_sync (old_vg_name, VG_INTF, "Rename", params, NULL, extra, TRUE, error);
    2000              : }
    2001              : 
    2002              : /**
    2003              :  * bd_lvm_vgactivate:
    2004              :  * @vg_name: name of the to be activated VG
    2005              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VG activation
    2006              :  *                                                 (just passed to LVM as is)
    2007              :  * @error: (out) (optional): place to store error (if any)
    2008              :  *
    2009              :  * Returns: whether the VG was successfully activated or not
    2010              :  *
    2011              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
    2012              :  */
    2013            3 : gboolean bd_lvm_vgactivate (const gchar *vg_name, const BDExtraArg **extra, GError **error) {
    2014            3 :     GVariant *params = g_variant_new ("(t)", (guint64) 0);
    2015            3 :     return call_lvm_obj_method_sync (vg_name, VG_INTF, "Activate", params, NULL, extra, TRUE, error);
    2016              : }
    2017              : 
    2018              : /**
    2019              :  * bd_lvm_vgdeactivate:
    2020              :  * @vg_name: name of the to be deactivated VG
    2021              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VG deactivation
    2022              :  *                                                 (just passed to LVM as is)
    2023              :  * @error: (out) (optional): place to store error (if any)
    2024              :  *
    2025              :  * Returns: whether the VG was successfully deactivated or not
    2026              :  *
    2027              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
    2028              :  */
    2029            3 : gboolean bd_lvm_vgdeactivate (const gchar *vg_name, const BDExtraArg **extra, GError **error) {
    2030            3 :     GVariant *params = g_variant_new ("(t)", (guint64) 0);
    2031            3 :     return call_lvm_obj_method_sync (vg_name, VG_INTF, "Deactivate", params, NULL, extra, TRUE, error);
    2032              : }
    2033              : 
    2034              : /**
    2035              :  * bd_lvm_vgextend:
    2036              :  * @vg_name: name of the to be extended VG
    2037              :  * @device: PV device to extend the @vg_name VG with
    2038              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VG extension
    2039              :  *                                                 (just passed to LVM as is)
    2040              :  * @error: (out) (optional): place to store error (if any)
    2041              :  *
    2042              :  * Returns: whether the VG @vg_name was successfully extended with the given @device or not.
    2043              :  *
    2044              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
    2045              :  */
    2046            4 : gboolean bd_lvm_vgextend (const gchar *vg_name, const gchar *device, const BDExtraArg **extra, GError **error) {
    2047            4 :     g_autofree gchar *pv = NULL;
    2048            4 :     GVariant *pv_var = NULL;
    2049            4 :     GVariant *pvs = NULL;
    2050            4 :     GVariant *params = NULL;
    2051              : 
    2052            4 :     pv = get_object_path (device, error);
    2053            4 :     if (!pv)
    2054            1 :         return FALSE;
    2055              : 
    2056            3 :     pv_var = g_variant_new ("o", pv);
    2057            3 :     pvs = g_variant_new_array (NULL, &pv_var, 1);
    2058            3 :     params = g_variant_new_tuple (&pvs, 1);
    2059            3 :     return call_lvm_obj_method_sync (vg_name, VG_INTF, "Extend", params, NULL, extra, TRUE, error);
    2060              : }
    2061              : 
    2062              : /**
    2063              :  * bd_lvm_vgreduce:
    2064              :  * @vg_name: name of the to be reduced VG
    2065              :  * @device: (nullable): PV device the @vg_name VG should be reduced of or %NULL
    2066              :  *                        if the VG should be reduced of the missing PVs
    2067              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VG reduction
    2068              :  *                                                 (just passed to LVM as is)
    2069              :  * @error: (out) (optional): place to store error (if any)
    2070              :  *
    2071              :  * Returns: whether the VG @vg_name was successfully reduced of the given @device or not
    2072              :  *
    2073              :  * Note: This function does not move extents off of the PV before removing
    2074              :  *       it from the VG. You must do that first by calling #bd_lvm_pvmove.
    2075              :  *
    2076              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
    2077              :  */
    2078            4 : gboolean bd_lvm_vgreduce (const gchar *vg_name, const gchar *device, const BDExtraArg **extra, GError **error) {
    2079            4 :     g_autofree gchar *pv = NULL;
    2080              :     GVariantBuilder builder;
    2081            4 :     GVariantType *type = NULL;
    2082            4 :     GVariant *pv_var = NULL;
    2083            4 :     GVariant *params = NULL;
    2084            4 :     GVariant *extra_params = NULL;
    2085              : 
    2086            4 :     if (device) {
    2087            2 :         pv = get_object_path (device, error);
    2088            2 :         if (!pv)
    2089            0 :             return FALSE;
    2090              :     }
    2091              : 
    2092            4 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    2093            4 :     if (device) {
    2094              :         /* do not remove missing */
    2095            2 :         pv_var = g_variant_new ("o", pv);
    2096            2 :         g_variant_builder_add_value (&builder, g_variant_new_boolean (FALSE));
    2097            2 :         g_variant_builder_add_value (&builder, g_variant_new_array (NULL, &pv_var, 1));
    2098            2 :         params = g_variant_builder_end (&builder);
    2099            2 :         g_variant_builder_clear (&builder);
    2100              :     } else {
    2101              :         /* remove missing */
    2102            2 :         g_variant_builder_add_value (&builder, g_variant_new_boolean (TRUE));
    2103            2 :         type = g_variant_type_new ("ao");
    2104            2 :         g_variant_builder_add_value (&builder, g_variant_new_array (type, NULL, 0));
    2105            2 :         g_variant_type_free (type);
    2106            2 :         params = g_variant_builder_end (&builder);
    2107            2 :         g_variant_builder_clear (&builder);
    2108              : 
    2109            2 :         g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
    2110            2 :         g_variant_builder_add_value (&builder, g_variant_new ("{sv}", "--force", g_variant_new ("s", "")));
    2111            2 :         extra_params = g_variant_builder_end (&builder);
    2112            2 :         g_variant_builder_clear (&builder);
    2113              :     }
    2114              : 
    2115            4 :     return call_lvm_obj_method_sync (vg_name, VG_INTF, "Reduce", params, extra_params, extra, TRUE, error);
    2116              : }
    2117              : 
    2118              : /**
    2119              :  * bd_lvm_add_vg_tags:
    2120              :  * @vg_name: the VG to set tags on
    2121              :  * @tags: (array zero-terminated=1): list of tags to add
    2122              :  * @error: (out) (optional): place to store error (if any)
    2123              :  *
    2124              :  * Returns: whether the tags were successfully added to @vg_name or not
    2125              :  *
    2126              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_QUERY
    2127              :  */
    2128            2 : gboolean bd_lvm_add_vg_tags (const gchar *vg_name, const gchar **tags, GError **error) {
    2129            4 :     g_autofree gchar *obj_path = get_object_path (vg_name, error);
    2130            2 :     if (!obj_path)
    2131            0 :         return FALSE;
    2132              : 
    2133            2 :     return _manage_lvm_tags (obj_path, NULL, VG_INTF, tags, "TagsAdd", error);
    2134              : }
    2135              : 
    2136              : /**
    2137              :  * bd_lvm_delete_vg_tags:
    2138              :  * @vg_name: the VG to set tags on
    2139              :  * @tags: (array zero-terminated=1): list of tags to remove
    2140              :  * @error: (out) (optional): place to store error (if any)
    2141              :  *
    2142              :  * Returns: whether the tags were successfully removed from @vg_name or not
    2143              :  *
    2144              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_QUERY
    2145              :  */
    2146            1 : gboolean bd_lvm_delete_vg_tags (const gchar *vg_name, const gchar **tags, GError **error) {
    2147            2 :     g_autofree gchar *obj_path = get_object_path (vg_name, error);
    2148            1 :     if (!obj_path)
    2149            0 :         return FALSE;
    2150              : 
    2151            1 :     return _manage_lvm_tags (obj_path, NULL, VG_INTF, tags, "TagsDel", error);
    2152              : }
    2153              : 
    2154            0 : static gboolean _vglock_start_stop (const gchar *vg_name, gboolean start, const BDExtraArg **extra, GError **error) {
    2155              :     GVariantBuilder builder;
    2156            0 :     GVariant *params = NULL;
    2157              : 
    2158            0 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
    2159            0 :     if (start)
    2160            0 :         g_variant_builder_add (&builder, "{sv}", "--lockstart", g_variant_new ("s", ""));
    2161              :     else
    2162            0 :         g_variant_builder_add (&builder, "{sv}", "--lockstop", g_variant_new ("s", ""));
    2163            0 :     params = g_variant_builder_end (&builder);
    2164            0 :     g_variant_builder_clear (&builder);
    2165              : 
    2166            0 :     return call_lvm_obj_method_sync (vg_name, VG_INTF, "Change", NULL, params, extra, TRUE, error);
    2167              : }
    2168              : 
    2169              : /**
    2170              :  * bd_lvm_vglock_start:
    2171              :  * @vg_name: a shared VG to start the lockspace in lvmlockd
    2172              :  * @extra: (nullable) (array zero-terminated=1): extra options for the vgchange command
    2173              :  *                                               (just passed to LVM as is)
    2174              :  * @error: (out) (optional): place to store error (if any)
    2175              :  *
    2176              :  * Returns: whether the lock was successfully started for @vg_name or not
    2177              :  *
    2178              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
    2179              :  */
    2180            0 : gboolean bd_lvm_vglock_start (const gchar *vg_name, const BDExtraArg **extra, GError **error) {
    2181            0 :     return _vglock_start_stop (vg_name, TRUE, extra, error);
    2182              : }
    2183              : 
    2184              : /**
    2185              :  * bd_lvm_vglock_stop:
    2186              :  * @vg_name: a shared VG to stop the lockspace in lvmlockd
    2187              :  * @extra: (nullable) (array zero-terminated=1): extra options for the vgchange command
    2188              :  *                                               (just passed to LVM as is)
    2189              :  * @error: (out) (optional): place to store error (if any)
    2190              :  *
    2191              :  * Returns: whether the lock was successfully stopped for @vg_name or not
    2192              :  *
    2193              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
    2194              :  */
    2195            0 : gboolean bd_lvm_vglock_stop (const gchar *vg_name, const BDExtraArg **extra, GError **error) {
    2196            0 :     return _vglock_start_stop (vg_name, FALSE, extra, error);
    2197              : }
    2198              : 
    2199              : /**
    2200              :  * bd_lvm_vginfo:
    2201              :  * @vg_name: a VG to get information about
    2202              :  * @error: (out) (optional): place to store error (if any)
    2203              :  *
    2204              :  * Returns: (transfer full): information about the @vg_name VG or %NULL in case
    2205              :  * of error (the @error) gets populated in those cases)
    2206              :  *
    2207              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_QUERY
    2208              :  */
    2209            6 : BDLVMVGdata* bd_lvm_vginfo (const gchar *vg_name, GError **error) {
    2210            6 :     GVariant *props = NULL;
    2211            6 :     BDLVMVGdata *ret = NULL;
    2212              : 
    2213            6 :     props = get_vg_properties (vg_name, error);
    2214            6 :     if (!props)
    2215              :         /* the error is already populated */
    2216            0 :         return NULL;
    2217              : 
    2218            6 :     ret = get_vg_data_from_props (props, error);
    2219            6 :     g_variant_unref (props);
    2220              : 
    2221            6 :     return ret;
    2222              : }
    2223              : 
    2224              : /**
    2225              :  * bd_lvm_vgs:
    2226              :  * @error: (out) (optional): place to store error (if any)
    2227              :  *
    2228              :  * Returns: (array zero-terminated=1): information about VGs found in the system
    2229              :  *
    2230              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_QUERY
    2231              :  */
    2232            2 : BDLVMVGdata** bd_lvm_vgs (GError **error) {
    2233            2 :     gchar **objects = NULL;
    2234            2 :     guint64 n_vgs = 0;
    2235            2 :     GVariant *props = NULL;
    2236            2 :     BDLVMVGdata **ret = NULL;
    2237            2 :     guint64 i = 0;
    2238            2 :     GError *l_error = NULL;
    2239              : 
    2240            2 :     objects = get_existing_objects (VG_OBJ_PREFIX, &l_error);
    2241            2 :     if (!objects) {
    2242            0 :         if (!l_error) {
    2243              :             /* no VGs */
    2244            0 :             ret = g_new0 (BDLVMVGdata*, 1);
    2245            0 :             ret[0] = NULL;
    2246            0 :             return ret;
    2247              :         } else {
    2248            0 :             g_propagate_error (error, l_error);
    2249            0 :             return NULL;
    2250              :         }
    2251              :     }
    2252              : 
    2253            2 :     n_vgs = g_strv_length ((gchar **) objects);
    2254              : 
    2255              :     /* now create the return value -- NULL-terminated array of BDLVMVGdata */
    2256            2 :     ret = g_new0 (BDLVMVGdata*, n_vgs + 1);
    2257            3 :     for (i=0; i < n_vgs; i++) {
    2258            1 :         props = get_object_properties (objects[i], VG_INTF, error);
    2259            1 :         if (!props) {
    2260            0 :             g_strfreev (objects);
    2261            0 :             g_free (ret);
    2262            0 :             return NULL;
    2263              :         }
    2264            1 :         ret[i] = get_vg_data_from_props (props, error);
    2265            1 :         g_variant_unref (props);
    2266            1 :         if (!(ret[i])) {
    2267            0 :             g_strfreev (objects);
    2268            0 :             g_free (ret);
    2269            0 :             return NULL;
    2270              :         }
    2271              :     }
    2272            2 :     ret[i] = NULL;
    2273              : 
    2274            2 :     g_strfreev (objects);
    2275            2 :     return ret;
    2276              : }
    2277              : 
    2278              : /**
    2279              :  * bd_lvm_lvorigin:
    2280              :  * @vg_name: name of the VG containing the queried LV
    2281              :  * @lv_name: name of the queried LV
    2282              :  * @error: (out) (optional): place to store error (if any)
    2283              :  *
    2284              :  * Returns: (transfer full): the origin volume for the @vg_name/@lv_name LV or
    2285              :  * %NULL if failed to determine (@error) is set in those cases)
    2286              :  *
    2287              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_QUERY
    2288              :  */
    2289            1 : gchar* bd_lvm_lvorigin (const gchar *vg_name, const gchar *lv_name, GError **error) {
    2290            1 :     GVariant *prop = NULL;
    2291            1 :     gchar *obj_path = NULL;
    2292            1 :     gchar *ret = NULL;
    2293              : 
    2294            1 :     prop = get_lv_property (vg_name, lv_name, "OriginLv", error);
    2295            1 :     if (!prop)
    2296            0 :         return NULL;
    2297            1 :     g_variant_get (prop, "o", &obj_path);
    2298            1 :     g_variant_unref (prop);
    2299              : 
    2300            1 :     if (g_strcmp0 (obj_path, "/") == 0) {
    2301              :         /* no origin LV */
    2302            0 :         g_free (obj_path);
    2303            0 :         return NULL;
    2304              :     }
    2305            1 :     prop = get_object_property (obj_path, LV_CMN_INTF, "Name", error);
    2306            1 :     if (!prop) {
    2307            0 :         g_free (obj_path);
    2308            0 :         return NULL;
    2309              :     }
    2310              : 
    2311            1 :     g_variant_get (prop, "s", &ret);
    2312            1 :     g_variant_unref (prop);
    2313              : 
    2314            1 :     return ret;
    2315              : }
    2316              : 
    2317              : /**
    2318              :  * bd_lvm_lvcreate:
    2319              :  * @vg_name: name of the VG to create a new LV in
    2320              :  * @lv_name: name of the to-be-created LV
    2321              :  * @size: requested size of the new LV
    2322              :  * @type: (nullable): type of the new LV ("striped", "raid1",..., see lvcreate (8))
    2323              :  * @pv_list: (nullable) (array zero-terminated=1): list of PVs the newly created LV should use or %NULL
    2324              :  * if not specified
    2325              :  * @extra: (nullable) (array zero-terminated=1): extra options for the LV creation
    2326              :  *                                                 (just passed to LVM as is)
    2327              :  * @error: (out) (optional): place to store error (if any)
    2328              :  *
    2329              :  * Returns: whether the given @vg_name/@lv_name LV was successfully created or not
    2330              :  *
    2331              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_CREATE
    2332              :  */
    2333           47 : gboolean bd_lvm_lvcreate (const gchar *vg_name, const gchar *lv_name, guint64 size, const gchar *type, const gchar **pv_list, const BDExtraArg **extra, GError **error) {
    2334              :     GVariantBuilder builder;
    2335           47 :     gchar *path = NULL;
    2336           47 :     const gchar **pv = NULL;
    2337           47 :     GVariant *pvs = NULL;
    2338           47 :     GVariantType *var_type = NULL;
    2339           47 :     GVariant *params = NULL;
    2340           47 :     GVariant *extra_params = NULL;
    2341              : 
    2342              :     /* build the array of PVs (object paths) */
    2343           47 :     if (pv_list && *pv_list) {
    2344           44 :         g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
    2345           91 :         for (pv=pv_list; *pv; pv++) {
    2346           48 :             path = get_object_path (*pv, error);
    2347           48 :             if (!path) {
    2348            1 :                 g_variant_builder_clear (&builder);
    2349            1 :                 return FALSE;
    2350              :             }
    2351           47 :             g_variant_builder_add_value (&builder, g_variant_new ("(ott)", path, (guint64) 0, (guint64) 0));
    2352              :         }
    2353           43 :         pvs = g_variant_builder_end (&builder);
    2354           43 :         g_variant_builder_clear (&builder);
    2355              :     } else {
    2356            3 :         var_type = g_variant_type_new ("a(ott)");
    2357            3 :         pvs = g_variant_new_array (var_type, NULL, 0);
    2358            3 :         g_variant_type_free (var_type);
    2359              :     }
    2360              : 
    2361              :     /* build the params tuple */
    2362           46 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    2363           46 :     g_variant_builder_add_value (&builder, g_variant_new ("s", lv_name));
    2364           46 :     g_variant_builder_add_value (&builder, g_variant_new ("t", size));
    2365           46 :     g_variant_builder_add_value (&builder, pvs);
    2366           46 :     params = g_variant_builder_end (&builder);
    2367           46 :     g_variant_builder_clear (&builder);
    2368              : 
    2369           46 :     if (type) {
    2370              :         /* and now the extra_params params */
    2371            3 :         g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
    2372            3 :         if (pv_list && g_strcmp0 (type, "striped") == 0)
    2373            1 :             g_variant_builder_add_value (&builder, g_variant_new ("{sv}", "stripes", g_variant_new ("i", g_strv_length ((gchar **) pv_list))));
    2374              :         else
    2375            2 :             g_variant_builder_add_value (&builder, g_variant_new ("{sv}", "type", g_variant_new ("s", type)));
    2376            3 :         extra_params = g_variant_builder_end (&builder);
    2377            3 :         g_variant_builder_clear (&builder);
    2378              :     }
    2379              : 
    2380           46 :     return call_lvm_obj_method_sync (vg_name, VG_INTF, "LvCreate", params, extra_params, extra, TRUE, error);
    2381              : }
    2382              : 
    2383              : /**
    2384              :  * bd_lvm_lvremove:
    2385              :  * @vg_name: name of the VG containing the to-be-removed LV
    2386              :  * @lv_name: name of the to-be-removed LV
    2387              :  * @force: whether to force removal or not
    2388              :  * @extra: (nullable) (array zero-terminated=1): extra options for the LV removal
    2389              :  *                                                 (just passed to LVM as is)
    2390              :  * @error: (out) (optional): place to store error (if any)
    2391              :  *
    2392              :  * Returns: whether the @vg_name/@lv_name LV was successfully removed or not
    2393              :  *
    2394              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_REMOVE
    2395              :  */
    2396           55 : gboolean bd_lvm_lvremove (const gchar *vg_name, const gchar *lv_name, gboolean force, const BDExtraArg **extra, GError **error) {
    2397              :     GVariantBuilder builder;
    2398           55 :     GVariant *extra_params = NULL;
    2399              : 
    2400           55 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
    2401              :     /* '--yes' is needed if DISCARD is enabled */
    2402           55 :     g_variant_builder_add (&builder, "{sv}", "--yes", g_variant_new ("s", ""));
    2403           55 :     if (force) {
    2404           53 :         g_variant_builder_add (&builder, "{sv}", "--force", g_variant_new ("s", ""));
    2405              :     }
    2406           55 :     extra_params = g_variant_builder_end (&builder);
    2407           55 :     g_variant_builder_clear (&builder);
    2408              : 
    2409           55 :     return call_lv_method_sync (vg_name, lv_name, "Remove", NULL, extra_params, extra, TRUE, error);
    2410              : }
    2411              : 
    2412              : /**
    2413              :  * bd_lvm_lvrename:
    2414              :  * @vg_name: name of the VG containing the to-be-renamed LV
    2415              :  * @lv_name: name of the to-be-renamed LV
    2416              :  * @new_name: new name for the @vg_name/@lv_name LV
    2417              :  * @extra: (nullable) (array zero-terminated=1): extra options for the LV rename
    2418              :  *                                                 (just passed to LVM as is)
    2419              :  * @error: (out) (optional): place to store error (if any)
    2420              :  *
    2421              :  * Returns: whether the @vg_name/@lv_name LV was successfully renamed to
    2422              :  * @vg_name/@new_name or not
    2423              :  *
    2424              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
    2425              :  */
    2426            6 : gboolean bd_lvm_lvrename (const gchar *vg_name, const gchar *lv_name, const gchar *new_name, const BDExtraArg **extra, GError **error) {
    2427            6 :     GVariant *params = NULL;
    2428              : 
    2429            6 :     params = g_variant_new ("(s)", new_name);
    2430            6 :     return call_lv_method_sync (vg_name, lv_name, "Rename", params, NULL, extra, TRUE, error);
    2431              : }
    2432              : 
    2433              : /**
    2434              :  * bd_lvm_lvresize:
    2435              :  * @vg_name: name of the VG containing the to-be-resized LV
    2436              :  * @lv_name: name of the to-be-resized LV
    2437              :  * @size: the requested new size of the LV
    2438              :  * @extra: (nullable) (array zero-terminated=1): extra options for the LV resize
    2439              :  *                                                 (just passed to LVM as is)
    2440              :  * @error: (out) (optional): place to store error (if any)
    2441              :  *
    2442              :  * Returns: whether the @vg_name/@lv_name LV was successfully resized or not
    2443              :  *
    2444              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
    2445              :  */
    2446           10 : gboolean bd_lvm_lvresize (const gchar *vg_name, const gchar *lv_name, guint64 size, const BDExtraArg **extra, GError **error) {
    2447              :     GVariantBuilder builder;
    2448           10 :     GVariantType *type = NULL;
    2449           10 :     GVariant *params = NULL;
    2450           10 :     GVariant *extra_params = NULL;
    2451           10 :     gboolean success = FALSE;
    2452              : 
    2453           10 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    2454           10 :     g_variant_builder_add_value (&builder, g_variant_new ("t", size));
    2455           10 :     type = g_variant_type_new ("a(ott)");
    2456           10 :     g_variant_builder_add_value (&builder, g_variant_new_array (type, NULL, 0));
    2457           10 :     g_variant_type_free (type);
    2458           10 :     params = g_variant_builder_end (&builder);
    2459           10 :     g_variant_builder_clear (&builder);
    2460              : 
    2461              :     /* Starting with 2.03.19 we need to add an extra option to avoid
    2462              :        any filesystem related checks by lvresize.
    2463              :     */
    2464           10 :     success = bd_utils_check_util_version (deps[DEPS_LVM].name, LVM_VERSION_FSRESIZE,
    2465           10 :                                            deps[DEPS_LVM].ver_arg, deps[DEPS_LVM].ver_regexp, NULL);
    2466           10 :     if (success) {
    2467           10 :       g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
    2468           10 :       g_variant_builder_add (&builder, "{sv}", "--fs", g_variant_new ("s", "ignore"));
    2469           10 :       extra_params = g_variant_builder_end (&builder);
    2470           10 :       g_variant_builder_clear (&builder);
    2471              :     }
    2472              : 
    2473           10 :     return call_lv_method_sync (vg_name, lv_name, "Resize", params, extra_params, extra, TRUE, error);
    2474              : }
    2475              : 
    2476              : /**
    2477              :  * bd_lvm_lvrepair:
    2478              :  * @vg_name: name of the VG containing the to-be-repaired LV
    2479              :  * @lv_name: name of the to-be-repaired LV
    2480              :  * @pv_list: (array zero-terminated=1): list of PVs to be used for the repair
    2481              :  * @extra: (nullable) (array zero-terminated=1): extra options for the LV repair
    2482              :  *                                                 (just passed to LVM as is)
    2483              :  * @error: (out) (optional): place to store error (if any)
    2484              :  *
    2485              :  * Returns: whether the @vg_name/@lv_name LV was successfully repaired or not
    2486              :  *
    2487              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
    2488              :  */
    2489            1 : gboolean bd_lvm_lvrepair (const gchar *vg_name, const gchar *lv_name, const gchar **pv_list,
    2490              :                           const BDExtraArg **extra, GError **error) {
    2491              :     GVariantBuilder builder;
    2492            1 :     GVariant *params = NULL;
    2493            1 :     gchar *path = NULL;
    2494            1 :     const gchar **pv = NULL;
    2495            1 :     GVariant *pvs = NULL;
    2496              : 
    2497              :     /* build the array of PVs (object paths) */
    2498            1 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_OBJECT_PATH_ARRAY);
    2499            2 :     for (pv=pv_list; *pv; pv++) {
    2500            1 :         path = get_object_path (*pv, error);
    2501            1 :         if (!path) {
    2502            0 :             g_variant_builder_clear (&builder);
    2503            0 :             return FALSE;
    2504              :         }
    2505            1 :         g_variant_builder_add_value (&builder, g_variant_new ("o", path));
    2506              :     }
    2507            1 :     pvs = g_variant_builder_end (&builder);
    2508            1 :     g_variant_builder_clear (&builder);
    2509              : 
    2510            1 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    2511            1 :     g_variant_builder_add_value (&builder, pvs);
    2512            1 :     params = g_variant_builder_end (&builder);
    2513            1 :     g_variant_builder_clear (&builder);
    2514              : 
    2515            1 :     return call_lv_method_sync (vg_name, lv_name, "RepairRaidLv", params, NULL, extra, TRUE, error);
    2516              : 
    2517              :   return FALSE;
    2518              : }
    2519              : 
    2520              : /**
    2521              :  * bd_lvm_lvactivate:
    2522              :  * @vg_name: name of the VG containing the to-be-activated LV
    2523              :  * @lv_name: name of the to-be-activated LV
    2524              :  * @ignore_skip: whether to ignore the skip flag or not
    2525              :  * @shared: whether to activate the LV in shared mode (used for shared LVM setups with lvmlockd,
    2526              :  *          use %FALSE if not sure)
    2527              :  * @extra: (nullable) (array zero-terminated=1): extra options for the LV activation
    2528              :  *                                                 (just passed to LVM as is)
    2529              :  * @error: (out) (optional): place to store error (if any)
    2530              :  *
    2531              :  * Returns: whether the @vg_name/@lv_name LV was successfully activated or not
    2532              :  *
    2533              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
    2534              :  */
    2535            6 : gboolean bd_lvm_lvactivate (const gchar *vg_name, const gchar *lv_name, gboolean ignore_skip, gboolean shared, const BDExtraArg **extra, GError **error) {
    2536            6 :     GVariant *params = NULL;
    2537              :     GVariantBuilder builder;
    2538            6 :     GVariant *extra_params = NULL;
    2539              : 
    2540            6 :     if (shared)
    2541            1 :         params = g_variant_new ("(t)", (guint64) 1 << 6);
    2542              :     else
    2543            5 :         params = g_variant_new ("(t)", (guint64) 0);
    2544              : 
    2545            6 :     if (ignore_skip) {
    2546            6 :         g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
    2547            6 :         g_variant_builder_add (&builder, "{sv}", "-K", g_variant_new ("s", ""));
    2548            6 :         extra_params = g_variant_builder_end (&builder);
    2549            6 :         g_variant_builder_clear (&builder);
    2550              :     }
    2551              : 
    2552            6 :     return call_lv_method_sync (vg_name, lv_name, "Activate", params, extra_params, extra, TRUE, error);
    2553              : }
    2554              : 
    2555              : /**
    2556              :  * bd_lvm_lvdeactivate:
    2557              :  * @vg_name: name of the VG containing the to-be-deactivated LV
    2558              :  * @lv_name: name of the to-be-deactivated LV
    2559              :  * @extra: (nullable) (array zero-terminated=1): extra options for the LV deactivation
    2560              :  *                                                 (just passed to LVM as is)
    2561              :  * @error: (out) (optional): place to store error (if any)
    2562              :  *
    2563              :  * Returns: whether the @vg_name/@lv_name LV was successfully deactivated or not
    2564              :  *
    2565              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY
    2566              :  */
    2567           13 : gboolean bd_lvm_lvdeactivate (const gchar *vg_name, const gchar *lv_name, const BDExtraArg **extra, GError **error) {
    2568           13 :     GVariant *params = g_variant_new ("(t)", (guint64) 0);
    2569           13 :     return call_lv_method_sync (vg_name, lv_name, "Deactivate", params, NULL, extra, TRUE, error);
    2570              : }
    2571              : 
    2572              : /**
    2573              :  * bd_lvm_lvsnapshotcreate:
    2574              :  * @vg_name: name of the VG containing the LV a new snapshot should be created of
    2575              :  * @origin_name: name of the LV a new snapshot should be created of
    2576              :  * @snapshot_name: name of the to-be-created snapshot
    2577              :  * @size: requested size for the snapshot
    2578              :  * @extra: (nullable) (array zero-terminated=1): extra options for the LV snapshot creation
    2579              :  *                                                 (just passed to LVM as is)
    2580              :  * @error: (out) (optional): place to store error (if any)
    2581              :  *
    2582              :  * Returns: whether the @snapshot_name snapshot of the @vg_name/@origin_name LV
    2583              :  * was successfully created or not.
    2584              :  *
    2585              :  * Tech category: %BD_LVM_TECH_BASIC_SNAP-%BD_LVM_TECH_MODE_CREATE
    2586              :  */
    2587            1 : gboolean bd_lvm_lvsnapshotcreate (const gchar *vg_name, const gchar *origin_name, const gchar *snapshot_name, guint64 size, const BDExtraArg **extra, GError **error) {
    2588              :     GVariantBuilder builder;
    2589            1 :     GVariant *params = NULL;
    2590              : 
    2591            1 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    2592            1 :     g_variant_builder_add_value (&builder, g_variant_new ("s", snapshot_name));
    2593            1 :     g_variant_builder_add_value (&builder, g_variant_new ("t", size));
    2594            1 :     params = g_variant_builder_end (&builder);
    2595            1 :     g_variant_builder_clear (&builder);
    2596              : 
    2597            1 :     return call_lv_method_sync (vg_name, origin_name, "Snapshot", params, NULL, extra, TRUE, error);
    2598              : }
    2599              : 
    2600              : /**
    2601              :  * bd_lvm_lvsnapshotmerge:
    2602              :  * @vg_name: name of the VG containing the to-be-merged LV snapshot
    2603              :  * @snapshot_name: name of the to-be-merged LV snapshot
    2604              :  * @extra: (nullable) (array zero-terminated=1): extra options for the LV snapshot merge
    2605              :  *                                                 (just passed to LVM as is)
    2606              :  * @error: (out) (optional): place to store error (if any)
    2607              :  *
    2608              :  * Returns: whether the @vg_name/@snapshot_name LV snapshot was successfully merged or not
    2609              :  *
    2610              :  * Tech category: %BD_LVM_TECH_BASIC_SNAP-%BD_LVM_TECH_MODE_MODIFY
    2611              :  */
    2612            1 : gboolean bd_lvm_lvsnapshotmerge (const gchar *vg_name, const gchar *snapshot_name, const BDExtraArg **extra, GError **error) {
    2613            1 :     gchar *obj_id = NULL;
    2614            1 :     gchar *obj_path = NULL;
    2615              : 
    2616              :     /* get object path for vg_name/snapshot_name and call SNAP_INTF, "Merge" */
    2617            1 :     obj_id = g_strdup_printf ("%s/%s", vg_name, snapshot_name);
    2618            1 :     obj_path = get_object_path (obj_id, error);
    2619            1 :     g_free (obj_id);
    2620            1 :     if (!obj_path)
    2621            0 :         return FALSE;
    2622              : 
    2623            1 :     return call_lvm_method_sync (obj_path, SNAP_INTF, "Merge", NULL, NULL, extra, TRUE, error);
    2624              : }
    2625              : 
    2626              : /**
    2627              :  * bd_lvm_add_lv_tags:
    2628              :  * @vg_name: name of the VG that contains the LV to set tags on
    2629              :  * @lv_name: name of the LV to set tags on
    2630              :  * @tags: (array zero-terminated=1): list of tags to add
    2631              :  * @error: (out) (optional): place to store error (if any)
    2632              :  *
    2633              :  * Returns: whether the tags were successfully added to @device or not
    2634              :  *
    2635              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_QUERY
    2636              :  */
    2637            2 : gboolean bd_lvm_add_lv_tags (const gchar *vg_name, const gchar *lv_name, const gchar **tags, GError **error) {
    2638            2 :     g_autofree gchar *obj_id = NULL;
    2639            2 :     g_autofree gchar *obj_path = NULL;
    2640              : 
    2641              :     /* get object path for vg_name/lv_name */
    2642            2 :     obj_id = g_strdup_printf ("%s/%s", vg_name, lv_name);
    2643            2 :     obj_path = get_object_path (obj_id, error);
    2644            2 :     if (!obj_path)
    2645            0 :         return FALSE;
    2646              : 
    2647            2 :     return _manage_lvm_tags (obj_path, NULL, LV_INTF, tags, "TagsAdd", error);
    2648              : }
    2649              : 
    2650              : /**
    2651              :  * bd_lvm_delete_lv_tags:
    2652              :  * @vg_name: name of the VG that contains the LV to set tags on
    2653              :  * @lv_name: name of the LV to set tags on
    2654              :  * @tags: (array zero-terminated=1): list of tags to remove
    2655              :  * @error: (out) (optional): place to store error (if any)
    2656              :  *
    2657              :  * Returns: whether the tags were successfully removed from @device or not
    2658              :  *
    2659              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_QUERY
    2660              :  */
    2661            1 : gboolean bd_lvm_delete_lv_tags (const gchar *vg_name, const gchar *lv_name, const gchar **tags, GError **error) {
    2662            1 :     g_autofree gchar *obj_id = NULL;
    2663            1 :     g_autofree gchar *obj_path = NULL;
    2664              : 
    2665              :     /* get object path for vg_name/lv_name */
    2666            1 :     obj_id = g_strdup_printf ("%s/%s", vg_name, lv_name);
    2667            1 :     obj_path = get_object_path (obj_id, error);
    2668            1 :     if (!obj_path)
    2669            0 :         return FALSE;
    2670              : 
    2671            1 :     return _manage_lvm_tags (obj_path, NULL, LV_INTF, tags, "TagsDel", error);
    2672              : }
    2673              : 
    2674              : /**
    2675              :  * bd_lvm_lvinfo:
    2676              :  * @vg_name: name of the VG that contains the LV to get information about
    2677              :  * @lv_name: name of the LV to get information about
    2678              :  * @error: (out) (optional): place to store error (if any)
    2679              :  *
    2680              :  * Returns: (transfer full): information about the @vg_name/@lv_name LV or %NULL in case
    2681              :  * of error (the @error) gets populated in those cases)
    2682              :  *
    2683              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_QUERY
    2684              :  */
    2685           37 : BDLVMLVdata* bd_lvm_lvinfo (const gchar *vg_name, const gchar *lv_name, GError **error) {
    2686           37 :     GVariant *props = NULL;
    2687           37 :     BDLVMLVdata* ret = NULL;
    2688              : 
    2689           37 :     props = get_lv_properties (vg_name, lv_name, error);
    2690           37 :     if (!props)
    2691              :         /* the error is already populated */
    2692            0 :         return NULL;
    2693              : 
    2694           37 :     ret = get_lv_data_from_props (props, error);
    2695           37 :     if (!ret)
    2696            0 :         return NULL;
    2697              : 
    2698           67 :     if (g_strcmp0 (ret->segtype, "thin-pool") == 0 ||
    2699           30 :         g_strcmp0 (ret->segtype, "cache-pool") == 0) {
    2700            7 :         ret->data_lv = _lvm_data_lv_name (vg_name, lv_name, NULL);
    2701            7 :         ret->metadata_lv = _lvm_metadata_lv_name (vg_name, lv_name, NULL);
    2702              :     }
    2703           37 :     if (g_strcmp0 (ret->segtype, "vdo-pool") == 0) {
    2704            5 :         ret->data_lv = _lvm_data_lv_name (vg_name, lv_name, NULL);
    2705              :     }
    2706              : 
    2707           37 :     return ret;
    2708              : }
    2709              : 
    2710            4 : BDLVMLVdata* bd_lvm_lvinfo_tree (const gchar *vg_name, const gchar *lv_name, GError **error) {
    2711            4 :     GVariant *props = NULL;
    2712            4 :     BDLVMLVdata* ret = NULL;
    2713              : 
    2714            4 :     props = get_lv_properties (vg_name, lv_name, error);
    2715            4 :     if (!props)
    2716              :         /* the error is already populated */
    2717            0 :         return NULL;
    2718              : 
    2719            4 :     ret = get_lv_data_from_props (props, error);
    2720            4 :     if (!ret)
    2721            0 :         return NULL;
    2722              : 
    2723            8 :     if (g_strcmp0 (ret->segtype, "thin-pool") == 0 ||
    2724            4 :         g_strcmp0 (ret->segtype, "cache-pool") == 0) {
    2725            0 :         ret->data_lv = _lvm_data_lv_name (vg_name, lv_name, NULL);
    2726            0 :         ret->metadata_lv = _lvm_metadata_lv_name (vg_name, lv_name, NULL);
    2727              :     }
    2728            4 :     if (g_strcmp0 (ret->segtype, "vdo-pool") == 0) {
    2729            0 :         ret->data_lv = _lvm_data_lv_name (vg_name, lv_name, NULL);
    2730              :     }
    2731            4 :     ret->segs = _lvm_segs (vg_name, lv_name, NULL);
    2732            4 :     _lvm_data_and_metadata_lvs (vg_name, lv_name, &ret->data_lvs, &ret->metadata_lvs, NULL);
    2733              : 
    2734            4 :     return ret;
    2735              : }
    2736              : 
    2737           46 : static gchar* get_lv_vg_name (const gchar *lv_obj_path, GError **error) {
    2738           46 :     GVariant *value = NULL;
    2739           46 :     gchar *vg_obj_path = NULL;
    2740           46 :     gchar *ret = NULL;
    2741              : 
    2742           46 :     value = get_object_property (lv_obj_path, LV_CMN_INTF, "Vg", error);
    2743           46 :     g_variant_get (value, "o", &vg_obj_path);
    2744           46 :     g_variant_unref (value);
    2745              : 
    2746           46 :     value = get_object_property (vg_obj_path, VG_INTF, "Name", error);
    2747           46 :     g_variant_get (value, "s", &ret);
    2748           46 :     g_free (vg_obj_path);
    2749           46 :     g_variant_unref (value);
    2750              : 
    2751           46 :     return ret;
    2752              : }
    2753              : 
    2754              : /**
    2755              :  * filter_lvs_by_vg: (skip)
    2756              :  *
    2757              :  * Filter LVs by VG name and prepend the matching ones to the @out list.
    2758              :  */
    2759           90 : static gboolean filter_lvs_by_vg (gchar **lvs, const gchar *vg_name, GSList **out, guint64 *n_lvs, GError **error) {
    2760           90 :     gchar **lv_p = NULL;
    2761           90 :     gchar *lv_vg_name = NULL;
    2762           90 :     gboolean success = TRUE;
    2763              : 
    2764           90 :     if (!lvs)
    2765              :         /* nothing to do */
    2766            0 :         return TRUE;
    2767              : 
    2768          137 :     for (lv_p=lvs; *lv_p; lv_p++) {
    2769           47 :         if (vg_name) {
    2770           46 :             lv_vg_name = get_lv_vg_name (*lv_p, error);
    2771           46 :             if (!lv_vg_name) {
    2772            0 :                 g_free (*lv_p);
    2773            0 :                 success = FALSE;
    2774            0 :                 continue;
    2775              :             }
    2776              : 
    2777           46 :             if (g_strcmp0 (lv_vg_name, vg_name) == 0) {
    2778           46 :                 *out = g_slist_prepend (*out, *lv_p);
    2779           46 :                 (*n_lvs)++;
    2780              :             } else {
    2781            0 :                 g_free (*lv_p);
    2782              :             }
    2783              : 
    2784           46 :             g_free (lv_vg_name);
    2785              :         } else {
    2786            1 :             *out = g_slist_prepend (*out, *lv_p);
    2787            1 :             (*n_lvs)++;
    2788              :         }
    2789              :     }
    2790           90 :     return success;
    2791              : }
    2792              : 
    2793              : /**
    2794              :  * bd_lvm_lvs:
    2795              :  * @vg_name: (nullable): name of the VG to get information about LVs from
    2796              :  * @error: (out) (optional): place to store error (if any)
    2797              :  *
    2798              :  * Returns: (array zero-terminated=1): information about LVs found in the given
    2799              :  * @vg_name VG or in system if @vg_name is %NULL
    2800              :  *
    2801              :  * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_QUERY
    2802              :  */
    2803           14 : BDLVMLVdata** bd_lvm_lvs (const gchar *vg_name, GError **error) {
    2804           14 :     gchar **lvs = NULL;
    2805           14 :     guint64 n_lvs = 0;
    2806           14 :     GVariant *props = NULL;
    2807           14 :     BDLVMLVdata **ret = NULL;
    2808           14 :     guint64 j = 0;
    2809           14 :     GSList *matched_lvs = NULL;
    2810           14 :     GSList *lv = NULL;
    2811           14 :     gboolean success = FALSE;
    2812           14 :     GError *l_error = NULL;
    2813              : 
    2814           14 :     lvs = get_existing_objects (LV_OBJ_PREFIX, &l_error);
    2815           14 :     if (!lvs && l_error) {
    2816            0 :         g_propagate_error (error, l_error);
    2817            0 :         return NULL;
    2818              :     }
    2819           14 :     success = filter_lvs_by_vg (lvs, vg_name, &matched_lvs, &n_lvs, error);
    2820           14 :     g_free (lvs);
    2821           14 :     if (!success) {
    2822            0 :         g_slist_free_full (matched_lvs, g_free);
    2823            0 :         return NULL;
    2824              :     }
    2825              : 
    2826           14 :     lvs = get_existing_objects (THIN_POOL_OBJ_PREFIX, &l_error);
    2827           14 :     if (!lvs && l_error) {
    2828            0 :         g_propagate_error (error, l_error);
    2829            0 :         g_slist_free_full (matched_lvs, g_free);
    2830            0 :         return NULL;
    2831              :     }
    2832           14 :     success = filter_lvs_by_vg (lvs, vg_name, &matched_lvs, &n_lvs, error);
    2833           14 :     g_free (lvs);
    2834           14 :     if (!success) {
    2835            0 :         g_slist_free_full (matched_lvs, g_free);
    2836            0 :         return NULL;
    2837              :     }
    2838              : 
    2839           14 :     lvs = get_existing_objects (CACHE_POOL_OBJ_PREFIX, &l_error);
    2840           14 :     if (!lvs && l_error) {
    2841            0 :         g_propagate_error (error, l_error);
    2842            0 :         g_slist_free_full (matched_lvs, g_free);
    2843            0 :         return NULL;
    2844              :     }
    2845           14 :     success = filter_lvs_by_vg (lvs, vg_name, &matched_lvs, &n_lvs, error);
    2846           14 :     g_free (lvs);
    2847           14 :     if (!success) {
    2848            0 :         g_slist_free_full (matched_lvs, g_free);
    2849            0 :         return NULL;
    2850              :     }
    2851              : 
    2852           14 :     lvs = get_existing_objects (VDO_POOL_OBJ_PREFIX, &l_error);
    2853           14 :     if (!lvs && l_error) {
    2854            0 :         g_propagate_error (error, l_error);
    2855            0 :         g_slist_free_full (matched_lvs, g_free);
    2856            0 :         return NULL;
    2857              :     }
    2858           14 :     success = filter_lvs_by_vg (lvs, vg_name, &matched_lvs, &n_lvs, error);
    2859           14 :     g_free (lvs);
    2860           14 :     if (!success) {
    2861            0 :         g_slist_free_full (matched_lvs, g_free);
    2862            0 :         return NULL;
    2863              :     }
    2864              : 
    2865           14 :     lvs = get_existing_objects (HIDDEN_LV_OBJ_PREFIX, &l_error);
    2866           14 :     if (!lvs && l_error) {
    2867            0 :         g_propagate_error (error, l_error);
    2868            0 :         g_slist_free_full (matched_lvs, g_free);
    2869            0 :         return NULL;
    2870              :     }
    2871           14 :     success = filter_lvs_by_vg (lvs, vg_name, &matched_lvs, &n_lvs, error);
    2872           14 :     g_free (lvs);
    2873           14 :     if (!success) {
    2874            0 :         g_slist_free_full (matched_lvs, g_free);
    2875            0 :         return NULL;
    2876              :     }
    2877              : 
    2878           14 :     if (n_lvs == 0) {
    2879              :         /* no LVs */
    2880            2 :         ret = g_new0 (BDLVMLVdata*, 1);
    2881            2 :         ret[0] = NULL;
    2882            2 :         g_slist_free_full (matched_lvs, g_free);
    2883            2 :         return ret;
    2884              :     }
    2885              : 
    2886              :     /* we have been prepending to the list so far, but it will be nicer if we
    2887              :        reverse it (to get back the original order) */
    2888           12 :     matched_lvs = g_slist_reverse (matched_lvs);
    2889              : 
    2890              :     /* now create the return value -- NULL-terminated array of BDLVMLVdata */
    2891           12 :     ret = g_new0 (BDLVMLVdata*, n_lvs + 1);
    2892              : 
    2893           12 :     lv = matched_lvs;
    2894           39 :     while (lv) {
    2895           27 :         props = get_object_properties (lv->data, LV_CMN_INTF, &l_error);
    2896           27 :         if (!props) {
    2897            0 :             g_slist_free_full (matched_lvs, g_free);
    2898            0 :             g_free (ret);
    2899            0 :             g_propagate_error (error, l_error);
    2900            0 :             return NULL;
    2901              :         }
    2902           27 :         ret[j] = get_lv_data_from_props (props, &l_error);
    2903           27 :         if (!(ret[j])) {
    2904            0 :             g_slist_free_full (matched_lvs, g_free);
    2905            0 :             for (guint64 i = 0; i < j; i++)
    2906            0 :                 bd_lvm_lvdata_free (ret[i]);
    2907            0 :             g_free (ret);
    2908            0 :             g_propagate_error (error, l_error);
    2909            0 :             return NULL;
    2910           53 :         } else if ((g_strcmp0 (ret[j]->segtype, "thin-pool") == 0) ||
    2911           26 :                    (g_strcmp0 (ret[j]->segtype, "cache-pool") == 0)) {
    2912            3 :             ret[j]->data_lv = _lvm_data_lv_name (ret[j]->vg_name, ret[j]->lv_name, &l_error);
    2913            3 :             ret[j]->metadata_lv = _lvm_metadata_lv_name (ret[j]->vg_name, ret[j]->lv_name, &l_error);
    2914           24 :         } else if (g_strcmp0 (ret[j]->segtype, "vdo-pool") == 0) {
    2915            1 :             ret[j]->data_lv = _lvm_data_lv_name (ret[j]->vg_name, ret[j]->lv_name, &l_error);
    2916              :         }
    2917           27 :         if (l_error) {
    2918            0 :             g_slist_free_full (matched_lvs, g_free);
    2919            0 :             for (guint64 i = 0; i <= j; i++)
    2920            0 :                 bd_lvm_lvdata_free (ret[i]);
    2921            0 :             g_free (ret);
    2922            0 :             g_propagate_error (error, l_error);
    2923            0 :             return NULL;
    2924              :         }
    2925           27 :         j++;
    2926           27 :         lv = g_slist_next (lv);
    2927              :     }
    2928           12 :     g_slist_free_full (matched_lvs, g_free);
    2929              : 
    2930           12 :     ret[j] = NULL;
    2931           12 :     return ret;
    2932              : }
    2933              : 
    2934            4 : BDLVMLVdata** bd_lvm_lvs_tree (const gchar *vg_name, GError **error) {
    2935            4 :     gchar **lvs = NULL;
    2936            4 :     guint64 n_lvs = 0;
    2937            4 :     GVariant *props = NULL;
    2938            4 :     BDLVMLVdata **ret = NULL;
    2939            4 :     guint64 j = 0;
    2940            4 :     GSList *matched_lvs = NULL;
    2941            4 :     GSList *lv = NULL;
    2942            4 :     gboolean success = FALSE;
    2943            4 :     GError *l_error = NULL;
    2944              : 
    2945            4 :     lvs = get_existing_objects (LV_OBJ_PREFIX, &l_error);
    2946            4 :     if (!lvs && l_error) {
    2947            0 :         g_propagate_error (error, l_error);
    2948            0 :         return NULL;
    2949              :     }
    2950            4 :     success = filter_lvs_by_vg (lvs, vg_name, &matched_lvs, &n_lvs, error);
    2951            4 :     g_free (lvs);
    2952            4 :     if (!success) {
    2953            0 :         g_slist_free_full (matched_lvs, g_free);
    2954            0 :         return NULL;
    2955              :     }
    2956              : 
    2957            4 :     lvs = get_existing_objects (THIN_POOL_OBJ_PREFIX, &l_error);
    2958            4 :     if (!lvs && l_error) {
    2959            0 :         g_propagate_error (error, l_error);
    2960            0 :         g_slist_free_full (matched_lvs, g_free);
    2961            0 :         return NULL;
    2962              :     }
    2963            4 :     success = filter_lvs_by_vg (lvs, vg_name, &matched_lvs, &n_lvs, error);
    2964            4 :     g_free (lvs);
    2965            4 :     if (!success) {
    2966            0 :         g_slist_free_full (matched_lvs, g_free);
    2967            0 :         return NULL;
    2968              :     }
    2969              : 
    2970            4 :     lvs = get_existing_objects (CACHE_POOL_OBJ_PREFIX, &l_error);
    2971            4 :     if (!lvs && l_error) {
    2972            0 :         g_propagate_error (error, l_error);
    2973            0 :         g_slist_free_full (matched_lvs, g_free);
    2974            0 :         return NULL;
    2975              :     }
    2976            4 :     success = filter_lvs_by_vg (lvs, vg_name, &matched_lvs, &n_lvs, error);
    2977            4 :     g_free (lvs);
    2978            4 :     if (!success) {
    2979            0 :         g_slist_free_full (matched_lvs, g_free);
    2980            0 :         return NULL;
    2981              :     }
    2982              : 
    2983            4 :     lvs = get_existing_objects (VDO_POOL_OBJ_PREFIX, &l_error);
    2984            4 :     if (!lvs && l_error) {
    2985            0 :         g_propagate_error (error, l_error);
    2986            0 :         g_slist_free_full (matched_lvs, g_free);
    2987            0 :         return NULL;
    2988              :     }
    2989            4 :     success = filter_lvs_by_vg (lvs, vg_name, &matched_lvs, &n_lvs, error);
    2990            4 :     g_free (lvs);
    2991            4 :     if (!success) {
    2992            0 :         g_slist_free_full (matched_lvs, g_free);
    2993            0 :         return NULL;
    2994              :     }
    2995              : 
    2996            4 :     lvs = get_existing_objects (HIDDEN_LV_OBJ_PREFIX, &l_error);
    2997            4 :     if (!lvs && l_error) {
    2998            0 :         g_propagate_error (error, l_error);
    2999            0 :         g_slist_free_full (matched_lvs, g_free);
    3000            0 :         return NULL;
    3001              :     }
    3002            4 :     success = filter_lvs_by_vg (lvs, vg_name, &matched_lvs, &n_lvs, error);
    3003            4 :     g_free (lvs);
    3004            4 :     if (!success) {
    3005            0 :         g_slist_free_full (matched_lvs, g_free);
    3006            0 :         return NULL;
    3007              :     }
    3008              : 
    3009            4 :     if (n_lvs == 0) {
    3010              :         /* no LVs */
    3011            0 :         ret = g_new0 (BDLVMLVdata*, 1);
    3012            0 :         ret[0] = NULL;
    3013            0 :         g_slist_free_full (matched_lvs, g_free);
    3014            0 :         return ret;
    3015              :     }
    3016              : 
    3017              :     /* we have been prepending to the list so far, but it will be nicer if we
    3018              :        reverse it (to get back the original order) */
    3019            4 :     matched_lvs = g_slist_reverse (matched_lvs);
    3020              : 
    3021              :     /* now create the return value -- NULL-terminated array of BDLVMLVdata */
    3022            4 :     ret = g_new0 (BDLVMLVdata*, n_lvs + 1);
    3023              : 
    3024            4 :     lv = matched_lvs;
    3025           24 :     while (lv) {
    3026           20 :         props = get_object_properties (lv->data, LV_CMN_INTF, &l_error);
    3027           20 :         if (!props) {
    3028            0 :             g_slist_free_full (matched_lvs, g_free);
    3029            0 :             g_free (ret);
    3030            0 :             g_propagate_error (error, l_error);
    3031            0 :             return NULL;
    3032              :         }
    3033           20 :         ret[j] = get_lv_data_from_props (props, &l_error);
    3034           20 :         if (!(ret[j])) {
    3035            0 :             g_slist_free_full (matched_lvs, g_free);
    3036            0 :             for (guint64 i = 0; i < j; i++)
    3037            0 :                 bd_lvm_lvdata_free (ret[i]);
    3038            0 :             g_free (ret);
    3039            0 :             g_propagate_error (error, l_error);
    3040            0 :             return NULL;
    3041           40 :         } else if ((g_strcmp0 (ret[j]->segtype, "thin-pool") == 0) ||
    3042           20 :                    (g_strcmp0 (ret[j]->segtype, "cache-pool") == 0)) {
    3043            0 :             ret[j]->data_lv = _lvm_data_lv_name (ret[j]->vg_name, ret[j]->lv_name, &l_error);
    3044            0 :             ret[j]->metadata_lv = _lvm_metadata_lv_name (ret[j]->vg_name, ret[j]->lv_name, &l_error);
    3045           20 :         } else if (g_strcmp0 (ret[j]->segtype, "vdo-pool") == 0) {
    3046            0 :             ret[j]->data_lv = _lvm_data_lv_name (ret[j]->vg_name, ret[j]->lv_name, &l_error);
    3047              :         }
    3048           20 :         ret[j]->segs = _lvm_segs (ret[j]->vg_name, ret[j]->lv_name, &l_error);
    3049           20 :         _lvm_data_and_metadata_lvs (ret[j]->vg_name, ret[j]->lv_name, &ret[j]->data_lvs, &ret[j]->metadata_lvs,
    3050              :                                     &l_error);
    3051           20 :         if (l_error) {
    3052            0 :             g_slist_free_full (matched_lvs, g_free);
    3053            0 :             for (guint64 i = 0; i <= j; i++)
    3054            0 :                 bd_lvm_lvdata_free (ret[i]);
    3055            0 :             g_free (ret);
    3056            0 :             g_propagate_error (error, l_error);
    3057            0 :             return NULL;
    3058              :         }
    3059           20 :         j++;
    3060           20 :         lv = g_slist_next (lv);
    3061              :     }
    3062            4 :     g_slist_free_full (matched_lvs, g_free);
    3063              : 
    3064            4 :     ret[j] = NULL;
    3065            4 :     return ret;
    3066              : }
    3067              : 
    3068              : /**
    3069              :  * bd_lvm_thpoolcreate:
    3070              :  * @vg_name: name of the VG to create a thin pool in
    3071              :  * @lv_name: name of the to-be-created pool LV
    3072              :  * @size: requested size of the to-be-created pool
    3073              :  * @md_size: requested metadata size or 0 to use the default
    3074              :  * @chunk_size: requested chunk size or 0 to use the default
    3075              :  * @profile: (nullable): profile to use (see lvm(8) for more information) or %NULL to use
    3076              :  *                         the default
    3077              :  * @extra: (nullable) (array zero-terminated=1): extra options for the thin pool creation
    3078              :  *                                                 (just passed to LVM as is)
    3079              :  * @error: (out) (optional): place to store error (if any)
    3080              :  *
    3081              :  * Returns: whether the @vg_name/@lv_name thin pool was successfully created or not
    3082              :  *
    3083              :  * Tech category: %BD_LVM_TECH_THIN-%BD_LVM_TECH_MODE_CREATE
    3084              :  */
    3085            6 : gboolean bd_lvm_thpoolcreate (const gchar *vg_name, const gchar *lv_name, guint64 size, guint64 md_size, guint64 chunk_size, const gchar *profile, const BDExtraArg **extra, GError **error) {
    3086              :     GVariantBuilder builder;
    3087            6 :     GVariant *params = NULL;
    3088            6 :     GVariant *extra_params = NULL;
    3089            6 :     GVariant *param = NULL;
    3090              : 
    3091            6 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    3092            6 :     g_variant_builder_add_value (&builder, g_variant_new ("s", lv_name));
    3093            6 :     g_variant_builder_add_value (&builder, g_variant_new_uint64 (size));
    3094            6 :     g_variant_builder_add_value (&builder, g_variant_new_boolean (TRUE));
    3095            6 :     params = g_variant_builder_end (&builder);
    3096            6 :     g_variant_builder_clear (&builder);
    3097              : 
    3098            6 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
    3099            6 :     if (md_size != 0) {
    3100            6 :         param = create_size_str_param (md_size, "b");
    3101            6 :         g_variant_builder_add (&builder, "{sv}", "poolmetadatasize", param);
    3102              :     }
    3103            6 :     if (chunk_size != 0) {
    3104            6 :         param = create_size_str_param (chunk_size, "b");
    3105            6 :         g_variant_builder_add (&builder, "{sv}", "chunksize", param);
    3106              :     }
    3107            6 :     if (profile) {
    3108            4 :         g_variant_builder_add (&builder, "{sv}", "profile", g_variant_new ("s", profile));
    3109              :     }
    3110            6 :     extra_params = g_variant_builder_end (&builder);
    3111            6 :     g_variant_builder_clear (&builder);
    3112              : 
    3113            6 :     return call_lvm_obj_method_sync (vg_name, VG_INTF, "LvCreateLinear", params, extra_params, extra, TRUE, error);
    3114              : }
    3115              : 
    3116              : /**
    3117              :  * bd_lvm_thlvcreate:
    3118              :  * @vg_name: name of the VG containing the thin pool providing extents for the to-be-created thin LV
    3119              :  * @pool_name: name of the pool LV providing extents for the to-be-created thin LV
    3120              :  * @lv_name: name of the to-be-created thin LV
    3121              :  * @size: requested virtual size of the to-be-created thin LV
    3122              :  * @extra: (nullable) (array zero-terminated=1): extra options for the thin LV creation
    3123              :  *                                                 (just passed to LVM as is)
    3124              :  * @error: (out) (optional): place to store error (if any)
    3125              :  *
    3126              :  * Returns: whether the @vg_name/@lv_name thin LV was successfully created or not
    3127              :  *
    3128              :  * Tech category: %BD_LVM_TECH_THIN-%BD_LVM_TECH_MODE_CREATE
    3129              :  */
    3130            2 : gboolean bd_lvm_thlvcreate (const gchar *vg_name, const gchar *pool_name, const gchar *lv_name, guint64 size, const BDExtraArg **extra, GError **error) {
    3131              :     GVariantBuilder builder;
    3132            2 :     GVariant *params = NULL;
    3133              : 
    3134            2 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    3135            2 :     g_variant_builder_add_value (&builder, g_variant_new ("s", lv_name));
    3136            2 :     g_variant_builder_add_value (&builder, g_variant_new ("t", size));
    3137            2 :     params = g_variant_builder_end (&builder);
    3138            2 :     g_variant_builder_clear (&builder);
    3139              : 
    3140            2 :     return call_thpool_method_sync (vg_name, pool_name, "LvCreate", params, NULL, extra, TRUE, error);
    3141              : }
    3142              : 
    3143              : /**
    3144              :  * bd_lvm_thlvpoolname:
    3145              :  * @vg_name: name of the VG containing the queried thin LV
    3146              :  * @lv_name: name of the queried thin LV
    3147              :  * @error: (out) (optional): place to store error (if any)
    3148              :  *
    3149              :  * Returns: (transfer full): the name of the pool volume for the @vg_name/@lv_name
    3150              :  * thin LV or %NULL if failed to determine (@error) is set in those cases)
    3151              :  *
    3152              :  * Tech category: %BD_LVM_TECH_THIN-%BD_LVM_TECH_MODE_QUERY
    3153              :  */
    3154            1 : gchar* bd_lvm_thlvpoolname (const gchar *vg_name, const gchar *lv_name, GError **error) {
    3155            1 :     GVariant *prop = NULL;
    3156            1 :     gboolean is_thin = FALSE;
    3157            1 :     gchar *pool_obj_path = NULL;
    3158            1 :     gchar *ret = NULL;
    3159              : 
    3160            1 :     prop = get_lv_property (vg_name, lv_name, "IsThinVolume", error);
    3161            1 :     if (!prop)
    3162            0 :         return NULL;
    3163            1 :     is_thin = g_variant_get_boolean (prop);
    3164            1 :     g_variant_unref (prop);
    3165              : 
    3166            1 :     if (!is_thin) {
    3167            0 :         g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_NOEXIST,
    3168              :                      "The LV '%s' is not a thin LV and thus have no thin pool", lv_name);
    3169            0 :         return NULL;
    3170              :     }
    3171            1 :     prop = get_lv_property (vg_name, lv_name, "PoolLv", error);
    3172            1 :     if (!prop)
    3173            0 :         return NULL;
    3174            1 :     g_variant_get (prop, "o", &pool_obj_path);
    3175            1 :     g_variant_unref (prop);
    3176              : 
    3177            1 :     prop = get_object_property (pool_obj_path, LV_CMN_INTF, "Name", error);
    3178            1 :     g_free (pool_obj_path);
    3179            1 :     if (!prop)
    3180            0 :         return NULL;
    3181            1 :     g_variant_get (prop, "s", &ret);
    3182            1 :     g_variant_unref (prop);
    3183              : 
    3184            1 :     return ret;
    3185              : }
    3186              : 
    3187              : /**
    3188              :  * bd_lvm_thsnapshotcreate:
    3189              :  * @vg_name: name of the VG containing the thin LV a new snapshot should be created of
    3190              :  * @origin_name: name of the thin LV a new snapshot should be created of
    3191              :  * @snapshot_name: name of the to-be-created snapshot
    3192              :  * @pool_name: (nullable): name of the thin pool to create the snapshot in or %NULL if not specified
    3193              :  * @extra: (nullable) (array zero-terminated=1): extra options for the thin LV snapshot creation
    3194              :  *                                                 (just passed to LVM as is)
    3195              :  * @error: (out) (optional): place to store error (if any)
    3196              :  *
    3197              :  * Returns: whether the @snapshot_name snapshot of the @vg_name/@origin_name
    3198              :  * thin LV was successfully created or not.
    3199              :  *
    3200              :  * Tech category: %BD_LVM_TECH_THIN-%BD_LVM_TECH_MODE_CREATE
    3201              :  */
    3202            1 : gboolean bd_lvm_thsnapshotcreate (const gchar *vg_name, const gchar *origin_name, const gchar *snapshot_name, const gchar *pool_name, const BDExtraArg **extra, GError **error) {
    3203              :     GVariantBuilder builder;
    3204            1 :     GVariant *params = NULL;
    3205            1 :     GVariant *extra_params = NULL;
    3206              : 
    3207            1 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    3208            1 :     g_variant_builder_add_value (&builder, g_variant_new ("s", snapshot_name));
    3209            1 :     g_variant_builder_add_value (&builder, g_variant_new ("t", (guint64) 0));
    3210            1 :     params = g_variant_builder_end (&builder);
    3211            1 :     g_variant_builder_clear (&builder);
    3212              : 
    3213            1 :     if (pool_name) {
    3214            1 :         g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
    3215            1 :         g_variant_builder_add (&builder, "{sv}", "thinpool", g_variant_new ("s", pool_name));
    3216            1 :         extra_params = g_variant_builder_end (&builder);
    3217            1 :         g_variant_builder_clear (&builder);
    3218              :     }
    3219              : 
    3220            1 :     return call_lv_method_sync (vg_name, origin_name, "Snapshot", params, extra_params, extra, TRUE, error);
    3221              : }
    3222              : 
    3223              : /**
    3224              :  * get_lv_type_from_flags: (skip)
    3225              :  * @meta: getting type for a (future) metadata LV
    3226              :  *
    3227              :  * Get LV type string from flags.
    3228              :  */
    3229           16 : static const gchar* get_lv_type_from_flags (BDLVMCachePoolFlags flags, gboolean meta, GError **error G_GNUC_UNUSED) {
    3230           16 :     if (!meta) {
    3231            8 :         if (flags & BD_LVM_CACHE_POOL_STRIPED)
    3232            1 :             return "striped";
    3233            7 :         else if (flags & BD_LVM_CACHE_POOL_RAID1)
    3234            0 :             return "raid1";
    3235            7 :         else if (flags & BD_LVM_CACHE_POOL_RAID5)
    3236            0 :             return "raid5";
    3237            7 :         else if (flags & BD_LVM_CACHE_POOL_RAID6)
    3238            0 :             return "raid6";
    3239            7 :         else if (flags & BD_LVM_CACHE_POOL_RAID10)
    3240            0 :             return "raid10";
    3241              :         else
    3242            7 :             return NULL;
    3243              :     } else {
    3244            8 :         if (flags & BD_LVM_CACHE_POOL_META_STRIPED)
    3245            0 :             return "striped";
    3246            8 :         else if (flags & BD_LVM_CACHE_POOL_META_RAID1)
    3247            1 :             return "raid1";
    3248            7 :         else if (flags & BD_LVM_CACHE_POOL_META_RAID5)
    3249            0 :             return "raid5";
    3250            7 :         else if (flags & BD_LVM_CACHE_POOL_META_RAID6)
    3251            0 :             return "raid6";
    3252            7 :         else if (flags & BD_LVM_CACHE_POOL_META_RAID10)
    3253            0 :             return "raid10";
    3254              :         else
    3255            7 :             return NULL;
    3256              :     }
    3257              : }
    3258              : 
    3259              : /**
    3260              :  * bd_lvm_cache_create_pool:
    3261              :  * @vg_name: name of the VG to create @pool_name in
    3262              :  * @pool_name: name of the cache pool LV to create
    3263              :  * @pool_size: desired size of the cache pool @pool_name
    3264              :  * @md_size: desired size of the @pool_name cache pool's metadata LV or 0 to
    3265              :  *           use the default
    3266              :  * @mode: cache mode of the @pool_name cache pool
    3267              :  * @flags: a combination of (ORed) #BDLVMCachePoolFlags
    3268              :  * @fast_pvs: (array zero-terminated=1): list of (fast) PVs to create the @pool_name
    3269              :  *                                       cache pool (and the metadata LV)
    3270              :  * @error: (out) (optional): place to store error (if any)
    3271              :  *
    3272              :  * Returns: whether the cache pool @vg_name/@pool_name was successfully created or not
    3273              :  *
    3274              :  * Tech category: %BD_LVM_TECH_CACHE-%BD_LVM_TECH_MODE_CREATE
    3275              :  */
    3276            8 : gboolean bd_lvm_cache_create_pool (const gchar *vg_name, const gchar *pool_name, guint64 pool_size, guint64 md_size, BDLVMCacheMode mode, BDLVMCachePoolFlags flags, const gchar **fast_pvs, GError **error) {
    3277            8 :     gboolean success = FALSE;
    3278            8 :     const gchar *type = NULL;
    3279            8 :     gchar *name = NULL;
    3280              :     GVariantBuilder builder;
    3281            8 :     GVariant *params = NULL;
    3282            8 :     GVariant *extra = NULL;
    3283            8 :     gchar *lv_id = NULL;
    3284            8 :     gchar *lv_obj_path = NULL;
    3285            8 :     const gchar *mode_str = NULL;
    3286            8 :     gchar *msg = NULL;
    3287            8 :     guint64 progress_id = 0;
    3288            8 :     GError *l_error = NULL;
    3289              : 
    3290            8 :     msg = g_strdup_printf ("Started 'create cache pool %s/%s'", vg_name, pool_name);
    3291            8 :     progress_id = bd_utils_report_started (msg);
    3292            8 :     g_free (msg);
    3293              : 
    3294              :     /* create an LV for the pool */
    3295            8 :     type = get_lv_type_from_flags (flags, FALSE, NULL);
    3296            8 :     success = bd_lvm_lvcreate (vg_name, pool_name, pool_size, type, fast_pvs, NULL, &l_error);
    3297            8 :     if (!success) {
    3298            0 :         g_prefix_error (&l_error, "Failed to create the pool LV: ");
    3299            0 :         bd_utils_report_finished (progress_id, l_error->message);
    3300            0 :         g_propagate_error (error, l_error);
    3301            0 :         return FALSE;
    3302              :     }
    3303              : 
    3304              :     /* 1/3 steps done */
    3305            8 :     bd_utils_report_progress (progress_id, 33, "Created the data LV");
    3306              : 
    3307              :     /* determine the size of the metadata LV */
    3308            8 :     type = get_lv_type_from_flags (flags, TRUE, NULL);
    3309            8 :     if (md_size == 0)
    3310            7 :         md_size = bd_lvm_cache_get_default_md_size (pool_size, NULL);
    3311            8 :     name = g_strdup_printf ("%s_meta", pool_name);
    3312              : 
    3313              :     /* create the metadata LV */
    3314            8 :     success = bd_lvm_lvcreate (vg_name, name, md_size, type, fast_pvs, NULL, &l_error);
    3315            8 :     if (!success) {
    3316            0 :         g_free (name);
    3317            0 :         g_prefix_error (&l_error, "Failed to create the pool metadata LV: ");
    3318            0 :         bd_utils_report_finished (progress_id, l_error->message);
    3319            0 :         g_propagate_error (error, l_error);
    3320            0 :         return FALSE;
    3321              :     }
    3322              : 
    3323              :     /* 2/3 steps done */
    3324            8 :     bd_utils_report_progress (progress_id, 66, "Created the metadata LV");
    3325              : 
    3326              :     /* create the cache pool from the two LVs */
    3327              :     /* build the params tuple */
    3328            8 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    3329            8 :     lv_id = g_strdup_printf ("%s/%s", vg_name, name);
    3330            8 :     lv_obj_path = get_object_path (lv_id, &l_error);
    3331            8 :     g_free (lv_id);
    3332            8 :     if (!lv_obj_path) {
    3333            0 :         g_variant_builder_clear (&builder);
    3334            0 :         bd_utils_report_finished (progress_id, l_error->message);
    3335            0 :         g_propagate_error (error, l_error);
    3336            0 :         return FALSE;
    3337              :     }
    3338            8 :     g_variant_builder_add_value (&builder, g_variant_new ("o", lv_obj_path));
    3339            8 :     lv_id = g_strdup_printf ("%s/%s", vg_name, pool_name);
    3340            8 :     lv_obj_path = get_object_path (lv_id, &l_error);
    3341            8 :     g_free (lv_id);
    3342            8 :     if (!lv_obj_path) {
    3343            0 :         g_variant_builder_clear (&builder);
    3344            0 :         bd_utils_report_finished (progress_id, l_error->message);
    3345            0 :         g_propagate_error (error, l_error);
    3346            0 :         return FALSE;
    3347              :     }
    3348            8 :     g_variant_builder_add_value (&builder, g_variant_new ("o", lv_obj_path));
    3349            8 :     params = g_variant_builder_end (&builder);
    3350            8 :     g_variant_builder_clear (&builder);
    3351              : 
    3352              :     /* build the dictionary with the extra params */
    3353            8 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
    3354            8 :     mode_str = bd_lvm_cache_get_mode_str (mode, &l_error);
    3355            8 :     if (!mode_str) {
    3356            0 :         g_variant_builder_clear (&builder);
    3357            0 :         bd_utils_report_finished (progress_id, l_error->message);
    3358            0 :         g_propagate_error (error, l_error);
    3359            0 :         return FALSE;
    3360              :     }
    3361            8 :     g_variant_builder_add (&builder, "{sv}", "cachemode", g_variant_new ("s", mode_str));
    3362            8 :     extra = g_variant_builder_end (&builder);
    3363            8 :     g_variant_builder_clear (&builder);
    3364              : 
    3365            8 :     success = call_lvm_obj_method_sync (vg_name, VG_INTF, "CreateCachePool", params, extra, NULL, TRUE, &l_error);
    3366            8 :     if (!success) {
    3367            0 :         bd_utils_report_finished (progress_id, l_error->message);
    3368            0 :         g_propagate_error (error, l_error);
    3369              :     } else
    3370            8 :         bd_utils_report_finished (progress_id, "Completed");
    3371              : 
    3372            8 :     return success;
    3373              : }
    3374              : 
    3375              : /**
    3376              :  * bd_lvm_cache_attach:
    3377              :  * @vg_name: name of the VG containing the @data_lv and the @cache_pool_lv LVs
    3378              :  * @data_lv: data LV to attach the @cache_pool_lv to
    3379              :  * @cache_pool_lv: cache pool LV to attach to the @data_lv
    3380              :  * @extra: (nullable) (array zero-terminated=1): extra options for the cache attachment
    3381              :  *                                                 (just passed to LVM as is)
    3382              :  * @error: (out) (optional): place to store error (if any)
    3383              :  *
    3384              :  * Returns: whether the @cache_pool_lv was successfully attached to the @data_lv or not
    3385              :  *
    3386              :  * Tech category: %BD_LVM_TECH_CACHE-%BD_LVM_TECH_MODE_MODIFY
    3387              :  */
    3388            6 : gboolean bd_lvm_cache_attach (const gchar *vg_name, const gchar *data_lv, const gchar *cache_pool_lv, const BDExtraArg **extra, GError **error) {
    3389              :     GVariantBuilder builder;
    3390            6 :     GVariant *params = NULL;
    3391            6 :     gchar *lv_id = NULL;
    3392            6 :     g_autofree gchar *lv_obj_path = NULL;
    3393            6 :     gboolean ret = FALSE;
    3394              : 
    3395            6 :     lv_id = g_strdup_printf ("%s/%s", vg_name, data_lv);
    3396            6 :     lv_obj_path = get_object_path (lv_id, error);
    3397            6 :     g_free (lv_id);
    3398            6 :     if (!lv_obj_path)
    3399            0 :         return FALSE;
    3400            6 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    3401            6 :     g_variant_builder_add_value (&builder, g_variant_new ("o", lv_obj_path));
    3402            6 :     params = g_variant_builder_end (&builder);
    3403            6 :     g_variant_builder_clear (&builder);
    3404              : 
    3405            6 :     lv_id = g_strdup_printf ("%s/%s", vg_name, cache_pool_lv);
    3406              : 
    3407            6 :     ret = call_lvm_obj_method_sync (lv_id, CACHE_POOL_INTF, "CacheLv", params, NULL, extra, TRUE, error);
    3408            6 :     g_free (lv_id);
    3409            6 :     return ret;
    3410              : }
    3411              : 
    3412              : /**
    3413              :  * bd_lvm_cache_detach:
    3414              :  * @vg_name: name of the VG containing the @cached_lv
    3415              :  * @cached_lv: name of the cached LV to detach its cache from
    3416              :  * @destroy: whether to destroy the cache after detach or not
    3417              :  * @extra: (nullable) (array zero-terminated=1): extra options for the cache detachment
    3418              :  *                                                 (just passed to LVM as is)
    3419              :  * @error: (out) (optional): place to store error (if any)
    3420              :  *
    3421              :  * Returns: whether the cache was successfully detached from the @cached_lv or not
    3422              :  *
    3423              :  * Note: synces the cache first
    3424              :  *
    3425              :  * Tech category: %BD_LVM_TECH_CACHE-%BD_LVM_TECH_MODE_MODIFY
    3426              :  */
    3427            4 : gboolean bd_lvm_cache_detach (const gchar *vg_name, const gchar *cached_lv, gboolean destroy, const BDExtraArg **extra, GError **error) {
    3428            4 :     g_autofree gchar *lv_id = NULL;
    3429            4 :     g_autofree gchar *cache_pool_name = NULL;
    3430              :     GVariantBuilder builder;
    3431            4 :     GVariant *params = NULL;
    3432              : 
    3433            4 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    3434            4 :     g_variant_builder_add_value (&builder, g_variant_new ("b", destroy));
    3435            4 :     params = g_variant_builder_end (&builder);
    3436            4 :     g_variant_builder_clear (&builder);
    3437              : 
    3438            4 :     cache_pool_name = bd_lvm_cache_pool_name (vg_name, cached_lv, error);
    3439            4 :     if (!cache_pool_name)
    3440            0 :         return FALSE;
    3441            4 :     lv_id = g_strdup_printf ("%s/%s", vg_name, cached_lv);
    3442            4 :     return call_lvm_obj_method_sync (lv_id, CACHED_LV_INTF, "DetachCachePool", params, NULL, extra, TRUE, error);
    3443              : }
    3444              : 
    3445              : /**
    3446              :  * bd_lvm_cache_create_cached_lv:
    3447              :  * @vg_name: name of the VG to create a cached LV in
    3448              :  * @lv_name: name of the cached LV to create
    3449              :  * @data_size: size of the data LV
    3450              :  * @cache_size: size of the cache (or cached LV more precisely)
    3451              :  * @md_size: size of the cache metadata LV or 0 to use the default
    3452              :  * @mode: cache mode for the cached LV
    3453              :  * @flags: a combination of (ORed) #BDLVMCachePoolFlags
    3454              :  * @slow_pvs: (array zero-terminated=1): list of slow PVs (used for the data LV)
    3455              :  * @fast_pvs: (array zero-terminated=1): list of fast PVs (used for the cache LV)
    3456              :  * @error: (out) (optional): place to store error (if any)
    3457              :  *
    3458              :  * Returns: whether the cached LV @lv_name was successfully created or not
    3459              :  *
    3460              :  * Tech category: %BD_LVM_TECH_CACHE-%BD_LVM_TECH_MODE_CREATE
    3461              :  */
    3462            1 : gboolean bd_lvm_cache_create_cached_lv (const gchar *vg_name, const gchar *lv_name, guint64 data_size, guint64 cache_size, guint64 md_size, BDLVMCacheMode mode, BDLVMCachePoolFlags flags,
    3463              :                                         const gchar **slow_pvs, const gchar **fast_pvs, GError **error) {
    3464            1 :     gboolean success = FALSE;
    3465            1 :     gchar *name = NULL;
    3466            1 :     gchar *msg = NULL;
    3467            1 :     guint64 progress_id = 0;
    3468            1 :     GError *l_error = NULL;
    3469              : 
    3470            1 :     msg = g_strdup_printf ("Started 'create cached LV %s/%s'", vg_name, lv_name);
    3471            1 :     progress_id = bd_utils_report_started (msg);
    3472            1 :     g_free (msg);
    3473              : 
    3474            1 :     success = bd_lvm_lvcreate (vg_name, lv_name, data_size, NULL, slow_pvs, NULL, &l_error);
    3475            1 :     if (!success) {
    3476            0 :         g_prefix_error (&l_error, "Failed to create the data LV: ");
    3477            0 :         bd_utils_report_finished (progress_id, l_error->message);
    3478            0 :         g_propagate_error (error, l_error);
    3479            0 :         return FALSE;
    3480              :     }
    3481              : 
    3482              :     /* 1/5 steps (cache pool creation has 3 steps) done */
    3483            1 :     bd_utils_report_progress (progress_id, 20, "Data LV created");
    3484              : 
    3485            1 :     name = g_strdup_printf ("%s_cache", lv_name);
    3486            1 :     success = bd_lvm_cache_create_pool (vg_name, name, cache_size, md_size, mode, flags, fast_pvs, &l_error);
    3487            1 :     if (!success) {
    3488            0 :         g_prefix_error (&l_error, "Failed to create the cache pool '%s': ", name);
    3489            0 :         g_free (name);
    3490            0 :         bd_utils_report_finished (progress_id, l_error->message);
    3491            0 :         g_propagate_error (error, l_error);
    3492            0 :         return FALSE;
    3493              :     }
    3494              : 
    3495              :     /* 4/5 steps (cache pool creation has 3 steps) done */
    3496            1 :     bd_utils_report_progress (progress_id, 80, "Cache pool created");
    3497              : 
    3498            1 :     success = bd_lvm_cache_attach (vg_name, lv_name, name, NULL, &l_error);
    3499            1 :     if (!success) {
    3500            0 :         g_prefix_error (&l_error, "Failed to attach the cache pool '%s' to the data LV: ", name);
    3501            0 :         g_free (name);
    3502            0 :         bd_utils_report_finished (progress_id, l_error->message);
    3503            0 :         g_propagate_error (error, l_error);
    3504            0 :         return FALSE;
    3505              :     }
    3506              : 
    3507            1 :     bd_utils_report_finished (progress_id, "Completed");
    3508            1 :     g_free (name);
    3509            1 :     return TRUE;
    3510              : }
    3511              : 
    3512              : /**
    3513              :  * bd_lvm_writecache_attach:
    3514              :  * @vg_name: name of the VG containing the @data_lv and the @cache_pool_lv LVs
    3515              :  * @data_lv: data LV to attach the @cache_lv to
    3516              :  * @cache_lv: cache (fast) LV to attach to the @data_lv
    3517              :  * @extra: (nullable) (array zero-terminated=1): extra options for the cache attachment
    3518              :  *                                                 (just passed to LVM as is)
    3519              :  * @error: (out) (optional): place to store error (if any)
    3520              :  *
    3521              :  * Returns: whether the @cache_lv was successfully attached to the @data_lv or not
    3522              :  *
    3523              :  * Note: Both @data_lv and @cache_lv will be deactivated before the operation.
    3524              :  *
    3525              :  * Tech category: %BD_LVM_TECH_WRITECACHE-%BD_LVM_TECH_MODE_MODIFY
    3526              :  */
    3527            3 : gboolean bd_lvm_writecache_attach (const gchar *vg_name, const gchar *data_lv, const gchar *cache_lv, const BDExtraArg **extra, GError **error) {
    3528              :     GVariantBuilder builder;
    3529            3 :     GVariant *params = NULL;
    3530            3 :     gchar *lv_id = NULL;
    3531            3 :     g_autofree gchar *lv_obj_path = NULL;
    3532            3 :     gboolean success = FALSE;
    3533              : 
    3534              :     /* both LVs need to be inactive for the writecache convert to work */
    3535            3 :     success = bd_lvm_lvdeactivate (vg_name, data_lv, NULL, error);
    3536            3 :     if (!success)
    3537            0 :         return FALSE;
    3538              : 
    3539            3 :     success = bd_lvm_lvdeactivate (vg_name, cache_lv, NULL, error);
    3540            3 :     if (!success)
    3541            0 :         return FALSE;
    3542              : 
    3543            3 :     lv_id = g_strdup_printf ("%s/%s", vg_name, data_lv);
    3544            3 :     lv_obj_path = get_object_path (lv_id, error);
    3545            3 :     g_free (lv_id);
    3546            3 :     if (!lv_obj_path)
    3547            0 :         return FALSE;
    3548            3 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    3549            3 :     g_variant_builder_add_value (&builder, g_variant_new ("o", lv_obj_path));
    3550            3 :     params = g_variant_builder_end (&builder);
    3551            3 :     g_variant_builder_clear (&builder);
    3552              : 
    3553            3 :     lv_id = g_strdup_printf ("%s/%s", vg_name, cache_lv);
    3554              : 
    3555            3 :     success = call_lvm_obj_method_sync (lv_id, LV_INTF, "WriteCacheLv", params, NULL, extra, TRUE, error);
    3556            3 :     g_free (lv_id);
    3557            3 :     return success;
    3558              : }
    3559              : 
    3560              : /**
    3561              :  * bd_lvm_writecache_detach:
    3562              :  * @vg_name: name of the VG containing the @cached_lv
    3563              :  * @cached_lv: name of the cached LV to detach its cache from
    3564              :  * @destroy: whether to destroy the cache after detach or not
    3565              :  * @extra: (nullable) (array zero-terminated=1): extra options for the cache detachment
    3566              :  *                                                 (just passed to LVM as is)
    3567              :  * @error: (out) (optional): place to store error (if any)
    3568              :  *
    3569              :  * Returns: whether the cache was successfully detached from the @cached_lv or not
    3570              :  *
    3571              :  * Note: synces the cache first
    3572              :  *
    3573              :  * Tech category: %BD_LVM_TECH_WRITECACHE-%BD_LVM_TECH_MODE_MODIFY
    3574              :  */
    3575            2 : gboolean bd_lvm_writecache_detach (const gchar *vg_name, const gchar *cached_lv, gboolean destroy, const BDExtraArg **extra, GError **error) {
    3576            2 :     return bd_lvm_cache_detach (vg_name, cached_lv, destroy, extra, error);
    3577              : }
    3578              : 
    3579              : /**
    3580              :  * bd_lvm_writecache_create_cached_lv:
    3581              :  * @vg_name: name of the VG to create a cached LV in
    3582              :  * @lv_name: name of the cached LV to create
    3583              :  * @data_size: size of the data LV
    3584              :  * @cache_size: size of the cache (or cached LV more precisely)
    3585              :  * @slow_pvs: (array zero-terminated=1): list of slow PVs (used for the data LV)
    3586              :  * @fast_pvs: (array zero-terminated=1): list of fast PVs (used for the cache LV)
    3587              :  * @error: (out) (optional): place to store error (if any)
    3588              :  *
    3589              :  * Returns: whether the cached LV @lv_name was successfully created or not
    3590              :  *
    3591              :  * Tech category: %BD_LVM_TECH_WRITECACHE-%BD_LVM_TECH_MODE_CREATE
    3592              :  */
    3593            1 : gboolean bd_lvm_writecache_create_cached_lv (const gchar *vg_name, const gchar *lv_name, guint64 data_size, guint64 cache_size,
    3594              :                                              const gchar **slow_pvs, const gchar **fast_pvs, GError **error) {
    3595            1 :     gboolean success = FALSE;
    3596            1 :     gchar *name = NULL;
    3597            1 :     gchar *msg = NULL;
    3598            1 :     guint64 progress_id = 0;
    3599            1 :     GError *l_error = NULL;
    3600              : 
    3601            1 :     msg = g_strdup_printf ("Started 'create cached LV %s/%s'", vg_name, lv_name);
    3602            1 :     progress_id = bd_utils_report_started (msg);
    3603            1 :     g_free (msg);
    3604              : 
    3605            1 :     name = g_strdup_printf ("%s_writecache", lv_name);
    3606            1 :     success = bd_lvm_lvcreate (vg_name, name, cache_size, NULL, fast_pvs, NULL, &l_error);
    3607            1 :     if (!success) {
    3608            0 :         g_prefix_error (&l_error, "Failed to create the cache LV '%s': ", name);
    3609            0 :         g_free (name);
    3610            0 :         bd_utils_report_finished (progress_id, l_error->message);
    3611            0 :         g_propagate_error (error, l_error);
    3612            0 :         return FALSE;
    3613              :     }
    3614              : 
    3615              :     /* 1/3 steps done */
    3616            1 :     bd_utils_report_progress (progress_id, 33, "Cache LV created");
    3617              : 
    3618            1 :     success = bd_lvm_lvcreate (vg_name, lv_name, data_size, NULL, slow_pvs, NULL, &l_error);
    3619            1 :     if (!success) {
    3620            0 :         g_prefix_error (&l_error, "Failed to create the data LV: ");
    3621            0 :         g_free (name);
    3622            0 :         bd_utils_report_finished (progress_id, l_error->message);
    3623            0 :         g_propagate_error (error, l_error);
    3624            0 :         return FALSE;
    3625              :     }
    3626              : 
    3627              :     /* 2/3 steps done */
    3628            1 :     bd_utils_report_progress (progress_id, 66, "Data LV created");
    3629              : 
    3630            1 :     success = bd_lvm_writecache_attach (vg_name, lv_name, name, NULL, &l_error);
    3631            1 :     if (!success) {
    3632            0 :         g_prefix_error (&l_error, "Failed to attach the cache LV '%s' to the data LV: ", name);
    3633            0 :         g_free (name);
    3634            0 :         bd_utils_report_finished (progress_id, l_error->message);
    3635            0 :         g_propagate_error (error, l_error);
    3636            0 :         return FALSE;
    3637              :     }
    3638              : 
    3639            1 :     bd_utils_report_finished (progress_id, "Completed");
    3640            1 :     g_free (name);
    3641            1 :     return TRUE;
    3642              : }
    3643              : 
    3644              : /**
    3645              :  * bd_lvm_cache_pool_name:
    3646              :  * @vg_name: name of the VG containing the @cached_lv
    3647              :  * @cached_lv: cached LV to get the name of the its pool LV for
    3648              :  * @error: (out) (optional): place to store error (if any)
    3649              :  *
    3650              :  * Returns: name of the cache pool LV used by the @cached_lv or %NULL in case of error
    3651              :  *
    3652              :  * Tech category: %BD_LVM_TECH_CACHE-%BD_LVM_TECH_MODE_QUERY
    3653              :  */
    3654            5 : gchar* bd_lvm_cache_pool_name (const gchar *vg_name, const gchar *cached_lv, GError **error) {
    3655            5 :     gchar *ret = NULL;
    3656            5 :     gchar *name_start = NULL;
    3657            5 :     gchar *name_end = NULL;
    3658            5 :     gchar *pool_name = NULL;
    3659            5 :     gchar *lv_spec = NULL;
    3660            5 :     GVariant *prop = NULL;
    3661            5 :     gchar *pool_obj_path = NULL;
    3662              : 
    3663              :     /* same as for a thin LV, but with square brackets */
    3664            5 :     lv_spec = g_strdup_printf ("%s/%s", vg_name, cached_lv);
    3665            5 :     prop = get_lvm_object_property (lv_spec, CACHED_LV_INTF, "CachePool", error);
    3666            5 :     g_free (lv_spec);
    3667            5 :     if (!prop)
    3668            0 :         return NULL;
    3669            5 :     g_variant_get (prop, "o", &pool_obj_path);
    3670            5 :     prop = get_object_property (pool_obj_path, LV_CMN_INTF, "Name", error);
    3671            5 :     g_free (pool_obj_path);
    3672            5 :     if (!prop)
    3673            0 :         return NULL;
    3674            5 :     g_variant_get (prop, "s", &ret);
    3675            5 :     g_variant_unref (prop);
    3676              : 
    3677            5 :     name_start = strchr (ret, '[');
    3678            5 :     if (!name_start) {
    3679            0 :         g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_CACHE_INVAL,
    3680              :                      "Failed to determine cache pool name from: '%s'", ret);
    3681            0 :         g_free (ret);
    3682            0 :         return NULL;
    3683              :     }
    3684            5 :     name_start++;
    3685              : 
    3686            5 :     name_end = strchr (ret, ']');
    3687            5 :     if (!name_end) {
    3688            0 :         g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_CACHE_INVAL,
    3689              :                      "Failed to determine cache pool name from: '%s'", ret);
    3690            0 :         g_free (ret);
    3691            0 :         return NULL;
    3692              :     }
    3693              : 
    3694            5 :     pool_name = g_strndup (name_start, name_end - name_start);
    3695            5 :     g_free (ret);
    3696              : 
    3697            5 :     return pool_name;
    3698              : }
    3699              : 
    3700              : /**
    3701              :  * bd_lvm_thpool_convert:
    3702              :  * @vg_name: name of the VG to create the new thin pool in
    3703              :  * @data_lv: name of the LV that should become the data part of the new pool
    3704              :  * @metadata_lv: name of the LV that should become the metadata part of the new pool
    3705              :  * @name: (nullable): name for the thin pool (if %NULL, the name @data_lv is inherited)
    3706              :  * @extra: (nullable) (array zero-terminated=1): extra options for the thin pool creation
    3707              :  *                                                 (just passed to LVM as is)
    3708              :  * @error: (out) (optional): place to store error (if any)
    3709              :  *
    3710              :  * Converts the @data_lv and @metadata_lv into a new thin pool in the @vg_name
    3711              :  * VG.
    3712              :  *
    3713              :  * Returns: whether the new thin pool was successfully created from @data_lv and
    3714              :  *          @metadata_lv or not
    3715              :  *
    3716              :  * Tech category: %BD_LVM_TECH_THIN-%BD_LVM_TECH_MODE_CREATE
    3717              :  */
    3718            1 : gboolean bd_lvm_thpool_convert (const gchar *vg_name, const gchar *data_lv, const gchar *metadata_lv, const gchar *name, const BDExtraArg **extra, GError **error) {
    3719              :     GVariantBuilder builder;
    3720            1 :     GVariant *params = NULL;
    3721            1 :     gchar *obj_id = NULL;
    3722            1 :     gchar *data_lv_path = NULL;
    3723            1 :     gchar *metadata_lv_path = NULL;
    3724            1 :     gboolean ret = FALSE;
    3725              : 
    3726            1 :     obj_id = g_strdup_printf ("%s/%s", vg_name, data_lv);
    3727            1 :     data_lv_path = get_object_path (obj_id, error);
    3728            1 :     g_free (obj_id);
    3729            1 :     if (!data_lv_path)
    3730            0 :         return FALSE;
    3731              : 
    3732            1 :     obj_id = g_strdup_printf ("%s/%s", vg_name, metadata_lv);
    3733            1 :     metadata_lv_path = get_object_path (obj_id, error);
    3734            1 :     g_free (obj_id);
    3735            1 :     if (!metadata_lv_path)
    3736            0 :         return FALSE;
    3737              : 
    3738            1 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    3739            1 :     g_variant_builder_add_value (&builder, g_variant_new ("o", metadata_lv_path));
    3740            1 :     g_variant_builder_add_value (&builder, g_variant_new ("o", data_lv_path));
    3741            1 :     params = g_variant_builder_end (&builder);
    3742            1 :     g_variant_builder_clear (&builder);
    3743              : 
    3744            1 :     ret = call_lvm_obj_method_sync (vg_name, VG_INTF, "CreateThinPool", params, NULL, extra, TRUE, error);
    3745            1 :     if (ret && name)
    3746            1 :         bd_lvm_lvrename (vg_name, data_lv, name, NULL, error);
    3747            1 :     return ret;
    3748              : }
    3749              : 
    3750              : /**
    3751              :  * bd_lvm_cache_pool_convert:
    3752              :  * @vg_name: name of the VG to create the new thin pool in
    3753              :  * @data_lv: name of the LV that should become the data part of the new pool
    3754              :  * @metadata_lv: name of the LV that should become the metadata part of the new pool
    3755              :  * @name: (nullable): name for the thin pool (if %NULL, the name @data_lv is inherited)
    3756              :  * @extra: (nullable) (array zero-terminated=1): extra options for the thin pool creation
    3757              :  *                                                 (just passed to LVM as is)
    3758              :  * @error: (out) (optional): place to store error (if any)
    3759              :  *
    3760              :  * Converts the @data_lv and @metadata_lv into a new cache pool in the @vg_name
    3761              :  * VG.
    3762              :  *
    3763              :  * Returns: whether the new cache pool was successfully created from @data_lv and
    3764              :  *          @metadata_lv or not
    3765              :  *
    3766              :  * Tech category: %BD_LVM_TECH_CACHE-%BD_LVM_TECH_MODE_CREATE
    3767              :  */
    3768            1 : gboolean bd_lvm_cache_pool_convert (const gchar *vg_name, const gchar *data_lv, const gchar *metadata_lv, const gchar *name, const BDExtraArg **extra, GError **error) {
    3769              :     GVariantBuilder builder;
    3770            1 :     GVariant *params = NULL;
    3771            1 :     gchar *obj_id = NULL;
    3772            1 :     gchar *data_lv_path = NULL;
    3773            1 :     gchar *metadata_lv_path = NULL;
    3774            1 :     gboolean ret = FALSE;
    3775              : 
    3776            1 :     obj_id = g_strdup_printf ("%s/%s", vg_name, data_lv);
    3777            1 :     data_lv_path = get_object_path (obj_id, error);
    3778            1 :     g_free (obj_id);
    3779            1 :     if (!data_lv_path)
    3780            0 :         return FALSE;
    3781              : 
    3782            1 :     obj_id = g_strdup_printf ("%s/%s", vg_name, metadata_lv);
    3783            1 :     metadata_lv_path = get_object_path (obj_id, error);
    3784            1 :     g_free (obj_id);
    3785            1 :     if (!metadata_lv_path)
    3786            0 :         return FALSE;
    3787              : 
    3788            1 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    3789            1 :     g_variant_builder_add_value (&builder, g_variant_new ("o", metadata_lv_path));
    3790            1 :     g_variant_builder_add_value (&builder, g_variant_new ("o", data_lv_path));
    3791            1 :     params = g_variant_builder_end (&builder);
    3792            1 :     g_variant_builder_clear (&builder);
    3793              : 
    3794            1 :     ret = call_lvm_obj_method_sync (vg_name, VG_INTF, "CreateCachePool", params, NULL, extra, TRUE, error);
    3795              : 
    3796            1 :     if (!ret && name)
    3797            0 :         bd_lvm_lvrename (vg_name, data_lv, name, NULL, error);
    3798              : 
    3799            1 :     return ret;
    3800              : }
    3801              : 
    3802              : /**
    3803              :  * bd_lvm_vdo_pool_create:
    3804              :  * @vg_name: name of the VG to create a new LV in
    3805              :  * @lv_name: name of the to-be-created VDO LV
    3806              :  * @pool_name: (nullable): name of the to-be-created VDO pool LV or %NULL for default name
    3807              :  * @data_size: requested size of the data VDO LV (physical size of the @pool_name VDO pool LV)
    3808              :  * @virtual_size: requested virtual_size of the @lv_name VDO LV
    3809              :  * @index_memory: amount of index memory (in bytes) or 0 for default
    3810              :  * @compression: whether to enable compression or not
    3811              :  * @deduplication: whether to enable deduplication or not
    3812              :  * @write_policy: write policy for the volume
    3813              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VDO LV creation
    3814              :  *                                                 (just passed to LVM as is)
    3815              :  * @error: (out) (optional): place to store error (if any)
    3816              :  *
    3817              :  * Returns: whether the given @vg_name/@lv_name VDO LV was successfully created or not
    3818              :  *
    3819              :  * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_CREATE
    3820              :  */
    3821            7 : gboolean bd_lvm_vdo_pool_create (const gchar *vg_name, const gchar *lv_name, const gchar *pool_name, guint64 data_size, guint64 virtual_size, guint64 index_memory, gboolean compression, gboolean deduplication, BDLVMVDOWritePolicy write_policy, const BDExtraArg **extra, GError **error) {
    3822              :     GVariantBuilder builder;
    3823            7 :     GVariant *params = NULL;
    3824            7 :     GVariant *extra_params = NULL;
    3825            7 :     gchar *old_config = NULL;
    3826            7 :     const gchar *write_policy_str = NULL;
    3827            7 :     g_autofree gchar *name = NULL;
    3828            7 :     gboolean ret = FALSE;
    3829              : 
    3830            7 :     write_policy_str = bd_lvm_get_vdo_write_policy_str (write_policy, error);
    3831            7 :     if (write_policy_str == NULL)
    3832            0 :         return FALSE;
    3833              : 
    3834              :     /* build the params tuple */
    3835            7 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
    3836              : 
    3837            7 :     if (!pool_name) {
    3838            1 :         name = g_strdup_printf ("%s_vpool", lv_name);
    3839            1 :         g_variant_builder_add_value (&builder, g_variant_new ("s", name));
    3840              :     } else
    3841            6 :         g_variant_builder_add_value (&builder, g_variant_new ("s", pool_name));
    3842              : 
    3843            7 :     g_variant_builder_add_value (&builder, g_variant_new ("s", lv_name));
    3844            7 :     g_variant_builder_add_value (&builder, g_variant_new ("t", data_size));
    3845            7 :     g_variant_builder_add_value (&builder, g_variant_new ("t", virtual_size));
    3846            7 :     params = g_variant_builder_end (&builder);
    3847            7 :     g_variant_builder_clear (&builder);
    3848              : 
    3849              :     /* and now the extra_params params */
    3850            7 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
    3851            7 :     g_variant_builder_add_value (&builder, g_variant_new ("{sv}", "--compression", g_variant_new ("s", compression ? "y" : "n")));
    3852            7 :     g_variant_builder_add_value (&builder, g_variant_new ("{sv}", "--deduplication", g_variant_new ("s", deduplication ? "y" : "n")));
    3853            7 :     extra_params = g_variant_builder_end (&builder);
    3854            7 :     g_variant_builder_clear (&builder);
    3855              : 
    3856              :     /* index_memory and write_policy can be specified only using the config */
    3857            7 :     g_mutex_lock (&global_config_lock);
    3858            7 :     old_config = global_config_str;
    3859            7 :     if (index_memory != 0)
    3860            3 :         global_config_str = g_strdup_printf ("%s allocation {vdo_index_memory_size_mb=%"G_GUINT64_FORMAT" vdo_write_policy=\"%s\"}", old_config ? old_config : "",
    3861              :                                                                                                                                      index_memory / (1024 * 1024),
    3862              :                                                                                                                                      write_policy_str);
    3863              :     else
    3864            4 :         global_config_str = g_strdup_printf ("%s allocation {vdo_write_policy=\"%s\"}", old_config ? old_config : "",
    3865              :                                                                                         write_policy_str);
    3866              : 
    3867            7 :     ret = call_lvm_obj_method_sync (vg_name, VG_VDO_INTF, "CreateVdoPoolandLv", params, extra_params, extra, FALSE, error);
    3868              : 
    3869            7 :     g_free (global_config_str);
    3870            7 :     global_config_str = old_config;
    3871            7 :     g_mutex_unlock (&global_config_lock);
    3872              : 
    3873            7 :     return ret;
    3874              : }
    3875              : 
    3876              : /**
    3877              :  * bd_lvm_vdo_enable_compression:
    3878              :  * @vg_name: name of the VG containing the to-be-changed VDO pool LV
    3879              :  * @pool_name: name of the VDO pool LV to enable compression on
    3880              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VDO change
    3881              :  *                                                 (just passed to LVM as is)
    3882              :  * @error: (out) (optional): place to store error (if any)
    3883              :  *
    3884              :  * Returns: whether compression was successfully enabled on @vg_name/@pool_name LV or not
    3885              :  *
    3886              :  * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_MODIFY
    3887              :  */
    3888            1 : gboolean bd_lvm_vdo_enable_compression (const gchar *vg_name, const gchar *pool_name, const BDExtraArg **extra, GError **error) {
    3889            1 :     return call_vdopool_method_sync (vg_name, pool_name, "EnableCompression", NULL, NULL, extra, TRUE, error);
    3890              : }
    3891              : 
    3892              : /**
    3893              :  * bd_lvm_vdo_disable_compression:
    3894              :  * @vg_name: name of the VG containing the to-be-changed VDO pool LV
    3895              :  * @pool_name: name of the VDO pool LV to disable compression on
    3896              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VDO change
    3897              :  *                                                 (just passed to LVM as is)
    3898              :  * @error: (out) (optional): place to store error (if any)
    3899              :  *
    3900              :  * Returns: whether compression was successfully disabled on @vg_name/@pool_name LV or not
    3901              :  *
    3902              :  * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_MODIFY
    3903              :  */
    3904            1 : gboolean bd_lvm_vdo_disable_compression (const gchar *vg_name, const gchar *pool_name, const BDExtraArg **extra, GError **error) {
    3905            1 :     return call_vdopool_method_sync (vg_name, pool_name, "DisableCompression", NULL, NULL, extra, TRUE, error);
    3906              : }
    3907              : 
    3908              : /**
    3909              :  * bd_lvm_vdo_enable_deduplication:
    3910              :  * @vg_name: name of the VG containing the to-be-changed VDO pool LV
    3911              :  * @pool_name: name of the VDO pool LV to enable deduplication on
    3912              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VDO change
    3913              :  *                                                 (just passed to LVM as is)
    3914              :  * @error: (out) (optional): place to store error (if any)
    3915              :  *
    3916              :  * Returns: whether deduplication was successfully enabled on @vg_name/@pool_name LV or not
    3917              :  *
    3918              :  * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_MODIFY
    3919              :  */
    3920            1 : gboolean bd_lvm_vdo_enable_deduplication (const gchar *vg_name, const gchar *pool_name, const BDExtraArg **extra, GError **error) {
    3921            1 :     return call_vdopool_method_sync (vg_name, pool_name, "EnableDeduplication", NULL, NULL, extra, TRUE, error);
    3922              : }
    3923              : 
    3924              : /**
    3925              :  * bd_lvm_vdo_enable_deduplication:
    3926              :  * @vg_name: name of the VG containing the to-be-changed VDO pool LV
    3927              :  * @pool_name: name of the VDO pool LV to disable deduplication on
    3928              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VDO change
    3929              :  *                                                 (just passed to LVM as is)
    3930              :  * @error: (out) (optional): place to store error (if any)
    3931              :  *
    3932              :  * Returns: whether deduplication was successfully disabled on @vg_name/@pool_name LV or not
    3933              :  *
    3934              :  * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_MODIFY
    3935              :  */
    3936            1 : gboolean bd_lvm_vdo_disable_deduplication (const gchar *vg_name, const gchar *pool_name, const BDExtraArg **extra, GError **error) {
    3937            1 :     return call_vdopool_method_sync (vg_name, pool_name, "DisableDeduplication", NULL, NULL, extra, TRUE, error);
    3938              : }
    3939              : 
    3940              : /**
    3941              :  * bd_lvm_vdo_info:
    3942              :  * @vg_name: name of the VG that contains the LV to get information about
    3943              :  * @pool_name: name of the VDO pool LV to get information about
    3944              :  * @error: (out) (optional): place to store error (if any)
    3945              :  *
    3946              :  * Returns: (transfer full): information about the @vg_name/@lv_name LV or %NULL in case
    3947              :  * of error (the @error) gets populated in those cases)
    3948              :  *
    3949              :  * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_QUERY
    3950              :  */
    3951            9 : BDLVMVDOPooldata* bd_lvm_vdo_info (const gchar *vg_name, const gchar *pool_name, GError **error) {
    3952            9 :     GVariant *props = NULL;
    3953              : 
    3954            9 :     props = get_vdo_properties (vg_name, pool_name, error);
    3955            9 :     if (!props)
    3956              :         /* the error is already populated */
    3957            0 :         return NULL;
    3958              : 
    3959            9 :     return get_vdo_data_from_props (props, error);
    3960              : }
    3961              : 
    3962              : /**
    3963              :  * bd_lvm_vdo_resize:
    3964              :  * @vg_name: name of the VG containing the to-be-resized VDO LV
    3965              :  * @lv_name: name of the to-be-resized VDO LV
    3966              :  * @size: the requested new size of the VDO LV
    3967              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VDO LV resize
    3968              :  *                                                 (just passed to LVM as is)
    3969              :  * @error: (out) (optional): place to store error (if any)
    3970              :  *
    3971              :  * Returns: whether the @vg_name/@lv_name VDO LV was successfully resized or not
    3972              :  *
    3973              :  * Note: Reduction needs to process TRIM for reduced disk area to unmap used data blocks
    3974              :  *       from the VDO pool LV and it may take a long time.
    3975              :  *
    3976              :  * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_MODIFY
    3977              :  */
    3978            1 : gboolean bd_lvm_vdo_resize (const gchar *vg_name, const gchar *lv_name, guint64 size, const BDExtraArg **extra, GError **error) {
    3979            1 :     return bd_lvm_lvresize (vg_name, lv_name, size, extra, error);
    3980              : }
    3981              : 
    3982              : /**
    3983              :  * bd_lvm_vdo_pool_resize:
    3984              :  * @vg_name: name of the VG containing the to-be-resized VDO pool LV
    3985              :  * @pool_name: name of the to-be-resized VDO pool LV
    3986              :  * @size: the requested new size of the VDO pool LV
    3987              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VDO pool LV resize
    3988              :  *                                                 (just passed to LVM as is)
    3989              :  * @error: (out) (optional): place to store error (if any)
    3990              :  *
    3991              :  * Returns: whether the @vg_name/@pool_name VDO pool LV was successfully resized or not
    3992              :  *
    3993              :  * Note: Size of the VDO pool LV can be only extended, not reduced.
    3994              :  *
    3995              :  * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_MODIFY
    3996              :  */
    3997            2 : gboolean bd_lvm_vdo_pool_resize (const gchar *vg_name, const gchar *pool_name, guint64 size, const BDExtraArg **extra, GError **error) {
    3998            2 :     BDLVMLVdata *info = NULL;
    3999              : 
    4000            2 :     info = bd_lvm_lvinfo (vg_name, pool_name, error);
    4001            2 :     if (!info)
    4002            0 :         return FALSE;
    4003              : 
    4004            2 :     if (info->size >= size) {
    4005            1 :         g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_NOT_SUPPORTED,
    4006              :                      "Reducing physical size of the VDO pool LV is not supported.");
    4007            1 :         bd_lvm_lvdata_free (info);
    4008            1 :         return FALSE;
    4009              :     }
    4010              : 
    4011            1 :     bd_lvm_lvdata_free (info);
    4012              : 
    4013            1 :     return bd_lvm_lvresize (vg_name, pool_name, size, extra, error);
    4014              : }
    4015              : 
    4016              : /**
    4017              :  * bd_lvm_vdo_pool_convert:
    4018              :  * @vg_name: name of the VG that contains @pool_lv
    4019              :  * @pool_lv: name of the LV that should become the new VDO pool LV
    4020              :  * @name: (nullable): name for the VDO LV or %NULL for default name
    4021              :  * @virtual_size: virtual size for the new VDO LV
    4022              :  * @extra: (nullable) (array zero-terminated=1): extra options for the VDO pool creation
    4023              :  *                                                 (just passed to LVM as is)
    4024              :  * @error: (out) (optional): place to store error (if any)
    4025              :  *
    4026              :  * Converts the @pool_lv into a new VDO pool LV in the @vg_name VG and creates a new
    4027              :  * @name VDO LV with size @virtual_size.
    4028              :  *
    4029              :  * Note: All data on @pool_lv will be irreversibly destroyed.
    4030              :  *
    4031              :  * Returns: whether the new VDO pool LV was successfully created from @pool_lv and or not
    4032              :  *
    4033              :  * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_CREATE&%BD_LVM_TECH_MODE_MODIFY
    4034              :  */
    4035            0 : gboolean bd_lvm_vdo_pool_convert (const gchar *vg_name G_GNUC_UNUSED, const gchar *pool_lv G_GNUC_UNUSED, const gchar *name G_GNUC_UNUSED,
    4036              :                                   guint64 virtual_size G_GNUC_UNUSED, guint64 index_memory G_GNUC_UNUSED, gboolean compression G_GNUC_UNUSED,
    4037              :                                   gboolean deduplication G_GNUC_UNUSED, BDLVMVDOWritePolicy write_policy G_GNUC_UNUSED,
    4038              :                                   const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
    4039            0 :     return bd_lvm_is_tech_avail (BD_LVM_TECH_VDO, BD_LVM_TECH_MODE_CREATE | BD_LVM_TECH_MODE_MODIFY, error);
    4040              : }
    4041              : 
    4042              : /**
    4043              :  * bd_lvm_vdolvpoolname:
    4044              :  * @vg_name: name of the VG containing the queried VDO LV
    4045              :  * @lv_name: name of the queried VDO LV
    4046              :  * @error: (out) (optional): place to store error (if any)
    4047              :  *
    4048              :  * Returns: (transfer full): the name of the pool volume for the @vg_name/@lv_name
    4049              :  * VDO LV or %NULL if failed to determine (@error) is set in those cases
    4050              :  *
    4051              :  * Tech category: %BD_LVM_TECH_VDO-%BD_LVM_TECH_MODE_QUERY
    4052              :  */
    4053            2 : gchar* bd_lvm_vdolvpoolname (const gchar *vg_name, const gchar *lv_name, GError **error) {
    4054            2 :     GVariant *prop = NULL;
    4055            2 :     const gchar *segtype = NULL;
    4056            2 :     gchar *pool_obj_path = NULL;
    4057            2 :     gchar *ret = NULL;
    4058              : 
    4059            2 :     prop = get_lv_property (vg_name, lv_name, "SegType", error);
    4060            2 :     if (!prop)
    4061            0 :         return NULL;
    4062              : 
    4063            2 :     g_variant_get_child (prop, 0, "&s", &segtype);
    4064            2 :     if (g_strcmp0 (segtype, "vdo") != 0) {
    4065            0 :         g_variant_unref (prop);
    4066            0 :         g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_NOEXIST,
    4067              :                      "The LV '%s' is not a VDO LV and thus have no VDO pool", lv_name);
    4068            0 :         return NULL;
    4069              :     }
    4070            2 :     g_variant_unref (prop);
    4071              : 
    4072            2 :     prop = get_lv_property (vg_name, lv_name, "PoolLv", error);
    4073            2 :     if (!prop)
    4074            0 :         return NULL;
    4075            2 :     g_variant_get (prop, "o", &pool_obj_path);
    4076            2 :     g_variant_unref (prop);
    4077              : 
    4078            2 :     prop = get_object_property (pool_obj_path, LV_CMN_INTF, "Name", error);
    4079            2 :     g_free (pool_obj_path);
    4080            2 :     if (!prop)
    4081            0 :         return NULL;
    4082            2 :     g_variant_get (prop, "s", &ret);
    4083            2 :     g_variant_unref (prop);
    4084              : 
    4085            2 :     return ret;
    4086              : }
    4087              : 
    4088              : 
    4089              : 
    4090              : 
    4091              : 
    4092              : 
    4093              : 
    4094              : 
    4095              : 
    4096              : 
    4097              : 
    4098              : 
    4099              : 
        

Generated by: LCOV version 2.0-1