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 -0000 1.10 +++ block-qcow2.c 3 Feb 2008 18:10:07 -0000 @@ -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 && + update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, -1) < 0) goto fail; if (grow_l1_table(bs, sn->l1_size) < 0) @@ -1640,14 +1650,17 @@ if (bdrv_pread(s->hd, sn->l1_table_offset, s->l1_table, l1_size2) != l1_size2) goto fail; - if (bdrv_pwrite(s->hd, s->l1_table_offset, - s->l1_table, l1_size2) != l1_size2) + if (bs->read_only) + s->l1_table_offset = sn->l1_table_offset; + else if (bdrv_pwrite(s->hd, s->l1_table_offset, + s->l1_table, l1_size2) != l1_size2) goto fail; for(i = 0;i < s->l1_size; i++) { be64_to_cpus(&s->l1_table[i]); } - if (update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1) < 0) + if (!bs->read_only && + update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1) < 0) goto fail; #ifdef DEBUG_ALLOC @@ -1664,6 +1677,9 @@ QCowSnapshot *sn; int snapshot_index, ret; + if (bs->read_only) + return -EACCES; + snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id); if (snapshot_index < 0) return -ENOENT; @@ -1959,6 +1975,9 @@ int ret, refcount_table_index, block_index, refcount; uint64_t data64; + if (bs->read_only) + return 2; + refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); if (refcount_table_index >= s->refcount_table_size) { if (addend < 0) Index: vl.c =================================================================== RCS file: /sources/qemu/qemu/vl.c,v retrieving revision 1.403 diff -u -u -r1.403 vl.c --- vl.c 3 Feb 2008 03:45:47 -0000 1.403 +++ vl.c 3 Feb 2008 18:10:09 -0000 @@ -36,6 +36,7 @@ #include "qemu-timer.h" #include "qemu-char.h" #include "block.h" +#include "block_int.h" #include "audio/audio.h" #include @@ -5969,7 +5970,8 @@ { return (bs && !bdrv_is_removable(bs) && - !bdrv_is_read_only(bs)); + bs->drv && + bs->drv->bdrv_snapshot_goto); } /* device must be snapshots in order to have a reliable snapshot */ @@ -5977,7 +5979,8 @@ { return (bs && !bdrv_is_removable(bs) && - !bdrv_is_read_only(bs)); + bs->drv && + bs->drv->bdrv_snapshot_goto); } static BlockDriverState *get_bs_snapshots(void)