/*
 * 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 vgreduce_params {
	int force;
	int fixed;
	int already_consistent;
};

static int _remove_pv(struct volume_group *vg, struct pv_list *pvl, int silent)
{
	char uuid[64] __attribute__((aligned(8)));

	if (vg->pv_count == 1) {
		log_error("Volume Groups must always contain at least one PV");
		return 0;
	}

	if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid)))
		return_0;

	log_verbose("Removing PV with UUID %s from VG %s", uuid, vg->name);

	if (pvl->pv->pe_alloc_count) {
		if (!silent)
			log_error("LVs still present on PV with UUID %s: "
				  "Can't remove from VG %s", uuid, vg->name);
		return 0;
	}

	vg->free_count -= pvl->pv->pe_count;
	vg->extent_count -= pvl->pv->pe_count;
	del_pvl_from_vgs(vg, pvl);
	free_pv_fid(pvl->pv);

	return 1;
}

static int _consolidate_vg(struct cmd_context *cmd, struct volume_group *vg)
{
	struct pv_list *pvl;
	struct lv_list *lvl;
	int r = 1;

	dm_list_iterate_items(lvl, &vg->lvs)
		if (lv_is_partial(lvl->lv)) {
			log_warn("WARNING: Partial LV %s needs to be repaired "
				 "or removed. ", lvl->lv->name);
			r = 0;
		}

	if (!r) {
		cmd->handles_missing_pvs = 1;
		log_error("There are still partial LVs in VG %s.", vg->name);
		log_error("To remove them unconditionally use: vgreduce --removemissing --force.");
		log_warn("Proceeding to remove empty missing PVs.");
	}

	dm_list_iterate_items(pvl, &vg->pvs) {
		if (pvl->pv->dev && !is_missing_pv(pvl->pv))
			continue;
		if (r && !_remove_pv(vg, pvl, 0))
			return_0;
	}

	return r;
}

static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
{
	struct lv_list *lvl;
	struct logical_volume *lv;

	cmd->partial_activation = 1;

 restart:
	vg_mark_partial_lvs(vg, 1);

	dm_list_iterate_items(lvl, &vg->lvs) {
		lv = lvl->lv;

		/* Are any segments of this LV on missing PVs? */
		if (lv_is_partial(lv)) {
			if (seg_is_raid(first_seg(lv))) {
				if (!lv_raid_remove_missing(lv))
					return_0;
				goto restart;
			}

			if (lv_is_mirror(lv)) {
				if (!mirror_remove_missing(cmd, lv, 1))
					return_0;
				goto restart;
			}

			if (arg_is_set(cmd, mirrorsonly_ARG) && !lv_is_mirrored(lv)) {
				log_error("Non-mirror-image LV %s found: can't remove.", lv->name);
				continue;
			}

			if (!lv_is_visible(lv))
				continue;
			log_warn("Removing partial LV %s.", lv->name);
			if (!lv_remove_with_dependencies(cmd, lv, DONT_PROMPT, 0))
				return_0;
			goto restart;
		}
	}

	_consolidate_vg(cmd, vg);

	return 1;
}

/* Or take pv_name instead? */
static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
			    struct physical_volume *pv,
			    struct processing_handle *handle __attribute__((unused)))
{
	int r;

	if (!vg_check_status(vg, EXPORTED_VG | LVM_WRITE | RESIZEABLE_VG))
		return ECMD_FAILED;

	r = vgreduce_single(cmd, vg, pv, 1);
	if (!r)
		return ECMD_FAILED;

	return ECMD_PROCESSED;
}

static int _vgreduce_repair_single(struct cmd_context *cmd, const char *vg_name,
		                   struct volume_group *vg, struct processing_handle *handle)
{
	struct vgreduce_params *vp = (struct vgreduce_params *) handle->custom_handle;

	if (!vg_missing_pv_count(vg)) {
		vp->already_consistent = 1;
		return ECMD_PROCESSED;
	}

	if (!archive(vg))
		return_ECMD_FAILED;

	if (vp->force) {
		if (!_make_vg_consistent(cmd, vg))
			return_ECMD_FAILED;
		vp->fixed = 1;
	} else
		vp->fixed = _consolidate_vg(cmd, vg);

	if (!vg_write(vg) || !vg_commit(vg)) {
		log_error("Failed to write out a consistent VG for %s", vg_name);
		return ECMD_FAILED;
	}

	backup(vg);
	return ECMD_PROCESSED;
}

int vgreduce(struct cmd_context *cmd, int argc, char **argv)
{
	struct processing_handle *handle;
	struct vgreduce_params vp = { 0 };
	const char *vg_name;
	int repairing = arg_is_set(cmd, removemissing_ARG);
	int saved_ignore_suspended_devices = ignore_suspended_devices();
	int ret;

	if (!argc && !repairing) {
		log_error("Please give volume group name and "
			  "physical volume paths");
		return EINVALID_CMD_LINE;
	}
	
	if (!argc) { /* repairing */
		log_error("Please give volume group name");
		return EINVALID_CMD_LINE;
	}

	if (arg_is_set(cmd, mirrorsonly_ARG) && !repairing) {
		log_error("--mirrorsonly requires --removemissing");
		return EINVALID_CMD_LINE;
	}

	if (argc == 1 && !arg_is_set(cmd, all_ARG) && !repairing) {
		log_error("Please enter physical volume paths or option -a");
		return EINVALID_CMD_LINE;
	}

	if (argc > 1 && arg_is_set(cmd, all_ARG)) {
		log_error("Option -a and physical volume paths mutually "
			  "exclusive");
		return EINVALID_CMD_LINE;
	}

	if (argc > 1 && repairing) {
		log_error("Please only specify the volume group");
		return EINVALID_CMD_LINE;
	}

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

	/* Needed to change the set of orphan PVs. */
	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;
	}
	handle->custom_handle = &vp;

	if (!repairing) {
		/* FIXME: Pass private struct through to all these functions */
		/* and update in batch afterwards? */
		ret = process_each_pv(cmd, argc, argv, vg_name, 0, READ_FOR_UPDATE, handle, _vgreduce_single);
		goto out;
	}

	/*
	 * VG repair (removemissing)
	 */

	vp.force = arg_count(cmd, force_ARG);

	cmd->handles_missing_pvs = 1;

	init_ignore_suspended_devices(1);

	process_each_vg(cmd, 0, NULL, vg_name, NULL,
			READ_FOR_UPDATE | READ_ALLOW_EXPORTED,
			0, handle, &_vgreduce_repair_single);

	if (vp.already_consistent) {
		log_print_unless_silent("Volume group \"%s\" is already consistent", vg_name);
		ret = ECMD_PROCESSED;
	} else if (vp.fixed) {
		log_print_unless_silent("Wrote out consistent volume group %s", vg_name);
		ret = ECMD_PROCESSED;
	} else
		ret = ECMD_FAILED;
out:
	init_ignore_suspended_devices(saved_ignore_suspended_devices);
	destroy_processing_handle(cmd, handle);

	return ret;
}
