Commit 715cc00c authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote-tracking branch 'kwolf/for-anthony' into staging

* kwolf/for-anthony: (24 commits)
  block: Factor bdrv_read_unthrottled() out of guess_disk_lchs()
  qtest: Tidy up temporary files properly
  fdc: Drop broken code for user-defined floppy geometry
  fdc_test: introduce test_sense_interrupt
  fdc_test: update media_change test
  fdc: fix interrupt handling
  fdc: rewrite seek and DSKCHG bit handling
  block: introduce bdrv_swap, implement bdrv_append on top of it
  block: copy over job and dirty bitmap fields in bdrv_append
  raw: hook into blkdebug
  blkdebug: optionally tie errors to a specific sector
  blkdebug: store list of active rules
  blkdebug: pass getlength to underlying file
  blkdebug: tiny cleanup
  blkdebug: remove sync i/o events
  sheepdog: traverse pending_list from the first for each time
  sheepdog: split outstanding list into inflight and pending
  sheepdog: make sure we don't free aiocb before sending all requests
  sheepdog: use coroutine based socket functions in coroutine context
  sheepdog: restart I/O when socket becomes ready in do_co_req()
  ...
parents fe0cb8ef 07d27a44
Loading
Loading
Loading
Loading
+147 −114
Original line number Diff line number Diff line
@@ -971,101 +971,130 @@ static void bdrv_rebind(BlockDriverState *bs)
    }
}

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;
    bs_dest->dev_opaque         = bs_src->dev_opaque;
    bs_dest->dev                = bs_src->dev;
    bs_dest->buffer_alignment   = bs_src->buffer_alignment;
    bs_dest->copy_on_read       = bs_src->copy_on_read;

    bs_dest->enable_write_cache = bs_src->enable_write_cache;

    /* i/o timing parameters */
    bs_dest->slice_time         = bs_src->slice_time;
    bs_dest->slice_start        = bs_src->slice_start;
    bs_dest->slice_end          = bs_src->slice_end;
    bs_dest->io_limits          = bs_src->io_limits;
    bs_dest->io_base            = bs_src->io_base;
    bs_dest->throttled_reqs     = bs_src->throttled_reqs;
    bs_dest->block_timer        = bs_src->block_timer;
    bs_dest->io_limits_enabled  = bs_src->io_limits_enabled;

    /* geometry */
    bs_dest->cyls               = bs_src->cyls;
    bs_dest->heads              = bs_src->heads;
    bs_dest->secs               = bs_src->secs;
    bs_dest->translation        = bs_src->translation;

    /* r/w error */
    bs_dest->on_read_error      = bs_src->on_read_error;
    bs_dest->on_write_error     = bs_src->on_write_error;

    /* i/o status */
    bs_dest->iostatus_enabled   = bs_src->iostatus_enabled;
    bs_dest->iostatus           = bs_src->iostatus;

    /* dirty bitmap */
    bs_dest->dirty_count        = bs_src->dirty_count;
    bs_dest->dirty_bitmap       = bs_src->dirty_bitmap;

    /* job */
    bs_dest->in_use             = bs_src->in_use;
    bs_dest->job                = bs_src->job;

    /* keep the same entry in bdrv_states */
    pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
            bs_src->device_name);
    bs_dest->list = bs_src->list;
}

/*
 * Add new bs contents at the top of an image chain while the chain is
 * live, while keeping required fields on the top layer.
 * Swap bs contents for two image chains while they are live,
 * while keeping required fields on the BlockDriverState that is
 * actually attached to a device.
 *
 * This will modify the BlockDriverState fields, and swap contents
 * between bs_new and bs_top. Both bs_new and bs_top are modified.
 * between bs_new and bs_old. Both bs_new and bs_old are modified.
 *
 * bs_new is required to be anonymous.
 *
 * This function does not create any image files.
 */
