]> sourceware.org Git - lvm2.git/commitdiff
Replacement activation code. [Don't use this yet!]
authorAlasdair Kergon <agk@redhat.com>
Tue, 8 Nov 2005 22:52:26 +0000 (22:52 +0000)
committerAlasdair Kergon <agk@redhat.com>
Tue, 8 Nov 2005 22:52:26 +0000 (22:52 +0000)
18 files changed:
lib/activate/activate.c
lib/activate/activate.h
lib/activate/dev_manager.c
lib/activate/dev_manager.h
lib/activate/targets.h
lib/error/errseg.c
lib/log/log.h
lib/metadata/mirror.c
lib/metadata/segtype.h
lib/mirror/mirrored.c
lib/misc/lvm-string.c
lib/report/report.c
lib/snapshot/snapshot.c
lib/striped/striped.c
lib/zero/zero.c
man/lvs.8
tools/lvcreate.c
tools/lvremove.c

index f15123d74072517f3c6cfd3b7f76c2b5f7f23f58..6f1af347309a16dce3d497e9f30f7b23294217f5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
- * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
  *
  * This file is part of LVM2.
  *
@@ -284,10 +284,8 @@ static int _target_present(const char *target_name)
        struct dm_versions *target, *last_target;
 
        log_very_verbose("Getting target version for %s", target_name);
-       if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS))) {
-               stack;
-               return 0;
-       }
+       if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
+               return_0;
 
        if (!dm_task_run(dmt)) {
                log_debug("Failed to get %s target version", target_name);
@@ -314,7 +312,7 @@ static int _target_present(const char *target_name)
        return r;
 }
 
-int target_present(const char *target_name)
+int target_present(const char *target_name, int use_modprobe)
 {
 #ifdef MODPROBE_CMD
        char module[128];
@@ -324,17 +322,19 @@ int target_present(const char *target_name)
                return 0;
 
 #ifdef MODPROBE_CMD
-       if (_target_present(target_name))
-               return 1;
+       if (use_modprobe) {
+               if (_target_present(target_name))
+                       return 1;
 
-       if (lvm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
-               log_error("target_present module name too long: %s", target_name);
-               return 0;
-       }
+               if (lvm_snprintf(module, sizeof(module), "dm-%s", target_name)
+                   < 0) {
+                       log_error("target_present module name too long: %s",
+                                 target_name);
+                       return 0;
+               }
 
-       if (!exec_cmd(MODPROBE_CMD, module, "", "")) {
-               stack;
-               return 0;
+               if (!exec_cmd(MODPROBE_CMD, module, "", ""))
+                       return_0;
        }
 #endif
 
@@ -353,17 +353,14 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, in
        if (!activation())
                return 0;
 
-       if (!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL))) {
-               stack;
-               return 0;
-       }
+       if (!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
+               return_0;
 
        log_debug("Getting device info for %s", name);
        if (!dev_manager_info(lv->vg->cmd->mem, name, lv, with_mknodes,
                              with_open_count, &dminfo)) {
                dm_pool_free(cmd->mem, name);
-               stack;
-               return 0;
+               return_0;
        }
 
        info->exists = dminfo.exists;
@@ -372,6 +369,8 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, in
        info->major = dminfo.major;
        info->minor = dminfo.minor;
        info->read_only = dminfo.read_only;
+       info->live_table = dminfo.live_table;
+       info->inactive_table = dminfo.inactive_table;
 
        dm_pool_free(cmd->mem, name);
        return 1;
@@ -405,10 +404,8 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
        if (!activation())
                return 0;
 
-       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
-               stack;
-               return 0;
-       }
+       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
+               return_0;
 
        if (!(r = dev_manager_snapshot_percent(dm, lv, percent)))
                stack;
@@ -429,18 +426,14 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wa
        if (!activation())
                return 0;
 
-       if (!lv_info(cmd, lv, &info, 0)) {
-               stack;
-               return 0;
-       }
+       if (!lv_info(cmd, lv, &info, 0))
+               return_0;
 
        if (!info.exists)
                return 0;
 
-       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
-               stack;
-               return 0;
-       }
+       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
+               return_0;
 
        if (!(r = dev_manager_mirror_percent(dm, lv, wait, percent, event_nr)))
                stack;
@@ -474,16 +467,13 @@ static int _lv_open_count(struct cmd_context *cmd, struct logical_volume *lv)
        return info.open_count;
 }
 
-/* FIXME Need to detect and handle an lv rename */
 static int _lv_activate_lv(struct logical_volume *lv)
 {
        int r;
        struct dev_manager *dm;
 
-       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
-               stack;
-               return 0;
-       }
+       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
+               return_0;
 
        if (!(r = dev_manager_activate(dm, lv)))
                stack;
@@ -492,15 +482,28 @@ static int _lv_activate_lv(struct logical_volume *lv)
        return r;
 }
 
-static int _lv_deactivate(struct logical_volume *lv)
+static int _lv_preload(struct logical_volume *lv)
 {
        int r;
        struct dev_manager *dm;
 
-       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
+       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
+               return_0;
+
+       if (!(r = dev_manager_preload(dm, lv)))
                stack;
-               return 0;
-       }
+
+       dev_manager_destroy(dm);
+       return r;
+}
+
+static int _lv_deactivate(struct logical_volume *lv)
+{
+       int r;
+       struct dev_manager *dm;
+
+       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
+               return_0;
 
        if (!(r = dev_manager_deactivate(dm, lv)))
                stack;
@@ -514,10 +517,8 @@ static int _lv_suspend_lv(struct logical_volume *lv)
        int r;
        struct dev_manager *dm;
 
-       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
-               stack;
-               return 0;
-       }
+       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
+               return_0;
 
        if (!(r = dev_manager_suspend(dm, lv)))
                stack;
@@ -580,14 +581,20 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
                return 1;
        }
 
-       if (!lv_info(cmd, lv, &info, 0)) {
-               stack;
-               return 0;
-       }
+       if (!lv_info(cmd, lv, &info, 0))
+               return_0;
 
        if (!info.exists || info.suspended)
                return error_if_not_suspended ? 0 : 1;
 
+       /* If VG was precommitted, preload devices for the LV */
+       if ((lv->vg->status & PRECOMMITTED)) {
+               if (!_lv_preload(lv)) {
+                       /* FIXME Revert preloading */
+                       return_0;
+               }
+       }
+
        memlock_inc();
        if (!_lv_suspend_lv(lv)) {
                memlock_dec();
@@ -626,10 +633,8 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
                return 1;
        }
 
-       if (!lv_info(cmd, lv, &info, 0)) {
-               stack;
-               return 0;
-       }
+       if (!lv_info(cmd, lv, &info, 0))
+               return_0;
 
        if (!info.exists || !info.suspended)
                return error_if_not_active ? 0 : 1;
@@ -671,16 +676,14 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
                return 1;
        }
 
-       if (!lv_info(cmd, lv, &info, 1)) {
-               stack;
-               return 0;
-       }
+       if (!lv_info(cmd, lv, &info, 1))
+               return_0;
 
        if (!info.exists)
                return 1;
 
        if (info.open_count && (lv->status & VISIBLE_LV)) {
-               log_error("LV %s/%s in use: not removing", lv->vg->name,
+               log_error("LV %s/%s in use: not deactivating", lv->vg->name,
                          lv->name);
                return 0;
        }
@@ -741,12 +744,10 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
                return 1;
        }
 
-       if (!lv_info(cmd, lv, &info, 0)) {
-               stack;
-               return 0;
-       }
+       if (!lv_info(cmd, lv, &info, 0))
+               return_0;
 
-       if (info.exists && !info.suspended)
+       if (info.exists && !info.suspended && info.live_table)
                return 1;
 
        if (exclusive)
@@ -783,10 +784,8 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
                return r;
        }
 
-       if (!_lv_info(cmd, lv, 1, &info, 0)) {
-               stack;
-               return 0;
-       }
+       if (!_lv_info(cmd, lv, 1, &info, 0))
+               return_0;
 
        if (info.exists)
                r = dev_manager_lv_mknodes(lv);
index bf5b8b089114f2bad23939b2d737d5fc2abb610b..c05f667daa9a327133b56fd16b7727db24f908cf 100644 (file)
@@ -25,6 +25,8 @@ struct lvinfo {
        int major;
        int minor;
        int read_only;
+       int live_table;
+       int inactive_table;
 };
 
 void set_activation(int activation);
@@ -34,7 +36,7 @@ int driver_version(char *version, size_t size);
 int library_version(char *version, size_t size);
 int lvm1_present(struct cmd_context *cmd);
 
-int target_present(const char *target_name);
+int target_present(const char *target_name, int use_modprobe);
 
 void activation_exit(void);
 
index a41c18cc8c69285b16cc079a4504485b89ae9f01..65527f5621cc4b3ecf994b03d880e730fd50bed2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
- * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
  *
  * This file is part of LVM2.
  *
 #include <limits.h>
 #include <dirent.h>
 
-/*
- * Algorithm
- * ---------
- *
- * 1) Examine dm directory, and store details of active mapped devices
- *    in the VG.  Indexed by lvid-layer. (_scan_existing_devices)
- *
- * 2) Build lists of visible devices that need to be left in each state:
- *    active, reloaded, suspended.
- *
- * 3) Run through these lists and set the appropriate marks on each device
- *    and its dependencies.
- *
- * 4) Add layers not marked active to remove_list for removal at the end.
- *
- * 5) Remove unmarked layers from core.
- *
- * 6) Activate remaining layers, recursing to handle dependedncies and
- *    skipping any that already exist unless they are marked as needing
- *    reloading.
- *
- * 7) Remove layers in the remove_list.  (_remove_old_layers)
- *
- */
-
 #define MAX_TARGET_PARAMSIZE 50000
 #define UUID_PREFIX "LVM-"
 
-enum {
-       ACTIVE = 0,
-       RELOAD = 1,
-       VISIBLE = 2,
-       READWRITE = 3,
-       SUSPENDED = 4,
-       NOPROPAGATE = 5,
-       TOPLEVEL = 6,
-       REMOVE = 7,
-       RESUME_IMMEDIATE = 8
-};
-
 typedef enum {
+       PRELOAD,
        ACTIVATE,
        DEACTIVATE,
        SUSPEND,
-       RESUME
+       CLEAN
 } action_t;
 
