Commit 8b6db32a authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging



# gpg: Signature made Fri May 22 10:00:53 2015 BST using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"

* remotes/stefanha/tags/block-pull-request: (38 commits)
  block: get_block_status: use "else" when testing the opposite condition
  qemu-iotests: Test unaligned sub-block zero write
  block: Fix NULL deference for unaligned write if qiov is NULL
  Revert "block: Fix unaligned zero write"
  block: align bounce buffers to page
  block: minimal bounce buffer alignment
  block: return EPERM on writes or discards to read-only devices
  configure: Add workaround for ccache and clang
  configure: silence glib unknown attribute __alloc_size__
  configure: factor out supported flag check
  configure: handle clang -nopie argument warning
  block/parallels: improve image writing performance further
  block/parallels: optimize linear image expansion
  block/parallels: add prealloc-mode and prealloc-size open paramemets
  block/parallels: delay writing to BAT till bdrv_co_flush_to_os
  block/parallels: create bat_entry_off helper
  block/parallels: improve image reading performance
  iotests, parallels: check for incorrectly closed image in tests
  block/parallels: implement incorrect close detection
  block/parallels: implement parallels_check method of block driver
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents f5790c3b a53f1a95
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -106,13 +106,23 @@ int is_windows_drive(const char *filename)
size_t bdrv_opt_mem_align(BlockDriverState *bs)
{
    if (!bs || !bs->drv) {
        /* 4k should be on the safe side */
        return 4096;
        /* page size or 4k (hdd sector size) should be on the safe side */
        return MAX(4096, getpagesize());
    }

    return bs->bl.opt_mem_alignment;
}

size_t bdrv_min_mem_align(BlockDriverState *bs)
{
    if (!bs || !bs->drv) {
        /* page size or 4k (hdd sector size) should be on the safe side */
        return MAX(4096, getpagesize());
    }

    return bs->bl.min_mem_alignment;
}

/* check if the path starts with "<protocol>:" */
int path_has_protocol(const char *path)
{
@@ -890,6 +900,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
    }

    assert(bdrv_opt_mem_align(bs) != 0);
    assert(bdrv_min_mem_align(bs) != 0);
    assert((bs->request_alignment != 0) || bs->sg);
    return 0;

+111 −48
Original line number Diff line number Diff line
@@ -201,9 +201,11 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
        }
        bs->bl.opt_transfer_length = bs->file->bl.opt_transfer_length;
        bs->bl.max_transfer_length = bs->file->bl.max_transfer_length;
        bs->bl.min_mem_alignment = bs->file->bl.min_mem_alignment;
        bs->bl.opt_mem_alignment = bs->file->bl.opt_mem_alignment;
    } else {
        bs->bl.opt_mem_alignment = 512;
        bs->bl.min_mem_alignment = 512;
        bs->bl.opt_mem_alignment = getpagesize();
    }

    if (bs->backing_hd) {
@@ -221,6 +223,9 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
        bs->bl.opt_mem_alignment =
            MAX(bs->bl.opt_mem_alignment,
                bs->backing_hd->bl.opt_mem_alignment);
        bs->bl.min_mem_alignment =
            MAX(bs->bl.min_mem_alignment,
                bs->backing_hd->bl.min_mem_alignment);
    }

    /* Then let the driver override it */
@@ -929,19 +934,6 @@ out:
    return ret;
}

static inline uint64_t bdrv_get_align(BlockDriverState *bs)
{
    /* TODO Lift BDRV_SECTOR_SIZE restriction in BlockDriver interface */
    return MAX(BDRV_SECTOR_SIZE, bs->request_alignment);
}

static inline bool bdrv_req_is_aligned(BlockDriverState *bs,
                                       int64_t offset, size_t bytes)
{
    int64_t align = bdrv_get_align(bs);
    return !(offset & (align - 1) || (bytes & (align - 1)));
}

/*
 * Handle a read request in coroutine context
 */
@@ -952,7 +944,8 @@ static int coroutine_fn bdrv_co_do_preadv(BlockDriverState *bs,
    BlockDriver *drv = bs->drv;
    BdrvTrackedRequest req;

    uint64_t align = bdrv_get_align(bs);
    /* TODO Lift BDRV_SECTOR_SIZE restriction in BlockDriver interface */
    uint64_t align = MAX(BDRV_SECTOR_SIZE, bs->request_alignment);
    uint8_t *head_buf = NULL;
    uint8_t *tail_buf = NULL;
    QEMUIOVector local_qiov;
@@ -1186,6 +1179,94 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
    return ret;
}

