Re: [Qemu-devel] [PATCH] loadvm for read-only snapshot files

2008-02-10 Thread andrzej zaborowski
On 03/02/2008, Eddie Kohler [EMAIL PROTECTED] wrote:
 The following patch, against cvs, supports read-only snapshots on read-only
 qcow2 image files.  Snapshots can be loaded, but not saved.  This is really
 useful in my context, which is operating systems projects; a read-only memory
 snapshot allows students to share a snapshot that skips the boot process,
 allowing them to run their code right away.

 Please let me know if anything needs changing.

Instead of including block_int.h in vl.c you should use the provided
functions from block.h (bs-drv can be checked with _is_inserted).
-- 
Please do not print this email unless absolutely necessary. Spread
environmental awareness.




Re: [Qemu-devel] [PATCH] loadvm for read-only snapshot files

2008-02-10 Thread Eddie Kohler

andrzej zaborowski wrote:

On 03/02/2008, Eddie Kohler [EMAIL PROTECTED] wrote:

The following patch, against cvs, supports read-only snapshots on read-only
qcow2 image files.  Snapshots can be loaded, but not saved.  This is really
useful in my context, which is operating systems projects; a read-only memory
snapshot allows students to share a snapshot that skips the boot process,
allowing them to run their code right away.

Please let me know if anything needs changing.


Instead of including block_int.h in vl.c you should use the provided
functions from block.h (bs-drv can be checked with _is_inserted).


Thanks for the comment.  The attached patch introduces a new block.h function, 
bdev_is_snapshot_capable.  Better?


Eddie

Index: block-qcow2.c
===
RCS file: /sources/qemu/qemu/block-qcow2.c,v
retrieving revision 1.10
diff -u -u -r1.10 block-qcow2.c
--- block-qcow2.c	11 Nov 2007 02:51:16 -	1.10
+++ block-qcow2.c	10 Feb 2008 23:54:34 -
@@ -429,7 +429,6 @@
 BDRVQcowState *s = bs-opaque;
 int new_l1_size, new_l1_size2, ret, i;
 uint64_t *new_l1_table;
-uint64_t new_l1_table_offset;
 uint64_t data64;
 uint32_t data32;
 
@@ -450,28 +449,32 @@
 memcpy(new_l1_table, s-l1_table, s-l1_size * sizeof(uint64_t));
 
 /* write new table (align to cluster) */
-new_l1_table_offset = alloc_clusters(bs, new_l1_size2);
+if (!bs-read_only) {
+	uint64_t new_l1_table_offset = alloc_clusters(bs, new_l1_size2);
 
-for(i = 0; i  s-l1_size; i++)
-new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
-ret = bdrv_pwrite(s-hd, new_l1_table_offset, new_l1_table, new_l1_size2);
-if (ret != new_l1_size2)
-goto fail;
-for(i = 0; i  s-l1_size; i++)
-new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
-
-/* set new table */
-data64 = cpu_to_be64(new_l1_table_offset);
-if (bdrv_pwrite(s-hd, offsetof(QCowHeader, l1_table_offset),
-data64, sizeof(data64)) != sizeof(data64))
-goto fail;
-data32 = cpu_to_be32(new_l1_size);
-if (bdrv_pwrite(s-hd, offsetof(QCowHeader, l1_size),
-data32, sizeof(data32)) != sizeof(data32))
-goto fail;
+	for(i = 0; i  s-l1_size; i++)
+	new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
+	ret = bdrv_pwrite(s-hd, new_l1_table_offset, new_l1_table, new_l1_size2);
+	if (ret != new_l1_size2)
+	goto fail;
+	for(i = 0; i  s-l1_size; i++)
+	new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
+
+	/* set new table */
+	data64 = cpu_to_be64(new_l1_table_offset);
+	if (bdrv_pwrite(s-hd, offsetof(QCowHeader, l1_table_offset),
+			data64, sizeof(data64)) != sizeof(data64))
+	goto fail;
+	data32 = cpu_to_be32(new_l1_size);
+	if (bdrv_pwrite(s-hd, offsetof(QCowHeader, l1_size),
+			data32, sizeof(data32)) != sizeof(data32))
+	goto fail;
+	free_clusters(bs, s-l1_table_offset, s-l1_size * sizeof(uint64_t));
+	
+	s-l1_table_offset = new_l1_table_offset;
+}
+
 qemu_free(s-l1_table);