-struct dev_layer {
-       char *name;
-
-       int flags;
-
-       /*
-        * Setup the dm_task.
-        */
-       int (*populate) (struct dev_manager * dm,
-                        struct dm_task * dmt, struct dev_layer * dl);
-       struct dm_info info;
-
-       /* lvid plus layer */
-       char *dlid;
-
-       struct logical_volume *lv;
-
-       /*
-        * Devices that must be created before this one can be created.
-        * Reloads get propagated to this list.  Holds str_lists.
-        */
-       struct list pre_create;
-
-       /* Inverse of pre_create */
-       struct list pre_suspend;
-
-};
-
-struct dl_list {
-       struct list list;
-       struct dev_layer *dl;
-};
-
-static const char *stripe_filler = NULL;
-
 struct dev_manager {
        struct dm_pool *mem;
 
@@ -121,48 +50,14 @@ struct dev_manager {
        uint32_t pvmove_mirror_count;
 
        char *vg_name;
-
-       /*
-        * list of struct lv_list, contains lvs that we wish to
-        * be active after execution.
-        */
-       struct list active_list;
-
-       /*
-        * Layers that need reloading.
-        */
-       struct list reload_list;
-
-       /*
-        * Layers that need suspending.
-        */
-       struct list suspend_list;
-
-       /*
-        * Layers that will need removing after activation.
-        */
-       struct list remove_list;
-
-       struct dm_hash_table *layers;
 };
 
-/*
- * Functions to manage the flags.
- */
-static inline int _get_flag(struct dev_layer *dl, int bit)
-{
-       return (dl->flags & (1 << bit)) ? 1 : 0;
-}
-
-static inline void _set_flag(struct dev_layer *dl, int bit)
-{
-       dl->flags |= (1 << bit);
-}
+struct lv_layer {
+       struct logical_volume *lv;
+       const char *old_name;
+};
 
-static inline void _clear_flag(struct dev_layer *dl, int bit)
-{
-       dl->flags &= ~(1 << bit);
-}
+static const char *stripe_filler = NULL;
 
 static char *_build_dlid(struct dm_pool *mem, const char *lvid, const char *layer)
 {
@@ -175,7 +70,8 @@ static char *_build_dlid(struct dm_pool *mem, const char *lvid, const char *laye
        len = sizeof(UUID_PREFIX) + sizeof(union lvid) + strlen(layer);
 
        if (!(dlid = dm_pool_alloc(mem, len))) {
-               stack;
+               log_error("_build_dlid: pool allocation failed for %" PRIsize_t
+                         " %s %s.", len, lvid, layer);
                return NULL;
        }
 
@@ -189,6 +85,11 @@ char *build_dlid(struct dev_manager *dm, const char *lvid, const char *layer)
        return _build_dlid(dm->mem, lvid, layer);
 }
 
+static inline int _read_only_lv(struct logical_volume *lv)
+{
+       return (!(lv->vg->status & LVM_WRITE) || !(lv->status & LVM_WRITE));
+}
+
 /*
  * Low level device-layer operations.
  */
@@ -234,21 +135,15 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
                if (!dm_task_no_open_count(dmt))
                        log_error("Failed to disable open_count");
 
-       if (!dm_task_run(dmt)) {
-               stack;
-               goto out;
-       }
+       if (!dm_task_run(dmt))
+               goto_out;
 
-       if (!dm_task_get_info(dmt, info)) {
-               stack;
-               goto out;
-       }
+       if (!dm_task_get_info(dmt, info))
+               goto_out;
 
        if (info->exists && uuid_out) {
-               if (!(u = dm_task_get_uuid(dmt))) {
-                       stack;
-                       goto out;
-               }
+               if (!(u = dm_task_get_uuid(dmt)))
+                       goto_out;
                *uuid_out = dm_pool_strdup(mem, u);
        }
        r = 1;
@@ -316,15 +211,11 @@ static int _status_run(const char *name, const char *uuid,
        if (!dm_task_no_open_count(dmt))
                log_error("Failed to disable open_count");
 
-       if (!dm_task_run(dmt)) {
-               stack;
-               goto out;
-       }
+       if (!dm_task_run(dmt))
+               goto_out;
 
-       if (!dm_task_get_info(dmt, &info) || !info.exists) {
-               stack;
-               goto out;
-       }
+       if (!dm_task_get_info(dmt, &info) || !info.exists)
+               goto_out;
 
        do {
                next = dm_get_next_target(dmt, next, &start, &length,
@@ -409,15 +300,11 @@ static int _percent_run(struct dev_manager *dm, const char *name,
        if (!dm_task_no_open_count(dmt))
                log_error("Failed to disable open_count");
 
-       if (!dm_task_run(dmt)) {
-               stack;
-               goto out;
-       }
+       if (!dm_task_run(dmt))
+               goto_out;
 
-       if (!dm_task_get_info(dmt, &info) || !info.exists) {
-               stack;
-               goto out;
-       }
+       if (!dm_task_get_info(dmt, &info) || !info.exists)
+               goto_out;
 
        if (event_nr)
                *event_nr = info.event_nr;
@@ -445,10 +332,8 @@ static int _percent_run(struct dev_manager *dm, const char *name,
                                                  dm->cmd->cft, seg, params,
                                                  &total_numerator,
                                                  &total_denominator,
-                                                 percent)) {
-                       stack;
-                       goto out;
-               }
+                                                 percent))
+                       goto_out;
 
        } while (next);
 
@@ -493,1528 +378,164 @@ static int _percent(struct dev_manager *dm, const char *name, const char *dlid,
        return 0;
 }
 
-static int _rename(struct dev_manager *dm, struct dev_layer *dl, char *newname)
+/*
+ * dev_manager implementation.
+ */
+struct dev_manager *dev_manager_create(struct cmd_context *cmd,
+                                      const char *vg_name)
 {
-       int r = 1;
-       struct dm_task *dmt;
-       char *vgname, *lvname, *layer;
-
-       if (!split_dm_name(dm->mem, dl->name, &vgname, &lvname, &layer)) {
-               log_error("Couldn't split up dm layer name %s", dl->name);
-               return 0;
-       }
-
-       log_verbose("Renaming %s to %s", dl->name, newname);
+       struct dm_pool *mem;
+       struct dev_manager *dm;
 
-       if (!(dmt = _setup_task(dl->name, NULL, 0, DM_DEVICE_RENAME))) {
+       if (!(mem = dm_pool_create("dev_manager", 16 * 1024))) {
                stack;
-               return 0;
+               return NULL;
        }
 
-       if (!dm_task_set_newname(dmt, newname)) {
+       if (!(dm = dm_pool_alloc(mem, sizeof(*dm)))) {
                stack;
-               r = 0;
-               goto out;
+               goto bad;
        }
 
-       if (!dm_task_no_open_count(dmt))
-               log_error("Failed to disable open_count");
+       dm->cmd = cmd;
+       dm->mem = mem;
 
-       if (!(r = dm_task_run(dmt))) {
-               log_error("Couldn't rename device '%s'.", dl->name);
-               goto out;
+       if (!stripe_filler) {
+               stripe_filler = find_config_str(cmd->cft->root,
+                                               "activation/missing_stripe_filler",
+                                               DEFAULT_STRIPE_FILLER);
        }
+       dm->stripe_filler = stripe_filler;
 
-       if (r && _get_flag(dl, VISIBLE))
-               fs_rename_lv(dl->lv, newname, lvname);
-
-       dl->name = newname;
-
-      out:
-       dm_task_destroy(dmt);
-       return r;
-}
-
-static int _suspend_or_resume(const char *name, action_t suspend)
-{
-       int r;
-       struct dm_task *dmt;
-       int sus = (suspend == SUSPEND) ? 1 : 0;
-       int task = sus ? DM_DEVICE_SUSPEND : DM_DEVICE_RESUME;
-
-       log_very_verbose("%s %s", sus ? "Suspending" : "Resuming", name);
-       if (!(dmt = _setup_task(name, NULL, 0, task))) {
+       if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name))) {
                stack;
-               return 0;
+               goto bad;
        }
 
-       if (!dm_task_no_open_count(dmt))
-               log_error("Failed to disable open_count");
+       dm->target_state = NULL;
 
-       if (!(r = dm_task_run(dmt)))
-               log_error("Couldn't %s device '%s'", sus ? "suspend" : "resume",
-                         name);
+       return dm;
 
-       dm_task_destroy(dmt);
-       return r;
+      bad:
+       dm_pool_destroy(mem);
+       return NULL;
 }
 
-static int _suspend(struct dev_layer *dl)
+void dev_manager_destroy(struct dev_manager *dm)
 {
-       if (!dl->info.exists || dl->info.suspended)
-               return 1;
-
-       if (!_suspend_or_resume(dl->name, SUSPEND)) {
-               stack;
-               return 0;
-       }
+       dm_pool_destroy(dm->mem);
+}
 
-       dl->info.suspended = 1;
-       return 1;
+void dev_manager_exit(void)
+{
+       dm_lib_exit();
 }
 
-static int _resume(struct dev_layer *dl)
+int dev_manager_snapshot_percent(struct dev_manager *dm,
+                                struct logical_volume *lv, float *percent)
 {
-       if (!dl->info.exists || !dl->info.suspended)
-               return 1;
+       char *name;
+       const char *dlid;
+
+       /*
+        * Build a name for the top layer.
+        */
+       if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL)))
+               return_0;
+
+       if (!(dlid = build_dlid(dm, lv->lvid.s, NULL)))
+               return_0;
 
-       if (!_suspend_or_resume(dl->name, RESUME)) {
+       /*
+        * Try and get some info on this device.
+        */
+       log_debug("Getting device status percentage for %s", name);
+       if (!(_percent(dm, name, dlid, "snapshot", 0, NULL, percent,
+                      NULL))) {
                stack;
                return 0;
        }
 
-       dl->info.suspended = 0;
+       /* FIXME dm_pool_free ? */
+
+       /* If the snapshot isn't available, percent will be -1 */
        return 1;
 }
 
-static int _load(struct dev_manager *dm, struct dev_layer *dl, int task)
+/* FIXME Merge with snapshot_percent, auto-detecting target type */
+/* FIXME Cope with more than one target */
+int dev_manager_mirror_percent(struct dev_manager *dm,
+                              struct logical_volume *lv, int wait,
+                              float *percent, uint32_t *event_nr)
 {
-       int r = 1;
-       struct dm_task *dmt;
-
-       log_verbose("Loading %s", dl->name);
-       if (!(dmt = _setup_task(task == DM_DEVICE_CREATE ? dl->name : NULL,
-                               dl->dlid, 0, task))) {
-               stack;
-               return 0;
-       }
-
-       /*
-        * Populate the table.
-        */
-       if (!dl->populate(dm, dmt, dl)) {
-               log_error("Couldn't populate device '%s'.", dl->name);
-               r = 0;
-               goto out;
-       }
+       char *name;
+       const char *dlid;
 
        /*
-        * Do we want a specific device number ?
+        * Build a name for the top layer.
         */
-       if (dl->lv->major >= 0 && _get_flag(dl, VISIBLE)) {
-               if (!dm_task_set_major(dmt, dl->lv->major)) {
-                       log_error("Failed to set major number for %s to %d "
-                                 "during activation.", dl->name,
-                                 dl->lv->major);
-                       goto out;
-               } else
-                       log_very_verbose("Set major number for %s to %d.",
-                                        dl->name, dl->lv->major);
-       }
-
-       if (dl->lv->minor >= 0 && _get_flag(dl, VISIBLE)) {
-               if (!dm_task_set_minor(dmt, dl->lv->minor)) {
-                       log_error("Failed to set minor number for %s to %d "
-                                 "during activation.", dl->name,
-                                 dl->lv->minor);
-                       goto out;
-               } else
-                       log_very_verbose("Set minor number for %s to %d.",
-                                        dl->name, dl->lv->minor);
-       }
-
-       if (!_get_flag(dl, READWRITE)) {
-               if (!dm_task_set_ro(dmt)) {
-                       log_error("Failed to set %s read-only during "
-                                 "activation.", dl->name);
-                       goto out;
-               } else
-                       log_very_verbose("Activating %s read-only", dl->name);
-       }
+       if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL)))
+               return_0;
 
-       if (!dm_task_no_open_count(dmt))
-               log_error("Failed to disable open_count");
+       /* FIXME dm_pool_free ? */
 
