X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=block-cow.c;h=47a91e5ac97fef0dbce3d947bd5a74938bede87e;hb=064034211a65bb602a32ccee18d92109eb2cd656;hp=6af8b749759910eca057e6dd430ae01d8f099086;hpb=7a6cba611d09f8eccdfc90d5ad3eb03762e60ce9;p=qemu diff --git a/block-cow.c b/block-cow.c index 6af8b74..47a91e5 100644 --- a/block-cow.c +++ b/block-cow.c @@ -1,8 +1,8 @@ /* * Block driver for the COW format - * + * * Copyright (c) 2004 Fabrice Bellard - * + * * 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 @@ -56,13 +56,13 @@ static int cow_probe(const uint8_t *buf, int buf_size, const char *filename) if (buf_size >= sizeof(struct cow_header_v2) && be32_to_cpu(cow_header->magic) == COW_MAGIC && - be32_to_cpu(cow_header->version) == COW_VERSION) + be32_to_cpu(cow_header->version) == COW_VERSION) return 100; else return 0; } -static int cow_open(BlockDriverState *bs, const char *filename) +static int cow_open(BlockDriverState *bs, const char *filename, int flags) { BDRVCowState *s = bs->opaque; int fd; @@ -85,34 +85,18 @@ static int cow_open(BlockDriverState *bs, const char *filename) be32_to_cpu(cow_header.version) != COW_VERSION) { goto fail; } - + /* cow image found */ size = be64_to_cpu(cow_header.size); bs->total_sectors = size / 512; - pstrcpy(bs->backing_file, sizeof(bs->backing_file), + pstrcpy(bs->backing_file, sizeof(bs->backing_file), cow_header.backing_file); - -#if 0 - if (cow_header.backing_file[0] != '\0') { - if (stat(cow_header.backing_file, &st) != 0) { - fprintf(stderr, "%s: could not find original disk image '%s'\n", filename, cow_header.backing_file); - goto fail; - } - if (st.st_mtime != be32_to_cpu(cow_header.mtime)) { - fprintf(stderr, "%s: original raw disk image '%s' does not match saved timestamp\n", filename, cow_header.backing_file); - goto fail; - } - fd = open(cow_header.backing_file, O_RDONLY | O_LARGEFILE); - if (fd < 0) - goto fail; - bs->fd = fd; - } -#endif + /* mmap the bitmap */ s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header); - s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size), - s->cow_bitmap_size, + s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size), + s->cow_bitmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, 0); if (s->cow_bitmap_addr == MAP_FAILED) @@ -159,28 +143,35 @@ static inline int is_changed(uint8_t *bitmap, return changed; } -static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num, +static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum) { BDRVCowState *s = bs->opaque; return is_changed(s->cow_bitmap, sector_num, nb_sectors, pnum); } -static int cow_read(BlockDriverState *bs, int64_t sector_num, +static int cow_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors) { BDRVCowState *s = bs->opaque; int ret, n; - + while (nb_sectors > 0) { if (is_changed(s->cow_bitmap, sector_num, nb_sectors, &n)) { lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET); ret = read(s->fd, buf, n * 512); - if (ret != n * 512) + if (ret != n * 512) return -1; } else { + if (bs->backing_hd) { + /* read from the base image */ + ret = bdrv_read(bs->backing_hd, sector_num, buf, n); + if (ret < 0) + return -1; + } else { memset(buf, 0, n * 512); } + } nb_sectors -= n; sector_num += n; buf += n * 512; @@ -188,15 +179,15 @@ static int cow_read(BlockDriverState *bs, int64_t sector_num, return 0; } -static int cow_write(BlockDriverState *bs, int64_t sector_num, +static int cow_write(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors) { BDRVCowState *s = bs->opaque; int ret, i; - + lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET); ret = write(s->fd, buf, nb_sectors * 512); - if (ret != nb_sectors * 512) + if (ret != nb_sectors * 512) return -1; for (i = 0; i < nb_sectors; i++) cow_set_bit(s->cow_bitmap, sector_num + i); @@ -220,7 +211,7 @@ static int cow_create(const char *filename, int64_t image_sectors, if (flags) return -ENOTSUP; - cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, + cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); if (cow_fd < 0) return -1; @@ -228,18 +219,23 @@ static int cow_create(const char *filename, int64_t image_sectors, cow_header.magic = cpu_to_be32(COW_MAGIC); cow_header.version = cpu_to_be32(COW_VERSION); if (image_filename) { + /* Note: if no file, we put a dummy mtime */ + cow_header.mtime = cpu_to_be32(0); + fd = open(image_filename, O_RDONLY | O_BINARY); if (fd < 0) { close(cow_fd); - return -1; + goto mtime_fail; } if (fstat(fd, &st) != 0) { close(fd); - return -1; + goto mtime_fail; } close(fd); cow_header.mtime = cpu_to_be32(st.st_mtime); - realpath(image_filename, cow_header.backing_file); + mtime_fail: + pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file), + image_filename); } cow_header.sectorsize = cpu_to_be32(512); cow_header.size = cpu_to_be64(image_sectors * 512);