Provide segment type for virtual snapshots within the shared store. Signed-off-by: Mikulas Patocka --- lib/metadata/metadata-exported.h | 3 + lib/metadata/snapshot_manip.c | 7 ++ lib/multisnapshot/multisnapshot.c | 98 ++++++++++++++++++++++++++++++++++++++ libdm/.exported_symbols | 1 libdm/libdevmapper.h | 4 + libdm/libdm-deptree.c | 33 ++++++++++++ 6 files changed, 146 insertions(+) Index: LVM2.2.02.60/lib/multisnapshot/multisnapshot.c =================================================================== --- LVM2.2.02.60.orig/lib/multisnapshot/multisnapshot.c 2010-02-08 18:06:26.000000000 +0100 +++ LVM2.2.02.60/lib/multisnapshot/multisnapshot.c 2010-02-08 20:15:25.000000000 +0100 @@ -21,6 +21,7 @@ #include "config.h" #include "activate.h" #include "str_list.h" +#include "targets.h" #ifdef DMEVENTD # include "sharedlib.h" # include "libdevmapper-event.h" @@ -107,6 +108,57 @@ static int _multisnapshot_text_export(co return 1; } +static int _multisnap_snap_text_import(struct lv_segment *seg, + const struct config_node *sn, + struct dm_hash_table *pv_hash __attribute((unused))) +{ + const char *org_name, *snapid; + struct logical_volume *org; + int old_suppress; + + old_suppress = log_suppress(1); + + if (!(org_name = find_config_str(sn, "origin", NULL))) { + log_suppress(old_suppress); + log_error("Snapshot origin not specified."); + return 0; + } + + if (!(snapid = find_config_str(sn, "snapid", NULL))) { + log_suppress(old_suppress); + log_error("Snapshot ID not specified."); + return 0; + } + + snapid = dm_pool_strdup(seg->lv->vg->cmd->mem, snapid); + if (!snapid) { + log_error("Out of memory."); + return 0; + } + + if (!(org = find_lv(seg->lv->vg, org_name))) { + log_error("Unknown logical volume specified for " + "snapshot origin."); + return 0; + } + + log_suppress(old_suppress); + + seg->origin = org; + seg->snapid = snapid; + + return 1; +} + +static int _multisnap_snap_text_export(const struct lv_segment *seg, + struct formatter *f) +{ + outf(f, "origin = \"%s\"", seg->origin->name); + outf(f, "snapid = \"%s\"", seg->snapid); + return 1; +} + + #ifdef DEVMAPPER_SUPPORT static int _multisnapshot_target_percent(void **target_state __attribute((unused)), percent_range_t *percent_range, @@ -136,6 +188,25 @@ static int _multisnap_target_present(str return _multisnap_present; } +static int _multisnap_snap_add_target_line(struct dev_manager *dm, + struct dm_pool *mem, + struct cmd_context *cmd, + void **target_state, + struct lv_segment *seg, + struct dm_tree_node *node, + uint64_t len, + uint32_t *pvmove_mirror_count) +{ + const char *origin_dlid; + + if (!(origin_dlid = build_dlid(dm, seg->origin->lvid.s, "real"))) + return 0; + + return dm_tree_node_add_snapshot_shared_snap_target(node, len, + origin_dlid, + seg->snapid); +} + #endif static void _multisnap_destroy(const struct segment_type *segtype) @@ -155,6 +226,18 @@ static struct segtype_handler _multisnap .text_export = _multisnapshot_text_export, }; +static struct segtype_handler _multisnap_snap_ops = { + .name = _multisnap_name, + .modules_needed = _multisnap_modules_needed, + .destroy = _multisnap_destroy, +#ifdef DEVMAPPER_SUPPORT + .add_target_line = _multisnap_snap_add_target_line, + .target_present = _multisnap_target_present, +#endif + .text_import = _multisnap_snap_text_import, + .text_export = _multisnap_snap_text_export, +}; + #ifdef MULTISNAPSHOT_INTERNAL int init_multisnapshot_multiple_segtypes(struct cmd_context *cmd, struct segtype_library *lib) #else /* Shared */ @@ -179,5 +262,20 @@ int init_multiple_segtypes(struct cmd_co log_very_verbose("Initialised segtype: %s", segtype->name); + segtype = dm_malloc(sizeof(*segtype)); + if (!segtype) + return 0; + + segtype->cmd = cmd; + segtype->ops = &_multisnap_snap_ops; + segtype->name = "multisnap-snap"; + segtype->private = NULL; + segtype->flags = SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED; + + if (!lvm_register_segtype(lib, segtype)) + return 0; + + log_very_verbose("Initialised segtype: %s", segtype->name); + return 1; } Index: LVM2.2.02.60/lib/metadata/metadata-exported.h =================================================================== --- LVM2.2.02.60.orig/lib/metadata/metadata-exported.h 2010-02-08 19:58:02.000000000 +0100 +++ LVM2.2.02.60/lib/metadata/metadata-exported.h 2010-02-08 20:15:25.000000000 +0100 @@ -304,6 +304,8 @@ struct lv_segment { const char *exception_store; void *segtype_private; + const char *snapid; + struct dm_list tags; struct lv_segment_area *areas; @@ -623,6 +625,7 @@ int lv_is_cow(const struct logical_volum int lv_is_merging_origin(const struct logical_volume *origin); int lv_is_merging_cow(const struct logical_volume *snapshot); int lv_is_multisnap_origin(const struct logical_volume *lv); +int lv_is_multisnap_cow(const struct logical_volume *lv); /* Test if given LV is visible from user's perspective */ int lv_is_visible(const struct logical_volume *lv); Index: LVM2.2.02.60/libdm/.exported_symbols =================================================================== --- LVM2.2.02.60.orig/libdm/.exported_symbols 2010-02-08 18:32:31.000000000 +0100 +++ LVM2.2.02.60/libdm/.exported_symbols 2010-02-08 20:15:25.000000000 +0100 @@ -73,6 +73,7 @@ dm_tree_node_add_snapshot_origin_target dm_tree_node_add_snapshot_target dm_tree_node_add_snapshot_merge_target dm_tree_node_add_snapshot_shared_target +dm_tree_node_add_snapshot_shared_snap_target dm_tree_node_add_error_target dm_tree_node_add_zero_target dm_tree_node_add_linear_target Index: LVM2.2.02.60/libdm/libdevmapper.h =================================================================== --- LVM2.2.02.60.orig/libdm/libdevmapper.h 2010-02-08 18:32:31.000000000 +0100 +++ LVM2.2.02.60/libdm/libdevmapper.h 2010-02-08 20:15:25.000000000 +0100 @@ -406,6 +406,10 @@ int dm_tree_node_add_snapshot_shared_tar const char *cow_uuid, const char *exception_store, uint32_t chunk_size); +int dm_tree_node_add_snapshot_shared_snap_target(struct dm_tree_node *node, + uint64_t size, + const char *origin_uuid, + const char *snapid); int dm_tree_node_add_error_target(struct dm_tree_node *node, uint64_t size); int dm_tree_node_add_zero_target(struct dm_tree_node *node, Index: LVM2.2.02.60/libdm/libdm-deptree.c =================================================================== --- LVM2.2.02.60.orig/libdm/libdm-deptree.c 2010-02-08 19:53:51.000000000 +0100 +++ LVM2.2.02.60/libdm/libdm-deptree.c 2010-02-08 20:15:25.000000000 +0100 @@ -37,6 +37,7 @@ enum { SEG_SNAPSHOT_ORIGIN, SEG_SNAPSHOT_MERGE, SEG_SNAPSHOT_SHARED, + SEG_SNAPSHOT_SHARED_SNAP, SEG_STRIPED, SEG_ZERO, }; @@ -55,6 +56,7 @@ struct { { SEG_SNAPSHOT_ORIGIN, "snapshot-origin" }, { SEG_SNAPSHOT_MERGE, "snapshot-merge" }, { SEG_SNAPSHOT_SHARED, "multisnapshot" }, + { SEG_SNAPSHOT_SHARED_SNAP, "multisnap-snap" }, { SEG_STRIPED, "striped" }, { SEG_ZERO, "zero"}, }; @@ -86,6 +88,7 @@ struct load_segment { struct dm_tree_node *cow; /* Snapshot */ struct dm_tree_node *origin; /* Snapshot + Snapshot origin */ struct dm_tree_node *merge; /* Snapshot */ + const char *snapid; /* Shared snapshot */ struct dm_tree_node *log; /* Mirror */ uint32_t region_size; /* Mirror */ @@ -1500,6 +1503,11 @@ static int _emit_segment_line(struct dm_ EMIT_PARAMS(pos, "%s %s %d 0 %s 0", originbuf, cowbuf, seg->chunk_size, seg->exception_store); break; + case SEG_SNAPSHOT_SHARED_SNAP: + if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin)) + return_0; + EMIT_PARAMS(pos, "%s %s", originbuf, seg->snapid); + break; case SEG_STRIPED: EMIT_PARAMS(pos, "%u %u ", seg->area_count, seg->stripe_size); break; @@ -1883,6 +1891,31 @@ int dm_tree_node_add_snapshot_shared_tar SEG_SNAPSHOT_SHARED, exception_store, chunk_size); } +int dm_tree_node_add_snapshot_shared_snap_target(struct dm_tree_node *node, + uint64_t size, + const char *origin_uuid, + const char *snapid) +{ + struct load_segment *seg; + struct dm_tree_node *origin_node; + + if (!(seg = _add_segment(node, SEG_SNAPSHOT_SHARED_SNAP, size))) + return_0; + + if (!(origin_node = dm_tree_find_node_by_uuid(node->dtree, origin_uuid))) { + log_error("Couldn't find snapshot origin uuid %s.", origin_uuid); + return 0; + } + + seg->snapid = dm_pool_strdup(node->dtree->mem, snapid); + + seg->origin = origin_node; + if (!_link_tree_nodes(node, origin_node)) + return_0; + + return 1; +} + int dm_tree_node_add_error_target(struct dm_tree_node *node, uint64_t size) { Index: LVM2.2.02.60/lib/metadata/snapshot_manip.c =================================================================== --- LVM2.2.02.60.orig/lib/metadata/snapshot_manip.c 2010-02-08 19:58:02.000000000 +0100 +++ LVM2.2.02.60/lib/metadata/snapshot_manip.c 2010-02-08 20:15:25.000000000 +0100 @@ -17,6 +17,7 @@ #include "metadata.h" #include "toolcontext.h" #include "lv_alloc.h" +#include "segtype.h" int lv_is_origin(const struct logical_volume *lv) { @@ -33,6 +34,12 @@ int lv_is_multisnap_origin(const struct return lv_is_origin(lv) && lv->shared_snapshot; } +int lv_is_multisnap_cow(const struct logical_volume *lv) +{ + struct lv_segment *seg = first_seg(lv); + return seg && seg_is_virtual(seg) && seg->origin; +} + int lv_is_visible(const struct logical_volume *lv) { if (lv->status & SNAPSHOT)