-       if (!(r = dm_task_run(dmt))) {
-               log_error("Couldn't load device '%s'.", dl->name);
-               if ((dl->lv->minor >= 0 || dl->lv->major >= 0) &&
-                   _get_flag(dl, VISIBLE))
-                           log_error("Perhaps the persistent device number "
-                                     "%d:%d is already in use?",
-                                     dl->lv->major, dl->lv->minor);
+       if (!(dlid = build_dlid(dm, lv->lvid.s, NULL))) {
+               log_error("dlid build failed for %s", lv->name);
+               return 0;
        }
 
-       if (!dm_task_get_info(dmt, &dl->info)) {
+       log_debug("Getting device mirror status percentage for %s", name);
+       if (!(_percent(dm, name, dlid, "mirror", wait, lv, percent,
+                      event_nr))) {
                stack;
-               r = 0;
-               goto out;
+               return 0;
        }
 
-       if (!dl->info.exists || !dl->info.live_table) {
-               stack;
-               r = 0;
-               goto out;
-       }
+       return 1;
+}
 
-       if (_get_flag(dl, RESUME_IMMEDIATE) && dl->info.suspended &&
-           !_resume(dl)) {
-               stack;
-               r = 0;
-               goto out;
-       }
+#if 0
+       log_very_verbose("%s %s", sus ? "Suspending" : "Resuming", name);
 
+       log_verbose("Loading %s", dl->name);
+                       log_very_verbose("Activating %s read-only", dl->name);
        log_very_verbose("Activated %s %s %03u:%03u", dl->name,
                         dl->dlid, dl->info.major, dl->info.minor);
 
-       if (r && _get_flag(dl, VISIBLE))
-               fs_add_lv(dl->lv, dl->name);
-
-       _clear_flag(dl, RELOAD);
-
-      out:
-       dm_task_destroy(dmt);
-       return r;
-}
-
-static int _remove(struct dev_layer *dl)
-{
-       int r;
-       struct dm_task *dmt;
-
        if (_get_flag(dl, VISIBLE))
                log_verbose("Removing %s", dl->name);
        else
                log_very_verbose("Removing %s", dl->name);
 
-       if (!(dmt = _setup_task(dl->name, NULL, 0, DM_DEVICE_REMOVE))) {
-               stack;
-               return 0;
-       }
+       log_debug("Adding target: %" PRIu64 " %" PRIu64 " %s %s",
+                 extent_size * seg->le, extent_size * seg->len, target, params);
 
-       if (!dm_task_no_open_count(dmt))
-               log_error("Failed to disable open_count");
+       log_debug("Adding target: 0 %" PRIu64 " snapshot-origin %s",
+                 dl->lv->size, params);
+       log_debug("Adding target: 0 %" PRIu64 " snapshot %s", size, params);
+       log_debug("Getting device info for %s", dl->name);
 
-       /* Suppress error message if it's still in use - we'll log it later */
-       log_suppress(1);
+       /* Rename? */
+               if ((suffix = rindex(dl->dlid + sizeof(UUID_PREFIX) - 1, '-')))
+                       suffix++;
+               newname = build_dm_name(dm->mem, dm->vg_name, dl->lv->name,
+                                       suffix);
 
-       if ((r = dm_task_run(dmt)))
-               dl->info.exists = 0;
+static int _belong_to_vg(const char *vgname, const char *name)
+{
+       const char *v = vgname, *n = name;
 
-       log_suppress(0);
-
-       dm_task_destroy(dmt);
-
-       if (r && _get_flag(dl, VISIBLE))
-               fs_del_lv(dl->lv);
-
-       _clear_flag(dl, ACTIVE);
-
-       return r;
-}
-
-/*
- * The functions that populate the table in a dm_task as part of
- * a create/reload.
- */
-
-/*
- * Emit a target for a given segment.
- * FIXME: tidy this function.
- */
-static int _emit_target_line(struct dev_manager *dm, struct dm_task *dmt,
-                            struct lv_segment *seg, char *params,
-                            size_t paramsize)
-{
-       uint64_t esize = seg->lv->vg->extent_size;
-       int w = 0;
-       const char *target = NULL;
-       int r;
-
-       if (!seg->segtype->ops->compose_target_line) {
-               log_error("_emit_target: Internal error: Can't handle "
-                         "segment type %s", seg->segtype->name);
-               return 0;
-       }
-
-       if ((r = seg->segtype->ops->compose_target_line(dm, dm->mem,
-                                                       dm->cmd->cft,
-                                                       &dm->target_state, seg,
-                                                       params, paramsize,
-                                                       &target, &w,
-                                                       &dm->
-                                                       pvmove_mirror_count)) <=
-           0) {
-               stack;
-               return r;
-       }
-
-       log_debug("Adding target: %" PRIu64 " %" PRIu64 " %s %s",
-                 esize * seg->le, esize * seg->len, target, params);
-
-       if (!dm_task_add_target(dmt, esize * seg->le, esize * seg->len,
-                               target, params)) {
-               stack;
-               return 0;
-       }
-
-       return 1;
-}
-
-int build_dev_string(struct dev_manager *dm, char *dlid, char *devbuf,
-                    size_t bufsize, const char *desc)
-{
-       struct dev_layer *dl;
-
-       if (!(dl = dm_hash_lookup(dm->layers, dlid))) {
-               log_error("%s device layer %s missing from hash",
-                         desc, dlid);
-               return 0;
-       }
-
-       if (!dm_format_dev(devbuf, bufsize, dl->info.major,
-                          dl->info.minor)) {
-               log_error("Failed to format %s device number for %s as dm "
-                         "target (%u,%u)",
-                         desc, dlid, dl->info.major, dl->info.minor);
-               return 0;
-       }
-
-       return 1;
-}
-
-int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
-                      char *params, size_t paramsize, int *pos, int start_area,
-                      int areas)
-{
-       uint32_t s;
-       int tw = 0;
-       const char *trailing_space;
-       uint64_t esize = seg->lv->vg->extent_size;
-       char devbuf[10];
-       char *dlid;
-
-       for (s = start_area; s < areas; s++, *pos += tw) {
-               trailing_space = (areas - s - 1) ? " " : "";
-               if ((seg_type(seg, s) == AREA_PV &&
-                    (!seg_pvseg(seg, s) ||
-                     !seg_pv(seg, s) ||
-                     !seg_dev(seg, s))) ||
-                   (seg_type(seg, s) == AREA_LV && !seg_lv(seg, s)))
-                       tw = lvm_snprintf(params + *pos, paramsize - *pos,
-                                         "%s 0%s", dm->stripe_filler,
-                                         trailing_space);
-               else if (seg_type(seg, s) == AREA_PV)
-                       tw = lvm_snprintf(params + *pos, paramsize - *pos,
-                                         "%s %" PRIu64 "%s",
-                                         dev_name(seg_dev(seg, s)),
-                                         (seg_pv(seg, s)->pe_start +
-                                          (esize * seg_pe(seg, s))),
-                                         trailing_space);
-               else if (seg_type(seg, s) == AREA_LV) {
-                       if (!(dlid = _build_dlid(dm->mem,
-                                                seg_lv(seg, s)->lvid.s, NULL))) {
-                               stack;
-                               return 0;
-                       }
-                       if (!build_dev_string(dm, dlid,
-                                             devbuf,sizeof(devbuf), "LV")) {
-                               stack;
-                               return 0;
-                       }
-                       tw = lvm_snprintf(params + *pos, paramsize - *pos,
-                                         "%s %" PRIu64 "%s", devbuf,
-                                         esize * seg_le(seg, s),
-                                         trailing_space);
-               } else {
-                       log_error("Internal error: Unassigned area found in LV %s.",
-                                 seg->lv->name);
-                       return 0;
-               }
-
-               if (tw < 0) {
-                       stack;
-                       return -1;
-               }
-       }
-
-       return 1;
-}
-
-static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
-                       struct lv_segment *seg)
-{
-       char *params;
-       size_t paramsize = 4096;
-       int ret;
-
-       do {
-               if (!(params = dm_malloc(paramsize))) {
-                       log_error("Insufficient space for target parameters.");
-                       return 0;
-               }
-
-               ret = _emit_target_line(dm, dmt, seg, params, paramsize);
-               dm_free(params);
-
-               if (!ret)
-                       stack;
-
-               if (ret >= 0)
-                       return ret;
-
-               log_debug("Insufficient space in params[%" PRIsize_t
-                         "] for target parameters.", paramsize);
-
-               paramsize *= 2;
-       } while (paramsize < MAX_TARGET_PARAMSIZE);
-
-       log_error("Target parameter size too big. Aborting.");
-       return 0;
-}
-
-static int _populate_vanilla(struct dev_manager *dm,
-                            struct dm_task *dmt, struct dev_layer *dl)
-{
-       struct lv_segment *seg;
-       struct logical_volume *lv = dl->lv;
-
-       dm->pvmove_mirror_count = 0u;
-
-       list_iterate_items(seg, &lv->segments) {
-               if (!_emit_target(dm, dmt, seg)) {
-                       log_error("Unable to build table for '%s'", lv->name);
-                       return 0;
-               }
-       }
-
-       return 1;
-}
-
-static int _populate_origin(struct dev_manager *dm,
-                           struct dm_task *dmt, struct dev_layer *dl)
-{
-       char *real;
-       char params[PATH_MAX + 32];
-
-       if (!(real = _build_dlid(dm->mem, dl->lv->lvid.s, "real"))) {
-               stack;
-               return 0;
-       }
-
-       if (!build_dev_string(dm, real, params, sizeof(params), "origin")) {
-               stack;
-               return 0;
-       }
-
-       log_debug("Adding target: 0 %" PRIu64 " snapshot-origin %s",
-                 dl->lv->size, params);
-       if (!dm_task_add_target(dmt, UINT64_C(0), dl->lv->size,
-                               "snapshot-origin", params)) {
-               stack;
-               return 0;
-       }
-
-       return 1;
-}
-
-static int _populate_snapshot(struct dev_manager *dm,
-                             struct dm_task *dmt, struct dev_layer *dl)
-{
-       char *origin, *cow;
-       char params[PATH_MAX * 2 + 32];
-       struct lv_segment *snap_seg;
-       char devbufo[10], devbufc[10];
-       uint64_t size;
-
-       if (!(snap_seg = find_cow(dl->lv))) {
-               log_error("Couldn't find snapshot for '%s'.", dl->lv->name);
-               return 0;
-       }
-
-       if (!(origin = _build_dlid(dm->mem, snap_seg->origin->lvid.s,
-                                  "real"))) {
-               stack;
-               return 0;
-       }
-
-       if (!(cow = _build_dlid(dm->mem, snap_seg->cow->lvid.s, "cow"))) {
-               stack;
-               return 0;
-       }
-
-       if (!build_dev_string(dm, origin, devbufo, sizeof(devbufo), "origin")) {
-               stack;
-               return 0;
-       }
-
-       if (!build_dev_string(dm, cow, devbufc, sizeof(devbufc), "cow")) {
-               stack;
-               return 0;
-       }
-
-       if (lvm_snprintf(params, sizeof(params), "%s %s P %d",
-                        devbufo, devbufc, snap_seg->chunk_size) == -1) {
-               stack;
-               return 0;
-       }
-
-       size = (uint64_t) snap_seg->len * snap_seg->origin->vg->extent_size;
-
-       log_debug("Adding target: 0 %" PRIu64 " snapshot %s", size, params);
-       if (!dm_task_add_target(dmt, UINT64_C(0), size, "snapshot", params)) {
-               stack;
-               return 0;
-       }
-
-       return 1;
-}
-
-/*
- * dev_manager implementation.
- */
-struct dev_manager *dev_manager_create(struct cmd_context *cmd,
-                                      const char *vg_name)
-{
-       struct dm_pool *mem;
-       struct dev_manager *dm;
-
-       if (!(mem = dm_pool_create("dev_manager", 16 * 1024))) {
-               stack;
-               return NULL;
-       }
-
-       if (!(dm = dm_pool_alloc(mem, sizeof(*dm)))) {
-               stack;
-               goto bad;
-       }
-
-       dm->cmd = cmd;
-       dm->mem = mem;
-
-       if (!stripe_filler) {
-               stripe_filler = find_config_str(cmd->cft->root,
-                                               "activation/missing_stripe_filler",
-                                               DEFAULT_STRIPE_FILLER);
-       }
-       dm->stripe_filler = stripe_filler;
-
-       if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name))) {
-               stack;
-               goto bad;
-       }
-
-       if (!(dm->layers = dm_hash_create(32))) {
-               stack;
-               goto bad;
-       }
-
-       list_init(&dm->active_list);
-       list_init(&dm->reload_list);
-       list_init(&dm->remove_list);
-       list_init(&dm->suspend_list);
-
-       dm->target_state = NULL;
-
-       return dm;
-
-      bad:
-       dm_pool_destroy(mem);
-       return NULL;
-}
-
-void dev_manager_destroy(struct dev_manager *dm)
-{
-       dm_hash_destroy(dm->layers);
-       dm_pool_destroy(dm->mem);
-}
-
-int dev_manager_snapshot_percent(struct dev_manager *dm,
-                                struct logical_volume *lv, float *percent)
-{
-       char *name;
-       const char *dlid;
-
-       /*
-        * Build a name for the top layer.
-        */
-       if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) {
-               stack;
-               return 0;
-       }
-
-       if (!(dlid = _build_dlid(dm->mem, lv->lvid.s, NULL))) {
-               stack;
-               return 0;
-       }
-
-       /*
-        * Try and get some info on this device.
-        */
-       log_debug("Getting device status percentage for %s", name);
-       if (!(_percent(dm, name, dlid, "snapshot", 0, NULL, percent,
-                      NULL))) {
-               stack;
-               return 0;
-       }
-
-       /* FIXME dm_pool_free ? */
-
-       /* If the snapshot isn't available, percent will be -1 */
-       return 1;
-}
-
-/* FIXME Merge with snapshot_percent, auto-detecting target type */
-/* FIXME Cope with more than one target */
-int dev_manager_mirror_percent(struct dev_manager *dm,
-                              struct logical_volume *lv, int wait,
-                              float *percent, uint32_t *event_nr)
-{
-       char *name;
-       const char *dlid;
-
-       /*
-        * Build a name for the top layer.
-        */
-       if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) {
-               stack;
-               return 0;
-       }
-
-       /* FIXME dm_pool_free ? */
-
-       if (!(dlid = _build_dlid(dm->mem, lv->lvid.s, NULL))) {
-               log_error("dlid build failed for %s", lv->name);
-               return 0;
-       }
-
-       log_debug("Getting device mirror status percentage for %s", name);
-       if (!(_percent(dm, name, dlid, "mirror", wait, lv, percent,
-                      event_nr))) {
-               stack;
-               return 0;
-       }
-
-       return 1;
-}
-
-static struct dev_layer *_create_dev(struct dev_manager *dm, char *name,
-                                    char *dlid)
-{
-       struct dev_layer *dl;
-       char *uuid;
-
-       if (!(dl = dm_pool_zalloc(dm->mem, sizeof(*dl)))) {
-               stack;
-               return NULL;
-       }
-
-       dl->name = name;
-
-       log_debug("Getting device info for %s", dl->name);
-       if (!_info(dl->name, dlid, 0, 0, &dl->info, dm->mem, &uuid)) {
-               stack;
-               return NULL;
-       }
-
-       if (dl->info.exists) {
-               /* If old-style UUID found, convert it. */
-               if (strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1)) {
-                       if (!(dl->dlid = dm_pool_alloc(dm->mem, sizeof(UUID_PREFIX) + strlen(uuid)))) {
-                               stack;
-                               return NULL;
-                       }
-                       memcpy(dl->dlid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1);
-                       memcpy(dl->dlid + sizeof(UUID_PREFIX) - 1, uuid, strlen(uuid));
-               } else
-                       dl->dlid = uuid;
-       } else
-               dl->dlid = dlid;
-
-       list_init(&dl->pre_create);
-       list_init(&dl->pre_suspend);
-
-       if (!dm_hash_insert(dm->layers, dl->dlid, dl)) {
-               stack;
-               return NULL;
-       }
-
-       return dl;
-}
-
-static inline int _read_only_lv(struct logical_volume *lv)
-{
-       return (!(lv->vg->status & LVM_WRITE) || !(lv->status & LVM_WRITE));
-}
-
-static struct dev_layer *_create_layer(struct dev_manager *dm,
-                                      const char *layer,
-                                      struct logical_volume *lv)
-{
-       char *name, *dlid;
-       struct dev_layer *dl;
-
-       if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) {
-               stack;
-               return NULL;
-       }
-
-       if (!(dlid = _build_dlid(dm->mem, lv->lvid.s, layer))) {
-               stack;
-               return NULL;
-       }
-
-       if (!(dl = dm_hash_lookup(dm->layers, dlid)) &&
-           !(dl = _create_dev(dm, name, dlid))) {
-               stack;
-               return NULL;
-       }
-
-       dl->lv = lv;
-
-       if (!_read_only_lv(lv))
-               _set_flag(dl, READWRITE);
-
-       return dl;
-}
-
-static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
-                          int was_origin)
-{
-       /*
-        * only one layer.
-        */
-       struct dev_layer *dl, *dlr;
-       struct lv_segment *seg;
-       uint32_t s;
-
-       if (!(dl = _create_layer(dm, NULL, lv))) {
-               stack;
-               return 0;
-       }
-       dl->populate = _populate_vanilla;
-       if (lv->status & VISIBLE_LV) {
-               _set_flag(dl, VISIBLE);
-               _set_flag(dl, TOPLEVEL);
-       }
-
-       if (lv->status & PVMOVE)
-               _set_flag(dl, TOPLEVEL);
-
-       /* Add dependencies for any LVs that segments refer to */
-       list_iterate_items(seg, &lv->segments) {
-               // When do we need? _set_flag(dl, REMOVE) on the log?
-               if (seg->log_lv &&
-                   !str_list_add(dm->mem, &dl->pre_create,
-                                 _build_dlid(dm->mem, seg->log_lv->lvid.s,
-                                             NULL))) {
-                       stack;
-                       return 0;
-               }
-
-               for (s = 0; s < seg->area_count; s++) {
-                       if (seg_type(seg, s) != AREA_LV)
-                               continue;
-                       if (!str_list_add(dm->mem, &dl->pre_create,
-                                         _build_dlid(dm->mem,
-                                                     seg_lv(seg, s)->
-                                                     lvid.s, NULL))) {
-                               stack;
-                               return 0;
-                       }
-
-                       // ? if (seg_lv(seg, s)->status & PVMOVE)
-                       _set_flag(dl, NOPROPAGATE);
-                       // When do we need? _set_flag(dl, REMOVE) 
-               }
-       }
-
-       if (!was_origin)
-               return 1;
-
-       /* Deactivating the last snapshot */
-       if (!(dlr = _create_layer(dm, "real", lv))) {
-               stack;
-               return 0;
-       }
-
-       dlr->populate = _populate_vanilla;
-       _clear_flag(dlr, VISIBLE);
-       _clear_flag(dlr, TOPLEVEL);
-       _set_flag(dlr, REMOVE);
-
-       /* add the dependency on the real device */
-       if (!str_list_add(dm->mem, &dl->pre_create,
-                         dm_pool_strdup(dm->mem, dlr->dlid))) {
-               stack;
-               return 0;
-       }
-
-       return 1;
-}
-
-static int _expand_origin_real(struct dev_manager *dm,
-                              struct logical_volume *lv)
-{
-       struct dev_layer *dl;
-       const char *real_dlid;
-
-       if (!(dl = _create_layer(dm, "real", lv))) {
-               stack;
-               return 0;
-       }
-       dl->populate = _populate_vanilla;
-       _clear_flag(dl, VISIBLE);
-       _clear_flag(dl, TOPLEVEL);
-
-       /* Size changes must take effect before tables using it are reloaded */
-       _set_flag(dl, RESUME_IMMEDIATE);
-
-       real_dlid = dl->dlid;
-
-       if (!(dl = _create_layer(dm, NULL, lv))) {
-               stack;
-               return 0;
-       }
-       dl->populate = _populate_origin;
-       _set_flag(dl, VISIBLE);
-       _set_flag(dl, TOPLEVEL);
-
-       /* add the dependency on the real device */
-       if (!str_list_add(dm->mem, &dl->pre_create,
-                         dm_pool_strdup(dm->mem, real_dlid))) {
-               stack;
-               return 0;
-       }
-
-       return 1;
-}
-
-static int _expand_origin(struct dev_manager *dm, struct logical_volume *lv)
-{
-       struct logical_volume *active;
-       struct lv_segment *snap_seg;
-       struct lv_list *lvl;
-
-       /*
-        * We only need to create an origin layer if one of our
-        * snapshots is in the active list
-        */
-       list_iterate_items(lvl, &dm->active_list) {
-               active = lvl->lv;
-               if ((snap_seg = find_cow(active)) && (snap_seg->origin == lv))
-                       return _expand_origin_real(dm, lv);
-       }
-
-       /*
-        * We're deactivating the last snapshot
-        */
-       return _expand_vanilla(dm, lv, 1);
-}
-
-static int _expand_snapshot(struct dev_manager *dm, struct logical_volume *lv,
-                           struct lv_segment *snap_seg)
-{
-       /*
-        * snapshot(org, cow)
-        * cow
-        */
-       struct dev_layer *dl;
-       const char *cow_dlid;
-
-       if (!(dl = _create_layer(dm, "cow", lv))) {
-               stack;
-               return 0;
-       }
-       dl->populate = _populate_vanilla;
-       _clear_flag(dl, VISIBLE);
-       _clear_flag(dl, TOPLEVEL);
-       _set_flag(dl, READWRITE);
-
-       cow_dlid = dl->dlid;
-
-       if (!(dl = _create_layer(dm, NULL, lv))) {
-               stack;
-               return 0;
-       }
-       dl->populate = _populate_snapshot;
-       _set_flag(dl, VISIBLE);
-       _set_flag(dl, TOPLEVEL);
-
-       /* add the dependency on the cow device */
-       if (!str_list_add(dm->mem, &dl->pre_create,
-                         dm_pool_strdup(dm->mem, cow_dlid))) {
-               stack;
-               return 0;
-       }
-
-       /* add the dependency on the real origin device */
-       if (!str_list_add(dm->mem, &dl->pre_create,
-                         _build_dlid(dm->mem, snap_seg->origin->lvid.s,
-                                     "real"))) {
-               stack;
-               return 0;
-       }
-
-       /* add the dependency on the visible origin device */
-       if (!str_list_add(dm->mem, &dl->pre_suspend,
-                         _build_dlid(dm->mem, snap_seg->origin->lvid.s,
-                                     NULL))) {
-               stack;
-               return 0;
-       }
-
-       return 1;
-}
-
-/*
- * Inserts the appropriate dev_layers for a logical volume.
- */
-static int _expand_lv(struct dev_manager *dm, struct logical_volume *lv)
-{
-       struct lv_segment *snap_seg;
-
-       /*
-        * FIXME: this doesn't cope with recursive snapshots yet.
-        */
-       if ((snap_seg = find_cow(lv))) {
-               if (lv->vg->status & CLUSTERED) {
-                       log_error("Clustered snapshots are not yet supported");
-                       return 0;
-               }
-               return _expand_snapshot(dm, lv, snap_seg);
-       } else if (lv_is_origin(lv)) {
-               if (lv->vg->status & CLUSTERED) {
-                       log_error("Clustered snapshots are not yet supported");
-                       return 0;
-               }
-               return _expand_origin(dm, lv);
-       }
-
-       return _expand_vanilla(dm, lv, 0);
-}
-
-/*
- * Clears the mark bit on all layers.
- */
-static void _clear_marks(struct dev_manager *dm, int flag)
-{
-       struct dm_hash_node *hn;
-       struct dev_layer *dl;
-
-       dm_hash_iterate(hn, dm->layers) {
-               dl = dm_hash_get_data(dm->layers, hn);
-               _clear_flag(dl, flag);
-       }
-}
-
-/*
- * Propogates marks via the pre_create dependency list.
- */
-static int _trace_layer_marks(struct dev_manager *dm, struct dev_layer *dl,
-                             int flag)
-{
-       struct str_list *strl;
-       const char *dlid;
-       struct dev_layer *dep;
-
-       list_iterate_items(strl, &dl->pre_create) {
-               dlid = strl->str;
-
-               if (!(dep = dm_hash_lookup(dm->layers, dlid))) {
-                       log_error("Couldn't find device layer '%s'.", dlid);
-                       return 0;
-               }
-
-               if (_get_flag(dep, flag))
-                       continue;
-
-               /* FIXME Only propagate LV ACTIVE dependencies for now */
-               if ((flag != ACTIVE) && _get_flag(dl, NOPROPAGATE))
-                       continue;
-
-               _set_flag(dep, flag);
-
-               if (!_trace_layer_marks(dm, dep, flag)) {
-                       stack;
-                       return 0;
-               }
-       }
-
-       return 1;
-}
-
-/*
- * Calls _trace_single for every marked layer.
- */
-static int _trace_all_marks(struct dev_manager *dm, int flag)
-{
-       struct dm_hash_node *hn;
-       struct dev_layer *dl;
-
-       dm_hash_iterate(hn, dm->layers) {
-               dl = dm_hash_get_data(dm->layers, hn);
-               if (_get_flag(dl, flag) && !_trace_layer_marks(dm, dl, flag)) {
-                       stack;
-                       return 0;
-               }
-       }
-
-       return 1;
-}
-
-/*
- * Finds the specified layer.
- */
-static struct dev_layer *_lookup(struct dev_manager *dm,
-                                const char *lvid, const char *layer)
-{
-       char *dlid;
-       struct dev_layer *dl;
-
-       if (!(dlid = _build_dlid(dm->mem, lvid, layer))) {
-               stack;
-               return NULL;
-       }
-
-       dl = dm_hash_lookup(dm->layers, dlid);
-       dm_pool_free(dm->mem, dlid);
-       return dl;
-}
-
-/*
- * Marks the top layers, then traces these through the
- * dependencies.
- */
-static int _mark_lvs(struct dev_manager *dm, struct list *lvs, int flag)
-{
-       struct lv_list *lvl;
-       struct dev_layer *dl;
-
-       list_iterate_items(lvl, lvs) {
-               if (lvl->lv->status & SNAPSHOT)
-                       continue;
-
-               if (!(dl = _lookup(dm, lvl->lv->lvid.s, NULL))) {
-                       stack;
-                       return 0;
-               }
-
-               _set_flag(dl, flag);
-       }
-
-       if (!_trace_all_marks(dm, flag)) {
-               stack;
-               return 0;
-       }
-
-       return 1;
-}
-
-static int _suspend_parents(struct dev_manager *dm, struct dev_layer *dl)
-{
-       struct str_list *strl;
-       struct dev_layer *dep;
-       const char *dlid;
-
-       list_iterate_items(strl, &dl->pre_suspend) {
-               dlid = strl->str;
-
-               if (!(dep = dm_hash_lookup(dm->layers, dlid))) {
-                       log_debug("_suspend_parents couldn't find device "
-                                 "layer '%s' - skipping.", dlid);
-                       continue;
-               }
-
-               if (!strcmp(dep->dlid, dl->dlid)) {
-                       log_error("BUG: pre-suspend loop detected (%s)", dlid);
-                       return 0;
-               }
-
-               if (!_suspend_parents(dm, dep)) {
-                       stack;
-                       return 0;
-               }
-
-               if (dep->info.exists & !_suspend(dep)) {
-                       stack;
-                       return 0;
-               }
-       }
-
-       return 1;
-}
-
-static int _resume_with_deps(struct dev_manager *dm, struct dev_layer *dl)
-{
-       struct str_list *strl;
-       struct dev_layer *dep;
-       const char *dlid;
-
-       list_iterate_items(strl, &dl->pre_create) {
-               dlid = strl->str;
-
-               if (!(dep = dm_hash_lookup(dm->layers, dlid))) {
-                       log_debug("_resume_with_deps couldn't find device "
-                                 "layer '%s' - skipping.", dlid);
-                       continue;
-               }
-
-               if (!strcmp(dep->dlid, dl->dlid)) {
-                       log_error("BUG: pre-create loop detected (%s)", dlid);
-                       return 0;
-               }
-
-               if (!_resume_with_deps(dm, dep)) {
-                       stack;
-                       return 0;
-               }
-       }
-
-       if (dl->info.exists & !_get_flag(dl, SUSPENDED) && !_resume(dl)) {
-               stack;
-               return 0;
-       }
-
-       return 1;
-}
-
-/*
- * Recurses through the tree, ensuring that devices are created
- * in correct order.
- */
-static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
-{
-       struct str_list *strl;
-       struct dev_layer *dep;
-       const char *dlid;
-       char *newname, *suffix;
-
-       /* Suspend? */
-       if (_get_flag(dl, SUSPENDED) &&
-           (!_suspend_parents(dm, dl) || !_suspend(dl))) {
-               stack;
-               return 0;
-       }
-
-       list_iterate_items(strl, &dl->pre_create) {
-               dlid = strl->str;
-
-               if (!(dep = dm_hash_lookup(dm->layers, dlid))) {
-                       log_error("Couldn't find device layer '%s'.", dlid);
-                       return 0;
-               }
-
-               if (!strcmp(dep->dlid, dl->dlid)) {
-                       log_error("BUG: pre-create loop detected (%s)", dlid);
-                       return 0;
-               }
-
-               if (!_create_rec(dm, dep)) {
-                       stack;
-                       return 0;
-               }
-       }
-
-       /* Rename? */
-       if (dl->info.exists) {
-               if ((suffix = rindex(dl->dlid + sizeof(UUID_PREFIX) - 1, '-')))
-                       suffix++;
-               newname = build_dm_name(dm->mem, dm->vg_name, dl->lv->name,
-                                       suffix);
-               if (strcmp(newname, dl->name)) {
-                       if (!_suspend_parents(dm, dl) ||
-                           !_suspend(dl) || !_rename(dm, dl, newname)) {
-                               stack;
-                               return 0;
-                       }
-               }
-       }
-
-       /* Create? */
-       if (!dl->info.exists) {
-               if (!_suspend_parents(dm, dl) ||
-                   !_load(dm, dl, DM_DEVICE_CREATE)) {
-                       stack;
-                       return 0;
-               }
-               return 1;
-       }
-
-       /* Reload? */
-       if (_get_flag(dl, RELOAD) &&
-           (!_suspend_parents(dm, dl) || !_suspend(dl) ||
-            !_load(dm, dl, DM_DEVICE_RELOAD))) {
-               stack;
-               return 0;
-       }
-
-       return 1;
-}
-
-static int _build_all_layers(struct dev_manager *dm, struct volume_group *vg)
-{
-       struct lv_list *lvl;
-
-       /*
-        * Build layers for complete vg.
-        */
-       list_iterate_items(lvl, &vg->lvs) {
-               if (lvl->lv->status & SNAPSHOT)
-                       continue;
-               if (!_expand_lv(dm, lvl->lv)) {
-                       stack;
-                       return 0;
-               }
-       }
-
-       return 1;
-}
-
-static int _fill_in_remove_list(struct dev_manager *dm)
-{
-       struct dm_hash_node *hn;
-       struct dev_layer *dl;
-       struct dl_list *dll;
-
-       dm_hash_iterate(hn, dm->layers) {
-               dl = dm_hash_get_data(dm->layers, hn);
-
-               if (_get_flag(dl, REMOVE))
-                       _clear_flag(dl, ACTIVE);
-
-               if (!_get_flag(dl, ACTIVE)) {
-                       dll = dm_pool_alloc(dm->mem, sizeof(*dll));
-                       if (!dll) {
-                               stack;
-                               return 0;
-                       }
-
-                       dll->dl = dl;
-                       list_add(&dm->remove_list, &dll->list);
-               }
-       }
-
-       return 1;
-}
-
-static int _populate_pre_suspend_lists(struct dev_manager *dm)
-{
-       struct dm_hash_node *hn;
-       struct dev_layer *dl;
-       struct str_list *strl;
-       const char *dlid;
-       struct dev_layer *dep;
-
-       dm_hash_iterate(hn, dm->layers) {
-               dl = dm_hash_get_data(dm->layers, hn);
-
-               list_iterate_items(strl, &dl->pre_suspend) {
-                       dlid = strl->str;
-
-                       if (!(dep = dm_hash_lookup(dm->layers, dlid))) {
-                               log_debug("_populate_pre_suspend_lists: "
-                                         "Couldn't find device layer '%s' - "
-                                         "skipping.", dlid);
-                               continue;
-                       }
-
-                       if (!str_list_add(dm->mem, &dep->pre_create, dl->dlid)) {
-                               stack;
-                               return 0;
-                       }
-               }
-
-               list_iterate_items(strl, &dl->pre_create) {
-                       dlid = strl->str;
-
-                       if (!(dep = dm_hash_lookup(dm->layers, dlid))) {
-                               log_debug("_populate_pre_suspend_lists: "
-                                         "Couldn't find device layer '%s' - "
-                                         "skipping.", dlid);
-                               continue;
-                       }
-
-                       if (!str_list_add(dm->mem, &dep->pre_suspend, dl->dlid)) {
-                               stack;
-                               return 0;
-                       }
-               }
-       }
-
-       return 1;
-}
-
-/*
- * Layers are removed in a top-down manner.
- */
-static int _remove_old_layers(struct dev_manager *dm)
-{
-       int change;
-       struct dl_list *dll;
-       struct list *rh, *n;
-       struct dev_layer *dl;
-
-       do {
-               change = 0;
-               list_iterate_safe(rh, n, &dm->remove_list) {
-                       dl = list_item(rh, struct dl_list)->dl;
-
-                       if (!dl->info.exists) {
-                               list_del(rh);
-                               continue;
-                       }
-
-                       if (_remove(dl)) {
-                               change = 1;
-                               list_del(rh);
-                       }
-               }
-
-       } while (change);
-
-       if (!list_empty(&dm->remove_list)) {
-               list_iterate_items(dll, &dm->remove_list)
-                       log_error("Couldn't deactivate device %s", dll->dl->name);
-               return 0;
-       }
-
-       return 1;
-}
-
-/*
- * The guts of the activation unit, this examines the device
- * layers in the manager, and tries to issue the correct
- * instructions to activate them in order.
- */
-static int _execute(struct dev_manager *dm, struct volume_group *vg)
-{
-       struct dm_hash_node *hn;
-       struct dev_layer *dl;
-
-       if (!_build_all_layers(dm, vg)) {
-               stack;
-               return 0;
-       }
-
-       /*
-        * Mark all layer that need reloading.
-        */
-       _clear_marks(dm, RELOAD);
-       if (!_mark_lvs(dm, &dm->reload_list, RELOAD)) {
-               stack;
-               return 0;
-       }
-
-       /*
-        * Mark all layers that should be active.
-        */
-       _clear_marks(dm, ACTIVE);
-       if (!_mark_lvs(dm, &dm->active_list, ACTIVE)) {
-               stack;
-               return 0;
-       }
-
-       /* 
-        * Mark all layers that should be left suspended.
-        */
-       _clear_marks(dm, SUSPENDED);
-       if (!_mark_lvs(dm, &dm->suspend_list, SUSPENDED)) {
-               stack;
-               return 0;
-       }
-
-       if (!_fill_in_remove_list(dm)) {
-               stack;
-               return 0;
-       }
-
-       if (!_populate_pre_suspend_lists(dm)) {
-               stack;
-               return 0;
-       }
-
-       /*
-        * Now only top level devices will be unmarked.
-        */
-       dm_hash_iterate(hn, dm->layers) {
-               dl = dm_hash_get_data(dm->layers, hn);
-
-               if (_get_flag(dl, ACTIVE) && _get_flag(dl, TOPLEVEL))
-                       if (!_create_rec(dm, dl)) {
-                               stack;
-                               return 0;
-                       }
-       }
-
-       /* Resume devices */
-       dm_hash_iterate(hn, dm->layers) {
-               dl = dm_hash_get_data(dm->layers, hn);
-
-               if (!_resume_with_deps(dm, dl)) {
-                       stack;
-                       return 0;
-               }
-       }
-
-       if (!_remove_old_layers(dm)) {
-               stack;
-               return 0;
-       }
-
-       return 1;
-}
-
-/*
- * ATM we decide which vg a layer belongs to by
- * looking at the beginning of the device
- * name.
- */
-static int _belong_to_vg(const char *vgname, const char *name)
-{
-       const char *v = vgname, *n = name;
-
-       while (*v) {
-               if ((*v != *n) || (*v == '-' && *(++n) != '-'))
-                       return 0;
-               v++, n++;
-       }
-
-       if (*n == '-' && *(n + 1) != '-')
-               return 1;
-       else
-               return 0;
-}
-
-static int _add_existing_layer(struct dev_manager *dm, const char *name)
-{
-       struct dev_layer *dl;
-       char *copy;
-
-       log_debug("Found existing layer '%s'", name);
-
-       if (!(copy = dm_pool_strdup(dm->mem, name))) {
-               stack;
-               return 0;
-       }
-
-       if (!(dl = _create_dev(dm, copy, (char *)""))) {
-               stack;
-               return 0;
-       }
-
-       return 1;
-}
-
-static int _scan_existing_devices(struct dev_manager *dm)
-{
-       int r = 0;
-       struct dm_names *names;
-       unsigned next = 0;
-
-       struct dm_task *dmt;
-
-       if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
-               return 0;
-
-       if (!dm_task_run(dmt))
-               goto out;
-
-       if (!(names = dm_task_get_names(dmt)))
-               goto out;
-
-       r = 1;
-       if (!names->dev)
-               goto out;
-
-       do {
-               names = (void *) names + next;
-               if (_belong_to_vg(dm->vg_name, names->name) &&
-                   !_add_existing_layer(dm, names->name)) {
-                       stack;
-                       r = 0;
-                       break;
-               }
-               next = names->next;
-       } while (next);
-
-      out:
-       dm_task_destroy(dmt);
-       return r;
-}
-
-static int _add_lv(struct dm_pool *mem,
-                  struct list *head, struct logical_volume *lv)
-{
-       struct lv_list *lvl;
-
-       if (!(lvl = dm_pool_alloc(mem, sizeof(*lvl)))) {
-               stack;
-               return 0;
-       }
-
-       lvl->lv = lv;
-       list_add(head, &lvl->list);
-
-       return 1;
-}
-
-static int _add_lvs(struct dm_pool *mem,
-                   struct list *head, struct logical_volume *origin)
-{
-       struct lv_segment *snap_seg;
-       struct lv_list *lvl;
-
-       list_iterate_items(lvl, &origin->vg->lvs) {
-               if (lvl->lv->status & SNAPSHOT)
-                       continue;
-               if ((snap_seg = find_cow(lvl->lv)) && snap_seg->origin == origin)
-                       if (!_add_lv(mem, head, lvl->lv))
-                               return 0;
-       }
-
-       return _add_lv(mem, head, origin);
-}
-
-static void _remove_lv(struct list *head, struct logical_volume *lv)
-{
-       struct lv_list *lvl;
-
-       list_iterate_items(lvl, head) {
-               if (lvl->lv == lv) {
-                       list_del(&lvl->list);
-                       break;
-               }
-       }
-}
-
-static int _remove_lvs(struct dev_manager *dm, struct logical_volume *lv)
-{
-       struct logical_volume *active, *old_origin;
-       struct lv_segment *snap_seg;
-       struct list *active_head;
-       struct lv_list *lvl;
-
-       active_head = &dm->active_list;
-
-       /* Remove any snapshots with given origin */
-       list_iterate_items(lvl, active_head) {
-               active = lvl->lv;
-               if ((snap_seg = find_cow(active)) && snap_seg->origin == lv) {
-                       _remove_lv(active_head, active);
-               }
+       while (*v) {
+               if ((*v != *n) || (*v == '-' && *(++n) != '-'))
+                       return 0;
+               v++, n++;
        }
 
-       _remove_lv(active_head, lv);
+       if (*n == '-' && *(n + 1) != '-')
+               return 1;
+       else
+               return 0;
+}
 
        if (!(snap_seg = find_cow(lv)))
                return 1;
@@ -2030,313 +551,440 @@ static int _remove_lvs(struct dev_manager *dm, struct logical_volume *lv)
                }
        }
 
