qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Alex Beregszaszi <alex@fsn.hu>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH] Bochs Redolog disk image support
Date: Thu, 17 Mar 2005 18:52:44 +0100	[thread overview]
Message-ID: <20050317185244.7b9fdc20@caprice.artificis.hu> (raw)

[-- Attachment #1: Type: text/plain, Size: 632 bytes --]

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.

-- 
Alex Beregszaszi 			e-mail: alex@fsn.hu
Free Software Network			cell: +36 70 3144424

[-- Attachment #2: block-bochs.c --]
[-- Type: text/x-csrc, Size: 6387 bytes --]

/*
 * 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

[-- Attachment #3: block-bochs.diff --]
[-- Type: text/x-diff, Size: 2237 bytes --]

? 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);

             reply	other threads:[~2005-03-17 18:16 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-03-17 17:52 Alex Beregszaszi [this message]
2005-04-07 20:28 ` [Qemu-devel] [PATCH] Bochs Redolog disk image support Fabrice Bellard
2005-04-12 15:31   ` Alex Beregszaszi
2005-04-12 21:48     ` Hetz Ben Hamo
2005-04-12 15:33   ` Alex Beregszaszi
  -- strict thread matches above, loose matches on Subject: below --
2005-03-17 17:41 Alex Beregszaszi
2005-03-17 17:52 ` Paul Brook

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20050317185244.7b9fdc20@caprice.artificis.hu \
    --to=alex@fsn.hu \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).