mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block patches # gpg: Signature made Fri 15 Aug 2014 14:07:42 BST using RSA key ID C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" * remotes/kevin/tags/for-upstream: (59 commits) block: Catch !bs->drv in bdrv_check() iotests: Add test for image header overlap qcow2: Catch !*host_offset for data allocation qcow2: Return useful error code in refcount_init() mirror: Handle failure for potentially large allocations vpc: Handle failure for potentially large allocations vmdk: Handle failure for potentially large allocations vhdx: Handle failure for potentially large allocations vdi: Handle failure for potentially large allocations rbd: Handle failure for potentially large allocations raw-win32: Handle failure for potentially large allocations raw-posix: Handle failure for potentially large allocations qed: Handle failure for potentially large allocations qcow2: Handle failure for potentially large allocations qcow1: Handle failure for potentially large allocations parallels: Handle failure for potentially large allocations nfs: Handle failure for potentially large allocations iscsi: Handle failure for potentially large allocations dmg: Handle failure for potentially large allocations curl: Handle failure for potentially large allocations ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -1000,3 +1000,9 @@ SSH
|
||||
M: Richard W.M. Jones <rjones@redhat.com>
|
||||
S: Supported
|
||||
F: block/ssh.c
|
||||
|
||||
ARCHIPELAGO
|
||||
M: Chrysostomos Nanakos <cnanakos@grnet.gr>
|
||||
M: Chrysostomos Nanakos <chris@include.gr>
|
||||
S: Maintained
|
||||
F: block/archipelago.c
|
||||
|
||||
+4
-5
@@ -186,7 +186,7 @@ static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector)
|
||||
{
|
||||
int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK;
|
||||
|
||||
if ((sector << BDRV_SECTOR_BITS) < bdrv_getlength(bmds->bs)) {
|
||||
if (sector < bdrv_nb_sectors(bmds->bs)) {
|
||||
return !!(bmds->aio_bitmap[chunk / (sizeof(unsigned long) * 8)] &
|
||||
(1UL << (chunk % (sizeof(unsigned long) * 8))));
|
||||
} else {
|
||||
@@ -223,8 +223,7 @@ static void alloc_aio_bitmap(BlkMigDevState *bmds)
|
||||
BlockDriverState *bs = bmds->bs;
|
||||
int64_t bitmap_size;
|
||||
|
||||
bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS) +
|
||||
BDRV_SECTORS_PER_DIRTY_CHUNK * 8 - 1;
|
||||
bitmap_size = bdrv_nb_sectors(bs) + BDRV_SECTORS_PER_DIRTY_CHUNK * 8 - 1;
|
||||
bitmap_size /= BDRV_SECTORS_PER_DIRTY_CHUNK * 8;
|
||||
|
||||
bmds->aio_bitmap = g_malloc0(bitmap_size);
|
||||
@@ -350,7 +349,7 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
|
||||
int64_t sectors;
|
||||
|
||||
if (!bdrv_is_read_only(bs)) {
|
||||
sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
|
||||
sectors = bdrv_nb_sectors(bs);
|
||||
if (sectors <= 0) {
|
||||
return;
|
||||
}
|
||||
@@ -799,7 +798,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
|
||||
|
||||
if (bs != bs_prev) {
|
||||
bs_prev = bs;
|
||||
total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
|
||||
total_sectors = bdrv_nb_sectors(bs);
|
||||
if (total_sectors <= 0) {
|
||||
error_report("Error getting length of block device %s",
|
||||
device_name);
|
||||
|
||||
@@ -57,6 +57,8 @@ struct BdrvDirtyBitmap {
|
||||
|
||||
#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
|
||||
|
||||
#define COROUTINE_POOL_RESERVATION 64 /* number of coroutines to reserve */
|
||||
|
||||
static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load);
|
||||
static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
|
||||
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||
@@ -701,6 +703,7 @@ static int find_image_format(BlockDriverState *bs, const char *filename,
|
||||
|
||||
/**
|
||||
* Set the current 'total_sectors' value
|
||||
* Return 0 on success, -errno on error.
|
||||
*/
|
||||
static int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
|
||||
{
|
||||
@@ -1313,7 +1316,6 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
|
||||
error_setg_errno(errp, -total_size, "Could not get image size");
|
||||
goto out;
|
||||
}
|
||||
total_size &= BDRV_SECTOR_MASK;
|
||||
|
||||
/* Create the temporary image */
|
||||
ret = get_tmp_filename(tmp_filename, PATH_MAX + 1);
|
||||
@@ -2107,6 +2109,9 @@ int bdrv_attach_dev(BlockDriverState *bs, void *dev)
|
||||
}
|
||||
bs->dev = dev;
|
||||
bdrv_iostatus_reset(bs);
|
||||
|
||||
/* We're expecting I/O from the device so bump up coroutine pool size */
|
||||
qemu_coroutine_adjust_pool_size(COROUTINE_POOL_RESERVATION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2126,6 +2131,7 @@ void bdrv_detach_dev(BlockDriverState *bs, void *dev)
|
||||
bs->dev_ops = NULL;
|
||||
bs->dev_opaque = NULL;
|
||||
bs->guest_block_size = 512;
|
||||
qemu_coroutine_adjust_pool_size(-COROUTINE_POOL_RESERVATION);
|
||||
}
|
||||
|
||||
/* TODO change to return DeviceState * when all users are qdevified */
|
||||
@@ -2203,6 +2209,9 @@ bool bdrv_dev_is_medium_locked(BlockDriverState *bs)
|
||||
*/
|
||||
int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix)
|
||||
{
|
||||
if (bs->drv == NULL) {
|
||||
return -ENOMEDIUM;
|
||||
}
|
||||
if (bs->drv->bdrv_check == NULL) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
@@ -2269,7 +2278,14 @@ int bdrv_commit(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
total_sectors = length >> BDRV_SECTOR_BITS;
|
||||
buf = g_malloc(COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);
|
||||
|
||||
/* qemu_try_blockalign() for bs will choose an alignment that works for
|
||||
* bs->backing_hd as well, so no need to compare the alignment manually. */
|
||||
buf = qemu_try_blockalign(bs, COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);
|
||||
if (buf == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto ro_cleanup;
|
||||
}
|
||||
|
||||
for (sector = 0; sector < total_sectors; sector += n) {
|
||||
ret = bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n);
|
||||
@@ -2307,7 +2323,7 @@ int bdrv_commit(BlockDriverState *bs)
|
||||
|
||||
ret = 0;
|
||||
ro_cleanup:
|
||||
g_free(buf);
|
||||
qemu_vfree(buf);
|
||||
|
||||
if (ro) {
|
||||
/* ignoring error return here */
|
||||
@@ -2827,18 +2843,16 @@ int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num,
|
||||
*/
|
||||
int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
|
||||
{
|
||||
int64_t target_size;
|
||||
int64_t ret, nb_sectors, sector_num = 0;
|
||||
int64_t target_sectors, ret, nb_sectors, sector_num = 0;
|
||||
int n;
|
||||
|
||||
target_size = bdrv_getlength(bs);
|
||||
if (target_size < 0) {
|
||||
return target_size;
|
||||
target_sectors = bdrv_nb_sectors(bs);
|
||||
if (target_sectors < 0) {
|
||||
return target_sectors;
|
||||
}
|
||||
target_size /= BDRV_SECTOR_SIZE;
|
||||
|
||||
for (;;) {
|
||||
nb_sectors = target_size - sector_num;
|
||||
nb_sectors = target_sectors - sector_num;
|
||||
if (nb_sectors <= 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -2968,7 +2982,12 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs,
|
||||
cluster_sector_num, cluster_nb_sectors);
|
||||
|
||||
iov.iov_len = cluster_nb_sectors * BDRV_SECTOR_SIZE;
|
||||
iov.iov_base = bounce_buffer = qemu_blockalign(bs, iov.iov_len);
|
||||
iov.iov_base = bounce_buffer = qemu_try_blockalign(bs, iov.iov_len);
|
||||
if (bounce_buffer == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
qemu_iovec_init_external(&bounce_qiov, &iov, 1);
|
||||
|
||||
ret = drv->bdrv_co_readv(bs, cluster_sector_num, cluster_nb_sectors,
|
||||
@@ -3056,15 +3075,14 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs,
|
||||
ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
|
||||
} else {
|
||||
/* Read zeros after EOF of growable BDSes */
|
||||
int64_t len, total_sectors, max_nb_sectors;
|
||||
int64_t total_sectors, max_nb_sectors;
|
||||
|
||||
len = bdrv_getlength(bs);
|
||||
if (len < 0) {
|
||||
ret = len;
|
||||
total_sectors = bdrv_nb_sectors(bs);
|
||||
if (total_sectors < 0) {
|
||||
ret = total_sectors;
|
||||
goto out;
|
||||
}
|
||||
|
||||
total_sectors = DIV_ROUND_UP(len, BDRV_SECTOR_SIZE);
|
||||
max_nb_sectors = ROUND_UP(MAX(0, total_sectors - sector_num),
|
||||
align >> BDRV_SECTOR_BITS);
|
||||
if (max_nb_sectors > 0) {
|
||||
@@ -3253,7 +3271,11 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
|
||||
/* Fall back to bounce buffer if write zeroes is unsupported */
|
||||
iov.iov_len = num * BDRV_SECTOR_SIZE;
|
||||
if (iov.iov_base == NULL) {
|
||||
iov.iov_base = qemu_blockalign(bs, num * BDRV_SECTOR_SIZE);
|
||||
iov.iov_base = qemu_try_blockalign(bs, num * BDRV_SECTOR_SIZE);
|
||||
if (iov.iov_base == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
memset(iov.iov_base, 0, num * BDRV_SECTOR_SIZE);
|
||||
}
|
||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||
@@ -3273,6 +3295,7 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
|
||||
nb_sectors -= num;
|
||||
}
|
||||
|
||||
fail:
|
||||
qemu_vfree(iov.iov_base);
|
||||
return ret;
|
||||
}
|
||||
@@ -3536,11 +3559,12 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
/**
|
||||
* Length of a file in bytes. Return < 0 if error or unknown.
|
||||
* Return number of sectors on success, -errno on error.
|
||||
*/
|
||||
int64_t bdrv_getlength(BlockDriverState *bs)
|
||||
int64_t bdrv_nb_sectors(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
|
||||
@@ -3550,19 +3574,26 @@ int64_t bdrv_getlength(BlockDriverState *bs)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return bs->total_sectors * BDRV_SECTOR_SIZE;
|
||||
return bs->total_sectors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return length in bytes on success, -errno on error.
|
||||
* The length is always a multiple of BDRV_SECTOR_SIZE.
|
||||
*/
|
||||
int64_t bdrv_getlength(BlockDriverState *bs)
|
||||
{
|
||||
int64_t ret = bdrv_nb_sectors(bs);
|
||||
|
||||
return ret < 0 ? ret : ret * BDRV_SECTOR_SIZE;
|
||||
}
|
||||
|
||||
/* return 0 as number of sectors if no device present or error */
|
||||
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
|
||||
{
|
||||
int64_t length;
|
||||
length = bdrv_getlength(bs);
|
||||
if (length < 0)
|
||||
length = 0;
|
||||
else
|
||||
length = length >> BDRV_SECTOR_BITS;
|
||||
*nb_sectors_ptr = length;
|
||||
int64_t nb_sectors = bdrv_nb_sectors(bs);
|
||||
|
||||
*nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
|
||||
}
|
||||
|
||||
void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error,
|
||||
@@ -3945,21 +3976,21 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
|
||||
int64_t sector_num,
|
||||
int nb_sectors, int *pnum)
|
||||
{
|
||||
int64_t length;
|
||||
int64_t total_sectors;
|
||||
int64_t n;
|
||||
int64_t ret, ret2;
|
||||
|
||||
length = bdrv_getlength(bs);
|
||||
if (length < 0) {
|
||||
return length;
|
||||
total_sectors = bdrv_nb_sectors(bs);
|
||||
if (total_sectors < 0) {
|
||||
return total_sectors;
|
||||
}
|
||||
|
||||
if (sector_num >= (length >> BDRV_SECTOR_BITS)) {
|
||||
if (sector_num >= total_sectors) {
|
||||
*pnum = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = bs->total_sectors - sector_num;
|
||||
n = total_sectors - sector_num;
|
||||
if (n < nb_sectors) {
|
||||
nb_sectors = n;
|
||||
}
|
||||
@@ -3994,8 +4025,8 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
|
||||
ret |= BDRV_BLOCK_ZERO;
|
||||
} else if (bs->backing_hd) {
|
||||
BlockDriverState *bs2 = bs->backing_hd;
|
||||
int64_t length2 = bdrv_getlength(bs2);
|
||||
if (length2 >= 0 && sector_num >= (length2 >> BDRV_SECTOR_BITS)) {
|
||||
int64_t nb_sectors2 = bdrv_nb_sectors(bs2);
|
||||
if (nb_sectors2 >= 0 && sector_num >= nb_sectors2) {
|
||||
ret |= BDRV_BLOCK_ZERO;
|
||||
}
|
||||
}
|
||||
@@ -4607,8 +4638,9 @@ static void bdrv_aio_bh_cb(void *opaque)
|
||||
{
|
||||
BlockDriverAIOCBSync *acb = opaque;
|
||||
|
||||
if (!acb->is_write)
|
||||
if (!acb->is_write && acb->ret >= 0) {
|
||||
qemu_iovec_from_buf(acb->qiov, 0, acb->bounce, acb->qiov->size);
|
||||
}
|
||||
qemu_vfree(acb->bounce);
|
||||
acb->common.cb(acb->common.opaque, acb->ret);
|
||||
qemu_bh_delete(acb->bh);
|
||||
@@ -4630,10 +4662,12 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
|
||||
acb = qemu_aio_get(&bdrv_em_aiocb_info, bs, cb, opaque);
|
||||
acb->is_write = is_write;
|
||||
acb->qiov = qiov;
|
||||
acb->bounce = qemu_blockalign(bs, qiov->size);
|
||||
acb->bounce = qemu_try_blockalign(bs, qiov->size);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_aio_bh_cb, acb);
|
||||
|
||||
if (is_write) {
|
||||
if (acb->bounce == NULL) {
|
||||
acb->ret = -ENOMEM;
|
||||
} else if (is_write) {
|
||||
qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size);
|
||||
acb->ret = bs->drv->bdrv_write(bs, sector_num, acb->bounce, nb_sectors);
|
||||
} else {
|
||||
@@ -5247,6 +5281,19 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size)
|
||||
return qemu_memalign(bdrv_opt_mem_align(bs), size);
|
||||
}
|
||||
|
||||
void *qemu_try_blockalign(BlockDriverState *bs, size_t size)
|
||||
{
|
||||
size_t align = bdrv_opt_mem_align(bs);
|
||||
|
||||
/* Ensure that NULL is never returned on success */
|
||||
assert(align > 0);
|
||||
if (size == 0) {
|
||||
size = align;
|
||||
}
|
||||
|
||||
return qemu_try_memalign(align, size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if all memory in this vector is sector aligned.
|
||||
*/
|
||||
@@ -5277,13 +5324,12 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity,
|
||||
|
||||
granularity >>= BDRV_SECTOR_BITS;
|
||||
assert(granularity);
|
||||
bitmap_size = bdrv_getlength(bs);
|
||||
bitmap_size = bdrv_nb_sectors(bs);
|
||||
if (bitmap_size < 0) {
|
||||
error_setg_errno(errp, -bitmap_size, "could not get length of device");
|
||||
errno = -bitmap_size;
|
||||
return NULL;
|
||||
}
|
||||
bitmap_size >>= BDRV_SECTOR_BITS;
|
||||
bitmap = g_malloc0(sizeof(BdrvDirtyBitmap));
|
||||
bitmap->bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1);
|
||||
QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
|
||||
@@ -5371,6 +5417,9 @@ void bdrv_ref(BlockDriverState *bs)
|
||||
* deleted. */
|
||||
void bdrv_unref(BlockDriverState *bs)
|
||||
{
|
||||
if (!bs) {
|
||||
return;
|
||||
}
|
||||
assert(bs->refcnt > 0);
|
||||
if (--bs->refcnt == 0) {
|
||||
bdrv_delete(bs);
|
||||
@@ -5591,7 +5640,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
if (size == -1) {
|
||||
if (backing_file) {
|
||||
BlockDriverState *bs;
|
||||
uint64_t size;
|
||||
int64_t size;
|
||||
int back_flags;
|
||||
|
||||
/* backing files always opened read-only */
|
||||
@@ -5609,8 +5658,13 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
local_err = NULL;
|
||||
goto out;
|
||||
}
|
||||
bdrv_get_geometry(bs, &size);
|
||||
size *= 512;
|
||||
size = bdrv_getlength(bs);
|
||||
if (size < 0) {
|
||||
error_setg_errno(errp, -size, "Could not get size of '%s'",
|
||||
backing_file);
|
||||
bdrv_unref(bs);
|
||||
goto out;
|
||||
}
|
||||
|
||||
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size);
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ block-obj-$(CONFIG_LIBNFS) += nfs.o
|
||||
block-obj-$(CONFIG_CURL) += curl.o
|
||||
block-obj-$(CONFIG_RBD) += rbd.o
|
||||
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
|
||||
block-obj-$(CONFIG_ARCHIPELAGO) += archipelago.o
|
||||
block-obj-$(CONFIG_LIBSSH2) += ssh.o
|
||||
endif
|
||||
|
||||
@@ -35,5 +36,6 @@ gluster.o-cflags := $(GLUSTERFS_CFLAGS)
|
||||
gluster.o-libs := $(GLUSTERFS_LIBS)
|
||||
ssh.o-cflags := $(LIBSSH2_CFLAGS)
|
||||
ssh.o-libs := $(LIBSSH2_LIBS)
|
||||
archipelago.o-libs := $(ARCHIPELAGO_LIBS)
|
||||
qcow.o-libs := -lz
|
||||
linux-aio.o-libs := -laio
|
||||
|
||||
+1069
File diff suppressed because it is too large
Load Diff
+5
-1
@@ -131,7 +131,11 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
return -EFBIG;
|
||||
}
|
||||
|
||||
s->catalog_bitmap = g_malloc(s->catalog_size * 4);
|
||||
s->catalog_bitmap = g_try_malloc(s->catalog_size * 4);
|
||||
if (s->catalog_size && s->catalog_bitmap == NULL) {
|
||||
error_setg(errp, "Could not allocate memory for catalog");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap,
|
||||
s->catalog_size * 4);
|
||||
|
||||
+20
-3
@@ -116,7 +116,12 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
"try increasing block size");
|
||||
return -EINVAL;
|
||||
}
|
||||
s->offsets = g_malloc(offsets_size);
|
||||
|
||||
s->offsets = g_try_malloc(offsets_size);
|
||||
if (s->offsets == NULL) {
|
||||
error_setg(errp, "Could not allocate offsets table");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
|
||||
if (ret < 0) {
|
||||
@@ -158,8 +163,20 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
/* initialize zlib engine */
|
||||
s->compressed_block = g_malloc(max_compressed_block_size + 1);
|
||||
s->uncompressed_block = g_malloc(s->block_size);
|
||||
s->compressed_block = g_try_malloc(max_compressed_block_size + 1);
|
||||
if (s->compressed_block == NULL) {
|
||||
error_setg(errp, "Could not allocate compressed_block");
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
s->uncompressed_block = g_try_malloc(s->block_size);
|
||||
if (s->uncompressed_block == NULL) {
|
||||
error_setg(errp, "Could not allocate uncompressed_block");
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (inflateInit(&s->zstream) != Z_OK) {
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
|
||||
+7
-1
@@ -640,7 +640,13 @@ static void curl_readv_bh_cb(void *p)
|
||||
state->buf_start = start;
|
||||
state->buf_len = acb->end + s->readahead_size;
|
||||
end = MIN(start + state->buf_len, s->len) - 1;
|
||||
state->orig_buf = g_malloc(state->buf_len);
|
||||
state->orig_buf = g_try_malloc(state->buf_len);
|
||||
if (state->buf_len && state->orig_buf == NULL) {
|
||||
curl_clean_state(state);
|
||||
acb->common.cb(acb->common.opaque, -ENOMEM);
|
||||
qemu_aio_release(acb);
|
||||
return;
|
||||
}
|
||||
state->acb[0] = acb;
|
||||
|
||||
snprintf(state->range, 127, "%zd-%zd", start, end);
|
||||
|
||||
+13
-6
@@ -284,8 +284,15 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
/* initialize zlib engine */
|
||||
s->compressed_chunk = g_malloc(max_compressed_size + 1);
|
||||
s->uncompressed_chunk = g_malloc(512 * max_sectors_per_chunk);
|
||||
s->compressed_chunk = qemu_try_blockalign(bs->file,
|
||||
max_compressed_size + 1);
|
||||
s->uncompressed_chunk = qemu_try_blockalign(bs->file,
|
||||
512 * max_sectors_per_chunk);
|
||||
if (s->compressed_chunk == NULL || s->uncompressed_chunk == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (inflateInit(&s->zstream) != Z_OK) {
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
@@ -302,8 +309,8 @@ fail:
|
||||
g_free(s->lengths);
|
||||
g_free(s->sectors);
|
||||
g_free(s->sectorcounts);
|
||||
g_free(s->compressed_chunk);
|
||||
g_free(s->uncompressed_chunk);
|
||||
qemu_vfree(s->compressed_chunk);
|
||||
qemu_vfree(s->uncompressed_chunk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -426,8 +433,8 @@ static void dmg_close(BlockDriverState *bs)
|
||||
g_free(s->lengths);
|
||||
g_free(s->sectors);
|
||||
g_free(s->sectorcounts);
|
||||
g_free(s->compressed_chunk);
|
||||
g_free(s->uncompressed_chunk);
|
||||
qemu_vfree(s->compressed_chunk);
|
||||
qemu_vfree(s->uncompressed_chunk);
|
||||
|
||||
inflateEnd(&s->zstream);
|
||||
}
|
||||
|
||||
+4
-1
@@ -893,7 +893,10 @@ coroutine_fn iscsi_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
|
||||
nb_blocks = sector_qemu2lun(nb_sectors, iscsilun);
|
||||
|
||||
if (iscsilun->zeroblock == NULL) {
|
||||
iscsilun->zeroblock = g_malloc0(iscsilun->block_size);
|
||||
iscsilun->zeroblock = g_try_malloc0(iscsilun->block_size);
|
||||
if (iscsilun->zeroblock == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
iscsi_co_init_iscsitask(iscsilun, &iTask);
|
||||
|
||||
+6
-1
@@ -367,7 +367,12 @@ static void coroutine_fn mirror_run(void *opaque)
|
||||
}
|
||||
|
||||
end = s->common.len >> BDRV_SECTOR_BITS;
|
||||
s->buf = qemu_blockalign(bs, s->buf_size);
|
||||
s->buf = qemu_try_blockalign(bs, s->buf_size);
|
||||
if (s->buf == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto immediate_exit;
|
||||
}
|
||||
|
||||
sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS;
|
||||
mirror_free_init(s);
|
||||
|
||||
|
||||
+5
-1
@@ -172,7 +172,11 @@ static int coroutine_fn nfs_co_writev(BlockDriverState *bs,
|
||||
|
||||
nfs_co_init_task(client, &task);
|
||||
|
||||
buf = g_malloc(nb_sectors * BDRV_SECTOR_SIZE);
|
||||
buf = g_try_malloc(nb_sectors * BDRV_SECTOR_SIZE);
|
||||
if (nb_sectors && buf == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
qemu_iovec_to_buf(iov, 0, buf, nb_sectors * BDRV_SECTOR_SIZE);
|
||||
|
||||
if (nfs_pwrite_async(client->context, client->fh,
|
||||
|
||||
+5
-1
@@ -105,7 +105,11 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
ret = -EFBIG;
|
||||
goto fail;
|
||||
}
|
||||
s->catalog_bitmap = g_malloc(s->catalog_size * 4);
|
||||
s->catalog_bitmap = g_try_malloc(s->catalog_size * 4);
|
||||
if (s->catalog_size && s->catalog_bitmap == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file, 64, s->catalog_bitmap, s->catalog_size * 4);
|
||||
if (ret < 0) {
|
||||
|
||||
+36
-4
@@ -28,6 +28,13 @@
|
||||
#include "qapi-visit.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/qmp/types.h"
|
||||
#ifdef __linux__
|
||||
#include <linux/fs.h>
|
||||
#include <sys/ioctl.h>
|
||||
#ifndef FS_NOCOW_FL
|
||||
#define FS_NOCOW_FL 0x00800000 /* Do not cow file */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
BlockDeviceInfo *bdrv_block_device_info(BlockDriverState *bs)
|
||||
{
|
||||
@@ -165,19 +172,28 @@ void bdrv_query_image_info(BlockDriverState *bs,
|
||||
ImageInfo **p_info,
|
||||
Error **errp)
|
||||
{
|
||||
uint64_t total_sectors;
|
||||
int64_t size;
|
||||
const char *backing_filename;
|
||||
char backing_filename2[1024];
|
||||
BlockDriverInfo bdi;
|
||||
int ret;
|
||||
Error *err = NULL;
|
||||
ImageInfo *info = g_new0(ImageInfo, 1);
|
||||
ImageInfo *info;
|
||||
#ifdef __linux__
|
||||
int fd, attr;
|
||||
#endif
|
||||
|
||||
bdrv_get_geometry(bs, &total_sectors);
|
||||
size = bdrv_getlength(bs);
|
||||
if (size < 0) {
|
||||
error_setg_errno(errp, -size, "Can't get size of device '%s'",
|
||||
bdrv_get_device_name(bs));
|
||||
return;
|
||||
}
|
||||
|
||||
info = g_new0(ImageInfo, 1);
|
||||
info->filename = g_strdup(bs->filename);
|
||||
info->format = g_strdup(bdrv_get_format_name(bs));
|
||||
info->virtual_size = total_sectors * 512;
|
||||
info->virtual_size = size;
|
||||
info->actual_size = bdrv_get_allocated_file_size(bs);
|
||||
info->has_actual_size = info->actual_size >= 0;
|
||||
if (bdrv_is_encrypted(bs)) {
|
||||
@@ -195,6 +211,18 @@ void bdrv_query_image_info(BlockDriverState *bs,
|
||||
info->format_specific = bdrv_get_specific_info(bs);
|
||||
info->has_format_specific = info->format_specific != NULL;
|
||||
|
||||
#ifdef __linux__
|
||||
/* get NOCOW info */
|
||||
fd = qemu_open(bs->filename, O_RDONLY | O_NONBLOCK);
|
||||
if (fd >= 0) {
|
||||
if (ioctl(fd, FS_IOC_GETFLAGS, &attr) == 0 && (attr & FS_NOCOW_FL)) {
|
||||
info->has_nocow = true;
|
||||
info->nocow = true;
|
||||
}
|
||||
qemu_close(fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
backing_filename = bs->backing_file;
|
||||
if (backing_filename[0] != '\0') {
|
||||
info->backing_filename = g_strdup(backing_filename);
|
||||
@@ -625,4 +653,8 @@ void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
|
||||
func_fprintf(f, "Format specific information:\n");
|
||||
bdrv_image_info_specific_dump(func_fprintf, f, info->format_specific);
|
||||
}
|
||||
|
||||
if (info->has_nocow && info->nocow) {
|
||||
func_fprintf(f, "NOCOW flag: set\n");
|
||||
}
|
||||
}
|
||||
|
||||
+26
-7
@@ -182,7 +182,12 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
s->l1_table_offset = header.l1_table_offset;
|
||||
s->l1_table = g_malloc(s->l1_size * sizeof(uint64_t));
|
||||
s->l1_table = g_try_malloc(s->l1_size * sizeof(uint64_t));
|
||||
if (s->l1_table == NULL) {
|
||||
error_setg(errp, "Could not allocate memory for L1 table");
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table,
|
||||
s->l1_size * sizeof(uint64_t));
|
||||
@@ -193,8 +198,16 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
for(i = 0;i < s->l1_size; i++) {
|
||||
be64_to_cpus(&s->l1_table[i]);
|
||||
}
|
||||
/* alloc L2 cache */
|
||||
s->l2_cache = g_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
|
||||
|
||||
/* alloc L2 cache (max. 64k * 16 * 8 = 8 MB) */
|
||||
s->l2_cache =
|
||||
qemu_try_blockalign(bs->file,
|
||||
s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
|
||||
if (s->l2_cache == NULL) {
|
||||
error_setg(errp, "Could not allocate L2 table cache");
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
s->cluster_cache = g_malloc(s->cluster_size);
|
||||
s->cluster_data = g_malloc(s->cluster_size);
|
||||
s->cluster_cache_offset = -1;
|
||||
@@ -226,7 +239,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
fail:
|
||||
g_free(s->l1_table);
|
||||
g_free(s->l2_cache);
|
||||
qemu_vfree(s->l2_cache);
|
||||
g_free(s->cluster_cache);
|
||||
g_free(s->cluster_data);
|
||||
return ret;
|
||||
@@ -517,7 +530,10 @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
void *orig_buf;
|
||||
|
||||
if (qiov->niov > 1) {
|
||||
buf = orig_buf = qemu_blockalign(bs, qiov->size);
|
||||
buf = orig_buf = qemu_try_blockalign(bs, qiov->size);
|
||||
if (buf == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
} else {
|
||||
orig_buf = NULL;
|
||||
buf = (uint8_t *)qiov->iov->iov_base;
|
||||
@@ -619,7 +635,10 @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
s->cluster_cache_offset = -1; /* disable compressed cache */
|
||||
|
||||
if (qiov->niov > 1) {
|
||||
buf = orig_buf = qemu_blockalign(bs, qiov->size);
|
||||
buf = orig_buf = qemu_try_blockalign(bs, qiov->size);
|
||||
if (buf == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
qemu_iovec_to_buf(qiov, 0, buf, qiov->size);
|
||||
} else {
|
||||
orig_buf = NULL;
|
||||
@@ -685,7 +704,7 @@ static void qcow_close(BlockDriverState *bs)
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
|
||||
g_free(s->l1_table);
|
||||
g_free(s->l2_cache);
|
||||
qemu_vfree(s->l2_cache);
|
||||
g_free(s->cluster_cache);
|
||||
g_free(s->cluster_data);
|
||||
|
||||
|
||||
+12
-1
@@ -53,10 +53,21 @@ Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables)
|
||||
c->entries = g_malloc0(sizeof(*c->entries) * num_tables);
|
||||
|
||||
for (i = 0; i < c->size; i++) {
|
||||
c->entries[i].table = qemu_blockalign(bs, s->cluster_size);
|
||||
c->entries[i].table = qemu_try_blockalign(bs->file, s->cluster_size);
|
||||
if (c->entries[i].table == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
|
||||
fail:
|
||||
for (i = 0; i < c->size; i++) {
|
||||
qemu_vfree(c->entries[i].table);
|
||||
}
|
||||
g_free(c->entries);
|
||||
g_free(c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c)
|
||||
|
||||
+39
-8
@@ -72,14 +72,20 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
||||
#endif
|
||||
|
||||
new_l1_size2 = sizeof(uint64_t) * new_l1_size;
|
||||
new_l1_table = g_malloc0(align_offset(new_l1_size2, 512));
|
||||
new_l1_table = qemu_try_blockalign(bs->file,
|
||||
align_offset(new_l1_size2, 512));
|
||||
if (new_l1_table == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(new_l1_table, 0, align_offset(new_l1_size2, 512));
|
||||
|
||||
memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
|
||||
|
||||
/* write new table (align to cluster) */
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ALLOC_TABLE);
|
||||
new_l1_table_offset = qcow2_alloc_clusters(bs, new_l1_size2);
|
||||
if (new_l1_table_offset < 0) {
|
||||
g_free(new_l1_table);
|
||||
qemu_vfree(new_l1_table);
|
||||
return new_l1_table_offset;
|
||||
}
|
||||
|
||||
@@ -113,7 +119,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
g_free(s->l1_table);
|
||||
qemu_vfree(s->l1_table);
|
||||
old_l1_table_offset = s->l1_table_offset;
|
||||
s->l1_table_offset = new_l1_table_offset;
|
||||
s->l1_table = new_l1_table;
|
||||
@@ -123,7 +129,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
||||
QCOW2_DISCARD_OTHER);
|
||||
return 0;
|
||||
fail:
|
||||
g_free(new_l1_table);
|
||||
qemu_vfree(new_l1_table);
|
||||
qcow2_free_clusters(bs, new_l1_table_offset, new_l1_size2,
|
||||
QCOW2_DISCARD_OTHER);
|
||||
return ret;
|
||||
@@ -372,7 +378,10 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
iov.iov_len = n * BDRV_SECTOR_SIZE;
|
||||
iov.iov_base = qemu_blockalign(bs, iov.iov_len);
|
||||
iov.iov_base = qemu_try_blockalign(bs, iov.iov_len);
|
||||
if (iov.iov_base == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||
|
||||
@@ -702,7 +711,11 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
|
||||
trace_qcow2_cluster_link_l2(qemu_coroutine_self(), m->nb_clusters);
|
||||
assert(m->nb_clusters > 0);
|
||||
|
||||
old_cluster = g_malloc(m->nb_clusters * sizeof(uint64_t));
|
||||
old_cluster = g_try_malloc(m->nb_clusters * sizeof(uint64_t));
|
||||
if (old_cluster == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* copy content of unmodified sectors */
|
||||
ret = perform_cow(bs, m, &m->cow_start);
|
||||
@@ -1106,6 +1119,17 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* !*host_offset would overwrite the image header and is reserved for "no
|
||||
* host offset preferred". If 0 was a valid host offset, it'd trigger the
|
||||
* following overlap check; do that now to avoid having an invalid value in
|
||||
* *host_offset. */
|
||||
if (!alloc_cluster_offset) {
|
||||
ret = qcow2_pre_write_overlap_check(bs, 0, alloc_cluster_offset,
|
||||
nb_clusters * s->cluster_size);
|
||||
assert(ret < 0);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save info needed for meta data update.
|
||||
*
|
||||
@@ -1562,7 +1586,10 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
||||
if (!is_active_l1) {
|
||||
/* inactive L2 tables require a buffer to be stored in when loading
|
||||
* them from disk */
|
||||
l2_table = qemu_blockalign(bs, s->cluster_size);
|
||||
l2_table = qemu_try_blockalign(bs->file, s->cluster_size);
|
||||
if (l2_table == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < l1_size; i++) {
|
||||
@@ -1740,7 +1767,11 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs)
|
||||
|
||||
nb_clusters = size_to_clusters(s, bs->file->total_sectors *
|
||||
BDRV_SECTOR_SIZE);
|
||||
expanded_clusters = g_malloc0((nb_clusters + 7) / 8);
|
||||
expanded_clusters = g_try_malloc0((nb_clusters + 7) / 8);
|
||||
if (expanded_clusters == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = expand_zero_clusters_in_l1(bs, s->l1_table, s->l1_size,
|
||||
&expanded_clusters, &nb_clusters);
|
||||
|
||||
+42
-12
@@ -46,19 +46,25 @@ int qcow2_refcount_init(BlockDriverState *bs)
|
||||
|
||||
assert(s->refcount_table_size <= INT_MAX / sizeof(uint64_t));
|
||||
refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);
|
||||
s->refcount_table = g_malloc(refcount_table_size2);
|
||||
s->refcount_table = g_try_malloc(refcount_table_size2);
|
||||
|
||||
if (s->refcount_table_size > 0) {
|
||||
if (s->refcount_table == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_LOAD);
|
||||
ret = bdrv_pread(bs->file, s->refcount_table_offset,
|
||||
s->refcount_table, refcount_table_size2);
|
||||
if (ret != refcount_table_size2)
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
for(i = 0; i < s->refcount_table_size; i++)
|
||||
be64_to_cpus(&s->refcount_table[i]);
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
return -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void qcow2_refcount_close(BlockDriverState *bs)
|
||||
@@ -344,8 +350,14 @@ static int alloc_refcount_block(BlockDriverState *bs,
|
||||
uint64_t meta_offset = (blocks_used * refcount_block_clusters) *
|
||||
s->cluster_size;
|
||||
uint64_t table_offset = meta_offset + blocks_clusters * s->cluster_size;
|
||||
uint16_t *new_blocks = g_malloc0(blocks_clusters * s->cluster_size);
|
||||
uint64_t *new_table = g_malloc0(table_size * sizeof(uint64_t));
|
||||
uint64_t *new_table = g_try_malloc0(table_size * sizeof(uint64_t));
|
||||
uint16_t *new_blocks = g_try_malloc0(blocks_clusters * s->cluster_size);
|
||||
|
||||
assert(table_size > 0 && blocks_clusters > 0);
|
||||
if (new_table == NULL || new_blocks == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_table;
|
||||
}
|
||||
|
||||
/* Fill the new refcount table */
|
||||
memcpy(new_table, s->refcount_table,
|
||||
@@ -424,6 +436,7 @@ static int alloc_refcount_block(BlockDriverState *bs,
|
||||
return -EAGAIN;
|
||||
|
||||
fail_table:
|
||||
g_free(new_blocks);
|
||||
g_free(new_table);
|
||||
fail_block:
|
||||
if (*refcount_block != NULL) {
|
||||
@@ -847,7 +860,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||
int64_t l1_table_offset, int l1_size, int addend)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated;
|
||||
uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2;
|
||||
bool l1_allocated = false;
|
||||
int64_t old_offset, old_l2_offset;
|
||||
int i, j, l1_modified = 0, nb_csectors, refcount;
|
||||
int ret;
|
||||
@@ -862,8 +876,12 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||
* l1_table_offset when it is the current s->l1_table_offset! Be careful
|
||||
* when changing this! */
|
||||
if (l1_table_offset != s->l1_table_offset) {
|
||||
l1_table = g_malloc0(align_offset(l1_size2, 512));
|
||||
l1_allocated = 1;
|
||||
l1_table = g_try_malloc0(align_offset(l1_size2, 512));
|
||||
if (l1_size2 && l1_table == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
l1_allocated = true;
|
||||
|
||||
ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size2);
|
||||
if (ret < 0) {
|
||||
@@ -875,7 +893,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||
} else {
|
||||
assert(l1_size == s->l1_size);
|
||||
l1_table = s->l1_table;
|
||||
l1_allocated = 0;
|
||||
l1_allocated = false;
|
||||
}
|
||||
|
||||
for(i = 0; i < l1_size; i++) {
|
||||
@@ -1197,7 +1215,11 @@ static int check_refcounts_l1(BlockDriverState *bs,
|
||||
if (l1_size2 == 0) {
|
||||
l1_table = NULL;
|
||||
} else {
|
||||
l1_table = g_malloc(l1_size2);
|
||||
l1_table = g_try_malloc(l1_size2);
|
||||
if (l1_table == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
if (bdrv_pread(bs->file, l1_table_offset,
|
||||
l1_table, l1_size2) != l1_size2)
|
||||
goto fail;
|
||||
@@ -1501,7 +1523,11 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
return -EFBIG;
|
||||
}
|
||||
|
||||
refcount_table = g_malloc0(nb_clusters * sizeof(uint16_t));
|
||||
refcount_table = g_try_malloc0(nb_clusters * sizeof(uint16_t));
|
||||
if (nb_clusters && refcount_table == NULL) {
|
||||
res->check_errors++;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res->bfi.total_clusters =
|
||||
size_to_clusters(s, bs->total_sectors * BDRV_SECTOR_SIZE);
|
||||
@@ -1753,9 +1779,13 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
|
||||
uint64_t l1_ofs = s->snapshots[i].l1_table_offset;
|
||||
uint32_t l1_sz = s->snapshots[i].l1_size;
|
||||
uint64_t l1_sz2 = l1_sz * sizeof(uint64_t);
|
||||
uint64_t *l1 = g_malloc(l1_sz2);
|
||||
uint64_t *l1 = g_try_malloc(l1_sz2);
|
||||
int ret;
|
||||
|
||||
if (l1_sz2 && l1 == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file, l1_ofs, l1, l1_sz2);
|
||||
if (ret < 0) {
|
||||
g_free(l1);
|
||||
|
||||
+18
-5
@@ -381,7 +381,12 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
sn->l1_table_offset = l1_table_offset;
|
||||
sn->l1_size = s->l1_size;
|
||||
|
||||
l1_table = g_malloc(s->l1_size * sizeof(uint64_t));
|
||||
l1_table = g_try_malloc(s->l1_size * sizeof(uint64_t));
|
||||
if (s->l1_size && l1_table == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for(i = 0; i < s->l1_size; i++) {
|
||||
l1_table[i] = cpu_to_be64(s->l1_table[i]);
|
||||
}
|
||||
@@ -499,7 +504,11 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
||||
* Decrease the refcount referenced by the old one only when the L1
|
||||
* table is overwritten.
|
||||
*/
|
||||
sn_l1_table = g_malloc0(cur_l1_bytes);
|
||||
sn_l1_table = g_try_malloc0(cur_l1_bytes);
|
||||
if (cur_l1_bytes && sn_l1_table == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file, sn->l1_table_offset, sn_l1_table, sn_l1_bytes);
|
||||
if (ret < 0) {
|
||||
@@ -698,17 +707,21 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
|
||||
return -EFBIG;
|
||||
}
|
||||
new_l1_bytes = sn->l1_size * sizeof(uint64_t);
|
||||
new_l1_table = g_malloc0(align_offset(new_l1_bytes, 512));
|
||||
new_l1_table = qemu_try_blockalign(bs->file,
|
||||
align_offset(new_l1_bytes, 512));
|
||||
if (new_l1_table == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file, sn->l1_table_offset, new_l1_table, new_l1_bytes);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Failed to read l1 table for snapshot");
|
||||
g_free(new_l1_table);
|
||||
qemu_vfree(new_l1_table);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Switch the L1 table */
|
||||
g_free(s->l1_table);
|
||||
qemu_vfree(s->l1_table);
|
||||
|
||||
s->l1_size = sn->l1_size;
|
||||
s->l1_table_offset = sn->l1_table_offset;
|
||||
|
||||
+35
-10
@@ -688,8 +688,13 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
|
||||
if (s->l1_size > 0) {
|
||||
s->l1_table = g_malloc0(
|
||||
s->l1_table = qemu_try_blockalign(bs->file,
|
||||
align_offset(s->l1_size * sizeof(uint64_t), 512));
|
||||
if (s->l1_table == NULL) {
|
||||
error_setg(errp, "Could not allocate L1 table");
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table,
|
||||
s->l1_size * sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
@@ -704,11 +709,22 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
/* alloc L2 table/refcount block cache */
|
||||
s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE);
|
||||
s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE);
|
||||
if (s->l2_table_cache == NULL || s->refcount_block_cache == NULL) {
|
||||
error_setg(errp, "Could not allocate metadata caches");
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
s->cluster_cache = g_malloc(s->cluster_size);
|
||||
/* one more sector for decompressed data alignment */
|
||||
s->cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size
|
||||
+ 512);
|
||||
s->cluster_data = qemu_try_blockalign(bs->file, QCOW_MAX_CRYPT_CLUSTERS
|
||||
* s->cluster_size + 512);
|
||||
if (s->cluster_data == NULL) {
|
||||
error_setg(errp, "Could not allocate temporary cluster buffer");
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
s->cluster_cache_offset = -1;
|
||||
s->flags = flags;
|
||||
|
||||
@@ -852,7 +868,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
cleanup_unknown_header_ext(bs);
|
||||
qcow2_free_snapshots(bs);
|
||||
qcow2_refcount_close(bs);
|
||||
g_free(s->l1_table);
|
||||
qemu_vfree(s->l1_table);
|
||||
/* else pre-write overlap checks in cache_destroy may crash */
|
||||
s->l1_table = NULL;
|
||||
if (s->l2_table_cache) {
|
||||
@@ -1082,7 +1098,12 @@ static coroutine_fn int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
*/
|
||||
if (!cluster_data) {
|
||||
cluster_data =
|
||||
qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
|
||||
qemu_try_blockalign(bs->file, QCOW_MAX_CRYPT_CLUSTERS
|
||||
* s->cluster_size);
|
||||
if (cluster_data == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
assert(cur_nr_sectors <=
|
||||
@@ -1182,8 +1203,13 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
|
||||
|
||||
if (s->crypt_method) {
|
||||
if (!cluster_data) {
|
||||
cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS *
|
||||
s->cluster_size);
|
||||
cluster_data = qemu_try_blockalign(bs->file,
|
||||
QCOW_MAX_CRYPT_CLUSTERS
|
||||
* s->cluster_size);
|
||||
if (cluster_data == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
assert(hd_qiov.size <=
|
||||
@@ -1270,7 +1296,7 @@ fail:
|
||||
static void qcow2_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
g_free(s->l1_table);
|
||||
qemu_vfree(s->l1_table);
|
||||
/* else pre-write overlap checks in cache_destroy may crash */
|
||||
s->l1_table = NULL;
|
||||
|
||||
@@ -1557,7 +1583,7 @@ static int preallocate(BlockDriverState *bs)
|
||||
int ret;
|
||||
QCowL2Meta *meta;
|
||||
|
||||
nb_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
|
||||
nb_sectors = bdrv_nb_sectors(bs);
|
||||
offset = 0;
|
||||
|
||||
while (nb_sectors) {
|
||||
@@ -1947,7 +1973,6 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
||||
/* align end of file to a sector boundary to ease reading with
|
||||
sector based I/Os */
|
||||
cluster_offset = bdrv_getlength(bs->file);
|
||||
cluster_offset = (cluster_offset + 511) & ~511;
|
||||
bdrv_truncate(bs->file, cluster_offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user