-       return _add_lvs(dm->mem, &dm->reload_list, old_origin);
+#endif
+
+/*************************/
+/*  NEW CODE STARTS HERE */
+/*************************/
+
+int dev_manager_lv_mknodes(const struct logical_volume *lv)
+{
+       char *name;
+
+       if (!(name = build_dm_name(lv->vg->cmd->mem, lv->vg->name,
+                                  lv->name, NULL)))
+               return_0;
+
+       return fs_add_lv(lv, name);
 }
 
-static int _remove_suspended_lvs(struct dev_manager *dm,
-                                struct logical_volume *lv)
+int dev_manager_lv_rmnodes(const struct logical_volume *lv)
 {
-       struct logical_volume *suspended;
-       struct lv_segment *snap_seg;
-       struct list *suspend_head;
-       struct lv_list *lvl;
+       return fs_del_lv(lv);
+}
+
+static int _add_dev_to_deptree(struct dev_manager *dm, struct deptree *dtree,
+                              struct logical_volume *lv, const char *layer)
+{
+       char *dlid, *name;
+       struct dm_info info;
 
-       suspend_head = &dm->suspend_list;
+       if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
+               return_0;
 
-       /* Remove from list any snapshots with given origin */
-       list_iterate_items(lvl, suspend_head) {
-               suspended = lvl->lv;
-               if ((snap_seg = find_cow(suspended)) &&
-                   snap_seg->origin == lv) {
-                       _remove_lv(suspend_head, suspended);
-               }
+       if (!(dlid = build_dlid(dm, lv->lvid.s, layer)))
+               return_0;
+
+        log_debug("Getting device info for %s [%s]", name, dlid);
+        if (!_info(name, dlid, 0, 1, &info, dm->mem, NULL)) {
+                log_error("Failed to get info for %s [%s].", name, dlid);
+                return 0;
+        }
+
+       if (info.exists && !dm_deptree_add_dev(dtree, info.major, info.minor)) {
+               log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to deptree",
+                         info.major, info.minor);
+               return 0;
        }
 
-       _remove_lv(suspend_head, lv);
+       return 1;
+}
+
+/*
+ * Add LV and any known dependencies
+ */
+static int _add_lv_to_deptree(struct dev_manager *dm, struct deptree *dtree, struct logical_volume *lv)
+{
+       if (!_add_dev_to_deptree(dm, dtree, lv, NULL))
+               return_0;
+
+       /* FIXME Can we avoid doing this every time? */
+       if (!_add_dev_to_deptree(dm, dtree, lv, "real"))
+               return_0;
+
+       if (!_add_dev_to_deptree(dm, dtree, lv, "cow"))
+               return_0;
 
        return 1;
 }
 