void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top)
void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
{
    BlockDriverState tmp;

    /* bs_new must be anonymous */
    /* bs_new must be anonymous and shouldn't have anything fancy enabled */
    assert(bs_new->device_name[0] == '\0');
    assert(bs_new->dirty_bitmap == NULL);
    assert(bs_new->job == NULL);
    assert(bs_new->dev == NULL);
    assert(bs_new->in_use == 0);
    assert(bs_new->io_limits_enabled == false);
    assert(bs_new->block_timer == NULL);

    tmp = *bs_new;
    *bs_new = *bs_old;
    *bs_old = tmp;

    /* there are some fields that need to stay on the top layer: */
    tmp.open_flags        = bs_top->open_flags;

    /* dev info */
    tmp.dev_ops           = bs_top->dev_ops;
    tmp.dev_opaque        = bs_top->dev_opaque;
    tmp.dev               = bs_top->dev;
    tmp.buffer_alignment  = bs_top->buffer_alignment;
    tmp.copy_on_read      = bs_top->copy_on_read;
    /* there are some fields that should not be swapped, move them back */
    bdrv_move_feature_fields(&tmp, bs_old);
    bdrv_move_feature_fields(bs_old, bs_new);
    bdrv_move_feature_fields(bs_new, &tmp);

    tmp.enable_write_cache = bs_top->enable_write_cache;

    /* i/o timing parameters */
    tmp.slice_time        = bs_top->slice_time;
    tmp.slice_start       = bs_top->slice_start;
    tmp.slice_end         = bs_top->slice_end;
    tmp.io_limits         = bs_top->io_limits;
    tmp.io_base           = bs_top->io_base;
    tmp.throttled_reqs    = bs_top->throttled_reqs;
    tmp.block_timer       = bs_top->block_timer;
    tmp.io_limits_enabled = bs_top->io_limits_enabled;

    /* geometry */
    tmp.cyls              = bs_top->cyls;
    tmp.heads             = bs_top->heads;
    tmp.secs              = bs_top->secs;
    tmp.translation       = bs_top->translation;
    /* bs_new shouldn't be in bdrv_states even after the swap!  */
    assert(bs_new->device_name[0] == '\0');

    /* r/w error */
    tmp.on_read_error     = bs_top->on_read_error;
    tmp.on_write_error    = bs_top->on_write_error;
    /* Check a few fields that should remain attached to the device */
    assert(bs_new->dev == NULL);
    assert(bs_new->job == NULL);
    assert(bs_new->in_use == 0);
    assert(bs_new->io_limits_enabled == false);
    assert(bs_new->block_timer == NULL);

    /* i/o status */
    tmp.iostatus_enabled  = bs_top->iostatus_enabled;
    tmp.iostatus          = bs_top->iostatus;
    bdrv_rebind(bs_new);
    bdrv_rebind(bs_old);
}

    /* keep the same entry in bdrv_states */
    pstrcpy(tmp.device_name, sizeof(tmp.device_name), bs_top->device_name);
    tmp.list = bs_top->list;
/*
 * Add new bs contents at the top of an image chain while the chain is
 * live, while keeping required fields on the top layer.
 *
 * This will modify the BlockDriverState fields, and swap contents
 * between bs_new and bs_top. Both bs_new and bs_top are modified.
 *
 * bs_new is required to be anonymous.
 *
 * This function does not create any image files.
 */
void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top)
{
    bdrv_swap(bs_new, bs_top);

    /* The contents of 'tmp' will become bs_top, as we are
     * swapping bs_new and bs_top contents. */
    tmp.backing_hd = bs_new;
    pstrcpy(tmp.backing_file, sizeof(tmp.backing_file), bs_top->filename);
    pstrcpy(tmp.backing_format, sizeof(tmp.backing_format),
            bs_top->drv ? bs_top->drv->format_name : "");

    /* swap contents of the fixed new bs and the current top */
    *bs_new = *bs_top;
    *bs_top = tmp;

    /* device_name[] was carried over from the old bs_top.  bs_new
     * shouldn't be in bdrv_states, so we need to make device_name[]
     * reflect the anonymity of bs_new
     */
    bs_new->device_name[0] = '\0';

    /* clear the copied fields in the new backing file */
    bdrv_detach_dev(bs_new, bs_new->dev);

    qemu_co_queue_init(&bs_new->throttled_reqs);
    memset(&bs_new->io_base,   0, sizeof(bs_new->io_base));
    memset(&bs_new->io_limits, 0, sizeof(bs_new->io_limits));
    bdrv_iostatus_disable(bs_new);

    /* we don't use bdrv_io_limits_disable() for this, because we don't want
     * to affect or delete the block_timer, as it has been moved to bs_top */
    bs_new->io_limits_enabled = false;
    bs_new->block_timer       = NULL;
    bs_new->slice_time        = 0;
    bs_new->slice_start       = 0;
    bs_new->slice_end         = 0;

    bdrv_rebind(bs_new);
    bdrv_rebind(bs_top);
    bs_top->backing_hd = bs_new;
    bs_top->open_flags &= ~BDRV_O_NO_BACKING;
    pstrcpy(bs_top->backing_file, sizeof(bs_top->backing_file),
            bs_new->filename);
    pstrcpy(bs_top->backing_format, sizeof(bs_top->backing_format),
            bs_new->drv ? bs_new->drv->format_name : "");
}

