/* * Normal snapshot or thinly-provisioned snapshot? */ static int _determine_snapshot_type(struct volume_group *vg, struct lvcreate_params *lp) { struct lv_list *lvl; if (!(lvl = find_lv_in_vg(vg, lp->origin))) { log_error("Snapshot origin LV %s not found in Volume group %s.", lp->origin, vg->name); return 0; } if (!arg_count(vg->cmd, extents_ARG) && !arg_count(vg->cmd, size_ARG)) { if (!lv_is_thin_volume(lvl->lv)) { log_error("Please specify either size or extents with snapshots."); return 0; } lp->thin = 1; if (!(lp->segtype = get_segtype_from_string(vg->cmd, "thin"))) return_0; lp->pool = first_seg(lvl->lv)->pool_lv->name; } return 1; }
static percent_t _data_percent(const struct logical_volume *lv) { percent_t perc; if (lv_is_cow(lv)) return _snap_percent(lv); if (lv_is_thin_volume(lv)) return lv_thin_percent(lv, 0, &perc) ? perc : PERCENT_INVALID; return lv_thin_pool_percent(lv, 0, &perc) ? perc : PERCENT_INVALID; }
/* 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; }
static dm_percent_t _data_percent(const struct logical_volume *lv) { dm_percent_t percent; struct lv_status_cache *status; if (lv_is_cow(lv)) return _snap_percent(lv); if (lv_is_cache(lv) || lv_is_cache_pool(lv)) { if (!lv_cache_status(lv, &status)) { stack; return DM_PERCENT_INVALID; } percent = status->dirty_usage; dm_pool_destroy(status->mem); return percent; } if (lv_is_thin_volume(lv)) return lv_thin_percent(lv, 0, &percent) ? percent : DM_PERCENT_INVALID; return lv_thin_pool_percent(lv, 0, &percent) ? percent : DM_PERCENT_INVALID; }
int lv_is_cow(const struct logical_volume *lv) { /* Make sure a merging thin origin isn't confused as a cow LV */ return (!lv_is_thin_volume(lv) && !lv_is_origin(lv) && lv->snapshot) ? 1 : 0; }