-static int _targets_present(struct dev_manager *dm, struct list *lvs)
+static struct deptree *_create_partial_deptree(struct dev_manager *dm, struct logical_volume *lv)
 {
-       struct logical_volume *lv;
-       struct lv_list *lvl;
-       struct segment_type *segtype;
-       struct lv_segment *seg;
-       int snapshots = 0, mirrors = 0;
-
-       list_iterate_items(lvl, lvs) {
-               lv = lvl->lv;
-
-               if (!snapshots)
-                       if (lv_is_cow(lv) || lv_is_origin(lv))
-                               snapshots = 1;
-
-               if (!mirrors)
-                       if (lv->status & PVMOVE)
-                               mirrors = 1;
-
-               if (lv->status & VIRTUAL) {
-                       list_iterate_items(seg, &lv->segments) {
-                               if (seg->segtype->ops->target_present &&
-                                   !seg->segtype->ops->target_present()) {
-                                       log_error("Can't expand LV: %s target "
-                                                 "support missing "
-                                                 "from kernel?",
-                                                 seg->segtype->name);
-                                       return 0;
-                               }
-                       }
-               }
-       }
+       struct deptree *dtree;
+       struct list *snh, *snht;
 
-       if (mirrors) {
-               if (!(segtype = get_segtype_from_string(dm->cmd, "mirror"))) {
-                       log_error("Can't expand LV: Mirror support "
-                                 "missing from tools?");
-                       return 0;
-               }
+       if (!(dtree = dm_deptree_create())) {
+               log_error("Partial deptree creation failed for %s.", lv->name);
+               return NULL;
+       }
 
-               if (!segtype->ops->target_present ||
-                   !segtype->ops->target_present()) {
-                       log_error("Can't expand LV: Mirror support missing "
-                                 "from kernel?");
-                       return 0;
-               }
+       if (!_add_lv_to_deptree(dm, dtree, lv)) {
+               stack;
+               goto fail;
        }
 
-       if (snapshots) {
-               if (!(segtype = get_segtype_from_string(dm->cmd, "snapshot"))) {
-                       log_error("Can't expand LV: Snapshot support "
-                                 "missing from tools?");
-                       return 0;
+       /* Add any snapshots of this LV */
+       list_iterate_safe(snh, snht, &lv->snapshot_segs)
+               if (!_add_lv_to_deptree(dm, dtree, list_struct_base(snh, struct lv_segment, origin_list)->cow)) {
+                       stack;
+                       goto fail;
                }
 
-               if (!segtype->ops->target_present ||
-                   !segtype->ops->target_present()) {
-                       log_error("Can't expand LV: Snapshot support missing "
-                                 "from kernel?");
-                       return 0;
-               }
-       }
+       return dtree;
 
-       return 1;
+fail:
+       dm_deptree_free(dtree);
+       return NULL;
 }
 
-static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg)
+int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
+                  struct deptree_node *node, int start_area, int areas)
 {
+       uint64_t extent_size = seg->lv->vg->extent_size;
+       uint32_t s;
        char *dlid;
-       struct lv_list *lvl;
-       struct dev_layer *dl;
-
-       list_iterate_items(lvl, &vg->lvs) {
-               if (lvl->lv->status & SNAPSHOT)
-                       continue;
 
-               if (!(dlid = _build_dlid(dm->mem, lvl->lv->lvid.s, NULL))) {
-                       stack;
+       for (s = start_area; s < areas; s++) {
+               if ((seg_type(seg, s) == AREA_PV &&
+                    (!seg_pvseg(seg, s) ||
+                     !seg_pv(seg, s) ||
+                     !seg_dev(seg, s))) ||
+                   (seg_type(seg, s) == AREA_LV && !seg_lv(seg, s)))
+                       dm_deptree_node_add_target_area(node,
+                                                       dm->stripe_filler,
+                                                       NULL, 0);
+               else if (seg_type(seg, s) == AREA_PV)
+                       dm_deptree_node_add_target_area(node,
+                                                       dev_name(seg_dev(seg, s)),
+                                                       NULL,
+                                                       (seg_pv(seg, s)->pe_start +
+                                                        (extent_size * seg_pe(seg, s))));
+               else if (seg_type(seg, s) == AREA_LV) {
+                       if (!(dlid = build_dlid(dm,
+                                                seg_lv(seg, s)->lvid.s,
+                                                NULL)))
+                               return_0;
+                       dm_deptree_node_add_target_area(node, NULL, dlid,
+                                                       extent_size * seg_le(seg, s));
+               } else {
+                       log_error("Internal error: Unassigned area found in LV %s.",
+                                 seg->lv->name);
                        return 0;
                }
+       }
 
-               dl = dm_hash_lookup(dm->layers, dlid);
-               dm_pool_free(dm->mem, dlid);
+       return 1;
+}
 
-               if (dl) {
-                       log_debug("Found active lv %s%s", lvl->lv->name,
-                                 dl->info.suspended ? " (suspended)" : "");
+static int _add_origin_target_to_deptree(struct dev_manager *dm,
+                                        struct deptree *dtree,
+                                        struct deptree_node *dnode,
+                                        struct logical_volume *lv)
+{
+       const char *real_dlid;
 
-                       if (!_add_lv(dm->mem, &dm->active_list, lvl->lv)) {
-                               stack;
-                               return 0;
-                       }
+       if (!(real_dlid = build_dlid(dm, lv->lvid.s, "real")))
+               return_0;
 
-                       if (dl->info.suspended) {
-                               if (!_add_lv(dm->mem, &dm->suspend_list, lvl->lv)) {
-                                       stack;
-                                       return 0;
-                               }
-                       }
-               }
-       }
+       if (!dm_deptree_node_add_snapshot_origin_target(dnode, lv->size, real_dlid))
+               return_0;
 
        return 1;
 }
 
-static int _action_activate(struct dev_manager *dm, struct logical_volume *lv)
+static int _add_snapshot_target_to_deptree(struct dev_manager *dm,
+                                          struct deptree *dtree,
+                                          struct deptree_node *dnode,
+                                          struct logical_volume *lv)
 {
-       // Replace with deptree code for lv + known deps only.
-       if (!_scan_existing_devices(dm)) {
-               stack;
-               return 0;
-       }
-
-       if (!_fill_in_active_list(dm, lv->vg)) {
-               stack;
-               return 0;
-       }
+       const char *origin_dlid;
+       const char *cow_dlid;
+       struct lv_segment *snap_seg;
+       uint64_t size;
 
-       /* Get into known state - remove from active list if present */
-       if (!_remove_lvs(dm, lv)) {
-               stack;
+       if (!(snap_seg = find_cow(lv))) {
+               log_error("Couldn't find snapshot for '%s'.", lv->name);
                return 0;
        }
 
-       /* Add to active & reload lists */
-       if (!_add_lvs(dm->mem, &dm->reload_list, lv) ||
-           !_add_lvs(dm->mem, &dm->active_list, lv)) {
-               stack;
-               return 0;
-       }
+       if (!(origin_dlid = build_dlid(dm, snap_seg->origin->lvid.s, "real")))
+               return_0;
 
-       /* Get into known state - remove from suspend list if present */
-       if (!_remove_suspended_lvs(dm, lv)) {
-               stack;
-               return 0;
-       }
+       if (!(cow_dlid = build_dlid(dm, snap_seg->cow->lvid.s, "cow")))
+               return_0;
 
-       if (!_targets_present(dm, &dm->active_list) ||
-           !_targets_present(dm, &dm->reload_list)) {
-               stack;
-               return 0;
-       }
+       size = (uint64_t) snap_seg->len * snap_seg->origin->vg->extent_size;
 
-       if (!_execute(dm, lv->vg)) {
-               stack;
-               return 0;
-       }
+       if (!dm_deptree_node_add_snapshot_target(dnode, size, origin_dlid, cow_dlid, 1, snap_seg->chunk_size))
+               return_0;
 
        return 1;
 }
 
-int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv)
+static int _add_target_to_deptree(struct dev_manager *dm,
+                                 struct deptree *dtree,
+                                 struct deptree_node *dnode,
+                                 struct lv_segment *seg)
 {
-       return _action_activate(dm, lv);
+       uint64_t extent_size = seg->lv->vg->extent_size;
+
+       if (!seg->segtype->ops->add_target_line) {
+               log_error("_emit_target: Internal error: Can't handle "
+                         "segment type %s", seg->segtype->name);
+               return 0;
+       }
+
+       return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd->cft,
+                                                 &dm->target_state, seg,
+                                                 dnode,
+                                                 extent_size * seg->len,
+                                                 &dm-> pvmove_mirror_count);
 }
 
