/* * lv_cache_create * @pool * @origin * * Given a cache_pool and an origin, link the two and create a * cached LV. * * Returns: cache LV on success, NULL on failure */ struct logical_volume *lv_cache_create(struct logical_volume *pool, struct logical_volume *origin) { const struct segment_type *segtype; struct cmd_context *cmd = pool->vg->cmd; struct logical_volume *cache_lv; struct lv_segment *seg; if (!lv_is_cache_pool(pool)) { log_error(INTERNAL_ERROR "%s is not a cache_pool LV", pool->name); return NULL; } if (!dm_list_empty(&pool->segs_using_this_lv)) { seg = get_only_segment_using_this_lv(pool); log_error("%s is already in use by %s", pool->name, seg ? seg->lv->name : "another LV"); return NULL; } if (lv_is_cache_type(origin)) { /* * FIXME: We can layer caches, insert_layer_for_lv() would * have to do a better job renaming the LVs in the stack * first so that there isn't a name collision with <name>_corig. * The origin under the origin would become *_corig_corig * before renaming the origin above to *_corig. */ log_error(INTERNAL_ERROR "The origin, %s, cannot be of cache type", origin->name); return NULL; } if (!(segtype = get_segtype_from_string(cmd, "cache"))) return_NULL; cache_lv = origin; if (!(origin = insert_layer_for_lv(cmd, cache_lv, CACHE, "_corig"))) return_NULL; seg = first_seg(cache_lv); seg->segtype = segtype; if (!attach_pool_lv(seg, pool, NULL, NULL)) return_NULL; return cache_lv; }
/* Check if given LV is usable as snapshot origin LV */ int validate_snapshot_origin(const struct logical_volume *origin_lv) { const char *err = NULL; /* For error string */ if (lv_is_cow(origin_lv)) err = "snapshots"; else if (lv_is_locked(origin_lv)) err = "locked volumes"; else if (lv_is_pvmove(origin_lv)) err = "pvmoved volumes"; else if (!lv_is_visible(origin_lv)) err = "hidden volumes"; else if (lv_is_merging_origin(origin_lv)) err = "an origin that has a merging snapshot"; else if (lv_is_cache_type(origin_lv) && !lv_is_cache(origin_lv)) err = "cache type volumes"; else if (lv_is_thin_type(origin_lv) && !lv_is_thin_volume(origin_lv)) err = "thin pool type volumes"; else if (lv_is_mirror_type(origin_lv)) { if (!lv_is_mirror(origin_lv)) err = "mirror subvolumes"; else { log_warn("WARNING: Snapshots of mirrors can deadlock under rare device failures."); log_warn("WARNING: Consider using the raid1 mirror type to avoid this."); log_warn("WARNING: See global/mirror_segtype_default in lvm.conf."); } } else if (lv_is_raid_type(origin_lv) && !lv_is_raid(origin_lv)) err = "raid subvolumes"; if (err) { log_error("Snapshots of %s are not supported.", err); return 0; } if (vg_is_clustered(origin_lv->vg) && lv_is_active(origin_lv) && !lv_is_active_exclusive_locally(origin_lv)) { log_error("Snapshot origin must be active exclusively."); return 0; } return 1; }