LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/lib/format1 - import-extents.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 0 149 0.0 %
Date: 2010-04-13 Functions: 0 12 0.0 %
Branches: 0 94 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
       3                 :            :  * Copyright (C) 2004-2007 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 "lib.h"
      17                 :            : #include "metadata.h"
      18                 :            : #include "disk-rep.h"
      19                 :            : #include "lv_alloc.h"
      20                 :            : #include "display.h"
      21                 :            : #include "segtype.h"
      22                 :            : 
      23                 :            : /*
      24                 :            :  * After much thought I have decided it is easier,
      25                 :            :  * and probably no less efficient, to convert the
      26                 :            :  * pe->le map to a full le->pe map, and then
      27                 :            :  * process this to get the segments form that
      28                 :            :  * we're after.  Any code which goes directly from
      29                 :            :  * the pe->le map to segments would be gladly
      30                 :            :  * accepted, if it is less complicated than this
      31                 :            :  * file.
      32                 :            :  */
      33                 :            : struct pe_specifier {
      34                 :            :         struct physical_volume *pv;
      35                 :            :         uint32_t pe;
      36                 :            : };
      37                 :            : 
      38                 :            : struct lv_map {
      39                 :            :         struct logical_volume *lv;
      40                 :            :         uint32_t stripes;
      41                 :            :         uint32_t stripe_size;
      42                 :            :         struct pe_specifier *map;
      43                 :            : };
      44                 :            : 
      45                 :          0 : static struct dm_hash_table *_create_lv_maps(struct dm_pool *mem,
      46                 :            :                                           struct volume_group *vg)
      47                 :            : {
      48                 :          0 :         struct dm_hash_table *maps = dm_hash_create(32);
      49                 :            :         struct lv_list *ll;
      50                 :            :         struct lv_map *lvm;
      51                 :            : 
      52         [ #  # ]:          0 :         if (!maps) {
      53                 :          0 :                 log_error("Unable to create hash table for holding "
      54                 :            :                           "extent maps.");
      55                 :          0 :                 return NULL;
      56                 :            :         }
      57                 :            : 
      58         [ #  # ]:          0 :         dm_list_iterate_items(ll, &vg->lvs) {
      59         [ #  # ]:          0 :                 if (ll->lv->status & SNAPSHOT)
      60                 :          0 :                         continue;
      61                 :            : 
      62         [ #  # ]:          0 :                 if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm))))
      63                 :          0 :                         goto_bad;
      64                 :            : 
      65                 :          0 :                 lvm->lv = ll->lv;
      66         [ #  # ]:          0 :                 if (!(lvm->map = dm_pool_zalloc(mem, sizeof(*lvm->map)
      67                 :          0 :                                              * ll->lv->le_count)))
      68                 :          0 :                         goto_bad;
      69                 :            : 
      70         [ #  # ]:          0 :                 if (!dm_hash_insert(maps, ll->lv->name, lvm))
      71                 :          0 :                         goto_bad;
      72                 :            :         }
      73                 :            : 
      74                 :          0 :         return maps;
      75                 :            : 
      76                 :            :       bad:
      77                 :          0 :         dm_hash_destroy(maps);
      78                 :          0 :         return NULL;
      79                 :            : }
      80                 :            : 
      81                 :          0 : static int _fill_lv_array(struct lv_map **lvs,
      82                 :            :                           struct dm_hash_table *maps, struct disk_list *dl)
      83                 :            : {
      84                 :            :         struct lvd_list *ll;
      85                 :            :         struct lv_map *lvm;
      86                 :            : 
      87                 :          0 :         memset(lvs, 0, sizeof(*lvs) * MAX_LV);
      88                 :            : 
      89         [ #  # ]:          0 :         dm_list_iterate_items(ll, &dl->lvds) {
      90         [ #  # ]:          0 :                 if (!(lvm = dm_hash_lookup(maps, strrchr((char *)ll->lvd.lv_name, '/')
      91                 :            :                                         + 1))) {
      92                 :          0 :                         log_error("Physical volume (%s) contains an "
      93                 :            :                                   "unknown logical volume (%s).",
      94                 :            :                                 dev_name(dl->dev), ll->lvd.lv_name);
      95                 :          0 :                         return 0;
      96                 :            :                 }
      97                 :            : 
      98                 :          0 :                 lvm->stripes = ll->lvd.lv_stripes;
      99                 :          0 :                 lvm->stripe_size = ll->lvd.lv_stripesize;
     100                 :            : 
     101                 :          0 :                 lvs[ll->lvd.lv_number] = lvm;
     102                 :            :         }
     103                 :            : 
     104                 :          0 :         return 1;
     105                 :            : }
     106                 :            : 
     107                 :          0 : static int _fill_maps(struct dm_hash_table *maps, struct volume_group *vg,
     108                 :            :                       struct dm_list *pvds)
     109                 :            : {
     110                 :            :         struct disk_list *dl;
     111                 :            :         struct physical_volume *pv;
     112                 :            :         struct lv_map *lvms[MAX_LV], *lvm;
     113                 :            :         struct pe_disk *e;
     114                 :            :         uint32_t i, lv_num, le;
     115                 :            : 
     116         [ #  # ]:          0 :         dm_list_iterate_items(dl, pvds) {
     117                 :          0 :                 pv = find_pv(vg, dl->dev);
     118                 :          0 :                 e = dl->extents;
     119                 :            : 
     120                 :            :                 /* build an array of lv's for this pv */
     121         [ #  # ]:          0 :                 if (!_fill_lv_array(lvms, maps, dl))
     122                 :          0 :                         return_0;
     123                 :            : 
     124         [ #  # ]:          0 :                 for (i = 0; i < dl->pvd.pe_total; i++) {
     125                 :          0 :                         lv_num = e[i].lv_num;
     126                 :            : 
     127         [ #  # ]:          0 :                         if (lv_num == UNMAPPED_EXTENT)
     128                 :          0 :                                 continue;
     129                 :            : 
     130                 :            :                         else {
     131                 :          0 :                                 lv_num--;
     132                 :          0 :                                 lvm = lvms[lv_num];
     133                 :            : 
     134         [ #  # ]:          0 :                                 if (!lvm) {
     135                 :          0 :                                         log_error("Invalid LV in extent map "
     136                 :            :                                                   "(PV %s, PE %" PRIu32
     137                 :            :                                                   ", LV %" PRIu32
     138                 :            :                                                   ", LE %" PRIu32 ")",
     139                 :            :                                                   dev_name(pv->dev), i,
     140                 :            :                                                   lv_num, e[i].le_num);
     141                 :          0 :                                         return 0;
     142                 :            :                                 }
     143                 :            : 
     144                 :          0 :                                 le = e[i].le_num;
     145                 :            : 
     146         [ #  # ]:          0 :                                 if (le >= lvm->lv->le_count) {
     147                 :          0 :                                         log_error("logical extent number "
     148                 :            :                                                   "out of bounds");
     149                 :          0 :                                         return 0;
     150                 :            :                                 }
     151                 :            : 
     152         [ #  # ]:          0 :                                 if (lvm->map[le].pv) {
     153                 :          0 :                                         log_error("logical extent (%u) "
     154                 :            :                                                   "already mapped.", le);
     155                 :          0 :                                         return 0;
     156                 :            :                                 }
     157                 :            : 
     158                 :          0 :                                 lvm->map[le].pv = pv;
     159                 :          0 :                                 lvm->map[le].pe = i;
     160                 :            :                         }
     161                 :            :                 }
     162                 :            :         }
     163                 :            : 
     164                 :          0 :         return 1;
     165                 :            : }
     166                 :            : 
     167                 :          0 : static int _check_single_map(struct lv_map *lvm)
     168                 :            : {
     169                 :            :         uint32_t i;
     170                 :            : 
     171         [ #  # ]:          0 :         for (i = 0; i < lvm->lv->le_count; i++) {
     172         [ #  # ]:          0 :                 if (!lvm->map[i].pv) {
     173                 :          0 :                         log_error("Logical volume (%s) contains an incomplete "
     174                 :            :                                   "mapping table.", lvm->lv->name);
     175                 :          0 :                         return 0;
     176                 :            :                 }
     177                 :            :         }
     178                 :            : 
     179                 :          0 :         return 1;
     180                 :            : }
     181                 :            : 
     182                 :          0 : static int _check_maps_are_complete(struct dm_hash_table *maps)
     183                 :            : {
     184                 :            :         struct dm_hash_node *n;
     185                 :            :         struct lv_map *lvm;
     186                 :            : 
     187         [ #  # ]:          0 :         for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
     188                 :          0 :                 lvm = (struct lv_map *) dm_hash_get_data(maps, n);
     189                 :            : 
     190         [ #  # ]:          0 :                 if (!_check_single_map(lvm))
     191                 :          0 :                         return_0;
     192                 :            :         }
     193                 :          0 :         return 1;
     194                 :            : }
     195                 :            : 
     196                 :          0 : static uint32_t _area_length(struct lv_map *lvm, uint32_t le)
     197                 :            : {
     198                 :          0 :         uint32_t len = 0;
     199                 :            : 
     200                 :            :         do
     201                 :          0 :                 len++;
     202                 :          0 :         while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
     203                 :          0 :                  (lvm->map[le].pv &&
     204 [ #  # ][ #  # ]:          0 :                   lvm->map[le + len].pe == lvm->map[le].pe + len));
                 [ #  # ]
     205                 :            : 
     206                 :          0 :         return len;
     207                 :            : }
     208                 :            : 
     209                 :          0 : static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
     210                 :            : {
     211                 :          0 :         uint32_t le = 0, len;
     212                 :            :         struct lv_segment *seg;
     213                 :            :         struct segment_type *segtype;
     214                 :            : 
     215         [ #  # ]:          0 :         if (!(segtype = get_segtype_from_string(cmd, "striped")))
     216                 :          0 :                 return_0;
     217                 :            : 
     218         [ #  # ]:          0 :         while (le < lvm->lv->le_count) {
     219                 :          0 :                 len = _area_length(lvm, le);
     220                 :            : 
     221         [ #  # ]:          0 :                 if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, le,
     222                 :            :                                              len, 0, 0, NULL, 1, len, 0, 0, 0, NULL))) {
     223                 :          0 :                         log_error("Failed to allocate linear segment.");
     224                 :          0 :                         return 0;
     225                 :            :                 }
     226                 :            : 
     227         [ #  # ]:          0 :                 if (!set_lv_segment_area_pv(seg, 0, lvm->map[le].pv,
     228                 :          0 :                                             lvm->map[le].pe))
     229                 :          0 :                         return_0;
     230                 :            : 
     231                 :          0 :                 dm_list_add(&lvm->lv->segments, &seg->list);
     232                 :            : 
     233                 :          0 :                 le += seg->len;
     234                 :            :         }
     235                 :            : 
     236                 :          0 :         return 1;
     237                 :            : }
     238                 :            : 
     239                 :          0 : static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
     240                 :            :                          uint32_t area_len, uint32_t base_le,
     241                 :            :                          uint32_t total_area_len)
     242                 :            : {
     243                 :            :         uint32_t st;
     244                 :            : 
     245                 :            :         /*
     246                 :            :          * Is the next physical extent in every stripe adjacent to the last?
     247                 :            :          */
     248         [ #  # ]:          0 :         for (st = 0; st < area_count; st++)
     249 [ #  # ][ #  # ]:          0 :                 if ((lvm->map[base_le + st * total_area_len + area_len].pv !=
                 [ #  # ]
     250                 :          0 :                      lvm->map[base_le + st * total_area_len].pv) ||
     251                 :          0 :                     (lvm->map[base_le + st * total_area_len].pv &&
     252                 :          0 :                      lvm->map[base_le + st * total_area_len + area_len].pe !=
     253                 :          0 :                      lvm->map[base_le + st * total_area_len].pe + area_len))
     254                 :          0 :                         return 0;
     255                 :            : 
     256                 :          0 :         return 1;
     257                 :            : }
     258                 :            : 
     259                 :          0 : static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
     260                 :            : {
     261                 :          0 :         uint32_t st, first_area_le = 0, total_area_len;
     262                 :            :         uint32_t area_len;
     263                 :            :         struct lv_segment *seg;
     264                 :            :         struct segment_type *segtype;
     265                 :            : 
     266                 :            :         /*
     267                 :            :          * Work out overall striped length
     268                 :            :          */
     269         [ #  # ]:          0 :         if (lvm->lv->le_count % lvm->stripes) {
     270                 :          0 :                 log_error("Number of stripes (%u) incompatible "
     271                 :            :                           "with logical extent count (%u) for %s",
     272                 :            :                           lvm->stripes, lvm->lv->le_count, lvm->lv->name);
     273                 :            :         }
     274                 :            : 
     275                 :          0 :         total_area_len = lvm->lv->le_count / lvm->stripes;
     276                 :            : 
     277         [ #  # ]:          0 :         if (!(segtype = get_segtype_from_string(cmd, "striped")))
     278                 :          0 :                 return_0;
     279                 :            : 
     280         [ #  # ]:          0 :         while (first_area_le < total_area_len) {
     281                 :          0 :                 area_len = 1;
     282                 :            : 
     283                 :            :                 /*
     284                 :            :                  * Find how many extents are contiguous in all stripes
     285                 :            :                  * and so can form part of this segment
     286                 :            :                  */
     287         [ #  # ]:          0 :                 while (_check_stripe(lvm, lvm->stripes,
     288                 :            :                                      area_len, first_area_le, total_area_len))
     289                 :          0 :                         area_len++;
     290                 :            : 
     291         [ #  # ]:          0 :                 if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv,
     292                 :            :                                              lvm->stripes * first_area_le,
     293                 :            :                                              lvm->stripes * area_len,
     294                 :            :                                              0, lvm->stripe_size, NULL,
     295                 :            :                                              lvm->stripes,
     296                 :            :                                              area_len, 0, 0, 0, NULL))) {
     297                 :          0 :                         log_error("Failed to allocate striped segment.");
     298                 :          0 :                         return 0;
     299                 :            :                 }
     300                 :            : 
     301                 :            :                 /*
     302                 :            :                  * Set up start positions of each stripe in this segment
     303                 :            :                  */
     304         [ #  # ]:          0 :                 for (st = 0; st < seg->area_count; st++)
     305         [ #  # ]:          0 :                         if (!set_lv_segment_area_pv(seg, st,
     306                 :          0 :                               lvm->map[first_area_le + st * total_area_len].pv,
     307                 :          0 :                               lvm->map[first_area_le + st * total_area_len].pe))
     308                 :          0 :                                 return_0;
     309                 :            : 
     310                 :          0 :                 dm_list_add(&lvm->lv->segments, &seg->list);
     311                 :            : 
     312                 :          0 :                 first_area_le += area_len;
     313                 :            :         }
     314                 :            : 
     315                 :          0 :         return 1;
     316                 :            : }
     317                 :            : 
     318                 :          0 : static int _build_segments(struct cmd_context *cmd, struct lv_map *lvm)
     319                 :            : {
     320         [ #  # ]:          0 :         return (lvm->stripes > 1 ? _read_stripes(cmd, lvm) :
     321                 :          0 :                 _read_linear(cmd, lvm));
     322                 :            : }
     323                 :            : 
     324                 :          0 : static int _build_all_segments(struct cmd_context *cmd, struct dm_hash_table *maps)
     325                 :            : {
     326                 :            :         struct dm_hash_node *n;
     327                 :            :         struct lv_map *lvm;
     328                 :            : 
     329         [ #  # ]:          0 :         for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
     330                 :          0 :                 lvm = (struct lv_map *) dm_hash_get_data(maps, n);
     331         [ #  # ]:          0 :                 if (!_build_segments(cmd, lvm))
     332                 :          0 :                         return_0;
     333                 :            :         }
     334                 :            : 
     335                 :          0 :         return 1;
     336                 :            : }
     337                 :            : 
     338                 :          0 : int import_extents(struct cmd_context *cmd, struct volume_group *vg,
     339                 :            :                    struct dm_list *pvds)
     340                 :            : {
     341                 :          0 :         int r = 0;
     342                 :          0 :         struct dm_pool *scratch = dm_pool_create("lvm1 import_extents", 10 * 1024);
     343                 :            :         struct dm_hash_table *maps;
     344                 :            : 
     345         [ #  # ]:          0 :         if (!scratch)
     346                 :          0 :                 return_0;
     347                 :            : 
     348         [ #  # ]:          0 :         if (!(maps = _create_lv_maps(scratch, vg))) {
     349                 :          0 :                 log_error("Couldn't allocate logical volume maps.");
     350                 :          0 :                 goto out;
     351                 :            :         }
     352                 :            : 
     353         [ #  # ]:          0 :         if (!_fill_maps(maps, vg, pvds)) {
     354                 :          0 :                 log_error("Couldn't fill logical volume maps.");
     355                 :          0 :                 goto out;
     356                 :            :         }
     357                 :            : 
     358 [ #  # ][ #  # ]:          0 :         if (!_check_maps_are_complete(maps) && !(vg->status & PARTIAL_VG))
     359                 :          0 :                 goto_out;
     360                 :            : 
     361         [ #  # ]:          0 :         if (!_build_all_segments(cmd, maps)) {
     362                 :          0 :                 log_error("Couldn't build extent segments.");
     363                 :          0 :                 goto out;
     364                 :            :         }
     365                 :          0 :         r = 1;
     366                 :            : 
     367                 :            :       out:
     368         [ #  # ]:          0 :         if (maps)
     369                 :          0 :                 dm_hash_destroy(maps);
     370                 :          0 :         dm_pool_destroy(scratch);
     371                 :          0 :         return r;
     372                 :            : }

Generated by: LCOV version 1.8