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

Merge remote-tracking branch 'remotes/jnsnow/tags/ide-pull-request' into staging



# gpg: Signature made Mon 18 Jul 2016 23:53:15 BST
# gpg:                using RSA key 0x7DEF8106AAFC390E
# gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>"
# Primary key fingerprint: FAEB 9711 A12C F475 812F  18F2 88A9 064D 1835 61EB
#      Subkey fingerprint: F9B7 ABDB BCAC DF95 BE76  CBD0 7DEF 8106 AAFC 390E

* remotes/jnsnow/tags/ide-pull-request:
  block: ignore flush requests when storage is clean
  tests: in IDE and AHCI tests perform DMA write before flushing
  ide: set retry_unit for PIO and FLUSH requests
  ide: refactor retry_unit set and clear into separate function

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 0c1b58f2 3ff2f67a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -234,6 +234,8 @@ BlockDriverState *bdrv_new(void)
    bs->refcnt = 1;
    bs->aio_context = qemu_get_aio_context();

    qemu_co_queue_init(&bs->flush_queue);

    QTAILQ_INSERT_TAIL(&all_bdrv_states, bs, bs_list);

    return bs;
@@ -2472,6 +2474,7 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
        ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
        bdrv_dirty_bitmap_truncate(bs);
        bdrv_parent_cb_resize(bs);
        ++bs->write_gen;
    }
    return ret;
}
+21 −0
Original line number Diff line number Diff line
@@ -1303,6 +1303,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
    }
    bdrv_debug_event(bs, BLKDBG_PWRITEV_DONE);

    ++bs->write_gen;
    bdrv_set_dirty(bs, start_sector, end_sector - start_sector);

    if (bs->wr_highest_offset < offset + bytes) {
@@ -2236,6 +2237,15 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)

    tracked_request_begin(&req, bs, 0, 0, BDRV_TRACKED_FLUSH);

    int current_gen = bs->write_gen;

    /* Wait until any previous flushes are completed */
    while (bs->flush_started_gen != bs->flushed_gen) {
        qemu_co_queue_wait(&bs->flush_queue);
    }

    bs->flush_started_gen = current_gen;

    /* Write back all layers by calling one driver function */
    if (bs->drv->bdrv_co_flush) {
        ret = bs->drv->bdrv_co_flush(bs);
@@ -2256,6 +2266,11 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
        goto flush_parent;
    }

    /* Check if we really need to flush anything */
    if (bs->flushed_gen == current_gen) {
        goto flush_parent;
    }

    BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_DISK);
    if (bs->drv->bdrv_co_flush_to_disk) {
        ret = bs->drv->bdrv_co_flush_to_disk(bs);
@@ -2286,6 +2301,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
         */
        ret = 0;
    }

    if (ret < 0) {
        goto out;
    }
@@ -2296,6 +2312,10 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
flush_parent:
    ret = bs->file ? bdrv_co_flush(bs->file->bs) : 0;
out:
    /* Notify any pending flushes that we have completed */
    bs->flushed_gen = current_gen;
    qemu_co_queue_restart_all(&bs->flush_queue);

    tracked_request_end(&req);
    return ret;
}
@@ -2421,6 +2441,7 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
    }
    ret = 0;
out:
    ++bs->write_gen;
    bdrv_set_dirty(bs, req.offset >> BDRV_SECTOR_BITS,
                   req.bytes >> BDRV_SECTOR_BITS);
    tracked_request_end(&req);
+18 −6
Original line number Diff line number Diff line
@@ -466,6 +466,20 @@ void ide_abort_command(IDEState *s)
    s->error = ABRT_ERR;
}

static void ide_set_retry(IDEState *s)
{
    s->bus->retry_unit = s->unit;
    s->bus->retry_sector_num = ide_get_sector(s);
    s->bus->retry_nsector = s->nsector;
}

static void ide_clear_retry(IDEState *s)
{
    s->bus->retry_unit = -1;
    s->bus->retry_sector_num = 0;
    s->bus->retry_nsector = 0;
}

/* prepare data transfer and tell what to do after */
void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
                        EndTransferFunc *end_transfer_func)
