LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/tools - pvmove.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 0 312 0.0 %
Date: 2010-04-13 Functions: 0 15 0.0 %
Branches: 0 264 0.0 %

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

Generated by: LCOV version 1.8