mirror of https://github.com/xemu-project/xemu.git
block/rbd: increase dynamically the image size
RBD APIs don't allow us to write more than the size set with rbd_create() or rbd_resize(). In order to support growing images (eg. qcow2), we resize the image before write operations that exceed the current size. Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> Message-id: 20190509145927.293369-1-sgarzare@redhat.com Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
parent
7d0e02405f
commit
d24f80234b
42
block/rbd.c
42
block/rbd.c
|
@ -103,6 +103,7 @@ typedef struct BDRVRBDState {
|
||||||
rbd_image_t image;
|
rbd_image_t image;
|
||||||
char *image_name;
|
char *image_name;
|
||||||
char *snap;
|
char *snap;
|
||||||
|
uint64_t image_size;
|
||||||
} BDRVRBDState;
|
} BDRVRBDState;
|
||||||
|
|
||||||
static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
|
static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
|
||||||
|
@ -778,6 +779,14 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
goto failed_open;
|
goto failed_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r = rbd_get_size(s->image, &s->image_size);
|
||||||
|
if (r < 0) {
|
||||||
|
error_setg_errno(errp, -r, "error getting image size from %s",
|
||||||
|
s->image_name);
|
||||||
|
rbd_close(s->image);
|
||||||
|
goto failed_open;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we are using an rbd snapshot, we must be r/o, otherwise
|
/* If we are using an rbd snapshot, we must be r/o, otherwise
|
||||||
* leave as-is */
|
* leave as-is */
|
||||||
if (s->snap != NULL) {
|
if (s->snap != NULL) {
|
||||||
|
@ -834,6 +843,22 @@ static void qemu_rbd_close(BlockDriverState *bs)
|
||||||
rados_shutdown(s->cluster);
|
rados_shutdown(s->cluster);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Resize the RBD image and update the 'image_size' with the current size */
|
||||||
|
static int qemu_rbd_resize(BlockDriverState *bs, uint64_t size)
|
||||||
|
{
|
||||||
|
BDRVRBDState *s = bs->opaque;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = rbd_resize(s->image, size);
|
||||||
|
if (r < 0) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->image_size = size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const AIOCBInfo rbd_aiocb_info = {
|
static const AIOCBInfo rbd_aiocb_info = {
|
||||||
.aiocb_size = sizeof(RBDAIOCB),
|
.aiocb_size = sizeof(RBDAIOCB),
|
||||||
};
|
};
|
||||||
|
@ -935,13 +960,25 @@ static BlockAIOCB *rbd_start_aio(BlockDriverState *bs,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case RBD_AIO_WRITE:
|
case RBD_AIO_WRITE: {
|
||||||
|
/*
|
||||||
|
* RBD APIs don't allow us to write more than actual size, so in order
|
||||||
|
* to support growing images, we resize the image before write
|
||||||
|
* operations that exceed the current size.
|
||||||
|
*/
|
||||||
|
if (off + size > s->image_size) {
|
||||||
|
r = qemu_rbd_resize(bs, off + size);
|
||||||
|
if (r < 0) {
|
||||||
|
goto failed_completion;
|
||||||
|
}
|
||||||
|
}
|
||||||
#ifdef LIBRBD_SUPPORTS_IOVEC
|
#ifdef LIBRBD_SUPPORTS_IOVEC
|
||||||
r = rbd_aio_writev(s->image, qiov->iov, qiov->niov, off, c);
|
r = rbd_aio_writev(s->image, qiov->iov, qiov->niov, off, c);
|
||||||
#else
|
#else
|
||||||
r = rbd_aio_write(s->image, off, size, rcb->buf, c);
|
r = rbd_aio_write(s->image, off, size, rcb->buf, c);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case RBD_AIO_READ:
|
case RBD_AIO_READ:
|
||||||
#ifdef LIBRBD_SUPPORTS_IOVEC
|
#ifdef LIBRBD_SUPPORTS_IOVEC
|
||||||
r = rbd_aio_readv(s->image, qiov->iov, qiov->niov, off, c);
|
r = rbd_aio_readv(s->image, qiov->iov, qiov->niov, off, c);
|
||||||
|
@ -1052,7 +1089,6 @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
|
||||||
PreallocMode prealloc,
|
PreallocMode prealloc,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BDRVRBDState *s = bs->opaque;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (prealloc != PREALLOC_MODE_OFF) {
|
if (prealloc != PREALLOC_MODE_OFF) {
|
||||||
|
@ -1061,7 +1097,7 @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = rbd_resize(s->image, offset);
|
r = qemu_rbd_resize(bs, offset);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
error_setg_errno(errp, -r, "Failed to resize file");
|
error_setg_errno(errp, -r, "Failed to resize file");
|
||||||
return r;
|
return r;
|
||||||
|
|
Loading…
Reference in New Issue