LCOV - code coverage report
Current view: top level - vhd/lib - vhd-util-fill.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 98 0.0 %
Date: 2024-12-18 23:41:32 Functions: 0 4 0.0 %
Branches: 0 80 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2016, Citrix Systems, Inc.
       3                 :            :  *
       4                 :            :  * All rights reserved.
       5                 :            :  *
       6                 :            :  * Redistribution and use in source and binary forms, with or without
       7                 :            :  * modification, are permitted provided that the following conditions are met:
       8                 :            :  * 
       9                 :            :  *  1. Redistributions of source code must retain the above copyright
      10                 :            :  *     notice, this list of conditions and the following disclaimer.
      11                 :            :  *  2. Redistributions in binary form must reproduce the above copyright
      12                 :            :  *     notice, this list of conditions and the following disclaimer in the
      13                 :            :  *     documentation and/or other materials provided with the distribution.
      14                 :            :  *  3. Neither the name of the copyright holder nor the names of its 
      15                 :            :  *     contributors may be used to endorse or promote products derived from 
      16                 :            :  *     this software without specific prior written permission.
      17                 :            :  *
      18                 :            :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      19                 :            :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      20                 :            :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      21                 :            :  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
      22                 :            :  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
      23                 :            :  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      24                 :            :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
      25                 :            :  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
      26                 :            :  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
      27                 :            :  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
      28                 :            :  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      29                 :            :  */
      30                 :            : 
      31                 :            : #ifdef HAVE_CONFIG_H
      32                 :            : #include "config.h"
      33                 :            : #endif
      34                 :            : 
      35                 :            : #include <errno.h>
      36                 :            : #include <fcntl.h>
      37                 :            : #include <stdio.h>
      38                 :            : #include <stdlib.h>
      39                 :            : #include <unistd.h>
      40                 :            : #include <limits.h>
      41                 :            : #include <assert.h>
      42                 :            : #include <stdbool.h>
      43                 :            : 
      44                 :            : #include "libvhd.h"
      45                 :            : 
      46                 :            : #ifndef ULLONG_MAX
      47                 :            : #define ULLONG_MAX (~0ULL)
      48                 :            : #endif
      49                 :            : 
      50                 :            : int
      51                 :          0 : vhd_init_bitmap(vhd_context_t *ctx, const uint32_t block)
      52                 :            : {
      53                 :            :         int err;
      54                 :            :         void *buf;
      55                 :            :         int i;
      56                 :            :         int size;
      57                 :            : 
      58         [ #  # ]:          0 :         assert(ctx);
      59                 :            : 
      60                 :          0 :         size = vhd_bytes_padded(ctx->spb >> 3);
      61                 :            : 
      62                 :          0 :         err = posix_memalign(&buf, VHD_SECTOR_SIZE, size);
      63         [ #  # ]:          0 :         if (err)
      64                 :          0 :                 return err;
      65                 :            : 
      66         [ #  # ]:          0 :         for (i = 0; i < ctx->spb; i++)
      67                 :          0 :                 vhd_bitmap_set(ctx, buf, i);
      68                 :            : 
      69                 :          0 :         err = vhd_write_bitmap(ctx, block, buf);
      70                 :          0 :         free(buf);
      71         [ #  # ]:          0 :         if (err) {
      72                 :          0 :                 printf("failed to write bitmap for extent %u: %s\n", block,
      73                 :            :                                 strerror(-err));
      74                 :            :                 return err;
      75                 :            :         }
      76                 :            : 
      77                 :            :         return 0;
      78                 :            : }
      79                 :            : 
      80                 :            : int
      81                 :          0 : vhd_init_bitmaps(vhd_context_t *ctx, const uint32_t from_extent,
      82                 :            :                 const uint32_t to_extent) {
      83                 :            : 
      84                 :            :         unsigned int i;
      85                 :            :         int err;
      86                 :            : 
      87         [ #  # ]:          0 :         assert(ctx);
      88         [ #  # ]:          0 :         assert(from_extent <= to_extent);
      89                 :            : 
      90         [ #  # ]:          0 :         for (i = from_extent; i <= to_extent; i++) {
      91         [ #  # ]:          0 :                 if (ctx->bat.bat[i] == DD_BLK_UNUSED)
      92                 :          0 :                         continue;
      93                 :          0 :                 err = vhd_init_bitmap(ctx, i);
      94         [ #  # ]:          0 :                 if (err) {
      95                 :          0 :                         printf("failed to initialise bitmap for extent %u: %s\n", i,
      96                 :            :                                         strerror(-err));
      97                 :          0 :                         return err;
      98                 :            :                 }
      99                 :            :         }
     100                 :            : 
     101                 :            :         return 0;
     102                 :            : }
     103                 :            : 
     104                 :            : int
     105                 :          0 : vhd_io_allocate_blocks_fast(vhd_context_t *ctx, const uint32_t from_extent,
     106                 :            :                 const uint32_t to_extent, const bool ignore_2tb_limit)
     107                 :            : {
     108                 :            :         off64_t max;
     109                 :            :         int err, gap;
     110                 :          0 :         int i = 0;
     111                 :          0 :         int spp = getpagesize() >> VHD_SECTOR_SHIFT;
     112                 :            : 
     113         [ #  # ]:          0 :         assert(ctx);
     114         [ #  # ]:          0 :         assert(from_extent <= to_extent);
     115                 :            : 
     116                 :          0 :         err = vhd_end_of_data(ctx, &max);
     117         [ #  # ]:          0 :         if (err)
     118                 :          0 :                 return err;
     119                 :            : 
     120                 :          0 :         gap   = 0;
     121                 :          0 :         max >>= VHD_SECTOR_SHIFT;
     122                 :            : 
     123                 :            :         /* data region of segment should begin on page boundary */
     124         [ #  # ]:          0 :         if ((max + ctx->bm_secs) % spp) {
     125                 :          0 :                 gap  = (spp - ((max + ctx->bm_secs) % spp));
     126                 :          0 :                 max += gap;
     127                 :            :         }
     128                 :            : 
     129         [ #  # ]:          0 :         for (i = from_extent; i <= to_extent; i++) {
     130 [ #  # ][ #  # ]:          0 :                 if (max > UINT_MAX && !ignore_2tb_limit) {
     131                 :            :                         printf("sector offset for extent %u exceeds the 2 TB limit\n", i);
     132                 :            :                         err = -EOVERFLOW;
     133                 :            :                         goto out;
     134                 :            :                 }
     135                 :          0 :                 ctx->bat.bat[i] = max;
     136                 :          0 :                 max += ctx->bm_secs + ctx->bat.spb;
     137         [ #  # ]:          0 :                 if ((max + ctx->bm_secs) % spp) {
     138                 :          0 :                         gap = (spp - ((max + ctx->bm_secs) % spp));
     139                 :          0 :                         max += gap;
     140                 :            :                 }
     141                 :            :         }
     142                 :          0 :         err = vhd_write_bat(ctx, &ctx->bat);
     143         [ #  # ]:          0 :         if (err)
     144                 :            :                 goto out;
     145                 :            : 
     146                 :          0 :         err = vhd_init_bitmaps(ctx, from_extent, to_extent);
     147         [ #  # ]:          0 :         if (err)
     148                 :          0 :                 printf("failed to initialise bitmaps: %s\n", strerror(-err));
     149                 :            : 
     150                 :            : out:
     151                 :          0 :         return err;
     152                 :            : }
     153                 :            : 
     154                 :            : int
     155                 :          0 : vhd_util_fill(int argc, char **argv)
     156                 :            : {
     157                 :            :         int err, c;
     158                 :            :         char *name;
     159                 :            :         void *buf;
     160                 :            :         vhd_context_t vhd;
     161                 :            :         uint64_t i, sec, secs, from_sector, to_sector;
     162                 :            :         int init_bat;
     163                 :            :         bool ignore_2tb_limit;
     164                 :            : 
     165                 :          0 :         buf          = NULL;
     166                 :          0 :         name         = NULL;
     167                 :          0 :         init_bat     = 0;
     168                 :          0 :         from_sector  = ULLONG_MAX;
     169                 :          0 :         to_sector    = ULLONG_MAX;
     170                 :          0 :         ignore_2tb_limit = false;
     171                 :            : 
     172         [ #  # ]:          0 :         if (!argc || !argv)
     173                 :            :                 goto usage;
     174                 :            : 
     175                 :          0 :         optind = 0;
     176         [ #  # ]:          0 :         while ((c = getopt(argc, argv, "n:f:t:bBh")) != -1) {
     177   [ #  #  #  #  :          0 :                 switch (c) {
                   #  # ]
     178                 :            :                 case 'n':
     179                 :          0 :                         name = optarg;
     180                 :          0 :                         break;
     181                 :            :                 case 'f':
     182                 :          0 :                         from_sector = strtoull(optarg, NULL, 10);
     183                 :          0 :                         break;
     184                 :            :                 case 't':
     185                 :          0 :                         to_sector = strtoull(optarg, NULL, 10);
     186                 :          0 :                         break;
     187                 :            :                 case 'b':
     188                 :            :                         init_bat = 1;
     189                 :            :                         break;
     190                 :            :                 case 'B':
     191                 :          0 :                         ignore_2tb_limit = true;
     192                 :          0 :                         break;
     193                 :            :                 case 'h':
     194                 :            :                 default:
     195                 :            :                         goto usage;
     196                 :            :                 }
     197                 :            :         }
     198                 :            : 
     199 [ #  # ][ #  # ]:          0 :         if (!name || optind != argc)
     200                 :            :                 goto usage;
     201                 :            : 
     202 [ #  # ][ #  # ]:          0 :         if ((from_sector != ULLONG_MAX || to_sector != ULLONG_MAX) && !init_bat) {
     203                 :            :                 printf("-f/-t can only be used with -b\n");
     204                 :            :                 goto usage;
     205                 :            :         }
     206                 :            : 
     207         [ #  # ]:          0 :         if (from_sector != ULLONG_MAX && to_sector != ULLONG_MAX) {
     208         [ #  # ]:          0 :                 if (to_sector < from_sector) {
     209                 :            :                         printf("invalid sector range %llu-%llu\n",
     210                 :            :                                         (unsigned long long)from_sector,
     211                 :            :                                         (unsigned long long)to_sector);
     212                 :            :                         goto usage;
     213                 :            :                 }
     214                 :            :         }
     215                 :            : 
     216         [ #  # ]:          0 :         if (ignore_2tb_limit && !init_bat) {
     217                 :            :                 printf("-B can only be used with -b\n");
     218                 :            :                 goto usage;
     219                 :            :         }
     220                 :            : 
     221                 :          0 :         err = vhd_open(&vhd, name, VHD_OPEN_RDWR);
     222         [ #  # ]:          0 :         if (err) {
     223                 :            :                 printf("error opening %s: %d\n", name, err);
     224                 :          0 :                 return err;
     225                 :            :         }
     226                 :            : 
     227                 :          0 :         err = vhd_get_bat(&vhd);
     228         [ #  # ]:          0 :         if (err)
     229                 :            :                 goto done;
     230                 :            : 
     231         [ #  # ]:          0 :         if (init_bat) {
     232                 :            :                 uint32_t from_extent;
     233                 :            :                 uint32_t to_extent;
     234                 :            : 
     235         [ #  # ]:          0 :                 if (from_sector != ULLONG_MAX)
     236                 :          0 :                         from_extent = from_sector / vhd.spb;
     237                 :            :                 else
     238                 :            :                         from_extent = 0;
     239         [ #  # ]:          0 :                 if (to_sector != ULLONG_MAX)
     240                 :          0 :                         to_extent = to_sector / vhd.spb;
     241                 :            :                 else
     242                 :          0 :                         to_extent = vhd.bat.entries - 1;
     243                 :          0 :                 err = vhd_io_allocate_blocks_fast(&vhd, from_extent, to_extent,
     244                 :            :                                 ignore_2tb_limit);
     245                 :            :                 if (err)
     246                 :            :                         goto done;
     247                 :            :         } else {
     248                 :          0 :                 err = posix_memalign(&buf, 4096, vhd.header.block_size);
     249         [ #  # ]:          0 :                 if (err) {
     250                 :          0 :                         err = -err;
     251                 :          0 :                         goto done;
     252                 :            :                 }
     253                 :            : 
     254                 :          0 :                 sec = 0;
     255                 :          0 :                 secs = vhd.header.block_size >> VHD_SECTOR_SHIFT;
     256                 :            : 
     257         [ #  # ]:          0 :                 for (i = 0; i < vhd.header.max_bat_size; i++) {
     258                 :          0 :                         err = vhd_io_read(&vhd, buf, sec, secs);
     259         [ #  # ]:          0 :                         if (err)
     260                 :            :                                 goto done;
     261                 :            : 
     262                 :          0 :                         err = vhd_io_write(&vhd, buf, sec, secs);
     263         [ #  # ]:          0 :                         if (err)
     264                 :            :                                 goto done;
     265                 :            : 
     266                 :          0 :                         sec += secs;
     267                 :            :                 }
     268                 :            : 
     269                 :            :                 err = 0;
     270                 :            :         }
     271                 :            : 
     272                 :            : done:
     273                 :          0 :         free(buf);
     274                 :          0 :         vhd_close(&vhd);
     275                 :            :         return err;
     276                 :            : 
     277                 :            : usage:
     278                 :            :         printf("options: <-n name> [-h help] [-b initialise the BAT and bitmaps, "
     279                 :            :                         "don't write to the data blocks (much faster)] [-f start "
     280                 :            :                         "intialisation from this sector, only usable with -b] [-t "
     281                 :            :                         "intialise up to this sector (inclusive), only usable with -b] "
     282                 :            :                         "[-B ignore the 2 TB limit, only usable with -b]\n");
     283                 :            :         return -EINVAL;
     284                 :            : }

Generated by: LCOV version 1.13