LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/lib/format1 - disk-rep.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 0 361 0.0 %
Date: 2010-04-13 Functions: 0 28 0.0 %
Branches: 0 175 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 "disk-rep.h"
      18                 :            : #include "xlate.h"
      19                 :            : #include "filter.h"
      20                 :            : #include "lvmcache.h"
      21                 :            : 
      22                 :            : #include <fcntl.h>
      23                 :            : 
      24                 :            : #define xx16(v) disk->v = xlate16(disk->v)
      25                 :            : #define xx32(v) disk->v = xlate32(disk->v)
      26                 :            : #define xx64(v) disk->v = xlate64(disk->v)
      27                 :            : 
      28                 :            : /*
      29                 :            :  * Functions to perform the endian conversion
      30                 :            :  * between disk and core.  The same code works
      31                 :            :  * both ways of course.
      32                 :            :  */
      33                 :          0 : static void _xlate_pvd(struct pv_disk *disk)
      34                 :            : {
      35                 :          0 :         xx16(version);
      36                 :            : 
      37                 :          0 :         xx32(pv_on_disk.base);
      38                 :          0 :         xx32(pv_on_disk.size);
      39                 :          0 :         xx32(vg_on_disk.base);
      40                 :          0 :         xx32(vg_on_disk.size);
      41                 :          0 :         xx32(pv_uuidlist_on_disk.base);
      42                 :          0 :         xx32(pv_uuidlist_on_disk.size);
      43                 :          0 :         xx32(lv_on_disk.base);
      44                 :          0 :         xx32(lv_on_disk.size);
      45                 :          0 :         xx32(pe_on_disk.base);
      46                 :          0 :         xx32(pe_on_disk.size);
      47                 :            : 
      48                 :          0 :         xx32(pv_major);
      49                 :          0 :         xx32(pv_number);
      50                 :          0 :         xx32(pv_status);
      51                 :          0 :         xx32(pv_allocatable);
      52                 :          0 :         xx32(pv_size);
      53                 :          0 :         xx32(lv_cur);
      54                 :          0 :         xx32(pe_size);
      55                 :          0 :         xx32(pe_total);
      56                 :          0 :         xx32(pe_allocated);
      57                 :          0 :         xx32(pe_start);
      58                 :          0 : }
      59                 :            : 
      60                 :          0 : static void _xlate_lvd(struct lv_disk *disk)
      61                 :            : {
      62                 :          0 :         xx32(lv_access);
      63                 :          0 :         xx32(lv_status);
      64                 :          0 :         xx32(lv_open);
      65                 :          0 :         xx32(lv_dev);
      66                 :          0 :         xx32(lv_number);
      67                 :          0 :         xx32(lv_mirror_copies);
      68                 :          0 :         xx32(lv_recovery);
      69                 :          0 :         xx32(lv_schedule);
      70                 :          0 :         xx32(lv_size);
      71                 :          0 :         xx32(lv_snapshot_minor);
      72                 :          0 :         xx16(lv_chunk_size);
      73                 :          0 :         xx16(dummy);
      74                 :          0 :         xx32(lv_allocated_le);
      75                 :          0 :         xx32(lv_stripes);
      76                 :          0 :         xx32(lv_stripesize);
      77                 :          0 :         xx32(lv_badblock);
      78                 :          0 :         xx32(lv_allocation);
      79                 :          0 :         xx32(lv_io_timeout);
      80                 :          0 :         xx32(lv_read_ahead);
      81                 :          0 : }
      82                 :            : 
      83                 :          0 : static void _xlate_vgd(struct vg_disk *disk)
      84                 :            : {
      85                 :          0 :         xx32(vg_number);
      86                 :          0 :         xx32(vg_access);
      87                 :          0 :         xx32(vg_status);
      88                 :          0 :         xx32(lv_max);
      89                 :          0 :         xx32(lv_cur);
      90                 :          0 :         xx32(lv_open);
      91                 :          0 :         xx32(pv_max);
      92                 :          0 :         xx32(pv_cur);
      93                 :          0 :         xx32(pv_act);
      94                 :          0 :         xx32(dummy);
      95                 :          0 :         xx32(vgda);
      96                 :          0 :         xx32(pe_size);
      97                 :          0 :         xx32(pe_total);
      98                 :          0 :         xx32(pe_allocated);
      99                 :          0 :         xx32(pvg_total);
     100                 :          0 : }
     101                 :            : 
     102                 :          0 : static void _xlate_extents(struct pe_disk *extents, uint32_t count)
     103                 :            : {
     104                 :            :         unsigned i;
     105                 :            : 
     106         [ #  # ]:          0 :         for (i = 0; i < count; i++) {
     107                 :          0 :                 extents[i].lv_num = xlate16(extents[i].lv_num);
     108                 :          0 :                 extents[i].le_num = xlate16(extents[i].le_num);
     109                 :            :         }
     110                 :          0 : }
     111                 :            : 
     112                 :            : /*
     113                 :            :  * Handle both minor metadata formats.
     114                 :            :  */
     115                 :          0 : static int _munge_formats(struct pv_disk *pvd)
     116                 :            : {
     117                 :            :         uint32_t pe_start;
     118                 :            :         unsigned b, e;
     119                 :            : 
     120      [ #  #  # ]:          0 :         switch (pvd->version) {
     121                 :            :         case 1:
     122                 :          0 :                 pvd->pe_start = ((pvd->pe_on_disk.base +
     123                 :            :                                   pvd->pe_on_disk.size) >> SECTOR_SHIFT);
     124                 :          0 :                 break;
     125                 :            : 
     126                 :            :         case 2:
     127                 :          0 :                 pvd->version = 1;
     128                 :          0 :                 pe_start = pvd->pe_start << SECTOR_SHIFT;
     129                 :          0 :                 pvd->pe_on_disk.size = pe_start - pvd->pe_on_disk.base;
     130                 :          0 :                 break;
     131                 :            : 
     132                 :            :         default:
     133                 :          0 :                 return 0;
     134                 :            :         }
     135                 :            : 
     136                 :            :         /* UUID too long? */
     137         [ #  # ]:          0 :         if (pvd->pv_uuid[ID_LEN]) {
     138                 :            :                 /* Retain ID_LEN chars from end */
     139         [ #  # ]:          0 :                 for (e = ID_LEN; e < sizeof(pvd->pv_uuid); e++) {
     140         [ #  # ]:          0 :                         if (!pvd->pv_uuid[e]) {
     141                 :          0 :                                 e--;
     142                 :          0 :                                 break;
     143                 :            :                         }
     144                 :            :                 }
     145         [ #  # ]:          0 :                 for (b = 0; b < ID_LEN; b++) {
     146                 :          0 :                         pvd->pv_uuid[b] = pvd->pv_uuid[++e - ID_LEN];
     147                 :            :                         /* FIXME Remove all invalid chars */
     148         [ #  # ]:          0 :                         if (pvd->pv_uuid[b] == '/')
     149                 :          0 :                                 pvd->pv_uuid[b] = '#';
     150                 :            :                 }
     151                 :          0 :                 memset(&pvd->pv_uuid[ID_LEN], 0, sizeof(pvd->pv_uuid) - ID_LEN);
     152                 :            :         }
     153                 :            : 
     154                 :            :         /* If UUID is missing, create one */
     155         [ #  # ]:          0 :         if (pvd->pv_uuid[0] == '\0') {
     156                 :          0 :                 uuid_from_num((char *)pvd->pv_uuid, pvd->pv_number);
     157                 :          0 :                 pvd->pv_uuid[ID_LEN] = '\0';
     158                 :            :         }
     159                 :            : 
     160                 :          0 :         return 1;
     161                 :            : }
     162                 :            : 
     163                 :            : /*
     164                 :            :  * If exported, remove "PV_EXP" from end of VG name
     165                 :            :  */
     166                 :          0 : static void _munge_exported_vg(struct pv_disk *pvd)
     167                 :            : {
     168                 :            :         int l;
     169                 :            :         size_t s;
     170                 :            : 
     171                 :            :         /* Return if PV not in a VG */
     172         [ #  # ]:          0 :         if ((!*pvd->vg_name))
     173                 :          0 :                 return;
     174                 :            :         /* FIXME also check vgd->status & VG_EXPORTED? */
     175                 :            : 
     176                 :          0 :         l = strlen((char *)pvd->vg_name);
     177                 :          0 :         s = sizeof(EXPORTED_TAG);
     178         [ #  # ]:          0 :         if (!strncmp((char *)pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
     179                 :          0 :                 pvd->vg_name[l - s + 1] = '\0';
     180                 :          0 :                 pvd->pv_status |= VG_EXPORTED;
     181                 :            :         }
     182                 :            : }
     183                 :            : 
     184                 :          0 : int munge_pvd(struct device *dev, struct pv_disk *pvd)
     185                 :            : {
     186                 :          0 :         _xlate_pvd(pvd);
     187                 :            : 
     188   [ #  #  #  # ]:          0 :         if (pvd->id[0] != 'H' || pvd->id[1] != 'M') {
     189                 :          0 :                 log_very_verbose("%s does not have a valid LVM1 PV identifier",
     190                 :            :                                  dev_name(dev));
     191                 :          0 :                 return 0;
     192                 :            :         }
     193                 :            : 
     194         [ #  # ]:          0 :         if (!_munge_formats(pvd)) {
     195                 :          0 :                 log_very_verbose("format1: Unknown metadata version %d "
     196                 :            :                                  "found on %s", pvd->version, dev_name(dev));
     197                 :          0 :                 return 0;
     198                 :            :         }
     199                 :            : 
     200                 :            :         /* If VG is exported, set VG name back to the real name */
     201                 :          0 :         _munge_exported_vg(pvd);
     202                 :            : 
     203                 :          0 :         return 1;
     204                 :            : }
     205                 :            : 
     206                 :          0 : static int _read_pvd(struct device *dev, struct pv_disk *pvd)
     207                 :            : {
     208         [ #  # ]:          0 :         if (!dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd)) {
     209                 :          0 :                 log_very_verbose("Failed to read PV data from %s",
     210                 :            :                                  dev_name(dev));
     211                 :          0 :                 return 0;
     212                 :            :         }
     213                 :            : 
     214                 :          0 :         return munge_pvd(dev, pvd);
     215                 :            : }
     216                 :            : 
     217                 :          0 : static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
     218                 :            : {
     219         [ #  # ]:          0 :         if (!dev_read(dev, pos, sizeof(*disk), disk))
     220                 :          0 :                 return_0;
     221                 :            : 
     222                 :          0 :         _xlate_lvd(disk);
     223                 :            : 
     224                 :          0 :         return 1;
     225                 :            : }
     226                 :            : 
     227                 :          0 : int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd)
     228                 :            : {
     229                 :          0 :         uint64_t pos = pvd->vg_on_disk.base;
     230                 :            : 
     231         [ #  # ]:          0 :         if (!dev_read(dev, pos, sizeof(*vgd), vgd))
     232                 :          0 :                 return_0;
     233                 :            : 
     234                 :          0 :         _xlate_vgd(vgd);
     235                 :            : 
     236   [ #  #  #  # ]:          0 :         if ((vgd->lv_max > MAX_LV) || (vgd->pv_max > MAX_PV))
     237                 :          0 :                 return_0;
     238                 :            :                 
     239                 :            :         /* If UUID is missing, create one */
     240         [ #  # ]:          0 :         if (vgd->vg_uuid[0] == '\0')
     241                 :          0 :                 uuid_from_num((char *)vgd->vg_uuid, vgd->vg_number);
     242                 :            : 
     243                 :          0 :         return 1;
     244                 :            : }
     245                 :            : 
     246                 :          0 : static int _read_uuids(struct disk_list *data)
     247                 :            : {
     248                 :          0 :         unsigned num_read = 0;
     249                 :            :         struct uuid_list *ul;
     250                 :            :         char buffer[NAME_LEN] __attribute((aligned(8)));
     251                 :          0 :         uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
     252                 :          0 :         uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
     253                 :            : 
     254 [ #  # ][ #  # ]:          0 :         while (pos < end && num_read < data->vgd.pv_cur) {
     255         [ #  # ]:          0 :                 if (!dev_read(data->dev, pos, sizeof(buffer), buffer))
     256                 :          0 :                         return_0;
     257                 :            : 
     258         [ #  # ]:          0 :                 if (!(ul = dm_pool_alloc(data->mem, sizeof(*ul))))
     259                 :          0 :                         return_0;
     260                 :            : 
     261                 :          0 :                 memcpy(ul->uuid, buffer, NAME_LEN);
     262                 :          0 :                 ul->uuid[NAME_LEN - 1] = '\0';
     263                 :            : 
     264                 :          0 :                 dm_list_add(&data->uuids, &ul->list);
     265                 :            : 
     266                 :          0 :                 pos += NAME_LEN;
     267                 :          0 :                 num_read++;
     268                 :            :         }
     269                 :            : 
     270                 :          0 :         return 1;
     271                 :            : }
     272                 :            : 
     273                 :          0 : static int _check_lvd(struct lv_disk *lvd)
     274                 :            : {
     275                 :          0 :         return !(lvd->lv_name[0] == '\0');
     276                 :            : }
     277                 :            : 
     278                 :          0 : static int _read_lvs(struct disk_list *data)
     279                 :            : {
     280                 :          0 :         unsigned int i, lvs_read = 0;
     281                 :            :         uint64_t pos;
     282                 :            :         struct lvd_list *ll;
     283                 :          0 :         struct vg_disk *vgd = &data->vgd;
     284                 :            : 
     285 [ #  # ][ #  # ]:          0 :         for (i = 0; (i < vgd->lv_max) && (lvs_read < vgd->lv_cur); i++) {
     286                 :          0 :                 pos = data->pvd.lv_on_disk.base + (i * sizeof(struct lv_disk));
     287                 :          0 :                 ll = dm_pool_alloc(data->mem, sizeof(*ll));
     288                 :            : 
     289         [ #  # ]:          0 :                 if (!ll)
     290                 :          0 :                         return_0;
     291                 :            : 
     292         [ #  # ]:          0 :                 if (!_read_lvd(data->dev, pos, &ll->lvd))
     293                 :          0 :                         return_0;
     294                 :            : 
     295         [ #  # ]:          0 :                 if (!_check_lvd(&ll->lvd))
     296                 :          0 :                         continue;
     297                 :            : 
     298                 :          0 :                 lvs_read++;
     299                 :          0 :                 dm_list_add(&data->lvds, &ll->list);
     300                 :            :         }
     301                 :            : 
     302                 :          0 :         return 1;
     303                 :            : }
     304                 :            : 
     305                 :          0 : static int _read_extents(struct disk_list *data)
     306                 :            : {
     307                 :          0 :         size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
     308                 :          0 :         struct pe_disk *extents = dm_pool_alloc(data->mem, len);
     309                 :          0 :         uint64_t pos = data->pvd.pe_on_disk.base;
     310                 :            : 
     311         [ #  # ]:          0 :         if (!extents)
     312                 :          0 :                 return_0;
     313                 :            : 
     314         [ #  # ]:          0 :         if (!dev_read(data->dev, pos, len, extents))
     315                 :          0 :                 return_0;
     316                 :            : 
     317                 :          0 :         _xlate_extents(extents, data->pvd.pe_total);
     318                 :          0 :         data->extents = extents;
     319                 :            : 
     320                 :          0 :         return 1;
     321                 :            : }
     322                 :            : 
     323                 :          0 : static void __update_lvmcache(const struct format_type *fmt,
     324                 :            :                               struct disk_list *dl,
     325                 :            :                               struct device *dev, const char *vgid,
     326                 :            :                               unsigned exported)
     327                 :            : {
     328                 :            :         struct lvmcache_info *info;
     329                 :          0 :         const char *vgname = *((char *)dl->pvd.vg_name) ?
     330         [ #  # ]:          0 :                              (char *)dl->pvd.vg_name : fmt->orphan_vg_name;
     331                 :            : 
     332 [ #  # ][ #  # ]:          0 :         if (!(info = lvmcache_add(fmt->labeller, (char *)dl->pvd.pv_uuid, dev,
     333                 :            :                                   vgname, vgid, exported ? EXPORTED_VG : 0))) {
     334                 :          0 :                 stack;
     335                 :          0 :                 return;
     336                 :            :         }
     337                 :            : 
     338                 :          0 :         info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
     339                 :          0 :         dm_list_init(&info->mdas);
     340                 :          0 :         info->status &= ~CACHE_INVALID;
     341                 :            : }
     342                 :            : 
     343                 :          0 : static struct disk_list *__read_disk(const struct format_type *fmt,
     344                 :            :                                      struct device *dev, struct dm_pool *mem,
     345                 :            :                                      const char *vg_name)
     346                 :            : {
     347                 :          0 :         struct disk_list *dl = dm_pool_zalloc(mem, sizeof(*dl));
     348                 :          0 :         const char *name = dev_name(dev);
     349                 :            : 
     350         [ #  # ]:          0 :         if (!dl)
     351                 :          0 :                 return_NULL;
     352                 :            : 
     353                 :          0 :         dl->dev = dev;
     354                 :          0 :         dl->mem = mem;
     355                 :          0 :         dm_list_init(&dl->uuids);
     356                 :          0 :         dm_list_init(&dl->lvds);
     357                 :            : 
     358         [ #  # ]:          0 :         if (!_read_pvd(dev, &dl->pvd))
     359                 :          0 :                 goto_bad;
     360                 :            : 
     361                 :            :         /*
     362                 :            :          * is it an orphan ?
     363                 :            :          */
     364         [ #  # ]:          0 :         if (!*dl->pvd.vg_name) {
     365                 :          0 :                 log_very_verbose("%s is not a member of any format1 VG", name);
     366                 :            : 
     367                 :          0 :                 __update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
     368         [ #  # ]:          0 :                 return (vg_name) ? NULL : dl;
     369                 :            :         }
     370                 :            : 
     371         [ #  # ]:          0 :         if (!read_vgd(dl->dev, &dl->vgd, &dl->pvd)) {
     372                 :          0 :                 log_error("Failed to read VG data from PV (%s)", name);
     373                 :          0 :                 __update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
     374                 :          0 :                 goto bad;
     375                 :            :         }
     376                 :            : 
     377 [ #  # ][ #  # ]:          0 :         if (vg_name && strcmp(vg_name, (char *)dl->pvd.vg_name)) {
     378                 :          0 :                 log_very_verbose("%s is not a member of the VG %s",
     379                 :            :                                  name, vg_name);
     380                 :          0 :                 __update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
     381                 :          0 :                 goto bad;
     382                 :            :         }
     383                 :            : 
     384                 :          0 :         __update_lvmcache(fmt, dl, dev, (char *)dl->vgd.vg_uuid,
     385                 :            :                           dl->vgd.vg_status & VG_EXPORTED);
     386                 :            : 
     387         [ #  # ]:          0 :         if (!_read_uuids(dl)) {
     388                 :          0 :                 log_error("Failed to read PV uuid list from %s", name);
     389                 :          0 :                 goto bad;
     390                 :            :         }
     391                 :            : 
     392         [ #  # ]:          0 :         if (!_read_lvs(dl)) {
     393                 :          0 :                 log_error("Failed to read LV's from %s", name);
     394                 :          0 :                 goto bad;
     395                 :            :         }
     396                 :            : 
     397         [ #  # ]:          0 :         if (!_read_extents(dl)) {
     398                 :          0 :                 log_error("Failed to read extents from %s", name);
     399                 :          0 :                 goto bad;
     400                 :            :         }
     401                 :            : 
     402         [ #  # ]:          0 :         log_very_verbose("Found %s in %sVG %s", name,
     403                 :            :                          (dl->vgd.vg_status & VG_EXPORTED) ? "exported " : "",
     404                 :            :                          dl->pvd.vg_name);
     405                 :            : 
     406                 :          0 :         return dl;
     407                 :            : 
     408                 :            :       bad:
     409                 :          0 :         dm_pool_free(dl->mem, dl);
     410                 :          0 :         return NULL;
     411                 :            : }
     412                 :            : 
     413                 :          0 : struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
     414                 :            :                             struct dm_pool *mem, const char *vg_name)
     415                 :            : {
     416                 :            :         struct disk_list *dl;
     417                 :            : 
     418         [ #  # ]:          0 :         if (!dev_open(dev))
     419                 :          0 :                 return_NULL;
     420                 :            : 
     421                 :          0 :         dl = __read_disk(fmt, dev, mem, vg_name);
     422                 :            : 
     423         [ #  # ]:          0 :         if (!dev_close(dev))
     424                 :          0 :                 stack;
     425                 :            : 
     426                 :          0 :         return dl;
     427                 :            : }
     428                 :            : 
     429                 :          0 : static void _add_pv_to_list(struct dm_list *head, struct disk_list *data)
     430                 :            : {
     431                 :            :         struct pv_disk *pvd;
     432                 :            :         struct disk_list *diskl;
     433                 :            : 
     434         [ #  # ]:          0 :         dm_list_iterate_items(diskl, head) {
     435                 :          0 :                 pvd = &diskl->pvd;
     436         [ #  # ]:          0 :                 if (!strncmp((char *)data->pvd.pv_uuid, (char *)pvd->pv_uuid,
     437                 :            :                              sizeof(pvd->pv_uuid))) {
     438         [ #  # ]:          0 :                         if (!dev_subsystem_part_major(data->dev)) {
     439                 :          0 :                                 log_very_verbose("Ignoring duplicate PV %s on "
     440                 :            :                                                  "%s", pvd->pv_uuid,
     441                 :            :                                                  dev_name(data->dev));
     442                 :          0 :                                 return;
     443                 :            :                         }
     444                 :          0 :                         log_very_verbose("Duplicate PV %s - using %s %s",
     445                 :            :                                          pvd->pv_uuid, dev_subsystem_name(data->dev),
     446                 :            :                                          dev_name(data->dev));
     447                 :          0 :                         dm_list_del(&diskl->list);
     448                 :          0 :                         break;
     449                 :            :                 }
     450                 :            :         }
     451                 :          0 :         dm_list_add(head, &data->list);
     452                 :            : }
     453                 :            : 
     454                 :            : /*
     455                 :            :  * Build a list of pv_d's structures, allocated from mem.
     456                 :            :  * We keep track of the first object allocated from the pool
     457                 :            :  * so we can free off all the memory if something goes wrong.
     458                 :            :  */
     459                 :          0 : int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
     460                 :            :                    struct dev_filter *filter, struct dm_pool *mem,
     461                 :            :                    struct dm_list *head)
     462                 :            : {
     463                 :            :         struct dev_iter *iter;
     464                 :            :         struct device *dev;
     465                 :          0 :         struct disk_list *data = NULL;
     466                 :            :         struct lvmcache_vginfo *vginfo;
     467                 :            :         struct lvmcache_info *info;
     468                 :            : 
     469                 :            :         /* Fast path if we already saw this VG and cached the list of PVs */
     470 [ #  # ][ #  # ]:          0 :         if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
                 [ #  # ]
     471                 :          0 :             vginfo->infos.n) {
     472         [ #  # ]:          0 :                 dm_list_iterate_items(info, &vginfo->infos) {
     473                 :          0 :                         dev = info->dev;
     474 [ #  # ][ #  # ]:          0 :                         if (dev && !(data = read_disk(fmt, dev, mem, vg_name)))
     475                 :          0 :                                 break;
     476                 :          0 :                         _add_pv_to_list(head, data);
     477                 :            :                 }
     478                 :            : 
     479                 :            :                 /* Did we find the whole VG? */
     480 [ #  # ][ #  # ]:          0 :                 if (!vg_name || is_orphan_vg(vg_name) ||
                 [ #  # ]
           [ #  #  #  # ]
     481                 :          0 :                     (data && *data->pvd.vg_name &&
     482                 :          0 :                      dm_list_size(head) == data->vgd.pv_cur))
     483                 :          0 :                         return 1;
     484                 :            : 
     485                 :            :                 /* Failed */
     486                 :          0 :                 dm_list_init(head);
     487                 :            :                 /* vgcache_del(vg_name); */
     488                 :            :         }
     489                 :            : 
     490         [ #  # ]:          0 :         if (!(iter = dev_iter_create(filter, 1))) {
     491                 :          0 :                 log_error("read_pvs_in_vg: dev_iter_create failed");
     492                 :          0 :                 return 0;
     493                 :            :         }
     494                 :            : 
     495                 :            :         /* Otherwise do a complete scan */
     496         [ #  # ]:          0 :         for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
     497         [ #  # ]:          0 :                 if ((data = read_disk(fmt, dev, mem, vg_name))) {
     498                 :          0 :                         _add_pv_to_list(head, data);
     499                 :            :                 }
     500                 :            :         }
     501                 :          0 :         dev_iter_destroy(iter);
     502                 :            : 
     503         [ #  # ]:          0 :         if (dm_list_empty(head))
     504                 :          0 :                 return 0;
     505                 :            : 
     506                 :          0 :         return 1;
     507                 :            : }
     508                 :            : 
     509                 :          0 : static int _write_vgd(struct disk_list *data)
     510                 :            : {
     511                 :          0 :         struct vg_disk *vgd = &data->vgd;
     512                 :          0 :         uint64_t pos = data->pvd.vg_on_disk.base;
     513                 :            : 
     514                 :          0 :         log_debug("Writing %s VG metadata to %s at %" PRIu64 " len %" PRIsize_t,
     515                 :            :                   data->pvd.vg_name, dev_name(data->dev), pos, sizeof(*vgd));
     516                 :            : 
     517                 :          0 :         _xlate_vgd(vgd);
     518         [ #  # ]:          0 :         if (!dev_write(data->dev, pos, sizeof(*vgd), vgd))
     519                 :          0 :                 return_0;
     520                 :            : 
     521                 :          0 :         _xlate_vgd(vgd);
     522                 :            : 
     523                 :          0 :         return 1;
     524                 :            : }
     525                 :            : 
     526                 :          0 : static int _write_uuids(struct disk_list *data)
     527                 :            : {
     528                 :            :         struct uuid_list *ul;
     529                 :          0 :         uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
     530                 :          0 :         uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
     531                 :            : 
     532         [ #  # ]:          0 :         dm_list_iterate_items(ul, &data->uuids) {
     533         [ #  # ]:          0 :                 if (pos >= end) {
     534                 :          0 :                         log_error("Too many uuids to fit on %s",
     535                 :            :                                   dev_name(data->dev));
     536                 :          0 :                         return 0;
     537                 :            :                 }
     538                 :            : 
     539                 :          0 :                 log_debug("Writing %s uuidlist to %s at %" PRIu64 " len %d",
     540                 :            :                           data->pvd.vg_name, dev_name(data->dev),
     541                 :            :                           pos, NAME_LEN);
     542                 :            : 
     543         [ #  # ]:          0 :                 if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
     544                 :          0 :                         return_0;
     545                 :            : 
     546                 :          0 :                 pos += NAME_LEN;
     547                 :            :         }
     548                 :            : 
     549                 :          0 :         return 1;
     550                 :            : }
     551                 :            : 
     552                 :          0 : static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
     553                 :            : {
     554                 :          0 :         log_debug("Writing %s LV %s metadata to %s at %" PRIu64 " len %"
     555                 :            :                   PRIsize_t, disk->vg_name, disk->lv_name, dev_name(dev),
     556                 :            :                   pos, sizeof(*disk));
     557                 :            : 
     558                 :          0 :         _xlate_lvd(disk);
     559         [ #  # ]:          0 :         if (!dev_write(dev, pos, sizeof(*disk), disk))
     560                 :          0 :                 return_0;
     561                 :            : 
     562                 :          0 :         _xlate_lvd(disk);
     563                 :            : 
     564                 :          0 :         return 1;
     565                 :            : }
     566                 :            : 
     567                 :          0 : static int _write_lvs(struct disk_list *data)
     568                 :            : {
     569                 :            :         struct lvd_list *ll;
     570                 :            :         uint64_t pos, offset;
     571                 :            : 
     572                 :          0 :         pos = data->pvd.lv_on_disk.base;
     573                 :            : 
     574         [ #  # ]:          0 :         if (!dev_set(data->dev, pos, data->pvd.lv_on_disk.size, 0)) {
     575                 :          0 :                 log_error("Couldn't zero lv area on device '%s'",
     576                 :            :                           dev_name(data->dev));
     577                 :          0 :                 return 0;
     578                 :            :         }
     579                 :            : 
     580         [ #  # ]:          0 :         dm_list_iterate_items(ll, &data->lvds) {
     581                 :          0 :                 offset = sizeof(struct lv_disk) * ll->lvd.lv_number;
     582         [ #  # ]:          0 :                 if (offset + sizeof(struct lv_disk) > data->pvd.lv_on_disk.size) {
     583                 :          0 :                         log_error("lv_number %d too large", ll->lvd.lv_number);
     584                 :          0 :                         return 0;
     585                 :            :                 }
     586                 :            : 
     587         [ #  # ]:          0 :                 if (!_write_lvd(data->dev, pos + offset, &ll->lvd))
     588                 :          0 :                         return_0;
     589                 :            :         }
     590                 :            : 
     591                 :          0 :         return 1;
     592                 :            : }
     593                 :            : 
     594                 :          0 : static int _write_extents(struct disk_list *data)
     595                 :            : {
     596                 :          0 :         size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
     597                 :          0 :         struct pe_disk *extents = data->extents;
     598                 :          0 :         uint64_t pos = data->pvd.pe_on_disk.base;
     599                 :            : 
     600                 :          0 :         log_debug("Writing %s extents metadata to %s at %" PRIu64 " len %"
     601                 :            :                   PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
     602                 :            :                   pos, len);
     603                 :            : 
     604                 :          0 :         _xlate_extents(extents, data->pvd.pe_total);
     605         [ #  # ]:          0 :         if (!dev_write(data->dev, pos, len, extents))
     606                 :          0 :                 return_0;
     607                 :            : 
     608                 :          0 :         _xlate_extents(extents, data->pvd.pe_total);
     609                 :            : 
     610                 :          0 :         return 1;
     611                 :            : }
     612                 :            : 
     613                 :          0 : static int _write_pvd(struct disk_list *data)
     614                 :            : {
     615                 :            :         char *buf;
     616                 :          0 :         uint64_t pos = data->pvd.pv_on_disk.base;
     617                 :          0 :         size_t size = data->pvd.pv_on_disk.size;
     618                 :            : 
     619         [ #  # ]:          0 :         if (size < sizeof(struct pv_disk)) {
     620                 :          0 :                 log_error("Invalid PV structure size.");
     621                 :          0 :                 return 0;
     622                 :            :         }
     623                 :            : 
     624                 :            :         /* Make sure that the gap between the PV structure and
     625                 :            :            the next one is zeroed in order to make non LVM tools
     626                 :            :            happy (idea from AED) */
     627                 :          0 :         buf = dm_malloc(size);
     628         [ #  # ]:          0 :         if (!buf) {
     629                 :          0 :                 log_error("Couldn't allocate temporary PV buffer.");
     630                 :          0 :                 return 0;
     631                 :            :         }
     632                 :            : 
     633                 :          0 :         memset(buf, 0, size);
     634                 :          0 :         memcpy(buf, &data->pvd, sizeof(struct pv_disk));
     635                 :            : 
     636                 :          0 :         log_debug("Writing %s PV metadata to %s at %" PRIu64 " len %"
     637                 :            :                   PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
     638                 :            :                   pos, size);
     639                 :            : 
     640                 :          0 :         _xlate_pvd((struct pv_disk *) buf);
     641         [ #  # ]:          0 :         if (!dev_write(data->dev, pos, size, buf)) {
     642                 :          0 :                 dm_free(buf);
     643                 :          0 :                 return_0;
     644                 :            :         }
     645                 :            : 
     646                 :          0 :         dm_free(buf);
     647                 :          0 :         return 1;
     648                 :            : }
     649                 :            : 
     650                 :            : /*
     651                 :            :  * assumes the device has been opened.
     652                 :            :  */
     653                 :          0 : static int __write_all_pvd(const struct format_type *fmt __attribute((unused)),
     654                 :            :                            struct disk_list *data)
     655                 :            : {
     656                 :          0 :         const char *pv_name = dev_name(data->dev);
     657                 :            : 
     658         [ #  # ]:          0 :         if (!_write_pvd(data)) {
     659                 :          0 :                 log_error("Failed to write PV structure onto %s", pv_name);
     660                 :          0 :                 return 0;
     661                 :            :         }
     662                 :            : 
     663                 :            :         /* vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev, fmt); */
     664                 :            :         /*
     665                 :            :          * Stop here for orphan pv's.
     666                 :            :          */
     667         [ #  # ]:          0 :         if (data->pvd.vg_name[0] == '\0') {
     668                 :            :                 /* if (!test_mode())
     669                 :            :                    vgcache_add(data->pvd.vg_name, NULL, data->dev, fmt); */
     670                 :          0 :                 return 1;
     671                 :            :         }
     672                 :            : 
     673                 :            :         /* if (!test_mode())
     674                 :            :            vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev,
     675                 :            :            fmt); */
     676                 :            : 
     677         [ #  # ]:          0 :         if (!_write_vgd(data)) {
     678                 :          0 :                 log_error("Failed to write VG data to %s", pv_name);
     679                 :          0 :                 return 0;
     680                 :            :         }
     681                 :            : 
     682         [ #  # ]:          0 :         if (!_write_uuids(data)) {
     683                 :          0 :                 log_error("Failed to write PV uuid list to %s", pv_name);
     684                 :          0 :                 return 0;
     685                 :            :         }
     686                 :            : 
     687         [ #  # ]:          0 :         if (!_write_lvs(data)) {
     688                 :          0 :                 log_error("Failed to write LV's to %s", pv_name);
     689                 :          0 :                 return 0;
     690                 :            :         }
     691                 :            : 
     692         [ #  # ]:          0 :         if (!_write_extents(data)) {
     693                 :          0 :                 log_error("Failed to write extents to %s", pv_name);
     694                 :          0 :                 return 0;
     695                 :            :         }
     696                 :            : 
     697                 :          0 :         return 1;
     698                 :            : }
     699                 :            : 
     700                 :            : /*
     701                 :            :  * opens the device and hands to the above fn.
     702                 :            :  */
     703                 :          0 : static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data)
     704                 :            : {
     705                 :            :         int r;
     706                 :            : 
     707         [ #  # ]:          0 :         if (!dev_open(data->dev))
     708                 :          0 :                 return_0;
     709                 :            : 
     710                 :          0 :         r = __write_all_pvd(fmt, data);
     711                 :            : 
     712         [ #  # ]:          0 :         if (!dev_close(data->dev))
     713                 :          0 :                 stack;
     714                 :            : 
     715                 :          0 :         return r;
     716                 :            : }
     717                 :            : 
     718                 :            : /*
     719                 :            :  * Writes all the given pv's to disk.  Does very
     720                 :            :  * little sanity checking, so make sure correct
     721                 :            :  * data is passed to here.
     722                 :            :  */
     723                 :          0 : int write_disks(const struct format_type *fmt, struct dm_list *pvs)
     724                 :            : {
     725                 :            :         struct disk_list *dl;
     726                 :            : 
     727         [ #  # ]:          0 :         dm_list_iterate_items(dl, pvs) {
     728         [ #  # ]:          0 :                 if (!(_write_all_pvd(fmt, dl)))
     729                 :          0 :                         return_0;
     730                 :            : 
     731                 :          0 :                 log_very_verbose("Successfully wrote data to %s",
     732                 :            :                                  dev_name(dl->dev));
     733                 :            :         }
     734                 :            : 
     735                 :          0 :         return 1;
     736                 :            : }

Generated by: LCOV version 1.8