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