Commit e50bf234 authored by Peter Maydell's avatar Peter Maydell
Browse files

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: default avatarPeter Maydell <peter.maydell@linaro.org>
parents c090c10d b7079df4
Loading
Loading
Loading
Loading
+72 −36
Original line number Diff line number Diff line
@@ -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,11 +3622,26 @@ 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) {
        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 */
BlockDriverState *bdrv_find(const char *name)
+14 −9
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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;
+79 −74
Original line number Diff line number Diff line
@@ -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,26 +243,24 @@ 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:
            {
        if (msg->msg == CURLMSG_DONE) {
            CURLState *state = NULL;
                curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char**)&state);
            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) {
@@ -277,28 +281,31 @@ static void curl_multi_read(BDRVCURLState *s)
            curl_clean_state(state);
            break;
        }
            default:
                msgs_in_queue = 0;
                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,20 +344,19 @@ 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)
        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_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);
@@ -373,8 +379,7 @@ static CURLState *curl_init_state(BDRVCURLState *s)
#ifdef DEBUG_VERBOSE
        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,
+4 −4
Original line number Diff line number Diff line
@@ -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;
Loading