qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] Bochs Redolog disk image support


From: Fabrice Bellard
Subject: Re: [Qemu-devel] [PATCH] Bochs Redolog disk image support
Date: Thu, 07 Apr 2005 22:28:58 +0200
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040913

Hi,

Supporting Bochs disk images is interesting. I can commit your patch if you suppress the unneeded mmap() usage.

Fabrice.

Alex Beregszaszi wrote:
Hi,

Looks like I forgot to attach...

attached is a patch and file adding read-only support for bochs
"growing" type of disk images.

I wrote this for converting my bochs images into cow and I'm not
currently interested in adding write support.

Also note that altought the bochs "redolog" disk format has more
subtypes, the growing one is the widely used one. Also there's a
different format called "sparse", which is not supported by this driver.
The "flat" format used by bochs is just raw.

Also it could be speed up by several factors.



------------------------------------------------------------------------

/*
 * Block driver for the various disk image formats used by Bochs
 * Currently only for "growing" type in read-only mode
* * Copyright (c) 2005 Alex Beregszaszi * * 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.
 */
#ifndef _WIN32
#include "vl.h"
#include "block_int.h"
#include <sys/mman.h>

/**************************************************************/

#define HEADER_MAGIC "Bochs Virtual HD Image"
#define HEADER_VERSION 0x00010000
#define HEADER_SIZE 512

#define REDOLOG_TYPE "Redolog"
#define GROWING_TYPE "Growing"

// not allocated: 0xffffffff

// always little-endian
struct bochs_header {
    char magic[32]; // "Bochs Virtual HD Image"
    char type[16]; // "Redolog"
    char subtype[16]; // "Undoable" / "Volatile" / "Growing"
    uint32_t version;
    uint32_t header; // size of header
union {
        struct {
            uint32_t catalog; // num of entries
            uint32_t bitmap; // bitmap size
            uint32_t extent; // extent size
            uint64_t disk; // disk size
            char padding[HEADER_SIZE - 64 - 8 - 20];
        } redolog;
        char padding[HEADER_SIZE - 64 - 8];
    } extra;
};

typedef struct BDRVBochsState {
    int fd;
    uint32_t *catalog_bitmap;
    int catalog_size;
    int catalog_addr;
int bitmap_blocks, extent_blocks, extent_size;
} BDRVBochsState;

static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
{
    const struct bochs_header *bochs = (const void *)buf;
if (buf_size < HEADER_SIZE)
        return 0;

    if (!strcmp(bochs->magic, HEADER_MAGIC) &&
        !strcmp(bochs->type, REDOLOG_TYPE) &&
        !strcmp(bochs->subtype, GROWING_TYPE) &&
        (le32_to_cpu(bochs->version) == HEADER_VERSION))
        return 100;

    return 0;
}

static int bochs_open(BlockDriverState *bs, const char *filename)
{
    BDRVBochsState *s = bs->opaque;
    int fd;
    struct bochs_header bochs;
    int64_t size;

    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
    if (fd < 0) {
        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
        if (fd < 0)
            return -1;
    }
bs->read_only = 1; // no write support yet s->fd = fd;

    if (read(fd, &bochs, sizeof(bochs)) != sizeof(bochs)) {
        goto fail;
    }

    if (strcmp(bochs.magic, HEADER_MAGIC) ||
        strcmp(bochs.type, REDOLOG_TYPE) ||
        strcmp(bochs.subtype, GROWING_TYPE) ||
        (le32_to_cpu(bochs.version) != HEADER_VERSION)) {
        goto fail;
    }

    size = le64_to_cpu(bochs.extra.redolog.disk);

    bs->total_sectors = size / 512;
s->catalog_size = le32_to_cpu(bochs.extra.redolog.catalog) * 4 + le32_to_cpu(bochs.header); s->catalog_addr = mmap(get_mmap_addr(s->catalog_size), s->catalog_size, PROT_READ,
                              MAP_SHARED, s->fd, 0);
    if (s->catalog_addr == MAP_FAILED)
        goto fail;
    s->catalog_bitmap = s->catalog_addr + le32_to_cpu(bochs.header);

    s->bitmap_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.bitmap) - 1) / 512;
    s->extent_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.extent) - 1) / 512;
s->extent_size = le32_to_cpu(bochs.extra.redolog.extent);

    return 0;
 fail:
    close(fd);
    return -1;
}

