diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index ca226dc21..36fde83ff 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -3330,6 +3330,66 @@ static int _add_new_external_lv_to_dtree(struct dev_manager *dm, return 1; } +static int _add_new_cvol_subdev_to_dtree(struct dev_manager *dm, + struct dm_tree *dtree, + const struct logical_volume *lv, + struct lv_activate_opts *laopts, + struct lv_layer *lvlayer, + int meta_or_data) +{ + const char *layer = meta_or_data ? "cmeta" : "cdata"; + const struct lv_segment *lvseg = first_seg(lv); + uint64_t size = meta_or_data ? lvseg->metadata_len : lvseg->data_len; + const struct logical_volume *pool_lv = lvseg->pool_lv; + struct dm_tree_node *dnode; + char *dlid, *dlid_pool, *name; + union lvid lvid = { + { + lv->vg->id, + /* When ID is provided in form of metadata_id or data_id, otherwise use CVOL ID */ + (meta_or_data && lvseg->metadata_id) ? *lvseg->metadata_id : + (lvseg->data_id) ? *lvseg->data_id : pool_lv->lvid.id[1] + } + }; + + if (!(dlid = dm_build_dm_uuid(dm->mem, UUID_PREFIX, (const char *)&lvid.s, layer))) + return_0; + + if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, pool_lv->name, layer))) + return_0; + + if (!(dnode = dm_tree_add_new_dev_with_udev_flags(dtree, name, dlid, -1, -1, + read_only_lv(lv, laopts, layer), + ((lv->vg->status & PRECOMMITTED) | laopts->revert) ? 1 : 0, + lvlayer, + _get_udev_flags(dm, lv, layer, laopts->noscan, + laopts->temporary, 0)))) + return_0; + + if (dm->track_pending_delete) { + log_debug_activation("Using error for pending delete of %s-%s.", + display_lvname(lv), layer); + if (!dm_tree_node_add_error_target(dnode, size)) + return_0; + } else { + /* add load_segment to meta dnode: linear, size of meta area */ + if (!add_linear_area_to_dtree(dnode, size, lv->vg->extent_size, + lv->vg->cmd->use_linear_target, + lv->vg->name, lv->name)) + return_0; + + if (!(dlid_pool = build_dm_uuid(dm->mem, pool_lv, NULL))) + return_0; + + /* add seg_area to prev load_seg: offset 0 maps to cachevol lv offset 0 */ + if (!dm_tree_node_add_target_area(dnode, NULL, dlid_pool, + meta_or_data ? 0 : lvseg->metadata_len)) + return_0; + } + + return 1; +} + static int _add_segment_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struct dm_tree_node *dnode, @@ -3465,114 +3525,6 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, return 1; } - if (lv_is_cache(lv) && lv_is_cache_vol(first_seg(lv)->pool_lv)) { - struct logical_volume *pool_lv = first_seg(lv)->pool_lv; - struct lv_segment *lvseg = first_seg(lv); - struct volume_group *vg = lv->vg; - struct dm_tree_node *dnode_meta; - struct dm_tree_node *dnode_data; - union lvid lvid_meta; - union lvid lvid_data; - char *name_meta; - char *name_data; - char *dlid_meta; - char *dlid_data; - char *dlid_pool; - uint64_t meta_size = first_seg(lv)->metadata_len; - uint64_t data_size = first_seg(lv)->data_len; - uint16_t udev_flags = _get_udev_flags(dm, lv, layer, - laopts->noscan, laopts->temporary, - 0); - - if (lv_is_pending_delete(lvseg->lv)) - dm->track_pending_delete = 1; - - log_debug("Add cachevol %s to dtree before cache %s.", pool_lv->name, lv->name); - - if (!_add_new_lv_to_dtree(dm, dtree, pool_lv, laopts, lv_layer(pool_lv))) { - log_error("Failed to add cachevol to dtree before cache."); - return 0; - } - - memset(&lvid_meta, 0, sizeof(lvid_meta)); - memset(&lvid_data, 0, sizeof(lvid_meta)); - memcpy(&lvid_meta.id[0], &vg->id, sizeof(struct id)); - memcpy(&lvid_meta.id[1], lvseg->metadata_id ? : &pool_lv->lvid.id[1], sizeof(struct id)); - memcpy(&lvid_data.id[0], &vg->id, sizeof(struct id)); - memcpy(&lvid_data.id[1], lvseg->data_id ? : &pool_lv->lvid.id[1], sizeof(struct id)); - - if (!(dlid_meta = dm_build_dm_uuid(dm->mem, UUID_PREFIX, (const char *)&lvid_meta.s, "cmeta"))) - return_0; - if (!(dlid_data = dm_build_dm_uuid(dm->mem, UUID_PREFIX, (const char *)&lvid_data.s, "cdata"))) - return_0; - - if (!(name_meta = dm_build_dm_name(dm->mem, vg->name, pool_lv->name, "cmeta"))) - return_0; - if (!(name_data = dm_build_dm_name(dm->mem, vg->name, pool_lv->name, "cdata"))) - return_0; - - if (!(dlid_pool = build_dm_uuid(dm->mem, pool_lv, NULL))) - return_0; - - /* add meta dnode */ - if (!(dnode_meta = dm_tree_add_new_dev_with_udev_flags(dtree, - name_meta, - dlid_meta, - -1, -1, - read_only_lv(lv, laopts, layer), - ((lv->vg->status & PRECOMMITTED) | laopts->revert) ? 1 : 0, - lvlayer, - udev_flags))) - return_0; - - if (dm->track_pending_delete) { - log_debug_activation("Using error for pending meta delete %s.", display_lvname(lv)); - if (!dm_tree_node_add_error_target(dnode_meta, meta_size)) - return_0; - } else { - /* add load_segment to meta dnode: linear, size of meta area */ - if (!add_linear_area_to_dtree(dnode_meta, - meta_size, - lv->vg->extent_size, - lv->vg->cmd->use_linear_target, - lv->vg->name, lv->name)) - return_0; - - /* add seg_area to prev load_seg: offset 0 maps to cachepool lv offset 0 */ - if (!dm_tree_node_add_target_area(dnode_meta, NULL, dlid_pool, 0)) - return_0; - } - - /* add data dnode */ - if (!(dnode_data = dm_tree_add_new_dev_with_udev_flags(dtree, - name_data, - dlid_data, - -1, -1, - read_only_lv(lv, laopts, layer), - ((lv->vg->status & PRECOMMITTED) | laopts->revert) ? 1 : 0, - lvlayer, - udev_flags))) - return_0; - - if (dm->track_pending_delete) { - log_debug_activation("Using error for pending data delete %s.", display_lvname(lv)); - if (!dm_tree_node_add_error_target(dnode_data, data_size)) - return_0; - } else { - /* add load_segment to data dnode: linear, size of data area */ - if (!add_linear_area_to_dtree(dnode_data, - data_size, - lv->vg->extent_size, - lv->vg->cmd->use_linear_target, - lv->vg->name, lv->name)) - return_0; - - /* add seg_area to prev load_seg: offset 0 maps to cachepool lv after meta */ - if (!dm_tree_node_add_target_area(dnode_data, NULL, dlid_pool, meta_size)) - return_0; - } - } - /* FIXME Seek a simpler way to lay out the snapshot-merge tree. */ if (!layer && lv_is_merging_origin(lv)) { @@ -3675,6 +3627,14 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, /* Fow now used only by cache segtype, TODO snapshots */ dm->track_pending_delete = 1; + if (lv_is_cache_vol(lv)) + dm_list_iterate_items(sl, &lv->segs_using_this_lv) + if (lv_is_cache(sl->seg->lv) && + /* Cachevol is used by cache LV segment -> add cvol-cdata/cmeta extra layer */ + (!_add_new_cvol_subdev_to_dtree(dm, dtree, sl->seg->lv, laopts, lvlayer, 0) || + !_add_new_cvol_subdev_to_dtree(dm, dtree, sl->seg->lv, laopts, lvlayer, 1))) + return_0; + /* This is unused cache-pool - make metadata accessible */ if (lv_is_cache_pool(lv)) lv = first_seg(lv)->metadata_lv;