* @cache_lv
*
* Given a cache LV, remove the cache layer. This will unlink
- * the origin and cache_pool, remove the cache LV layer, and promote
+ * the origin and cache_pool/cachevol, remove the cache LV layer, and promote
* the origin to a usable non-cached LV of the same name as the
* given cache_lv.
*
struct lv_segment *cache_seg = first_seg(cache_lv);
struct logical_volume *corigin_lv;
struct logical_volume *cache_pool_lv;
+ const struct id *data_id, *metadata_id;
+ uint64_t data_len, metadata_len;
cache_mode_t cache_mode;
int is_clear;
return 0;
}
- if (lv_is_cache_vol(cache_seg->pool_lv)) {
- log_error(INTERNAL_ERROR "Incorrect remove for cache single");
- return 0;
- }
-
if (lv_is_pending_delete(cache_lv)) {
log_debug(INTERNAL_ERROR "LV %s is already dropped cache volume.",
display_lvname(cache_lv));
if (!remove_layer_from_lv(cache_lv, corigin_lv))
return_0;
+ /* Preserve currently imortant data from original cache segment.
+ * TODO: can it be done without this ? */
+ data_id = &cache_seg->data_id;
+ data_len = cache_seg->data_len;
+ metadata_id = &cache_seg->metadata_id;
+ metadata_len = cache_seg->metadata_len;
+
/* Replace 'error' with 'cache' segtype */
cache_seg = first_seg(corigin_lv);
if (!(cache_seg->segtype = get_segtype_from_string(corigin_lv->vg->cmd, SEG_TYPE_NAME_CACHE)))
corigin_lv->size = cache_lv->size;
corigin_lv->status |= LV_PENDING_DELETE;
+ /* Restore preserved data into a new cache segment that is going to be removed. */
+ if ((cache_seg->data_len = data_len)) {
+ cache_seg->metadata_len = metadata_len;
+ memcpy(&cache_seg->data_id, data_id, sizeof(struct id));
+ memcpy(&cache_seg->metadata_id, metadata_id, sizeof(struct id));
+ cache_pool_lv->status |= LV_CACHE_VOL;
+ /* Unused settings set only for passing metadata validation. */
+ cache_seg->cache_mode = CACHE_MODE_WRITETHROUGH;
+ cache_seg->chunk_size = DM_CACHE_MAX_DATA_BLOCK_SIZE;
+ cache_seg->cache_metadata_format = CACHE_METADATA_FORMAT_2;
+ }
+
/* Reattach cache pool */
if (!attach_pool_lv(cache_seg, cache_pool_lv, NULL, NULL, NULL))
return_0;
if (!lv_remove(cache_lv)) /* Will use LV_PENDING_DELETE */
return_0;
+ /* CachePool or CacheVol is left inactivate for further manipulation */
+
return 1;
}