Block patches
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJTYT60AAoJEH8JsnLIjy/WQIoP/2n2/YoSOgtv3IwV1YdjzmLK fAVYhkZz+ElvMuoM/Mj9k1VEYlIImCrx2Y8vwLEM0tDbRa4+J2vORAOgt4EaY2G7 OxEQoxdX380Cug94pJtupGhZmvkLPa/slnoOHoL2X1IfhD52k0xORVRPFy4nSaV0 f2zOjhPNHCE5ZOnHZshgUjtPUqglJlsBKBlWnXE0EZLBk0jbZO0oRWNEtXZRS3Tp GQQEqtG46gEuGJcJ6F1f9bDCLJ6KAdCmHMK3weY7niDSem84p35I76xfM/oGHYmb Y5CgQXDys2STXshw9mAeSUfn4QfYW9JZvQAWGrTYM/y4/hbQKsi8jfbqSYinWcjm qfBH/nEAqKGgVEmQ4jLlWIa7/Lr0WsirdZZmhBXZcgkfg6+gUP6uw+kDJprqd385 45mVu1AldLKVV4jBhAahuSLGdv8CErndGqVckVHaSPtl4XJxhZmemPJB4JAbczdM LZiQwRuVeYZC+ssQotr2ov5pzWg3n6IzFW6Zt0T7YWmluOAy9vTfm29IdUV7nxKl Ht6sm4vLLMtB3snHvLdpTOAXxTJ66J2IqpRGhIgNu71dKLjFU5IEgj5oddw38iiG sY2CA6DfWSwRmPfaVsH/F8o/T0vONQ9SrX40459UNADm81qvu70IuR8cr8b4xKXX vC9SwuNBO1upONNkX/4B =VH6g -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging Block patches # gpg: Signature made Wed 30 Apr 2014 19:19:32 BST using RSA key ID C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" * remotes/kevin/tags/for-upstream: (31 commits) curl: Fix hang reading from slow connections curl: Ensure all informationals are checked for completion curl: Eliminate unnecessary use of curl_multi_socket_all curl: Remove unnecessary explicit calls to internal event handler curl: Remove erroneous sleep waiting for curl completion curl: Fix return from curl_read_cb with invalid state curl: Remove unnecessary use of goto curl: Fix long line block/vdi: Error out immediately in vdi_create() block/bochs: Fix error handling for seek_to_sector() qcow2: Check min_size in qcow2_grow_l1_table() qcow2: Catch bdrv_getlength() error block: Use correct width in format strings qcow2: Avoid overflow in alloc_clusters_noref() block: Use error_abort in bdrv_image_info_specific_dump() block: Fix open_flags in bdrv_reopen() Revert "block: another bdrv_append fix" block: Unlink temporary files in raw-posix/win32 block: Remove BDRV_O_COPY_ON_READ for bs->file block: Create bdrv_backing_flags() ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
e50bf23438
108
block.c
108
block.c
@ -774,6 +774,45 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs)
|
||||
bs->copy_on_read--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the flags that bs->file should get, based on the given flags for
|
||||
* the parent BDS
|
||||
*/
|
||||
static int bdrv_inherited_flags(int flags)
|
||||
{
|
||||
/* Enable protocol handling, disable format probing for bs->file */
|
||||
flags |= BDRV_O_PROTOCOL;
|
||||
|
||||
/* Our block drivers take care to send flushes and respect unmap policy,
|
||||
* so we can enable both unconditionally on lower layers. */
|
||||
flags |= BDRV_O_CACHE_WB | BDRV_O_UNMAP;
|
||||
|
||||
/* The backing file of a temporary snapshot is read-only */
|
||||
if (flags & BDRV_O_SNAPSHOT) {
|
||||
flags &= ~BDRV_O_RDWR;
|
||||
}
|
||||
|
||||
/* Clear flags that only apply to the top layer */
|
||||
flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the flags that bs->backing_hd should get, based on the given flags
|
||||
* for the parent BDS
|
||||
*/
|
||||
static int bdrv_backing_flags(int flags)
|
||||
{
|
||||
/* backing files always opened read-only */
|
||||
flags &= ~(BDRV_O_RDWR | BDRV_O_COPY_ON_READ);
|
||||
|
||||
/* snapshot=on is handled on the top layer */
|
||||
flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_TEMPORARY);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int bdrv_open_flags(BlockDriverState *bs, int flags)
|
||||
{
|
||||
int open_flags = flags | BDRV_O_CACHE_WB;
|
||||
@ -792,7 +831,7 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
|
||||
/*
|
||||
* Snapshots should be writable.
|
||||
*/
|
||||
if (bs->is_temporary) {
|
||||
if (flags & BDRV_O_TEMPORARY) {
|
||||
open_flags |= BDRV_O_RDWR;
|
||||
}
|
||||
|
||||
@ -951,13 +990,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
||||
bdrv_refresh_limits(bs);
|
||||
assert(bdrv_opt_mem_align(bs) != 0);
|
||||
assert((bs->request_alignment != 0) || bs->sg);
|
||||
|
||||
#ifndef _WIN32
|
||||
if (bs->is_temporary) {
|
||||
assert(bs->filename[0] != '\0');
|
||||
unlink(bs->filename);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
free_and_fail:
|
||||
@ -1069,7 +1101,7 @@ fail:
|
||||
int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
||||
{
|
||||
char *backing_filename = g_malloc0(PATH_MAX);
|
||||
int back_flags, ret = 0;
|
||||
int ret = 0;
|
||||
BlockDriver *back_drv = NULL;
|
||||
Error *local_err = NULL;
|
||||
|
||||
@ -1097,14 +1129,10 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
||||
back_drv = bdrv_find_format(bs->backing_format);
|
||||
}
|
||||
|
||||
/* backing files always opened read-only */
|
||||
back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT |
|
||||
BDRV_O_COPY_ON_READ);
|
||||
|
||||
assert(bs->backing_hd == NULL);
|
||||
ret = bdrv_open(&bs->backing_hd,
|
||||
*backing_filename ? backing_filename : NULL, NULL, options,
|
||||
back_flags, back_drv, &local_err);
|
||||
bdrv_backing_flags(bs->open_flags), back_drv, &local_err);
|
||||
if (ret < 0) {
|
||||
bs->backing_hd = NULL;
|
||||
bs->open_flags |= BDRV_O_NO_BACKING;
|
||||
@ -1232,10 +1260,10 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
|
||||
qstring_from_str(tmp_filename));
|
||||
|
||||
bs_snapshot = bdrv_new("", &error_abort);
|
||||
bs_snapshot->is_temporary = 1;
|
||||
|
||||
ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
|
||||
bs->open_flags & ~BDRV_O_SNAPSHOT, bdrv_qcow2, &local_err);
|
||||
(bs->open_flags & ~BDRV_O_SNAPSHOT) | BDRV_O_TEMPORARY,
|
||||
bdrv_qcow2, &local_err);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
goto out;
|
||||
@ -1333,10 +1361,10 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||
|
||||
assert(file == NULL);
|
||||
ret = bdrv_open_image(&file, filename, options, "file",
|
||||
bdrv_open_flags(bs, flags | BDRV_O_UNMAP) |
|
||||
BDRV_O_PROTOCOL, true, &local_err);
|
||||
bdrv_inherited_flags(flags),
|
||||
true, &local_err);
|
||||
if (ret < 0) {
|
||||
goto unlink_and_fail;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Find the right image format driver */
|
||||
@ -1347,7 +1375,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||
if (!drv) {
|
||||
error_setg(errp, "Invalid driver: '%s'", drvname);
|
||||
ret = -EINVAL;
|
||||
goto unlink_and_fail;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1357,18 +1385,18 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||
} else {
|
||||
error_setg(errp, "Must specify either driver or file");
|
||||
ret = -EINVAL;
|
||||
goto unlink_and_fail;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!drv) {
|
||||
goto unlink_and_fail;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Open the image */
|
||||
ret = bdrv_open_common(bs, file, options, flags, drv, &local_err);
|
||||
if (ret < 0) {
|
||||
goto unlink_and_fail;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (file && (bs->file != file)) {
|
||||
@ -1430,14 +1458,10 @@ done:
|
||||
*pbs = bs;
|
||||
return 0;
|
||||
|
||||
unlink_and_fail:
|
||||
fail:
|
||||
if (file != NULL) {
|
||||
bdrv_unref(file);
|
||||
}
|
||||
if (bs->is_temporary) {
|
||||
unlink(filename);
|
||||
}
|
||||
fail:
|
||||
QDECREF(bs->options);
|
||||
QDECREF(options);
|
||||
bs->options = NULL;
|
||||
@ -1501,8 +1525,11 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
|
||||
QSIMPLEQ_INIT(bs_queue);
|
||||
}
|
||||
|
||||
/* bdrv_open() masks this flag out */
|
||||
flags &= ~BDRV_O_PROTOCOL;
|
||||
|
||||
if (bs->file) {
|
||||
bdrv_reopen_queue(bs_queue, bs->file, flags);
|
||||
bdrv_reopen_queue(bs_queue, bs->file, bdrv_inherited_flags(flags));
|
||||
}
|
||||
|
||||
bs_entry = g_new0(BlockReopenQueueEntry, 1);
|
||||
@ -1717,11 +1744,6 @@ void bdrv_close(BlockDriverState *bs)
|
||||
}
|
||||
bs->drv->bdrv_close(bs);
|
||||
g_free(bs->opaque);
|
||||
#ifdef _WIN32
|
||||
if (bs->is_temporary) {
|
||||
unlink(bs->filename);
|
||||
}
|
||||
#endif
|
||||
bs->opaque = NULL;
|
||||
bs->drv = NULL;
|
||||
bs->copy_on_read = 0;
|
||||
@ -1845,7 +1867,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
|
||||
BlockDriverState *bs_src)
|
||||
{
|
||||
/* move some fields that need to stay attached to the device */
|
||||
bs_dest->open_flags = bs_src->open_flags;
|
||||
|
||||
/* dev info */
|
||||
bs_dest->dev_ops = bs_src->dev_ops;
|
||||
@ -3601,10 +3622,25 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
|
||||
void *opaque)
|
||||
{
|
||||
BlockDriver *drv;
|
||||
int count = 0;
|
||||
const char **formats = NULL;
|
||||
|
||||
QLIST_FOREACH(drv, &bdrv_drivers, list) {
|
||||
it(opaque, drv->format_name);
|
||||
if (drv->format_name) {
|
||||
bool found = false;
|
||||
int i = count;
|
||||
while (formats && i && !found) {
|
||||
found = !strcmp(formats[--i], drv->format_name);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
formats = g_realloc(formats, (count + 1) * sizeof(char *));
|
||||
formats[count++] = drv->format_name;
|
||||
it(opaque, drv->format_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
g_free(formats);
|
||||
}
|
||||
|
||||
/* This function is to find block backend bs */
|
||||
|
@ -187,13 +187,14 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
|
||||
uint64_t offset = sector_num * 512;
|
||||
uint64_t extent_index, extent_offset, bitmap_offset;
|
||||
char bitmap_entry;
|
||||
int ret;
|
||||
|
||||
// seek to sector
|
||||
extent_index = offset / s->extent_size;
|
||||
extent_offset = (offset % s->extent_size) / 512;
|
||||
|
||||
if (s->catalog_bitmap[extent_index] == 0xffffffff) {
|
||||
return -1; /* not allocated */
|
||||
return 0; /* not allocated */
|
||||
}
|
||||
|
||||
bitmap_offset = s->data_offset +
|
||||
@ -201,13 +202,14 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
|
||||
(s->extent_blocks + s->bitmap_blocks));
|
||||
|
||||
/* read in bitmap for current extent */
|
||||
if (bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
|
||||
&bitmap_entry, 1) != 1) {
|
||||
return -1;
|
||||
ret = bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
|
||||
&bitmap_entry, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!((bitmap_entry >> (extent_offset % 8)) & 1)) {
|
||||
return -1; /* not allocated */
|
||||
return 0; /* not allocated */
|
||||
}
|
||||
|
||||
return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
|
||||
@ -220,13 +222,16 @@ static int bochs_read(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
while (nb_sectors > 0) {
|
||||
int64_t block_offset = seek_to_sector(bs, sector_num);
|
||||
if (block_offset >= 0) {
|
||||
if (block_offset < 0) {
|
||||
return block_offset;
|
||||
} else if (block_offset > 0) {
|
||||
ret = bdrv_pread(bs->file, block_offset, buf, 512);
|
||||
if (ret != 512) {
|
||||
return -1;
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
memset(buf, 0, 512);
|
||||
}
|
||||
nb_sectors--;
|
||||
sector_num++;
|
||||
buf += 512;
|
||||
|
@ -82,7 +82,7 @@ static int cow_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
if (be32_to_cpu(cow_header.version) != COW_VERSION) {
|
||||
char version[64];
|
||||
snprintf(version, sizeof(version),
|
||||
"COW version %d", cow_header.version);
|
||||
"COW version %" PRIu32, cow_header.version);
|
||||
error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
|
||||
bs->device_name, "cow", version);
|
||||
ret = -ENOTSUP;
|
||||
|
147
block/curl.c
147
block/curl.c
@ -71,6 +71,7 @@ typedef struct CURLState
|
||||
struct BDRVCURLState *s;
|
||||
CURLAIOCB *acb[CURL_NUM_ACB];
|
||||
CURL *curl;
|
||||
curl_socket_t sock_fd;
|
||||
char *orig_buf;
|
||||
size_t buf_start;
|
||||
size_t buf_off;
|
||||
@ -92,6 +93,7 @@ typedef struct BDRVCURLState {
|
||||
|
||||
static void curl_clean_state(CURLState *s);
|
||||
static void curl_multi_do(void *arg);
|
||||
static void curl_multi_read(void *arg);
|
||||
|
||||
#ifdef NEED_CURL_TIMER_CALLBACK
|
||||
static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
|
||||
@ -113,16 +115,20 @@ static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
|
||||
static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
|
||||
void *s, void *sp)
|
||||
{
|
||||
CURLState *state = NULL;
|
||||
curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state);
|
||||
state->sock_fd = fd;
|
||||
|
||||
DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd);
|
||||
switch (action) {
|
||||
case CURL_POLL_IN:
|
||||
qemu_aio_set_fd_handler(fd, curl_multi_do, NULL, s);
|
||||
qemu_aio_set_fd_handler(fd, curl_multi_read, NULL, state);
|
||||
break;
|
||||
case CURL_POLL_OUT:
|
||||
qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, s);
|
||||
qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, state);
|
||||
break;
|
||||
case CURL_POLL_INOUT:
|
||||
qemu_aio_set_fd_handler(fd, curl_multi_do, curl_multi_do, s);
|
||||
qemu_aio_set_fd_handler(fd, curl_multi_read, curl_multi_do, state);
|
||||
break;
|
||||
case CURL_POLL_REMOVE:
|
||||
qemu_aio_set_fd_handler(fd, NULL, NULL, NULL);
|
||||
@ -155,7 +161,7 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
|
||||
DPRINTF("CURL: Just reading %zd bytes\n", realsize);
|
||||
|
||||
if (!s || !s->orig_buf)
|
||||
goto read_end;
|
||||
return 0;
|
||||
|
||||
if (s->buf_off >= s->buf_len) {
|
||||
/* buffer full, read nothing */
|
||||
@ -180,7 +186,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
read_end:
|
||||
return realsize;
|
||||
}
|
||||
|
||||
@ -215,7 +220,8 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
|
||||
}
|
||||
|
||||
// Wait for unfinished chunks
|
||||
if ((start >= state->buf_start) &&
|
||||
if (state->in_use &&
|
||||
(start >= state->buf_start) &&
|
||||
(start <= buf_fend) &&
|
||||
(end >= state->buf_start) &&
|
||||
(end <= buf_fend))
|
||||
@ -237,68 +243,69 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
|
||||
return FIND_RET_NONE;
|
||||
}
|
||||
|
||||
static void curl_multi_read(BDRVCURLState *s)
|
||||
static void curl_multi_check_completion(BDRVCURLState *s)
|
||||
{
|
||||
int msgs_in_queue;
|
||||
|
||||
/* Try to find done transfers, so we can free the easy
|
||||
* handle again. */
|
||||
do {
|
||||
for (;;) {
|
||||
CURLMsg *msg;
|
||||
msg = curl_multi_info_read(s->multi, &msgs_in_queue);
|
||||
|
||||
/* Quit when there are no more completions */
|
||||
if (!msg)
|
||||
break;
|
||||
if (msg->msg == CURLMSG_NONE)
|
||||
break;
|
||||
|
||||
switch (msg->msg) {
|
||||
case CURLMSG_DONE:
|
||||
{
|
||||
CURLState *state = NULL;
|
||||
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char**)&state);
|
||||
if (msg->msg == CURLMSG_DONE) {
|
||||
CURLState *state = NULL;
|
||||
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE,
|
||||
(char **)&state);
|
||||
|
||||
/* ACBs for successful messages get completed in curl_read_cb */
|
||||
if (msg->data.result != CURLE_OK) {
|
||||
int i;
|
||||
for (i = 0; i < CURL_NUM_ACB; i++) {
|
||||
CURLAIOCB *acb = state->acb[i];
|
||||
/* ACBs for successful messages get completed in curl_read_cb */
|
||||
if (msg->data.result != CURLE_OK) {
|
||||
int i;
|
||||
for (i = 0; i < CURL_NUM_ACB; i++) {
|
||||
CURLAIOCB *acb = state->acb[i];
|
||||
|
||||
if (acb == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
acb->common.cb(acb->common.opaque, -EIO);
|
||||
qemu_aio_release(acb);
|
||||
state->acb[i] = NULL;
|
||||
if (acb == NULL) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
curl_clean_state(state);
|
||||
break;
|
||||
acb->common.cb(acb->common.opaque, -EIO);
|
||||
qemu_aio_release(acb);
|
||||
state->acb[i] = NULL;
|
||||
}
|
||||
}
|
||||
default:
|
||||
msgs_in_queue = 0;
|
||||
break;
|
||||
|
||||
curl_clean_state(state);
|
||||
break;
|
||||
}
|
||||
} while(msgs_in_queue);
|
||||
}
|
||||
}
|
||||
|
||||
static void curl_multi_do(void *arg)
|
||||
{
|
||||
BDRVCURLState *s = (BDRVCURLState *)arg;
|
||||
CURLState *s = (CURLState *)arg;
|
||||
int running;
|
||||
int r;
|
||||
|
||||
if (!s->multi) {
|
||||
if (!s->s->multi) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
r = curl_multi_socket_all(s->multi, &running);
|
||||
r = curl_multi_socket_action(s->s->multi, s->sock_fd, 0, &running);
|
||||
} while(r == CURLM_CALL_MULTI_PERFORM);
|
||||
|
||||
curl_multi_read(s);
|
||||
}
|
||||
|
||||
static void curl_multi_read(void *arg)
|
||||
{
|
||||
CURLState *s = (CURLState *)arg;
|
||||
|
||||
curl_multi_do(arg);
|
||||
curl_multi_check_completion(s->s);
|
||||
}
|
||||
|
||||
static void curl_multi_timeout_do(void *arg)
|
||||
@ -313,7 +320,7 @@ static void curl_multi_timeout_do(void *arg)
|
||||
|
||||
curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
|
||||
|
||||
curl_multi_read(s);
|
||||
curl_multi_check_completion(s);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
@ -337,44 +344,42 @@ static CURLState *curl_init_state(BDRVCURLState *s)
|
||||
break;
|
||||
}
|
||||
if (!state) {
|
||||
g_usleep(100);
|
||||
curl_multi_do(s);
|
||||
qemu_aio_wait();
|
||||
}
|
||||
} while(!state);
|
||||
|
||||
if (state->curl)
|
||||
goto has_curl;
|
||||
if (!state->curl) {
|
||||
state->curl = curl_easy_init();
|
||||
if (!state->curl) {
|
||||
return NULL;
|
||||
}
|
||||
curl_easy_setopt(state->curl, CURLOPT_URL, s->url);
|
||||
curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5);
|
||||
curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION,
|
||||
(void *)curl_read_cb);
|
||||
curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state);
|
||||
curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state);
|
||||
curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1);
|
||||
curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg);
|
||||
curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1);
|
||||
|
||||
state->curl = curl_easy_init();
|
||||
if (!state->curl)
|
||||
return NULL;
|
||||
curl_easy_setopt(state->curl, CURLOPT_URL, s->url);
|
||||
curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5);
|
||||
curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, (void *)curl_read_cb);
|
||||
curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state);
|
||||
curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state);
|
||||
curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1);
|
||||
curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg);
|
||||
curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1);
|
||||
|
||||
/* Restrict supported protocols to avoid security issues in the more
|
||||
* obscure protocols. For example, do not allow POP3/SMTP/IMAP see
|
||||
* CVE-2013-0249.
|
||||
*
|
||||
* Restricting protocols is only supported from 7.19.4 upwards.
|
||||
*/
|
||||
/* Restrict supported protocols to avoid security issues in the more
|
||||
* obscure protocols. For example, do not allow POP3/SMTP/IMAP see
|
||||
* CVE-2013-0249.
|
||||
*
|
||||
* Restricting protocols is only supported from 7.19.4 upwards.
|
||||
*/
|
||||
#if LIBCURL_VERSION_NUM >= 0x071304
|
||||
curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS);
|
||||
curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS);
|
||||
curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS);
|
||||
curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_VERBOSE
|
||||
curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1);
|
||||
curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1);
|
||||
#endif
|
||||
|
||||
has_curl:
|
||||
}
|
||||
|
||||
state->s = s;
|
||||
|
||||
@ -531,13 +536,11 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
// initialize the multi interface!
|
||||
|
||||
s->multi = curl_multi_init();
|
||||
curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, s);
|
||||
curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
|
||||
#ifdef NEED_CURL_TIMER_CALLBACK
|
||||
curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
|
||||
curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
|
||||
#endif
|
||||
curl_multi_do(s);
|
||||
|
||||
qemu_opts_del(opts);
|
||||
return 0;
|
||||
@ -566,6 +569,7 @@ static const AIOCBInfo curl_aiocb_info = {
|
||||
static void curl_readv_bh_cb(void *p)
|
||||
{
|
||||
CURLState *state;
|
||||
int running;
|
||||
|
||||
CURLAIOCB *acb = p;
|
||||
BDRVCURLState *s = acb->common.bs->opaque;
|
||||
@ -614,8 +618,9 @@ static void curl_readv_bh_cb(void *p)
|
||||
curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range);
|
||||
|
||||
curl_multi_add_handle(s->multi, state->curl);
|
||||
curl_multi_do(s);
|
||||
|
||||
/* Tell curl it needs to kick things off */
|
||||
curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
|
||||
}
|
||||
|
||||
static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
|
||||
|
@ -248,8 +248,8 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
offset += 8;
|
||||
|
||||
if (s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) {
|
||||
error_report("sector count %" PRIu64 " for chunk %u is "
|
||||
"larger than max (%u)",
|
||||
error_report("sector count %" PRIu64 " for chunk %" PRIu32
|
||||
" is larger than max (%u)",
|
||||
s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
@ -269,8 +269,8 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
offset += 8;
|
||||
|
||||
if (s->lengths[i] > DMG_LENGTHS_MAX) {
|
||||
error_report("length %" PRIu64 " for chunk %u is larger "
|
||||
"than max (%u)",
|
||||
error_report("length %" PRIu64 " for chunk %" PRIu32
|
||||
" is larger than max (%u)",
|
||||
s->lengths[i], i, DMG_LENGTHS_MAX);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
|
@ -325,11 +325,11 @@ static void coroutine_fn mirror_run(void *opaque)
|
||||
|
||||
s->common.len = bdrv_getlength(bs);
|
||||
if (s->common.len <= 0) {
|
||||
block_job_completed(&s->common, s->common.len);
|
||||
return;
|
||||
ret = s->common.len;
|
||||
goto immediate_exit;
|
||||
}
|
||||
|
||||
length = (bdrv_getlength(bs) + s->granularity - 1) / s->granularity;
|
||||
length = DIV_ROUND_UP(s->common.len, s->granularity);
|
||||
s->in_flight_bitmap = bitmap_new(length);
|
||||
|
||||
/* If we have no backing file yet in the destination, we cannot let
|
||||
@ -339,7 +339,10 @@ static void coroutine_fn mirror_run(void *opaque)
|
||||
bdrv_get_backing_filename(s->target, backing_filename,
|
||||
sizeof(backing_filename));
|
||||
if (backing_filename[0] && !s->target->backing_hd) {
|
||||
bdrv_get_info(s->target, &bdi);
|
||||
ret = bdrv_get_info(s->target, &bdi);
|
||||
if (ret < 0) {
|
||||
goto immediate_exit;
|
||||
}
|
||||
if (s->granularity < bdi.cluster_size) {
|
||||
s->buf_size = MAX(s->buf_size, bdi.cluster_size);
|
||||
s->cow_bitmap = bitmap_new(length);
|
||||
|
@ -532,12 +532,11 @@ static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
|
||||
void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,
|
||||
ImageInfoSpecific *info_spec)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
QmpOutputVisitor *ov = qmp_output_visitor_new();
|
||||
QObject *obj, *data;
|
||||
|
||||
visit_type_ImageInfoSpecific(qmp_output_get_visitor(ov), &info_spec, NULL,
|
||||
&local_err);
|
||||
&error_abort);
|
||||
obj = qmp_output_get_qobject(ov);
|
||||
assert(qobject_type(obj) == QTYPE_QDICT);
|
||||
data = qdict_get(qobject_to_qdict(obj), "data");
|
||||
|
@ -119,7 +119,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
if (header.version != QCOW_VERSION) {
|
||||
char version[64];
|
||||
snprintf(version, sizeof(version), "QCOW version %d", header.version);
|
||||
snprintf(version, sizeof(version), "QCOW version %" PRIu32,
|
||||
header.version);
|
||||
error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
|
||||
bs->device_name, "qcow", version);
|
||||
ret = -ENOTSUP;
|
||||
|
@ -42,6 +42,13 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
||||
if (min_size <= s->l1_size)
|
||||
return 0;
|
||||
|
||||
/* Do a sanity check on min_size before trying to calculate new_l1_size
|
||||
* (this prevents overflows during the while loop for the calculation of
|
||||
* new_l1_size) */
|
||||
if (min_size > INT_MAX / sizeof(uint64_t)) {
|
||||
return -EFBIG;
|
||||
}
|
||||
|
||||
if (exact_size) {
|
||||
new_l1_size = min_size;
|
||||
} else {
|
||||
@ -1360,9 +1367,9 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
|
||||
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
|
||||
|
||||
for (i = 0; i < nb_clusters; i++) {
|
||||
uint64_t old_offset;
|
||||
uint64_t old_l2_entry;
|
||||
|
||||
old_offset = be64_to_cpu(l2_table[l2_index + i]);
|
||||
old_l2_entry = be64_to_cpu(l2_table[l2_index + i]);
|
||||
|
||||
/*
|
||||
* Make sure that a discarded area reads back as zeroes for v3 images
|
||||
@ -1373,12 +1380,22 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
|
||||
* TODO We might want to use bdrv_get_block_status(bs) here, but we're
|
||||
* holding s->lock, so that doesn't work today.
|
||||
*/
|
||||
if (old_offset & QCOW_OFLAG_ZERO) {
|
||||
continue;
|
||||
}
|
||||
switch (qcow2_get_cluster_type(old_l2_entry)) {
|
||||
case QCOW2_CLUSTER_UNALLOCATED:
|
||||
if (!bs->backing_hd) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
if ((old_offset & L2E_OFFSET_MASK) == 0 && !bs->backing_hd) {
|
||||
continue;
|
||||
case QCOW2_CLUSTER_ZERO:
|
||||
continue;
|
||||
|
||||
case QCOW2_CLUSTER_NORMAL:
|
||||
case QCOW2_CLUSTER_COMPRESSED:
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
/* First remove L2 entries */
|
||||
@ -1390,7 +1407,7 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
|
||||
}
|
||||
|
||||
/* Then decrease the refcount */
|
||||
qcow2_free_any_clusters(bs, old_offset, 1, type);
|
||||
qcow2_free_any_clusters(bs, old_l2_entry, 1, type);
|
||||
}
|
||||
|
||||
ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
||||
|
@ -653,6 +653,13 @@ retry:
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure that all offsets in the "allocated" range are representable
|
||||
* in an int64_t */
|
||||
if (s->free_cluster_index - 1 > (INT64_MAX >> s->cluster_bits)) {
|
||||
return -EFBIG;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ALLOC2
|
||||
fprintf(stderr, "alloc_clusters: size=%" PRId64 " -> %" PRId64 "\n",
|
||||
size,
|
||||
@ -1480,6 +1487,11 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
int ret;
|
||||
|
||||
size = bdrv_getlength(bs->file);
|
||||
if (size < 0) {
|
||||
res->check_errors++;
|
||||
return size;
|
||||
}
|
||||
|
||||
nb_clusters = size_to_clusters(s, size);
|
||||
if (nb_clusters > INT_MAX) {
|
||||
res->check_errors++;
|
||||
|
@ -124,8 +124,9 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
||||
|
||||
case QCOW2_EXT_MAGIC_BACKING_FORMAT:
|
||||
if (ext.len >= sizeof(bs->backing_format)) {
|
||||
error_setg(errp, "ERROR: ext_backing_format: len=%u too large"
|
||||
" (>=%zu)", ext.len, sizeof(bs->backing_format));
|
||||
error_setg(errp, "ERROR: ext_backing_format: len=%" PRIu32
|
||||
" too large (>=%zu)", ext.len,
|
||||
sizeof(bs->backing_format));
|
||||
return 2;
|
||||
}
|
||||
ret = bdrv_pread(bs->file, offset, bs->backing_format, ext.len);
|
||||
@ -483,7 +484,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto fail;
|
||||
}
|
||||
if (header.version < 2 || header.version > 3) {
|
||||
report_unsupported(bs, errp, "QCOW version %d", header.version);
|
||||
report_unsupported(bs, errp, "QCOW version %" PRIu32, header.version);
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
}
|
||||
@ -493,7 +494,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
/* Initialise cluster size */
|
||||
if (header.cluster_bits < MIN_CLUSTER_BITS ||
|
||||
header.cluster_bits > MAX_CLUSTER_BITS) {
|
||||
error_setg(errp, "Unsupported cluster size: 2^%i", header.cluster_bits);
|
||||
error_setg(errp, "Unsupported cluster size: 2^%" PRIu32,
|
||||
header.cluster_bits);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
@ -591,7 +593,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
s->refcount_order = header.refcount_order;
|
||||
|
||||
if (header.crypt_method > QCOW_CRYPT_AES) {
|
||||
error_setg(errp, "Unsupported encryption method: %i",
|
||||
error_setg(errp, "Unsupported encryption method: %" PRIu32,
|
||||
header.crypt_method);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
|
@ -366,7 +366,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
BDRVRawState *s = bs->opaque;
|
||||
QemuOpts *opts;
|
||||
Error *local_err = NULL;
|
||||
const char *filename;
|
||||
const char *filename = NULL;
|
||||
int fd, ret;
|
||||
struct stat st;
|
||||
|
||||
@ -446,6 +446,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
|
||||
unlink(filename);
|
||||
}
|
||||
qemu_opts_del(opts);
|
||||
return ret;
|
||||
}
|
||||
|
@ -390,6 +390,9 @@ static void raw_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
CloseHandle(s->hfile);
|
||||
if (bs->open_flags & BDRV_O_TEMPORARY) {
|
||||
unlink(bs->filename);
|
||||
}
|
||||
}
|
||||
|
||||
static int raw_truncate(BlockDriverState *bs, int64_t offset)
|
||||
|
@ -1099,7 +1099,7 @@ static int find_vdi_name(BDRVSheepdogState *s, const char *filename,
|
||||
}
|
||||
|
||||
if (rsp->result != SD_RES_SUCCESS) {
|
||||
error_report("cannot get vdi info, %s, %s %d %s",
|
||||
error_report("cannot get vdi info, %s, %s %" PRIu32 " %s",
|
||||
sd_strerror(rsp->result), filename, snapid, tag);
|
||||
if (rsp->result == SD_RES_NO_VDI) {
|
||||
ret = -ENOENT;
|
||||
@ -2316,8 +2316,8 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
||||
sn_tab[found].vm_state_size = inode.vm_state_size;
|
||||
sn_tab[found].vm_clock_nsec = inode.vm_clock_nsec;
|
||||
|
||||
snprintf(sn_tab[found].id_str, sizeof(sn_tab[found].id_str), "%u",
|
||||
inode.snap_id);
|
||||
snprintf(sn_tab[found].id_str, sizeof(sn_tab[found].id_str),
|
||||
"%" PRIu32, inode.snap_id);
|
||||
pstrcpy(sn_tab[found].name,
|
||||
MIN(sizeof(sn_tab[found].name), sizeof(inode.tag)),
|
||||
inode.tag);
|
||||
|
28
block/vdi.c
28
block/vdi.c
@ -408,34 +408,35 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
if (header.signature != VDI_SIGNATURE) {
|
||||
error_setg(errp, "Image not in VDI format (bad signature %08x)", header.signature);
|
||||
error_setg(errp, "Image not in VDI format (bad signature %08" PRIx32
|
||||
")", header.signature);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
} else if (header.version != VDI_VERSION_1_1) {
|
||||
error_setg(errp, "unsupported VDI image (version %u.%u)",
|
||||
header.version >> 16, header.version & 0xffff);
|
||||
error_setg(errp, "unsupported VDI image (version %" PRIu32 ".%" PRIu32
|
||||
")", header.version >> 16, header.version & 0xffff);
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
} else if (header.offset_bmap % SECTOR_SIZE != 0) {
|
||||
/* We only support block maps which start on a sector boundary. */
|
||||
error_setg(errp, "unsupported VDI image (unaligned block map offset "
|
||||
"0x%x)", header.offset_bmap);
|
||||
"0x%" PRIx32 ")", header.offset_bmap);
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
} else if (header.offset_data % SECTOR_SIZE != 0) {
|
||||
/* We only support data blocks which start on a sector boundary. */
|
||||
error_setg(errp, "unsupported VDI image (unaligned data offset 0x%x)",
|
||||
header.offset_data);
|
||||
error_setg(errp, "unsupported VDI image (unaligned data offset 0x%"
|
||||
PRIx32 ")", header.offset_data);
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
} else if (header.sector_size != SECTOR_SIZE) {
|
||||
error_setg(errp, "unsupported VDI image (sector size %u is not %u)",
|
||||
header.sector_size, SECTOR_SIZE);
|
||||
error_setg(errp, "unsupported VDI image (sector size %" PRIu32
|
||||
" is not %u)", header.sector_size, SECTOR_SIZE);
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
|
||||
error_setg(errp, "unsupported VDI image (block size %u is not %u)",
|
||||
header.block_size, DEFAULT_CLUSTER_SIZE);
|
||||
error_setg(errp, "unsupported VDI image (block size %" PRIu32
|
||||
" is not %u)", header.block_size, DEFAULT_CLUSTER_SIZE);
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
} else if (header.disk_size >
|
||||
@ -755,6 +756,7 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
|
||||
vdi_header_to_le(&header);
|
||||
if (write(fd, &header, sizeof(header)) < 0) {
|
||||
result = -errno;
|
||||
goto close_and_exit;
|
||||
}
|
||||
|
||||
if (bmap_size > 0) {
|
||||
@ -768,6 +770,8 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
|
||||
}
|
||||
if (write(fd, bmap, bmap_size) < 0) {
|
||||
result = -errno;
|
||||
g_free(bmap);
|
||||
goto close_and_exit;
|
||||
}
|
||||
g_free(bmap);
|
||||
}
|
||||
@ -775,10 +779,12 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
|
||||
if (image_type == VDI_TYPE_STATIC) {
|
||||
if (ftruncate(fd, sizeof(header) + bmap_size + blocks * block_size)) {
|
||||
result = -errno;
|
||||
goto close_and_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (close(fd) < 0) {
|
||||
close_and_exit:
|
||||
if ((close(fd) < 0) && !result) {
|
||||
result = -errno;
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,7 @@ typedef enum {
|
||||
|
||||
#define BDRV_O_RDWR 0x0002
|
||||
#define BDRV_O_SNAPSHOT 0x0008 /* open the file read only and save writes in a snapshot */
|
||||
#define BDRV_O_TEMPORARY 0x0010 /* delete the file after use */
|
||||
#define BDRV_O_NOCACHE 0x0020 /* do not use the host page cache */
|
||||
#define BDRV_O_CACHE_WB 0x0040 /* use write-back caching */
|
||||
#define BDRV_O_NATIVE_AIO 0x0080 /* use native AIO instead of the thread pool */
|
||||
|
@ -299,7 +299,6 @@ struct BlockDriverState {
|
||||
char backing_file[1024]; /* if non zero, the image is a diff of
|
||||
this file image */
|
||||
char backing_format[16]; /* if non-zero and backing_file exists */
|
||||
int is_temporary;
|
||||
|
||||
BlockDriverState *backing_hd;
|
||||
BlockDriverState *file;
|
||||
|
26
qemu-img.c
26
qemu-img.c
@ -33,6 +33,9 @@
|
||||
#include "block/qapi.h"
|
||||
#include <getopt.h>
|
||||
|
||||
#define QEMU_IMG_VERSION "qemu-img version " QEMU_VERSION \
|
||||
", Copyright (c) 2004-2008 Fabrice Bellard\n"
|
||||
|
||||
typedef struct img_cmd_t {
|
||||
const char *name;
|
||||
int (*handler)(int argc, char **argv);
|
||||
@ -75,7 +78,7 @@ static void QEMU_NORETURN GCC_FMT_ATTR(1, 2) error_exit(const char *fmt, ...)
|
||||
static void QEMU_NORETURN help(void)
|
||||
{
|
||||
const char *help_msg =
|
||||
"qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
|
||||
QEMU_IMG_VERSION
|
||||
"usage: qemu-img command [command options]\n"
|
||||
"QEMU disk image utility\n"
|
||||
"\n"
|
||||
@ -2789,6 +2792,12 @@ int main(int argc, char **argv)
|
||||
{
|
||||
const img_cmd_t *cmd;
|
||||
const char *cmdname;
|
||||
int c;
|
||||
static const struct option long_options[] = {
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
#ifdef CONFIG_POSIX
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
@ -2803,15 +2812,24 @@ int main(int argc, char **argv)
|
||||
error_exit("Not enough arguments");
|
||||
}
|
||||
cmdname = argv[1];
|
||||
argc--; argv++;
|
||||
|
||||
/* find the command */
|
||||
for(cmd = img_cmds; cmd->name != NULL; cmd++) {
|
||||
for (cmd = img_cmds; cmd->name != NULL; cmd++) {
|
||||
if (!strcmp(cmdname, cmd->name)) {
|
||||
return cmd->handler(argc, argv);
|
||||
return cmd->handler(argc - 1, argv + 1);
|
||||
}
|
||||
}
|
||||
|
||||
c = getopt_long(argc, argv, "h", long_options, NULL);
|
||||
|
||||
if (c == 'h') {
|
||||
help();
|
||||
}
|
||||
if (c == 'v') {
|
||||
printf(QEMU_IMG_VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not found */
|
||||
error_exit("Command not found: %s", cmdname);
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ mv "$TEST_IMG" "$TEST_IMG.orig"
|
||||
for backing_option in "-B " "-o backing_file="; do
|
||||
|
||||
echo
|
||||
echo Testing conversion with $backing_option$TEST_IMG.base | _filter_testdir | _filter_imgfmt
|
||||
echo Testing conversion with $backing_option"$TEST_IMG.base" | _filter_testdir | _filter_imgfmt
|
||||
echo
|
||||
$QEMU_IMG convert -O $IMGFMT $backing_option"$TEST_IMG.base" "$TEST_IMG.orig" "$TEST_IMG"
|
||||
|
||||
|
@ -51,10 +51,10 @@ function run_qemu_img()
|
||||
size=128M
|
||||
|
||||
_make_test_img $size
|
||||
$QEMU_IO -c 'write 0 1M' $TEST_IMG | _filter_qemu_io
|
||||
$QEMU_IO -c 'write 2M 1M' $TEST_IMG | _filter_qemu_io
|
||||
$QEMU_IO -c 'write 4M 1M' $TEST_IMG | _filter_qemu_io
|
||||
$QEMU_IO -c 'write 32M 1M' $TEST_IMG | _filter_qemu_io
|
||||
$QEMU_IO -c 'write 0 1M' "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -c 'write 2M 1M' "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -c 'write 4M 1M' "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -c 'write 32M 1M' "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
$QEMU_IMG convert -p -O $IMGFMT -f $IMGFMT "$TEST_IMG" "$TEST_IMG".base 2>&1 |\
|
||||
_filter_testdir | sed -e 's/\r/\n/g'
|
||||
|
61
tests/qemu-iotests/090
Executable file
61
tests/qemu-iotests/090
Executable file
@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Test for discarding compressed clusters on qcow2 images
|
||||
#
|
||||
# Copyright (C) 2014 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# creator
|
||||
owner=mreitz@redhat.com
|
||||
|
||||
seq="$(basename $0)"
|
||||
echo "QA output created by $seq"
|
||||
|
||||
here="$PWD"
|
||||
tmp=/tmp/$$
|
||||
status=1 # failure is the default!
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_test_img
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt qcow2
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
IMG_SIZE=128K
|
||||
|
||||
_make_test_img $IMG_SIZE
|
||||
|
||||
$QEMU_IO -c 'write -c -P 42 0 64k' \
|
||||
-c 'write -c -P 23 64k 64k' \
|
||||
-c 'discard 64k 64k' \
|
||||
"$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
$QEMU_IO -c 'read -P 0 64k 64k' "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
_check_test_img
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
status=0
|
12
tests/qemu-iotests/090.out
Normal file
12
tests/qemu-iotests/090.out
Normal file
@ -0,0 +1,12 @@
|
||||
QA output created by 090
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072
|
||||
wrote 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset 65536
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
discard 65536/65536 bytes at offset 65536
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 65536
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
No errors were found on the image.
|
||||
*** done
|
@ -178,10 +178,10 @@ _rm_test_img()
|
||||
local img=$1
|
||||
if [ "$IMGFMT" = "vmdk" ]; then
|
||||
# Remove all the extents for vmdk
|
||||
$QEMU_IMG info $img 2>/dev/null | grep 'filename:' | cut -f 2 -d: \
|
||||
"$QEMU_IMG" info "$img" 2>/dev/null | grep 'filename:' | cut -f 2 -d: \
|
||||
| xargs -I {} rm -f "{}"
|
||||
fi
|
||||
rm -f $img
|
||||
rm -f "$img"
|
||||
}
|
||||
|
||||
_cleanup_test_img()
|
||||
|
@ -95,3 +95,4 @@
|
||||
086 rw auto quick
|
||||
087 rw auto
|
||||
088 rw auto
|
||||
090 rw auto quick
|
||||
|
Loading…
Reference in New Issue
Block a user