cow.c 12.1 KB
Newer Older
B
bellard 已提交
1 2
/*
 * Block driver for the COW format
3
 *
B
bellard 已提交
4
 * Copyright (c) 2004 Fabrice Bellard
5
 *
B
bellard 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
P
pbrook 已提交
24
#include "qemu-common.h"
25
#include "block/block_int.h"
26
#include "qemu/module.h"
B
bellard 已提交
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

/**************************************************************/
/* COW block driver using file system holes */

/* user mode linux compatible COW file */
#define COW_MAGIC 0x4f4f4f4d  /* MOOO */
#define COW_VERSION 2

struct cow_header_v2 {
    uint32_t magic;
    uint32_t version;
    char backing_file[1024];
    int32_t mtime;
    uint64_t size;
    uint32_t sectorsize;
};

typedef struct BDRVCowState {
45
    CoMutex lock;
B
bellard 已提交
46 47 48 49 50 51 52
    int64_t cow_sectors_offset;
} BDRVCowState;

static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
{
    const struct cow_header_v2 *cow_header = (const void *)buf;

B
bellard 已提交
53 54
    if (buf_size >= sizeof(struct cow_header_v2) &&
        be32_to_cpu(cow_header->magic) == COW_MAGIC &&
55
        be32_to_cpu(cow_header->version) == COW_VERSION)
B
bellard 已提交
56 57 58 59 60
        return 100;
    else
        return 0;
}

M
Max Reitz 已提交
61 62
static int cow_open(BlockDriverState *bs, QDict *options, int flags,
                    Error **errp)
B
bellard 已提交
63 64 65
{
    BDRVCowState *s = bs->opaque;
    struct cow_header_v2 cow_header;
C
Christoph Hellwig 已提交
66
    int bitmap_size;
B
bellard 已提交
67
    int64_t size;
L
Li Zhi Hui 已提交
68
    int ret;
B
bellard 已提交
69 70

    /* see if it is a cow image */
L
Li Zhi Hui 已提交
71 72 73 74 75 76
    ret = bdrv_pread(bs->file, 0, &cow_header, sizeof(cow_header));
    if (ret < 0) {
        goto fail;
    }

    if (be32_to_cpu(cow_header.magic) != COW_MAGIC) {
77
        ret = -EMEDIUMTYPE;
B
bellard 已提交
78 79 80
        goto fail;
    }

L
Li Zhi Hui 已提交
81 82 83 84 85 86 87
    if (be32_to_cpu(cow_header.version) != COW_VERSION) {
        char version[64];
        snprintf(version, sizeof(version),
               "COW version %d", cow_header.version);
        qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
            bs->device_name, "cow", version);
        ret = -ENOTSUP;
B
bellard 已提交
88 89
        goto fail;
    }
90

B
bellard 已提交
91 92 93 94
    /* cow image found */
    size = be64_to_cpu(cow_header.size);
    bs->total_sectors = size / 512;

95
    pstrcpy(bs->backing_file, sizeof(bs->backing_file),
B
bellard 已提交
96
            cow_header.backing_file);
97

C
Christoph Hellwig 已提交
98 99
    bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
    s->cow_sectors_offset = (bitmap_size + 511) & ~511;
100
    qemu_co_mutex_init(&s->lock);
B
bellard 已提交
101 102
    return 0;
 fail:
L
Li Zhi Hui 已提交
103
    return ret;
B
bellard 已提交
104 105
}

C
Charlie Shepherd 已提交
106
static inline void cow_set_bits(uint8_t *bitmap, int start, int64_t nb_sectors)
B
bellard 已提交
107
{
C
Charlie Shepherd 已提交
108 109 110 111 112 113
    int64_t bitnum = start, last = start + nb_sectors;
    while (bitnum < last) {
        if ((bitnum & 7) == 0 && bitnum + 8 <= last) {
            bitmap[bitnum / 8] = 0xFF;
            bitnum += 8;
            continue;
114
        }
C
Charlie Shepherd 已提交
115 116
        bitmap[bitnum/8] |= (1 << (bitnum % 8));
        bitnum++;
117
    }
B
bellard 已提交
118 119
}