-free_clusters(bs, s-l1_table_offset, s-l1_size * sizeof(uint64_t));
-s-l1_table_offset = new_l1_table_offset;
 s-l1_table = new_l1_table;
 s-l1_size = new_l1_size;
 return 0;
@@ -521,7 +524,8 @@
 /* update the L1 entry */
 s-l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
 tmp = cpu_to_be64(l2_offset | QCOW_OFLAG_COPIED);
-if (bdrv_pwrite(s-hd, s-l1_table_offset + l1_index * sizeof(tmp),
+if (!bs-read_only 
+	bdrv_pwrite(s-hd, s-l1_table_offset + l1_index * sizeof(tmp),
 tmp, sizeof(tmp)) != sizeof(tmp))
 return 0;
 min_index = l2_cache_new_entry(bs);
@@ -535,7 +539,8 @@
 s-l2_size * sizeof(uint64_t))
 return 0;
 }
-if (bdrv_pwrite(s-hd, l2_offset,
+if (!bs-read_only 
+	bdrv_pwrite(s-hd, l2_offset,
 l2_table, s-l2_size * sizeof(uint64_t)) !=
 s-l2_size * sizeof(uint64_t))
 return 0;
@@ -624,7 +629,8 @@
 }
 /* update L2 table */
 l2_table[l2_index] = tmp;
-if (bdrv_pwrite(s-hd,
+if (!bs-read_only 
+	bdrv_pwrite(s-hd,
 l2_offset + l2_index * sizeof(tmp), tmp, sizeof(tmp)) != sizeof(tmp))
 return 0;
 return cluster_offset;
@@ -1322,7 +1328,7 @@
 }
 }
 }
-if (l2_modified) {
+if (l2_modified  !bs-read_only) {
 if (bdrv_pwrite(s-hd,
 l2_offset, l2_table, l2_size) != l2_size)
 goto fail;
@@ -1342,7 +1348,7 @@
 }
 }
 }