@@ -473,6 +487,7 @@ void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
    s->end_transfer_func = end_transfer_func;
    s->data_ptr = buf;
    s->data_end = buf + size;
    ide_set_retry(s);
    if (!(s->status & ERR_STAT)) {
        s->status |= DRQ_STAT;
    }
@@ -756,9 +771,7 @@ void dma_buf_commit(IDEState *s, uint32_t tx_bytes)
void ide_set_inactive(IDEState *s, bool more)
{
    s->bus->dma->aiocb = NULL;
    s->bus->retry_unit = -1;
    s->bus->retry_sector_num = 0;
    s->bus->retry_nsector = 0;
    ide_clear_retry(s);
    if (s->bus->dma->ops->set_inactive) {
        s->bus->dma->ops->set_inactive(s->bus->dma, more);
    }
@@ -914,9 +927,7 @@ static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd)
void ide_start_dma(IDEState *s, BlockCompletionFunc *cb)
{
    s->io_buffer_index = 0;
    s->bus->retry_unit = s->unit;
    s->bus->retry_sector_num = ide_get_sector(s);
    s->bus->retry_nsector = s->nsector;
    ide_set_retry(s);
    if (s->bus->dma->ops->start_dma) {
        s->bus->dma->ops->start_dma(s->bus->dma, s, cb);
    }
@@ -1046,6 +1057,7 @@ static void ide_flush_cache(IDEState *s)
    }

    s->status |= BUSY_STAT;
    ide_set_retry(s);
    block_acct_start(blk_get_stats(s->blk), &s->acct, 0, BLOCK_ACCT_FLUSH);
    s->pio_aiocb = blk_aio_flush(s->blk, ide_flush_cb, s);
}
+5 −0
Original line number Diff line number Diff line
@@ -439,6 +439,11 @@ struct BlockDriverState {
    int copy_on_read; /* if nonzero, copy read backing sectors into image.
                         note this is a reference count */

    CoQueue flush_queue;            /* Serializing flush queue */
    unsigned int write_gen;         /* Current data generation */
    unsigned int flush_started_gen; /* Generation for which flush has started */
    unsigned int flushed_gen;       /* Flushed write generation */

    BlockDriver *drv; /* NULL means no media */
    void *opaque;

+32 −2
Original line number Diff line number Diff line
@@ -1063,11 +1063,34 @@ static void test_dma_fragmented(void)
    g_free(tx);
}

/*
 * Write sector 1 with random data to make AHCI storage dirty
 * Needed for flush tests so that flushes actually go though the block layer
 */
static void make_dirty(AHCIQState* ahci, uint8_t port)
{
    uint64_t ptr;
    unsigned bufsize = 512;

    ptr = ahci_alloc(ahci, bufsize);
    g_assert(ptr);

    ahci_guest_io(ahci, port, CMD_WRITE_DMA, ptr, bufsize, 1);
    ahci_free(ahci, ptr);
}

static void test_flush(void)
{
    AHCIQState *ahci;
    uint8_t port;

    ahci = ahci_boot_and_enable(NULL);

    port = ahci_port_select(ahci);
    ahci_port_clear(ahci, port);

    make_dirty(ahci, port);

    ahci_test_flush(ahci);
    ahci_shutdown(ahci);
}
@@ -1087,10 +1110,13 @@ static void test_flush_retry(void)
                                debug_path,
                                tmp_path, imgfmt);

    /* Issue Flush Command and wait for error */
    port = ahci_port_select(ahci);
    ahci_port_clear(ahci, port);

    /* Issue write so that flush actually goes to disk */
    make_dirty(ahci, port);

    /* Issue Flush Command and wait for error */
    cmd = ahci_guest_io_halt(ahci, port, CMD_FLUSH_CACHE, 0, 0, 0);
    ahci_guest_io_resume(ahci, cmd);

@@ -1343,9 +1369,13 @@ static void test_flush_migrate(void)

    set_context(src->parent);

    /* Issue Flush Command */
    px = ahci_port_select(src);
    ahci_port_clear(src, px);

    /* Dirty device so that flush reaches disk */
    make_dirty(src, px);

    /* Issue Flush Command */
    cmd = ahci_command_create(CMD_FLUSH_CACHE);
    ahci_command_commit(src, cmd, px);
    ahci_command_issue_async(src, cmd);
Loading