void bdrv_delete(BlockDriverState *bs)
@@ -1610,6 +1639,20 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num,
    return bdrv_rw_co(bs, sector_num, buf, nb_sectors, false);
}

/* Just like bdrv_read(), but with I/O throttling temporarily disabled */
int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num,
                          uint8_t *buf, int nb_sectors)
{
    bool enabled;
    int ret;

    enabled = bs->io_limits_enabled;
    bs->io_limits_enabled = false;
    ret = bdrv_read(bs, 0, buf, 1);
    bs->io_limits_enabled = enabled;
    return ret;
}

#define BITS_PER_LONG  (sizeof(unsigned long) * 8)

static void set_dirty_bitmap(BlockDriverState *bs, int64_t sector_num,
@@ -2107,11 +2150,10 @@ static int guess_disk_lchs(BlockDriverState *bs,
                           int *pcylinders, int *pheads, int *psectors)
{
    uint8_t buf[BDRV_SECTOR_SIZE];
    int ret, i, heads, sectors, cylinders;
    int i, heads, sectors, cylinders;
    struct partition *p;
    uint32_t nr_sects;
    uint64_t nb_sectors;
    bool enabled;

    bdrv_get_geometry(bs, &nb_sectors);

@@ -2120,12 +2162,9 @@ static int guess_disk_lchs(BlockDriverState *bs,
     * but also in async I/O mode. So the I/O throttling function has to
     * be disabled temporarily here, not permanently.
     */
    enabled = bs->io_limits_enabled;
    bs->io_limits_enabled = false;
    ret = bdrv_read(bs, 0, buf, 1);
    bs->io_limits_enabled = enabled;
    if (ret < 0)
    if (bdrv_read_unthrottled(bs, 0, buf, 1) < 0) {
        return -1;
    }
    /* test msdos magic */
    if (buf[510] != 0x55 || buf[511] != 0xaa)
        return -1;
@@ -2308,11 +2347,6 @@ void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads,
    uint64_t nb_sectors, size;
    int i, first_match, match;

    bdrv_get_geometry_hint(bs, nb_heads, max_track, last_sect);
    if (*nb_heads != 0 && *max_track != 0 && *last_sect != 0) {
        /* User defined disk */
        *rate = FDRIVE_RATE_500K;
    } else {
    bdrv_get_geometry(bs, &nb_sectors);
    match = -1;
    first_match = -1;
@@ -2348,7 +2382,6 @@ void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads,
    *drive = parse->drive;
    *rate = parse->rate;
}
}

int bdrv_get_translation_hint(BlockDriverState *bs)
{
+3 −2
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
int bdrv_create_file(const char* filename, QEMUOptionParameter *options);
BlockDriverState *bdrv_new(const char *device_name);
void bdrv_make_anon(BlockDriverState *bs);
void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
void bdrv_delete(BlockDriverState *bs);
int bdrv_parse_cache_flags(const char *mode, int *flags);
@@ -141,6 +142,8 @@ bool bdrv_dev_is_tray_open(BlockDriverState *bs);
bool bdrv_dev_is_medium_locked(BlockDriverState *bs);
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
              uint8_t *buf, int nb_sectors);
int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num,
                          uint8_t *buf, int nb_sectors);
int bdrv_write(BlockDriverState *bs, int64_t sector_num,
               const uint8_t *buf, int nb_sectors);
int bdrv_pread(BlockDriverState *bs, int64_t offset,
@@ -395,9 +398,7 @@ typedef enum {
    BLKDBG_L2_ALLOC_COW_READ,
    BLKDBG_L2_ALLOC_WRITE,

    BLKDBG_READ,
    BLKDBG_READ_AIO,
    BLKDBG_READ_BACKING,
    BLKDBG_READ_BACKING_AIO,
    BLKDBG_READ_COMPRESSED,

+61 −46
Original line number Diff line number Diff line
@@ -26,24 +26,10 @@
#include "block_int.h"
#include "module.h"

typedef struct BlkdebugVars {
    int state;

    /* If inject_errno != 0, an error is injected for requests */
    int inject_errno;

    /* Decides if all future requests fail (false) or only the next one and
     * after the next request inject_errno is reset to 0 (true) */
    bool inject_once;

    /* Decides if aio_readv/writev fails right away (true) or returns an error
     * return value only in the callback (false) */
    bool inject_immediately;
} BlkdebugVars;

typedef struct BDRVBlkdebugState {
    BlkdebugVars vars;
    QLIST_HEAD(list, BlkdebugRule) rules[BLKDBG_EVENT_MAX];
    int state;
    QLIST_HEAD(, BlkdebugRule) rules[BLKDBG_EVENT_MAX];
    QSIMPLEQ_HEAD(, BlkdebugRule) active_rules;
} BDRVBlkdebugState;

typedef struct BlkdebugAIOCB {
@@ -73,12 +59,14 @@ typedef struct BlkdebugRule {
            int error;
            int immediately;
            int once;
            int64_t sector;
        } inject;
        struct {
            int new_state;
        } set_state;
    } options;
    QLIST_ENTRY(BlkdebugRule) next;
    QSIMPLEQ_ENTRY(BlkdebugRule) active_next;
} BlkdebugRule;

static QemuOptsList inject_error_opts = {
@@ -97,6 +85,10 @@ static QemuOptsList inject_error_opts = {
            .name = "errno",
            .type = QEMU_OPT_NUMBER,
        },
        {
            .name = "sector",
            .type = QEMU_OPT_NUMBER,
        },
        {
            .name = "once",
            .type = QEMU_OPT_BOOL,
@@ -147,9 +139,7 @@ static const char *event_names[BLKDBG_EVENT_MAX] = {
    [BLKDBG_L2_ALLOC_COW_READ]              = "l2_alloc.cow_read",
    [BLKDBG_L2_ALLOC_WRITE]                 = "l2_alloc.write",

    [BLKDBG_READ]                           = "read",
    [BLKDBG_READ_AIO]                       = "read_aio",
    [BLKDBG_READ_BACKING]                   = "read_backing",
    [BLKDBG_READ_BACKING_AIO]               = "read_backing_aio",
    [BLKDBG_READ_COMPRESSED]                = "read_compressed",

@@ -228,6 +218,7 @@ static int add_rule(QemuOpts *opts, void *opaque)
        rule->options.inject.once  = qemu_opt_get_bool(opts, "once", 0);
        rule->options.inject.immediately =
            qemu_opt_get_bool(opts, "immediately", 0);
        rule->options.inject.sector = qemu_opt_get_number(opts, "sector", -1);
        break;

    case ACTION_SET_STATE:
@@ -302,7 +293,7 @@ static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)
    filename = c + 1;

    /* Set initial state */
    s->vars.state = 1;
    s->state = 1;

    /* Open the backing file */
    ret = bdrv_file_open(&bs->file, filename, flags);
@@ -328,18 +319,18 @@ static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb)
}

static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
    BlockDriverCompletionFunc *cb, void *opaque)
    BlockDriverCompletionFunc *cb, void *opaque, BlkdebugRule *rule)
{
    BDRVBlkdebugState *s = bs->opaque;
    int error = s->vars.inject_errno;
    int error = rule->options.inject.error;
    struct BlkdebugAIOCB *acb;
    QEMUBH *bh;

    if (s->vars.inject_once) {
        s->vars.inject_errno = 0;
    if (rule->options.inject.once) {
        QSIMPLEQ_INIT(&s->active_rules);
    }

    if (s->vars.inject_immediately) {
    if (rule->options.inject.immediately) {
        return NULL;
    }

@@ -358,14 +349,21 @@ static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
    BlockDriverCompletionFunc *cb, void *opaque)
{
    BDRVBlkdebugState *s = bs->opaque;
    BlkdebugRule *rule = NULL;

    QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
        if (rule->options.inject.sector == -1 ||
            (rule->options.inject.sector >= sector_num &&
             rule->options.inject.sector < sector_num + nb_sectors)) {
            break;
        }
    }

    if (s->vars.inject_errno) {
        return inject_error(bs, cb, opaque);
    if (rule && rule->options.inject.error) {
        return inject_error(bs, cb, opaque, rule);
    }

    BlockDriverAIOCB *acb =
        bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
    return acb;
    return bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
}

static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
@@ -373,14 +371,21 @@ static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
    BlockDriverCompletionFunc *cb, void *opaque)
{
    BDRVBlkdebugState *s = bs->opaque;
    BlkdebugRule *rule = NULL;

    if (s->vars.inject_errno) {
        return inject_error(bs, cb, opaque);
    QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
        if (rule->options.inject.sector == -1 ||
            (rule->options.inject.sector >= sector_num &&
             rule->options.inject.sector < sector_num + nb_sectors)) {
            break;
        }
    }

    BlockDriverAIOCB *acb =
        bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
    return acb;
    if (rule && rule->options.inject.error) {
        return inject_error(bs, cb, opaque, rule);
    }

    return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
}

static void blkdebug_close(BlockDriverState *bs)
@@ -397,42 +402,51 @@ static void blkdebug_close(BlockDriverState *bs)
    }
}

