LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/libdm - libdm-deptree.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 0 1093 0.0 %
Date: 2010-04-13 Functions: 0 75 0.0 %
Branches: 0 1216 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2005-2010 Red Hat, Inc. All rights reserved.
       3                 :            :  *
       4                 :            :  * This file is part of the device-mapper userspace tools.
       5                 :            :  *
       6                 :            :  * This copyrighted material is made available to anyone wishing to use,
       7                 :            :  * modify, copy, or redistribute it subject to the terms and conditions
       8                 :            :  * of the GNU Lesser General Public License v.2.1.
       9                 :            :  *
      10                 :            :  * You should have received a copy of the GNU Lesser General Public License
      11                 :            :  * along with this program; if not, write to the Free Software Foundation,
      12                 :            :  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      13                 :            :  */
      14                 :            : 
      15                 :            : #include "dmlib.h"
      16                 :            : #include "libdm-targets.h"
      17                 :            : #include "libdm-common.h"
      18                 :            : #include "kdev_t.h"
      19                 :            : #include "dm-ioctl.h"
      20                 :            : 
      21                 :            : #include <stdarg.h>
      22                 :            : #include <sys/param.h>
      23                 :            : #include <sys/utsname.h>
      24                 :            : 
      25                 :            : #define MAX_TARGET_PARAMSIZE 500000
      26                 :            : 
      27                 :            : /* FIXME Fix interface so this is used only by LVM */
      28                 :            : #define UUID_PREFIX "LVM-"
      29                 :            : 
      30                 :            : /* Supported segment types */
      31                 :            : enum {
      32                 :            :         SEG_CRYPT,
      33                 :            :         SEG_ERROR,
      34                 :            :         SEG_LINEAR,
      35                 :            :         SEG_MIRRORED,
      36                 :            :         SEG_REPLICATOR,
      37                 :            :         SEG_REPLICATOR_DEV,
      38                 :            :         SEG_SNAPSHOT,
      39                 :            :         SEG_SNAPSHOT_ORIGIN,
      40                 :            :         SEG_SNAPSHOT_MERGE,
      41                 :            :         SEG_STRIPED,
      42                 :            :         SEG_ZERO,
      43                 :            : };
      44                 :            : 
      45                 :            : /* FIXME Add crypt and multipath support */
      46                 :            : 
      47                 :            : struct {
      48                 :            :         unsigned type;
      49                 :            :         const char *target;
      50                 :            : } dm_segtypes[] = {
      51                 :            :         { SEG_CRYPT, "crypt" },
      52                 :            :         { SEG_ERROR, "error" },
      53                 :            :         { SEG_LINEAR, "linear" },
      54                 :            :         { SEG_MIRRORED, "mirror" },
      55                 :            :         { SEG_REPLICATOR, "replicator" },
      56                 :            :         { SEG_REPLICATOR_DEV, "replicator-dev" },
      57                 :            :         { SEG_SNAPSHOT, "snapshot" },
      58                 :            :         { SEG_SNAPSHOT_ORIGIN, "snapshot-origin" },
      59                 :            :         { SEG_SNAPSHOT_MERGE, "snapshot-merge" },
      60                 :            :         { SEG_STRIPED, "striped" },
      61                 :            :         { SEG_ZERO, "zero"},
      62                 :            : };
      63                 :            : 
      64                 :            : /* Some segment types have a list of areas of other devices attached */
      65                 :            : struct seg_area {
      66                 :            :         struct dm_list list;
      67                 :            : 
      68                 :            :         struct dm_tree_node *dev_node;
      69                 :            : 
      70                 :            :         uint64_t offset;
      71                 :            : 
      72                 :            :         unsigned rsite_index;           /* Replicator site index */
      73                 :            :         struct dm_tree_node *slog;      /* Replicator sync log node */
      74                 :            :         uint64_t region_size;           /* Replicator sync log size */
      75                 :            :         uint32_t flags;                 /* Replicator sync log flags */
      76                 :            : };
      77                 :            : 
      78                 :            : /* Replicator-log has a list of sites */
      79                 :            : /* CHECKME: maybe move to seg_area too? */
      80                 :            : struct replicator_site {
      81                 :            :         struct dm_list list;
      82                 :            : 
      83                 :            :         unsigned rsite_index;
      84                 :            :         dm_replicator_mode_t mode;
      85                 :            :         uint32_t async_timeout;
      86                 :            :         uint32_t fall_behind_ios;
      87                 :            :         uint64_t fall_behind_data;
      88                 :            : };
      89                 :            : 
      90                 :            : /* Per-segment properties */
      91                 :            : struct load_segment {
      92                 :            :         struct dm_list list;
      93                 :            : 
      94                 :            :         unsigned type;
      95                 :            : 
      96                 :            :         uint64_t size;
      97                 :            : 
      98                 :            :         unsigned area_count;            /* Linear + Striped + Mirrored + Crypt + Replicator */
      99                 :            :         struct dm_list areas;           /* Linear + Striped + Mirrored + Crypt + Replicator */
     100                 :            : 
     101                 :            :         uint32_t stripe_size;           /* Striped */
     102                 :            : 
     103                 :            :         int persistent;                 /* Snapshot */
     104                 :            :         uint32_t chunk_size;            /* Snapshot */
     105                 :            :         struct dm_tree_node *cow;       /* Snapshot */
     106                 :            :         struct dm_tree_node *origin;    /* Snapshot + Snapshot origin */
     107                 :            :         struct dm_tree_node *merge;     /* Snapshot */
     108                 :            : 
     109                 :            :         struct dm_tree_node *log;       /* Mirror + Replicator */
     110                 :            :         uint32_t region_size;           /* Mirror */
     111                 :            :         unsigned clustered;             /* Mirror */
     112                 :            :         unsigned mirror_area_count;     /* Mirror */
     113                 :            :         uint32_t flags;                 /* Mirror log */
     114                 :            :         char *uuid;                     /* Clustered mirror log */
     115                 :            : 
     116                 :            :         const char *cipher;             /* Crypt */
     117                 :            :         const char *chainmode;          /* Crypt */
     118                 :            :         const char *iv;                 /* Crypt */
     119                 :            :         uint64_t iv_offset;             /* Crypt */
     120                 :            :         const char *key;                /* Crypt */
     121                 :            : 
     122                 :            :         const char *rlog_type;          /* Replicator */
     123                 :            :         struct dm_list rsites;          /* Replicator */
     124                 :            :         unsigned rsite_count;           /* Replicator */
     125                 :            :         unsigned rdevice_count;         /* Replicator */
     126                 :            :         struct dm_tree_node *replicator;/* Replicator-dev */
     127                 :            :         uint64_t rdevice_index;         /* Replicator-dev */
     128                 :            : };
     129                 :            : 
     130                 :            : /* Per-device properties */
     131                 :            : struct load_properties {
     132                 :            :         int read_only;
     133                 :            :         uint32_t major;
     134                 :            :         uint32_t minor;
     135                 :            : 
     136                 :            :         uint32_t read_ahead;
     137                 :            :         uint32_t read_ahead_flags;
     138                 :            : 
     139                 :            :         unsigned segment_count;
     140                 :            :         unsigned size_changed;
     141                 :            :         struct dm_list segs;
     142                 :            : 
     143                 :            :         const char *new_name;
     144                 :            : };
     145                 :            : 
     146                 :            : /* Two of these used to join two nodes with uses and used_by. */
     147                 :            : struct dm_tree_link {
     148                 :            :         struct dm_list list;
     149                 :            :         struct dm_tree_node *node;
     150                 :            : };
     151                 :            : 
     152                 :            : struct dm_tree_node {
     153                 :            :         struct dm_tree *dtree;
     154                 :            : 
     155                 :            :         const char *name;
     156                 :            :         const char *uuid;
     157                 :            :         struct dm_info info;
     158                 :            : 
     159                 :            :         struct dm_list uses;            /* Nodes this node uses */
     160                 :            :         struct dm_list used_by;         /* Nodes that use this node */
     161                 :            : 
     162                 :            :         int activation_priority;        /* 0 gets activated first */
     163                 :            :         int suspend_priority;           /* 1 gets suspend first */
     164                 :            : 
     165                 :            :         uint16_t udev_flags;            /* Udev control flags */
     166                 :            : 
     167                 :            :         void *context;                  /* External supplied context */
     168                 :            : 
     169                 :            :         struct load_properties props;   /* For creation/table (re)load */
     170                 :            : };
     171                 :            : 
     172                 :            : struct dm_tree {
     173                 :            :         struct dm_pool *mem;
     174                 :            :         struct dm_hash_table *devs;
     175                 :            :         struct dm_hash_table *uuids;
     176                 :            :         struct dm_tree_node root;
     177                 :            :         int skip_lockfs;                /* 1 skips lockfs (for non-snapshots) */
     178                 :            :         int no_flush;           /* 1 sets noflush (mirrors/multipath) */
     179                 :            :         uint32_t cookie;
     180                 :            : };
     181                 :            : 
     182                 :          0 : struct dm_tree *dm_tree_create(void)
     183                 :            : {
     184                 :            :         struct dm_tree *dtree;
     185                 :            : 
     186         [ #  # ]:          0 :         if (!(dtree = dm_malloc(sizeof(*dtree)))) {
     187         [ #  # ]:          0 :                 log_error("dm_tree_create malloc failed");
     188                 :          0 :                 return NULL;
     189                 :            :         }
     190                 :            : 
     191                 :          0 :         memset(dtree, 0, sizeof(*dtree));
     192                 :          0 :         dtree->root.dtree = dtree;
     193                 :          0 :         dm_list_init(&dtree->root.uses);
     194                 :          0 :         dm_list_init(&dtree->root.used_by);
     195                 :          0 :         dtree->skip_lockfs = 0;
     196                 :          0 :         dtree->no_flush = 0;
     197                 :            : 
     198         [ #  # ]:          0 :         if (!(dtree->mem = dm_pool_create("dtree", 1024))) {
     199         [ #  # ]:          0 :                 log_error("dtree pool creation failed");
     200                 :          0 :                 dm_free(dtree);
     201                 :          0 :                 return NULL;
     202                 :            :         }
     203                 :            : 
     204         [ #  # ]:          0 :         if (!(dtree->devs = dm_hash_create(8))) {
     205         [ #  # ]:          0 :                 log_error("dtree hash creation failed");
     206                 :          0 :                 dm_pool_destroy(dtree->mem);
     207                 :          0 :                 dm_free(dtree);
     208                 :          0 :                 return NULL;
     209                 :            :         }
     210                 :            : 
     211         [ #  # ]:          0 :         if (!(dtree->uuids = dm_hash_create(32))) {
     212         [ #  # ]:          0 :                 log_error("dtree uuid hash creation failed");
     213                 :          0 :                 dm_hash_destroy(dtree->devs);
     214                 :          0 :                 dm_pool_destroy(dtree->mem);
     215                 :          0 :                 dm_free(dtree);
     216                 :          0 :                 return NULL;
     217                 :            :         }
     218                 :            : 
     219                 :          0 :         return dtree;
     220                 :            : }
     221                 :            : 
     222                 :          0 : void dm_tree_free(struct dm_tree *dtree)
     223                 :            : {
     224         [ #  # ]:          0 :         if (!dtree)
     225                 :          0 :                 return;
     226                 :            : 
     227                 :          0 :         dm_hash_destroy(dtree->uuids);
     228                 :          0 :         dm_hash_destroy(dtree->devs);
     229                 :          0 :         dm_pool_destroy(dtree->mem);
     230                 :          0 :         dm_free(dtree);
     231                 :            : }
     232                 :            : 
     233                 :          0 : static int _nodes_are_linked(const struct dm_tree_node *parent,
     234                 :            :                              const struct dm_tree_node *child)
     235                 :            : {
     236                 :            :         struct dm_tree_link *dlink;
     237                 :            : 
     238         [ #  # ]:          0 :         dm_list_iterate_items(dlink, &parent->uses)
     239         [ #  # ]:          0 :                 if (dlink->node == child)
     240                 :          0 :                         return 1;
     241                 :            : 
     242                 :          0 :         return 0;
     243                 :            : }
     244                 :            : 
     245                 :          0 : static int _link(struct dm_list *list, struct dm_tree_node *node)
     246                 :            : {
     247                 :            :         struct dm_tree_link *dlink;
     248                 :            : 
     249         [ #  # ]:          0 :         if (!(dlink = dm_pool_alloc(node->dtree->mem, sizeof(*dlink)))) {
     250         [ #  # ]:          0 :                 log_error("dtree link allocation failed");
     251                 :          0 :                 return 0;
     252                 :            :         }
     253                 :            : 
     254                 :          0 :         dlink->node = node;
     255                 :          0 :         dm_list_add(list, &dlink->list);
     256                 :            : 
     257                 :          0 :         return 1;
     258                 :            : }
     259                 :            : 
     260                 :          0 : static int _link_nodes(struct dm_tree_node *parent,
     261                 :            :                        struct dm_tree_node *child)
     262                 :            : {
     263         [ #  # ]:          0 :         if (_nodes_are_linked(parent, child))
     264                 :          0 :                 return 1;
     265                 :            : 
     266         [ #  # ]:          0 :         if (!_link(&parent->uses, child))
     267                 :          0 :                 return 0;
     268                 :            : 
     269         [ #  # ]:          0 :         if (!_link(&child->used_by, parent))
     270                 :          0 :                 return 0;
     271                 :            : 
     272                 :          0 :         return 1;
     273                 :            : }
     274                 :            : 
     275                 :          0 : static void _unlink(struct dm_list *list, struct dm_tree_node *node)
     276                 :            : {
     277                 :            :         struct dm_tree_link *dlink;
     278                 :            : 
     279         [ #  # ]:          0 :         dm_list_iterate_items(dlink, list)
     280         [ #  # ]:          0 :                 if (dlink->node == node) {
     281                 :          0 :                         dm_list_del(&dlink->list);
     282                 :          0 :                         break;
     283                 :            :                 }
     284                 :          0 : }
     285                 :            : 
     286                 :          0 : static void _unlink_nodes(struct dm_tree_node *parent,
     287                 :            :                           struct dm_tree_node *child)
     288                 :            : {
     289         [ #  # ]:          0 :         if (!_nodes_are_linked(parent, child))
     290                 :          0 :                 return;
     291                 :            : 
     292                 :          0 :         _unlink(&parent->uses, child);
     293                 :          0 :         _unlink(&child->used_by, parent);
     294                 :            : }
     295                 :            : 
     296                 :          0 : static int _add_to_toplevel(struct dm_tree_node *node)
     297                 :            : {
     298                 :          0 :         return _link_nodes(&node->dtree->root, node);
     299                 :            : }
     300                 :            : 
     301                 :          0 : static void _remove_from_toplevel(struct dm_tree_node *node)
     302                 :            : {
     303                 :          0 :         _unlink_nodes(&node->dtree->root, node);
     304                 :          0 : }
     305                 :            : 
     306                 :          0 : static int _add_to_bottomlevel(struct dm_tree_node *node)
     307                 :            : {
     308                 :          0 :         return _link_nodes(node, &node->dtree->root);
     309                 :            : }
     310                 :            : 
     311                 :          0 : static void _remove_from_bottomlevel(struct dm_tree_node *node)
     312                 :            : {
     313                 :          0 :         _unlink_nodes(node, &node->dtree->root);
     314                 :          0 : }
     315                 :            : 
     316                 :          0 : static int _link_tree_nodes(struct dm_tree_node *parent, struct dm_tree_node *child)
     317                 :            : {
     318                 :            :         /* Don't link to root node if child already has a parent */
     319         [ #  # ]:          0 :         if ((parent == &parent->dtree->root)) {
     320         [ #  # ]:          0 :                 if (dm_tree_node_num_children(child, 1))
     321                 :          0 :                         return 1;
     322                 :            :         } else
     323                 :          0 :                 _remove_from_toplevel(child);
     324                 :            : 
     325         [ #  # ]:          0 :         if ((child == &child->dtree->root)) {
     326         [ #  # ]:          0 :                 if (dm_tree_node_num_children(parent, 0))
     327                 :          0 :                         return 1;
     328                 :            :         } else
     329                 :          0 :                 _remove_from_bottomlevel(parent);
     330                 :            : 
     331                 :          0 :         return _link_nodes(parent, child);
     332                 :            : }
     333                 :            : 
     334                 :          0 : static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
     335                 :            :                                                  const char *name,
     336                 :            :                                                  const char *uuid,
     337                 :            :                                                  struct dm_info *info,
     338                 :            :                                                  void *context,
     339                 :            :                                                  uint16_t udev_flags)
     340                 :            : {
     341                 :            :         struct dm_tree_node *node;
     342                 :            :         uint64_t dev;
     343                 :            : 
     344         [ #  # ]:          0 :         if (!(node = dm_pool_zalloc(dtree->mem, sizeof(*node)))) {
     345         [ #  # ]:          0 :                 log_error("_create_dm_tree_node alloc failed");
     346                 :          0 :                 return NULL;
     347                 :            :         }
     348                 :            : 
     349                 :          0 :         node->dtree = dtree;
     350                 :            : 
     351                 :          0 :         node->name = name;
     352                 :          0 :         node->uuid = uuid;
     353                 :          0 :         node->info = *info;
     354                 :          0 :         node->context = context;
     355                 :          0 :         node->udev_flags = udev_flags;
     356                 :          0 :         node->activation_priority = 0;
     357                 :            : 
     358                 :          0 :         dm_list_init(&node->uses);
     359                 :          0 :         dm_list_init(&node->used_by);
     360                 :          0 :         dm_list_init(&node->props.segs);
     361                 :            : 
     362                 :          0 :         dev = MKDEV(info->major, info->minor);
     363                 :            : 
     364         [ #  # ]:          0 :         if (!dm_hash_insert_binary(dtree->devs, (const char *) &dev,
     365                 :            :                                 sizeof(dev), node)) {
     366         [ #  # ]:          0 :                 log_error("dtree node hash insertion failed");
     367                 :          0 :                 dm_pool_free(dtree->mem, node);
     368                 :          0 :                 return NULL;
     369                 :            :         }
     370                 :            : 
     371         [ #  # ]:          0 :         if (uuid && *uuid &&
           [ #  #  #  # ]
     372                 :          0 :             !dm_hash_insert(dtree->uuids, uuid, node)) {
     373         [ #  # ]:          0 :                 log_error("dtree uuid hash insertion failed");
     374                 :          0 :                 dm_hash_remove_binary(dtree->devs, (const char *) &dev,
     375                 :            :                                       sizeof(dev));
     376                 :          0 :                 dm_pool_free(dtree->mem, node);
     377                 :          0 :                 return NULL;
     378                 :            :         }
     379                 :            : 
     380                 :          0 :         return node;
     381                 :            : }
     382                 :            : 
     383                 :          0 : static struct dm_tree_node *_find_dm_tree_node(struct dm_tree *dtree,
     384                 :            :                                                uint32_t major, uint32_t minor)
     385                 :            : {
     386                 :          0 :         uint64_t dev = MKDEV(major, minor);
     387                 :            : 
     388                 :          0 :         return dm_hash_lookup_binary(dtree->devs, (const char *) &dev,
     389                 :            :                                   sizeof(dev));
     390                 :            : }
     391                 :            : 
     392                 :          0 : static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
     393                 :            :                                                        const char *uuid)
     394                 :            : {
     395                 :            :         struct dm_tree_node *node;
     396                 :            : 
     397                 :            :         struct dm_hash_node *n;
     398         [ #  # ]:          0 :         log_verbose("HASHLOOKUP %s", uuid);
     399         [ #  # ]:          0 :         dm_hash_iterate(n, dtree->uuids) {
     400         [ #  # ]:          0 :                 log_verbose("HASH %s  %p", dm_hash_get_key(dtree->uuids, n),
     401                 :            :                             dm_hash_get_data(dtree->uuids, n));
     402                 :            :         }
     403                 :            : 
     404         [ #  # ]:          0 :         if ((node = dm_hash_lookup(dtree->uuids, uuid)))
     405                 :          0 :                 return node;
     406                 :            : 
     407         [ #  # ]:          0 :         if (strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
     408                 :          0 :                 return NULL;
     409                 :            : 
     410                 :          0 :         return dm_hash_lookup(dtree->uuids, uuid + sizeof(UUID_PREFIX) - 1);
     411                 :            : }
     412                 :            : 
     413                 :          0 : static int _deps(struct dm_task **dmt, struct dm_pool *mem, uint32_t major, uint32_t minor,
     414                 :            :                  const char **name, const char **uuid,
     415                 :            :                  struct dm_info *info, struct dm_deps **deps)
     416                 :            : {
     417                 :          0 :         memset(info, 0, sizeof(*info));
     418                 :            : 
     419         [ #  # ]:          0 :         if (!dm_is_dm_major(major)) {
     420                 :          0 :                 *name = "";
     421                 :          0 :                 *uuid = "";
     422                 :          0 :                 *deps = NULL;
     423                 :          0 :                 info->major = major;
     424                 :          0 :                 info->minor = minor;
     425                 :          0 :                 info->exists = 0;
     426                 :          0 :                 info->live_table = 0;
     427                 :          0 :                 info->inactive_table = 0;
     428                 :          0 :                 info->read_only = 0;
     429                 :          0 :                 return 1;
     430                 :            :         }
     431                 :            : 
     432         [ #  # ]:          0 :         if (!(*dmt = dm_task_create(DM_DEVICE_DEPS))) {
     433         [ #  # ]:          0 :                 log_error("deps dm_task creation failed");
     434                 :          0 :                 return 0;
     435                 :            :         }
     436                 :            : 
     437         [ #  # ]:          0 :         if (!dm_task_set_major(*dmt, major)) {
     438         [ #  # ]:          0 :                 log_error("_deps: failed to set major for (%" PRIu32 ":%" PRIu32 ")",
     439                 :            :                           major, minor);
     440                 :          0 :                 goto failed;
     441                 :            :         }
     442                 :            : 
     443         [ #  # ]:          0 :         if (!dm_task_set_minor(*dmt, minor)) {
     444         [ #  # ]:          0 :                 log_error("_deps: failed to set minor for (%" PRIu32 ":%" PRIu32 ")",
     445                 :            :                           major, minor);
     446                 :          0 :                 goto failed;
     447                 :            :         }
     448                 :            : 
     449         [ #  # ]:          0 :         if (!dm_task_run(*dmt)) {
     450         [ #  # ]:          0 :                 log_error("_deps: task run failed for (%" PRIu32 ":%" PRIu32 ")",
     451                 :            :                           major, minor);
     452                 :          0 :                 goto failed;
     453                 :            :         }
     454                 :            : 
     455         [ #  # ]:          0 :         if (!dm_task_get_info(*dmt, info)) {
     456         [ #  # ]:          0 :                 log_error("_deps: failed to get info for (%" PRIu32 ":%" PRIu32 ")",
     457                 :            :                           major, minor);
     458                 :          0 :                 goto failed;
     459                 :            :         }
     460                 :            : 
     461         [ #  # ]:          0 :         if (!info->exists) {
     462                 :          0 :                 *name = "";
     463                 :          0 :                 *uuid = "";
     464                 :          0 :                 *deps = NULL;
     465                 :            :         } else {
     466         [ #  # ]:          0 :                 if (info->major != major) {
     467         [ #  # ]:          0 :                         log_error("Inconsistent dtree major number: %u != %u",
     468                 :            :                                   major, info->major);
     469                 :          0 :                         goto failed;
     470                 :            :                 }
     471         [ #  # ]:          0 :                 if (info->minor != minor) {
     472         [ #  # ]:          0 :                         log_error("Inconsistent dtree minor number: %u != %u",
     473                 :            :                                   minor, info->minor);
     474                 :          0 :                         goto failed;
     475                 :            :                 }
     476         [ #  # ]:          0 :                 if (!(*name = dm_pool_strdup(mem, dm_task_get_name(*dmt)))) {
     477         [ #  # ]:          0 :                         log_error("name pool_strdup failed");
     478                 :          0 :                         goto failed;
     479                 :            :                 }
     480         [ #  # ]:          0 :                 if (!(*uuid = dm_pool_strdup(mem, dm_task_get_uuid(*dmt)))) {
     481         [ #  # ]:          0 :                         log_error("uuid pool_strdup failed");
     482                 :          0 :                         goto failed;
     483                 :            :                 }
     484                 :          0 :                 *deps = dm_task_get_deps(*dmt);
     485                 :            :         }
     486                 :            : 
     487                 :          0 :         return 1;
     488                 :            : 
     489                 :            : failed:
     490                 :          0 :         dm_task_destroy(*dmt);
     491                 :          0 :         return 0;
     492                 :            : }
     493                 :            : 
     494                 :          0 : static struct dm_tree_node *_add_dev(struct dm_tree *dtree,
     495                 :            :                                      struct dm_tree_node *parent,
     496                 :            :                                      uint32_t major, uint32_t minor,
     497                 :            :                                      uint16_t udev_flags)
     498                 :            : {
     499                 :          0 :         struct dm_task *dmt = NULL;
     500                 :            :         struct dm_info info;
     501                 :          0 :         struct dm_deps *deps = NULL;
     502                 :          0 :         const char *name = NULL;
     503                 :          0 :         const char *uuid = NULL;
     504                 :          0 :         struct dm_tree_node *node = NULL;
     505                 :            :         uint32_t i;
     506                 :          0 :         int new = 0;
     507                 :            : 
     508                 :            :         /* Already in tree? */
     509         [ #  # ]:          0 :         if (!(node = _find_dm_tree_node(dtree, major, minor))) {
     510         [ #  # ]:          0 :                 if (!_deps(&dmt, dtree->mem, major, minor, &name, &uuid, &info, &deps))
     511         [ #  # ]:          0 :                         return_NULL;
     512                 :            : 
     513         [ #  # ]:          0 :                 if (!(node = _create_dm_tree_node(dtree, name, uuid, &info,
     514                 :            :                                                   NULL, udev_flags)))
     515         [ #  # ]:          0 :                         goto_out;
     516                 :          0 :                 new = 1;
     517                 :            :         }
     518                 :            : 
     519         [ #  # ]:          0 :         if (!_link_tree_nodes(parent, node)) {
     520                 :          0 :                 node = NULL;
     521         [ #  # ]:          0 :                 goto_out;
     522                 :            :         }
     523                 :            : 
     524                 :            :         /* If node was already in tree, no need to recurse. */
     525         [ #  # ]:          0 :         if (!new)
     526                 :          0 :                 goto out;
     527                 :            : 
     528                 :            :         /* Can't recurse if not a mapped device or there are no dependencies */
     529 [ #  # ][ #  # ]:          0 :         if (!node->info.exists || !deps->count) {
     530         [ #  # ]:          0 :                 if (!_add_to_bottomlevel(node)) {
     531         [ #  # ]:          0 :                         stack;
     532                 :          0 :                         node = NULL;
     533                 :            :                 }
     534                 :          0 :                 goto out;
     535                 :            :         }
     536                 :            : 
     537                 :            :         /* Add dependencies to tree */
     538         [ #  # ]:          0 :         for (i = 0; i < deps->count; i++)
     539         [ #  # ]:          0 :                 if (!_add_dev(dtree, node, MAJOR(deps->device[i]),
     540                 :          0 :                               MINOR(deps->device[i]), udev_flags)) {
     541                 :          0 :                         node = NULL;
     542         [ #  # ]:          0 :                         goto_out;
     543                 :            :                 }
     544                 :            : 
     545                 :            : out:
     546         [ #  # ]:          0 :         if (dmt)
     547                 :          0 :                 dm_task_destroy(dmt);
     548                 :            : 
     549                 :          0 :         return node;
     550                 :            : }
     551                 :            : 
     552                 :          0 : static int _node_clear_table(struct dm_tree_node *dnode)
     553                 :            : {
     554                 :            :         struct dm_task *dmt;
     555                 :            :         struct dm_info *info;
     556                 :            :         const char *name;
     557                 :            :         int r;
     558                 :            : 
     559         [ #  # ]:          0 :         if (!(info = &dnode->info)) {
     560         [ #  # ]:          0 :                 log_error("_node_clear_table failed: missing info");
     561                 :          0 :                 return 0;
     562                 :            :         }
     563                 :            : 
     564         [ #  # ]:          0 :         if (!(name = dm_tree_node_get_name(dnode))) {
     565         [ #  # ]:          0 :                 log_error("_node_clear_table failed: missing name");
     566                 :          0 :                 return 0;
     567                 :            :         }
     568                 :            : 
     569                 :            :         /* Is there a table? */
     570 [ #  # ][ #  # ]:          0 :         if (!info->exists || !info->inactive_table)
     571                 :          0 :                 return 1;
     572                 :            : 
     573         [ #  # ]:          0 :         log_verbose("Clearing inactive table %s (%" PRIu32 ":%" PRIu32 ")",
     574                 :            :                     name, info->major, info->minor);
     575                 :            : 
     576         [ #  # ]:          0 :         if (!(dmt = dm_task_create(DM_DEVICE_CLEAR))) {
     577                 :          0 :                 dm_task_destroy(dmt);
     578         [ #  # ]:          0 :                 log_error("Table clear dm_task creation failed for %s", name);
     579                 :          0 :                 return 0;
     580                 :            :         }
     581                 :            : 
     582   [ #  #  #  # ]:          0 :         if (!dm_task_set_major(dmt, info->major) ||
     583                 :          0 :             !dm_task_set_minor(dmt, info->minor)) {
     584         [ #  # ]:          0 :                 log_error("Failed to set device number for %s table clear", name);
     585                 :          0 :                 dm_task_destroy(dmt);
     586                 :          0 :                 return 0;
     587                 :            :         }
     588                 :            : 
     589                 :          0 :         r = dm_task_run(dmt);
     590                 :            : 
     591         [ #  # ]:          0 :         if (!dm_task_get_info(dmt, info)) {
     592         [ #  # ]:          0 :                 log_error("_node_clear_table failed: info missing after running task for %s", name);
     593                 :          0 :                 r = 0;
     594                 :            :         }
     595                 :            : 
     596                 :          0 :         dm_task_destroy(dmt);
     597                 :            : 
     598                 :          0 :         return r;
     599                 :            : }
     600                 :            : 
     601                 :          0 : struct dm_tree_node *dm_tree_add_new_dev(struct dm_tree *dtree,
     602                 :            :                                             const char *name,
     603                 :            :                                             const char *uuid,
     604                 :            :                                             uint32_t major, uint32_t minor,
     605                 :            :                                             int read_only,
     606                 :            :                                             int clear_inactive,
     607                 :            :                                             void *context)
     608                 :            : {
     609                 :            :         struct dm_tree_node *dnode;
     610                 :            :         struct dm_info info;
     611                 :            :         const char *name2;
     612                 :            :         const char *uuid2;
     613                 :            : 
     614                 :            :         /* Do we need to add node to tree? */
     615         [ #  # ]:          0 :         if (!(dnode = dm_tree_find_node_by_uuid(dtree, uuid))) {
     616         [ #  # ]:          0 :                 if (!(name2 = dm_pool_strdup(dtree->mem, name))) {
     617         [ #  # ]:          0 :                         log_error("name pool_strdup failed");
     618                 :          0 :                         return NULL;
     619                 :            :                 }
     620         [ #  # ]:          0 :                 if (!(uuid2 = dm_pool_strdup(dtree->mem, uuid))) {
     621         [ #  # ]:          0 :                         log_error("uuid pool_strdup failed");
     622                 :          0 :                         return NULL;
     623                 :            :                 }
     624                 :            : 
     625                 :          0 :                 info.major = 0;
     626                 :          0 :                 info.minor = 0;
     627                 :          0 :                 info.exists = 0;
     628                 :          0 :                 info.live_table = 0;
     629                 :          0 :                 info.inactive_table = 0;
     630                 :          0 :                 info.read_only = 0;
     631                 :            : 
     632         [ #  # ]:          0 :                 if (!(dnode = _create_dm_tree_node(dtree, name2, uuid2, &info,
     633                 :            :                                                    context, 0)))
     634         [ #  # ]:          0 :                         return_NULL;
     635                 :            : 
     636                 :            :                 /* Attach to root node until a table is supplied */
     637 [ #  # ][ #  # ]:          0 :                 if (!_add_to_toplevel(dnode) || !_add_to_bottomlevel(dnode))
     638         [ #  # ]:          0 :                         return_NULL;
     639                 :            : 
     640                 :          0 :                 dnode->props.major = major;
     641                 :          0 :                 dnode->props.minor = minor;
     642                 :          0 :                 dnode->props.new_name = NULL;
     643                 :          0 :                 dnode->props.size_changed = 0;
     644         [ #  # ]:          0 :         } else if (strcmp(name, dnode->name)) {
     645                 :            :                 /* Do we need to rename node? */
     646         [ #  # ]:          0 :                 if (!(dnode->props.new_name = dm_pool_strdup(dtree->mem, name))) {
     647         [ #  # ]:          0 :                         log_error("name pool_strdup failed");
     648                 :          0 :                         return 0;
     649                 :            :                 }
     650                 :            :         }
     651                 :            : 
     652                 :          0 :         dnode->props.read_only = read_only ? 1 : 0;
     653                 :          0 :         dnode->props.read_ahead = DM_READ_AHEAD_AUTO;
     654                 :          0 :         dnode->props.read_ahead_flags = 0;
     655                 :            : 
     656 [ #  # ][ #  # ]:          0 :         if (clear_inactive && !_node_clear_table(dnode))
     657         [ #  # ]:          0 :                 return_NULL;
     658                 :            : 
     659                 :          0 :         dnode->context = context;
     660                 :          0 :         dnode->udev_flags = 0;
     661                 :            : 
     662                 :          0 :         return dnode;
     663                 :            : }
     664                 :            : 
     665                 :          0 : struct dm_tree_node *dm_tree_add_new_dev_with_udev_flags(struct dm_tree *dtree,
     666                 :            :                                                          const char *name,
     667                 :            :                                                          const char *uuid,
     668                 :            :                                                          uint32_t major,
     669                 :            :                                                          uint32_t minor,
     670                 :            :                                                          int read_only,
     671                 :            :                                                          int clear_inactive,
     672                 :            :                                                          void *context,
     673                 :            :                                                          uint16_t udev_flags)
     674                 :            : {
     675                 :            :         struct dm_tree_node *node;
     676                 :            : 
     677         [ #  # ]:          0 :         if ((node = dm_tree_add_new_dev(dtree, name, uuid, major, minor, read_only,
     678                 :            :                                        clear_inactive, context)))
     679                 :          0 :                 node->udev_flags = udev_flags;
     680                 :            : 
     681                 :          0 :         return node;
     682                 :            : }
     683                 :            : 
     684                 :            : 
     685                 :          0 : void dm_tree_node_set_read_ahead(struct dm_tree_node *dnode,
     686                 :            :                                  uint32_t read_ahead,
     687                 :            :                                  uint32_t read_ahead_flags)
     688                 :            : {
     689                 :          0 :         dnode->props.read_ahead = read_ahead;
     690                 :          0 :         dnode->props.read_ahead_flags = read_ahead_flags;
     691                 :          0 : }
     692                 :            : 
     693                 :          0 : int dm_tree_set_suspend_priority(struct dm_tree *dtree, const char *uuid, int priority)
     694                 :            : {
     695                 :            :         struct dm_tree_node *dnode;
     696                 :            : 
     697         [ #  # ]:          0 :         if ((dnode = dm_tree_find_node_by_uuid(dtree, uuid))) {
     698         [ #  # ]:          0 :                 log_verbose("Setting suspend priority for %s.", dnode->name);
     699                 :          0 :                 dnode->suspend_priority = priority;
     700                 :            :         }
     701                 :            : 
     702                 :          0 :         return 1;
     703                 :            : }
     704                 :            : 
     705                 :          0 : int dm_tree_add_dev(struct dm_tree *dtree, uint32_t major, uint32_t minor)
     706                 :            : {
     707                 :          0 :         return _add_dev(dtree, &dtree->root, major, minor, 0) ? 1 : 0;
     708                 :            : }
     709                 :            : 
     710                 :          0 : int dm_tree_add_dev_with_udev_flags(struct dm_tree *dtree, uint32_t major,
     711                 :            :                                     uint32_t minor, uint16_t udev_flags)
     712                 :            : {
     713                 :          0 :         return _add_dev(dtree, &dtree->root, major, minor, udev_flags) ? 1 : 0;
     714                 :            : }
     715                 :            : 
     716                 :          0 : const char *dm_tree_node_get_name(const struct dm_tree_node *node)
     717                 :            : {
     718         [ #  # ]:          0 :         return node->info.exists ? node->name : "";
     719                 :            : }
     720                 :            : 
     721                 :          0 : const char *dm_tree_node_get_uuid(const struct dm_tree_node *node)
     722                 :            : {
     723         [ #  # ]:          0 :         return node->info.exists ? node->uuid : "";
     724                 :            : }
     725                 :            : 
     726                 :          0 : const struct dm_info *dm_tree_node_get_info(const struct dm_tree_node *node)
     727                 :            : {
     728                 :          0 :         return &node->info;
     729                 :            : }
     730                 :            : 
     731                 :          0 : void *dm_tree_node_get_context(const struct dm_tree_node *node)
     732                 :            : {
     733                 :          0 :         return node->context;
     734                 :            : }
     735                 :            : 
     736                 :          0 : int dm_tree_node_size_changed(const struct dm_tree_node *dnode)
     737                 :            : {
     738                 :          0 :         return dnode->props.size_changed;
     739                 :            : }
     740                 :            : 
     741                 :          0 : int dm_tree_node_num_children(const struct dm_tree_node *node, uint32_t inverted)
     742                 :            : {
     743         [ #  # ]:          0 :         if (inverted) {
     744         [ #  # ]:          0 :                 if (_nodes_are_linked(&node->dtree->root, node))
     745                 :          0 :                         return 0;
     746                 :          0 :                 return dm_list_size(&node->used_by);
     747                 :            :         }
     748                 :            : 
     749         [ #  # ]:          0 :         if (_nodes_are_linked(node, &node->dtree->root))
     750                 :          0 :                 return 0;
     751                 :            : 
     752                 :          0 :         return dm_list_size(&node->uses);
     753                 :            : }
     754                 :            : 
     755                 :            : /*
     756                 :            :  * Returns 1 if no prefix supplied
     757                 :            :  */
     758                 :          0 : static int _uuid_prefix_matches(const char *uuid, const char *uuid_prefix, size_t uuid_prefix_len)
     759                 :            : {
     760         [ #  # ]:          0 :         if (!uuid_prefix)
     761                 :          0 :                 return 1;
     762                 :            : 
     763         [ #  # ]:          0 :         if (!strncmp(uuid, uuid_prefix, uuid_prefix_len))
     764                 :          0 :                 return 1;
     765                 :            : 
     766                 :            :         /* Handle transition: active device uuids might be missing the prefix */
     767         [ #  # ]:          0 :         if (uuid_prefix_len <= 4)
     768                 :          0 :                 return 0;
     769                 :            : 
     770         [ #  # ]:          0 :         if (!strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
     771                 :          0 :                 return 0;
     772                 :            : 
     773         [ #  # ]:          0 :         if (strncmp(uuid_prefix, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
     774                 :          0 :                 return 0;
     775                 :            : 
     776         [ #  # ]:          0 :         if (!strncmp(uuid, uuid_prefix + sizeof(UUID_PREFIX) - 1, uuid_prefix_len - (sizeof(UUID_PREFIX) - 1)))
     777                 :          0 :                 return 1;
     778                 :            : 
     779                 :          0 :         return 0;
     780                 :            : }
     781                 :            : 
     782                 :            : /*
     783                 :            :  * Returns 1 if no children.
     784                 :            :  */
     785                 :          0 : static int _children_suspended(struct dm_tree_node *node,
     786                 :            :                                uint32_t inverted,
     787                 :            :                                const char *uuid_prefix,
     788                 :            :                                size_t uuid_prefix_len)
     789                 :            : {
     790                 :            :         struct dm_list *list;
     791                 :            :         struct dm_tree_link *dlink;
     792                 :            :         const struct dm_info *dinfo;
     793                 :            :         const char *uuid;
     794                 :            : 
     795         [ #  # ]:          0 :         if (inverted) {
     796         [ #  # ]:          0 :                 if (_nodes_are_linked(&node->dtree->root, node))
     797                 :          0 :                         return 1;
     798                 :          0 :                 list = &node->used_by;
     799                 :            :         } else {
     800         [ #  # ]:          0 :                 if (_nodes_are_linked(node, &node->dtree->root))
     801                 :          0 :                         return 1;
     802                 :          0 :                 list = &node->uses;
     803                 :            :         }
     804                 :            : 
     805         [ #  # ]:          0 :         dm_list_iterate_items(dlink, list) {
     806         [ #  # ]:          0 :                 if (!(uuid = dm_tree_node_get_uuid(dlink->node))) {
     807         [ #  # ]:          0 :                         stack;
     808                 :          0 :                         continue;
     809                 :            :                 }
     810                 :            : 
     811                 :            :                 /* Ignore if it doesn't belong to this VG */
     812         [ #  # ]:          0 :                 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
     813                 :          0 :                         continue;
     814                 :            : 
     815         [ #  # ]:          0 :                 if (!(dinfo = dm_tree_node_get_info(dlink->node))) {
     816         [ #  # ]:          0 :                         stack;  /* FIXME Is this normal? */
     817                 :          0 :                         return 0;
     818                 :            :                 }
     819                 :            : 
     820         [ #  # ]:          0 :                 if (!dinfo->suspended)
     821                 :          0 :                         return 0;
     822                 :            :         }
     823                 :            : 
     824                 :          0 :         return 1;
     825                 :            : }
     826                 :            : 
     827                 :            : /*
     828                 :            :  * Set major and minor to zero for root of tree.
     829                 :            :  */
     830                 :          0 : struct dm_tree_node *dm_tree_find_node(struct dm_tree *dtree,
     831                 :            :                                           uint32_t major,
     832                 :            :                                           uint32_t minor)
     833                 :            : {
     834 [ #  # ][ #  # ]:          0 :         if (!major && !minor)
     835                 :          0 :                 return &dtree->root;
     836                 :            : 
     837                 :          0 :         return _find_dm_tree_node(dtree, major, minor);
     838                 :            : }
     839                 :            : 
     840                 :            : /*
     841                 :            :  * Set uuid to NULL for root of tree.
     842                 :            :  */
     843                 :          0 : struct dm_tree_node *dm_tree_find_node_by_uuid(struct dm_tree *dtree,
     844                 :            :                                                   const char *uuid)
     845                 :            : {
     846 [ #  # ][ #  # ]:          0 :         if (!uuid || !*uuid)
     847                 :          0 :                 return &dtree->root;
     848                 :            : 
     849                 :          0 :         return _find_dm_tree_node_by_uuid(dtree, uuid);
     850                 :            : }
     851                 :            : 
     852                 :            : /*
     853                 :            :  * First time set *handle to NULL.
     854                 :            :  * Set inverted to invert the tree.
     855                 :            :  */
     856                 :          0 : struct dm_tree_node *dm_tree_next_child(void **handle,
     857                 :            :                                         const struct dm_tree_node *parent,
     858                 :            :                                         uint32_t inverted)
     859                 :            : {
     860                 :          0 :         struct dm_list **dlink = (struct dm_list **) handle;
     861                 :            :         const struct dm_list *use_list;
     862                 :            : 
     863         [ #  # ]:          0 :         if (inverted)
     864                 :          0 :                 use_list = &parent->used_by;
     865                 :            :         else
     866                 :          0 :                 use_list = &parent->uses;
     867                 :            : 
     868         [ #  # ]:          0 :         if (!*dlink)
     869                 :          0 :                 *dlink = dm_list_first(use_list);
     870                 :            :         else
     871                 :          0 :                 *dlink = dm_list_next(use_list, *dlink);
     872                 :            : 
     873         [ #  # ]:          0 :         return (*dlink) ? dm_list_item(*dlink, struct dm_tree_link)->node : NULL;
     874                 :            : }
     875                 :            : 
     876                 :            : /*
     877                 :            :  * Deactivate a device with its dependencies if the uuid prefix matches.
     878                 :            :  */
     879                 :          0 : static int _info_by_dev(uint32_t major, uint32_t minor, int with_open_count,
     880                 :            :                         struct dm_info *info)
     881                 :            : {
     882                 :            :         struct dm_task *dmt;
     883                 :            :         int r;
     884                 :            : 
     885         [ #  # ]:          0 :         if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
     886         [ #  # ]:          0 :                 log_error("_info_by_dev: dm_task creation failed");
     887                 :          0 :                 return 0;
     888                 :            :         }
     889                 :            : 
     890 [ #  # ][ #  # ]:          0 :         if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
     891         [ #  # ]:          0 :                 log_error("_info_by_dev: Failed to set device number");
     892                 :          0 :                 dm_task_destroy(dmt);
     893                 :          0 :                 return 0;
     894                 :            :         }
     895                 :            : 
     896 [ #  # ][ #  # ]:          0 :         if (!with_open_count && !dm_task_no_open_count(dmt))
     897         [ #  # ]:          0 :                 log_error("Failed to disable open_count");
     898                 :            : 
     899         [ #  # ]:          0 :         if ((r = dm_task_run(dmt)))
     900                 :          0 :                 r = dm_task_get_info(dmt, info);
     901                 :            : 
     902                 :          0 :         dm_task_destroy(dmt);
     903                 :            : 
     904                 :          0 :         return r;
     905                 :            : }
     906                 :            : 
     907                 :          0 : static int _deactivate_node(const char *name, uint32_t major, uint32_t minor,
     908                 :            :                             uint32_t *cookie, uint16_t udev_flags)
     909                 :            : {
     910                 :            :         struct dm_task *dmt;
     911                 :          0 :         int r = 0;
     912                 :            : 
     913         [ #  # ]:          0 :         log_verbose("Removing %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);
     914                 :            : 
     915         [ #  # ]:          0 :         if (!(dmt = dm_task_create(DM_DEVICE_REMOVE))) {
     916         [ #  # ]:          0 :                 log_error("Deactivation dm_task creation failed for %s", name);
     917                 :          0 :                 return 0;
     918                 :            :         }
     919                 :            : 
     920 [ #  # ][ #  # ]:          0 :         if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
     921         [ #  # ]:          0 :                 log_error("Failed to set device number for %s deactivation", name);
     922                 :          0 :                 goto out;
     923                 :            :         }
     924                 :            : 
     925         [ #  # ]:          0 :         if (!dm_task_no_open_count(dmt))
     926         [ #  # ]:          0 :                 log_error("Failed to disable open_count");
     927                 :            : 
     928         [ #  # ]:          0 :         if (!dm_task_set_cookie(dmt, cookie, udev_flags))
     929                 :          0 :                 goto out;
     930                 :            : 
     931                 :          0 :         r = dm_task_run(dmt);
     932                 :            : 
     933                 :            :         /* FIXME Until kernel returns actual name so dm-ioctl.c can handle it */
     934   [ #  #  #  # ]:          0 :         rm_dev_node(name, dmt->cookie_set &&
     935                 :          0 :                           !(udev_flags & DM_UDEV_DISABLE_DM_RULES_FLAG));
     936                 :            : 
     937                 :            :         /* FIXME Remove node from tree or mark invalid? */
     938                 :            : 
     939                 :            : out:
     940                 :          0 :         dm_task_destroy(dmt);
     941                 :            : 
     942                 :          0 :         return r;
     943                 :            : }
     944                 :            : 
     945                 :          0 : static int _rename_node(const char *old_name, const char *new_name, uint32_t major,
     946                 :            :                         uint32_t minor, uint32_t *cookie, uint16_t udev_flags)
     947                 :            : {
     948                 :            :         struct dm_task *dmt;
     949                 :          0 :         int r = 0;
     950                 :            : 
     951         [ #  # ]:          0 :         log_verbose("Renaming %s (%" PRIu32 ":%" PRIu32 ") to %s", old_name, major, minor, new_name);
     952                 :            : 
     953         [ #  # ]:          0 :         if (!(dmt = dm_task_create(DM_DEVICE_RENAME))) {
     954         [ #  # ]:          0 :                 log_error("Rename dm_task creation failed for %s", old_name);
     955                 :          0 :                 return 0;
     956                 :            :         }
     957                 :            : 
     958         [ #  # ]:          0 :         if (!dm_task_set_name(dmt, old_name)) {
     959         [ #  # ]:          0 :                 log_error("Failed to set name for %s rename.", old_name);
     960                 :          0 :                 goto out;
     961                 :            :         }
     962                 :            : 
     963         [ #  # ]:          0 :         if (!dm_task_set_newname(dmt, new_name))
     964         [ #  # ]:          0 :                 goto_out;
     965                 :            : 
     966         [ #  # ]:          0 :         if (!dm_task_no_open_count(dmt))
     967         [ #  # ]:          0 :                 log_error("Failed to disable open_count");
     968                 :            : 
     969         [ #  # ]:          0 :         if (!dm_task_set_cookie(dmt, cookie, udev_flags))
     970                 :          0 :                 goto out;
     971                 :            : 
     972                 :          0 :         r = dm_task_run(dmt);
     973                 :            : 
     974                 :            : out:
     975                 :          0 :         dm_task_destroy(dmt);
     976                 :            : 
     977                 :          0 :         return r;
     978                 :            : }
     979                 :            : 
     980                 :            : /* FIXME Merge with _suspend_node? */
     981                 :          0 : static int _resume_node(const char *name, uint32_t major, uint32_t minor,
     982                 :            :                         uint32_t read_ahead, uint32_t read_ahead_flags,
     983                 :            :                         struct dm_info *newinfo, uint32_t *cookie,
     984                 :            :                         uint16_t udev_flags)
     985                 :            : {
     986                 :            :         struct dm_task *dmt;
     987                 :          0 :         int r = 0;
     988                 :            : 
     989         [ #  # ]:          0 :         log_verbose("Resuming %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);
     990                 :            : 
     991         [ #  # ]:          0 :         if (!(dmt = dm_task_create(DM_DEVICE_RESUME))) {
     992         [ #  # ]:          0 :                 log_error("Suspend dm_task creation failed for %s", name);
     993                 :          0 :                 return 0;
     994                 :            :         }
     995                 :            : 
     996                 :            :         /* FIXME Kernel should fill in name on return instead */
     997         [ #  # ]:          0 :         if (!dm_task_set_name(dmt, name)) {
     998         [ #  # ]:          0 :                 log_error("Failed to set readahead device name for %s", name);
     999                 :          0 :                 goto out;
    1000                 :            :         }
    1001                 :            : 
    1002 [ #  # ][ #  # ]:          0 :         if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
    1003         [ #  # ]:          0 :                 log_error("Failed to set device number for %s resumption.", name);
    1004                 :          0 :                 goto out;
    1005                 :            :         }
    1006                 :            : 
    1007         [ #  # ]:          0 :         if (!dm_task_no_open_count(dmt))
    1008         [ #  # ]:          0 :                 log_error("Failed to disable open_count");
    1009                 :            : 
    1010         [ #  # ]:          0 :         if (!dm_task_set_read_ahead(dmt, read_ahead, read_ahead_flags))
    1011         [ #  # ]:          0 :                 log_error("Failed to set read ahead");
    1012                 :            : 
    1013         [ #  # ]:          0 :         if (!dm_task_set_cookie(dmt, cookie, udev_flags))
    1014                 :          0 :                 goto out;
    1015                 :            : 
    1016         [ #  # ]:          0 :         if ((r = dm_task_run(dmt)))
    1017                 :          0 :                 r = dm_task_get_info(dmt, newinfo);
    1018                 :            : 
    1019                 :            : out:
    1020                 :          0 :         dm_task_destroy(dmt);
    1021                 :            : 
    1022                 :          0 :         return r;
    1023                 :            : }
    1024                 :            : 
    1025                 :          0 : static int _suspend_node(const char *name, uint32_t major, uint32_t minor,
    1026                 :            :                          int skip_lockfs, int no_flush, struct dm_info *newinfo)
    1027                 :            : {
    1028                 :            :         struct dm_task *dmt;
    1029                 :            :         int r;
    1030                 :            : 
    1031 [ #  # ][ #  # ]:          0 :         log_verbose("Suspending %s (%" PRIu32 ":%" PRIu32 ")%s%s",
         [ #  # ][ #  # ]
                 [ #  # ]
    1032                 :            :                     name, major, minor,
    1033                 :            :                     skip_lockfs ? "" : " with filesystem sync",
    1034                 :            :                     no_flush ? "" : " with device flush");
    1035                 :            : 
    1036         [ #  # ]:          0 :         if (!(dmt = dm_task_create(DM_DEVICE_SUSPEND))) {
    1037         [ #  # ]:          0 :                 log_error("Suspend dm_task creation failed for %s", name);
    1038                 :          0 :                 return 0;
    1039                 :            :         }
    1040                 :            : 
    1041 [ #  # ][ #  # ]:          0 :         if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
    1042         [ #  # ]:          0 :                 log_error("Failed to set device number for %s suspension.", name);
    1043                 :          0 :                 dm_task_destroy(dmt);
    1044                 :          0 :                 return 0;
    1045                 :            :         }
    1046                 :            : 
    1047         [ #  # ]:          0 :         if (!dm_task_no_open_count(dmt))
    1048         [ #  # ]:          0 :                 log_error("Failed to disable open_count");
    1049                 :            : 
    1050 [ #  # ][ #  # ]:          0 :         if (skip_lockfs && !dm_task_skip_lockfs(dmt))
    1051         [ #  # ]:          0 :                 log_error("Failed to set skip_lockfs flag.");
    1052                 :            : 
    1053 [ #  # ][ #  # ]:          0 :         if (no_flush && !dm_task_no_flush(dmt))
    1054         [ #  # ]:          0 :                 log_error("Failed to set no_flush flag.");
    1055                 :            : 
    1056         [ #  # ]:          0 :         if ((r = dm_task_run(dmt)))
    1057                 :          0 :                 r = dm_task_get_info(dmt, newinfo);
    1058                 :            : 
    1059                 :          0 :         dm_task_destroy(dmt);
    1060                 :            : 
    1061                 :          0 :         return r;
    1062                 :            : }
    1063                 :            : 
    1064                 :          0 : static int _suspend_parent(struct dm_tree_node *dnode, const char *uuid_prefix,
    1065                 :            :                            size_t uuid_prefix_len)
    1066                 :            : {
    1067                 :            :         struct dm_info info;
    1068                 :            :         const struct dm_info *dinfo;
    1069                 :            :         const char *name;
    1070                 :            :         const char *uuid;
    1071                 :            :         struct dm_tree_link *dlink;
    1072                 :            : 
    1073         [ #  # ]:          0 :         dm_list_iterate_items(dlink, &dnode->uses) {
    1074         [ #  # ]:          0 :                 if (!dlink->node->suspend_priority)
    1075                 :          0 :                         continue;
    1076                 :            : 
    1077         [ #  # ]:          0 :                 if (!(uuid = dm_tree_node_get_uuid(dlink->node))) {
    1078         [ #  # ]:          0 :                         stack;
    1079                 :          0 :                         continue;
    1080                 :            :                 }
    1081                 :            :                 /* Ignore if it doesn't belong to this VG */
    1082         [ #  # ]:          0 :                 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
    1083                 :          0 :                         continue;
    1084                 :            : 
    1085         [ #  # ]:          0 :                 if (!(dinfo = dm_tree_node_get_info(dlink->node))) {
    1086         [ #  # ]:          0 :                         stack;
    1087                 :          0 :                         continue;
    1088                 :            :                 }
    1089                 :            : 
    1090         [ #  # ]:          0 :                 if (dinfo->suspended)
    1091                 :          0 :                         continue;
    1092                 :            : 
    1093         [ #  # ]:          0 :                 if (!(name = dm_tree_node_get_name(dlink->node))) {
    1094         [ #  # ]:          0 :                         stack;
    1095                 :          0 :                         continue;
    1096                 :            :                 }
    1097                 :            : 
    1098         [ #  # ]:          0 :                 if (!_suspend_node(name, dinfo->major, dinfo->minor,
    1099                 :            :                                    1, 1, &info)) {
    1100         [ #  # ]:          0 :                         log_error("Unable to suspend %s (%" PRIu32
    1101                 :            :                                   ":%" PRIu32 ").", name, dinfo->major,
    1102                 :            :                                   dinfo->minor);
    1103                 :          0 :                         return 0;
    1104                 :            :                 }
    1105                 :            :         }
    1106                 :            : 
    1107                 :          0 :         return 1;
    1108                 :            : }
    1109                 :            : 
    1110                 :            : /*
    1111                 :            :  * FIXME Don't attempt to deactivate known internal dependencies.
    1112                 :            :  */
    1113                 :          0 : static int _dm_tree_deactivate_children(struct dm_tree_node *dnode,
    1114                 :            :                                         const char *uuid_prefix,
    1115                 :            :                                         size_t uuid_prefix_len,
    1116                 :            :                                         unsigned level)
    1117                 :            : {
    1118                 :          0 :         int r = 1;
    1119                 :          0 :         void *handle = NULL;
    1120                 :          0 :         struct dm_tree_node *child = dnode;
    1121                 :            :         struct dm_info info;
    1122                 :            :         const struct dm_info *dinfo;
    1123                 :            :         const char *name;
    1124                 :            :         const char *uuid;
    1125                 :            : 
    1126         [ #  # ]:          0 :         while ((child = dm_tree_next_child(&handle, dnode, 0))) {
    1127         [ #  # ]:          0 :                 log_verbose("DEACTIVATECHILDREN %s", child->name);
    1128         [ #  # ]:          0 :                 if (!(dinfo = dm_tree_node_get_info(child))) {
    1129         [ #  # ]:          0 :                         stack;
    1130                 :          0 :                         continue;
    1131                 :            :                 }
    1132                 :            : 
    1133         [ #  # ]:          0 :                 if (!(name = dm_tree_node_get_name(child))) {
    1134         [ #  # ]:          0 :                         stack;
    1135                 :          0 :                         continue;
    1136                 :            :                 }
    1137                 :            : 
    1138         [ #  # ]:          0 :                 if (!(uuid = dm_tree_node_get_uuid(child))) {
    1139         [ #  # ]:          0 :                         stack;
    1140                 :          0 :                         continue;
    1141                 :            :                 }
    1142                 :            : 
    1143                 :            :                 /* Ignore if it doesn't belong to this VG */
    1144         [ #  # ]:          0 :                 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
    1145                 :          0 :                         continue;
    1146                 :            : 
    1147                 :            :                 /* Refresh open_count */
    1148 [ #  # ][ #  # ]:          0 :                 if (!_info_by_dev(dinfo->major, dinfo->minor, 1, &info) ||
    1149                 :          0 :                     !info.exists)
    1150                 :          0 :                         continue;
    1151                 :            : 
    1152         [ #  # ]:          0 :                 if (info.open_count) {
    1153                 :            :                         /* Only report error from (likely non-internal) dependency at top level */
    1154         [ #  # ]:          0 :                         if (!level) {
    1155         [ #  # ]:          0 :                                 log_error("Unable to deactivate open %s (%" PRIu32
    1156                 :            :                                           ":%" PRIu32 ")", name, info.major,
    1157                 :            :                                         info.minor);
    1158                 :          0 :                                 r = 0;
    1159                 :            :                         }
    1160                 :          0 :                         continue;
    1161                 :            :                 }
    1162                 :            : 
    1163         [ #  # ]:          0 :                 if (!_suspend_parent(child, uuid_prefix, uuid_prefix_len))
    1164                 :          0 :                         continue;
    1165                 :            : 
    1166         [ #  # ]:          0 :                 if (!_deactivate_node(name, info.major, info.minor,
    1167                 :          0 :                                       &child->dtree->cookie, child->udev_flags)) {
    1168         [ #  # ]:          0 :                         log_error("Unable to deactivate %s (%" PRIu32
    1169                 :            :                                   ":%" PRIu32 ")", name, info.major,
    1170                 :            :                                   info.minor);
    1171                 :          0 :                         r = 0;
    1172                 :          0 :                         continue;
    1173                 :            :                 }
    1174                 :            : 
    1175         [ #  # ]:          0 :                 if (dm_tree_node_num_children(child, 0)) {
    1176         [ #  # ]:          0 :                         if (!_dm_tree_deactivate_children(child, uuid_prefix, uuid_prefix_len, level + 1))
    1177         [ #  # ]:          0 :                                 return_0;
    1178                 :            :                 }
    1179                 :            :         }
    1180                 :            : 
    1181                 :          0 :         return r;
    1182                 :            : }
    1183                 :            : 
    1184                 :          0 : int dm_tree_deactivate_children(struct dm_tree_node *dnode,
    1185                 :            :                                    const char *uuid_prefix,
    1186                 :            :                                    size_t uuid_prefix_len)
    1187                 :            : {
    1188                 :          0 :         return _dm_tree_deactivate_children(dnode, uuid_prefix, uuid_prefix_len, 0);
    1189                 :            : }
    1190                 :            : 
    1191                 :          0 : void dm_tree_skip_lockfs(struct dm_tree_node *dnode)
    1192                 :            : {
    1193                 :          0 :         dnode->dtree->skip_lockfs = 1;
    1194                 :          0 : }
    1195                 :            : 
    1196                 :          0 : void dm_tree_use_no_flush_suspend(struct dm_tree_node *dnode)
    1197                 :            : {
    1198                 :          0 :         dnode->dtree->no_flush = 1;
    1199                 :          0 : }
    1200                 :            : 
    1201                 :          0 : int dm_tree_suspend_children(struct dm_tree_node *dnode,
    1202                 :            :                              const char *uuid_prefix,
    1203                 :            :                              size_t uuid_prefix_len)
    1204                 :            : {
    1205                 :          0 :         int r = 1;
    1206                 :          0 :         void *handle = NULL;
    1207                 :          0 :         struct dm_tree_node *child = dnode;
    1208                 :            :         struct dm_info info, newinfo;
    1209                 :            :         const struct dm_info *dinfo;
    1210                 :            :         const char *name;
    1211                 :            :         const char *uuid;
    1212                 :            : 
    1213                 :            :         /* Suspend nodes at this level of the tree */
    1214         [ #  # ]:          0 :         while ((child = dm_tree_next_child(&handle, dnode, 0))) {
    1215         [ #  # ]:          0 :                 log_verbose("SUSPENDCHILDREN %s", child->name);
    1216         [ #  # ]:          0 :                 if (!(dinfo = dm_tree_node_get_info(child))) {
    1217         [ #  # ]:          0 :                         stack;
    1218                 :          0 :                         continue;
    1219                 :            :                 }
    1220                 :            : 
    1221         [ #  # ]:          0 :                 if (!(name = dm_tree_node_get_name(child))) {
    1222         [ #  # ]:          0 :                         stack;
    1223                 :          0 :                         continue;
    1224                 :            :                 }
    1225                 :            : 
    1226         [ #  # ]:          0 :                 if (!(uuid = dm_tree_node_get_uuid(child))) {
    1227         [ #  # ]:          0 :                         stack;
    1228                 :          0 :                         continue;
    1229                 :            :                 }
    1230                 :            : 
    1231                 :            :                 /* Ignore if it doesn't belong to this VG */
    1232         [ #  # ]:          0 :                 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
    1233                 :          0 :                         continue;
    1234                 :            : 
    1235                 :            :                 /* Ensure immediate parents are already suspended */
    1236         [ #  # ]:          0 :                 if (!_children_suspended(child, 1, uuid_prefix, uuid_prefix_len))
    1237                 :          0 :                         continue;
    1238                 :            : 
    1239 [ #  # ][ #  # ]:          0 :                 if (!_info_by_dev(dinfo->major, dinfo->minor, 0, &info) ||
                 [ #  # ]
    1240                 :          0 :                     !info.exists || info.suspended)
    1241                 :          0 :                         continue;
    1242                 :            : 
    1243         [ #  # ]:          0 :                 if (!_suspend_node(name, info.major, info.minor,
    1244                 :          0 :                                    child->dtree->skip_lockfs,
    1245                 :          0 :                                    child->dtree->no_flush, &newinfo)) {
    1246         [ #  # ]:          0 :                         log_error("Unable to suspend %s (%" PRIu32
    1247                 :            :                                   ":%" PRIu32 ")", name, info.major,
    1248                 :            :                                   info.minor);
    1249                 :          0 :                         r = 0;
    1250                 :          0 :                         continue;
    1251                 :            :                 }
    1252                 :            : 
    1253                 :            :                 /* Update cached info */
    1254                 :          0 :                 child->info = newinfo;
    1255                 :            :         }
    1256                 :            : 
    1257                 :            :         /* Then suspend any child nodes */
    1258                 :          0 :         handle = NULL;
    1259                 :            : 
    1260         [ #  # ]:          0 :         while ((child = dm_tree_next_child(&handle, dnode, 0))) {
    1261         [ #  # ]:          0 :                 if (!(uuid = dm_tree_node_get_uuid(child))) {
    1262         [ #  # ]:          0 :                         stack;
    1263                 :          0 :                         continue;
    1264                 :            :                 }
    1265                 :            : 
    1266                 :            :                 /* Ignore if it doesn't belong to this VG */
    1267         [ #  # ]:          0 :                 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
    1268                 :          0 :                         continue;
    1269                 :            : 
    1270         [ #  # ]:          0 :                 if (dm_tree_node_num_children(child, 0))
    1271         [ #  # ]:          0 :                         if (!dm_tree_suspend_children(child, uuid_prefix, uuid_prefix_len))
    1272         [ #  # ]:          0 :                                 return_0;
    1273                 :            :         }
    1274                 :            : 
    1275                 :          0 :         return r;
    1276                 :            : }
    1277                 :            : 
    1278                 :          0 : int dm_tree_activate_children(struct dm_tree_node *dnode,
    1279                 :            :                                  const char *uuid_prefix,
    1280                 :            :                                  size_t uuid_prefix_len)
    1281                 :            : {
    1282                 :          0 :         int r = 1;
    1283                 :          0 :         void *handle = NULL;
    1284                 :          0 :         struct dm_tree_node *child = dnode;
    1285                 :            :         struct dm_info newinfo;
    1286                 :            :         const char *name;
    1287                 :            :         const char *uuid;
    1288                 :            :         int priority;
    1289                 :            : 
    1290                 :            :         /* Activate children first */
    1291         [ #  # ]:          0 :         while ((child = dm_tree_next_child(&handle, dnode, 0))) {
    1292         [ #  # ]:          0 :                 if (!(uuid = dm_tree_node_get_uuid(child))) {
    1293         [ #  # ]:          0 :                         stack;
    1294                 :          0 :                         continue;
    1295                 :            :                 }
    1296                 :            : 
    1297         [ #  # ]:          0 :                 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
    1298                 :          0 :                         continue;
    1299                 :            : 
    1300         [ #  # ]:          0 :                 if (dm_tree_node_num_children(child, 0))
    1301         [ #  # ]:          0 :                         if (!dm_tree_activate_children(child, uuid_prefix, uuid_prefix_len))
    1302         [ #  # ]:          0 :                                 return_0;
    1303                 :            :         }
    1304                 :            : 
    1305                 :          0 :         handle = NULL;
    1306                 :            : 
    1307         [ #  # ]:          0 :         for (priority = 0; priority < 3; priority++) {
    1308         [ #  # ]:          0 :                 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
    1309         [ #  # ]:          0 :                         if (!(uuid = dm_tree_node_get_uuid(child))) {
    1310         [ #  # ]:          0 :                                 stack;
    1311                 :          0 :                                 continue;
    1312                 :            :                         }
    1313                 :            : 
    1314         [ #  # ]:          0 :                         if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
    1315                 :          0 :                                 continue;
    1316                 :            : 
    1317         [ #  # ]:          0 :                         if (priority != child->activation_priority)
    1318                 :          0 :                                 continue;
    1319                 :            : 
    1320         [ #  # ]:          0 :                         if (!(name = dm_tree_node_get_name(child))) {
    1321         [ #  # ]:          0 :                                 stack;
    1322                 :          0 :                                 continue;
    1323                 :            :                         }
    1324                 :            : 
    1325                 :            :                         /* Rename? */
    1326         [ #  # ]:          0 :                         if (child->props.new_name) {
    1327         [ #  # ]:          0 :                                 if (!_rename_node(name, child->props.new_name, child->info.major,
    1328                 :          0 :                                                   child->info.minor, &child->dtree->cookie,
    1329                 :          0 :                                                   child->udev_flags)) {
    1330         [ #  # ]:          0 :                                         log_error("Failed to rename %s (%" PRIu32
    1331                 :            :                                                   ":%" PRIu32 ") to %s", name, child->info.major,
    1332                 :            :                                                   child->info.minor, child->props.new_name);
    1333                 :          0 :                                         return 0;
    1334                 :            :                                 }
    1335                 :          0 :                                 child->name = child->props.new_name;
    1336                 :          0 :                                 child->props.new_name = NULL;
    1337                 :            :                         }
    1338                 :            : 
    1339 [ #  # ][ #  # ]:          0 :                         if (!child->info.inactive_table && !child->info.suspended)
    1340                 :          0 :                                 continue;
    1341                 :            : 
    1342         [ #  # ]:          0 :                         log_verbose("ACTIVATERESUME %s", child->name);
    1343         [ #  # ]:          0 :                         if (!_resume_node(child->name, child->info.major, child->info.minor,
    1344                 :            :                                           child->props.read_ahead, child->props.read_ahead_flags,
    1345                 :          0 :                                           &newinfo, &child->dtree->cookie, child->udev_flags)) {
    1346         [ #  # ]:          0 :                                 log_error("Unable to resume %s (%" PRIu32
    1347                 :            :                                           ":%" PRIu32 ")", child->name, child->info.major,
    1348                 :            :                                           child->info.minor);
    1349                 :          0 :                                 r = 0;
    1350                 :          0 :                                 continue;
    1351                 :            :                         }
    1352                 :            : 
    1353                 :            :                         /* Update cached info */
    1354                 :          0 :                         child->info = newinfo;
    1355                 :            :                 }
    1356                 :            :         }
    1357                 :            : 
    1358                 :          0 :         handle = NULL;
    1359                 :            : 
    1360                 :          0 :         return r;
    1361                 :            : }
    1362                 :            : 
    1363                 :          0 : static int _create_node(struct dm_tree_node *dnode)
    1364                 :            : {
    1365                 :          0 :         int r = 0;
    1366                 :            :         struct dm_task *dmt;
    1367                 :            : 
    1368         [ #  # ]:          0 :         log_verbose("Creating %s", dnode->name);
    1369                 :            : 
    1370         [ #  # ]:          0 :         if (!(dmt = dm_task_create(DM_DEVICE_CREATE))) {
    1371         [ #  # ]:          0 :                 log_error("Create dm_task creation failed for %s", dnode->name);
    1372                 :          0 :                 return 0;
    1373                 :            :         }
    1374                 :            : 
    1375         [ #  # ]:          0 :         if (!dm_task_set_name(dmt, dnode->name)) {
    1376         [ #  # ]:          0 :                 log_error("Failed to set device name for %s", dnode->name);
    1377                 :          0 :                 goto out;
    1378                 :            :         }
    1379                 :            : 
    1380         [ #  # ]:          0 :         if (!dm_task_set_uuid(dmt, dnode->uuid)) {
    1381         [ #  # ]:          0 :                 log_error("Failed to set uuid for %s", dnode->name);
    1382                 :          0 :                 goto out;
    1383                 :            :         }
    1384                 :            : 
    1385 [ #  #  #  #  # :          0 :         if (dnode->props.major &&
                      # ]
    1386                 :          0 :             (!dm_task_set_major(dmt, dnode->props.major) ||
    1387                 :          0 :              !dm_task_set_minor(dmt, dnode->props.minor))) {
    1388         [ #  # ]:          0 :                 log_error("Failed to set device number for %s creation.", dnode->name);
    1389                 :          0 :                 goto out;
    1390                 :            :         }
    1391                 :            : 
    1392 [ #  # ][ #  # ]:          0 :         if (dnode->props.read_only && !dm_task_set_ro(dmt)) {
    1393         [ #  # ]:          0 :                 log_error("Failed to set read only flag for %s", dnode->name);
    1394                 :          0 :                 goto out;
    1395                 :            :         }
    1396                 :            : 
    1397         [ #  # ]:          0 :         if (!dm_task_no_open_count(dmt))
    1398         [ #  # ]:          0 :                 log_error("Failed to disable open_count");
    1399                 :            : 
    1400         [ #  # ]:          0 :         if ((r = dm_task_run(dmt)))
    1401                 :          0 :                 r = dm_task_get_info(dmt, &dnode->info);
    1402                 :            : 
    1403                 :            : out:
    1404                 :          0 :         dm_task_destroy(dmt);
    1405                 :            : 
    1406                 :          0 :         return r;
    1407                 :            : }
    1408                 :            : 
    1409                 :            : 
    1410                 :          0 : static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *node)
    1411                 :            : {
    1412         [ #  # ]:          0 :         if (!dm_format_dev(devbuf, bufsize, node->info.major, node->info.minor)) {
    1413         [ #  # ]:          0 :                 log_error("Failed to format %s device number for %s as dm "
    1414                 :            :                           "target (%u,%u)",
    1415                 :            :                           node->name, node->uuid, node->info.major, node->info.minor);
    1416                 :          0 :                 return 0;
    1417                 :            :         }
    1418                 :            : 
    1419                 :          0 :         return 1;
    1420                 :            : }
    1421                 :            : 
    1422                 :            : /* simplify string emiting code */
    1423                 :            : #define EMIT_PARAMS(p, str...)\
    1424                 :            : do {\
    1425                 :            :         int w;\
    1426                 :            :         if ((w = dm_snprintf(params + p, paramsize - (size_t) p, str)) < 0) {\
    1427                 :            :                 stack; /* Out of space */\
    1428                 :            :                 return -1;\
    1429                 :            :         }\
    1430                 :            :         p += w;\
    1431                 :            : } while (0)
    1432                 :            : 
    1433                 :            : /*
    1434                 :            :  * _emit_areas_line
    1435                 :            :  *
    1436                 :            :  * Returns: 1 on success, 0 on failure
    1437                 :            :  */
    1438                 :          0 : static int _emit_areas_line(struct dm_task *dmt __attribute((unused)),
    1439                 :            :                             struct load_segment *seg, char *params,
    1440                 :            :                             size_t paramsize, int *pos)
    1441                 :            : {
    1442                 :            :         struct seg_area *area;
    1443                 :            :         char devbuf[DM_FORMAT_DEV_BUFSIZE];
    1444                 :          0 :         unsigned first_time = 1;
    1445                 :            :         const char *logtype;
    1446                 :            :         unsigned log_parm_count;
    1447                 :            : 
    1448         [ #  # ]:          0 :         dm_list_iterate_items(area, &seg->areas) {
    1449         [ #  # ]:          0 :                 if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node))
    1450         [ #  # ]:          0 :                         return_0;
    1451                 :            : 
    1452         [ #  # ]:          0 :                 switch (seg->type) {
    1453                 :            :                 case SEG_REPLICATOR_DEV:
    1454 [ #  # ][ #  # ]:          0 :                         EMIT_PARAMS(*pos, " %d 1 %s", area->rsite_index, devbuf);
    1455         [ #  # ]:          0 :                         if (first_time)
    1456 [ #  # ][ #  # ]:          0 :                                 EMIT_PARAMS(*pos, " nolog 0");
    1457                 :            :                         else {
    1458                 :            :                                 /* Remote devices */
    1459         [ #  # ]:          0 :                                 log_parm_count = (area->flags &
    1460                 :            :                                                   (DM_NOSYNC | DM_FORCESYNC)) ? 2 : 1;
    1461                 :            : 
    1462         [ #  # ]:          0 :                                 if (!area->slog) {
    1463                 :          0 :                                         devbuf[0] = 0;          /* Only core log parameters */
    1464                 :          0 :                                         logtype = "core";
    1465                 :            :                                 } else {
    1466                 :          0 :                                         devbuf[0] = ' ';        /* Extra space before device name */
    1467         [ #  # ]:          0 :                                         if (!_build_dev_string(devbuf + 1,
    1468                 :            :                                                                sizeof(devbuf) - 1,
    1469                 :            :                                                                area->slog))
    1470         [ #  # ]:          0 :                                                 return_0;
    1471                 :          0 :                                         logtype = "disk";
    1472                 :          0 :                                         log_parm_count++;       /* Extra sync log device name parameter */
    1473                 :            :                                 }
    1474                 :            : 
    1475 [ #  # ][ #  # ]:          0 :                                 EMIT_PARAMS(*pos, " %s %u%s %" PRIu64, logtype,
    1476                 :            :                                             log_parm_count, devbuf, area->region_size);
    1477                 :            : 
    1478 [ #  # ][ #  # ]:          0 :                                 logtype = (area->flags & DM_NOSYNC) ?
    1479                 :          0 :                                         " nosync" : (area->flags & DM_FORCESYNC) ?
    1480                 :            :                                         " sync" : NULL;
    1481                 :            : 
    1482         [ #  # ]:          0 :                                 if (logtype)
    1483 [ #  # ][ #  # ]:          0 :                                         EMIT_PARAMS(*pos, logtype);
    1484                 :            :                         }
    1485                 :          0 :                         break;
    1486                 :            :                 default:
    1487 [ #  # ][ #  # ]:          0 :                         EMIT_PARAMS(*pos, "%s%s %" PRIu64, first_time ? "" : " ",
                 [ #  # ]
    1488                 :            :                                     devbuf, area->offset);
    1489                 :            :                 }
    1490                 :            : 
    1491                 :          0 :                 first_time = 0;
    1492                 :            :         }
    1493                 :            : 
    1494                 :          0 :         return 1;
    1495                 :            : }
    1496                 :            : 
    1497                 :          0 : static int _replicator_emit_segment_line(const struct load_segment *seg, char *params,
    1498                 :            :                                          size_t paramsize, int *pos)
    1499                 :            : {
    1500                 :            :         const struct load_segment *rlog_seg;
    1501                 :            :         struct replicator_site *rsite;
    1502                 :            :         char rlogbuf[DM_FORMAT_DEV_BUFSIZE];
    1503                 :            :         unsigned parm_count;
    1504                 :            : 
    1505 [ #  # ][ #  # ]:          0 :         if (!seg->log || !_build_dev_string(rlogbuf, sizeof(rlogbuf), seg->log))
    1506         [ #  # ]:          0 :                 return_0;
    1507                 :            : 
    1508                 :          0 :         rlog_seg = dm_list_item(dm_list_last(&seg->log->props.segs),
    1509                 :            :                                 struct load_segment);
    1510                 :            : 
    1511   [ #  #  #  # ]:          0 :         EMIT_PARAMS(*pos, "%s 4 %s 0 auto %" PRIu64,
    1512                 :            :                     seg->rlog_type, rlogbuf, rlog_seg->size);
    1513                 :            : 
    1514         [ #  # ]:          0 :         dm_list_iterate_items(rsite, &seg->rsites) {
    1515 [ #  # ][ #  # ]:          0 :                 parm_count = (rsite->fall_behind_data
                 [ #  # ]
    1516                 :          0 :                               || rsite->fall_behind_ios
    1517                 :          0 :                               || rsite->async_timeout) ? 4 : 2;
    1518                 :            : 
    1519 [ #  # ][ #  # ]:          0 :                 EMIT_PARAMS(*pos, " blockdev %u %u %s", parm_count, rsite->rsite_index,
                 [ #  # ]
    1520                 :            :                             (rsite->mode == DM_REPLICATOR_SYNC) ? "synchronous" : "asynchronous");
    1521                 :            : 
    1522         [ #  # ]:          0 :                 if (rsite->fall_behind_data)
    1523 [ #  # ][ #  # ]:          0 :                         EMIT_PARAMS(*pos, " data %" PRIu64, rsite->fall_behind_data);
    1524         [ #  # ]:          0 :                 else if (rsite->fall_behind_ios)
    1525 [ #  # ][ #  # ]:          0 :                         EMIT_PARAMS(*pos, " ios %" PRIu32, rsite->fall_behind_ios);
    1526         [ #  # ]:          0 :                 else if (rsite->async_timeout)
    1527 [ #  # ][ #  # ]:          0 :                         EMIT_PARAMS(*pos, " timeout %" PRIu32, rsite->async_timeout);
    1528                 :            :         }
    1529                 :            : 
    1530                 :          0 :         return 1;
    1531                 :            : }
    1532                 :            : 
    1533                 :            : /*
    1534                 :            :  * Returns: 1 on success, 0 on failure
    1535                 :            :  */
    1536                 :          0 : static int _mirror_emit_segment_line(struct dm_task *dmt, uint32_t major,
    1537                 :            :                                      uint32_t minor, struct load_segment *seg,
    1538                 :            :                                      uint64_t *seg_start, char *params,
    1539                 :            :                                      size_t paramsize)
    1540                 :            : {
    1541                 :            :         int r;
    1542                 :          0 :         int block_on_error = 0;
    1543                 :          0 :         int handle_errors = 0;
    1544                 :          0 :         int dm_log_userspace = 0;
    1545                 :            :         struct utsname uts;
    1546                 :            :         unsigned log_parm_count;
    1547                 :          0 :         int pos = 0;
    1548                 :            :         char logbuf[DM_FORMAT_DEV_BUFSIZE];
    1549                 :            :         const char *logtype;
    1550                 :            : 
    1551                 :          0 :         r = uname(&uts);
    1552         [ #  # ]:          0 :         if (r)
    1553         [ #  # ]:          0 :                 return_0;
    1554                 :            : 
    1555         [ #  # ]:          0 :         if ((seg->flags & DM_BLOCK_ON_ERROR)) {
    1556                 :            :                 /*
    1557                 :            :                  * Originally, block_on_error was an argument to the log
    1558                 :            :                  * portion of the mirror CTR table.  It was renamed to
    1559                 :            :                  * "handle_errors" and now resides in the 'features'
    1560                 :            :                  * section of the mirror CTR table (i.e. at the end).
    1561                 :            :                  *
    1562                 :            :                  * We can identify whether to use "block_on_error" or
    1563                 :            :                  * "handle_errors" by the dm-mirror module's version
    1564                 :            :                  * number (>= 1.12) or by the kernel version (>= 2.6.22).
    1565                 :            :                  */
    1566         [ #  # ]:          0 :                 if (strncmp(uts.release, "2.6.22", 6) >= 0)
    1567                 :          0 :                         handle_errors = 1;
    1568                 :            :                 else
    1569                 :          0 :                         block_on_error = 1;
    1570                 :            :         }
    1571                 :            : 
    1572         [ #  # ]:          0 :         if (seg->clustered) {
    1573                 :            :                 /* Cluster mirrors require a UUID */
    1574         [ #  # ]:          0 :                 if (!seg->uuid)
    1575         [ #  # ]:          0 :                         return_0;
    1576                 :            : 
    1577                 :            :                 /*
    1578                 :            :                  * Cluster mirrors used to have their own log
    1579                 :            :                  * types.  Now they are accessed through the
    1580                 :            :                  * userspace log type.
    1581                 :            :                  *
    1582                 :            :                  * The dm-log-userspace module was added to the
    1583                 :            :                  * 2.6.31 kernel.
    1584                 :            :                  */
    1585         [ #  # ]:          0 :                 if (strncmp(uts.release, "2.6.31", 6) >= 0)
    1586                 :          0 :                         dm_log_userspace = 1;
    1587                 :            :         }
    1588                 :            : 
    1589                 :            :         /* Region size */
    1590                 :          0 :         log_parm_count = 1;
    1591                 :            : 
    1592                 :            :         /* [no]sync, block_on_error etc. */
    1593                 :          0 :         log_parm_count += hweight32(seg->flags);
    1594                 :            : 
    1595                 :            :         /* "handle_errors" is a feature arg now */
    1596         [ #  # ]:          0 :         if (handle_errors)
    1597                 :          0 :                 log_parm_count--;
    1598                 :            : 
    1599                 :            :         /* DM_CORELOG does not count in the param list */
    1600         [ #  # ]:          0 :         if (seg->flags & DM_CORELOG)
    1601                 :          0 :                 log_parm_count--;
    1602                 :            : 
    1603         [ #  # ]:          0 :         if (seg->clustered) {
    1604                 :          0 :                 log_parm_count++; /* For UUID */
    1605                 :            : 
    1606         [ #  # ]:          0 :                 if (!dm_log_userspace)
    1607 [ #  # ][ #  # ]:          0 :                         EMIT_PARAMS(pos, "clustered-");
    1608                 :            :                 else
    1609                 :            :                         /* For clustered-* type field inserted later */
    1610                 :          0 :                         log_parm_count++;
    1611                 :            :         }
    1612                 :            : 
    1613         [ #  # ]:          0 :         if (!seg->log)
    1614                 :          0 :                 logtype = "core";
    1615                 :            :         else {
    1616                 :          0 :                 logtype = "disk";
    1617                 :          0 :                 log_parm_count++;
    1618         [ #  # ]:          0 :                 if (!_build_dev_string(logbuf, sizeof(logbuf), seg->log))
    1619         [ #  # ]:          0 :                         return_0;
    1620                 :            :         }
    1621                 :            : 
    1622         [ #  # ]:          0 :         if (dm_log_userspace)
    1623 [ #  # ][ #  # ]:          0 :                 EMIT_PARAMS(pos, "userspace %u %s clustered-%s",
    1624                 :            :                             log_parm_count, seg->uuid, logtype);
    1625                 :            :         else
    1626 [ #  # ][ #  # ]:          0 :                 EMIT_PARAMS(pos, "%s %u", logtype, log_parm_count);
    1627                 :            : 
    1628         [ #  # ]:          0 :         if (seg->log)
    1629 [ #  # ][ #  # ]:          0 :                 EMIT_PARAMS(pos, " %s", logbuf);
    1630                 :            : 
    1631 [ #  # ][ #  # ]:          0 :         EMIT_PARAMS(pos, " %u", seg->region_size);
    1632                 :            : 
    1633 [ #  # ][ #  # ]:          0 :         if (seg->clustered && !dm_log_userspace)
    1634 [ #  # ][ #  # ]:          0 :                 EMIT_PARAMS(pos, " %s", seg->uuid);
    1635                 :            : 
    1636         [ #  # ]:          0 :         if ((seg->flags & DM_NOSYNC))
    1637 [ #  # ][ #  # ]:          0 :                 EMIT_PARAMS(pos, " nosync");
    1638         [ #  # ]:          0 :         else if ((seg->flags & DM_FORCESYNC))
    1639 [ #  # ][ #  # ]:          0 :                 EMIT_PARAMS(pos, " sync");
    1640                 :            : 
    1641         [ #  # ]:          0 :         if (block_on_error)
    1642 [ #  # ][ #  # ]:          0 :                 EMIT_PARAMS(pos, " block_on_error");
    1643                 :            : 
    1644 [ #  # ][ #  # ]:          0 :         EMIT_PARAMS(pos, " %u ", seg->mirror_area_count);
    1645                 :            : 
    1646         [ #  # ]:          0 :         if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0)
    1647         [ #  # ]:          0 :                 return_0;
    1648                 :            : 
    1649         [ #  # ]:          0 :         if (handle_errors)
    1650 [ #  # ][ #  # ]:          0 :                 EMIT_PARAMS(pos, " 1 handle_errors");
    1651                 :            : 
    1652                 :          0 :         return 1;
    1653                 :            : }
    1654                 :            : 
    1655                 :          0 : static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
    1656                 :            :                               uint32_t minor, struct load_segment *seg,
    1657                 :            :                               uint64_t *seg_start, char *params,
    1658                 :            :                               size_t paramsize)
    1659                 :            : {
    1660                 :          0 :         int pos = 0;
    1661                 :            :         int r;
    1662                 :            :         char originbuf[DM_FORMAT_DEV_BUFSIZE], cowbuf[DM_FORMAT_DEV_BUFSIZE];
    1663                 :            : 
    1664 [ #  #  #  #  # :          0 :         switch(seg->type) {
             #  #  #  # ]
    1665                 :            :         case SEG_ERROR:
    1666                 :            :         case SEG_ZERO:
    1667                 :            :         case SEG_LINEAR:
    1668                 :          0 :                 break;
    1669                 :            :         case SEG_MIRRORED:
    1670                 :            :                 /* Mirrors are pretty complicated - now in separate function */
    1671                 :          0 :                 r = _mirror_emit_segment_line(dmt, major, minor, seg, seg_start,
    1672                 :            :                                               params, paramsize);
    1673         [ #  # ]:          0 :                 if (!r)
    1674         [ #  # ]:          0 :                         return_0;
    1675                 :          0 :                 break;
    1676                 :            :         case SEG_REPLICATOR:
    1677         [ #  # ]:          0 :                 if ((r = _replicator_emit_segment_line(seg, params, paramsize,
    1678                 :            :                                                        &pos)) <= 0) {
    1679         [ #  # ]:          0 :                         stack;
    1680                 :          0 :                         return r;
    1681                 :            :                 }
    1682                 :          0 :                 break;
    1683                 :            :         case SEG_REPLICATOR_DEV:
    1684 [ #  # ][ #  # ]:          0 :                 if (!seg->replicator || !_build_dev_string(originbuf,
    1685                 :            :                                                            sizeof(originbuf),
    1686                 :            :                                                            seg->replicator))
    1687         [ #  # ]:          0 :                         return_0;
    1688                 :            : 
    1689 [ #  # ][ #  # ]:          0 :                 EMIT_PARAMS(pos, "%s %" PRIu64, originbuf, seg->rdevice_index);
    1690                 :          0 :                 break;
    1691                 :            :         case SEG_SNAPSHOT:
    1692                 :            :         case SEG_SNAPSHOT_MERGE:
    1693         [ #  # ]:          0 :                 if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
    1694         [ #  # ]:          0 :                         return_0;
    1695         [ #  # ]:          0 :                 if (!_build_dev_string(cowbuf, sizeof(cowbuf), seg->cow))
    1696         [ #  # ]:          0 :                         return_0;
    1697 [ #  # ][ #  # ]:          0 :                 EMIT_PARAMS(pos, "%s %s %c %d", originbuf, cowbuf,
                 [ #  # ]
    1698                 :            :                             seg->persistent ? 'P' : 'N', seg->chunk_size);
    1699                 :          0 :                 break;
    1700                 :            :         case SEG_SNAPSHOT_ORIGIN:
    1701         [ #  # ]:          0 :                 if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
    1702         [ #  # ]:          0 :                         return_0;
    1703 [ #  # ][ #  # ]:          0 :                 EMIT_PARAMS(pos, "%s", originbuf);
    1704                 :          0 :                 break;
    1705                 :            :         case SEG_STRIPED:
    1706 [ #  # ][ #  # ]:          0 :                 EMIT_PARAMS(pos, "%u %u ", seg->area_count, seg->stripe_size);
    1707                 :          0 :                 break;
    1708                 :            :         case SEG_CRYPT:
    1709 [ #  # ][ #  # ]:          0 :                 EMIT_PARAMS(pos, "%s%s%s%s%s %s %" PRIu64 " ", seg->cipher,
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1710                 :            :                             seg->chainmode ? "-" : "", seg->chainmode ?: "",
    1711                 :            :                             seg->iv ? "-" : "", seg->iv ?: "", seg->key,
    1712                 :            :                             seg->iv_offset != DM_CRYPT_IV_DEFAULT ?
    1713                 :            :                             seg->iv_offset : *seg_start);
    1714                 :            :                 break;
    1715                 :            :         }
    1716                 :            : 
    1717      [ #  #  # ]:          0 :         switch(seg->type) {
    1718                 :            :         case SEG_ERROR:
    1719                 :            :         case SEG_REPLICATOR:
    1720                 :            :         case SEG_SNAPSHOT:
    1721                 :            :         case SEG_SNAPSHOT_ORIGIN:
    1722                 :            :         case SEG_SNAPSHOT_MERGE:
    1723                 :            :         case SEG_ZERO:
    1724                 :          0 :                 break;
    1725                 :            :         case SEG_CRYPT:
    1726                 :            :         case SEG_LINEAR:
    1727                 :            :         case SEG_REPLICATOR_DEV:
    1728                 :            :         case SEG_STRIPED:
    1729         [ #  # ]:          0 :                 if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) {
    1730         [ #  # ]:          0 :                         stack;
    1731                 :          0 :                         return r;
    1732                 :            :                 }
    1733                 :            :                 break;
    1734                 :            :         }
    1735                 :            : 
    1736         [ #  # ]:          0 :         log_debug("Adding target to (%" PRIu32 ":%" PRIu32 "): %" PRIu64
    1737                 :            :                   " %" PRIu64 " %s %s", major, minor,
    1738                 :            :                   *seg_start, seg->size, dm_segtypes[seg->type].target, params);
    1739                 :            : 
    1740         [ #  # ]:          0 :         if (!dm_task_add_target(dmt, *seg_start, seg->size, dm_segtypes[seg->type].target, params))
    1741         [ #  # ]:          0 :                 return_0;
    1742                 :            : 
    1743                 :          0 :         *seg_start += seg->size;
    1744                 :            : 
    1745                 :          0 :         return 1;
    1746                 :            : }
    1747                 :            : 
    1748                 :            : #undef EMIT_PARAMS
    1749                 :            : 
    1750                 :          0 : static int _emit_segment(struct dm_task *dmt, uint32_t major, uint32_t minor,
    1751                 :            :                          struct load_segment *seg, uint64_t *seg_start)
    1752                 :            : {
    1753                 :            :         char *params;
    1754                 :          0 :         size_t paramsize = 4096;
    1755                 :            :         int ret;
    1756                 :            : 
    1757                 :            :         do {
    1758         [ #  # ]:          0 :                 if (!(params = dm_malloc(paramsize))) {
    1759         [ #  # ]:          0 :                         log_error("Insufficient space for target parameters.");
    1760                 :          0 :                         return 0;
    1761                 :            :                 }
    1762                 :            : 
    1763                 :          0 :                 params[0] = '\0';
    1764                 :          0 :                 ret = _emit_segment_line(dmt, major, minor, seg, seg_start,
    1765                 :            :                                          params, paramsize);
    1766                 :          0 :                 dm_free(params);
    1767                 :            : 
    1768         [ #  # ]:          0 :                 if (!ret)
    1769         [ #  # ]:          0 :                         stack;
    1770                 :            : 
    1771         [ #  # ]:          0 :                 if (ret >= 0)
    1772                 :          0 :                         return ret;
    1773                 :            : 
    1774         [ #  # ]:          0 :                 log_debug("Insufficient space in params[%" PRIsize_t
    1775                 :            :                           "] for target parameters.", paramsize);
    1776                 :            : 
    1777                 :          0 :                 paramsize *= 2;
    1778         [ #  # ]:          0 :         } while (paramsize < MAX_TARGET_PARAMSIZE);
    1779                 :            : 
    1780         [ #  # ]:          0 :         log_error("Target parameter size too big. Aborting.");
    1781                 :          0 :         return 0;
    1782                 :            : }
    1783                 :            : 
    1784                 :          0 : static int _load_node(struct dm_tree_node *dnode)
    1785                 :            : {
    1786                 :          0 :         int r = 0;
    1787                 :            :         struct dm_task *dmt;
    1788                 :            :         struct load_segment *seg;
    1789                 :          0 :         uint64_t seg_start = 0;
    1790                 :            : 
    1791         [ #  # ]:          0 :         log_verbose("Loading %s table (%" PRIu32 ":%" PRIu32 ")", dnode->name,
    1792                 :            :                     dnode->info.major, dnode->info.minor);
    1793                 :            : 
    1794         [ #  # ]:          0 :         if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) {
    1795         [ #  # ]:          0 :                 log_error("Reload dm_task creation failed for %s", dnode->name);
    1796                 :          0 :                 return 0;
    1797                 :            :         }
    1798                 :            : 
    1799   [ #  #  #  # ]:          0 :         if (!dm_task_set_major(dmt, dnode->info.major) ||
    1800                 :          0 :             !dm_task_set_minor(dmt, dnode->info.minor)) {
    1801         [ #  # ]:          0 :                 log_error("Failed to set device number for %s reload.", dnode->name);
    1802                 :          0 :                 goto out;
    1803                 :            :         }
    1804                 :            : 
    1805 [ #  # ][ #  # ]:          0 :         if (dnode->props.read_only && !dm_task_set_ro(dmt)) {
    1806         [ #  # ]:          0 :                 log_error("Failed to set read only flag for %s", dnode->name);
    1807                 :          0 :                 goto out;
    1808                 :            :         }
    1809                 :            : 
    1810         [ #  # ]:          0 :         if (!dm_task_no_open_count(dmt))
    1811         [ #  # ]:          0 :                 log_error("Failed to disable open_count");
    1812                 :            : 
    1813         [ #  # ]:          0 :         dm_list_iterate_items(seg, &dnode->props.segs)
    1814         [ #  # ]:          0 :                 if (!_emit_segment(dmt, dnode->info.major, dnode->info.minor,
    1815                 :            :                                    seg, &seg_start))
    1816         [ #  # ]:          0 :                         goto_out;
    1817                 :            : 
    1818         [ #  # ]:          0 :         if (!dm_task_suppress_identical_reload(dmt))
    1819         [ #  # ]:          0 :                 log_error("Failed to suppress reload of identical tables.");
    1820                 :            : 
    1821         [ #  # ]:          0 :         if ((r = dm_task_run(dmt))) {
    1822                 :          0 :                 r = dm_task_get_info(dmt, &dnode->info);
    1823   [ #  #  #  # ]:          0 :                 if (r && !dnode->info.inactive_table)
    1824         [ #  # ]:          0 :                         log_verbose("Suppressed %s identical table reload.",
    1825                 :            :                                     dnode->name);
    1826                 :            : 
    1827         [ #  # ]:          0 :                 if ((dnode->props.size_changed =
    1828                 :            :                      (dm_task_get_existing_table_size(dmt) == seg_start) ? 0 : 1))
    1829         [ #  # ]:          0 :                         log_debug("Table size changed from %" PRIu64 " to %"
    1830                 :            :                                   PRIu64 " for %s",
    1831                 :            :                                   dm_task_get_existing_table_size(dmt),
    1832                 :            :                                   seg_start, dnode->name);
    1833                 :            :         }
    1834                 :            : 
    1835                 :          0 :         dnode->props.segment_count = 0;
    1836                 :            : 
    1837                 :            : out:
    1838                 :          0 :         dm_task_destroy(dmt);
    1839                 :            : 
    1840                 :          0 :         return r;
    1841                 :            : }
    1842                 :            : 
    1843                 :          0 : int dm_tree_preload_children(struct dm_tree_node *dnode,
    1844                 :            :                              const char *uuid_prefix,
    1845                 :            :                              size_t uuid_prefix_len)
    1846                 :            : {
    1847                 :          0 :         int r = 1;
    1848                 :          0 :         void *handle = NULL;
    1849                 :            :         struct dm_tree_node *child;
    1850                 :            :         struct dm_info newinfo;
    1851                 :            : 
    1852         [ #  # ]:          0 :         log_verbose("PRELOAD %s",  dnode->name);
    1853                 :            : 
    1854                 :            :         /* Preload children first */
    1855         [ #  # ]:          0 :         while ((child = dm_tree_next_child(&handle, dnode, 0))) {
    1856                 :            :                 /* Skip existing non-device-mapper devices */
    1857 [ #  # ][ #  # ]:          0 :                 if (!child->info.exists && child->info.major)
    1858                 :          0 :                         continue;
    1859                 :            : 
    1860                 :            :                 /* Ignore if it doesn't belong to this VG */
    1861   [ #  #  #  # ]:          0 :                 if (child->info.exists &&
    1862                 :          0 :                     !_uuid_prefix_matches(child->uuid, uuid_prefix, uuid_prefix_len))
    1863                 :          0 :                         continue;
    1864                 :            : 
    1865         [ #  # ]:          0 :                 log_verbose("CHILDRENS %s   %s  %d  i:%d   prio:%d", dnode->name, child->name, dm_tree_node_num_children(child, 0), dm_tree_node_num_children(child, 1), child->activation_priority);
    1866         [ #  # ]:          0 :                 if (dm_tree_node_num_children(child, 0))
    1867         [ #  # ]:          0 :                         if (!dm_tree_preload_children(child, uuid_prefix, uuid_prefix_len))
    1868         [ #  # ]:          0 :                                 return_0;
    1869                 :            : 
    1870                 :            :                 /* FIXME Cope if name exists with no uuid? */
    1871         [ #  # ]:          0 :                 if (!child->info.exists) {
    1872         [ #  # ]:          0 :                         if (!_create_node(child)) {
    1873         [ #  # ]:          0 :                                 stack;
    1874                 :          0 :                                 return 0;
    1875                 :            :                         }
    1876                 :            :                 }
    1877                 :            : 
    1878 [ #  # ][ #  # ]:          0 :                 if (!child->info.inactive_table && child->props.segment_count) {
    1879         [ #  # ]:          0 :                         if (!_load_node(child)) {
    1880         [ #  # ]:          0 :                                 stack;
    1881                 :          0 :                                 return 0;
    1882                 :            :                         }
    1883                 :            :                 }
    1884                 :            : 
    1885         [ #  # ]:          0 :                 if (child->activation_priority != 0)
    1886                 :          0 :                         continue;
    1887                 :            : 
    1888                 :            :                 /* Propagate device size change change */
    1889         [ #  # ]:          0 :                 if (child->props.size_changed)
    1890                 :          0 :                         dnode->props.size_changed = 1;
    1891                 :            : 
    1892                 :            :                 /* Resume device immediately if it has parents and its size changed */
    1893 [ #  # ][ #  # ]:          0 :                 if (!dm_tree_node_num_children(child, 1) || !child->props.size_changed)
    1894                 :          0 :                         continue;
    1895                 :            : 
    1896 [ #  # ][ #  # ]:          0 :                 if (!child->info.inactive_table && !child->info.suspended)
    1897                 :          0 :                         continue;
    1898                 :            : 
    1899         [ #  # ]:          0 :                 log_verbose("PRELOADRESUME %s  %s", dnode->name, child->name);
    1900         [ #  # ]:          0 :                 if (!_resume_node(child->name, child->info.major, child->info.minor,
    1901                 :            :                                   child->props.read_ahead, child->props.read_ahead_flags,
    1902                 :          0 :                                   &newinfo, &child->dtree->cookie, child->udev_flags)) {
    1903         [ #  # ]:          0 :                         log_error("Unable to resume %s (%" PRIu32
    1904                 :            :                                   ":%" PRIu32 ")", child->name, child->info.major,
    1905                 :            :                                   child->info.minor);
    1906                 :          0 :                         r = 0;
    1907                 :          0 :                         continue;
    1908                 :            :                 }
    1909                 :            : 
    1910                 :            :                 /* Update cached info */
    1911                 :          0 :                 child->info = newinfo;
    1912                 :            :         }
    1913                 :            : 
    1914                 :          0 :         handle = NULL;
    1915                 :            : 
    1916         [ #  # ]:          0 :         log_verbose("PRELOADING %s FINISHED",  dnode->name);
    1917                 :          0 :         return r;
    1918                 :            : }
    1919                 :            : 
    1920                 :            : /*
    1921                 :            :  * Returns 1 if unsure.
    1922                 :            :  */
    1923                 :          0 : int dm_tree_children_use_uuid(struct dm_tree_node *dnode,
    1924                 :            :                                  const char *uuid_prefix,
    1925                 :            :                                  size_t uuid_prefix_len)
    1926                 :            : {
    1927                 :          0 :         void *handle = NULL;
    1928                 :          0 :         struct dm_tree_node *child = dnode;
    1929                 :            :         const char *uuid;
    1930                 :            : 
    1931         [ #  # ]:          0 :         while ((child = dm_tree_next_child(&handle, dnode, 0))) {
    1932         [ #  # ]:          0 :                 if (!(uuid = dm_tree_node_get_uuid(child))) {
    1933         [ #  # ]:          0 :                         log_error("Failed to get uuid for dtree node.");
    1934                 :          0 :                         return 1;
    1935                 :            :                 }
    1936                 :            : 
    1937         [ #  # ]:          0 :                 if (_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
    1938                 :          0 :                         return 1;
    1939                 :            : 
    1940         [ #  # ]:          0 :                 if (dm_tree_node_num_children(child, 0))
    1941                 :          0 :                         dm_tree_children_use_uuid(child, uuid_prefix, uuid_prefix_len);
    1942                 :            :         }
    1943                 :            : 
    1944                 :          0 :         return 0;
    1945                 :            : }
    1946                 :            : 
    1947                 :            : /*
    1948                 :            :  * Target functions
    1949                 :            :  */
    1950                 :          0 : static struct load_segment *_add_segment(struct dm_tree_node *dnode, unsigned type, uint64_t size)
    1951                 :            : {
    1952                 :            :         struct load_segment *seg;
    1953                 :            : 
    1954         [ #  # ]:          0 :         if (!(seg = dm_pool_zalloc(dnode->dtree->mem, sizeof(*seg)))) {
    1955         [ #  # ]:          0 :                 log_error("dtree node segment allocation failed");
    1956                 :          0 :                 return NULL;
    1957                 :            :         }
    1958                 :            : 
    1959                 :          0 :         seg->type = type;
    1960                 :          0 :         seg->size = size;
    1961                 :          0 :         seg->area_count = 0;
    1962                 :          0 :         dm_list_init(&seg->areas);
    1963                 :          0 :         seg->stripe_size = 0;
    1964                 :          0 :         seg->persistent = 0;
    1965                 :          0 :         seg->chunk_size = 0;
    1966                 :          0 :         seg->cow = NULL;
    1967                 :          0 :         seg->origin = NULL;
    1968                 :          0 :         seg->merge = NULL;
    1969                 :            : 
    1970                 :          0 :         dm_list_add(&dnode->props.segs, &seg->list);
    1971                 :          0 :         dnode->props.segment_count++;
    1972                 :            : 
    1973                 :          0 :         return seg;
    1974                 :            : }
    1975                 :            : 
    1976                 :          0 : int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
    1977                 :            :                                                uint64_t size,
    1978                 :            :                                                const char *origin_uuid)
    1979                 :            : {
    1980                 :            :         struct load_segment *seg;
    1981                 :            :         struct dm_tree_node *origin_node;
    1982                 :            : 
    1983         [ #  # ]:          0 :         if (!(seg = _add_segment(dnode, SEG_SNAPSHOT_ORIGIN, size)))
    1984         [ #  # ]:          0 :                 return_0;
    1985                 :            : 
    1986         [ #  # ]:          0 :         if (!(origin_node = dm_tree_find_node_by_uuid(dnode->dtree, origin_uuid))) {
    1987         [ #  # ]:          0 :                 log_error("Couldn't find snapshot origin uuid %s.", origin_uuid);
    1988                 :          0 :                 return 0;
    1989                 :            :         }
    1990                 :            : 
    1991                 :          0 :         seg->origin = origin_node;
    1992         [ #  # ]:          0 :         if (!_link_tree_nodes(dnode, origin_node))
    1993         [ #  # ]:          0 :                 return_0;
    1994                 :            : 
    1995                 :            :         /* Resume snapshot origins after new snapshots */
    1996                 :          0 :         dnode->activation_priority = 1;
    1997                 :            : 
    1998                 :          0 :         return 1;
    1999                 :            : }
    2000                 :            : 
    2001                 :          0 : static int _add_snapshot_target(struct dm_tree_node *node,
    2002                 :            :                                    uint64_t size,
    2003                 :            :                                    const char *origin_uuid,
    2004                 :            :                                    const char *cow_uuid,
    2005                 :            :                                    const char *merge_uuid,
    2006                 :            :                                    int persistent,
    2007                 :            :                                    uint32_t chunk_size)
    2008                 :            : {
    2009                 :            :         struct load_segment *seg;
    2010                 :            :         struct dm_tree_node *origin_node, *cow_node, *merge_node;
    2011                 :            :         unsigned seg_type;
    2012                 :            : 
    2013         [ #  # ]:          0 :         seg_type = !merge_uuid ? SEG_SNAPSHOT : SEG_SNAPSHOT_MERGE;
    2014                 :            : 
    2015         [ #  # ]:          0 :         if (!(seg = _add_segment(node, seg_type, size)))
    2016         [ #  # ]:          0 :                 return_0;
    2017                 :            : 
    2018         [ #  # ]:          0 :         if (!(origin_node = dm_tree_find_node_by_uuid(node->dtree, origin_uuid))) {
    2019         [ #  # ]:          0 :                 log_error("Couldn't find snapshot origin uuid %s.", origin_uuid);
    2020                 :          0 :                 return 0;
    2021                 :            :         }
    2022                 :            : 
    2023                 :          0 :         seg->origin = origin_node;
    2024         [ #  # ]:          0 :         if (!_link_tree_nodes(node, origin_node))
    2025         [ #  # ]:          0 :                 return_0;
    2026                 :            : 
    2027         [ #  # ]:          0 :         if (!(cow_node = dm_tree_find_node_by_uuid(node->dtree, cow_uuid))) {
    2028         [ #  # ]:          0 :                 log_error("Couldn't find snapshot COW device uuid %s.", cow_uuid);
    2029                 :          0 :                 return 0;
    2030                 :            :         }
    2031                 :            : 
    2032                 :          0 :         seg->cow = cow_node;
    2033         [ #  # ]:          0 :         if (!_link_tree_nodes(node, cow_node))
    2034         [ #  # ]:          0 :                 return_0;
    2035                 :            : 
    2036                 :          0 :         seg->persistent = persistent ? 1 : 0;
    2037                 :          0 :         seg->chunk_size = chunk_size;
    2038                 :            : 
    2039         [ #  # ]:          0 :         if (merge_uuid) {
    2040         [ #  # ]:          0 :                 if (!(merge_node = dm_tree_find_node_by_uuid(node->dtree, merge_uuid))) {
    2041                 :            :                         /* not a pure error, merging snapshot may have been deactivated */
    2042         [ #  # ]:          0 :                         log_verbose("Couldn't find merging snapshot uuid %s.", merge_uuid);
    2043                 :            :                 } else {
    2044                 :          0 :                         seg->merge = merge_node;
    2045                 :            :                         /* must not link merging snapshot, would undermine activation_priority below */
    2046                 :            :                 }
    2047                 :            : 
    2048                 :            :                 /* Resume snapshot-merge (acting origin) after other snapshots */
    2049                 :          0 :                 node->activation_priority = 1;
    2050         [ #  # ]:          0 :                 if (seg->merge) {
    2051                 :            :                         /* Resume merging snapshot after snapshot-merge */
    2052                 :          0 :                         seg->merge->activation_priority = 2;
    2053                 :            :                 }
    2054                 :            :         }
    2055                 :            : 
    2056                 :          0 :         return 1;
    2057                 :            : }
    2058                 :            : 
    2059                 :            : 
    2060                 :          0 : int dm_tree_node_add_snapshot_target(struct dm_tree_node *node,
    2061                 :            :                                      uint64_t size,
    2062                 :            :                                      const char *origin_uuid,
    2063                 :            :                                      const char *cow_uuid,
    2064                 :            :                                      int persistent,
    2065                 :            :                                      uint32_t chunk_size)
    2066                 :            : {
    2067                 :          0 :         return _add_snapshot_target(node, size, origin_uuid, cow_uuid,
    2068                 :            :                                     NULL, persistent, chunk_size);
    2069                 :            : }
    2070                 :            : 
    2071                 :          0 : int dm_tree_node_add_snapshot_merge_target(struct dm_tree_node *node,
    2072                 :            :                                            uint64_t size,
    2073                 :            :                                            const char *origin_uuid,
    2074                 :            :                                            const char *cow_uuid,
    2075                 :            :                                            const char *merge_uuid,
    2076                 :            :                                            uint32_t chunk_size)
    2077                 :            : {
    2078                 :          0 :         return _add_snapshot_target(node, size, origin_uuid, cow_uuid,
    2079                 :            :                                     merge_uuid, 1, chunk_size);
    2080                 :            : }
    2081                 :            : 
    2082                 :          0 : int dm_tree_node_add_error_target(struct dm_tree_node *node,
    2083                 :            :                                      uint64_t size)
    2084                 :            : {
    2085         [ #  # ]:          0 :         if (!_add_segment(node, SEG_ERROR, size))
    2086         [ #  # ]:          0 :                 return_0;
    2087                 :            : 
    2088                 :          0 :         return 1;
    2089                 :            : }
    2090                 :            : 
    2091                 :          0 : int dm_tree_node_add_zero_target(struct dm_tree_node *node,
    2092                 :            :                                     uint64_t size)
    2093                 :            : {
    2094         [ #  # ]:          0 :         if (!_add_segment(node, SEG_ZERO, size))
    2095         [ #  # ]:          0 :                 return_0;
    2096                 :            : 
    2097                 :          0 :         return 1;
    2098                 :            : }
    2099                 :            : 
    2100                 :          0 : int dm_tree_node_add_linear_target(struct dm_tree_node *node,
    2101                 :            :                                       uint64_t size)
    2102                 :            : {
    2103         [ #  # ]:          0 :         if (!_add_segment(node, SEG_LINEAR, size))
    2104         [ #  # ]:          0 :                 return_0;
    2105                 :            : 
    2106                 :          0 :         return 1;
    2107                 :            : }
    2108                 :            : 
    2109                 :          0 : int dm_tree_node_add_striped_target(struct dm_tree_node *node,
    2110                 :            :                                        uint64_t size,
    2111                 :            :                                        uint32_t stripe_size)
    2112                 :            : {
    2113                 :            :         struct load_segment *seg;
    2114                 :            : 
    2115         [ #  # ]:          0 :         if (!(seg = _add_segment(node, SEG_STRIPED, size)))
    2116         [ #  # ]:          0 :                 return_0;
    2117                 :            : 
    2118                 :          0 :         seg->stripe_size = stripe_size;
    2119                 :            : 
    2120                 :          0 :         return 1;
    2121                 :            : }
    2122                 :            : 
    2123                 :          0 : int dm_tree_node_add_crypt_target(struct dm_tree_node *node,
    2124                 :            :                                   uint64_t size,
    2125                 :            :                                   const char *cipher,
    2126                 :            :                                   const char *chainmode,
    2127                 :            :                                   const char *iv,
    2128                 :            :                                   uint64_t iv_offset,
    2129                 :            :                                   const char *key)
    2130                 :            : {
    2131                 :            :         struct load_segment *seg;
    2132                 :            : 
    2133         [ #  # ]:          0 :         if (!(seg = _add_segment(node, SEG_CRYPT, size)))
    2134         [ #  # ]:          0 :                 return_0;
    2135                 :            : 
    2136                 :          0 :         seg->cipher = cipher;
    2137                 :          0 :         seg->chainmode = chainmode;
    2138                 :          0 :         seg->iv = iv;
    2139                 :          0 :         seg->iv_offset = iv_offset;
    2140                 :          0 :         seg->key = key;
    2141                 :            : 
    2142                 :          0 :         return 1;
    2143                 :            : }
    2144                 :            : 
    2145                 :          0 : int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
    2146                 :            :                                           uint32_t region_size,
    2147                 :            :                                           unsigned clustered,
    2148                 :            :                                           const char *log_uuid,
    2149                 :            :                                           unsigned area_count,
    2150                 :            :                                           uint32_t flags)
    2151                 :            : {
    2152                 :          0 :         struct dm_tree_node *log_node = NULL;
    2153                 :            :         struct load_segment *seg;
    2154                 :            : 
    2155         [ #  # ]:          0 :         if (!node->props.segment_count) {
    2156         [ #  # ]:          0 :                 log_error(INTERNAL_ERROR "Attempt to add target area to missing segment.");
    2157                 :          0 :                 return 0;
    2158                 :            :         }
    2159                 :            : 
    2160                 :          0 :         seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
    2161                 :            : 
    2162         [ #  # ]:          0 :         if (log_uuid) {
    2163         [ #  # ]:          0 :                 if (!(seg->uuid = dm_pool_strdup(node->dtree->mem, log_uuid))) {
    2164         [ #  # ]:          0 :                         log_error("log uuid pool_strdup failed");
    2165                 :          0 :                         return 0;
    2166                 :            :                 }
    2167         [ #  # ]:          0 :                 if (!(flags & DM_CORELOG)) {
    2168         [ #  # ]:          0 :                         if (!(log_node = dm_tree_find_node_by_uuid(node->dtree, log_uuid))) {
    2169         [ #  # ]:          0 :                                 log_error("Couldn't find mirror log uuid %s.", log_uuid);
    2170                 :          0 :                                 return 0;
    2171                 :            :                         }
    2172                 :            : 
    2173         [ #  # ]:          0 :                         if (!_link_tree_nodes(node, log_node))
    2174         [ #  # ]:          0 :                                 return_0;
    2175                 :            :                 }
    2176                 :            :         }
    2177                 :            : 
    2178                 :          0 :         seg->log = log_node;
    2179                 :          0 :         seg->region_size = region_size;
    2180                 :          0 :         seg->clustered = clustered;
    2181                 :          0 :         seg->mirror_area_count = area_count;
    2182                 :          0 :         seg->flags = flags;
    2183                 :            : 
    2184                 :          0 :         return 1;
    2185                 :            : }
    2186                 :            : 
    2187                 :          0 : int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
    2188                 :            :                                       uint64_t size)
    2189                 :            : {
    2190                 :            :         struct load_segment *seg;
    2191                 :            : 
    2192         [ #  # ]:          0 :         if (!(seg = _add_segment(node, SEG_MIRRORED, size)))
    2193         [ #  # ]:          0 :                 return_0;
    2194                 :            : 
    2195                 :          0 :         return 1;
    2196                 :            : }
    2197                 :            : 
    2198                 :          0 : int dm_tree_node_add_replicator_target(struct dm_tree_node *node,
    2199                 :            :                                        uint64_t size,
    2200                 :            :                                        const char *rlog_uuid,
    2201                 :            :                                        const char *rlog_type,
    2202                 :            :                                        unsigned rsite_index,
    2203                 :            :                                        dm_replicator_mode_t mode,
    2204                 :            :                                        uint32_t async_timeout,
    2205                 :            :                                        uint64_t fall_behind_data,
    2206                 :            :                                        uint32_t fall_behind_ios)
    2207                 :            : {
    2208                 :            :         struct load_segment *rseg;
    2209                 :            :         struct replicator_site *rsite;
    2210                 :            : 
    2211         [ #  # ]:          0 :         log_verbose("replicator idx:%d  a:%d  t:%d  i:%d  d:%" PRId64, rsite_index, mode, async_timeout, fall_behind_ios, fall_behind_data);
    2212         [ #  # ]:          0 :         log_verbose("add element %d", node->props.segment_count);
    2213                 :            :         /* Local site0 - adds replicator segment and links rlog device */
    2214         [ #  # ]:          0 :         if (rsite_index == 0) {
    2215         [ #  # ]:          0 :                 if (node->props.segment_count) {
    2216         [ #  # ]:          0 :                         log_error(INTERNAL_ERROR "Attempt to add replicator segment to already used node.");
    2217                 :          0 :                         return 0;
    2218                 :            :                 }
    2219                 :            : 
    2220         [ #  # ]:          0 :                 if (!(rseg = _add_segment(node, SEG_REPLICATOR, size)))
    2221         [ #  # ]:          0 :                         return_0;
    2222                 :            : 
    2223         [ #  # ]:          0 :                 if (!(rseg->log = dm_tree_find_node_by_uuid(node->dtree, rlog_uuid))) {
    2224         [ #  # ]:          0 :                         log_error("Missing replicator log uuid %s.", rlog_uuid);
    2225                 :          0 :                         return 0;
    2226                 :            :                 }
    2227                 :            : 
    2228         [ #  # ]:          0 :                 if (!_link_tree_nodes(node, rseg->log))
    2229         [ #  # ]:          0 :                         return_0;
    2230                 :            : 
    2231         [ #  # ]:          0 :                 if (strcmp(rlog_type, "ringbuffer") != 0) {
    2232         [ #  # ]:          0 :                         log_error("Unsupported rlog type %s.", rlog_type);
    2233                 :          0 :                         return 0;
    2234                 :            :                 }
    2235                 :            : 
    2236         [ #  # ]:          0 :                 if (!(rseg->rlog_type = dm_pool_strdup(node->dtree->mem, rlog_type)))
    2237         [ #  # ]:          0 :                         return_0;
    2238                 :            : 
    2239                 :          0 :                 dm_list_init(&rseg->rsites);
    2240                 :          0 :                 rseg->rdevice_count = 0;
    2241                 :          0 :                 node->activation_priority = 1;
    2242                 :            :         }
    2243                 :            : 
    2244                 :            :         /* Add site to segment */
    2245 [ #  # ][ #  # ]:          0 :         if (mode == DM_REPLICATOR_SYNC
         [ #  # ][ #  # ]
    2246                 :            :             && (async_timeout || fall_behind_ios || fall_behind_data)) {
    2247         [ #  # ]:          0 :                 log_error("Async parameters passed for synchronnous replicator.");
    2248                 :          0 :                 return 0;
    2249                 :            :         }
    2250                 :            : 
    2251         [ #  # ]:          0 :         if (node->props.segment_count != 1) {
    2252         [ #  # ]:          0 :                 log_error(INTERNAL_ERROR "Attempt to add remote site area before setting replog.");
    2253                 :          0 :                 return 0;
    2254                 :            :         }
    2255                 :            : 
    2256                 :          0 :         rseg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
    2257         [ #  # ]:          0 :         if (rseg->type != SEG_REPLICATOR) {
    2258         [ #  # ]:          0 :                 log_error(INTERNAL_ERROR "Attempt to use non replicator segment %s.",
    2259                 :            :                           dm_segtypes[rseg->type].target);
    2260                 :          0 :                 return 0;
    2261                 :            :         }
    2262                 :            : 
    2263         [ #  # ]:          0 :         if (!(rsite = dm_pool_zalloc(node->dtree->mem, sizeof(*rsite)))) {
    2264         [ #  # ]:          0 :                 log_error("Failed to allocate remote site segment.");
    2265                 :          0 :                 return 0;
    2266                 :            :         }
    2267                 :            : 
    2268                 :          0 :         dm_list_add(&rseg->rsites, &rsite->list);
    2269                 :          0 :         rseg->rsite_count++;
    2270                 :            : 
    2271                 :          0 :         rsite->mode = mode;
    2272                 :          0 :         rsite->async_timeout = async_timeout;
    2273                 :          0 :         rsite->fall_behind_data = fall_behind_data;
    2274                 :          0 :         rsite->fall_behind_ios = fall_behind_ios;
    2275                 :          0 :         rsite->rsite_index = rsite_index;
    2276                 :            : 
    2277         [ #  # ]:          0 :         log_verbose("ADDEDSEGLOG %p", rseg->log);
    2278                 :          0 :         return 1;
    2279                 :            : }
    2280                 :            : 
    2281                 :            : /* Appends device node to Replicator */
    2282                 :          0 : int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
    2283                 :            :                                            uint64_t size,
    2284                 :            :                                            const char *replicator_uuid,
    2285                 :            :                                            uint64_t rdevice_index,
    2286                 :            :                                            const char *rdev_uuid,
    2287                 :            :                                            unsigned rsite_index,
    2288                 :            :                                            const char *slog_uuid,
    2289                 :            :                                            uint32_t slog_flags,
    2290                 :            :                                            uint32_t slog_region_size)
    2291                 :            : {
    2292                 :            :         struct seg_area *area;
    2293                 :            :         struct load_segment *rseg;
    2294                 :            :         struct load_segment *rep_seg;
    2295                 :            : 
    2296         [ #  # ]:          0 :         log_verbose("replicator-dev:%s  device index:%" PRIu64 " uuid:%s  dev:%s",
    2297                 :            :                     node->name, rdevice_index, node->uuid, rdev_uuid);
    2298         [ #  # ]:          0 :         log_verbose("dev:%s   log:%s", rdev_uuid, slog_uuid);
    2299         [ #  # ]:          0 :         if (rsite_index == 0) {
    2300                 :            :                 /* Site index for local target */
    2301         [ #  # ]:          0 :                 if (!(rseg = _add_segment(node, SEG_REPLICATOR_DEV, size)))
    2302         [ #  # ]:          0 :                         return_0;
    2303                 :            : 
    2304         [ #  # ]:          0 :                 if (!(rseg->replicator = dm_tree_find_node_by_uuid(node->dtree, replicator_uuid))) {
    2305         [ #  # ]:          0 :                         log_error("Missing replicator uuid %s.", replicator_uuid);
    2306                 :          0 :                         return 0;
    2307                 :            :                 }
    2308                 :            : 
    2309                 :            :                 /* Local slink 0 for replicator must be always initialized first */
    2310         [ #  # ]:          0 :                 if (rseg->replicator->props.segment_count != 1) {
    2311         [ #  # ]:          0 :                         log_error(INTERNAL_ERROR "Attempt to use non replicator segment.");
    2312                 :          0 :                         return 0;
    2313                 :            :                 }
    2314                 :            : 
    2315                 :          0 :                 rep_seg = dm_list_item(dm_list_last(&rseg->replicator->props.segs), struct load_segment);
    2316         [ #  # ]:          0 :                 if (rep_seg->type != SEG_REPLICATOR) {
    2317         [ #  # ]:          0 :                         log_error(INTERNAL_ERROR "Attempt to use non replicator segment %s.",
    2318                 :            :                                   dm_segtypes[rep_seg->type].target);
    2319                 :          0 :                         return 0;
    2320                 :            :                 }
    2321                 :          0 :                 rep_seg->rdevice_count++;
    2322                 :            : 
    2323         [ #  # ]:          0 :                 if (!_link_tree_nodes(node, rseg->replicator))
    2324         [ #  # ]:          0 :                         return_0;
    2325                 :            : 
    2326                 :          0 :                 rseg->rdevice_index = rdevice_index;
    2327                 :            :         } else {
    2328         [ #  # ]:          0 :                 if (node->props.segment_count != 1) {
    2329                 :            :                         /* Local slink 0 for replicator must be always initialized first */
    2330         [ #  # ]:          0 :                         log_error(INTERNAL_ERROR "Attempt to use non replicator-dev segment.");
    2331                 :          0 :                         return 0;
    2332                 :            :                 }
    2333                 :            : 
    2334                 :          0 :                 rseg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
    2335         [ #  # ]:          0 :                 if (rseg->type != SEG_REPLICATOR_DEV) {
    2336         [ #  # ]:          0 :                         log_error(INTERNAL_ERROR "Attempt to use non replicator-dev segment %s.",
    2337                 :            :                                   dm_segtypes[rseg->type].target);
    2338                 :          0 :                         return 0;
    2339                 :            :                 }
    2340                 :            :         }
    2341                 :            : 
    2342 [ #  # ][ #  # ]:          0 :         if (!(slog_flags & DM_CORELOG) && !slog_uuid) {
    2343         [ #  # ]:          0 :                 log_error("Unspecified sync log uuid.");
    2344                 :          0 :                 return 0;
    2345                 :            :         }
    2346                 :            : 
    2347         [ #  # ]:          0 :         log_verbose("CREATE CHILDRENS1 %s  %d", node->name, dm_tree_node_num_children(node, 0));
    2348         [ #  # ]:          0 :         if (!dm_tree_node_add_target_area(node, NULL, rdev_uuid, 0))
    2349         [ #  # ]:          0 :                 return_0;
    2350                 :            : 
    2351                 :          0 :         area = dm_list_item(dm_list_last(&rseg->areas), struct seg_area);
    2352                 :            : 
    2353         [ #  # ]:          0 :         if (!(slog_flags & DM_CORELOG)) {
    2354         [ #  # ]:          0 :                 if (!(area->slog = dm_tree_find_node_by_uuid(node->dtree, slog_uuid))) {
    2355         [ #  # ]:          0 :                         log_error("Couldn't find sync log uuid %s.", slog_uuid);
    2356                 :          0 :                         return 0;
    2357                 :            :                 }
    2358                 :            : 
    2359         [ #  # ]:          0 :                 if (!_link_tree_nodes(node, area->slog))
    2360         [ #  # ]:          0 :                         return_0;
    2361         [ #  # ]:          0 :                 log_verbose("CREATE CHILDRENS2 %s  %d ", node->name, dm_tree_node_num_children(node, 0));
    2362                 :            :         }
    2363                 :            : 
    2364                 :          0 :         area->flags = slog_flags;
    2365                 :          0 :         area->region_size = slog_region_size;
    2366                 :          0 :         area->rsite_index = rsite_index;
    2367                 :            : 
    2368                 :          0 :         return 1;
    2369                 :            : }
    2370                 :            : 
    2371                 :          0 : static int _add_area(struct dm_tree_node *node, struct load_segment *seg, struct dm_tree_node *dev_node, uint64_t offset)
    2372                 :            : {
    2373                 :            :         struct seg_area *area;
    2374                 :            : 
    2375         [ #  # ]:          0 :         if (!(area = dm_pool_zalloc(node->dtree->mem, sizeof (*area)))) {
    2376         [ #  # ]:          0 :                 log_error("Failed to allocate target segment area.");
    2377                 :          0 :                 return 0;
    2378                 :            :         }
    2379                 :            : 
    2380                 :          0 :         area->dev_node = dev_node;
    2381                 :          0 :         area->offset = offset;
    2382                 :            : 
    2383                 :          0 :         dm_list_add(&seg->areas, &area->list);
    2384                 :          0 :         seg->area_count++;
    2385                 :            : 
    2386                 :          0 :         return 1;
    2387                 :            : }
    2388                 :            : 
    2389                 :          0 : int dm_tree_node_add_target_area(struct dm_tree_node *node,
    2390                 :            :                                     const char *dev_name,
    2391                 :            :                                     const char *uuid,
    2392                 :            :                                     uint64_t offset)
    2393                 :            : {
    2394                 :            :         struct load_segment *seg;
    2395                 :            :         struct stat info;
    2396                 :            :         struct dm_tree_node *dev_node;
    2397                 :            : 
    2398 [ #  # ][ #  # ]:          0 :         if ((!dev_name || !*dev_name) && (!uuid || !*uuid)) {
         [ #  # ][ #  # ]
    2399         [ #  # ]:          0 :                 log_error("dm_tree_node_add_target_area called without device");
    2400                 :          0 :                 return 0;
    2401                 :            :         }
    2402                 :            : 
    2403         [ #  # ]:          0 :         if (uuid) {
    2404         [ #  # ]:          0 :                 if (!(dev_node = dm_tree_find_node_by_uuid(node->dtree, uuid))) {
    2405         [ #  # ]:          0 :                         log_error("Couldn't find area uuid %s.", uuid);
    2406                 :          0 :                         return 0;
    2407                 :            :                 }
    2408         [ #  # ]:          0 :                 if (!_link_tree_nodes(node, dev_node))
    2409         [ #  # ]:          0 :                         return_0;
    2410                 :            :         } else {
    2411         [ #  # ]:          0 :                 if (stat(dev_name, &info) < 0) {
    2412         [ #  # ]:          0 :                         log_error("Device %s not found.", dev_name);
    2413                 :          0 :                         return 0;
    2414                 :            :                 }
    2415                 :            : 
    2416         [ #  # ]:          0 :                 if (!S_ISBLK(info.st_mode)) {
    2417         [ #  # ]:          0 :                         log_error("Device %s is not a block device.", dev_name);
    2418                 :          0 :                         return 0;
    2419                 :            :                 }
    2420                 :            : 
    2421                 :            :                 /* FIXME Check correct macro use */
    2422         [ #  # ]:          0 :                 if (!(dev_node = _add_dev(node->dtree, node, MAJOR(info.st_rdev),
    2423                 :          0 :                                           MINOR(info.st_rdev), 0)))
    2424         [ #  # ]:          0 :                         return_0;
    2425                 :            :         }
    2426                 :            : 
    2427         [ #  # ]:          0 :         if (!node->props.segment_count) {
    2428         [ #  # ]:          0 :                 log_error(INTERNAL_ERROR "Attempt to add target area to missing segment.");
    2429                 :          0 :                 return 0;
    2430                 :            :         }
    2431                 :            : 
    2432                 :          0 :         seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
    2433                 :            : 
    2434         [ #  # ]:          0 :         if (!_add_area(node, seg, dev_node, offset))
    2435         [ #  # ]:          0 :                 return_0;
    2436                 :            : 
    2437                 :          0 :         return 1;
    2438                 :            : }
    2439                 :            : 
    2440                 :          0 : void dm_tree_set_cookie(struct dm_tree_node *node, uint32_t cookie)
    2441                 :            : {
    2442                 :          0 :         node->dtree->cookie = cookie;
    2443                 :          0 : }
    2444                 :            : 
    2445                 :          0 : uint32_t dm_tree_get_cookie(struct dm_tree_node *node)
    2446                 :            : {
    2447                 :          0 :         return node->dtree->cookie;
    2448                 :            : }

Generated by: LCOV version 1.8