static int coroutine_fn bdrv_co_do_zero_pwritev(BlockDriverState *bs,
                                                int64_t offset,
                                                unsigned int bytes,
                                                BdrvRequestFlags flags,
                                                BdrvTrackedRequest *req)
{
    uint8_t *buf = NULL;
    QEMUIOVector local_qiov;
    struct iovec iov;
    uint64_t align = MAX(BDRV_SECTOR_SIZE, bs->request_alignment);
    unsigned int head_padding_bytes, tail_padding_bytes;
    int ret = 0;

    head_padding_bytes = offset & (align - 1);
    tail_padding_bytes = align - ((offset + bytes) & (align - 1));


    assert(flags & BDRV_REQ_ZERO_WRITE);
    if (head_padding_bytes || tail_padding_bytes) {
        buf = qemu_blockalign(bs, align);
        iov = (struct iovec) {
            .iov_base   = buf,
            .iov_len    = align,
        };
        qemu_iovec_init_external(&local_qiov, &iov, 1);
    }
    if (head_padding_bytes) {
        uint64_t zero_bytes = MIN(bytes, align - head_padding_bytes);

        /* RMW the unaligned part before head. */
        mark_request_serialising(req, align);
        wait_serialising_requests(req);
        BLKDBG_EVENT(bs, BLKDBG_PWRITEV_RMW_HEAD);
        ret = bdrv_aligned_preadv(bs, req, offset & ~(align - 1), align,
                                  align, &local_qiov, 0);
        if (ret < 0) {
            goto fail;
        }
        BLKDBG_EVENT(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);

        memset(buf + head_padding_bytes, 0, zero_bytes);
        ret = bdrv_aligned_pwritev(bs, req, offset & ~(align - 1), align,
                                   &local_qiov,
                                   flags & ~BDRV_REQ_ZERO_WRITE);
        if (ret < 0) {
            goto fail;
        }
        offset += zero_bytes;
        bytes -= zero_bytes;
    }

    assert(!bytes || (offset & (align - 1)) == 0);
    if (bytes >= align) {
        /* Write the aligned part in the middle. */
        uint64_t aligned_bytes = bytes & ~(align - 1);
        ret = bdrv_aligned_pwritev(bs, req, offset, aligned_bytes,
                                   NULL, flags);
        if (ret < 0) {
            goto fail;
        }
        bytes -= aligned_bytes;
        offset += aligned_bytes;
    }

    assert(!bytes || (offset & (align - 1)) == 0);
    if (bytes) {
        assert(align == tail_padding_bytes + bytes);
        /* RMW the unaligned part after tail. */
        mark_request_serialising(req, align);
        wait_serialising_requests(req);
        BLKDBG_EVENT(bs, BLKDBG_PWRITEV_RMW_TAIL);
        ret = bdrv_aligned_preadv(bs, req, offset, align,
                                  align, &local_qiov, 0);
        if (ret < 0) {
            goto fail;
        }
        BLKDBG_EVENT(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);

        memset(buf, 0, bytes);
        ret = bdrv_aligned_pwritev(bs, req, offset, align,
                                   &local_qiov, flags & ~BDRV_REQ_ZERO_WRITE);
    }
fail:
    qemu_vfree(buf);
    return ret;

}

/*
 * Handle a write request in coroutine context
 */
@@ -1194,7 +1275,8 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs,
    BdrvRequestFlags flags)
{
    BdrvTrackedRequest req;
    uint64_t align = bdrv_get_align(bs);
    /* TODO Lift BDRV_SECTOR_SIZE restriction in BlockDriver interface */
    uint64_t align = MAX(BDRV_SECTOR_SIZE, bs->request_alignment);
    uint8_t *head_buf = NULL;
    uint8_t *tail_buf = NULL;
    QEMUIOVector local_qiov;
@@ -1205,7 +1287,7 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs,
        return -ENOMEDIUM;
    }
    if (bs->read_only) {
        return -EACCES;
        return -EPERM;
    }

    ret = bdrv_check_byte_request(bs, offset, bytes);
@@ -1225,6 +1307,11 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs,
     */
    tracked_request_begin(&req, bs, offset, bytes, true);

    if (!qiov) {
        ret = bdrv_co_do_zero_pwritev(bs, offset, bytes, flags, &req);
        goto out;
    }

    if (offset & (align - 1)) {
        QEMUIOVector head_qiov;
        struct iovec head_iov;
@@ -1293,23 +1380,19 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs,
        bytes = ROUND_UP(bytes, align);
    }

    if (use_local_qiov) {
        /* Local buffer may have non-zero data. */
        flags &= ~BDRV_REQ_ZERO_WRITE;
    }
    ret = bdrv_aligned_pwritev(bs, &req, offset, bytes,
                               use_local_qiov ? &local_qiov : qiov,
                               flags);