120 121 122 123
#define BITS_PER_BITMAP_SECTOR (512 * 8)

/* Cannot use bitmap.c on big-endian machines.  */
static int cow_test_bit(int64_t bitnum, const uint8_t *bitmap)
B
bellard 已提交
124
{
125 126
    return (bitmap[bitnum / 8] & (1 << (bitnum & 7))) != 0;
}
B
bellard 已提交
127

128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
static int cow_find_streak(const uint8_t *bitmap, int value, int start, int nb_sectors)
{
    int streak_value = value ? 0xFF : 0;
    int last = MIN(start + nb_sectors, BITS_PER_BITMAP_SECTOR);
    int bitnum = start;
    while (bitnum < last) {
        if ((bitnum & 7) == 0 && bitmap[bitnum / 8] == streak_value) {
            bitnum += 8;
            continue;
        }
        if (cow_test_bit(bitnum, bitmap) == value) {
            bitnum++;
            continue;
        }
        break;
C
Christoph Hellwig 已提交
143
    }
144
    return MIN(bitnum, last) - start;
C
Christoph Hellwig 已提交
145
}
B
bellard 已提交
146 147 148 149

/* Return true if first block has been changed (ie. current version is
 * in COW file).  Set the number of continuous blocks for which that
 * is true. */
150 151
static int coroutine_fn cow_co_is_allocated(BlockDriverState *bs,
        int64_t sector_num, int nb_sectors, int *num_same)
B
bellard 已提交
152
{
153 154
    int64_t bitnum = sector_num + sizeof(struct cow_header_v2) * 8;
    uint64_t offset = (bitnum / 8) & -BDRV_SECTOR_SIZE;
155 156
    bool first = true;
    int changed = 0, same = 0;
B
bellard 已提交
157

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
    do {
        int ret;
        uint8_t bitmap[BDRV_SECTOR_SIZE];

        bitnum &= BITS_PER_BITMAP_SECTOR - 1;
        int sector_bits = MIN(nb_sectors, BITS_PER_BITMAP_SECTOR - bitnum);

        ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
        if (ret < 0) {
            return ret;
        }

        if (first) {
            changed = cow_test_bit(bitnum, bitmap);
            first = false;
        }

        same += cow_find_streak(bitmap, changed, bitnum, nb_sectors);

        bitnum += sector_bits;
        nb_sectors -= sector_bits;
        offset += BDRV_SECTOR_SIZE;
    } while (nb_sectors);
B
bellard 已提交
181

182
    *num_same = same;
B
bellard 已提交
183 184 185
    return changed;
}

186 187 188
static int64_t coroutine_fn cow_co_get_block_status(BlockDriverState *bs,
        int64_t sector_num, int nb_sectors, int *num_same)
{
189 190 191 192 193 194 195
    BDRVCowState *s = bs->opaque;
    int ret = cow_co_is_allocated(bs, sector_num, nb_sectors, num_same);
    int64_t offset = s->cow_sectors_offset + (sector_num << BDRV_SECTOR_BITS);
    if (ret < 0) {
        return ret;
    }
    return (ret ? BDRV_BLOCK_DATA : 0) | offset | BDRV_BLOCK_OFFSET_VALID;
196 197
}

C
Christoph Hellwig 已提交
198 199
static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num,
        int nb_sectors)
