qemu/block/cloop.c
<<
>>
Prefs
   1/*
   2 * QEMU Block driver for CLOOP images
   3 *
   4 * Copyright (c) 2004 Johannes E. Schindelin
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a copy
   7 * of this software and associated documentation files (the "Software"), to deal
   8 * in the Software without restriction, including without limitation the rights
   9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 * copies of the Software, and to permit persons to whom the Software is
  11 * furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 * THE SOFTWARE.
  23 */
  24#include "qemu/osdep.h"
  25#include "qapi/error.h"
  26#include "qemu-common.h"
  27#include "block/block_int.h"
  28#include "qemu/module.h"
  29#include "qemu/bswap.h"
  30#include <zlib.h>
  31
  32/* Maximum compressed block size */
  33#define MAX_BLOCK_SIZE (64 * 1024 * 1024)
  34
  35typedef struct BDRVCloopState {
  36    CoMutex lock;
  37    uint32_t block_size;
  38    uint32_t n_blocks;
  39    uint64_t *offsets;
  40    uint32_t sectors_per_block;
  41    uint32_t current_block;
  42    uint8_t *compressed_block;
  43    uint8_t *uncompressed_block;
  44    z_stream zstream;
  45} BDRVCloopState;
  46
  47static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
  48{
  49    const char *magic_version_2_0 = "#!/bin/sh\n"
  50        "#V2.0 Format\n"
  51        "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
  52    int length = strlen(magic_version_2_0);
  53    if (length > buf_size) {
  54        length = buf_size;
  55    }
  56    if (!memcmp(magic_version_2_0, buf, length)) {
  57        return 2;
  58    }
  59    return 0;
  60}
  61
  62static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
  63                      Error **errp)
  64{
  65    BDRVCloopState *s = bs->opaque;
  66    uint32_t offsets_size, max_compressed_block_size = 1, i;
  67    int ret;
  68
  69    bs->read_only = true;
  70
  71    /* read header */
  72    ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
  73    if (ret < 0) {
  74        return ret;
  75    }
  76    s->block_size = be32_to_cpu(s->block_size);
  77    if (s->block_size % 512) {
  78        error_setg(errp, "block_size %" PRIu32 " must be a multiple of 512",
  79                   s->block_size);
  80        return -EINVAL;
  81    }
  82    if (s->block_size == 0) {
  83        error_setg(errp, "block_size cannot be zero");
  84        return -EINVAL;
  85    }
  86
  87    /* cloop's create_compressed_fs.c warns about block sizes beyond 256 KB but
  88     * we can accept more.  Prevent ridiculous values like 4 GB - 1 since we
  89     * need a buffer this big.
  90     */
  91    if (s->block_size > MAX_BLOCK_SIZE) {
  92        error_setg(errp, "block_size %" PRIu32 " must be %u MB or less",
  93                   s->block_size,
  94                   MAX_BLOCK_SIZE / (1024 * 1024));
  95        return -EINVAL;
  96    }
  97
  98    ret = bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4);
  99    if (ret < 0) {
 100        return ret;
 101    }
 102    s->n_blocks = be32_to_cpu(s->n_blocks);
 103
 104    /* read offsets */
 105    if (s->n_blocks > (UINT32_MAX - 1) / sizeof(uint64_t)) {
 106        /* Prevent integer overflow */
 107        error_setg(errp, "n_blocks %" PRIu32 " must be %zu or less",
 108                   s->n_blocks,
 109                   (UINT32_MAX - 1) / sizeof(uint64_t));
 110        return -EINVAL;
 111    }
 112    offsets_size = (s->n_blocks + 1) * sizeof(uint64_t);
 113    if (offsets_size > 512 * 1024 * 1024) {
 114        /* Prevent ridiculous offsets_size which causes memory allocation to
 115         * fail or overflows bdrv_pread() size.  In practice the 512 MB
 116         * offsets[] limit supports 16 TB images at 256 KB block size.
 117         */
 118        error_setg(errp, "image requires too many offsets, "
 119                   "try increasing block size");
 120        return -EINVAL;
 121    }
 122
 123    s->offsets = g_try_malloc(offsets_size);
 124    if (s->offsets == NULL) {
 125        error_setg(errp, "Could not allocate offsets table");
 126        return -ENOMEM;
 127    }
 128
 129    ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
 130    if (ret < 0) {
 131        goto fail;
 132    }
 133
 134    for (i = 0; i < s->n_blocks + 1; i++) {
 135        uint64_t size;
 136
 137        s->offsets[i] = be64_to_cpu(s->offsets[i]);
 138        if (i == 0) {
 139            continue;
 140        }
 141
 142        if (s->offsets[i] < s->offsets[i - 1]) {
 143            error_setg(errp, "offsets not monotonically increasing at "
 144                       "index %" PRIu32 ", image file is corrupt", i);
 145            ret = -EINVAL;
 146            goto fail;
 147        }
 148
 149        size = s->offsets[i] - s->offsets[i - 1];
 150
 151        /* Compressed blocks should be smaller than the uncompressed block size
 152         * but maybe compression performed poorly so the compressed block is
 153         * actually bigger.  Clamp down on unrealistic values to prevent
 154         * ridiculous s->compressed_block allocation.
 155         */
 156        if (size > 2 * MAX_BLOCK_SIZE) {
 157            error_setg(errp, "invalid compressed block size at index %" PRIu32
 158                       ", image file is corrupt", i);
 159            ret = -EINVAL;
 160            goto fail;
 161        }
 162
 163        if (size > max_compressed_block_size) {
 164            max_compressed_block_size = size;
 165        }
 166    }
 167
 168    /* initialize zlib engine */
 169    s->compressed_block = g_try_malloc(max_compressed_block_size + 1);
 170    if (s->compressed_block == NULL) {
 171        error_setg(errp, "Could not allocate compressed_block");
 172        ret = -ENOMEM;
 173        goto fail;
 174    }
 175
 176    s->uncompressed_block = g_try_malloc(s->block_size);
 177    if (s->uncompressed_block == NULL) {
 178        error_setg(errp, "Could not allocate uncompressed_block");
 179        ret = -ENOMEM;
 180        goto fail;
 181    }
 182
 183    if (inflateInit(&s->zstream) != Z_OK) {
 184        ret = -EINVAL;
 185        goto fail;
 186    }
 187    s->current_block = s->n_blocks;
 188
 189    s->sectors_per_block = s->block_size/512;
 190    bs->total_sectors = s->n_blocks * s->sectors_per_block;
 191    qemu_co_mutex_init(&s->lock);
 192    return 0;
 193
 194fail:
 195    g_free(s->offsets);
 196    g_free(s->compressed_block);
 197    g_free(s->uncompressed_block);
 198    return ret;
 199}
 200
 201static void cloop_refresh_limits(BlockDriverState *bs, Error **errp)
 202{
 203    bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
 204}
 205
 206static inline int cloop_read_block(BlockDriverState *bs, int block_num)
 207{
 208    BDRVCloopState *s = bs->opaque;
 209
 210    if (s->current_block != block_num) {
 211        int ret;
 212        uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num];
 213
 214        ret = bdrv_pread(bs->file, s->offsets[block_num],
 215                         s->compressed_block, bytes);
 216        if (ret != bytes) {
 217            return -1;
 218        }
 219
 220        s->zstream.next_in = s->compressed_block;
 221        s->zstream.avail_in = bytes;
 222        s->zstream.next_out = s->uncompressed_block;
 223        s->zstream.avail_out = s->block_size;
 224        ret = inflateReset(&s->zstream);
 225        if (ret != Z_OK) {
 226            return -1;
 227        }
 228        ret = inflate(&s->zstream, Z_FINISH);
 229        if (ret != Z_STREAM_END || s->zstream.total_out != s->block_size) {
 230            return -1;
 231        }
 232
 233        s->current_block = block_num;
 234    }
 235    return 0;
 236}
 237
 238static int coroutine_fn
 239cloop_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
 240                QEMUIOVector *qiov, int flags)
 241{
 242    BDRVCloopState *s = bs->opaque;
 243    uint64_t sector_num = offset >> BDRV_SECTOR_BITS;
 244    int nb_sectors = bytes >> BDRV_SECTOR_BITS;
 245    int ret, i;
 246
 247    assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
 248    assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
 249
 250    qemu_co_mutex_lock(&s->lock);
 251
 252    for (i = 0; i < nb_sectors; i++) {
 253        void *data;
 254        uint32_t sector_offset_in_block =
 255            ((sector_num + i) % s->sectors_per_block),
 256            block_num = (sector_num + i) / s->sectors_per_block;
 257        if (cloop_read_block(bs, block_num) != 0) {
 258            ret = -EIO;
 259            goto fail;
 260        }
 261
 262        data = s->uncompressed_block + sector_offset_in_block * 512;
 263        qemu_iovec_from_buf(qiov, i * 512, data, 512);
 264    }
 265
 266    ret = 0;
 267fail:
 268    qemu_co_mutex_unlock(&s->lock);
 269
 270    return ret;
 271}
 272
 273static void cloop_close(BlockDriverState *bs)
 274{
 275    BDRVCloopState *s = bs->opaque;
 276    g_free(s->offsets);
 277    g_free(s->compressed_block);
 278    g_free(s->uncompressed_block);
 279    inflateEnd(&s->zstream);
 280}
 281
 282static BlockDriver bdrv_cloop = {
 283    .format_name    = "cloop",
 284    .instance_size  = sizeof(BDRVCloopState),
 285    .bdrv_probe     = cloop_probe,
 286    .bdrv_open      = cloop_open,
 287    .bdrv_refresh_limits = cloop_refresh_limits,
 288    .bdrv_co_preadv = cloop_co_preadv,
 289    .bdrv_close     = cloop_close,
 290};
 291
 292static void bdrv_cloop_init(void)
 293{
 294    bdrv_register(&bdrv_cloop);
 295}
 296
 297block_init(bdrv_cloop_init);
 298