LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/lib/label - label.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 24 171 14.0 %
Date: 2010-04-13 Functions: 5 13 38.5 %
Branches: 5 98 5.1 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2002-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 "label.h"
      18                 :            : #include "crc.h"
      19                 :            : #include "xlate.h"
      20                 :            : #include "lvmcache.h"
      21                 :            : #include "metadata.h"
      22                 :            : 
      23                 :            : #include <sys/stat.h>
      24                 :            : #include <fcntl.h>
      25                 :            : #include <unistd.h>
      26                 :            : 
      27                 :            : /* FIXME Allow for larger labels?  Restricted to single sector currently */
      28                 :            : 
      29                 :            : /*
      30                 :            :  * Internal labeller struct.
      31                 :            :  */
      32                 :            : struct labeller_i {
      33                 :            :         struct dm_list list;
      34                 :            : 
      35                 :            :         struct labeller *l;
      36                 :            :         char name[0];
      37                 :            : };
      38                 :            : 
      39                 :            : static struct dm_list _labellers;
      40                 :            : 
      41                 :          9 : static struct labeller_i *_alloc_li(const char *name, struct labeller *l)
      42                 :            : {
      43                 :            :         struct labeller_i *li;
      44                 :            :         size_t len;
      45                 :            : 
      46                 :          9 :         len = sizeof(*li) + strlen(name) + 1;
      47                 :            : 
      48         [ -  + ]:          9 :         if (!(li = dm_malloc(len))) {
      49                 :          0 :                 log_error("Couldn't allocate memory for labeller list object.");
      50                 :          0 :                 return NULL;
      51                 :            :         }
      52                 :            : 
      53                 :          9 :         li->l = l;
      54                 :          9 :         strcpy(li->name, name);
      55                 :            : 
      56                 :          9 :         return li;
      57                 :            : }
      58                 :            : 
      59                 :          9 : static void _free_li(struct labeller_i *li)
      60                 :            : {
      61                 :          9 :         dm_free(li);
      62                 :          9 : }
      63                 :            : 
      64                 :          3 : int label_init(void)
      65                 :            : {
      66                 :          3 :         dm_list_init(&_labellers);
      67                 :          3 :         return 1;
      68                 :            : }
      69                 :            : 
      70                 :          3 : void label_exit(void)
      71                 :            : {
      72                 :            :         struct dm_list *c, *n;
      73                 :            :         struct labeller_i *li;
      74                 :            : 
      75 [ +  - ][ +  + ]:         12 :         for (c = _labellers.n; c && c != &_labellers; c = n) {
      76                 :          9 :                 n = c->n;
      77                 :          9 :                 li = dm_list_item(c, struct labeller_i);
      78                 :          9 :                 li->l->ops->destroy(li->l);
      79                 :          9 :                 _free_li(li);
      80                 :            :         }
      81                 :            : 
      82                 :          3 :         dm_list_init(&_labellers);
      83                 :          3 : }
      84                 :            : 
      85                 :          9 : int label_register_handler(const char *name, struct labeller *handler)
      86                 :            : {
      87                 :            :         struct labeller_i *li;
      88                 :            : 
      89         [ -  + ]:          9 :         if (!(li = _alloc_li(name, handler)))
      90                 :          0 :                 return_0;
      91                 :            : 
      92                 :          9 :         dm_list_add(&_labellers, &li->list);
      93                 :          9 :         return 1;
      94                 :            : }
      95                 :            : 
      96                 :          0 : struct labeller *label_get_handler(const char *name)
      97                 :            : {
      98                 :            :         struct labeller_i *li;
      99                 :            : 
     100         [ #  # ]:          0 :         dm_list_iterate_items(li, &_labellers)
     101         [ #  # ]:          0 :                 if (!strcmp(li->name, name))
     102                 :          0 :                         return li->l;
     103                 :            : 
     104                 :          0 :         return NULL;
     105                 :            : }
     106                 :            : 
     107                 :          0 : static struct labeller *_find_labeller(struct device *dev, char *buf,
     108                 :            :                                        uint64_t *label_sector,
     109                 :            :                                        uint64_t scan_sector)
     110                 :            : {
     111                 :            :         struct labeller_i *li;
     112                 :          0 :         struct labeller *r = NULL;
     113                 :            :         struct label_header *lh;
     114                 :            :         struct lvmcache_info *info;
     115                 :            :         uint64_t sector;
     116                 :          0 :         int found = 0;
     117                 :            :         char readbuf[LABEL_SCAN_SIZE] __attribute((aligned(8)));
     118                 :            : 
     119         [ #  # ]:          0 :         if (!dev_read(dev, scan_sector << SECTOR_SHIFT,
     120                 :            :                       LABEL_SCAN_SIZE, readbuf)) {
     121                 :          0 :                 log_debug("%s: Failed to read label area", dev_name(dev));
     122                 :          0 :                 goto out;
     123                 :            :         }
     124                 :            : 
     125                 :            :         /* Scan a few sectors for a valid label */
     126         [ #  # ]:          0 :         for (sector = 0; sector < LABEL_SCAN_SECTORS;
     127                 :          0 :              sector += LABEL_SIZE >> SECTOR_SHIFT) {
     128                 :          0 :                 lh = (struct label_header *) (readbuf +
     129                 :          0 :                                               (sector << SECTOR_SHIFT));
     130                 :            : 
     131         [ #  # ]:          0 :                 if (!strncmp((char *)lh->id, LABEL_ID, sizeof(lh->id))) {
     132         [ #  # ]:          0 :                         if (found) {
     133                 :          0 :                                 log_error("Ignoring additional label on %s at "
     134                 :            :                                           "sector %" PRIu64, dev_name(dev),
     135                 :            :                                           sector + scan_sector);
     136                 :            :                         }
     137         [ #  # ]:          0 :                         if (xlate64(lh->sector_xl) != sector + scan_sector) {
     138                 :          0 :                                 log_info("%s: Label for sector %" PRIu64
     139                 :            :                                          " found at sector %" PRIu64
     140                 :            :                                          " - ignoring", dev_name(dev),
     141                 :            :                                          (uint64_t)xlate64(lh->sector_xl),
     142                 :            :                                          sector + scan_sector);
     143                 :          0 :                                 continue;
     144                 :            :                         }
     145         [ #  # ]:          0 :                         if (calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE -
     146                 :            :                                      ((uintptr_t) &lh->offset_xl - (uintptr_t) lh)) !=
     147                 :          0 :                             xlate32(lh->crc_xl)) {
     148                 :          0 :                                 log_info("Label checksum incorrect on %s - "
     149                 :            :                                          "ignoring", dev_name(dev));
     150                 :          0 :                                 continue;
     151                 :            :                         }
     152         [ #  # ]:          0 :                         if (found)
     153                 :          0 :                                 continue;
     154                 :            :                 }
     155                 :            : 
     156         [ #  # ]:          0 :                 dm_list_iterate_items(li, &_labellers) {
     157         [ #  # ]:          0 :                         if (li->l->ops->can_handle(li->l, (char *) lh,
     158                 :            :                                                    sector + scan_sector)) {
     159                 :          0 :                                 log_very_verbose("%s: %s label detected",
     160                 :            :                                                  dev_name(dev), li->name);
     161         [ #  # ]:          0 :                                 if (found) {
     162                 :          0 :                                         log_error("Ignoring additional label "
     163                 :            :                                                   "on %s at sector %" PRIu64,
     164                 :            :                                                   dev_name(dev),
     165                 :            :                                                   sector + scan_sector);
     166                 :          0 :                                         continue;
     167                 :            :                                 }
     168                 :          0 :                                 r = li->l;
     169                 :          0 :                                 memcpy(buf, lh, LABEL_SIZE);
     170         [ #  # ]:          0 :                                 if (label_sector)
     171                 :          0 :                                         *label_sector = sector + scan_sector;
     172                 :          0 :                                 found = 1;
     173                 :          0 :                                 break;
     174                 :            :                         }
     175                 :            :                 }
     176                 :            :         }
     177                 :            : 
     178                 :            :       out:
     179         [ #  # ]:          0 :         if (!found) {
     180         [ #  # ]:          0 :                 if ((info = info_from_pvid(dev->pvid, 0)))
     181                 :          0 :                         lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
     182                 :          0 :                                                       info->fmt->orphan_vg_name,
     183                 :            :                                                       0, NULL);
     184                 :          0 :                 log_very_verbose("%s: No label detected", dev_name(dev));
     185                 :            :         }
     186                 :            : 
     187                 :          0 :         return r;
     188                 :            : }
     189                 :            : 
     190                 :            : /* FIXME Also wipe associated metadata area headers? */
     191                 :          0 : int label_remove(struct device *dev)
     192                 :            : {
     193                 :            :         char buf[LABEL_SIZE] __attribute((aligned(8)));
     194                 :            :         char readbuf[LABEL_SCAN_SIZE] __attribute((aligned(8)));
     195                 :          0 :         int r = 1;
     196                 :            :         uint64_t sector;
     197                 :            :         int wipe;
     198                 :            :         struct labeller_i *li;
     199                 :            :         struct label_header *lh;
     200                 :            : 
     201                 :          0 :         memset(buf, 0, LABEL_SIZE);
     202                 :            : 
     203                 :          0 :         log_very_verbose("Scanning for labels to wipe from %s", dev_name(dev));
     204                 :            : 
     205         [ #  # ]:          0 :         if (!dev_open(dev))
     206                 :          0 :                 return_0;
     207                 :            : 
     208                 :            :         /*
     209                 :            :          * We flush the device just in case someone is stupid
     210                 :            :          * enough to be trying to import an open pv into lvm.
     211                 :            :          */
     212                 :          0 :         dev_flush(dev);
     213                 :            : 
     214         [ #  # ]:          0 :         if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
     215                 :          0 :                 log_debug("%s: Failed to read label area", dev_name(dev));
     216                 :          0 :                 goto out;
     217                 :            :         }
     218                 :            : 
     219                 :            :         /* Scan first few sectors for anything looking like a label */
     220         [ #  # ]:          0 :         for (sector = 0; sector < LABEL_SCAN_SECTORS;
     221                 :          0 :              sector += LABEL_SIZE >> SECTOR_SHIFT) {
     222                 :          0 :                 lh = (struct label_header *) (readbuf +
     223                 :          0 :                                               (sector << SECTOR_SHIFT));
     224                 :            : 
     225                 :          0 :                 wipe = 0;
     226                 :            : 
     227         [ #  # ]:          0 :                 if (!strncmp((char *)lh->id, LABEL_ID, sizeof(lh->id))) {
     228         [ #  # ]:          0 :                         if (xlate64(lh->sector_xl) == sector)
     229                 :          0 :                                 wipe = 1;
     230                 :            :                 } else {
     231         [ #  # ]:          0 :                         dm_list_iterate_items(li, &_labellers) {
     232         [ #  # ]:          0 :                                 if (li->l->ops->can_handle(li->l, (char *) lh,
     233                 :            :                                                            sector)) {
     234                 :          0 :                                         wipe = 1;
     235                 :          0 :                                         break;
     236                 :            :                                 }
     237                 :            :                         }
     238                 :            :                 }
     239                 :            : 
     240         [ #  # ]:          0 :                 if (wipe) {
     241                 :          0 :                         log_info("%s: Wiping label at sector %" PRIu64,
     242                 :            :                                  dev_name(dev), sector);
     243         [ #  # ]:          0 :                         if (!dev_write(dev, sector << SECTOR_SHIFT, LABEL_SIZE,
     244                 :            :                                        buf)) {
     245                 :          0 :                                 log_error("Failed to remove label from %s at "
     246                 :            :                                           "sector %" PRIu64, dev_name(dev),
     247                 :            :                                           sector);
     248                 :          0 :                                 r = 0;
     249                 :            :                         }
     250                 :            :                 }
     251                 :            :         }
     252                 :            : 
     253                 :            :       out:
     254         [ #  # ]:          0 :         if (!dev_close(dev))
     255                 :          0 :                 stack;
     256                 :            : 
     257                 :          0 :         return r;
     258                 :            : }
     259                 :            : 
     260                 :          0 : int label_read(struct device *dev, struct label **result,
     261                 :            :                 uint64_t scan_sector)
     262                 :            : {
     263                 :            :         char buf[LABEL_SIZE] __attribute((aligned(8)));
     264                 :            :         struct labeller *l;
     265                 :            :         uint64_t sector;
     266                 :            :         struct lvmcache_info *info;
     267                 :          0 :         int r = 0;
     268                 :            : 
     269         [ #  # ]:          0 :         if ((info = info_from_pvid(dev->pvid, 1))) {
     270                 :          0 :                 log_debug("Using cached label for %s", dev_name(dev));
     271                 :          0 :                 *result = info->label;
     272                 :          0 :                 return 1;
     273                 :            :         }
     274                 :            : 
     275         [ #  # ]:          0 :         if (!dev_open(dev)) {
     276                 :          0 :                 stack;
     277                 :            : 
     278         [ #  # ]:          0 :                 if ((info = info_from_pvid(dev->pvid, 0)))
     279                 :          0 :                         lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
     280                 :          0 :                                                       info->fmt->orphan_vg_name,
     281                 :            :                                                       0, NULL);
     282                 :            : 
     283                 :          0 :                 return r;
     284                 :            :         }
     285                 :            : 
     286         [ #  # ]:          0 :         if (!(l = _find_labeller(dev, buf, &sector, scan_sector)))
     287                 :          0 :                 goto out;
     288                 :            : 
     289 [ #  # ][ #  # ]:          0 :         if ((r = (l->ops->read)(l, dev, buf, result)) && result && *result)
                 [ #  # ]
     290                 :          0 :                 (*result)->sector = sector;
     291                 :            : 
     292                 :            :       out:
     293         [ #  # ]:          0 :         if (!dev_close(dev))
     294                 :          0 :                 stack;
     295                 :            : 
     296                 :          0 :         return r;
     297                 :            : }
     298                 :            : 
     299                 :            : /* Caller may need to use label_get_handler to create label struct! */
     300                 :          0 : int label_write(struct device *dev, struct label *label)
     301                 :            : {
     302                 :            :         char buf[LABEL_SIZE] __attribute((aligned(8)));
     303                 :          0 :         struct label_header *lh = (struct label_header *) buf;
     304                 :          0 :         int r = 1;
     305                 :            : 
     306         [ #  # ]:          0 :         if (!label->labeller->ops->write) {
     307                 :          0 :                 log_error("Label handler does not support label writes");
     308                 :          0 :                 return 0;
     309                 :            :         }
     310                 :            : 
     311         [ #  # ]:          0 :         if ((LABEL_SIZE + (label->sector << SECTOR_SHIFT)) > LABEL_SCAN_SIZE) {
     312                 :          0 :                 log_error("Label sector %" PRIu64 " beyond range (%ld)",
     313                 :            :                           label->sector, LABEL_SCAN_SECTORS);
     314                 :          0 :                 return 0;
     315                 :            :         }
     316                 :            : 
     317                 :          0 :         memset(buf, 0, LABEL_SIZE);
     318                 :            : 
     319                 :          0 :         strncpy((char *)lh->id, LABEL_ID, sizeof(lh->id));
     320                 :          0 :         lh->sector_xl = xlate64(label->sector);
     321                 :          0 :         lh->offset_xl = xlate32(sizeof(*lh));
     322                 :            : 
     323         [ #  # ]:          0 :         if (!(label->labeller->ops->write)(label, buf))
     324                 :          0 :                 return_0;
     325                 :            : 
     326                 :          0 :         lh->crc_xl = xlate32(calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE -
     327                 :            :                                       ((uintptr_t) &lh->offset_xl - (uintptr_t) lh)));
     328                 :            : 
     329         [ #  # ]:          0 :         if (!dev_open(dev))
     330                 :          0 :                 return_0;
     331                 :            : 
     332                 :          0 :         log_info("%s: Writing label to sector %" PRIu64 " with stored offset %"
     333                 :            :                  PRIu32 ".", dev_name(dev), label->sector,
     334                 :            :                  xlate32(lh->offset_xl));
     335         [ #  # ]:          0 :         if (!dev_write(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, buf)) {
     336                 :          0 :                 log_debug("Failed to write label to %s", dev_name(dev));
     337                 :          0 :                 r = 0;
     338                 :            :         }
     339                 :            : 
     340         [ #  # ]:          0 :         if (!dev_close(dev))
     341                 :          0 :                 stack;
     342                 :            : 
     343                 :          0 :         return r;
     344                 :            : }
     345                 :            : 
     346                 :            : /* Unused */
     347                 :          0 : int label_verify(struct device *dev)
     348                 :            : {
     349                 :            :         struct labeller *l;
     350                 :            :         char buf[LABEL_SIZE] __attribute((aligned(8)));
     351                 :            :         uint64_t sector;
     352                 :            :         struct lvmcache_info *info;
     353                 :          0 :         int r = 0;
     354                 :            : 
     355         [ #  # ]:          0 :         if (!dev_open(dev)) {
     356         [ #  # ]:          0 :                 if ((info = info_from_pvid(dev->pvid, 0)))
     357                 :          0 :                         lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
     358                 :          0 :                                                       info->fmt->orphan_vg_name,
     359                 :            :                                                       0, NULL);
     360                 :            : 
     361                 :          0 :                 return_0;
     362                 :            :         }
     363                 :            : 
     364         [ #  # ]:          0 :         if (!(l = _find_labeller(dev, buf, &sector, UINT64_C(0))))
     365                 :          0 :                 goto out;
     366                 :            : 
     367         [ #  # ]:          0 :         r = l->ops->verify ? l->ops->verify(l, buf, sector) : 1;
     368                 :            : 
     369                 :            :       out:
     370         [ #  # ]:          0 :         if (!dev_close(dev))
     371                 :          0 :                 stack;
     372                 :            : 
     373                 :          0 :         return r;
     374                 :            : }
     375                 :            : 
     376                 :          0 : void label_destroy(struct label *label)
     377                 :            : {
     378                 :          0 :         label->labeller->ops->destroy_label(label->labeller, label);
     379                 :          0 :         dm_free(label);
     380                 :          0 : }
     381                 :            : 
     382                 :          0 : struct label *label_create(struct labeller *labeller)
     383                 :            : {
     384                 :            :         struct label *label;
     385                 :            : 
     386         [ #  # ]:          0 :         if (!(label = dm_malloc(sizeof(*label)))) {
     387                 :          0 :                 log_error("label allocaction failed");
     388                 :          0 :                 return NULL;
     389                 :            :         }
     390                 :          0 :         memset(label, 0, sizeof(*label));
     391                 :            : 
     392                 :          0 :         label->labeller = labeller;
     393                 :            : 
     394                 :          0 :         labeller->ops->initialise_label(labeller, label);
     395                 :            : 
     396                 :          0 :         return label;
     397                 :            : }

Generated by: LCOV version 1.8