B
bellard 已提交
200
{
C
Charlie Shepherd 已提交
201 202
    int64_t bitnum = sector_num + sizeof(struct cow_header_v2) * 8;
    uint64_t offset = (bitnum / 8) & -BDRV_SECTOR_SIZE;
203
    bool first = true;
C
Charlie Shepherd 已提交
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
    int sector_bits;

    for ( ; nb_sectors;
            bitnum += sector_bits,
            nb_sectors -= sector_bits,
            offset += BDRV_SECTOR_SIZE) {
        int ret, set;
        uint8_t bitmap[BDRV_SECTOR_SIZE];

        bitnum &= BITS_PER_BITMAP_SECTOR - 1;
        sector_bits = MIN(nb_sectors, BITS_PER_BITMAP_SECTOR - bitnum);

        ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
        if (ret < 0) {
            return ret;
        }

        /* Skip over any already set bits */
        set = cow_find_streak(bitmap, 1, bitnum, sector_bits);
        bitnum += set;
        sector_bits -= set;
        nb_sectors -= set;
        if (!sector_bits) {
            continue;
        }

        if (first) {
            ret = bdrv_flush(bs->file);
            if (ret < 0) {
                return ret;
            }
            first = false;
        }

        cow_set_bits(bitmap, bitnum, sector_bits);
C
Christoph Hellwig 已提交
239

C
Charlie Shepherd 已提交
240 241 242
        ret = bdrv_pwrite(bs->file, offset, &bitmap, sizeof(bitmap));
        if (ret < 0) {
            return ret;
C
Christoph Hellwig 已提交
243 244 245
        }
    }

C
Charlie Shepherd 已提交
246
    return 0;
B
bellard 已提交
247 248
}

S
Stefan Hajnoczi 已提交
249 250
static int coroutine_fn cow_read(BlockDriverState *bs, int64_t sector_num,
                                 uint8_t *buf, int nb_sectors)
B
bellard 已提交
251 252 253
{
    BDRVCowState *s = bs->opaque;
    int ret, n;
254

B
bellard 已提交
255
    while (nb_sectors > 0) {
256 257 258 259 260
        ret = cow_co_is_allocated(bs, sector_num, nb_sectors, &n);
        if (ret < 0) {
            return ret;
        }
        if (ret) {
C
Christoph Hellwig 已提交
261 262 263
            ret = bdrv_pread(bs->file,
                        s->cow_sectors_offset + sector_num * 512,
                        buf, n * 512);
L
Li Zhi Hui 已提交
264 265 266
            if (ret < 0) {
                return ret;
            }
B
bellard 已提交
267
        } else {
B
bellard 已提交
268 269 270
            if (bs->backing_hd) {
                /* read from the base image */
                ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
L
Li Zhi Hui 已提交
271 272 273
                if (ret < 0) {
                    return ret;
                }
B
bellard 已提交
274
            } else {
L
Li Zhi Hui 已提交
275 276
                memset(buf, 0, n * 512);
            }
B
bellard 已提交
277
        }
B
bellard 已提交
278 279 280 281 282 283 284
        nb_sectors -= n;
        sector_num += n;
        buf += n * 512;
    }
    return 0;
}

285 286 287 288 289 290 291 292 293 294 295
static coroutine_fn int cow_co_read(BlockDriverState *bs, int64_t sector_num,
                                    uint8_t *buf, int nb_sectors)
{
    int ret;
    BDRVCowState *s = bs->opaque;
    qemu_co_mutex_lock(&s->lock);
    ret = cow_read(bs, sector_num, buf, nb_sectors);
    qemu_co_mutex_unlock(&s->lock);
    return ret;
}

296
static int cow_write(BlockDriverState *bs, int64_t sector_num,
B
bellard 已提交
297 298 299
                     const uint8_t *buf, int nb_sectors)
{
    BDRVCowState *s = bs->opaque;
C
Christoph Hellwig 已提交
300
    int ret;
301

C
Christoph Hellwig 已提交
302 303
    ret = bdrv_pwrite(bs->file, s->cow_sectors_offset + sector_num * 512,
                      buf, nb_sectors * 512);
L
Li Zhi Hui 已提交
304 305 306
    if (ret < 0) {
        return ret;
    }
C
Christoph Hellwig 已提交
307 308

    return cow_update_bitmap(bs, sector_num, nb_sectors);
B
bellard 已提交
309 310
}

311 312 313 314 315 316 317 318 319 320 321
static coroutine_fn int cow_co_write(BlockDriverState *bs, int64_t sector_num,
                                     const uint8_t *buf, int nb_sectors)
{
    int ret;
    BDRVCowState *s = bs->opaque;
    qemu_co_mutex_lock(&s->lock);
    ret = cow_write(bs, sector_num, buf, nb_sectors);
    qemu_co_mutex_unlock(&s->lock);
    return ret;
}

