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

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
       3                 :            :  * Copyright (C) 2004-2009 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                 :            : 
      18                 :            : #define SIZE_BUF 128
      19                 :            : 
      20                 :            : struct lvresize_params {
      21                 :            :         const char *vg_name;
      22                 :            :         const char *lv_name;
      23                 :            : 
      24                 :            :         uint32_t stripes;
      25                 :            :         uint32_t stripe_size;
      26                 :            :         uint32_t mirrors;
      27                 :            : 
      28                 :            :         const struct segment_type *segtype;
      29                 :            : 
      30                 :            :         /* size */
      31                 :            :         uint32_t extents;
      32                 :            :         uint64_t size;
      33                 :            :         sign_t sign;
      34                 :            :         percent_t percent;
      35                 :            : 
      36                 :            :         enum {
      37                 :            :                 LV_ANY = 0,
      38                 :            :                 LV_REDUCE = 1,
      39                 :            :                 LV_EXTEND = 2
      40                 :            :         } resize;
      41                 :            : 
      42                 :            :         int resizefs;
      43                 :            :         int nofsck;
      44                 :            : 
      45                 :            :         int argc;
      46                 :            :         char **argv;
      47                 :            : };
      48                 :            : 
      49                 :          0 : static int _validate_stripesize(struct cmd_context *cmd,
      50                 :            :                                 const struct volume_group *vg,
      51                 :            :                                 struct lvresize_params *lp)
      52                 :            : {
      53         [ #  # ]:          0 :         if (arg_sign_value(cmd, stripesize_ARG, 0) == SIGN_MINUS) {
      54                 :          0 :                 log_error("Stripesize may not be negative.");
      55                 :          0 :                 return 0;
      56                 :            :         }
      57                 :            : 
      58         [ #  # ]:          0 :         if (arg_uint_value(cmd, stripesize_ARG, 0) > STRIPE_SIZE_LIMIT * 2) {
      59                 :          0 :                 log_error("Stripe size cannot be larger than %s",
      60                 :            :                           display_size(cmd, (uint64_t) STRIPE_SIZE_LIMIT));
      61                 :          0 :                 return 0;
      62                 :            :         }
      63                 :            : 
      64         [ #  # ]:          0 :         if (!(vg->fid->fmt->features & FMT_SEGMENTS))
      65                 :          0 :                 log_warn("Varied stripesize not supported. Ignoring.");
      66         [ #  # ]:          0 :         else if (arg_uint_value(cmd, stripesize_ARG, 0) > vg->extent_size * 2) {
      67                 :          0 :                 log_error("Reducing stripe size %s to maximum, "
      68                 :            :                           "physical extent size %s",
      69                 :            :                           display_size(cmd,
      70                 :            :                                        (uint64_t) arg_uint_value(cmd, stripesize_ARG, 0)),
      71                 :            :                           display_size(cmd, (uint64_t) vg->extent_size));
      72                 :          0 :                 lp->stripe_size = vg->extent_size;
      73                 :            :         } else
      74                 :          0 :                 lp->stripe_size = arg_uint_value(cmd, stripesize_ARG, 0);
      75                 :            : 
      76         [ #  # ]:          0 :         if (lp->stripe_size & (lp->stripe_size - 1)) {
      77                 :          0 :                 log_error("Stripe size must be power of 2");
      78                 :          0 :                 return 0;
      79                 :            :         }
      80                 :            : 
      81                 :          0 :         return 1;
      82                 :            : }
      83                 :            : 
      84                 :          0 : static int _request_confirmation(struct cmd_context *cmd,
      85                 :            :                                  const struct volume_group *vg,
      86                 :            :                                  const struct logical_volume *lv,
      87                 :            :                                  const struct lvresize_params *lp)
      88                 :            : {
      89                 :            :         struct lvinfo info;
      90                 :            : 
      91                 :          0 :         memset(&info, 0, sizeof(info));
      92                 :            : 
      93 [ #  # ][ #  # ]:          0 :         if (!lv_info(cmd, lv, &info, 1, 0) && driver_version(NULL, 0)) {
      94                 :          0 :                 log_error("lv_info failed: aborting");
      95                 :          0 :                 return 0;
      96                 :            :         }
      97                 :            : 
      98         [ #  # ]:          0 :         if (lp->resizefs) {
      99         [ #  # ]:          0 :                 if (!info.exists) {
     100                 :          0 :                         log_error("Logical volume %s must be activated "
     101                 :            :                                   "before resizing filesystem", lp->lv_name);
     102                 :          0 :                         return 0;
     103                 :            :                 }
     104                 :          0 :                 return 1;
     105                 :            :         }
     106                 :            : 
     107         [ #  # ]:          0 :         if (!info.exists)
     108                 :          0 :                 return 1;
     109                 :            : 
     110         [ #  # ]:          0 :         log_warn("WARNING: Reducing active%s logical volume to %s",
     111                 :            :                  info.open_count ? " and open" : "",
     112                 :            :                  display_size(cmd, (uint64_t) lp->extents * vg->extent_size));
     113                 :            : 
     114                 :          0 :         log_warn("THIS MAY DESTROY YOUR DATA (filesystem etc.)");
     115                 :            : 
     116         [ #  # ]:          0 :         if (!arg_count(cmd, force_ARG)) {
     117         [ #  # ]:          0 :                 if (yes_no_prompt("Do you really want to reduce %s? [y/n]: ",
     118                 :            :                                   lp->lv_name) == 'n') {
     119                 :          0 :                         log_error("Logical volume %s NOT reduced", lp->lv_name);
     120                 :          0 :                         return 0;
     121                 :            :                 }
     122         [ #  # ]:          0 :                 if (sigint_caught())
     123                 :          0 :                         return 0;
     124                 :            :         }
     125                 :            : 
     126                 :          0 :         return 1;
     127                 :            : }
     128                 :            : 
     129                 :            : enum fsadm_cmd_e { FSADM_CMD_CHECK, FSADM_CMD_RESIZE };
     130                 :            : #define FSADM_CMD "fsadm"
     131                 :            : #define FSADM_CMD_MAX_ARGS 6
     132                 :            : 
     133                 :            : /*
     134                 :            :  * FSADM_CMD --dry-run --verbose --force check lv_path
     135                 :            :  * FSADM_CMD --dry-run --verbose --force resize lv_path size
     136                 :            :  */
     137                 :          0 : static int _fsadm_cmd(struct cmd_context *cmd,
     138                 :            :                       const struct volume_group *vg,
     139                 :            :                       const struct lvresize_params *lp,
     140                 :            :                       enum fsadm_cmd_e fcmd)
     141                 :            : {
     142                 :            :         char lv_path[PATH_MAX];
     143                 :            :         char size_buf[SIZE_BUF];
     144                 :            :         const char *argv[FSADM_CMD_MAX_ARGS + 2];
     145                 :          0 :         unsigned i = 0;
     146                 :            : 
     147                 :          0 :         argv[i++] = FSADM_CMD;
     148                 :            : 
     149         [ #  # ]:          0 :         if (test_mode())
     150                 :          0 :                 argv[i++] = "--dry-run";
     151                 :            : 
     152         [ #  # ]:          0 :         if (verbose_level() >= _LOG_NOTICE)
     153                 :          0 :                 argv[i++] = "--verbose";
     154                 :            : 
     155         [ #  # ]:          0 :         if (arg_count(cmd, force_ARG))
     156                 :          0 :                 argv[i++] = "--force";
     157                 :            : 
     158         [ #  # ]:          0 :         argv[i++] = (fcmd == FSADM_CMD_RESIZE) ? "resize" : "check";
     159                 :            : 
     160         [ #  # ]:          0 :         if (dm_snprintf(lv_path, PATH_MAX, "%s%s/%s", cmd->dev_dir, lp->vg_name,
     161                 :            :                         lp->lv_name) < 0) {
     162                 :          0 :                 log_error("Couldn't create LV path for %s", lp->lv_name);
     163                 :          0 :                 return 0;
     164                 :            :         }
     165                 :            : 
     166                 :          0 :         argv[i++] = lv_path;
     167                 :            : 
     168         [ #  # ]:          0 :         if (fcmd == FSADM_CMD_RESIZE) {
     169         [ #  # ]:          0 :                 if (dm_snprintf(size_buf, SIZE_BUF, "%" PRIu64 "K",
     170                 :          0 :                                 (uint64_t) lp->extents * vg->extent_size / 2) < 0) {
     171                 :          0 :                         log_error("Couldn't generate new LV size string");
     172                 :          0 :                         return 0;
     173                 :            :                 }
     174                 :            : 
     175                 :          0 :                 argv[i++] = size_buf;
     176                 :            :         }
     177                 :            : 
     178                 :          0 :         argv[i] = NULL;
     179                 :            : 
     180                 :          0 :         return exec_cmd(cmd, argv);
     181                 :            : }
     182                 :            : 
     183                 :          0 : static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
     184                 :            :                             struct lvresize_params *lp)
     185                 :            : {
     186                 :            :         const char *cmd_name;
     187                 :            :         char *st;
     188                 :          0 :         unsigned dev_dir_found = 0;
     189                 :            : 
     190                 :          0 :         lp->sign = SIGN_NONE;
     191                 :          0 :         lp->resize = LV_ANY;
     192                 :            : 
     193                 :          0 :         cmd_name = command_name(cmd);
     194         [ #  # ]:          0 :         if (!strcmp(cmd_name, "lvreduce"))
     195                 :          0 :                 lp->resize = LV_REDUCE;
     196         [ #  # ]:          0 :         if (!strcmp(cmd_name, "lvextend"))
     197                 :          0 :                 lp->resize = LV_EXTEND;
     198                 :            : 
     199                 :            :         /*
     200                 :            :          * Allow omission of extents and size if the user has given us
     201                 :            :          * one or more PVs.  Most likely, the intent was "resize this
     202                 :            :          * LV the best you can with these PVs"
     203                 :            :          */
     204 [ #  # ][ #  # ]:          0 :         if ((arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG) == 0) &&
     205                 :            :             (argc >= 2)) {
     206                 :          0 :                 lp->extents = 100;
     207                 :          0 :                 lp->percent = PERCENT_PVS;
     208                 :          0 :                 lp->sign = SIGN_PLUS;
     209         [ #  # ]:          0 :         } else if ((arg_count(cmd, extents_ARG) +
     210                 :          0 :                     arg_count(cmd, size_ARG) != 1)) {
     211                 :          0 :                 log_error("Please specify either size or extents but not "
     212                 :            :                           "both.");
     213                 :          0 :                 return 0;
     214                 :            :         }
     215                 :            : 
     216         [ #  # ]:          0 :         if (arg_count(cmd, extents_ARG)) {
     217                 :          0 :                 lp->extents = arg_uint_value(cmd, extents_ARG, 0);
     218                 :          0 :                 lp->sign = arg_sign_value(cmd, extents_ARG, SIGN_NONE);
     219                 :          0 :                 lp->percent = arg_percent_value(cmd, extents_ARG, PERCENT_NONE);
     220                 :            :         }
     221                 :            : 
     222                 :            :         /* Size returned in kilobyte units; held in sectors */
     223         [ #  # ]:          0 :         if (arg_count(cmd, size_ARG)) {
     224                 :          0 :                 lp->size = arg_uint64_value(cmd, size_ARG, UINT64_C(0));
     225                 :          0 :                 lp->sign = arg_sign_value(cmd, size_ARG, SIGN_NONE);
     226                 :          0 :                 lp->percent = PERCENT_NONE;
     227                 :            :         }
     228                 :            : 
     229 [ #  # ][ #  # ]:          0 :         if (lp->resize == LV_EXTEND && lp->sign == SIGN_MINUS) {
     230                 :          0 :                 log_error("Negative argument not permitted - use lvreduce");
     231                 :          0 :                 return 0;
     232                 :            :         }
     233                 :            : 
     234 [ #  # ][ #  # ]:          0 :         if (lp->resize == LV_REDUCE && lp->sign == SIGN_PLUS) {
     235                 :          0 :                 log_error("Positive sign not permitted - use lvextend");
     236                 :          0 :                 return 0;
     237                 :            :         }
     238                 :            : 
     239                 :          0 :         lp->resizefs = arg_is_set(cmd, resizefs_ARG);
     240                 :          0 :         lp->nofsck = arg_is_set(cmd, nofsck_ARG);
     241                 :            : 
     242         [ #  # ]:          0 :         if (!argc) {
     243                 :          0 :                 log_error("Please provide the logical volume name");
     244                 :          0 :                 return 0;
     245                 :            :         }
     246                 :            : 
     247                 :          0 :         lp->lv_name = argv[0];
     248                 :          0 :         argv++;
     249                 :          0 :         argc--;
     250                 :            : 
     251   [ #  #  #  # ]:          0 :         if (!(lp->lv_name = skip_dev_dir(cmd, lp->lv_name, &dev_dir_found)) ||
     252                 :          0 :             !(lp->vg_name = extract_vgname(cmd, lp->lv_name))) {
     253                 :          0 :                 log_error("Please provide a volume group name");
     254                 :          0 :                 return 0;
     255                 :            :         }
     256                 :            : 
     257         [ #  # ]:          0 :         if (!validate_name(lp->vg_name)) {
     258                 :          0 :                 log_error("Volume group name %s has invalid characters",
     259                 :            :                           lp->vg_name);
     260                 :          0 :                 return 0;
     261                 :            :         }
     262                 :            : 
     263         [ #  # ]:          0 :         if ((st = strrchr(lp->lv_name, '/')))
     264                 :          0 :                 lp->lv_name = st + 1;
     265                 :            : 
     266                 :          0 :         lp->argc = argc;
     267                 :          0 :         lp->argv = argv;
     268                 :            : 
     269                 :          0 :         return 1;
     270                 :            : }
     271                 :            : 
     272                 :          0 : static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
     273                 :            :                      struct lvresize_params *lp)
     274                 :            : {
     275                 :            :         struct logical_volume *lv;
     276                 :            :         struct lvinfo info;
     277                 :          0 :         uint32_t stripesize_extents = 0;
     278                 :          0 :         uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size = 0;
     279                 :          0 :         uint32_t seg_mirrors = 0;
     280                 :          0 :         uint32_t extents_used = 0;
     281                 :            :         uint32_t size_rest;
     282                 :          0 :         uint32_t pv_extent_count = 0;
     283                 :            :         alloc_policy_t alloc;
     284                 :            :         struct logical_volume *lock_lv;
     285                 :            :         struct lv_list *lvl;
     286                 :          0 :         struct lv_segment *seg, *uninitialized_var(mirr_seg);
     287                 :            :         uint32_t seg_extents;
     288                 :            :         uint32_t sz, str;
     289                 :          0 :         struct dm_list *pvh = NULL;
     290                 :            : 
     291                 :            :         /* does LV exist? */
     292         [ #  # ]:          0 :         if (!(lvl = find_lv_in_vg(vg, lp->lv_name))) {
     293                 :          0 :                 log_error("Logical volume %s not found in volume group %s",
     294                 :            :                           lp->lv_name, lp->vg_name);
     295                 :          0 :                 return ECMD_FAILED;
     296                 :            :         }
     297                 :            : 
     298         [ #  # ]:          0 :         if (arg_count(cmd, stripes_ARG)) {
     299         [ #  # ]:          0 :                 if (vg->fid->fmt->features & FMT_SEGMENTS)
     300                 :          0 :                         lp->stripes = arg_uint_value(cmd, stripes_ARG, 1);
     301                 :            :                 else
     302                 :          0 :                         log_warn("Varied striping not supported. Ignoring.");
     303                 :            :         }
     304                 :            : 
     305         [ #  # ]:          0 :         if (arg_count(cmd, mirrors_ARG)) {
     306         [ #  # ]:          0 :                 if (vg->fid->fmt->features & FMT_SEGMENTS)
     307                 :          0 :                         lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 1) + 1;
     308                 :            :                 else
     309                 :          0 :                         log_warn("Mirrors not supported. Ignoring.");
     310         [ #  # ]:          0 :                 if (arg_sign_value(cmd, mirrors_ARG, 0) == SIGN_MINUS) {
     311                 :          0 :                         log_error("Mirrors argument may not be negative");
     312                 :          0 :                         return EINVALID_CMD_LINE;
     313                 :            :                 }
     314                 :            :         }
     315                 :            : 
     316   [ #  #  #  # ]:          0 :         if (arg_count(cmd, stripesize_ARG) &&
     317                 :          0 :             !_validate_stripesize(cmd, vg, lp))
     318                 :          0 :                 return EINVALID_CMD_LINE;
     319                 :            : 
     320                 :          0 :         lv = lvl->lv;
     321                 :            : 
     322         [ #  # ]:          0 :         if (!lv_is_visible(lv)) {
     323                 :          0 :                 log_error("Can't resize internal logical volume %s", lv->name);
     324                 :          0 :                 return ECMD_FAILED;
     325                 :            :         }
     326                 :            : 
     327         [ #  # ]:          0 :         if (lv->status & LOCKED) {
     328                 :          0 :                 log_error("Can't resize locked LV %s", lv->name);
     329                 :          0 :                 return ECMD_FAILED;
     330                 :            :         }
     331                 :            : 
     332         [ #  # ]:          0 :         if (lv->status & CONVERTING) {
     333                 :          0 :                 log_error("Can't resize %s while lvconvert in progress", lv->name);
     334                 :          0 :                 return ECMD_FAILED;
     335                 :            :         }
     336                 :            : 
     337                 :          0 :         alloc = arg_uint_value(cmd, alloc_ARG, lv->alloc);
     338                 :            : 
     339         [ #  # ]:          0 :         if (lp->size) {
     340         [ #  # ]:          0 :                 if (lp->size % vg->extent_size) {
     341         [ #  # ]:          0 :                         if (lp->sign == SIGN_MINUS)
     342                 :          0 :                                 lp->size -= lp->size % vg->extent_size;
     343                 :            :                         else
     344                 :          0 :                                 lp->size += vg->extent_size -
     345                 :          0 :                                     (lp->size % vg->extent_size);
     346                 :            : 
     347                 :          0 :                         log_print("Rounding up size to full physical extent %s",
     348                 :            :                                   display_size(cmd, (uint64_t) lp->size));
     349                 :            :                 }
     350                 :            : 
     351                 :          0 :                 lp->extents = lp->size / vg->extent_size;
     352                 :            :         }
     353                 :            : 
     354 [ #  # ][ #  # ]:          0 :         if (!(pvh = lp->argc ? create_pv_list(cmd->mem, vg, lp->argc,
     355                 :            :                                                      lp->argv, 1) : &vg->pvs)) {
     356                 :          0 :                 stack;
     357                 :          0 :                 return ECMD_FAILED;
     358                 :            :         }
     359                 :            : 
     360 [ #  #  #  #  # :          0 :         switch(lp->percent) {
                      # ]
     361                 :            :                 case PERCENT_VG:
     362                 :          0 :                         lp->extents = lp->extents * vg->extent_count / 100;
     363                 :          0 :                         break;
     364                 :            :                 case PERCENT_FREE:
     365                 :          0 :                         lp->extents = lp->extents * vg->free_count / 100;
     366                 :          0 :                         break;
     367                 :            :                 case PERCENT_LV:
     368                 :          0 :                         lp->extents = lp->extents * lv->le_count / 100;
     369                 :          0 :                         break;
     370                 :            :                 case PERCENT_PVS:
     371         [ #  # ]:          0 :                         if (lp->argc) {
     372                 :          0 :                                 pv_extent_count = pv_list_extents_free(pvh);
     373                 :          0 :                                 lp->extents = lp->extents * pv_extent_count / 100;
     374                 :            :                         } else
     375                 :          0 :                                 lp->extents = lp->extents * vg->extent_count / 100;
     376                 :          0 :                         break;
     377                 :            :                 case PERCENT_ORIGIN:
     378         [ #  # ]:          0 :                         if (!lv_is_cow(lv)) {
     379                 :          0 :                                 log_error("Specified LV does not have an origin LV.");
     380                 :          0 :                                 return EINVALID_CMD_LINE;
     381                 :            :                         }
     382                 :          0 :                         lp->extents = lp->extents * origin_from_cow(lv)->le_count / 100;
     383                 :            :                         break;
     384                 :            :                 case PERCENT_NONE:
     385                 :            :                         break;
     386                 :            :         }
     387                 :            : 
     388         [ #  # ]:          0 :         if (lp->sign == SIGN_PLUS)
     389                 :          0 :                 lp->extents += lv->le_count;
     390                 :            : 
     391         [ #  # ]:          0 :         if (lp->sign == SIGN_MINUS) {
     392         [ #  # ]:          0 :                 if (lp->extents >= lv->le_count) {
     393                 :          0 :                         log_error("Unable to reduce %s below 1 extent",
     394                 :            :                                   lp->lv_name);
     395                 :          0 :                         return EINVALID_CMD_LINE;
     396                 :            :                 }
     397                 :            : 
     398                 :          0 :                 lp->extents = lv->le_count - lp->extents;
     399                 :            :         }
     400                 :            : 
     401         [ #  # ]:          0 :         if (!lp->extents) {
     402                 :          0 :                 log_error("New size of 0 not permitted");
     403                 :          0 :                 return EINVALID_CMD_LINE;
     404                 :            :         }
     405                 :            : 
     406         [ #  # ]:          0 :         if (lp->extents == lv->le_count) {
     407         [ #  # ]:          0 :                 if (!lp->resizefs) {
     408                 :          0 :                         log_error("New size (%d extents) matches existing size "
     409                 :            :                                   "(%d extents)", lp->extents, lv->le_count);
     410                 :          0 :                         return EINVALID_CMD_LINE;
     411                 :            :                 }
     412                 :          0 :                 lp->resize = LV_EXTEND; /* lets pretend zero size extension */
     413                 :            :         }
     414                 :            : 
     415                 :          0 :         seg_size = lp->extents - lv->le_count;
     416                 :            : 
     417                 :            :         /* Use segment type of last segment */
     418         [ #  # ]:          0 :         dm_list_iterate_items(seg, &lv->segments) {
     419                 :          0 :                 lp->segtype = seg->segtype;
     420                 :            :         }
     421                 :            : 
     422                 :            :         /* FIXME Support LVs with mixed segment types */
     423         [ #  # ]:          0 :         if (lp->segtype != arg_ptr_value(cmd, type_ARG, lp->segtype)) {
     424                 :          0 :                 log_error("VolumeType does not match (%s)", lp->segtype->name);
     425                 :          0 :                 return EINVALID_CMD_LINE;
     426                 :            :         }
     427                 :            : 
     428                 :            :         /* If extending, find mirrors of last segment */
     429         [ #  # ]:          0 :         if ((lp->extents > lv->le_count)) {
     430         [ #  # ]:          0 :                 dm_list_iterate_back_items(mirr_seg, &lv->segments) {
     431         [ #  # ]:          0 :                         if (seg_is_mirrored(mirr_seg))
     432                 :          0 :                                 seg_mirrors = lv_mirror_count(mirr_seg->lv);
     433                 :            :                         else
     434                 :          0 :                                 seg_mirrors = 0;
     435                 :          0 :                         break;
     436                 :            :                 }
     437 [ #  # ][ #  # ]:          0 :                 if (!arg_count(cmd, mirrors_ARG) && seg_mirrors) {
     438                 :          0 :                         log_print("Extending %" PRIu32 " mirror images.",
     439                 :            :                                   seg_mirrors);
     440                 :          0 :                         lp->mirrors = seg_mirrors;
     441                 :            :                 }
     442 [ #  # ][ #  # ]:          0 :                 if ((arg_count(cmd, mirrors_ARG) || seg_mirrors) &&
                 [ #  # ]
     443                 :          0 :                     (lp->mirrors != seg_mirrors)) {
     444                 :          0 :                         log_error("Cannot vary number of mirrors in LV yet.");
     445                 :          0 :                         return EINVALID_CMD_LINE;
     446                 :            :                 }
     447                 :            :         }
     448                 :            : 
     449                 :            :         /* If extending, find stripes, stripesize & size of last segment */
     450 [ #  # ][ #  # ]:          0 :         if ((lp->extents > lv->le_count) &&
         [ #  # ][ #  # ]
     451                 :            :             !(lp->stripes == 1 || (lp->stripes > 1 && lp->stripe_size))) {
     452                 :            :                 /* FIXME Don't assume mirror seg will always be AREA_LV */
     453 [ #  # ][ #  # ]:          0 :                 dm_list_iterate_items(seg, seg_mirrors ? &seg_lv(mirr_seg, 0)->segments : &lv->segments) {
                 [ #  # ]
     454         [ #  # ]:          0 :                         if (!seg_is_striped(seg))
     455                 :          0 :                                 continue;
     456                 :            : 
     457                 :          0 :                         sz = seg->stripe_size;
     458                 :          0 :                         str = seg->area_count;
     459                 :            : 
     460 [ #  # ][ #  # ]:          0 :                         if ((seg_stripesize && seg_stripesize != sz &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     461                 :          0 :                              sz && !lp->stripe_size) ||
     462                 :          0 :                             (seg_stripes && seg_stripes != str && !lp->stripes)) {
     463                 :          0 :                                 log_error("Please specify number of "
     464                 :            :                                           "stripes (-i) and stripesize (-I)");
     465                 :          0 :                                 return EINVALID_CMD_LINE;
     466                 :            :                         }
     467                 :            : 
     468                 :          0 :                         seg_stripesize = sz;
     469                 :          0 :                         seg_stripes = str;
     470                 :            :                 }
     471                 :            : 
     472         [ #  # ]:          0 :                 if (!lp->stripes)
     473                 :          0 :                         lp->stripes = seg_stripes;
     474                 :            : 
     475 [ #  # ][ #  # ]:          0 :                 if (!lp->stripe_size && lp->stripes > 1) {
     476         [ #  # ]:          0 :                         if (seg_stripesize) {
     477                 :          0 :                                 log_print("Using stripesize of last segment %s",
     478                 :            :                                           display_size(cmd, (uint64_t) seg_stripesize));
     479                 :          0 :                                 lp->stripe_size = seg_stripesize;
     480                 :            :                         } else {
     481                 :          0 :                                 lp->stripe_size =
     482                 :          0 :                                         find_config_tree_int(cmd,
     483                 :            :                                                         "metadata/stripesize",
     484                 :            :                                                         DEFAULT_STRIPESIZE) * 2;
     485                 :          0 :                                 log_print("Using default stripesize %s",
     486                 :            :                                           display_size(cmd, (uint64_t) lp->stripe_size));
     487                 :            :                         }
     488                 :            :                 }
     489                 :            :         }
     490                 :            : 
     491                 :            :         /* If reducing, find stripes, stripesize & size of last segment */
     492         [ #  # ]:          0 :         if (lp->extents < lv->le_count) {
     493                 :          0 :                 extents_used = 0;
     494                 :            : 
     495 [ #  # ][ #  # ]:          0 :                 if (lp->stripes || lp->stripe_size || lp->mirrors)
                 [ #  # ]
     496                 :          0 :                         log_error("Ignoring stripes, stripesize and mirrors "
     497                 :            :                                   "arguments when reducing");
     498                 :            : 
     499         [ #  # ]:          0 :                 dm_list_iterate_items(seg, &lv->segments) {
     500                 :          0 :                         seg_extents = seg->len;
     501                 :            : 
     502         [ #  # ]:          0 :                         if (seg_is_striped(seg)) {
     503                 :          0 :                                 seg_stripesize = seg->stripe_size;
     504                 :          0 :                                 seg_stripes = seg->area_count;
     505                 :            :                         }
     506                 :            : 
     507         [ #  # ]:          0 :                         if (seg_is_mirrored(seg))
     508                 :          0 :                                 seg_mirrors = lv_mirror_count(seg->lv);
     509                 :            :                         else
     510                 :          0 :                                 seg_mirrors = 0;
     511                 :            : 
     512         [ #  # ]:          0 :                         if (lp->extents <= extents_used + seg_extents)
     513                 :          0 :                                 break;
     514                 :            : 
     515                 :          0 :                         extents_used += seg_extents;
     516                 :            :                 }
     517                 :            : 
     518                 :          0 :                 seg_size = lp->extents - extents_used;
     519                 :          0 :                 lp->stripe_size = seg_stripesize;
     520                 :          0 :                 lp->stripes = seg_stripes;
     521                 :          0 :                 lp->mirrors = seg_mirrors;
     522                 :            :         }
     523                 :            : 
     524 [ #  # ][ #  # ]:          0 :         if (lp->stripes > 1 && !lp->stripe_size) {
     525                 :          0 :                 log_error("Stripesize for striped segment should not be 0!");
     526                 :          0 :                 return EINVALID_CMD_LINE;
     527                 :            :         }
     528                 :            : 
     529         [ #  # ]:          0 :         if ((lp->stripes > 1)) {
     530         [ #  # ]:          0 :                 if (!(stripesize_extents = lp->stripe_size / vg->extent_size))
     531                 :          0 :                         stripesize_extents = 1;
     532                 :            : 
     533         [ #  # ]:          0 :                 if ((size_rest = seg_size % (lp->stripes * stripesize_extents))) {
     534                 :          0 :                         log_print("Rounding size (%d extents) down to stripe "
     535                 :            :                                   "boundary size for segment (%d extents)",
     536                 :            :                                   lp->extents, lp->extents - size_rest);
     537                 :          0 :                         lp->extents = lp->extents - size_rest;
     538                 :            :                 }
     539                 :            : 
     540         [ #  # ]:          0 :                 if (lp->stripe_size < STRIPE_SIZE_MIN) {
     541                 :          0 :                         log_error("Invalid stripe size %s",
     542                 :            :                                   display_size(cmd, (uint64_t) lp->stripe_size));
     543                 :          0 :                         return EINVALID_CMD_LINE;
     544                 :            :                 }
     545                 :            :         }
     546                 :            : 
     547         [ #  # ]:          0 :         if (lp->extents < lv->le_count) {
     548         [ #  # ]:          0 :                 if (lp->resize == LV_EXTEND) {
     549                 :          0 :                         log_error("New size given (%d extents) not larger "
     550                 :            :                                   "than existing size (%d extents)",
     551                 :            :                                   lp->extents, lv->le_count);
     552                 :          0 :                         return EINVALID_CMD_LINE;
     553                 :            :                 }
     554                 :          0 :                 lp->resize = LV_REDUCE;
     555         [ #  # ]:          0 :         } else if (lp->extents > lv->le_count) {
     556         [ #  # ]:          0 :                 if (lp->resize == LV_REDUCE) {
     557                 :          0 :                         log_error("New size given (%d extents) not less than "
     558                 :            :                                   "existing size (%d extents)", lp->extents,
     559                 :            :                                   lv->le_count);
     560                 :          0 :                         return EINVALID_CMD_LINE;
     561                 :            :                 }
     562                 :          0 :                 lp->resize = LV_EXTEND;
     563                 :            :         }
     564                 :            : 
     565         [ #  # ]:          0 :         if (lv_is_origin(lv)) {
     566         [ #  # ]:          0 :                 if (lp->resize == LV_REDUCE) {
     567                 :          0 :                         log_error("Snapshot origin volumes cannot be reduced "
     568                 :            :                                   "in size yet.");
     569                 :          0 :                         return ECMD_FAILED;
     570                 :            :                 }
     571                 :            : 
     572                 :          0 :                 memset(&info, 0, sizeof(info));
     573                 :            : 
     574 [ #  # ][ #  # ]:          0 :                 if (lv_info(cmd, lv, &info, 0, 0) && info.exists) {
     575                 :          0 :                         log_error("Snapshot origin volumes can be resized "
     576                 :            :                                   "only while inactive: try lvchange -an");
     577                 :          0 :                         return ECMD_FAILED;
     578                 :            :                 }
     579                 :            :         }
     580                 :            : 
     581 [ #  # ][ #  # ]:          0 :         if ((lp->resize == LV_REDUCE) && lp->argc)
     582                 :          0 :                 log_warn("Ignoring PVs on command line when reducing");
     583                 :            : 
     584                 :            :         /* Request confirmation before operations that are often mistakes. */
     585         [ #  # ]:          0 :         if ((lp->resizefs || (lp->resize == LV_REDUCE)) &&
           [ #  #  #  # ]
     586                 :          0 :             !_request_confirmation(cmd, vg, lv, lp)) {
     587                 :          0 :                 stack;
     588                 :          0 :                 return ECMD_FAILED;
     589                 :            :         }
     590                 :            : 
     591         [ #  # ]:          0 :         if (lp->resizefs) {
     592   [ #  #  #  # ]:          0 :                 if (!lp->nofsck &&
     593                 :          0 :                     !_fsadm_cmd(cmd, vg, lp, FSADM_CMD_CHECK)) {
     594                 :          0 :                         stack;
     595                 :          0 :                         return ECMD_FAILED;
     596                 :            :                 }
     597                 :            : 
     598   [ #  #  #  # ]:          0 :                 if ((lp->resize == LV_REDUCE) &&
     599                 :          0 :                     !_fsadm_cmd(cmd, vg, lp, FSADM_CMD_RESIZE)) {
     600                 :          0 :                         stack;
     601                 :          0 :                         return ECMD_FAILED;
     602                 :            :                 }
     603                 :            :         }
     604                 :            : 
     605         [ #  # ]:          0 :         if (!archive(vg)) {
     606                 :          0 :                 stack;
     607                 :          0 :                 return ECMD_FAILED;
     608                 :            :         }
     609                 :            : 
     610         [ #  # ]:          0 :         log_print("%sing logical volume %s to %s",
     611                 :            :                   (lp->resize == LV_REDUCE) ? "Reduc" : "Extend",
     612                 :            :                   lp->lv_name,
     613                 :            :                   display_size(cmd, (uint64_t) lp->extents * vg->extent_size));
     614                 :            : 
     615         [ #  # ]:          0 :         if (lp->resize == LV_REDUCE) {
     616         [ #  # ]:          0 :                 if (!lv_reduce(lv, lv->le_count - lp->extents)) {
     617                 :          0 :                         stack;
     618                 :          0 :                         return ECMD_FAILED;
     619                 :            :                 }
     620   [ #  #  #  # ]:          0 :         } else if ((lp->extents > lv->le_count) && /* Ensure we extend */
     621                 :          0 :                    !lv_extend(lv, lp->segtype, lp->stripes,
     622                 :            :                               lp->stripe_size, lp->mirrors,
     623                 :            :                               lp->extents - lv->le_count,
     624                 :            :                               NULL, 0u, 0u, pvh, alloc)) {
     625                 :          0 :                 stack;
     626                 :          0 :                 return ECMD_FAILED;
     627                 :            :         }
     628                 :            : 
     629                 :            :         /* store vg on disk(s) */
     630         [ #  # ]:          0 :         if (!vg_write(vg)) {
     631                 :          0 :                 stack;
     632                 :          0 :                 return ECMD_FAILED;
     633                 :            :         }
     634                 :            : 
     635                 :            :         /* If snapshot, must suspend all associated devices */
     636         [ #  # ]:          0 :         if (lv_is_cow(lv))
     637                 :          0 :                 lock_lv = origin_from_cow(lv);
     638                 :            :         else
     639                 :          0 :                 lock_lv = lv;
     640                 :            : 
     641 [ #  # ][ #  # ]:          0 :         if (!suspend_lv(cmd, lock_lv)) {
                 [ #  # ]
     642                 :          0 :                 log_error("Failed to suspend %s", lp->lv_name);
     643                 :          0 :                 vg_revert(vg);
     644                 :          0 :                 backup(vg);
     645                 :          0 :                 return ECMD_FAILED;
     646                 :            :         }
     647                 :            : 
     648         [ #  # ]:          0 :         if (!vg_commit(vg)) {
     649                 :          0 :                 stack;
     650   [ #  #  #  # ]:          0 :                 if (!resume_lv(cmd, lock_lv))
                 [ #  # ]
     651                 :          0 :                         stack;
     652                 :          0 :                 backup(vg);
     653                 :          0 :                 return ECMD_FAILED;
     654                 :            :         }
     655                 :            : 
     656 [ #  # ][ #  # ]:          0 :         if (!resume_lv(cmd, lock_lv)) {
                 [ #  # ]
     657                 :          0 :                 log_error("Problem reactivating %s", lp->lv_name);
     658                 :          0 :                 backup(vg);
     659                 :          0 :                 return ECMD_FAILED;
     660                 :            :         }
     661                 :            : 
     662                 :          0 :         backup(vg);
     663                 :            : 
     664                 :          0 :         log_print("Logical volume %s successfully resized", lp->lv_name);
     665                 :            : 
     666 [ #  #  #  #  # :          0 :         if (lp->resizefs && (lp->resize == LV_EXTEND) &&
                      # ]
     667                 :          0 :             !_fsadm_cmd(cmd, vg, lp, FSADM_CMD_RESIZE)) {
     668                 :          0 :                 stack;
     669                 :          0 :                 return ECMD_FAILED;
     670                 :            :         }
     671                 :            : 
     672                 :          0 :         return ECMD_PROCESSED;
     673                 :            : }
     674                 :            : 
     675                 :          0 : int lvresize(struct cmd_context *cmd, int argc, char **argv)
     676                 :            : {
     677                 :            :         struct lvresize_params lp;
     678                 :            :         struct volume_group *vg;
     679                 :            :         int r;
     680                 :            : 
     681                 :          0 :         memset(&lp, 0, sizeof(lp));
     682                 :            : 
     683         [ #  # ]:          0 :         if (!_lvresize_params(cmd, argc, argv, &lp))
     684                 :          0 :                 return EINVALID_CMD_LINE;
     685                 :            : 
     686                 :          0 :         log_verbose("Finding volume group %s", lp.vg_name);
     687                 :          0 :         vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0);
     688         [ #  # ]:          0 :         if (vg_read_error(vg)) {
     689                 :          0 :                 vg_release(vg);
     690                 :          0 :                 stack;
     691                 :          0 :                 return ECMD_FAILED;
     692                 :            :         }
     693                 :            : 
     694         [ #  # ]:          0 :         if (!(r = _lvresize(cmd, vg, &lp)))
     695                 :          0 :                 stack;
     696                 :            : 
     697                 :          0 :         unlock_and_release_vg(cmd, vg, lp.vg_name);
     698                 :            : 
     699                 :          0 :         return r;
     700                 :            : }

Generated by: LCOV version 1.8