diff options
author | Mike Snitzer <snitzer@redhat.com> | 2010-02-17 22:59:46 +0000 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2010-02-17 22:59:46 +0000 |
commit | a5ec3e3827b9b35da222575349a6a1be99958e14 (patch) | |
tree | 33fe8853a843bd968c32a05eb43f7ff1eb60638c /lib/metadata/snapshot_manip.c | |
parent | 943c443426ce063177d5a4973155e7f072d3b12f (diff) | |
download | lvm2-a5ec3e3827b9b35da222575349a6a1be99958e14.tar.gz lvm2-a5ec3e3827b9b35da222575349a6a1be99958e14.tar.xz lvm2-a5ec3e3827b9b35da222575349a6a1be99958e14.zip |
Refactor snapshot-merge deptree and device removal to support info-by-uuid
Add a merging snapshot to the deptree, using the "error" target, rather
than avoid adding it entirely. This allows proper cleanup of the -cow
device without having to rename the -cow to use the origin's name as a
prefix.
Move the preloading of the origin LV, after a merge, from
lv_remove_single() to vg_remove_snapshot(). Having vg_remove_snapshot()
preload the origin allows the -cow device to be released so that it can
be removed via deactivate_lv(). lv_remove_single()'s deactivate_lv()
reliably removes the -cow device because the associated snapshot LV,
that is to be removed when a snapshot-merge completes, is always added
to the deptree (and kernel -- via "error" target).
Now when the snapshot LV is removed both the -cow and -real devices
get removed using uuid rather than device name. This paves the way
for us to switch over to info-by-uuid queries.
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'lib/metadata/snapshot_manip.c')
-rw-r--r-- | lib/metadata/snapshot_manip.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c index 19effe38..f7218c26 100644 --- a/lib/metadata/snapshot_manip.c +++ b/lib/metadata/snapshot_manip.c @@ -15,6 +15,7 @@ #include "lib.h" #include "metadata.h" +#include "locking.h" #include "toolcontext.h" #include "lv_alloc.h" @@ -58,9 +59,9 @@ int lv_is_merging_origin(const struct logical_volume *origin) struct lv_segment *find_merging_cow(const struct logical_volume *origin) { - /* FIXME: eliminate this wrapper and just use find_cow()? - * - find_merging_cow() adds to code clarity in caller - */ + if (!lv_is_merging_origin(origin)) + return NULL; + return find_cow(origin); } @@ -170,12 +171,22 @@ int vg_add_snapshot(struct logical_volume *origin, int vg_remove_snapshot(struct logical_volume *cow) { + int preload_origin = 0; struct logical_volume *origin = origin_from_cow(cow); dm_list_del(&cow->snapshot->origin_list); origin->origin_count--; - if (find_merging_cow(origin) == find_cow(cow)) - clear_snapshot_merge(origin_from_cow(cow)); + if (find_merging_cow(origin) == find_cow(cow)) { + clear_snapshot_merge(origin); + /* + * preload origin to: + * - allow proper release of -cow + * - avoid allocations with other devices suspended + * when transitioning from "snapshot-merge" to + * "snapshot-origin after a merge completes. + */ + preload_origin = 1; + } if (!lv_remove(cow->snapshot->lv)) { log_error("Failed to remove internal snapshot LV %s", @@ -186,5 +197,21 @@ int vg_remove_snapshot(struct logical_volume *cow) cow->snapshot = NULL; lv_set_visible(cow); + if (preload_origin) { + if (!vg_write(origin->vg)) + return_0; + if (!suspend_lv(origin->vg->cmd, origin)) { + log_error("Failed to refresh %s without snapshot.", + origin->name); + return 0; + } + if (!vg_commit(origin->vg)) + return_0; + if (!resume_lv(origin->vg->cmd, origin)) { + log_error("Failed to resume %s.", origin->name); + return 0; + } + } + return 1; } |