B
bellard 已提交
322
static void cow_close(BlockDriverState *bs)
B
bellard 已提交
323 324 325
{
}

326 327
static int cow_create(const char *filename, QEMUOptionParameter *options,
                      Error **errp)
B
bellard 已提交
328 329 330
{
    struct cow_header_v2 cow_header;
    struct stat st;
331 332
    int64_t image_sectors = 0;
    const char *image_filename = NULL;
333
    Error *local_err = NULL;
334
    int ret;
335
    BlockDriverState *cow_bs;
336 337 338 339 340 341 342 343 344 345

    /* Read out options */
    while (options && options->name) {
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
            image_sectors = options->value.n / 512;
        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
            image_filename = options->value.s;
        }
        options++;
    }
B
bellard 已提交
346

347
    ret = bdrv_create_file(filename, options, &local_err);
348
    if (ret < 0) {
349 350
        qerror_report_err(local_err);
        error_free(local_err);
351 352 353
        return ret;
    }

354
    ret = bdrv_file_open(&cow_bs, filename, NULL, BDRV_O_RDWR, &local_err);
355
    if (ret < 0) {
356 357
        qerror_report_err(local_err);
        error_free(local_err);
358 359 360
        return ret;
    }

B
bellard 已提交
361 362 363 364
    memset(&cow_header, 0, sizeof(cow_header));
    cow_header.magic = cpu_to_be32(COW_MAGIC);
    cow_header.version = cpu_to_be32(COW_VERSION);
    if (image_filename) {
B
bellard 已提交
365 366 367
        /* Note: if no file, we put a dummy mtime */
        cow_header.mtime = cpu_to_be32(0);

368
        if (stat(image_filename, &st) != 0) {
B
bellard 已提交
369
            goto mtime_fail;
B
bellard 已提交
370 371
        }
        cow_header.mtime = cpu_to_be32(st.st_mtime);
B
bellard 已提交
372 373 374
    mtime_fail:
        pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file),
                image_filename);
B
bellard 已提交
375 376 377
    }
    cow_header.sectorsize = cpu_to_be32(512);
    cow_header.size = cpu_to_be64(image_sectors * 512);
378
    ret = bdrv_pwrite(cow_bs, 0, &cow_header, sizeof(cow_header));
L
Li Zhi Hui 已提交
379
    if (ret < 0) {
380 381 382
        goto exit;
    }

B
bellard 已提交
383
    /* resize to include at least all the bitmap */
384 385
    ret = bdrv_truncate(cow_bs,
        sizeof(cow_header) + ((image_sectors + 7) >> 3));
L
Li Zhi Hui 已提交
386
    if (ret < 0) {
387 388 389 390
        goto exit;
    }

exit:
F
Fam Zheng 已提交
391
    bdrv_unref(cow_bs);
392
    return ret;
B
bellard 已提交
393 394
}

395
static QEMUOptionParameter cow_create_options[] = {
396 397 398 399 400 401 402 403 404 405
    {
        .name = BLOCK_OPT_SIZE,
        .type = OPT_SIZE,
        .help = "Virtual disk size"
    },
    {
        .name = BLOCK_OPT_BACKING_FILE,
        .type = OPT_STRING,
        .help = "File name of a base image"
    },
406 407 408
    { NULL }
};

409
static BlockDriver bdrv_cow = {
410 411 412 413 414 415 416
    .format_name    = "cow",
    .instance_size  = sizeof(BDRVCowState),

    .bdrv_probe     = cow_probe,
    .bdrv_open      = cow_open,
    .bdrv_close     = cow_close,
    .bdrv_create    = cow_create,
417
    .bdrv_has_zero_init     = bdrv_has_zero_init_1,
418 419 420

    .bdrv_read              = cow_co_read,
    .bdrv_write             = cow_co_write,
421
    .bdrv_co_get_block_status   = cow_co_get_block_status,
422 423

    .create_options = cow_create_options,
B
bellard 已提交
424
};
425 426 427 428 429 430 431

static void bdrv_cow_init(void)
{
    bdrv_register(&bdrv_cow);
}

block_init(bdrv_cow_init);