Am 28.04.2010 11:24, schrieb Stefan Hajnoczi: > This patch adds the ability to grow qcow2 images in-place using > bdrv_truncate(). This enables qemu-img resize command support for > qcow2. > > Snapshots are not supported and bdrv_truncate() will return -ENOTSUP. > The notion of resizing an image with snapshots could lead to confusion: > users may expect snapshots to remain unchanged, but this is not possible > with the current qcow2 on-disk format where the header.size field is > global instead of per-snapshot. Others may expect snapshots to change > size along with the current image data. I think it is safest to not > support snapshots and perhaps add behavior later if there is a > consensus. > > Backing images continue to work. If the image is now larger than its > backing image, zeroes are read when accessing beyond the end of the > backing image. > > Signed-off-by: Stefan Hajnoczi <stefa...@linux.vnet.ibm.com> > --- > v2: > * Remove superfluous qcow2_grow_l1_table()-related changes > > block/qcow2.c | 45 +++++++++++++++++++++++++++++++++++++++++---- > block/qcow2.h | 6 ++++++ > 2 files changed, 47 insertions(+), 4 deletions(-) > > diff --git a/block/qcow2.c b/block/qcow2.c > index 4fa3ff9..a65af41 100644 > --- a/block/qcow2.c > +++ b/block/qcow2.c > @@ -140,7 +140,7 @@ static int qcow_read_extensions(BlockDriverState *bs, > uint64_t start_offset, > static int qcow_open(BlockDriverState *bs, int flags) > { > BDRVQcowState *s = bs->opaque; > - int len, i, shift; > + int len, i; > QCowHeader header; > uint64_t ext_end; > > @@ -188,8 +188,7 @@ static int qcow_open(BlockDriverState *bs, int flags) > > /* read the level 1 table */ > s->l1_size = header.l1_size; > - shift = s->cluster_bits + s->l2_bits; > - s->l1_vm_state_index = (header.size + (1LL << shift) - 1) >> shift; > + s->l1_vm_state_index = size_to_l1(s, header.size); > /* the L1 table must contain at least enough entries to put > header.size bytes */ > if (s->l1_size < s->l1_vm_state_index) > @@ -851,6 +850,42 @@ static int qcow_make_empty(BlockDriverState *bs) > return 0; > } > > +static int qcow2_truncate(BlockDriverState *bs, int64_t offset) > +{ > + BDRVQcowState *s = bs->opaque; > + int ret, new_l1_size; > + > + if (offset & 511) { > + return -EINVAL; > + } > + > + /* cannot proceed if image has snapshots */ > + if (s->nb_snapshots) { > + return -ENOTSUP; > + } > + > + /* shrinking is currently not supported */ > + if (offset < bs->total_sectors * 512) { > + return -ENOTSUP; > + } > + > + new_l1_size = size_to_l1(s, offset); > + ret = qcow2_grow_l1_table(bs, new_l1_size); > + if (ret < 0) { > + return ret; > + } > + > + /* write updated header.size */ > + offset = cpu_to_be64(offset); > + if (bdrv_pwrite(bs->file, offsetof(QCowHeader, size), &offset, > + sizeof(uint64_t)) != sizeof(uint64_t)) { > + return -EIO; > + }
Please return the right error code here. Also, bdrv_pwrite doesn't return short writes, so the code can look like this: ret = bdrv_pwrite(...); if (ret < 0) { return ret; } Otherwise I like the patch. It has actually become simple and easy to understand. Kevin