Re: [Qemu-devel] [PATCH] loadvm for read-only snapshot files
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
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
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 +