/*
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 * Copyright (C) 2004-2009 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"

struct vgextend_params {
	struct pvcreate_params pp;
};

static int _restore_pv(struct volume_group *vg, const char *pv_name)
{
	struct pv_list *pvl = NULL;
	pvl = find_pv_in_vg(vg, pv_name);
	if (!pvl) {
		log_warn("WARNING: PV %s not found in VG %s", pv_name, vg->name);
		return 0;
	}

	if (!(pvl->pv->status & MISSING_PV)) {
		log_warn("WARNING: PV %s was not missing in VG %s", pv_name, vg->name);
		return 0;
	}

	if (!pvl->pv->dev) {
		log_warn("WARNING: The PV %s is still missing.", pv_name);
		return 0;
	}

	pvl->pv->status &= ~MISSING_PV;
	return 1;
}

static int _vgextend_restoremissing(struct cmd_context *cmd __attribute__((unused)),
				    const char *vg_name, struct volume_group *vg,
				    struct processing_handle *handle)
{
	struct vgextend_params *vp = (struct vgextend_params *) handle->custom_handle;
	struct pvcreate_params *pp = &vp->pp;
	int fixed = 0;
	int i;

	if (!archive(vg))
		return_0;

	for (i = 0; i < pp->pv_count; i++)
		if (_restore_pv(vg, pp->pv_names[i]))
			fixed++;

	if (!fixed) {
		log_error("No PV has been restored.");
		return ECMD_FAILED;
	}

	if (!vg_write(vg) || !vg_commit(vg))
		return_ECMD_FAILED;

	backup(vg);

	log_print_unless_silent("Volume group \"%s\" successfully extended", vg_name);

	return ECMD_PROCESSED;
}

static int _vgextend_single(struct cmd_context *cmd, const char *vg_name,
			    struct volume_group *vg, struct processing_handle *handle)
{
	struct vgextend_params *vp = (struct vgextend_params *) handle->custom_handle;
	struct pvcreate_params *pp = &vp->pp;
	uint32_t mda_copies;
	uint32_t mda_used;
	int ret = ECMD_FAILED;

	if (arg_is_set(cmd, metadataignore_ARG) &&
	    (pp->force == PROMPT) && !pp->yes &&
	    (vg_mda_copies(vg) != VGMETADATACOPIES_UNMANAGED) &&
	    (yes_no_prompt("Override preferred number of copies of VG %s metadata? [y/n]: ", vg_name) == 'n')) {
		log_error("Volume group %s not changed", vg_name);
		return ECMD_FAILED;
	}

	if (!archive(vg))
		return_ECMD_FAILED;

	if (!vg_extend_each_pv(vg, pp))
		goto_out;

	if (arg_is_set(cmd, metadataignore_ARG)) {
		mda_copies = vg_mda_copies(vg);
		mda_used = vg_mda_used_count(vg);

		if ((mda_copies != VGMETADATACOPIES_UNMANAGED) &&
		    (mda_copies != mda_used)) {
			log_warn("WARNING: Changing preferred number of copies of VG %s metadata from %"PRIu32" to %"PRIu32,
				 vg_name, mda_copies, mda_used);
			vg_set_mda_copies(vg, mda_used);
		}
	}

	log_verbose("Volume group \"%s\" will be extended by %d new physical volumes", vg_name, pp->pv_count);

	if (!vg_write(vg) || !vg_commit(vg))
		goto_out;

	backup(vg);

	log_print_unless_silent("Volume group \"%s\" successfully extended", vg_name);
	ret = ECMD_PROCESSED;
out:
	return ret;
}

int vgextend(struct cmd_context *cmd, int argc, char **argv)
{
	struct processing_handle *handle;
	struct vgextend_params vp;
	struct pvcreate_params *pp = &vp.pp;
	unsigned restoremissing = arg_is_set(cmd, restoremissing_ARG);
	const char *vg_name;
	int ret;

	if (!argc) {
		log_error("Please enter volume group name and "
			  "physical volume(s)");
		return EINVALID_CMD_LINE;
	}

	if (arg_is_set(cmd, metadatacopies_ARG)) {
		log_error("Invalid option --metadatacopies, "
			  "use --pvmetadatacopies instead.");
		return EINVALID_CMD_LINE;
	}

	vg_name = skip_dev_dir(cmd, argv[0], NULL);
	argc--;
	argv++;

	pvcreate_params_set_defaults(pp);

	if (!pvcreate_params_from_args(cmd, pp))
		return EINVALID_CMD_LINE;

	pp->pv_count = argc;
	pp->pv_names = argv;

	/* Don't create a new PV on top of an existing PV like pvcreate does. */
	pp->preserve_existing = 1;

	/* pvcreate within vgextend cannot be forced. */
	pp->force = 0;

	/*
	 * Needed to change the set of orphan PVs.
	 * (disable afterward to prevent process_each_pv from doing
	 * a shared global lock since it's already acquired it ex.)
	 */
	if (!lockd_gl(cmd, "ex", 0))
		return_ECMD_FAILED;
	cmd->lockd_gl_disable = 1;

	if (!(handle = init_processing_handle(cmd, NULL))) {
		log_error("Failed to initialize processing handle.");
		return ECMD_FAILED;
	}

	if (!restoremissing) {
		if (!pvcreate_each_device(cmd, handle, pp)) {
			destroy_processing_handle(cmd, handle);
			return_ECMD_FAILED;
		}
	}

	/*
	 * pvcreate_each_device returns with the VG_ORPHANS write lock held,
	 * which was used to do pvcreate.  Now to create the VG using those
	 * PVs, the VG lock will be taken (with the orphan lock already held.)
	 */

	/*
	 * It is always ok to add new PVs to a VG - even if there are
	 * missing PVs.  No LVs are affected by this operation, but
	 * repair processes - particularly for RAID segtypes - can
	 * be facilitated.
	 */
	cmd->handles_missing_pvs = 1;

	handle->custom_handle = &vp;

	ret = process_each_vg(cmd, 0, NULL, vg_name, NULL,
			      READ_FOR_UPDATE, 0, handle,
			      restoremissing ? &_vgextend_restoremissing : &_vgextend_single);

	destroy_processing_handle(cmd, handle);

	if (!restoremissing)
		unlock_vg(cmd, NULL, VG_ORPHANS);
	return ret;
}
