Home | History | Annotate | Line # | Download | only in tools
pvmove.c revision 1.1
      1  1.1  haad /*	$NetBSD: pvmove.c,v 1.1 2008/12/22 00:19:07 haad Exp $	*/
      2  1.1  haad 
      3  1.1  haad /*
      4  1.1  haad  * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
      5  1.1  haad  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
      6  1.1  haad  *
      7  1.1  haad  * This file is part of LVM2.
      8  1.1  haad  *
      9  1.1  haad  * This copyrighted material is made available to anyone wishing to use,
     10  1.1  haad  * modify, copy, or redistribute it subject to the terms and conditions
     11  1.1  haad  * of the GNU Lesser General Public License v.2.1.
     12  1.1  haad  *
     13  1.1  haad  * You should have received a copy of the GNU Lesser General Public License
     14  1.1  haad  * along with this program; if not, write to the Free Software Foundation,
     15  1.1  haad  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     16  1.1  haad  */
     17  1.1  haad 
     18  1.1  haad #include "tools.h"
     19  1.1  haad #include "polldaemon.h"
     20  1.1  haad #include "display.h"
     21  1.1  haad 
     22  1.1  haad #define PVMOVE_FIRST_TIME   0x00000001      /* Called for first time */
     23  1.1  haad 
     24  1.1  haad static int _pvmove_target_present(struct cmd_context *cmd, int clustered)
     25  1.1  haad {
     26  1.1  haad 	const struct segment_type *segtype;
     27  1.1  haad 	unsigned attr = 0;
     28  1.1  haad 	int found = 1;
     29  1.1  haad 	static int _clustered_found = -1;
     30  1.1  haad 
     31  1.1  haad 	if (clustered && _clustered_found >= 0)
     32  1.1  haad 		return _clustered_found;
     33  1.1  haad 
     34  1.1  haad 	if (!(segtype = get_segtype_from_string(cmd, "mirror")))
     35  1.1  haad 		return_0;
     36  1.1  haad 
     37  1.1  haad 	if (activation() && segtype->ops->target_present &&
     38  1.1  haad 	    !segtype->ops->target_present(NULL, clustered ? &attr : NULL))
     39  1.1  haad 		found = 0;
     40  1.1  haad 
     41  1.1  haad 	if (activation() && clustered) {
     42  1.1  haad 		if (found && (attr & MIRROR_LOG_CLUSTERED))
     43  1.1  haad 			_clustered_found = found = 1;
     44  1.1  haad 		else
     45  1.1  haad 			_clustered_found = found = 0;
     46  1.1  haad 	}
     47  1.1  haad 
     48  1.1  haad 	return found;
     49  1.1  haad }
     50  1.1  haad 
     51  1.1  haad static unsigned _pvmove_is_exclusive(struct cmd_context *cmd,
     52  1.1  haad 				     struct volume_group *vg)
     53  1.1  haad {
     54  1.1  haad 	if (vg_is_clustered(vg))
     55  1.1  haad 		if (!_pvmove_target_present(cmd, 1))
     56  1.1  haad 			return 1;
     57  1.1  haad 
     58  1.1  haad 	return 0;
     59  1.1  haad }
     60  1.1  haad 
     61  1.1  haad /* Allow /dev/vgname/lvname, vgname/lvname or lvname */
     62  1.1  haad static const char *_extract_lvname(struct cmd_context *cmd, const char *vgname,
     63  1.1  haad 				   const char *arg)
     64  1.1  haad {
     65  1.1  haad 	const char *lvname;
     66  1.1  haad 
     67  1.1  haad 	/* Is an lvname supplied directly? */
     68  1.1  haad 	if (!strchr(arg, '/'))
     69  1.1  haad 		return arg;
     70  1.1  haad 
     71  1.1  haad 	lvname = skip_dev_dir(cmd, arg, NULL);
     72  1.1  haad 	while (*lvname == '/')
     73  1.1  haad 		lvname++;
     74  1.1  haad 	if (!strchr(lvname, '/')) {
     75  1.1  haad 		log_error("--name takes a logical volume name");
     76  1.1  haad 		return NULL;
     77  1.1  haad 	}
     78  1.1  haad 	if (strncmp(vgname, lvname, strlen(vgname)) ||
     79  1.1  haad 	    (lvname += strlen(vgname), *lvname != '/')) {
     80  1.1  haad 		log_error("Named LV and old PV must be in the same VG");
     81  1.1  haad 		return NULL;
     82  1.1  haad 	}
     83  1.1  haad 	while (*lvname == '/')
     84  1.1  haad 		lvname++;
     85  1.1  haad 	if (!*lvname) {
     86  1.1  haad 		log_error("Incomplete LV name supplied with --name");
     87  1.1  haad 		return NULL;
     88  1.1  haad 	}
     89  1.1  haad 	return lvname;
     90  1.1  haad }
     91  1.1  haad 
     92  1.1  haad static struct volume_group *_get_vg(struct cmd_context *cmd, const char *vgname)
     93  1.1  haad {
     94  1.1  haad 	struct volume_group *vg;
     95  1.1  haad 
     96  1.1  haad 	dev_close_all();
     97  1.1  haad 
     98  1.1  haad 	if (!(vg = vg_lock_and_read(cmd, vgname, NULL, LCK_VG_WRITE,
     99  1.1  haad 				    CLUSTERED | EXPORTED_VG | LVM_WRITE,
    100  1.1  haad 				    CORRECT_INCONSISTENT | FAIL_INCONSISTENT)))
    101  1.1  haad 		 return NULL;
    102  1.1  haad 
    103  1.1  haad 	return vg;
    104  1.1  haad }
    105  1.1  haad 
    106  1.1  haad /* Create list of PVs for allocation of replacement extents */
    107  1.1  haad static struct dm_list *_get_allocatable_pvs(struct cmd_context *cmd, int argc,
    108  1.1  haad 					 char **argv, struct volume_group *vg,
    109  1.1  haad 					 struct physical_volume *pv,
    110  1.1  haad 					 alloc_policy_t alloc)
    111  1.1  haad {
    112  1.1  haad 	struct dm_list *allocatable_pvs, *pvht, *pvh;
    113  1.1  haad 	struct pv_list *pvl;
    114  1.1  haad 
    115  1.1  haad 	if (argc)
    116  1.1  haad 		allocatable_pvs = create_pv_list(cmd->mem, vg, argc, argv, 1);
    117  1.1  haad 	else
    118  1.1  haad 		allocatable_pvs = clone_pv_list(cmd->mem, &vg->pvs);
    119  1.1  haad 
    120  1.1  haad 	if (!allocatable_pvs)
    121  1.1  haad 		return_NULL;
    122  1.1  haad 
    123  1.1  haad 	dm_list_iterate_safe(pvh, pvht, allocatable_pvs) {
    124  1.1  haad 		pvl = dm_list_item(pvh, struct pv_list);
    125  1.1  haad 
    126  1.1  haad 		/* Don't allocate onto the PV we're clearing! */
    127  1.1  haad 		if ((alloc != ALLOC_ANYWHERE) && (pvl->pv->dev == pv_dev(pv))) {
    128  1.1  haad 			dm_list_del(&pvl->list);
    129  1.1  haad 			continue;
    130  1.1  haad 		}
    131  1.1  haad 
    132  1.1  haad 		/* Remove PV if full */
    133  1.1  haad 		if ((pvl->pv->pe_count == pvl->pv->pe_alloc_count))
    134  1.1  haad 			dm_list_del(&pvl->list);
    135  1.1  haad 	}
    136  1.1  haad 
    137  1.1  haad 	if (dm_list_empty(allocatable_pvs)) {
    138  1.1  haad 		log_error("No extents available for allocation");
    139  1.1  haad 		return NULL;
    140  1.1  haad 	}
    141  1.1  haad 
    142  1.1  haad 	return allocatable_pvs;
    143  1.1  haad }
    144  1.1  haad 
    145  1.1  haad /*
    146  1.1  haad  * Replace any LV segments on given PV with temporary mirror.
    147  1.1  haad  * Returns list of LVs changed.
    148  1.1  haad  */
    149  1.1  haad static int _insert_pvmove_mirrors(struct cmd_context *cmd,
    150  1.1  haad 				  struct logical_volume *lv_mirr,
    151  1.1  haad 				  struct dm_list *source_pvl,
    152  1.1  haad 				  struct logical_volume *lv,
    153  1.1  haad 				  struct dm_list *lvs_changed)
    154  1.1  haad 
    155  1.1  haad {
    156  1.1  haad 	struct pv_list *pvl;
    157  1.1  haad 	uint32_t prev_le_count;
    158  1.1  haad 
    159  1.1  haad 	/* Only 1 PV may feature in source_pvl */
    160  1.1  haad 	pvl = dm_list_item(source_pvl->n, struct pv_list);
    161  1.1  haad 
    162  1.1  haad 	prev_le_count = lv_mirr->le_count;
    163  1.1  haad 	if (!insert_layer_for_segments_on_pv(cmd, lv, lv_mirr, PVMOVE,
    164  1.1  haad 					     pvl, lvs_changed))
    165  1.1  haad 		return_0;
    166  1.1  haad 
    167  1.1  haad 	/* check if layer was inserted */
    168  1.1  haad 	if (lv_mirr->le_count - prev_le_count) {
    169  1.1  haad 		lv->status |= LOCKED;
    170  1.1  haad 
    171  1.1  haad 		log_verbose("Moving %u extents of logical volume %s/%s",
    172  1.1  haad 			    lv_mirr->le_count - prev_le_count,
    173  1.1  haad 			    lv->vg->name, lv->name);
    174  1.1  haad 	}
    175  1.1  haad 
    176  1.1  haad 	return 1;
    177  1.1  haad }
    178  1.1  haad 
    179  1.1  haad /* Create new LV with mirror segments for the required copies */
    180  1.1  haad static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
    181  1.1  haad 						struct volume_group *vg,
    182  1.1  haad 						struct dm_list *source_pvl,
    183  1.1  haad 						const char *lv_name,
    184  1.1  haad 						struct dm_list *allocatable_pvs,
    185  1.1  haad 						alloc_policy_t alloc,
    186  1.1  haad 						struct dm_list **lvs_changed)
    187  1.1  haad {
    188  1.1  haad 	struct logical_volume *lv_mirr, *lv;
    189  1.1  haad 	struct lv_list *lvl;
    190  1.1  haad 	uint32_t log_count = 0;
    191  1.1  haad 	int lv_found = 0;
    192  1.1  haad 
    193  1.1  haad 	/* FIXME Cope with non-contiguous => splitting existing segments */
    194  1.1  haad 	if (!(lv_mirr = lv_create_empty("pvmove%d", NULL,
    195  1.1  haad 					LVM_READ | LVM_WRITE,
    196  1.1  haad 					ALLOC_CONTIGUOUS, 0, vg))) {
    197  1.1  haad 		log_error("Creation of temporary pvmove LV failed");
    198  1.1  haad 		return NULL;
    199  1.1  haad 	}
    200  1.1  haad 
    201  1.1  haad 	lv_mirr->status |= (PVMOVE | LOCKED);
    202  1.1  haad 
    203  1.1  haad 	if (!(*lvs_changed = dm_pool_alloc(cmd->mem, sizeof(**lvs_changed)))) {
    204  1.1  haad 		log_error("lvs_changed list struct allocation failed");
    205  1.1  haad 		return NULL;
    206  1.1  haad 	}
    207  1.1  haad 
    208  1.1  haad 	dm_list_init(*lvs_changed);
    209  1.1  haad 
    210  1.1  haad 	/* Find segments to be moved and set up mirrors */
    211  1.1  haad 	dm_list_iterate_items(lvl, &vg->lvs) {
    212  1.1  haad 		lv = lvl->lv;
    213  1.1  haad 		if ((lv == lv_mirr))
    214  1.1  haad 			continue;
    215  1.1  haad 		if (lv_name) {
    216  1.1  haad 			if (strcmp(lv->name, lv_name))
    217  1.1  haad 				continue;
    218  1.1  haad 			lv_found = 1;
    219  1.1  haad 		}
    220  1.1  haad 		if (lv_is_origin(lv) || lv_is_cow(lv)) {
    221  1.1  haad 			log_print("Skipping snapshot-related LV %s", lv->name);
    222  1.1  haad 			continue;
    223  1.1  haad 		}
    224  1.1  haad 		if (lv->status & MIRRORED) {
    225  1.1  haad 			log_print("Skipping mirror LV %s", lv->name);
    226  1.1  haad 			continue;
    227  1.1  haad 		}
    228  1.1  haad 		if (lv->status & MIRROR_LOG) {
    229  1.1  haad 			log_print("Skipping mirror log LV %s", lv->name);
    230  1.1  haad 			continue;
    231  1.1  haad 		}
    232  1.1  haad 		if (lv->status & MIRROR_IMAGE) {
    233  1.1  haad 			log_print("Skipping mirror image LV %s", lv->name);
    234  1.1  haad 			continue;
    235  1.1  haad 		}
    236  1.1  haad 		if (lv->status & LOCKED) {
    237  1.1  haad 			log_print("Skipping locked LV %s", lv->name);
    238  1.1  haad 			continue;
    239  1.1  haad 		}
    240  1.1  haad 		if (!_insert_pvmove_mirrors(cmd, lv_mirr, source_pvl, lv,
    241  1.1  haad 					    *lvs_changed))
    242  1.1  haad 			return_NULL;
    243  1.1  haad 	}
    244  1.1  haad 
    245  1.1  haad 	if (lv_name && !lv_found) {
    246  1.1  haad 		log_error("Logical volume %s not found.", lv_name);
    247  1.1  haad 		return NULL;
    248  1.1  haad 	}
    249  1.1  haad 
    250  1.1  haad 	/* Is temporary mirror empty? */
    251  1.1  haad 	if (!lv_mirr->le_count) {
    252  1.1  haad 		log_error("No data to move for %s", vg->name);
    253  1.1  haad 		return NULL;
    254  1.1  haad 	}
    255  1.1  haad 
    256  1.1  haad 	if (!lv_add_mirrors(cmd, lv_mirr, 1, 1, 0, log_count,
    257  1.1  haad 			    allocatable_pvs, alloc, MIRROR_BY_SEG)) {
    258  1.1  haad 		log_error("Failed to convert pvmove LV to mirrored");
    259  1.1  haad 		return_NULL;
    260  1.1  haad 	}
    261  1.1  haad 
    262  1.1  haad 	if (!split_parent_segments_for_layer(cmd, lv_mirr)) {
    263  1.1  haad 		log_error("Failed to split segments being moved");
    264  1.1  haad 		return_NULL;
    265  1.1  haad 	}
    266  1.1  haad 
    267  1.1  haad 	return lv_mirr;
    268  1.1  haad }
    269  1.1  haad 
    270  1.1  haad static int _activate_lv(struct cmd_context *cmd, struct logical_volume *lv_mirr,
    271  1.1  haad 			unsigned exclusive)
    272  1.1  haad {
    273  1.1  haad 	if (exclusive)
    274  1.1  haad 		return activate_lv_excl(cmd, lv_mirr);
    275  1.1  haad 
    276  1.1  haad 	return activate_lv(cmd, lv_mirr);
    277  1.1  haad }
    278  1.1  haad 
    279  1.1  haad static int _update_metadata(struct cmd_context *cmd, struct volume_group *vg,
    280  1.1  haad 			    struct logical_volume *lv_mirr,
    281  1.1  haad 			    struct dm_list *lvs_changed, unsigned flags)
    282  1.1  haad {
    283  1.1  haad 	unsigned exclusive = _pvmove_is_exclusive(cmd, vg);
    284  1.1  haad 	unsigned first_time = (flags & PVMOVE_FIRST_TIME) ? 1 : 0;
    285  1.1  haad 
    286  1.1  haad 	log_verbose("Updating volume group metadata");
    287  1.1  haad 	if (!vg_write(vg)) {
    288  1.1  haad 		log_error("ABORTING: Volume group metadata update failed.");
    289  1.1  haad 		return 0;
    290  1.1  haad 	}
    291  1.1  haad 
    292  1.1  haad 	backup(vg);
    293  1.1  haad 
    294  1.1  haad 	/* Suspend lvs_changed */
    295  1.1  haad 	if (!suspend_lvs(cmd, lvs_changed))
    296  1.1  haad 		return_0;
    297  1.1  haad 
    298  1.1  haad 	/* Suspend mirrors on subsequent calls */
    299  1.1  haad 	if (!first_time) {
    300  1.1  haad 		if (!suspend_lv(cmd, lv_mirr)) {
    301  1.1  haad 			stack;
    302  1.1  haad 			resume_lvs(cmd, lvs_changed);
    303  1.1  haad 			vg_revert(vg);
    304  1.1  haad 			return 0;
    305  1.1  haad 		}
    306  1.1  haad 	}
    307  1.1  haad 
    308  1.1  haad 	/* Commit on-disk metadata */
    309  1.1  haad 	if (!vg_commit(vg)) {
    310  1.1  haad 		log_error("ABORTING: Volume group metadata update failed.");
    311  1.1  haad 		if (!first_time)
    312  1.1  haad 			resume_lv(cmd, lv_mirr);
    313  1.1  haad 		resume_lvs(cmd, lvs_changed);
    314  1.1  haad 		return 0;
    315  1.1  haad 	}
    316  1.1  haad 
    317  1.1  haad 	/* Activate the temporary mirror LV */
    318  1.1  haad 	/* Only the first mirror segment gets activated as a mirror */
    319  1.1  haad 	/* FIXME: Add option to use a log */
    320  1.1  haad 	if (first_time) {
    321  1.1  haad 		if (!_activate_lv(cmd, lv_mirr, exclusive)) {
    322  1.1  haad 			if (!test_mode())
    323  1.1  haad 				log_error("ABORTING: Temporary mirror "
    324  1.1  haad 					  "activation failed.  "
    325  1.1  haad 					  "Run pvmove --abort.");
    326  1.1  haad 			/* FIXME Resume using *original* metadata here! */
    327  1.1  haad 			resume_lvs(cmd, lvs_changed);
    328  1.1  haad 			return 0;
    329  1.1  haad 		}
    330  1.1  haad 	} else if (!resume_lv(cmd, lv_mirr)) {
    331  1.1  haad 		log_error("Unable to reactivate logical volume \"%s\"",
    332  1.1  haad 			  lv_mirr->name);
    333  1.1  haad 		resume_lvs(cmd, lvs_changed);
    334  1.1  haad 		return 0;
    335  1.1  haad 	}
    336  1.1  haad 
    337  1.1  haad 	/* Unsuspend LVs */
    338  1.1  haad 	if (!resume_lvs(cmd, lvs_changed)) {
    339  1.1  haad 		log_error("Unable to resume logical volumes");
    340  1.1  haad 		return 0;
    341  1.1  haad 	}
    342  1.1  haad 
    343  1.1  haad 	return 1;
    344  1.1  haad }
    345  1.1  haad 
    346  1.1  haad static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
    347  1.1  haad 			  int argc, char **argv)
    348  1.1  haad {
    349  1.1  haad 	const char *lv_name = NULL;
    350  1.1  haad 	char *pv_name_arg;
    351  1.1  haad 	struct volume_group *vg;
    352  1.1  haad 	struct dm_list *source_pvl;
    353  1.1  haad 	struct dm_list *allocatable_pvs;
    354  1.1  haad 	alloc_policy_t alloc;
    355  1.1  haad 	struct dm_list *lvs_changed;
    356  1.1  haad 	struct physical_volume *pv;
    357  1.1  haad 	struct logical_volume *lv_mirr;
    358  1.1  haad 	unsigned first_time = 1;
    359  1.1  haad 	unsigned exclusive;
    360  1.1  haad 
    361  1.1  haad 	pv_name_arg = argv[0];
    362  1.1  haad 	argc--;
    363  1.1  haad 	argv++;
    364  1.1  haad 
    365  1.1  haad 	/* Find PV (in VG) */
    366  1.1  haad 	if (!(pv = find_pv_by_name(cmd, pv_name))) {
    367  1.1  haad 		stack;
    368  1.1  haad 		return EINVALID_CMD_LINE;
    369  1.1  haad 	}
    370  1.1  haad 
    371  1.1  haad 	if (arg_count(cmd, name_ARG)) {
    372  1.1  haad 		if (!(lv_name = _extract_lvname(cmd, pv_vg_name(pv),
    373  1.1  haad 						arg_value(cmd, name_ARG)))) {
    374  1.1  haad 			stack;
    375  1.1  haad 			return EINVALID_CMD_LINE;
    376  1.1  haad 		}
    377  1.1  haad 
    378  1.1  haad 		if (!validate_name(lv_name)) {
    379  1.1  haad 			log_error("Logical volume name %s is invalid", lv_name);
    380  1.1  haad 			return EINVALID_CMD_LINE;
    381  1.1  haad 		}
    382  1.1  haad 	}
    383  1.1  haad 
    384  1.1  haad 	/* Read VG */
    385  1.1  haad 	log_verbose("Finding volume group \"%s\"", pv_vg_name(pv));
    386  1.1  haad 
    387  1.1  haad 	if (!(vg = _get_vg(cmd, pv_vg_name(pv)))) {
    388  1.1  haad 		stack;
    389  1.1  haad 		return ECMD_FAILED;
    390  1.1  haad 	}
    391  1.1  haad 
    392  1.1  haad 	exclusive = _pvmove_is_exclusive(cmd, vg);
    393  1.1  haad 
    394  1.1  haad 	if ((lv_mirr = find_pvmove_lv(vg, pv_dev(pv), PVMOVE))) {
    395  1.1  haad 		log_print("Detected pvmove in progress for %s", pv_name);
    396  1.1  haad 		if (argc || lv_name)
    397  1.1  haad 			log_error("Ignoring remaining command line arguments");
    398  1.1  haad 
    399  1.1  haad 		if (!(lvs_changed = lvs_using_lv(cmd, vg, lv_mirr))) {
    400  1.1  haad 			log_error
    401  1.1  haad 			    ("ABORTING: Failed to generate list of moving LVs");
    402  1.1  haad 			unlock_vg(cmd, pv_vg_name(pv));
    403  1.1  haad 			return ECMD_FAILED;
    404  1.1  haad 		}
    405  1.1  haad 
    406  1.1  haad 		/* Ensure mirror LV is active */
    407  1.1  haad 		if (!_activate_lv(cmd, lv_mirr, exclusive)) {
    408  1.1  haad 			log_error
    409  1.1  haad 			    ("ABORTING: Temporary mirror activation failed.");
    410  1.1  haad 			unlock_vg(cmd, pv_vg_name(pv));
    411  1.1  haad 			return ECMD_FAILED;
    412  1.1  haad 		}
    413  1.1  haad 
    414  1.1  haad 		first_time = 0;
    415  1.1  haad 	} else {
    416  1.1  haad 		/* Determine PE ranges to be moved */
    417  1.1  haad 		if (!(source_pvl = create_pv_list(cmd->mem, vg, 1,
    418  1.1  haad 						  &pv_name_arg, 0))) {
    419  1.1  haad 			stack;
    420  1.1  haad 			unlock_vg(cmd, pv_vg_name(pv));
    421  1.1  haad 			return ECMD_FAILED;
    422  1.1  haad 		}
    423  1.1  haad 
    424  1.1  haad 		alloc = arg_uint_value(cmd, alloc_ARG, ALLOC_INHERIT);
    425  1.1  haad 		if (alloc == ALLOC_INHERIT)
    426  1.1  haad 			alloc = vg->alloc;
    427  1.1  haad 
    428  1.1  haad 		/* Get PVs we can use for allocation */
    429  1.1  haad 		if (!(allocatable_pvs = _get_allocatable_pvs(cmd, argc, argv,
    430  1.1  haad 							     vg, pv, alloc))) {
    431  1.1  haad 			stack;
    432  1.1  haad 			unlock_vg(cmd, pv_vg_name(pv));
    433  1.1  haad 			return ECMD_FAILED;
    434  1.1  haad 		}
    435  1.1  haad 
    436  1.1  haad 		if (!archive(vg)) {
    437  1.1  haad 			unlock_vg(cmd, pv_vg_name(pv));
    438  1.1  haad 			stack;
    439  1.1  haad 			return ECMD_FAILED;
    440  1.1  haad 		}
    441  1.1  haad 
    442  1.1  haad 		if (!(lv_mirr = _set_up_pvmove_lv(cmd, vg, source_pvl, lv_name,
    443  1.1  haad 						  allocatable_pvs, alloc,
    444  1.1  haad 						  &lvs_changed))) {
    445  1.1  haad 			stack;
    446  1.1  haad 			unlock_vg(cmd, pv_vg_name(pv));
    447  1.1  haad 			return ECMD_FAILED;
    448  1.1  haad 		}
    449  1.1  haad 	}
    450  1.1  haad 
    451  1.1  haad 	/* Lock lvs_changed and activate (with old metadata) */
    452  1.1  haad 	if (!activate_lvs(cmd, lvs_changed, exclusive)) {
    453  1.1  haad 		stack;
    454  1.1  haad 		unlock_vg(cmd, pv_vg_name(pv));
    455  1.1  haad 		return ECMD_FAILED;
    456  1.1  haad 	}
    457  1.1  haad 
    458  1.1  haad 	/* FIXME Presence of a mirror once set PVMOVE - now remove associated logic */
    459  1.1  haad 	/* init_pvmove(1); */
    460  1.1  haad 	/* vg->status |= PVMOVE; */
    461  1.1  haad 
    462  1.1  haad 	if (first_time) {
    463  1.1  haad 		if (!_update_metadata
    464  1.1  haad 		    (cmd, vg, lv_mirr, lvs_changed, PVMOVE_FIRST_TIME)) {
    465  1.1  haad 			stack;
    466  1.1  haad 			unlock_vg(cmd, pv_vg_name(pv));
    467  1.1  haad 			return ECMD_FAILED;
    468  1.1  haad 		}
    469  1.1  haad 	}
    470  1.1  haad 
    471  1.1  haad 	/* LVs are all in status LOCKED */
    472  1.1  haad 	unlock_vg(cmd, pv_vg_name(pv));
    473  1.1  haad 
    474  1.1  haad 	return ECMD_PROCESSED;
    475  1.1  haad }
    476  1.1  haad 
    477  1.1  haad static int _finish_pvmove(struct cmd_context *cmd, struct volume_group *vg,
    478  1.1  haad 			  struct logical_volume *lv_mirr,
    479  1.1  haad 			  struct dm_list *lvs_changed)
    480  1.1  haad {
    481  1.1  haad 	int r = 1;
    482  1.1  haad 	struct dm_list lvs_completed;
    483  1.1  haad 	struct lv_list *lvl;
    484  1.1  haad 
    485  1.1  haad 	/* Update metadata to remove mirror segments and break dependencies */
    486  1.1  haad 	dm_list_init(&lvs_completed);
    487  1.1  haad 	if (!lv_remove_mirrors(cmd, lv_mirr, 1, 0, NULL, PVMOVE) ||
    488  1.1  haad 	    !remove_layers_for_segments_all(cmd, lv_mirr, PVMOVE,
    489  1.1  haad 					    &lvs_completed)) {
    490  1.1  haad 		log_error("ABORTING: Removal of temporary mirror failed");
    491  1.1  haad 		return 0;
    492  1.1  haad 	}
    493  1.1  haad 
    494  1.1  haad 	dm_list_iterate_items(lvl, &lvs_completed)
    495  1.1  haad 		/* FIXME Assumes only one pvmove at a time! */
    496  1.1  haad 		lvl->lv->status &= ~LOCKED;
    497  1.1  haad 
    498  1.1  haad 	/* Store metadata without dependencies on mirror segments */
    499  1.1  haad 	if (!vg_write(vg)) {
    500  1.1  haad 		log_error("ABORTING: Failed to write new data locations "
    501  1.1  haad 			  "to disk.");
    502  1.1  haad 		return 0;
    503  1.1  haad 	}
    504  1.1  haad 
    505  1.1  haad 	/* Suspend LVs changed */
    506  1.1  haad 	if (!suspend_lvs(cmd, lvs_changed)) {
    507  1.1  haad 		log_error("Locking LVs to remove temporary mirror failed");
    508  1.1  haad 		r = 0;
    509  1.1  haad 	}
    510  1.1  haad 
    511  1.1  haad 	/* Suspend mirror LV to flush pending I/O */
    512  1.1  haad 	if (!suspend_lv(cmd, lv_mirr)) {
    513  1.1  haad 		log_error("Suspension of temporary mirror LV failed");
    514  1.1  haad 		r = 0;
    515  1.1  haad 	}
    516  1.1  haad 
    517  1.1  haad 	/* Store metadata without dependencies on mirror segments */
    518  1.1  haad 	if (!vg_commit(vg)) {
    519  1.1  haad 		log_error("ABORTING: Failed to write new data locations "
    520  1.1  haad 			  "to disk.");
    521  1.1  haad 		vg_revert(vg);
    522  1.1  haad 		resume_lv(cmd, lv_mirr);
    523  1.1  haad 		resume_lvs(cmd, lvs_changed);
    524  1.1  haad 		return 0;
    525  1.1  haad 	}
    526  1.1  haad 
    527  1.1  haad 	/* Release mirror LV.  (No pending I/O because it's been suspended.) */
    528  1.1  haad 	if (!resume_lv(cmd, lv_mirr)) {
    529  1.1  haad 		log_error("Unable to reactivate logical volume \"%s\"",
    530  1.1  haad 			  lv_mirr->name);
    531  1.1  haad 		r = 0;
    532  1.1  haad 	}
    533  1.1  haad 
    534  1.1  haad 	/* Unsuspend LVs */
    535  1.1  haad 	resume_lvs(cmd, lvs_changed);
    536  1.1  haad 
    537  1.1  haad 	/* Deactivate mirror LV */
    538  1.1  haad 	if (!deactivate_lv(cmd, lv_mirr)) {
    539  1.1  haad 		log_error("ABORTING: Unable to deactivate temporary logical "
    540  1.1  haad 			  "volume \"%s\"", lv_mirr->name);
    541  1.1  haad 		r = 0;
    542  1.1  haad 	}
    543  1.1  haad 
    544  1.1  haad 	log_verbose("Removing temporary pvmove LV");
    545  1.1  haad 	if (!lv_remove(lv_mirr)) {
    546  1.1  haad 		log_error("ABORTING: Removal of temporary pvmove LV failed");
    547  1.1  haad 		return 0;
    548  1.1  haad 	}
    549  1.1  haad 
    550  1.1  haad 	/* Store it on disks */
    551  1.1  haad 	log_verbose("Writing out final volume group after pvmove");
    552  1.1  haad 	if (!vg_write(vg) || !vg_commit(vg)) {
    553  1.1  haad 		log_error("ABORTING: Failed to write new data locations "
    554  1.1  haad 			  "to disk.");
    555  1.1  haad 		return 0;
    556  1.1  haad 	}
    557  1.1  haad 
    558  1.1  haad 	/* FIXME backup positioning */
    559  1.1  haad 	backup(vg);
    560  1.1  haad 
    561  1.1  haad 	return r;
    562  1.1  haad }
    563  1.1  haad 
    564  1.1  haad static struct volume_group *_get_move_vg(struct cmd_context *cmd,
    565  1.1  haad 					 const char *name)
    566  1.1  haad {
    567  1.1  haad 	struct physical_volume *pv;
    568  1.1  haad 
    569  1.1  haad 	/* Reread all metadata in case it got changed */
    570  1.1  haad 	if (!(pv = find_pv_by_name(cmd, name))) {
    571  1.1  haad 		log_error("ABORTING: Can't reread PV %s", name);
    572  1.1  haad 		/* What more could we do here? */
    573  1.1  haad 		return NULL;
    574  1.1  haad 	}
    575  1.1  haad 
    576  1.1  haad 	return _get_vg(cmd, pv_vg_name(pv));
    577  1.1  haad }
    578  1.1  haad 
    579  1.1  haad static struct poll_functions _pvmove_fns = {
    580  1.1  haad 	.get_copy_name_from_lv = get_pvmove_pvname_from_lv_mirr,
    581  1.1  haad 	.get_copy_vg = _get_move_vg,
    582  1.1  haad 	.get_copy_lv = find_pvmove_lv_from_pvname,
    583  1.1  haad 	.update_metadata = _update_metadata,
    584  1.1  haad 	.finish_copy = _finish_pvmove,
    585  1.1  haad };
    586  1.1  haad 
    587  1.1  haad int pvmove_poll(struct cmd_context *cmd, const char *pv_name,
    588  1.1  haad 		unsigned background)
    589  1.1  haad {
    590  1.1  haad 	return poll_daemon(cmd, pv_name, background, PVMOVE, &_pvmove_fns,
    591  1.1  haad 			   "Moved");
    592  1.1  haad }
    593  1.1  haad 
    594  1.1  haad int pvmove(struct cmd_context *cmd, int argc, char **argv)
    595  1.1  haad {
    596  1.1  haad 	char *pv_name = NULL;
    597  1.1  haad 	char *colon;
    598  1.1  haad 	int ret;
    599  1.1  haad 
    600  1.1  haad 	/* dm raid1 target must be present in every case */
    601  1.1  haad 	if (!_pvmove_target_present(cmd, 0)) {
    602  1.1  haad 		log_error("Required device-mapper target(s) not "
    603  1.1  haad 			  "detected in your kernel");
    604  1.1  haad 		return ECMD_FAILED;
    605  1.1  haad 	}
    606  1.1  haad 
    607  1.1  haad 	if (argc) {
    608  1.1  haad 		pv_name = argv[0];
    609  1.1  haad 
    610  1.1  haad 		/* Drop any PE lists from PV name */
    611  1.1  haad 		if ((colon = strchr(pv_name, ':'))) {
    612  1.1  haad 			if (!(pv_name = dm_pool_strndup(cmd->mem, pv_name,
    613  1.1  haad 						     (unsigned) (colon -
    614  1.1  haad 								 pv_name)))) {
    615  1.1  haad 				log_error("Failed to clone PV name");
    616  1.1  haad 				return ECMD_FAILED;
    617  1.1  haad 			}
    618  1.1  haad 		}
    619  1.1  haad 
    620  1.1  haad 		if (!arg_count(cmd, abort_ARG) &&
    621  1.1  haad 		    (ret = _set_up_pvmove(cmd, pv_name, argc, argv)) !=
    622  1.1  haad 		    ECMD_PROCESSED) {
    623  1.1  haad 			stack;
    624  1.1  haad 			return ret;
    625  1.1  haad 		}
    626  1.1  haad 	}
    627  1.1  haad 
    628  1.1  haad 	return pvmove_poll(cmd, pv_name,
    629  1.1  haad 			   arg_count(cmd, background_ARG) ? 1U : 0);
    630  1.1  haad }
    631