fail:
    tracked_request_end(&req);

    if (use_local_qiov) {
        qemu_iovec_destroy(&local_qiov);
    }
    qemu_vfree(head_buf);
    qemu_vfree(tail_buf);

out:
    tracked_request_end(&req);
    return ret;
}

@@ -1337,32 +1420,14 @@ int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs,
                                      int64_t sector_num, int nb_sectors,
                                      BdrvRequestFlags flags)
{
    int ret;

    trace_bdrv_co_write_zeroes(bs, sector_num, nb_sectors, flags);

    if (!(bs->open_flags & BDRV_O_UNMAP)) {
        flags &= ~BDRV_REQ_MAY_UNMAP;
    }
    if (bdrv_req_is_aligned(bs, sector_num << BDRV_SECTOR_BITS,
                            nb_sectors << BDRV_SECTOR_BITS)) {
        ret = bdrv_co_do_writev(bs, sector_num, nb_sectors, NULL,
                                BDRV_REQ_ZERO_WRITE | flags);
    } else {
        uint8_t *buf;
        QEMUIOVector local_qiov;
        size_t bytes = nb_sectors << BDRV_SECTOR_BITS;

        buf = qemu_memalign(bdrv_opt_mem_align(bs), bytes);
        memset(buf, 0, bytes);
        qemu_iovec_init(&local_qiov, 1);
        qemu_iovec_add(&local_qiov, buf, bytes);

        ret = bdrv_co_do_writev(bs, sector_num, nb_sectors, &local_qiov,
    return bdrv_co_do_writev(bs, sector_num, nb_sectors, NULL,
                             BDRV_REQ_ZERO_WRITE | flags);
        qemu_vfree(buf);
    }
    return ret;
}

int bdrv_flush_all(void)
@@ -1456,9 +1521,7 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,

    if (ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ZERO)) {
        ret |= BDRV_BLOCK_ALLOCATED;
    }

    if (!(ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO)) {
    } else {
        if (bdrv_unallocated_blocks_are_zero(bs)) {
            ret |= BDRV_BLOCK_ZERO;
        } else if (bs->backing_hd) {
@@ -2340,7 +2403,7 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
    if (ret < 0) {
        return ret;
    } else if (bs->read_only) {
        return -EROFS;
        return -EPERM;
    }

    bdrv_reset_dirty(bs, sector_num, nb_sectors);
@@ -2489,7 +2552,7 @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size)
bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
{
    int i;
    size_t alignment = bdrv_opt_mem_align(bs);
    size_t alignment = bdrv_min_mem_align(bs);

    for (i = 0; i < qiov->niov; i++) {
        if ((uintptr_t) qiov->iov[i].iov_base % alignment) {
+612 −67

File changed.

Preview size limit exceeded, changes collapsed.

+8 −6
Original line number Diff line number Diff line
@@ -301,6 +301,7 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
{
    BDRVRawState *s = bs->opaque;
    char *buf;
    size_t max_align = MAX(MAX_BLOCKSIZE, getpagesize());

    /* For /dev/sg devices the alignment is not really used.
       With buffered I/O, we don't have any restrictions. */
@@ -330,9 +331,9 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
    /* If we could not get the sizes so far, we can only guess them */
    if (!s->buf_align) {
        size_t align;
        buf = qemu_memalign(MAX_BLOCKSIZE, 2 * MAX_BLOCKSIZE);
        for (align = 512; align <= MAX_BLOCKSIZE; align <<= 1) {
            if (raw_is_io_aligned(fd, buf + align, MAX_BLOCKSIZE)) {
        buf = qemu_memalign(max_align, 2 * max_align);
        for (align = 512; align <= max_align; align <<= 1) {
            if (raw_is_io_aligned(fd, buf + align, max_align)) {
                s->buf_align = align;
                break;
            }
@@ -342,8 +343,8 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)

    if (!bs->request_alignment) {
        size_t align;
        buf = qemu_memalign(s->buf_align, MAX_BLOCKSIZE);
        for (align = 512; align <= MAX_BLOCKSIZE; align <<= 1) {
        buf = qemu_memalign(s->buf_align, max_align);
        for (align = 512; align <= max_align; align <<= 1) {
            if (raw_is_io_aligned(fd, buf, align)) {
                bs->request_alignment = align;
                break;
@@ -725,7 +726,8 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
    BDRVRawState *s = bs->opaque;

    raw_probe_alignment(bs, s->fd, errp);
    bs->bl.opt_mem_alignment = s->buf_align;
    bs->bl.min_mem_alignment = s->buf_align;
    bs->bl.opt_mem_alignment = MAX(s->buf_align, getpagesize());
}

static int check_for_dasd(int fd)
+65 −16
Original line number Diff line number Diff line
@@ -103,7 +103,8 @@ update_cxxflags() {
}

compile_object() {
  do_cc $QEMU_CFLAGS -c -o $TMPO $TMPC
  local_cflags="$1"
  do_cc $QEMU_CFLAGS $local_cflags -c -o $TMPO $TMPC
}

compile_prog() {
@@ -436,6 +437,12 @@ EOF
  compile_object
}

write_c_skeleton() {
    cat > $TMPC <<EOF
int main(void) { return 0; }
EOF
}

if check_define __linux__ ; then
  targetos="Linux"
elif check_define _WIN32 ; then
@@ -705,9 +712,7 @@ if test "$mingw32" = "yes" ; then
  # enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later)
  QEMU_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $QEMU_CFLAGS"
  LIBS="-lwinmm -lws2_32 -liphlpapi $LIBS"
cat > $TMPC << EOF
int main(void) { return 0; }
EOF
  write_c_skeleton;
  if compile_prog "" "-liberty" ; then
    LIBS="-liberty $LIBS"
  fi
@@ -1445,10 +1450,7 @@ if test -z "$werror" ; then
fi

# check that the C compiler works.
cat > $TMPC <<EOF
int main(void) { return 0; }
EOF

write_c_skeleton;
if compile_object ; then
  : C compiler works ok
else
@@ -1496,15 +1498,19 @@ gcc_flags="-Wno-string-plus-int $gcc_flags"
# enable it for all configure tests. If a configure test failed due
# to -Werror this would just silently disable some features,
# so it's too error prone.
cat > $TMPC << EOF
int main(void) { return 0; }
EOF
for flag in $gcc_flags; do

cc_has_warning_flag() {
    write_c_skeleton;

    # Use the positive sense of the flag when testing for -Wno-wombat
    # support (gcc will happily accept the -Wno- form of unknown
    # warning options).
    optflag="$(echo $flag | sed -e 's/^-Wno-/-W/')"
    if compile_prog "-Werror $optflag" "" ; then
    optflag="$(echo $1 | sed -e 's/^-Wno-/-W/')"
    compile_prog "-Werror $optflag" ""
}

for flag in $gcc_flags; do
    if cc_has_warning_flag $flag ; then
        QEMU_CFLAGS="$QEMU_CFLAGS $flag"
    fi
done
@@ -1607,7 +1613,7 @@ EOF
    fi
  fi

  if compile_prog "-fno-pie" "-nopie"; then
  if compile_prog "-Werror -fno-pie" "-nopie"; then
    CFLAGS_NOPIE="-fno-pie"
    LDFLAGS_NOPIE="-nopie"
  fi
@@ -2802,6 +2808,18 @@ if ! $pkg_config --atleast-version=2.38 glib-2.0; then
    glib_subprocess=no
fi

# Silence clang 3.5.0 warnings about glib attribute __alloc_size__ usage
cat > $TMPC << EOF
#include <glib.h>
int main(void) { return 0; }
EOF
if ! compile_prog "$glib_cflags -Werror" "$glib_libs" ; then
    if cc_has_warning_flag "-Wno-unknown-attributes"; then
        glib_cflags="-Wno-unknown-attributes $glib_cflags"
        CFLAGS="-Wno-unknown-attributes $CFLAGS"
    fi
fi

##########################################
# SHA command probe for modules
if test "$modules" = yes; then
@@ -4192,6 +4210,33 @@ if compile_prog "" "" ; then
    getauxval=yes
fi

########################################
# check if ccache is interfering with
# semantic analysis of macros

ccache_cpp2=no
cat > $TMPC << EOF
static const int Z = 1;
#define fn() ({ Z; })
#define TAUT(X) ((X) == Z)
#define PAREN(X, Y) (X == Y)
#define ID(X) (X)
int main(int argc, char *argv[])
{
    int x = 0, y = 0;
    x = ID(x);
    x = fn();
    fn();
    if (PAREN(x, y)) return 0;
    if (TAUT(Z)) return 0;
    return 0;
}
EOF

if ! compile_object "-Werror"; then
    ccache_cpp2=yes
fi

##########################################
# End of CC checks
# After here, no more $cc or $ld runs
@@ -5485,6 +5530,10 @@ if test "$numa" = "yes"; then
  echo "CONFIG_NUMA=y" >> $config_host_mak
fi

if test "$ccache_cpp2" = "yes"; then
  echo "export CCACHE_CPP2=y" >> $config_host_mak
fi

# build tree in object directory in case the source is not in the current directory
DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-schema tests/tcg/xtensa tests/qemu-iotests"
DIRS="$DIRS fsdev"
Loading