-int dev_manager_lv_mknodes(const struct logical_volume *lv)
+static int _add_new_lv_to_deptree(struct dev_manager *dm, struct deptree *dtree,
+                                 struct logical_volume *lv, const char *layer);
+
+static int _add_segment_to_deptree(struct dev_manager *dm,
+                                  struct deptree *dtree,
+                                  struct deptree_node *dnode,
+                                  struct lv_segment *seg,
+                                  const char *layer)
 {
-       char *name;
+       uint32_t s;
+       struct list *snh;
 
-       if (!(name = build_dm_name(lv->vg->cmd->mem, lv->vg->name,
-                                  lv->name, NULL))) {
-               stack;
+       /* Ensure required device-mapper targets are loaded */
+       if (seg->segtype->ops->target_present &&
+           !seg->segtype->ops->target_present()) {
+               log_error("Can't expand LV %s: %s target support missing "
+                         "from kernel?", seg->lv->name, seg->segtype->name);
                return 0;
        }
 
-       return fs_add_lv(lv, name);
-}
+       /* Add mirror log */
+       if (seg->log_lv &&
+           !_add_new_lv_to_deptree(dm, dtree, seg->log_lv, NULL))
+               return_0;
 
-int dev_manager_lv_rmnodes(const struct logical_volume *lv)
-{
-       return fs_del_lv(lv);
-}
+       /* If this is a snapshot origin, add real LV */
+       if (lv_is_origin(seg->lv) && !layer) {
+               if (seg->lv->vg->status & CLUSTERED) {
+                       log_error("Clustered snapshots are not yet supported");
+                       return 0;
+               }
+               if (!_add_new_lv_to_deptree(dm, dtree, seg->lv, "real"))
+                       return_0;
+       } else if (lv_is_cow(seg->lv) && !layer) {
+               if (!_add_new_lv_to_deptree(dm, dtree, seg->lv, "cow"))
+                       return_0;
+       } else {
+               /* Add any LVs used by this segment */
+               for (s = 0; s < seg->area_count; s++)
+                       if ((seg_type(seg, s) == AREA_LV) &&
+                           (!_add_new_lv_to_deptree(dm, dtree, seg_lv(seg, s), NULL)))
+                               return_0;
+       }
+
+       /* Now we've added its dependencies, we can add the target itself */
+       if (lv_is_origin(seg->lv) && !layer) {
+               if (!_add_origin_target_to_deptree(dm, dtree, dnode, seg->lv))
+                       return_0;
+       } else if (lv_is_cow(seg->lv) && !layer) {
+               if (!_add_snapshot_target_to_deptree(dm, dtree, dnode, seg->lv))
+                       return_0;
+       } else if (!_add_target_to_deptree(dm, dtree, dnode, seg))
+               return_0;
+
+       if (lv_is_origin(seg->lv) && !layer)
+               /* Add any snapshots of this LV */
+               list_iterate(snh, &seg->lv->snapshot_segs)
+                       if (!_add_new_lv_to_deptree(dm, dtree, list_struct_base(snh, struct lv_segment, origin_list)->cow, NULL))
+                               return_0;
 
-void dev_manager_exit(void)
-{
-       dm_lib_exit();
+       return 1;
 }
 
-/*
- * New deactivation code
- */
-static int _add_lv_to_deptree(struct dev_manager *dm, struct deptree *dtree, struct logical_volume *lv)
+static int _add_new_lv_to_deptree(struct dev_manager *dm, struct deptree *dtree,
+                                 struct logical_volume *lv, const char *layer)
 {
-       char *dlid, *name;
-       struct dm_info info;
+       struct lv_segment *seg;
+       struct lv_layer *lvlayer;
+       struct deptree_node *dnode;
+       char *name, *dlid;
 
-       if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) {
-               stack;
-               return 0;
-       }
+       if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
+               return_0;
 
-       if (!(dlid = _build_dlid(dm->mem, lv->lvid.s, NULL))) {
-               stack;
-               return 0;
-       }
+       if (!(dlid = build_dlid(dm, lv->lvid.s, layer)))
+               return_0;
 
-        log_debug("Getting device info for %s [%s]", name, dlid);
-        if (!_info(name, dlid, 0, 1, &info, dm->mem, NULL)) {
-                stack;
-                return 0;
-        }
+       /* We've already processed this node if it already has a context ptr */
+       if ((dnode = dm_deptree_find_node_by_uuid(dtree, dlid)) &&
+           dm_deptree_node_get_context(dnode))
+               return 1;
 
-       if (info.exists && !dm_deptree_add_dev(dtree, info.major, info.minor)) {
-               log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to deptree",
-                         info.major, info.minor);
+       /* FIXME How do we determine whether a pre-existing node need reloading or not? */
+       if (!(lvlayer = dm_pool_alloc(dm->mem, sizeof(*lvlayer)))) {
+               log_error("_add_new_lv_to_deptree: pool alloc failed for %s %s.", lv->name, layer);
                return 0;
        }
 
-       /* FIXME Check for any related nodes left behind e.g. -real */
+       lvlayer->lv = lv;
+
+       /*
+        * Add LV to deptree.
+        * If we're working with precommitted metadata, clear any
+        * existing inactive table left behind.
+        * Major/minor settings only apply to the visible layer.
+        */
+       if (!(dnode = dm_deptree_add_new_dev(dtree, name, dlid,
+                                            layer ? lv->major : 0,
+                                            layer ? lv->minor : 0,
+                                            _read_only_lv(lv),
+                                            lv->vg->status & PRECOMMITTED,
+                                            lvlayer)))
+               return_0;
+
+       /* Store existing name so we can do rename later */
+       lvlayer->old_name = dm_deptree_node_get_name(dnode);
+
+       /* Create table */
+       dm->pvmove_mirror_count = 0u;
+       list_iterate_items(seg, &lv->segments) {
+               if (!_add_segment_to_deptree(dm, dtree, dnode, seg, layer))
+                       return_0;
+               /* These aren't real segments in the LVM2 metadata */
+               if (lv_is_origin(lv) && !layer)
+                       break;
+               if (lv_is_cow(lv) && !layer)
+                       break;
+       }
 
        return 1;
 }
 