-if (l1_modified) {
+if (l1_modified  !bs-read_only) {
 for(i = 0; i  l1_size; i++)
 cpu_to_be64s(l1_table[i]);
 if (bdrv_pwrite(s-hd, l1_table_offset, l1_table,
@@ -1553,6 +1559,9 @@
 int i, ret;
 uint64_t *l1_table = NULL;
 
+if 

[Qemu-devel] [PATCH] loadvm for read-only snapshot files

2008-02-03 Thread Eddie Kohler

Hi all,

The following patch, against cvs, supports read-only snapshots on read-only 
qcow2 image files.  Snapshots can be loaded, but not saved.  This is really 
useful in my context, which is operating systems projects; a read-only memory 
snapshot allows students to share a snapshot that skips the boot process, 
allowing them to run their code right away.


Please let me know if anything needs changing.

Eddie Kohler

Index: block-qcow2.c
===
RCS file: /sources/qemu/qemu/block-qcow2.c,v
retrieving revision 1.10
diff -u -u -r1.10 block-qcow2.c
--- block-qcow2.c	11 Nov 2007 02:51:16 -	1.10
+++ block-qcow2.c	3 Feb 2008 18:10:07 -
@@ -429,7 +429,6 @@
 BDRVQcowState *s = bs-opaque;
 int new_l1_size, new_l1_size2, ret, i;
 uint64_t *new_l1_table;
-uint64_t new_l1_table_offset;
 uint64_t data64;
 uint32_t data32;
 
@@ -450,28 +449,32 @@
 memcpy(new_l1_table, s-l1_table, s-l1_size * sizeof(uint64_t));
 
 /* write new table (align to cluster) */
-new_l1_table_offset = alloc_clusters(bs, new_l1_size2);
+if (!bs-read_only) {
+	uint64_t new_l1_table_offset = alloc_clusters(bs, new_l1_size2);
 
-for(i = 0; i  s-l1_size; i++)
-new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
-ret = bdrv_pwrite(s-hd, new_l1_table_offset, new_l1_table, new_l1_size2);
-if (ret != new_l1_size2)
-goto fail;
-for(i = 0; i  s-l1_size; i++)
-new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
-
-/* set new table */
-data64 = cpu_to_be64(new_l1_table_offset);
-if (bdrv_pwrite(s-hd, offsetof(QCowHeader, l1_table_offset),
-data64, sizeof(data64)) != sizeof(data64))
-goto fail;
-data32 = cpu_to_be32(new_l1_size);
-if (bdrv_pwrite(s-hd, offsetof(QCowHeader, l1_size),
-data32, sizeof(data32)) != sizeof(data32))
-goto fail;
+	for(i = 0; i  s-l1_size; i++)
+	new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
+	ret = bdrv_pwrite(s-hd, new_l1_table_offset, new_l1_table, new_l1_size2);
+	if (ret != new_l1_size2)
+	goto fail;
+	for(i = 0; i  s-l1_size; i++)
+	new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
+
+	/* set new table */
+	data64 = cpu_to_be64(new_l1_table_offset);
+	if (bdrv_pwrite(s-hd, offsetof(QCowHeader, l1_table_offset),
+			data64, sizeof(data64)) != sizeof(data64))
+	goto fail;
+	data32 = cpu_to_be32(new_l1_size);
+	if (bdrv_pwrite(s-hd, offsetof(QCowHeader, l1_size),
+			data32, sizeof(data32)) != sizeof(data32))
+	goto fail;
+	free_clusters(bs, s-l1_table_offset, s-l1_size * sizeof(uint64_t));
+	
+	s-l1_table_offset = new_l1_table_offset;
+}
+
 qemu_free(s-l1_table);
-free_clusters(bs, s-l1_table_offset, s-l1_size * sizeof(uint64_t));
-s-l1_table_offset = new_l1_table_offset;
 s-l1_table = new_l1_table;
 s-l1_size = new_l1_size;
 return 0;
@@ -521,7 +524,8 @@
 /* update the L1 entry */
 s-l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
 tmp = cpu_to_be64(l2_offset | QCOW_OFLAG_COPIED);
-if (bdrv_pwrite(s-hd, s-l1_table_offset + l1_index * sizeof(tmp),
+if (!bs-read_only 
+	bdrv_pwrite(s-hd, s-l1_table_offset + l1_index * sizeof(tmp),
 tmp, sizeof(tmp)) != sizeof(tmp))
 return 0;
 min_index = l2_cache_new_entry(bs);
@@ -535,7 +539,8 @@
 s-l2_size * sizeof(uint64_t))
 return 0;
 }
-if (bdrv_pwrite(s-hd, l2_offset,
+if (!bs-read_only 
+	bdrv_pwrite(s-hd, l2_offset,
 l2_table, s-l2_size * sizeof(uint64_t)) !=
 s-l2_size * sizeof(uint64_t))
 return 0;
@@ -624,7 +629,8 @@
 }
 /* update L2 table */
 l2_table[l2_index] = tmp;
-if (bdrv_pwrite(s-hd,
+if (!bs-read_only 
+	bdrv_pwrite(s-hd,
 l2_offset + l2_index * sizeof(tmp), tmp, sizeof(tmp)) != sizeof(tmp))
 return 0;
 return cluster_offset;
@@ -1322,7 +1328,7 @@
 }
 }
 }
-if (l2_modified) {
+if (l2_modified  !bs-read_only) {
 if (bdrv_pwrite(s-hd,
 l2_offset, l2_table, l2_size) != l2_size)
 goto fail;
@@ -1342,7 +1348,7 @@
 }
 }
 }
-if (l1_modified) {
+if (l1_modified  !bs-read_only) {
 for(i = 0; i  l1_size; i++)
 cpu_to_be64s(l1_table[i]);
 if (bdrv_pwrite(s-hd, l1_table_offset, l1_table,
@@ -1553,6 +1559,9 @@
 int i, ret;
 uint64_t *l1_table = NULL;
 
+if (bs-read_only)
+	return -EACCES;
+
 memset(sn, 0, sizeof(*sn));
 
 if (sn_info-id_str[0] == '\0') {
@@ -1628,7 +1637,8 @@
 return -ENOENT;
 sn = s-snapshots[snapshot_index];
 
-if (update_snapshot_refcount(bs, s-l1_table_offset, s-l1_size, -1)  0)
+if (!bs-read_only 
+