/*
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
 *
 * This file is part of LVM2.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU Lesser General Public License v.2.1.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "tools.h"

static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
			    struct volume_group *vg,
			    struct processing_handle *handle __attribute__((unused)))
{
	struct pv_create_args pva = { 0 };
	struct logical_volume *lv;
	struct lv_list *lvl;
	struct lvinfo info;
	int active = 0;

	if (!vg_check_status(vg, LVM_WRITE | EXPORTED_VG))
		return_ECMD_FAILED;

	if (vg->fid->fmt == cmd->fmt) {
		log_error("Volume group \"%s\" already uses format %s",
			  vg_name, cmd->fmt->name);
		return ECMD_FAILED;
	}

	if (cmd->fmt->features & FMT_MDAS) {
		if (arg_sign_value(cmd, metadatasize_ARG, SIGN_NONE) == SIGN_MINUS) {
			log_error("Metadata size may not be negative");
			return EINVALID_CMD_LINE;
		}

		pva.pvmetadatasize = arg_uint64_value(cmd, metadatasize_ARG, UINT64_C(0));
		if (!pva.pvmetadatasize)
			pva.pvmetadatasize = find_config_tree_int(cmd, metadata_pvmetadatasize_CFG, NULL);

		pva.pvmetadatacopies = arg_int_value(cmd, pvmetadatacopies_ARG, -1);
		if (pva.pvmetadatacopies < 0)
			pva.pvmetadatacopies = find_config_tree_int(cmd, metadata_pvmetadatacopies_CFG, NULL);
	}

	if (cmd->fmt->features & FMT_BAS) {
		if (arg_sign_value(cmd, bootloaderareasize_ARG, SIGN_NONE) == SIGN_MINUS) {
			log_error("Bootloader area size may not be negative");
			return EINVALID_CMD_LINE;
		}

		pva.ba_size = arg_uint64_value(cmd, bootloaderareasize_ARG, UINT64_C(0));
	}

	if (!vg_check_new_extent_size(cmd->fmt, vg->extent_size))
		return_ECMD_FAILED;

	if (!archive(vg)) {
		log_error("Archive of \"%s\" metadata failed.", vg_name);
		return ECMD_FAILED;
	}

	/* Set PV/LV limit if converting from unlimited metadata format */
	if (vg->fid->fmt->features & FMT_UNLIMITED_VOLS &&
	    !(cmd->fmt->features & FMT_UNLIMITED_VOLS)) {
		if (!vg->max_lv)
			vg->max_lv = 255;
		if (!vg->max_pv)
			vg->max_pv = 255;
	}

	/* If converting to restricted lvid, check if lvid is compatible */
	if (!(vg->fid->fmt->features & FMT_RESTRICTED_LVIDS) &&
	    cmd->fmt->features & FMT_RESTRICTED_LVIDS)
		dm_list_iterate_items(lvl, &vg->lvs)
			if (!lvid_in_restricted_range(&lvl->lv->lvid)) {
				log_error("Logical volume %s lvid format is"
					  " incompatible with requested"
					  " metadata format.", lvl->lv->name);
				return ECMD_FAILED;
			}

	/* New-style system ID supported? */ 
	if (vg->system_id && *vg->system_id && (cmd->fmt->features & FMT_SYSTEMID_ON_PVS)) {
		log_error("Unable to convert VG %s while it has a system ID set (%s).", vg->name,
			  vg->system_id);
		return ECMD_FAILED;
	}

	/* Attempt to change any LVIDs that are too big */
	if (cmd->fmt->features & FMT_RESTRICTED_LVIDS) {
		dm_list_iterate_items(lvl, &vg->lvs) {
			lv = lvl->lv;
			if (lv->status & SNAPSHOT)
				continue;
			if (lvnum_from_lvid(&lv->lvid) < MAX_RESTRICTED_LVS)
				continue;
			if (lv_info(cmd, lv, 0, &info, 0, 0) && info.exists) {
				log_error("Logical volume %s must be "
					  "deactivated before conversion.",
					   lv->name);
				active++;
				continue;
			}
			lvid_from_lvnum(&lv->lvid, &lv->vg->id, find_free_lvnum(lv));

		}
	}

	if (active)
		return_ECMD_FAILED;

	/* FIXME Cache the label format change so we don't have to skip this */
	if (test_mode()) {
		log_verbose("Test mode: Skipping metadata writing for VG %s in"
			    " format %s", vg_name, cmd->fmt->name);
		return ECMD_PROCESSED;
	}

	log_verbose("Writing metadata for VG %s using format %s", vg_name,
		    cmd->fmt->name);

	if (!backup_restore_vg(cmd, vg, 1, &pva)) {
		log_error("Conversion failed for volume group %s.", vg_name);
		log_error("Use pvcreate and vgcfgrestore to repair from "
			  "archived metadata.");
		return ECMD_FAILED;
	}
	log_print_unless_silent("Volume group %s successfully converted", vg_name);

	backup(vg);

	return ECMD_PROCESSED;
}

int vgconvert(struct cmd_context *cmd, int argc, char **argv)
{
	if (!argc) {
		log_error("Please enter volume group(s)");
		return EINVALID_CMD_LINE;
	}

	if (arg_is_set(cmd, metadatatype_ARG) && lvmetad_used()) {
		log_error("lvmetad must be disabled to change metadata types.");
		return EINVALID_CMD_LINE;
	}

	if (arg_int_value(cmd, labelsector_ARG, 0) >= LABEL_SCAN_SECTORS) {
		log_error("labelsector must be less than %lu",
			  LABEL_SCAN_SECTORS);
		return EINVALID_CMD_LINE;
	}

	if (arg_is_set(cmd, metadatacopies_ARG)) {
		log_error("Invalid option --metadatacopies, "
			  "use --pvmetadatacopies instead.");
		return EINVALID_CMD_LINE;
	}
	if (!(cmd->fmt->features & FMT_MDAS) &&
	    (arg_is_set(cmd, pvmetadatacopies_ARG) ||
	     arg_is_set(cmd, metadatasize_ARG))) {
		log_error("Metadata parameters only apply to text format");
		return EINVALID_CMD_LINE;
	}

	if (arg_is_set(cmd, pvmetadatacopies_ARG) &&
	    arg_int_value(cmd, pvmetadatacopies_ARG, -1) > 2) {
		log_error("Metadatacopies may only be 0, 1 or 2");
		return EINVALID_CMD_LINE;
	}

	if (!(cmd->fmt->features & FMT_BAS) &&
		arg_is_set(cmd, bootloaderareasize_ARG)) {
		log_error("Bootloader area parameters only apply to text format");
		return EINVALID_CMD_LINE;
	}

	return process_each_vg(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, 0, NULL,
			       &vgconvert_single);
}