static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
    BlkdebugVars *old_vars)
static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
    int old_state, bool injected)
{
    BDRVBlkdebugState *s = bs->opaque;
    BlkdebugVars *vars = &s->vars;

    /* Only process rules for the current state */
    if (rule->state && rule->state != old_vars->state) {
        return;
    if (rule->state && rule->state != old_state) {
        return injected;
    }

    /* Take the action */
    switch (rule->action) {
    case ACTION_INJECT_ERROR:
        vars->inject_errno       = rule->options.inject.error;
        vars->inject_once        = rule->options.inject.once;
        vars->inject_immediately = rule->options.inject.immediately;
        if (!injected) {
            QSIMPLEQ_INIT(&s->active_rules);
            injected = true;
        }
        QSIMPLEQ_INSERT_HEAD(&s->active_rules, rule, active_next);
        break;

    case ACTION_SET_STATE:
        vars->state              = rule->options.set_state.new_state;
        s->state = rule->options.set_state.new_state;
        break;
    }
    return injected;
}

static void blkdebug_debug_event(BlockDriverState *bs, BlkDebugEvent event)
{
    BDRVBlkdebugState *s = bs->opaque;
    struct BlkdebugRule *rule;
    BlkdebugVars old_vars = s->vars;
    int old_state = s->state;
    bool injected;

    assert((int)event >= 0 && event < BLKDBG_EVENT_MAX);

    injected = false;
    QLIST_FOREACH(rule, &s->rules[event], next) {
        process_rule(bs, rule, &old_vars);
        injected = process_rule(bs, rule, old_state, injected);
    }
}

static int64_t blkdebug_getlength(BlockDriverState *bs)
{
    return bdrv_getlength(bs->file);
}

static BlockDriver bdrv_blkdebug = {
@@ -443,6 +457,7 @@ static BlockDriver bdrv_blkdebug = {

    .bdrv_file_open     = blkdebug_open,
    .bdrv_close         = blkdebug_close,
    .bdrv_getlength     = blkdebug_getlength,

    .bdrv_aio_readv     = blkdebug_aio_readv,
    .bdrv_aio_writev    = blkdebug_aio_writev,
+4 −3
Original line number Diff line number Diff line
@@ -627,10 +627,11 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
    BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_BYTES);
    assert(size > 0 && size <= s->cluster_size);
    if (s->free_byte_offset == 0) {
        s->free_byte_offset = qcow2_alloc_clusters(bs, s->cluster_size);
        if (s->free_byte_offset < 0) {
            return s->free_byte_offset;
        offset = qcow2_alloc_clusters(bs, s->cluster_size);
        if (offset < 0) {
            return offset;
        }
        s->free_byte_offset = offset;
    }
 redo:
    free_in_cluster = s->cluster_size -
+3 −3
Original line number Diff line number Diff line
@@ -405,7 +405,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
#ifdef DEBUG_ALLOC
    {
      BdrvCheckResult result = {0};
      qcow2_check_refcounts(bs, &result);
      qcow2_check_refcounts(bs, &result, 0);
    }
#endif
    return 0;
@@ -522,7 +522,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
#ifdef DEBUG_ALLOC
    {
        BdrvCheckResult result = {0};
        qcow2_check_refcounts(bs, &result);
        qcow2_check_refcounts(bs, &result, 0);
    }
#endif
    return 0;
@@ -582,7 +582,7 @@ int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
#ifdef DEBUG_ALLOC
    {
        BdrvCheckResult result = {0};
        qcow2_check_refcounts(bs, &result);
        qcow2_check_refcounts(bs, &result, 0);
    }
#endif
    return 0;
Loading