static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
{
    BDRVBochsState *s = bs->opaque;
    int64_t offset = sector_num * 512;
    int64_t extent_index, extent_offset, bitmap_offset, block_offset;
    char bitmap_entry;

    // seek to sector
    extent_index = offset / s->extent_size;
    extent_offset = (offset % s->extent_size) / 512;
if (le32_to_cpu(s->catalog_bitmap[extent_index]) == 0xffffffff)
    {
//      fprintf(stderr, "page not allocated [%x - %x:%x]\n",
//          sector_num, extent_index, extent_offset);
        return -1; // not allocated
    }

    bitmap_offset = s->catalog_size + (512 * 
le32_to_cpu(s->catalog_bitmap[extent_index]) *
        (s->extent_blocks + s->bitmap_blocks));
    block_offset = bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
// fprintf(stderr, "sect: %x [ext i: %x o: %x] -> %x bitmap: %x block: %x\n",
//      sector_num, extent_index, extent_offset,
//      le32_to_cpu(s->catalog_bitmap[extent_index]),
//      bitmap_offset, block_offset);
// read in bitmap for current extent
    lseek(s->fd, bitmap_offset + (extent_offset / 8), SEEK_SET);
read(s->fd, &bitmap_entry, 1); if (!((bitmap_entry >> (extent_offset % 8)) & 1))
    {
//      fprintf(stderr, "sector (%x) in bitmap not allocated\n",
//          sector_num);
        return -1; // not allocated
    }

    lseek(s->fd, block_offset, SEEK_SET);
return 0;
}

static int bochs_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors)
{
    BDRVBochsState *s = bs->opaque;
    int ret, n;

    while (nb_sectors > 0) {
        if (!seek_to_sector(bs, sector_num))
        {
            ret = read(s->fd, buf, 512);
            if (ret != 512)
                return -1;
        }
        else
            memset(buf, 0, 512);
        nb_sectors--;
        sector_num++;
        buf += 512;
    }
    return 0;
}

static void bochs_close(BlockDriverState *bs)
{
    BDRVBochsState *s = bs->opaque;
    munmap(s->catalog_addr, s->catalog_size);
    close(s->fd);
}

BlockDriver bdrv_bochs = {
    "bochs",
    sizeof(BDRVBochsState),
    bochs_probe,
    bochs_open,
    bochs_read,
    NULL,
    bochs_close,
};
#endif


------------------------------------------------------------------------

? block-bochs.c
? block-bochs.diff
Index: Makefile
===================================================================
RCS file: /cvsroot/qemu/qemu/Makefile,v
retrieving revision 1.82
diff -u -r1.82 Makefile
--- Makefile    10 Feb 2005 21:48:51 -0000      1.82
+++ Makefile    17 Mar 2005 17:27:00 -0000
@@ -21,7 +21,7 @@
        $(MAKE) -C kqemu
 endif
-qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c
+qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c 
block-vmdk.c block-cloop.c block-dmg.c block-bochs.c
        $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
dyngen$(EXESUF): dyngen.c
Index: Makefile.target
===================================================================
RCS file: /cvsroot/qemu/qemu/Makefile.target,v
retrieving revision 1.62
diff -u -r1.62 Makefile.target
--- Makefile.target     13 Mar 2005 16:52:10 -0000      1.62
+++ Makefile.target     17 Mar 2005 17:27:00 -0000
@@ -309,7 +309,7 @@
# must use static linking to avoid leaving stuff in virtual address space VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o -VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o
+VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o 
block-bochs.o
SOUND_HW = sb16.o
 AUDIODRV = audio.o noaudio.o wavaudio.o
Index: block.c
===================================================================
RCS file: /cvsroot/qemu/qemu/block.c,v
retrieving revision 1.16
diff -u -r1.16 block.c
--- block.c     12 Dec 2004 11:24:44 -0000      1.16
+++ block.c     17 Mar 2005 17:27:00 -0000
@@ -608,4 +608,5 @@
     bdrv_register(&bdrv_vmdk);
     bdrv_register(&bdrv_cloop);
     bdrv_register(&bdrv_dmg);
+    bdrv_register(&bdrv_bochs);
 }
Index: vl.h
===================================================================
RCS file: /cvsroot/qemu/qemu/vl.h,v
retrieving revision 1.69
diff -u -r1.69 vl.h
--- vl.h        13 Mar 2005 09:43:36 -0000      1.69
+++ vl.h        17 Mar 2005 17:27:01 -0000
@@ -381,6 +381,7 @@
 extern BlockDriver bdrv_vmdk;
 extern BlockDriver bdrv_cloop;
 extern BlockDriver bdrv_dmg;
+extern BlockDriver bdrv_bochs;
void bdrv_init(void);
 BlockDriver *bdrv_find_format(const char *format_name);


------------------------------------------------------------------------

_______________________________________________
Qemu-devel mailing list
address@hidden
http://lists.nongnu.org/mailman/listinfo/qemu-devel





reply via email to

[Prev in Thread] Current Thread [Next in Thread]