-static struct deptree *_create_partial_deptree(struct dev_manager *dm, struct logical_volume *lv)
+/*
+ * Create LV symlinks for children of supplied root node.
+ */
+static int _create_lv_symlinks(struct dev_manager *dm, struct deptree_node *root)
 {
-       struct deptree *dtree;
-       struct list *snh, *snht;
+       void *handle = NULL;
+       struct deptree_node *child;
+       struct lv_layer *lvlayer;
+       char *vgname, *lvname, *layer;
+       const char *name;
+       int r = 1;
 
-       if (!(dtree = dm_deptree_create())) {
-               log_error("partial deptree creation failed");
-               return NULL;
-       }
+       while ((child = dm_deptree_next_child(&handle, root, 0))) {
+               if (!(lvlayer = (struct lv_layer *) dm_deptree_node_get_context(child)))
+                       continue;
 
-       if (!_add_lv_to_deptree(dm, dtree, lv)) {
-               stack;
-               goto fail;
-       }
+               /* Detect rename */
+               name = dm_deptree_node_get_name(child);
 
-       /* Add any snapshots of this LV */
-       list_iterate_safe(snh, snht, &lv->snapshot_segs) {
-               if (!_add_lv_to_deptree(dm, dtree, list_struct_base(snh, struct lv_segment, origin_list)->cow)) {
-                       stack;
-                       goto fail;
-               }
+               if (name && lvlayer->old_name && *lvlayer->old_name && strcmp(name, lvlayer->old_name)) {
+                       if (!split_dm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
+                               log_error("_create_lv_symlinks: Couldn't split up old device name %s", lvlayer->old_name);
+                               return 0;
+                       }
+                       fs_rename_lv(lvlayer->lv, name, lvname);
+               } else if (!dev_manager_lv_mknodes(lvlayer->lv))
+                       r = 0;
        }
 
-       return dtree;
+       return r;
+}
 
-fail:
-       dm_deptree_free(dtree);
-       return NULL;
+static int _clean_tree(struct dev_manager *dm, struct logical_volume *lv, struct deptree_node *root)
+{
+       void *handle = NULL;
+       struct deptree_node *child;
+       char *vgname, *lvname, *layer;
+       const char *name, *uuid;
+
+       while ((child = dm_deptree_next_child(&handle, root, 0))) {
+               if (!(name = dm_deptree_node_get_name(child)))
+                       continue;
+
+               if (!(uuid = dm_deptree_node_get_uuid(child)))
+                       continue;
+
+               if (!split_dm_name(dm->mem, name, &vgname, &lvname, &layer)) {
+                       log_error("_clean_tree: Couldn't split up device name %s.", name);
+                       return 0;
+               }
+
+               /* Not meant to be top level? */
+               if (!*layer)
+                       continue;
+
+               if (!dm_deptree_deactivate_children(root, uuid, strlen(uuid)))
+                       return_0;
+       }
+
+       return 1;
 }
 
-/*
- * Deactivate LV and all devices it references that nothing else has open.
- */
 static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, action_t action)
 {
        struct deptree *dtree;
-       struct deptree_node *dnode;
+       struct deptree_node *root;
        char *dlid;
        int r = 0;
 
-       if (!(dtree = _create_partial_deptree(dm, lv))) {
-               stack;
-               return 0;
-       }
+       if (!(dtree = _create_partial_deptree(dm, lv)))
+               return_0;
 
-       if (!(dnode = dm_deptree_find_node(dtree, 0, 0))) {
+       if (!(root = dm_deptree_find_node(dtree, 0, 0))) {
                log_error("Lost dependency tree root node");
                goto out;
        }
 
-       if (!(dlid = _build_dlid(dm->mem, lv->lvid.s, NULL))) {
-               log_error("dlid build failed for %s", lv->name);
-               goto out;
-       }
+       if (!(dlid = build_dlid(dm, lv->lvid.s, NULL)))
+               goto_out;
 
        /* Only process nodes with uuid of "LVM-" plus VG id. */
        switch(action) {
+       case CLEAN:
+               /* Deactivate any unused non-toplevel nodes */
+               if (!_clean_tree(dm, lv, root))
+                       goto_out;
+               break;
        case DEACTIVATE:
-               if (!dm_deptree_deactivate_children(dnode, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1)) {
-                       stack;
-                       goto out;
-               }
+               /* Deactivate LV and all devices it references that nothing else has open. */
+               if (!dm_deptree_deactivate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
+                       goto_out;
                break;
        case SUSPEND:
-               if (!dm_deptree_suspend_children(dnode, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1)) {
-                       stack;
+               if (!dm_deptree_suspend_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
+                       goto_out;
+               break;
+       case PRELOAD:
+       case ACTIVATE:
+               /* Add all required new devices to tree */
+               if (!_add_new_lv_to_deptree(dm, dtree, lv, NULL))
+                       goto_out;
+
+               /* Preload any devices required before any suspensions */
+               if (!dm_deptree_preload_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
+                       goto_out;
+
+               if ((action == ACTIVATE) &&
+                   !dm_deptree_activate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
+                       goto_out;
+
+               if (!_create_lv_symlinks(dm, root)) {
+                       log_error("Failed to create symlinks for %s.", lv->name);
                        goto out;
                }
                break;
@@ -2353,6 +1001,18 @@ out:
        return r;
 }
 
+int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv)
+{
+       if (!_tree_action(dm, lv, ACTIVATE))
+               return_0;
+
+       return _tree_action(dm, lv, CLEAN);
+}
+
+int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv)
+{
+       return _tree_action(dm, lv, PRELOAD);
+}
 
 int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
 {
@@ -2378,7 +1038,7 @@ int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
                               struct volume_group *vg)
 {
        struct deptree *dtree;
-       struct deptree_node *dnode;
+       struct deptree_node *root;
        char dlid[sizeof(UUID_PREFIX) + sizeof(struct id) - 1];
        int r = 1;
 
@@ -2396,15 +1056,13 @@ int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
        memcpy(dlid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1);
        memcpy(dlid + sizeof(UUID_PREFIX) - 1, &vg->id.uuid[0], sizeof(vg->id));
 
-       if (!(dnode = dm_deptree_find_node(dtree, 0, 0))) {
+       if (!(root = dm_deptree_find_node(dtree, 0, 0))) {
                log_error("Lost dependency tree root node");
                goto out;
        }
 
-       if (dm_deptree_children_use_uuid(dnode, dlid, sizeof(UUID_PREFIX) + sizeof(vg->id) - 1)) {
-               stack;
-               goto out;
-       }
+       if (dm_deptree_children_use_uuid(root, dlid, sizeof(UUID_PREFIX) + sizeof(vg->id) - 1))
+               goto_out;
 
        r = 0;
 
index 6a7519feb52825e2b6af7cb81dda2a34d6935141..19b6572c2e596cc9fbc131df09bd0fbbc625ff86 100644 (file)
@@ -47,6 +47,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
                               float *percent, uint32_t *event_nr);
 int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
 int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
+int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv);
 int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
 
 int dev_manager_lv_mknodes(const struct logical_volume *lv);
index c51079b6462f4a02e32e22e900c2aa391c9f36bf..8a8b8ac7ec6fe74a4081a27a7f01f86d4d2c655c 100644 (file)
@@ -23,6 +23,9 @@ int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
                       char *params, size_t paramsize, int *pos,
                       int start_area, int areas);
 
+int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
+                   struct deptree_node *node, int start_area, int areas);
+
 int build_dev_string(struct dev_manager *dm, char *dlid, char *devbuf,
                     size_t bufsize, const char *desc);
 
index 906d1df178c0eecd8b45016131377081c04636eb..a41619af919ad548e6919a404ed0a939397aae7a 100644 (file)
@@ -38,18 +38,13 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
 }
 
 #ifdef DEVMAPPER_SUPPORT
-static int _compose_target_line(struct dev_manager *dm, struct dm_pool *mem,
+static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
                                struct config_tree *cft, void **target_state,
-                               struct lv_segment *seg, char *params,
-                               size_t paramsize, const char **target, int *pos,
+                               struct lv_segment *seg,
+                               struct deptree_node *node, uint64_t len,
                                uint32_t *pvmove_mirror_count)
 {
-       /*   error */
-
-       *target = "error";
-       *params = '\0';
-
-       return 1;
+       return dm_deptree_node_add_error_target(node, len);
 }
 
 static int _target_present(void)
@@ -57,8 +52,10 @@ static int _target_present(void)
        static int checked = 0;
        static int present = 0;
 
-       if (!checked)
-               present = target_present("error");
+       /* Reported truncated in older kernels */
+       if (!checked &&
+           (target_present("error", 0) || target_present("erro", 0)))
+               present = 1;
 
        checked = 1;
        return present;
@@ -74,7 +71,7 @@ static struct segtype_handler _error_ops = {
        name:_name,
        merge_segments:_merge_segments,
 #ifdef DEVMAPPER_SUPPORT
-       compose_target_line:_compose_target_line,
+       add_target_line:_add_target_line,
        target_present:_target_present,
 #endif
        destroy:_destroy,
@@ -84,16 +81,14 @@ struct segment_type *init_error_segtype(struct cmd_context *cmd)
 {
        struct segment_type *segtype = dm_malloc(sizeof(*segtype));
 
-       if (!segtype) {
-               stack;
-               return NULL;
-       }
+       if (!segtype)
+               return_NULL;
 
        segtype->cmd = cmd;
        segtype->ops = &_error_ops;
        segtype->name = "error";
        segtype->private = NULL;
-       segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL;
+       segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
 
        log_very_verbose("Initialised segtype: %s", segtype->name);
 
index 4c59055988a020883a883454ab969329d42b29d6..36eed30fd0d5d7bf602b40338120a83284f8791e 100644 (file)
@@ -124,4 +124,8 @@ void print_log(int level, const char *file, int line, const char *format, ...)
 #define log_sys_debug(x, y) \
                log_debug("%s: %s failed: %s", y, x, strerror(errno))
 
+#define return_0       do { stack; return 0; } while (0)
+#define return_NULL    do { stack; return NULL; } while (0)
+#define goto_out       do { stack; goto out; } while (0)
+
 #endif
index 9e03a6bb2630571bd389226d0ef8b030e42bdd9c..b6b5e4e21db340661dd653d3038fefb6ef354301 100644 (file)
@@ -204,10 +204,8 @@ int create_mirror_layers(struct alloc_handle *ah,
                                                  MIRROR_IMAGE);
 
        /* Already got a non-mirrored area to be converted? */
-       if (!first_area) {
+       if (first_area)
                _move_lv_segments(img_lvs[0], lv);
-               lv->status |= MIRRORED;
-       }
 
        if (!lv_add_mirror_segment(ah, lv, img_lvs, num_mirrors, segtype,
                                   0, region_size, log_lv)) {
@@ -216,6 +214,8 @@ int create_mirror_layers(struct alloc_handle *ah,
                return 0;
        }
 
+       lv->status |= MIRRORED;
+
        return 1;
 }
 
index 7ac0887ede4e076ddd9a376bb7f552a806abde89..415feb0b75e9347efce4f16b59026622eab7c097 100644 (file)
@@ -31,12 +31,14 @@ struct dev_manager;
 #define SEG_SNAPSHOT           0x00000008
 #define SEG_FORMAT1_SUPPORT    0x00000010
 #define SEG_VIRTUAL            0x00000020
+#define SEG_CANNOT_BE_ZEROED   0x00000040
 
 #define seg_is_mirrored(seg)   ((seg)->segtype->flags & SEG_AREAS_MIRRORED ? 1 : 0)
 #define seg_is_striped(seg)    ((seg)->segtype->flags & SEG_AREAS_STRIPED ? 1 : 0)
 #define seg_is_snapshot(seg)   ((seg)->segtype->flags & SEG_SNAPSHOT ? 1 : 0)
 #define seg_is_virtual(seg)    ((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0)
 #define seg_can_split(seg)     ((seg)->segtype->flags & SEG_CAN_SPLIT ? 1 : 0)
+#define seg_cannot_be_zeroed(seg) ((seg)->segtype->flags & SEG_CANNOT_BE_ZEROED ? 1 : 0)
 
 #define segtype_is_striped(segtype)    ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
 #define segtype_is_mirrored(segtype)   ((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0)
@@ -64,12 +66,11 @@ struct segtype_handler {
                            struct dm_hash_table * pv_hash);
        int (*merge_segments) (struct lv_segment * seg1,
                               struct lv_segment * seg2);
-       int (*compose_target_line) (struct dev_manager * dm, struct dm_pool * mem,
-                                   struct config_tree * cft,
-                                   void **target_state,
-                                   struct lv_segment * seg, char *params,
-                                   size_t paramsize, const char **target,
-                                   int *pos, uint32_t *pvmove_mirror_count);
+       int (*add_target_line) (struct dev_manager *dm, struct dm_pool *mem,
+                                struct config_tree *cft, void **target_state,
+                                struct lv_segment *seg,
+                                struct deptree_node *node, uint64_t len,
+                                uint32_t *pvmove_mirror_count);
        int (*target_percent) (void **target_state, struct dm_pool * mem,
                               struct config_tree * cft,
                               struct lv_segment * seg, char *params,
index dcd9736476e015aa25b4f3d6a695e7e6f5bbf479..e3a7e26232a26add780a72af4f716845818eb177 100644 (file)
@@ -165,118 +165,6 @@ static struct mirror_state *_init_target(struct dm_pool *mem,
        return mirr_state;
 }
 
-static int _compose_log_line(struct dev_manager *dm, struct lv_segment *seg,
-                            char *params, size_t paramsize, int *pos,
-                            int areas, uint32_t region_size)
-{
-       int tw;
-       char devbuf[10];
-       const char *clustered = "";
-       char *dlid;
-
-       /*
-        * Use clustered mirror log for non-exclusive activation 
-        * in clustered VG.
-        */
-       if ((!(seg->lv->status & ACTIVATE_EXCL) &&
-             (seg->lv->vg->status & CLUSTERED)))
-               clustered = "cluster ";
-
-       if (!seg->log_lv)
-               tw = lvm_snprintf(params, paramsize, "%score 1 %u %u ",
-                                 clustered, region_size, areas);
-       else {
-               if (!(dlid = build_dlid(dm, seg->log_lv->lvid.s, NULL))) {
-                       stack;
-                       return 0;
-               }
-               if (!build_dev_string(dm, dlid, devbuf,
-                                     sizeof(devbuf), "log")) {
-                       stack;
-                       return 0;
-               }
-
-               /* FIXME add sync parm? */
-               tw = lvm_snprintf(params, paramsize, "%sdisk 2 %s %u %u ",
-                                 clustered, devbuf, region_size, areas);
-       }
-
-       if (tw < 0) {
-               stack;
-               return -1;
-       }
-
-       *pos += tw;
-
-       return 1;
-}
-
-static int _compose_target_line(struct dev_manager *dm, struct dm_pool *mem,
-                               struct config_tree *cft, void **target_state,
-                               struct lv_segment *seg, char *params,
-                               size_t paramsize, const char **target, int *pos,
-                               uint32_t *pvmove_mirror_count)
-{
-       struct mirror_state *mirr_state;
-       int mirror_status = MIRR_RUNNING;
-       int areas = seg->area_count;
-       int start_area = 0u;
-       uint32_t region_size, region_max;
-       int ret;
-
-       if (!*target_state)
-               *target_state = _init_target(mem, cft);
-
-       mirr_state = *target_state;
-
-       /*   mirror  log_type #log_params [log_params]* 
-        *           #mirrors [device offset]+
-        */
-       if (seg->status & PVMOVE) {
-               if (seg->extents_copied == seg->area_len) {
-                       mirror_status = MIRR_COMPLETED;
-                       start_area = 1;
-               } else if ((*pvmove_mirror_count)++) {
-                       mirror_status = MIRR_DISABLED;
-                       areas = 1;
-               }
-       }
-
-       if (mirror_status != MIRR_RUNNING) {
-               *target = "linear";
-       } else {
-               *target = "mirror";
-
-               if (!(seg->status & PVMOVE)) {
-                       if (!seg->region_size) {
-                               log_error("Missing region size for mirror segment.");
-                               return 0;
-                       }
-                       region_size = seg->region_size;
-               } else {
-                       /* Find largest power of 2 region size unit we can use */
-                       region_max = (1 << (ffs(seg->area_len) - 1)) *
-                             seg->lv->vg->extent_size;
-
-                       region_size = mirr_state->default_region_size;
-                       if (region_max < region_size) {
-                               region_size = region_max;
-                               log_verbose("Using reduced mirror region size of %u sectors",
-                                           region_size);
-                       }
-               }
-
-               if ((ret = _compose_log_line(dm, seg, params, paramsize, pos,
-                                            areas, region_size)) <= 0) {
-                       stack;
-                       return ret;
-               }
-       }
-
-       return compose_areas_line(dm, seg, params, paramsize, pos, start_area,
-                                 areas);
-}
-
 static int _target_percent(void **target_state, struct dm_pool *mem,
                           struct config_tree *cft, struct lv_segment *seg,
                           char *params, uint64_t *total_numerator,
@@ -328,13 +216,109 @@ static int _target_percent(void **target_state, struct dm_pool *mem,
        return 1;
 }
 
+static int _add_log(struct dev_manager *dm, struct lv_segment *seg,
+                   struct deptree_node *node, uint32_t area_count, uint32_t region_size)
+{
+       unsigned clustered = 0;
+       char *log_dlid = NULL;
+
+       /*
+        * Use clustered mirror log for non-exclusive activation 
+        * in clustered VG.
+        */
+       if ((!(seg->lv->status & ACTIVATE_EXCL) &&
+             (seg->lv->vg->status & CLUSTERED)))
+               clustered = 1;
+
+       if (seg->log_lv &&
+           !(log_dlid = build_dlid(dm, seg->log_lv->lvid.s, NULL))) {
+               log_error("Failed to build uuid for log LV %s.",
+                         seg->log_lv->name);
+               return 0;
+       }
+
+       /* FIXME Add sync parm? */
+       return dm_deptree_node_add_mirror_target_log(node, region_size, clustered, log_dlid, area_count);
+}
+
+static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
+                                struct config_tree *cft, void **target_state,
+                                struct lv_segment *seg,
+                                struct deptree_node *node, uint64_t len,
+                                uint32_t *pvmove_mirror_count)
+{
+       struct mirror_state *mirr_state;
+       uint32_t area_count = seg->area_count;
+       int start_area = 0u;
+       int mirror_status = MIRR_RUNNING;
+       uint32_t region_size, region_max;
+       int r;
+
+       if (!*target_state)
+               *target_state = _init_target(mem, cft);
+
+       mirr_state = *target_state;
+
+       /*
+        * For pvmove, only have one mirror segment RUNNING at once.
+        * Segments before this are COMPLETED and use 2nd area.
+        * Segments after this are DISABLED and use 1st area.
+        */
+       if (seg->status & PVMOVE) {
+               if (seg->extents_copied == seg->area_len) {
+                       mirror_status = MIRR_COMPLETED;
+                       start_area = 1;
+               } else if ((*pvmove_mirror_count)++) {
+                       mirror_status = MIRR_DISABLED;
+                       area_count = 1;
+               }
+               /* else MIRR_RUNNING */
+       }
+
+       if (mirror_status != MIRR_RUNNING) {
+               if (!dm_deptree_node_add_linear_target(node, len))
+                       return_0;
+               goto done;
+       }
+
+       if (!(seg->status & PVMOVE)) {
+               if (!seg->region_size) {
+                       log_error("Missing region size for mirror segment.");
+                       return 0;
+               }
+               region_size = seg->region_size;
+       } else {
+               /* Find largest power of 2 region size unit we can use */
+               region_max = (1 << (ffs(seg->area_len) - 1)) *
+                     seg->lv->vg->extent_size;
+
+               region_size = mirr_state->default_region_size;
+               if (region_max < region_size) {
+                       region_size = region_max;
+                       log_verbose("Using reduced mirror region size of %u sectors",
+                                   region_size);
+               }
+       }
+
+       if (!dm_deptree_node_add_mirror_target(node, len))
+               return_0;
+
+       if ((r = _add_log(dm, seg, node, area_count, region_size)) <= 0) {
+               stack;
+               return r;
+       }
+
+      done:
+       return add_areas_line(dm, seg, node, start_area, seg->area_count);
+}
+
 static int _target_present(void)
 {
        static int checked = 0;
        static int present = 0;
 
        if (!checked)
-               present = target_present("mirror");
+               present = target_present("mirror", 1);
 
        checked = 1;
 
@@ -354,7 +338,7 @@ static struct segtype_handler _mirrored_ops = {
        text_import:_text_import,
        text_export:_text_export,
 #ifdef DEVMAPPER_SUPPORT
-       compose_target_line:_compose_target_line,
+       add_target_line:_add_target_line,
        target_percent:_target_percent,
        target_present:_target_present,
 #endif
index a1f91125c947eef2fc1b82e6decdbf7fd0ad2316..e620e49c52ad9af14227ae2aff4996961e37f69d 100644 (file)
@@ -130,15 +130,15 @@ static void _quote_hyphens(char **out, const char *src)
 /*
  * <vg>-<lv>-<layer> or if !layer just <vg>-<lv>.
  */
-char *build_dm_name(struct dm_pool *mem, const char *vg,
-                   const char *lv, const char *layer)
+char *build_dm_name(struct dm_pool *mem, const char *vgname,
+                   const char *lvname, const char *layer)
 {
        size_t len = 1;
        int hyphens = 1;
        char *r, *out;
 
-       _count_hyphens(vg, &len, &hyphens);
-       _count_hyphens(lv, &len, &hyphens);
+       _count_hyphens(vgname, &len, &hyphens);
+       _count_hyphens(lvname, &len, &hyphens);
 
        if (layer && *layer) {
                _count_hyphens(layer, &len, &hyphens);
@@ -148,14 +148,15 @@ char *build_dm_name(struct dm_pool *mem, const char *vg,
        len += hyphens;
 
        if (!(r = dm_pool_alloc(mem, len))) {
-               stack;
+               log_error("build_dm_name: Allocation failed for %" PRIsize_t
+                         " for %s %s %s.", len, vgname, lvname, layer);
                return NULL;
        }
 
        out = r;
-       _quote_hyphens(&out, vg);
+       _quote_hyphens(&out, vgname);
        *out++ = '-';
-       _quote_hyphens(&out, lv);
+       _quote_hyphens(&out, lvname);
 
        if (layer && *layer) {
                *out++ = '-';
@@ -174,6 +175,7 @@ static char *_unquote(char *component)
 {
        char *c = component;
        char *o = c;
+       char *r;
 
        while (*c) {
                if (*(c + 1)) {
@@ -189,8 +191,10 @@ static char *_unquote(char *component)
                c++;
        }
 
+       r = (*c) ? c + 1 : c;
        *o = '\0';
-       return (c + 1);
+
+       return r;
 }
 
 int split_dm_name(struct dm_pool *mem, const char *dmname,
index ef9fbc729c31ef19526c86ee0206b33dbdbec689..855f197007f6e58f9f14426edd7ce92618029903 100644 (file)
@@ -369,24 +369,28 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
        if (lv_info(lv->vg->cmd, lv, &info, 1) && info.exists) {
                if (info.suspended)
                        repstr[4] = 's';        /* Suspended */
-               else
+               else if (info.live_table)
                        repstr[4] = 'a';        /* Active */
-               if (info.open_count)
-                       repstr[5] = 'o';        /* Open */
+               else if (info.inactive_table)
+                       repstr[4] = 'i';        /* Inactive with table */
                else
-                       repstr[5] = '-';
+                       repstr[4] = 'd';        /* Inactive without table */
 
                /* Snapshot dropped? */
-               if ((snap_seg = find_cow(lv)) &&
+               if (info.live_table && (snap_seg = find_cow(lv)) &&
                    (!lv_snapshot_percent(snap_seg->cow, &snap_percent) ||
                     snap_percent < 0 || snap_percent >= 100)) {
                        repstr[0] = toupper(repstr[0]);
                        if (info.suspended)
-                               repstr[4] = 'S';
+                               repstr[4] = 'S'; /* Susp Inv snapshot */
                        else
-                               repstr[4] = 'I';
+                               repstr[4] = 'I'; /* Invalid snapshot */
                }
 
+               if (info.open_count)
+                       repstr[5] = 'o';        /* Open */
+               else
+                       repstr[5] = '-';
        } else {
                repstr[4] = '-';
                repstr[5] = '-';
index a19d6794f0690b8267c152e90e943a3b0427d3dc..d918f4ef4f85757ad9352340788ecaf9881f0f2d 100644 (file)
@@ -115,8 +115,8 @@ static int _target_present(void)
        static int present = 0;
 
        if (!checked)
-               present = target_present("snapshot") &&
-                   target_present("snapshot-origin");
+               present = target_present("snapshot", 1) &&
+                   target_present("snapshot-origin", 0);
 
        checked = 1;
 
index 84da3a0aa8c27197a3bc9ee9bd67d175bc603246..e23da877b9a53221991219a58a2ade3051fde8bd 100644 (file)
@@ -106,7 +106,8 @@ static int _segments_compatible(struct lv_segment *first,
        unsigned s;
 
        if ((first->area_count != second->area_count) ||
-           (first->stripe_size != second->stripe_size)) return 0;
+           (first->stripe_size != second->stripe_size))
+               return 0;
 
        for (s = 0; s < first->area_count; s++) {
 
@@ -150,32 +151,25 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
 }
 
 #ifdef DEVMAPPER_SUPPORT
-static int _compose_target_line(struct dev_manager *dm, struct dm_pool *mem,
-                               struct config_tree *cft, void **target_state,
-                               struct lv_segment *seg, char *params,
-                               size_t paramsize, const char **target, int *pos,
-                               uint32_t *pvmove_mirror_count)
+static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
+                                struct config_tree *cft, void **target_state,
+                                struct lv_segment *seg,
+                                struct deptree_node *node, uint64_t len,
+                                uint32_t *pvmove_mirror_count)
 {
-       /*   linear [device offset]+
-        *   striped #stripes stripe_size [device offset]+   */
-
-       if (seg->area_count == 1)
-               *target = "linear";
-       else if (seg->area_count > 1) {
-               *target = "striped";
-               if ((*pos = lvm_snprintf(params, paramsize, "%u %u ",
-                                        seg->area_count,
-                                        seg->stripe_size)) < 0) {
-                       stack;
-                       return -1;
-               }
-       } else {
-               log_error("Internal error: striped target with no stripes");
+       if (!seg->area_count) {
+               log_error("Internal error: striped add_target_line called "
+                         "with no areas for %s.", seg->lv->name);
                return 0;
        }
-
-       return compose_areas_line(dm, seg, params, paramsize, pos, 0u,
-                                 seg->area_count);
+       if (seg->area_count == 1) {
+               if (!dm_deptree_node_add_linear_target(node, len))
+                       return_0;
+       } else if (!dm_deptree_node_add_striped_target(node, len,
+                                                 seg->stripe_size))
+               return_0;
+
+       return add_areas_line(dm, seg, node, 0u, seg->area_count);
 }
 
 static int _target_present(void)
@@ -184,7 +178,8 @@ static int _target_present(void)
        static int present = 0;
 
        if (!checked)
-               present = target_present("linear") && target_present("striped");
+               present = target_present("linear", 0) &&
+                         target_present("striped", 0);
 
        checked = 1;
        return present;
@@ -204,7 +199,7 @@ static struct segtype_handler _striped_ops = {
        text_export:_text_export,
        merge_segments:_merge_segments,
 #ifdef DEVMAPPER_SUPPORT
-       compose_target_line:_compose_target_line,
+       add_target_line:_add_target_line,
        target_present:_target_present,
 #endif
        destroy:_destroy,
index f1439b607d40b0b09a979b1befe083dec160a801..6c3ccf06471e447907d09c3984c5be56b0781616 100644 (file)
@@ -38,18 +38,13 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
 }
 
 #ifdef DEVMAPPER_SUPPORT
-static int _compose_target_line(struct dev_manager *dm, struct dm_pool *mem,
-                               struct config_tree *cft, void **target_state,
-                               struct lv_segment *seg, char *params,
-                               size_t paramsize, const char **target, int *pos,
-                               uint32_t *pvmove_mirror_count)
+static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
+                                struct config_tree *cft, void **target_state,
+                                struct lv_segment *seg,
+                                struct deptree_node *node, uint64_t len,
+                                uint32_t *pvmove_mirror_count)
 {
-       /*   zero */
-
-       *target = "zero";
-       *params = '\0';
-
-       return 1;
+       return dm_deptree_node_add_zero_target(node, len);
 }
 
 static int _target_present(void)
@@ -58,7 +53,7 @@ static int _target_present(void)
        static int present = 0;
 
        if (!checked)
-               present = target_present("zero");
+               present = target_present("zero", 0);
 
        checked = 1;
        return present;
@@ -74,7 +69,7 @@ static struct segtype_handler _zero_ops = {
        name:_name,
        merge_segments:_merge_segments,
 #ifdef DEVMAPPER_SUPPORT
-       compose_target_line:_compose_target_line,
+       add_target_line:_add_target_line,
        target_present:_target_present,
 #endif
        destroy:_destroy,
@@ -93,7 +88,7 @@ struct segment_type *init_zero_segtype(struct cmd_context *cmd)
        segtype->ops = &_zero_ops;
        segtype->name = "zero";
        segtype->private = NULL;
-       segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL;
+       segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
 
        log_very_verbose("Initialised segtype: %s", segtype->name);
 
index eb8018ef0e7bd088dd24f47c31d67a11ee0cb47c..57051eb69c0ac85fae08bff86214eb1f10b2752c 100644 (file)
--- a/man/lvs.8
+++ b/man/lvs.8
@@ -55,7 +55,8 @@ changes, for example during \fBpvmove\fP (8).
 .IP 4 3
 fixed (m)inor
 .IP 5 3
-State: (a)ctive, (s)uspended, (I)nvalid snapshot, invalid (S)uspended snapshot 
+State: (a)ctive, (s)uspended, (I)nvalid snapshot, invalid (S)uspended snapshot,
+mapped (d)evice present without tables, mapped device present with (i)nactive table
 .IP 6 3
 device (o)pen
 .RE
index 4977397da119595bb35e10257dcc075811ae944a..31a8405b1ba83349b62668cbaadbeece04a4905f 100644 (file)
@@ -359,7 +359,8 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
        /*
         * Should we zero the lv.
         */
-       lp->zero = strcmp(arg_str_value(cmd, zero_ARG, "y"), "n");
+       lp->zero = strcmp(arg_str_value(cmd, zero_ARG, 
+               (lp->segtype->flags & SEG_CANNOT_BE_ZEROED) ? "n" : "y"), "n");
 
        /*
         * Alloc policy
index 003c727c5885f97854acde0c2f25bfe49125aaaf..e29af6f387350044b83448273ee14cc3299292e5 100644 (file)
@@ -20,6 +20,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
 {
        struct volume_group *vg;
        struct lvinfo info;
+       struct logical_volume *origin = NULL;
 
        vg = lv->vg;
 
@@ -74,6 +75,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
        if (!archive(vg))
                return ECMD_FAILED;
 
+       /* FIXME Snapshot commit out of sequence if it fails after here? */
        if (!deactivate_lv(cmd, lv)) {
                log_error("Unable to deactivate logical volume \"%s\"",
                          lv->name);
@@ -81,6 +83,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
        }
 
        if (lv_is_cow(lv)) {
+               origin = find_cow(lv)->origin;
                log_verbose("Removing snapshot %s", lv->name);
                if (!vg_remove_snapshot(lv)) {
                        stack;
@@ -103,6 +106,14 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
        if (!vg_commit(vg))
                return ECMD_FAILED;
 
+       /* If no snapshots left, reload without -real. */
+       if (origin && !lv_is_origin(origin)) {
+               if (!suspend_lv(cmd, origin))
+                       log_error("Failed to refresh %s without snapshot.", origin->name);
+               else if (!resume_lv(cmd, origin))
+                       log_error("Failed to resume %s.", origin->name);
+       }
+
        log_print("Logical volume \"%s\" successfully removed", lv->name);
        return ECMD_PROCESSED;
 }
This page took 0.128886 seconds and 5 git commands to generate.