struct logical_volume *lv_to_poll;
- uint64_t poolmetadata_size; /* thin pool */
+ uint64_t poolmetadata_size;
const char *pool_data_lv_name;
- /* pool_metadata_lv_name is lv_name */
+ const char *pool_metadata_lv_name;
+ thin_discards_t discards;
};
static int _lvconvert_name_params(struct lvconvert_params *lp,
if ((ptr = strrchr(lp->lv_name_full, '/')))
lp->lv_name = ptr + 1;
- if (!lp->merge_mirror && !apply_lvname_restrictions(lp->lv_name))
+ if (!lp->merge_mirror &&
+ !strstr(lp->lv_name, "_tdata") &&
+ !strstr(lp->lv_name, "_tmeta") &&
+ !apply_lvname_restrictions(lp->lv_name))
return_0;
if (*pargc && lp->snapshot) {
log_error("--thinpool and --splitmirrors are mutually exlusive.");
return 0;
}
+ lp->discards = (thin_discards_t) arg_uint_value(cmd, discards_ARG, THIN_DISCARDS_PASSDOWN);
+ } else if (arg_count(cmd, discards_ARG)) {
+ log_error("--discards is only valid with --thinpool.");
+ return 0;
}
/*
return 0;
}
- if (arg_count(cmd, poolmetadatasize_ARG)) {
+ if (arg_count(cmd, poolmetadata_ARG)) {
+ lp->pool_metadata_lv_name = arg_str_value(cmd, poolmetadata_ARG, "");
+ } else if (arg_count(cmd, poolmetadatasize_ARG)) {
if (arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE) == SIGN_MINUS) {
log_error("Negative pool metadata size is invalid.");
return 0;
}
} else
lp->chunk_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
+
log_verbose("Setting pool metadata chunk size to %u sectors.",
lp->chunk_size);
} else { /* Mirrors (and some RAID functions) */
if (arg_count(cmd, chunksize_ARG)) {
log_error("--chunksize is only available with "
- "snapshots");
+ "snapshots or thin pools.");
return 0;
}
if (arg_count(cmd, zero_ARG)) {
- log_error("--zero is only available with snapshots");
+ log_error("--zero is only available with snapshots or thin pools.");
return 0;
}
return r;
}
+/*
+ * Thin lvconvert version which
+ * rename metadata
+ * convert/layers thinpool over data
+ * attach metadata
+ */
static int _lvconvert_thinpool(struct cmd_context *cmd,
- struct logical_volume *metadata_lv,
+ struct logical_volume *pool_lv,
struct lvconvert_params *lp)
{
int r = 0;
char *name;
int len;
- int was_active;
struct lv_segment *seg;
struct logical_volume *data_lv;
- struct logical_volume *pool_lv =
- (lp->pool_data_lv_name == lp->lv_name) ?
- metadata_lv : find_lv(metadata_lv->vg,
- lp->pool_data_lv_name);
+ struct logical_volume *metadata_lv;
+
+ if (lv_is_thin_type(pool_lv)) {
+ log_error("Can't use thin logical volume %s/%s for thin pool data.",
+ pool_lv->vg->name, pool_lv->name);
+ return 0;
+ }
- if (!pool_lv) {
- log_error("Can't find pool logical volume %s.", lp->lv_name);
+ /* We are changing target type, so deactivate first */
+ if (!deactivate_lv(cmd, pool_lv)) {
+ log_error("Can't deactivate logical volume %s/%s.",
+ pool_lv->vg->name, pool_lv->name);
return 0;
}
- if ((pool_lv != metadata_lv)) {
- if (!lv_is_visible(metadata_lv)) {
- log_error("Can't use hidden logical volume %s/%s for thin pool metadata.",
- metadata_lv->vg->name, metadata_lv->name);
- goto out;
+ if (lp->pool_metadata_lv_name) {
+ metadata_lv = find_lv(pool_lv->vg, lp->pool_metadata_lv_name);
+ if (!metadata_lv) {
+ log_error("Unknown metadata LV %s", lp->pool_metadata_lv_name);
+ return 0;
}
- if (lv_is_thin_pool(metadata_lv)) {
- log_error("Can't use thin pool logical volume %s/%s for thin pool metadata.",
- metadata_lv->vg->name, metadata_lv->name);
- goto out;
+ if (metadata_lv == pool_lv) {
+ log_error("Can't use same LV for thin data and metadata LV %s",
+ lp->pool_metadata_lv_name);
+ return 0;
}
- /* FIXME: any more types prohibited here ? */
- if (!deactivate_lv(cmd, metadata_lv)) {
- log_error("Can't deactivate logical volume %s/%s.",
+ if (lv_is_thin_type(metadata_lv)) {
+ log_error("Can't use thin pool logical volume %s/%s "
+ "for thin pool metadata.",
metadata_lv->vg->name, metadata_lv->name);
- goto out;
+ return 0;
}
- /* FIXME: initialize metadata LV! */
+ } else if (arg_count(cmd, poolmetadatasize_ARG)) {
+ /* FIXME: allocate metadata LV! */
+ metadata_lv = NULL;
+ log_error("Uncreated metadata.");
+ return 0;
} else {
- /* FIXME: add creation of metadata LV */
+ log_error("Uknown metadata.");
+ return 0;
}
- if (!lv_is_visible(pool_lv)) {
- log_error("Can't use hidden logical volume %s/%s for thin pool data.",
- metadata_lv->vg->name, metadata_lv->name);
- goto out;
- }
- if (lv_is_thin_pool(pool_lv)) {
- log_error("Can't use thin pool logical volume %s/%s for thin pool data.",
- metadata_lv->vg->name, metadata_lv->name);
- goto out;
+ len = strlen(pool_lv->name) + 16;
+ if (!(name = dm_pool_alloc(pool_lv->vg->vgmem, len))) {
+ log_error("Cannot allocate new name.");
+ return 0;
}
- /* FIXME: any more types prohibited here ? */
- if ((was_active = lv_is_active(pool_lv))) {
- if (!deactivate_lv(cmd, pool_lv)) {
+
+ if (!lv_is_active(metadata_lv)) {
+ if (!deactivate_lv(cmd, metadata_lv)) {
log_error("Can't deactivate logical volume %s/%s.",
- pool_lv->vg->name, pool_lv->name);
- goto out;
+ metadata_lv->vg->name, metadata_lv->name);
+ return 0;
+ }
+ if (!activate_lv_local(cmd, metadata_lv)) {
+ log_error("Aborting. Failed to activate thin metadata lv.");
+ return 0;
}
}
+ if (!set_lv(cmd, metadata_lv, UINT64_C(0), 0)) {
+ log_error("Aborting. Failed to wipe thin metadata lv.");
+ return 0;
+ }
+
+ if (!deactivate_lv(cmd, metadata_lv)) {
+ log_error("Aborting. Failed to deactivate thin metadata lv. "
+ "Manual intervention required.");
+ return 0;
+ }
+
+ if (dm_snprintf(name, len, "%s_tmeta", pool_lv->name) < 0)
+ return_0;
+
+ /* Rename deactivated metadata LV to have _tmeta suffix */
+ /* Implicit checks if metadata_lv is visible */
+ if (!lv_rename_update(cmd, metadata_lv, name, 0))
+ return_0;
+
+ /*
+ * Since we wish to have underlaying dev, to match _tdata
+ * rename data LV first, also checks for visible LV
+ */
+ /* FIXME: any more types prohibited here? */
+ /* FIXME: revert renamed LVs in fail path? */
+
/* FIXME: common code with metadata/thin_manip.c extend_pool() */
+ /* Create layer _tdata */
if (!(data_lv = insert_layer_for_lv(pool_lv->vg->cmd, pool_lv,
pool_lv->status, "_tdata")))
return_0;
seg->chunk_size = lp->chunk_size;
seg->zero_new_blocks = lp->zero ? 1 : 0;
+ seg->discards = lp->discards;
seg->low_water_mark = 0;
-
- len = strlen(pool_lv->name) + 16;
- if (!(name = dm_pool_alloc(pool_lv->vg->vgmem, len))) {
- log_error("Cannot allocate new name.");
- return 0;
- }
-
- if (dm_snprintf(name, len, "%s_tmeta", pool_lv->name) < 0)
- return_0;
- metadata_lv->name = name;
+ seg->transaction_id = 0;
if (!attach_pool_metadata_lv(seg, metadata_lv))
return_0;
if (!attach_pool_data_lv(seg, data_lv))
return_0;
- /* store vg on disk(s) */
if (!vg_write(pool_lv->vg) || !vg_commit(pool_lv->vg))
return_0;
- log_print_unless_silent("Converted %s/%s to thin pool.",
- pool_lv->vg->name, pool_lv->name);
- if (was_active && !activate_lv(cmd, pool_lv)) {
+ if (!activate_lv_excl(cmd, pool_lv)) {
log_error("Failed to activate pool logical volume %s/%s.",
pool_lv->vg->name, pool_lv->name);
goto out;
}
+ log_print_unless_silent("Converted %s/%s to thin pool.",
+ pool_lv->vg->name, pool_lv->name);
+
r = 1;
out:
backup(pool_lv->vg);
stack;
return ECMD_FAILED;
}
+ } else if (arg_count(cmd, thinpool_ARG)) {
+ if (!archive(lv->vg)) {
+ stack;
+ return ECMD_FAILED;
+ }
+ if (!_lvconvert_thinpool(cmd, lv, lp)) {
+ stack;
+ return ECMD_FAILED;
+ }
} else if (segtype_is_raid(lp->segtype) ||
(lv->status & RAID) || lp->merge_mirror) {
if (!archive(lv->vg)) {
/* If repairing and using policies, remove missing PVs from VG */
if (arg_count(cmd, repair_ARG) && arg_count(cmd, use_policies_ARG))
_remove_missing_empty_pv(lv->vg, failed_pvs);
- } else if (arg_count(cmd, thinpool_ARG)) {
- if (!archive(lv->vg)) {
- stack;
- return ECMD_FAILED;
- }
- if (!_lvconvert_thinpool(cmd, lv, lp)) {
- stack;
- return ECMD_FAILED;
- }
}
return ECMD_PROCESSED;