From: Anthony Liguori <aliguori-NZpS4cJIG2HvQtjrzfazuQ@public.gmane.org>
To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
Subject: [PATCH 5/7] VMDK Snapshot Support
Date: Fri, 03 Nov 2006 00:30:38 -0600 [thread overview]
Message-ID: <454AE20E.8010006@cs.utexas.edu> (raw)
In-Reply-To: <454AE007.5070905-NZpS4cJIG2HvQtjrzfazuQ@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 193 bytes --]
This is from Avi's original patch. It implements snapshot support for
VMDK disk images. It's not directly related to KVM but it's included
here for completeness.
Regards,
Anthony Liguori
[-- Attachment #2: vmdk-snapshot.diff --]
[-- Type: text/x-patch, Size: 8784 bytes --]
diff -r 1e79f1fb1c91 Makefile
--- a/Makefile Thu Nov 02 19:04:46 2006 -0600
+++ b/Makefile Thu Nov 02 19:06:29 2006 -0600
@@ -13,7 +13,7 @@ CFLAGS+=-mcpu=ultrasparc
CFLAGS+=-mcpu=ultrasparc
endif
LDFLAGS=-g
-LIBS=
+LIBS=-luuid
DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
TOOLS=qemu-img$(EXESUF)
ifdef CONFIG_STATIC
diff -r 1e79f1fb1c91 Makefile.target
--- a/Makefile.target Thu Nov 02 19:04:46 2006 -0600
+++ b/Makefile.target Thu Nov 02 19:07:05 2006 -0600
@@ -407,7 +407,7 @@ ifndef CONFIG_DARWIN
ifndef CONFIG_DARWIN
ifndef CONFIG_WIN32
ifndef CONFIG_SOLARIS
-VL_LIBS=-lutil -lrt
+VL_LIBS=-lutil -lrt -luuid
endif
endif
endif
diff -r 1e79f1fb1c91 block-vmdk.c
--- a/block-vmdk.c Thu Nov 02 19:04:46 2006 -0600
+++ b/block-vmdk.c Thu Nov 02 19:07:41 2006 -0600
@@ -22,6 +22,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include <uuid/uuid.h>
#include "vl.h"
#include "block_int.h"
@@ -89,6 +90,190 @@ static int vmdk_probe(const uint8_t *buf
return 0;
}
+#define SECTOR_SIZE 512
+#define DESC_SIZE 20*SECTOR_SIZE // 20 sectors of 512 bytes each
+#define HEADER_SIZE 512 // first sector of 512 bytes
+int vmdk_snapshot_create(BlockDriverState *bs)
+{
+ int snp_fd, p_fd;
+ uint32_t p_cid;
+ char *p_name, *gd_buf, *rgd_buf;
+ VMDK4Header header;
+ uint32_t gde_entries, gd_size;
+ int64_t gd_offset, rgd_offset, capacity, gt_size;
+ char p_desc[DESC_SIZE], s_desc[DESC_SIZE], hdr[HEADER_SIZE];
+ char parent_filename[1024];
+ char snapshot_filename[1024];
+ uuid_t name;
+ char *desc_template =
+ "# Disk DescriptorFile\n"
+ "version=1\n"
+ "CID=%x\n"
+ "parentCID=%x\n"
+ "createType=\"monolithicSparse\"\n"
+ "parentFileNameHint=\"%s\"\n"
+ "\n"
+ "# Extent description\n"
+ "RW %lu SPARSE \"%s\"\n"
+ "\n"
+ "# The Disk Data Base \n"
+ "#DDB\n"
+ "\n";
+
+ strcpy(parent_filename, bs->filename);
+ uuid_generate(name); // it should be unique filename
+ uuid_unparse(name, snapshot_filename);
+ strcat(snapshot_filename,".vmdk");
+
+ snp_fd = open(snapshot_filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644);
+ if (snp_fd < 0)
+ return -1;
+ p_fd = open(parent_filename, O_RDONLY | O_BINARY | O_LARGEFILE);
+ if (p_fd < 0) {
+ close(snp_fd);
+ return -1;
+ }
+
+ if (lseek(p_fd, 0x0, SEEK_SET) == -1)
+ goto fail;
+ if (read(p_fd, hdr, HEADER_SIZE) != HEADER_SIZE)
+ goto fail;
+
+ /* write the header */
+ if (lseek(snp_fd, 0x0, SEEK_SET) == -1)
+ goto fail;
+ if (write(snp_fd, hdr, HEADER_SIZE) == -1)
+ goto fail;
+
+ memset(&header, 0, sizeof(header));
+ memcpy(&header,&hdr[4], sizeof(header)); // skip the VMDK4_MAGIC
+
+ ftruncate(snp_fd, header.grain_offset << 9);
+ /* the descriptor offset = 0x200 */
+ if (lseek(p_fd, 0x200, SEEK_SET) == -1)
+ goto fail;
+ if (read(p_fd, p_desc, DESC_SIZE) != DESC_SIZE)
+ goto fail;
+
+ if ((p_name = strstr(p_desc,"CID")) != 0) {
+ p_name += sizeof("CID");
+ sscanf(p_name,"%x",&p_cid);
+ }
+ sprintf(s_desc, desc_template, p_cid, p_cid, parent_filename
+ , (uint32_t)header.capacity, snapshot_filename);
+
+ bs->parent_cid = p_cid;
+
+ /* write the descriptor */
+ if (lseek(snp_fd, 0x200, SEEK_SET) == -1)
+ goto fail;
+ if (write(snp_fd, s_desc, strlen(s_desc)) == -1)
+ goto fail;
+
+ gd_offset = header.gd_offset * SECTOR_SIZE; // offset of GD table
+ rgd_offset = header.rgd_offset * SECTOR_SIZE; // offset of RGD table
+ capacity = header.capacity * SECTOR_SIZE; // Extent size
+ /*
+ * Each GDE span 32M disk, means:
+ * 512 GTE per GT, each GTE points to grain
+ */
+ gt_size = (int64_t)header.num_gtes_per_gte * header.granularity * SECTOR_SIZE;
+ if (!gt_size)
+ goto fail;
+ gde_entries = (uint32_t)(capacity / gt_size); // number of gde/rgde
+ gd_size = gde_entries * sizeof(uint32_t);
+
+ /* write RGD */
+ rgd_buf = qemu_malloc(gd_size);
+ if (!rgd_buf)
+ goto fail;
+ if (lseek(p_fd, rgd_offset, SEEK_SET) == -1)
+ goto fail_rgd;
+ if (read(p_fd, rgd_buf, gd_size) != gd_size)
+ goto fail_rgd;
+ if (lseek(snp_fd, rgd_offset, SEEK_SET) == -1)
+ goto fail_rgd;
+ if (write(snp_fd, rgd_buf, gd_size) == -1)
+ goto fail_rgd;
+ qemu_free(rgd_buf);
+
+ /* write GD */
+ gd_buf = qemu_malloc(gd_size);
+ if (!gd_buf)
+ goto fail_rgd;
+ if (lseek(p_fd, gd_offset, SEEK_SET) == -1)
+ goto fail_gd;
+ if (read(p_fd, gd_buf, gd_size) != gd_size)
+ goto fail_gd;
+ if (lseek(snp_fd, gd_offset, SEEK_SET) == -1)
+ goto fail_gd;
+ if (write(snp_fd, gd_buf, gd_size) == -1)
+ goto fail_gd;
+ qemu_free(gd_buf);
+
+ close(p_fd);
+ close(snp_fd);
+ return 0;
+
+ fail_gd:
+ qemu_free(gd_buf);
+ fail_rgd:
+ qemu_free(rgd_buf);
+ fail:
+ close(p_fd);
+ close(snp_fd);
+ return -1;
+}
+
+static void vmdk_parent_close(BlockDriverState *bs)
+{
+ if (bs->bs_par_table)
+ bdrv_close(bs->bs_par_table);
+}
+
+static int vmdk_parent_open(BlockDriverState *bs, int fd)
+{
+ char *p_name;
+ char desc[DESC_SIZE];
+ static int idx=0;
+
+ /* the descriptor offset = 0x200 */
+ if (lseek(fd, 0x200, SEEK_SET) == -1)
+ return -1;
+ if (read(fd, desc, DESC_SIZE) != DESC_SIZE)
+ return -1;
+
+ if ((p_name = strstr(desc,"parentFileNameHint")) != 0) {
+ char *end_name, *tmp_name;
+ char name[256], buf[128];
+ int name_size;
+
+ p_name += sizeof("parentFileNameHint") + 1;
+ if ((end_name = strchr(p_name,'\"')) == 0)
+ return -1;
+
+ bs->parent_img_name = qemu_mallocz(end_name - p_name + 2);
+ strncpy(bs->parent_img_name, p_name, end_name - p_name);
+
+ tmp_name = strstr(bs->device_name,"_QEMU");
+ name_size = tmp_name ? (tmp_name - bs->device_name) : sizeof(bs->device_name);
+ strncpy(name,bs->device_name,name_size);
+ sprintf(buf, "_QEMU_%d", ++idx);
+
+ bs->bs_par_table = bdrv_new(strcat(name, buf));
+ if (!bs->bs_par_table) {
+ failure:
+ bdrv_close(bs);
+ return -1;
+ }
+
+ if (bdrv_open(bs->bs_par_table, bs->parent_img_name, 0) < 0)
+ goto failure;
+ }
+
+ return 0;
+}
+
static int vmdk_open(BlockDriverState *bs, const char *filename)
{
BDRVVmdkState *s = bs->opaque;
@@ -133,6 +318,10 @@ static int vmdk_open(BlockDriverState *b
/ s->l1_entry_sectors;
s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;
s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9;
+
+ // try to open parent images, if exist
+ if (vmdk_parent_open(bs, fd) != 0)
+ goto fail;
} else {
goto fail;
}
@@ -275,11 +464,17 @@ static int vmdk_read(BlockDriverState *b
if (n > nb_sectors)
n = nb_sectors;
if (!cluster_offset) {
- memset(buf, 0, 512 * n);
+ // try to read from parent image, if exist
+ if (bs->bs_par_table) {
+ if (vmdk_read(bs->bs_par_table, sector_num, buf, nb_sectors) == -1)
+ return -1;
+ } else {
+ memset(buf, 0, 512 * n);
+ }
} else {
lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
ret = read(s->fd, buf, n * 512);
- if (ret != n * 512)
+ if (ret != n * 512)
return -1;
}
nb_sectors -= n;
@@ -421,9 +616,12 @@ static void vmdk_close(BlockDriverState
static void vmdk_close(BlockDriverState *bs)
{
BDRVVmdkState *s = bs->opaque;
+
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
close(s->fd);
+ // try to close parent image, if exist
+ vmdk_parent_close(bs);
}
static void vmdk_flush(BlockDriverState *bs)
diff -r 1e79f1fb1c91 block_int.h
--- a/block_int.h Thu Nov 02 19:04:46 2006 -0600
+++ b/block_int.h Thu Nov 02 19:06:21 2006 -0600
@@ -67,12 +67,17 @@ struct BlockDriverState {
int is_temporary;
BlockDriverState *backing_hd;
+
+ BlockDriverState *bs_par_table;
+ char *parent_img_name;
+ uint32_t parent_cid;
+ uint32_t cid;
/* NOTE: the following infos are only hints for real hardware
drivers. They are not used by the block driver */
int cyls, heads, secs, translation;
int type;
- char device_name[32];
+ char device_name[256];
BlockDriverState *next;
};
[-- Attachment #3: Type: text/plain, Size: 373 bytes --]
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
[-- Attachment #4: Type: text/plain, Size: 186 bytes --]
_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel
next prev parent reply other threads:[~2006-11-03 6:30 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-11-03 6:21 [PATCH 0/7] Split up QEMU patches Anthony Liguori
[not found] ` <454AE007.5070905-NZpS4cJIG2HvQtjrzfazuQ@public.gmane.org>
2006-11-03 6:25 ` [PATCH 1/7] Compile fix for usb-linux.c Anthony Liguori
2006-11-03 6:26 ` [PATCH 2/7] APIC save/restore fix Anthony Liguori
2006-11-03 6:27 ` [PATCH 3/7] Timer " Anthony Liguori
2006-11-03 6:29 ` [PATCH 4/7] gdbstub for x86-64 Anthony Liguori
2006-11-03 6:30 ` Anthony Liguori [this message]
2006-11-03 6:31 ` [PATCH 6/7] KVM changes for QEMU Anthony Liguori
2006-11-03 6:35 ` [PATCH 7/7] Allow KVM from a normal QEMU binary Anthony Liguori
[not found] ` <454AE323.8090309-NZpS4cJIG2HvQtjrzfazuQ@public.gmane.org>
2006-11-05 9:27 ` Avi Kivity
[not found] ` <454DAE74.4030306-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2006-11-05 17:28 ` Anthony Liguori
[not found] ` <454E1F40.2070200-NZpS4cJIG2HvQtjrzfazuQ@public.gmane.org>
2006-11-05 17:48 ` Avi Kivity
[not found] ` <454E23EE.7040505-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2006-11-05 18:18 ` Anthony Liguori
[not found] ` <454E2ADC.1060607-NZpS4cJIG2HvQtjrzfazuQ@public.gmane.org>
2006-11-05 18:29 ` Avi Kivity
[not found] ` <454E2DA4.8070405-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2006-11-05 19:53 ` Anthony Liguori
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=454AE20E.8010006@cs.utexas.edu \
--to=aliguori-nzps4cjig2hvqtjrzfazuq@public.gmane.org \
--cc=kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.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