Merge remote-tracking branch 'kwolf/for-anthony' into staging
* kwolf/for-anthony: (26 commits) qemu-io: Use bdrv_drain_all instead of qemu_aio_flush megasas: Use bdrv_drain_all instead of qemu_aio_flush vmdk: Fix data corruption bug in WRITE and READ handling fdc: remove last usage of FD_STATE_SEEK fdc: fix typo in zero constant fdc: remove double affectation of FD_MSR_CMDBUSY flag fdc-tests: add tests for VERIFY command fdc: implement VERIFY command fdc-test: Check READ ID fdc: fix false FD_SR0_SEEK fdc: fix FD_SR0_SEEK for initial seek on DMA transfers fdc: fix FD_SR0_SEEK for non-DMA transfers and multi sectors transfers fdc: use status0 field instead of a local variable fdc-test: add tests for non-DMA READ command fdc-test: insert media before fuzzing registers fdc-test: split test_media_change() test, so insert part can be reused fdc: Remove status0 parameter from fdctrl_set_fifo() aio: rename AIOPool to AIOCBInfo aio: use g_slice_alloc() for AIOCB pooling aio: switch aiocb_size type int -> size_t ... Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
		
						commit
						ad1db3b341
					
				@ -553,6 +553,7 @@ T: git git://github.com/kvaneesh/QEMU.git
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
virtio-blk
 | 
					virtio-blk
 | 
				
			||||||
M: Kevin Wolf <kwolf@redhat.com>
 | 
					M: Kevin Wolf <kwolf@redhat.com>
 | 
				
			||||||
 | 
					M: Stefan Hajnoczi <stefanha@redhat.com>
 | 
				
			||||||
S: Supported
 | 
					S: Supported
 | 
				
			||||||
F: hw/virtio-blk*
 | 
					F: hw/virtio-blk*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -583,6 +584,7 @@ F: audio/
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Block
 | 
					Block
 | 
				
			||||||
M: Kevin Wolf <kwolf@redhat.com>
 | 
					M: Kevin Wolf <kwolf@redhat.com>
 | 
				
			||||||
 | 
					M: Stefan Hajnoczi <stefanha@redhat.com>
 | 
				
			||||||
S: Supported
 | 
					S: Supported
 | 
				
			||||||
F: block*
 | 
					F: block*
 | 
				
			||||||
F: block/
 | 
					F: block/
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										31
									
								
								block.c
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								block.c
									
									
									
									
									
								
							@ -3521,7 +3521,7 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void bdrv_aio_cancel(BlockDriverAIOCB *acb)
 | 
					void bdrv_aio_cancel(BlockDriverAIOCB *acb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    acb->pool->cancel(acb);
 | 
					    acb->aiocb_info->cancel(acb);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* block I/O throttling */
 | 
					/* block I/O throttling */
 | 
				
			||||||
@ -3711,7 +3711,7 @@ static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
 | 
				
			|||||||
    qemu_aio_release(acb);
 | 
					    qemu_aio_release(acb);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool bdrv_em_aio_pool = {
 | 
					static const AIOCBInfo bdrv_em_aiocb_info = {
 | 
				
			||||||
    .aiocb_size         = sizeof(BlockDriverAIOCBSync),
 | 
					    .aiocb_size         = sizeof(BlockDriverAIOCBSync),
 | 
				
			||||||
    .cancel             = bdrv_aio_cancel_em,
 | 
					    .cancel             = bdrv_aio_cancel_em,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -3740,7 +3740,7 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    BlockDriverAIOCBSync *acb;
 | 
					    BlockDriverAIOCBSync *acb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&bdrv_em_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
    acb->is_write = is_write;
 | 
					    acb->is_write = is_write;
 | 
				
			||||||
    acb->qiov = qiov;
 | 
					    acb->qiov = qiov;
 | 
				
			||||||
    acb->bounce = qemu_blockalign(bs, qiov->size);
 | 
					    acb->bounce = qemu_blockalign(bs, qiov->size);
 | 
				
			||||||
@ -3785,7 +3785,7 @@ static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb)
 | 
				
			|||||||
    qemu_aio_flush();
 | 
					    qemu_aio_flush();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool bdrv_em_co_aio_pool = {
 | 
					static const AIOCBInfo bdrv_em_co_aiocb_info = {
 | 
				
			||||||
    .aiocb_size         = sizeof(BlockDriverAIOCBCoroutine),
 | 
					    .aiocb_size         = sizeof(BlockDriverAIOCBCoroutine),
 | 
				
			||||||
    .cancel             = bdrv_aio_co_cancel_em,
 | 
					    .cancel             = bdrv_aio_co_cancel_em,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -3828,7 +3828,7 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
 | 
				
			|||||||
    Coroutine *co;
 | 
					    Coroutine *co;
 | 
				
			||||||
    BlockDriverAIOCBCoroutine *acb;
 | 
					    BlockDriverAIOCBCoroutine *acb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&bdrv_em_co_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
    acb->req.sector = sector_num;
 | 
					    acb->req.sector = sector_num;
 | 
				
			||||||
    acb->req.nb_sectors = nb_sectors;
 | 
					    acb->req.nb_sectors = nb_sectors;
 | 
				
			||||||
    acb->req.qiov = qiov;
 | 
					    acb->req.qiov = qiov;
 | 
				
			||||||
@ -3858,7 +3858,7 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
 | 
				
			|||||||
    Coroutine *co;
 | 
					    Coroutine *co;
 | 
				
			||||||
    BlockDriverAIOCBCoroutine *acb;
 | 
					    BlockDriverAIOCBCoroutine *acb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&bdrv_em_co_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
    co = qemu_coroutine_create(bdrv_aio_flush_co_entry);
 | 
					    co = qemu_coroutine_create(bdrv_aio_flush_co_entry);
 | 
				
			||||||
    qemu_coroutine_enter(co, acb);
 | 
					    qemu_coroutine_enter(co, acb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -3884,7 +3884,7 @@ BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    trace_bdrv_aio_discard(bs, sector_num, nb_sectors, opaque);
 | 
					    trace_bdrv_aio_discard(bs, sector_num, nb_sectors, opaque);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&bdrv_em_co_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
    acb->req.sector = sector_num;
 | 
					    acb->req.sector = sector_num;
 | 
				
			||||||
    acb->req.nb_sectors = nb_sectors;
 | 
					    acb->req.nb_sectors = nb_sectors;
 | 
				
			||||||
    co = qemu_coroutine_create(bdrv_aio_discard_co_entry);
 | 
					    co = qemu_coroutine_create(bdrv_aio_discard_co_entry);
 | 
				
			||||||
@ -3904,18 +3904,13 @@ void bdrv_init_with_whitelist(void)
 | 
				
			|||||||
    bdrv_init();
 | 
					    bdrv_init();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
 | 
					void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
 | 
				
			||||||
                   BlockDriverCompletionFunc *cb, void *opaque)
 | 
					                   BlockDriverCompletionFunc *cb, void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BlockDriverAIOCB *acb;
 | 
					    BlockDriverAIOCB *acb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (pool->free_aiocb) {
 | 
					    acb = g_slice_alloc(aiocb_info->aiocb_size);
 | 
				
			||||||
        acb = pool->free_aiocb;
 | 
					    acb->aiocb_info = aiocb_info;
 | 
				
			||||||
        pool->free_aiocb = acb->next;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        acb = g_malloc0(pool->aiocb_size);
 | 
					 | 
				
			||||||
        acb->pool = pool;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    acb->bs = bs;
 | 
					    acb->bs = bs;
 | 
				
			||||||
    acb->cb = cb;
 | 
					    acb->cb = cb;
 | 
				
			||||||
    acb->opaque = opaque;
 | 
					    acb->opaque = opaque;
 | 
				
			||||||
@ -3924,10 +3919,8 @@ void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void qemu_aio_release(void *p)
 | 
					void qemu_aio_release(void *p)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BlockDriverAIOCB *acb = (BlockDriverAIOCB *)p;
 | 
					    BlockDriverAIOCB *acb = p;
 | 
				
			||||||
    AIOPool *pool = acb->pool;
 | 
					    g_slice_free1(acb->aiocb_info->aiocb_size, acb);
 | 
				
			||||||
    acb->next = pool->free_aiocb;
 | 
					 | 
				
			||||||
    pool->free_aiocb = acb;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**************************************************************/
 | 
					/**************************************************************/
 | 
				
			||||||
 | 
				
			|||||||
@ -41,7 +41,7 @@ typedef struct BlkdebugAIOCB {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb);
 | 
					static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool blkdebug_aio_pool = {
 | 
					static const AIOCBInfo blkdebug_aiocb_info = {
 | 
				
			||||||
    .aiocb_size = sizeof(BlkdebugAIOCB),
 | 
					    .aiocb_size = sizeof(BlkdebugAIOCB),
 | 
				
			||||||
    .cancel     = blkdebug_aio_cancel,
 | 
					    .cancel     = blkdebug_aio_cancel,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -335,7 +335,7 @@ static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
 | 
				
			|||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&blkdebug_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&blkdebug_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
    acb->ret = -error;
 | 
					    acb->ret = -error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bh = qemu_bh_new(error_callback_bh, acb);
 | 
					    bh = qemu_bh_new(error_callback_bh, acb);
 | 
				
			||||||
 | 
				
			|||||||
@ -48,7 +48,7 @@ static void blkverify_aio_cancel(BlockDriverAIOCB *blockacb)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool blkverify_aio_pool = {
 | 
					static const AIOCBInfo blkverify_aiocb_info = {
 | 
				
			||||||
    .aiocb_size         = sizeof(BlkverifyAIOCB),
 | 
					    .aiocb_size         = sizeof(BlkverifyAIOCB),
 | 
				
			||||||
    .cancel             = blkverify_aio_cancel,
 | 
					    .cancel             = blkverify_aio_cancel,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -233,7 +233,7 @@ static BlkverifyAIOCB *blkverify_aio_get(BlockDriverState *bs, bool is_write,
 | 
				
			|||||||
                                         BlockDriverCompletionFunc *cb,
 | 
					                                         BlockDriverCompletionFunc *cb,
 | 
				
			||||||
                                         void *opaque)
 | 
					                                         void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BlkverifyAIOCB *acb = qemu_aio_get(&blkverify_aio_pool, bs, cb, opaque);
 | 
					    BlkverifyAIOCB *acb = qemu_aio_get(&blkverify_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb->bh = NULL;
 | 
					    acb->bh = NULL;
 | 
				
			||||||
    acb->is_write = is_write;
 | 
					    acb->is_write = is_write;
 | 
				
			||||||
 | 
				
			|||||||
@ -438,7 +438,7 @@ static void curl_aio_cancel(BlockDriverAIOCB *blockacb)
 | 
				
			|||||||
    // Do we have to implement canceling? Seems to work without...
 | 
					    // Do we have to implement canceling? Seems to work without...
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool curl_aio_pool = {
 | 
					static const AIOCBInfo curl_aiocb_info = {
 | 
				
			||||||
    .aiocb_size         = sizeof(CURLAIOCB),
 | 
					    .aiocb_size         = sizeof(CURLAIOCB),
 | 
				
			||||||
    .cancel             = curl_aio_cancel,
 | 
					    .cancel             = curl_aio_cancel,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -505,7 +505,7 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    CURLAIOCB *acb;
 | 
					    CURLAIOCB *acb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&curl_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&curl_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb->qiov = qiov;
 | 
					    acb->qiov = qiov;
 | 
				
			||||||
    acb->sector_num = sector_num;
 | 
					    acb->sector_num = sector_num;
 | 
				
			||||||
 | 
				
			|||||||
@ -388,7 +388,7 @@ static void qemu_gluster_aio_cancel(BlockDriverAIOCB *blockacb)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool gluster_aio_pool = {
 | 
					static const AIOCBInfo gluster_aiocb_info = {
 | 
				
			||||||
    .aiocb_size = sizeof(GlusterAIOCB),
 | 
					    .aiocb_size = sizeof(GlusterAIOCB),
 | 
				
			||||||
    .cancel = qemu_gluster_aio_cancel,
 | 
					    .cancel = qemu_gluster_aio_cancel,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -439,7 +439,7 @@ static BlockDriverAIOCB *qemu_gluster_aio_rw(BlockDriverState *bs,
 | 
				
			|||||||
    size = nb_sectors * BDRV_SECTOR_SIZE;
 | 
					    size = nb_sectors * BDRV_SECTOR_SIZE;
 | 
				
			||||||
    s->qemu_aio_count++;
 | 
					    s->qemu_aio_count++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&gluster_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&gluster_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
    acb->size = size;
 | 
					    acb->size = size;
 | 
				
			||||||
    acb->ret = 0;
 | 
					    acb->ret = 0;
 | 
				
			||||||
    acb->finished = NULL;
 | 
					    acb->finished = NULL;
 | 
				
			||||||
@ -484,7 +484,7 @@ static BlockDriverAIOCB *qemu_gluster_aio_flush(BlockDriverState *bs,
 | 
				
			|||||||
    GlusterAIOCB *acb;
 | 
					    GlusterAIOCB *acb;
 | 
				
			||||||
    BDRVGlusterState *s = bs->opaque;
 | 
					    BDRVGlusterState *s = bs->opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&gluster_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&gluster_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
    acb->size = 0;
 | 
					    acb->size = 0;
 | 
				
			||||||
    acb->ret = 0;
 | 
					    acb->ret = 0;
 | 
				
			||||||
    acb->finished = NULL;
 | 
					    acb->finished = NULL;
 | 
				
			||||||
 | 
				
			|||||||
@ -133,7 +133,7 @@ iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool iscsi_aio_pool = {
 | 
					static const AIOCBInfo iscsi_aiocb_info = {
 | 
				
			||||||
    .aiocb_size         = sizeof(IscsiAIOCB),
 | 
					    .aiocb_size         = sizeof(IscsiAIOCB),
 | 
				
			||||||
    .cancel             = iscsi_aio_cancel,
 | 
					    .cancel             = iscsi_aio_cancel,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -234,7 +234,7 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
 | 
				
			|||||||
    uint64_t lba;
 | 
					    uint64_t lba;
 | 
				
			||||||
    struct iscsi_data data;
 | 
					    struct iscsi_data data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
    trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);
 | 
					    trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb->iscsilun = iscsilun;
 | 
					    acb->iscsilun = iscsilun;
 | 
				
			||||||
@ -325,7 +325,7 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;
 | 
					    qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
    trace_iscsi_aio_readv(iscsi, sector_num, nb_sectors, opaque, acb);
 | 
					    trace_iscsi_aio_readv(iscsi, sector_num, nb_sectors, opaque, acb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb->iscsilun = iscsilun;
 | 
					    acb->iscsilun = iscsilun;
 | 
				
			||||||
@ -430,7 +430,7 @@ iscsi_aio_flush(BlockDriverState *bs,
 | 
				
			|||||||
    struct iscsi_context *iscsi = iscsilun->iscsi;
 | 
					    struct iscsi_context *iscsi = iscsilun->iscsi;
 | 
				
			||||||
    IscsiAIOCB *acb;
 | 
					    IscsiAIOCB *acb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb->iscsilun = iscsilun;
 | 
					    acb->iscsilun = iscsilun;
 | 
				
			||||||
    acb->canceled   = 0;
 | 
					    acb->canceled   = 0;
 | 
				
			||||||
@ -483,7 +483,7 @@ iscsi_aio_discard(BlockDriverState *bs,
 | 
				
			|||||||
    IscsiAIOCB *acb;
 | 
					    IscsiAIOCB *acb;
 | 
				
			||||||
    struct unmap_list list[1];
 | 
					    struct unmap_list list[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb->iscsilun = iscsilun;
 | 
					    acb->iscsilun = iscsilun;
 | 
				
			||||||
    acb->canceled   = 0;
 | 
					    acb->canceled   = 0;
 | 
				
			||||||
@ -558,7 +558,7 @@ static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    assert(req == SG_IO);
 | 
					    assert(req == SG_IO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb->iscsilun = iscsilun;
 | 
					    acb->iscsilun = iscsilun;
 | 
				
			||||||
    acb->canceled    = 0;
 | 
					    acb->canceled    = 0;
 | 
				
			||||||
 | 
				
			|||||||
@ -140,7 +140,7 @@ static void laio_cancel(BlockDriverAIOCB *blockacb)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool laio_pool = {
 | 
					static const AIOCBInfo laio_aiocb_info = {
 | 
				
			||||||
    .aiocb_size         = sizeof(struct qemu_laiocb),
 | 
					    .aiocb_size         = sizeof(struct qemu_laiocb),
 | 
				
			||||||
    .cancel             = laio_cancel,
 | 
					    .cancel             = laio_cancel,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -154,7 +154,7 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
 | 
				
			|||||||
    struct iocb *iocbs;
 | 
					    struct iocb *iocbs;
 | 
				
			||||||
    off_t offset = sector_num * 512;
 | 
					    off_t offset = sector_num * 512;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    laiocb = qemu_aio_get(&laio_pool, bs, cb, opaque);
 | 
					    laiocb = qemu_aio_get(&laio_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
    laiocb->nbytes = nb_sectors * 512;
 | 
					    laiocb->nbytes = nb_sectors * 512;
 | 
				
			||||||
    laiocb->ctx = s;
 | 
					    laiocb->ctx = s;
 | 
				
			||||||
    laiocb->ret = -EINPROGRESS;
 | 
					    laiocb->ret = -EINPROGRESS;
 | 
				
			||||||
 | 
				
			|||||||
@ -301,7 +301,8 @@ static int alloc_refcount_block(BlockDriverState *bs,
 | 
				
			|||||||
    uint64_t last_table_size;
 | 
					    uint64_t last_table_size;
 | 
				
			||||||
    uint64_t blocks_clusters;
 | 
					    uint64_t blocks_clusters;
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        uint64_t table_clusters = size_to_clusters(s, table_size);
 | 
					        uint64_t table_clusters =
 | 
				
			||||||
 | 
					            size_to_clusters(s, table_size * sizeof(uint64_t));
 | 
				
			||||||
        blocks_clusters = 1 +
 | 
					        blocks_clusters = 1 +
 | 
				
			||||||
            ((table_clusters + refcount_block_clusters - 1)
 | 
					            ((table_clusters + refcount_block_clusters - 1)
 | 
				
			||||||
            / refcount_block_clusters);
 | 
					            / refcount_block_clusters);
 | 
				
			||||||
 | 
				
			|||||||
@ -30,7 +30,7 @@ static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool qed_aio_pool = {
 | 
					static const AIOCBInfo qed_aiocb_info = {
 | 
				
			||||||
    .aiocb_size         = sizeof(QEDAIOCB),
 | 
					    .aiocb_size         = sizeof(QEDAIOCB),
 | 
				
			||||||
    .cancel             = qed_aio_cancel,
 | 
					    .cancel             = qed_aio_cancel,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -1311,7 +1311,7 @@ static BlockDriverAIOCB *qed_aio_setup(BlockDriverState *bs,
 | 
				
			|||||||
                                       BlockDriverCompletionFunc *cb,
 | 
					                                       BlockDriverCompletionFunc *cb,
 | 
				
			||||||
                                       void *opaque, int flags)
 | 
					                                       void *opaque, int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    QEDAIOCB *acb = qemu_aio_get(&qed_aio_pool, bs, cb, opaque);
 | 
					    QEDAIOCB *acb = qemu_aio_get(&qed_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    trace_qed_aio_setup(bs->opaque, acb, sector_num, nb_sectors,
 | 
					    trace_qed_aio_setup(bs->opaque, acb, sector_num, nb_sectors,
 | 
				
			||||||
                        opaque, flags);
 | 
					                        opaque, flags);
 | 
				
			||||||
 | 
				
			|||||||
@ -570,7 +570,7 @@ static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb)
 | 
				
			|||||||
    acb->cancelled = 1;
 | 
					    acb->cancelled = 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool rbd_aio_pool = {
 | 
					static const AIOCBInfo rbd_aiocb_info = {
 | 
				
			||||||
    .aiocb_size = sizeof(RBDAIOCB),
 | 
					    .aiocb_size = sizeof(RBDAIOCB),
 | 
				
			||||||
    .cancel = qemu_rbd_aio_cancel,
 | 
					    .cancel = qemu_rbd_aio_cancel,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -672,7 +672,7 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    BDRVRBDState *s = bs->opaque;
 | 
					    BDRVRBDState *s = bs->opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&rbd_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&rbd_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
    acb->cmd = cmd;
 | 
					    acb->cmd = cmd;
 | 
				
			||||||
    acb->qiov = qiov;
 | 
					    acb->qiov = qiov;
 | 
				
			||||||
    if (cmd == RBD_AIO_DISCARD) {
 | 
					    if (cmd == RBD_AIO_DISCARD) {
 | 
				
			||||||
 | 
				
			|||||||
@ -420,7 +420,7 @@ static void sd_aio_cancel(BlockDriverAIOCB *blockacb)
 | 
				
			|||||||
    acb->canceled = true;
 | 
					    acb->canceled = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool sd_aio_pool = {
 | 
					static const AIOCBInfo sd_aiocb_info = {
 | 
				
			||||||
    .aiocb_size = sizeof(SheepdogAIOCB),
 | 
					    .aiocb_size = sizeof(SheepdogAIOCB),
 | 
				
			||||||
    .cancel = sd_aio_cancel,
 | 
					    .cancel = sd_aio_cancel,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -431,7 +431,7 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    SheepdogAIOCB *acb;
 | 
					    SheepdogAIOCB *acb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = qemu_aio_get(&sd_aio_pool, bs, cb, opaque);
 | 
					    acb = qemu_aio_get(&sd_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb->qiov = qiov;
 | 
					    acb->qiov = qiov;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								block/vmdk.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								block/vmdk.c
									
									
									
									
									
								
							@ -1092,6 +1092,7 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
 | 
				
			|||||||
    BDRVVmdkState *s = bs->opaque;
 | 
					    BDRVVmdkState *s = bs->opaque;
 | 
				
			||||||
    int ret;
 | 
					    int ret;
 | 
				
			||||||
    uint64_t n, index_in_cluster;
 | 
					    uint64_t n, index_in_cluster;
 | 
				
			||||||
 | 
					    uint64_t extent_begin_sector, extent_relative_sector_num;
 | 
				
			||||||
    VmdkExtent *extent = NULL;
 | 
					    VmdkExtent *extent = NULL;
 | 
				
			||||||
    uint64_t cluster_offset;
 | 
					    uint64_t cluster_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1103,7 +1104,9 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
 | 
				
			|||||||
        ret = get_cluster_offset(
 | 
					        ret = get_cluster_offset(
 | 
				
			||||||
                            bs, extent, NULL,
 | 
					                            bs, extent, NULL,
 | 
				
			||||||
                            sector_num << 9, 0, &cluster_offset);
 | 
					                            sector_num << 9, 0, &cluster_offset);
 | 
				
			||||||
        index_in_cluster = sector_num % extent->cluster_sectors;
 | 
					        extent_begin_sector = extent->end_sector - extent->sectors;
 | 
				
			||||||
 | 
					        extent_relative_sector_num = sector_num - extent_begin_sector;
 | 
				
			||||||
 | 
					        index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
 | 
				
			||||||
        n = extent->cluster_sectors - index_in_cluster;
 | 
					        n = extent->cluster_sectors - index_in_cluster;
 | 
				
			||||||
        if (n > nb_sectors) {
 | 
					        if (n > nb_sectors) {
 | 
				
			||||||
            n = nb_sectors;
 | 
					            n = nb_sectors;
 | 
				
			||||||
@ -1154,6 +1157,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
 | 
				
			|||||||
    VmdkExtent *extent = NULL;
 | 
					    VmdkExtent *extent = NULL;
 | 
				
			||||||
    int n, ret;
 | 
					    int n, ret;
 | 
				
			||||||
    int64_t index_in_cluster;
 | 
					    int64_t index_in_cluster;
 | 
				
			||||||
 | 
					    uint64_t extent_begin_sector, extent_relative_sector_num;
 | 
				
			||||||
    uint64_t cluster_offset;
 | 
					    uint64_t cluster_offset;
 | 
				
			||||||
    VmdkMetaData m_data;
 | 
					    VmdkMetaData m_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1196,7 +1200,9 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
 | 
				
			|||||||
        if (ret) {
 | 
					        if (ret) {
 | 
				
			||||||
            return -EINVAL;
 | 
					            return -EINVAL;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        index_in_cluster = sector_num % extent->cluster_sectors;
 | 
					        extent_begin_sector = extent->end_sector - extent->sectors;
 | 
				
			||||||
 | 
					        extent_relative_sector_num = sector_num - extent_begin_sector;
 | 
				
			||||||
 | 
					        index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
 | 
				
			||||||
        n = extent->cluster_sectors - index_in_cluster;
 | 
					        n = extent->cluster_sectors - index_in_cluster;
 | 
				
			||||||
        if (n > nb_sectors) {
 | 
					        if (n > nb_sectors) {
 | 
				
			||||||
            n = nb_sectors;
 | 
					            n = nb_sectors;
 | 
				
			||||||
 | 
				
			|||||||
@ -131,7 +131,7 @@ static void win32_aio_cancel(BlockDriverAIOCB *blockacb)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool win32_aio_pool = {
 | 
					static const AIOCBInfo win32_aiocb_info = {
 | 
				
			||||||
    .aiocb_size         = sizeof(QEMUWin32AIOCB),
 | 
					    .aiocb_size         = sizeof(QEMUWin32AIOCB),
 | 
				
			||||||
    .cancel             = win32_aio_cancel,
 | 
					    .cancel             = win32_aio_cancel,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -145,7 +145,7 @@ BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
 | 
				
			|||||||
    uint64_t offset = sector_num * 512;
 | 
					    uint64_t offset = sector_num * 512;
 | 
				
			||||||
    DWORD rc;
 | 
					    DWORD rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    waiocb = qemu_aio_get(&win32_aio_pool, bs, cb, opaque);
 | 
					    waiocb = qemu_aio_get(&win32_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
    waiocb->nbytes = nb_sectors * 512;
 | 
					    waiocb->nbytes = nb_sectors * 512;
 | 
				
			||||||
    waiocb->qiov = qiov;
 | 
					    waiocb->qiov = qiov;
 | 
				
			||||||
    waiocb->is_read = (type == QEMU_AIO_READ);
 | 
					    waiocb->is_read = (type == QEMU_AIO_READ);
 | 
				
			||||||
@ -167,11 +167,11 @@ BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
 | 
				
			|||||||
        waiocb->is_linear = true;
 | 
					        waiocb->is_linear = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    waiocb->ov = (OVERLAPPED) {
 | 
					    memset(&waiocb->ov, 0, sizeof(waiocb->ov));
 | 
				
			||||||
        .Offset = (DWORD) offset,
 | 
					    waiocb->ov.Offset = (DWORD)offset;
 | 
				
			||||||
        .OffsetHigh = (DWORD) (offset >> 32),
 | 
					    waiocb->ov.OffsetHigh = (DWORD)(offset >> 32);
 | 
				
			||||||
        .hEvent = event_notifier_get_handle(&aio->e)
 | 
					    waiocb->ov.hEvent = event_notifier_get_handle(&aio->e);
 | 
				
			||||||
    };
 | 
					
 | 
				
			||||||
    aio->count++;
 | 
					    aio->count++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (type & QEMU_AIO_READ) {
 | 
					    if (type & QEMU_AIO_READ) {
 | 
				
			||||||
 | 
				
			|||||||
@ -195,7 +195,7 @@ static void dma_aio_cancel(BlockDriverAIOCB *acb)
 | 
				
			|||||||
    dma_complete(dbs, 0);
 | 
					    dma_complete(dbs, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool dma_aio_pool = {
 | 
					static const AIOCBInfo dma_aiocb_info = {
 | 
				
			||||||
    .aiocb_size         = sizeof(DMAAIOCB),
 | 
					    .aiocb_size         = sizeof(DMAAIOCB),
 | 
				
			||||||
    .cancel             = dma_aio_cancel,
 | 
					    .cancel             = dma_aio_cancel,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -205,7 +205,7 @@ BlockDriverAIOCB *dma_bdrv_io(
 | 
				
			|||||||
    DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
 | 
					    DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
 | 
				
			||||||
    void *opaque, DMADirection dir)
 | 
					    void *opaque, DMADirection dir)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    DMAAIOCB *dbs = qemu_aio_get(&dma_aio_pool, bs, cb, opaque);
 | 
					    DMAAIOCB *dbs = qemu_aio_get(&dma_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    trace_dma_bdrv_io(dbs, bs, sector_num, (dir == DMA_DIRECTION_TO_DEVICE));
 | 
					    trace_dma_bdrv_io(dbs, bs, sector_num, (dir == DMA_DIRECTION_TO_DEVICE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										109
									
								
								hw/fdc.c
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								hw/fdc.c
									
									
									
									
									
								
							@ -327,7 +327,7 @@ static void fdctrl_reset(FDCtrl *fdctrl, int do_irq);
 | 
				
			|||||||
static void fdctrl_reset_fifo(FDCtrl *fdctrl);
 | 
					static void fdctrl_reset_fifo(FDCtrl *fdctrl);
 | 
				
			||||||
static int fdctrl_transfer_handler (void *opaque, int nchan,
 | 
					static int fdctrl_transfer_handler (void *opaque, int nchan,
 | 
				
			||||||
                                    int dma_pos, int dma_len);
 | 
					                                    int dma_pos, int dma_len);
 | 
				
			||||||
static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0);
 | 
					static void fdctrl_raise_irq(FDCtrl *fdctrl);
 | 
				
			||||||
static FDrive *get_cur_drv(FDCtrl *fdctrl);
 | 
					static FDrive *get_cur_drv(FDCtrl *fdctrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint32_t fdctrl_read_statusA(FDCtrl *fdctrl);
 | 
					static uint32_t fdctrl_read_statusA(FDCtrl *fdctrl);
 | 
				
			||||||
@ -349,12 +349,12 @@ enum {
 | 
				
			|||||||
    FD_DIR_SCANE   = 2,
 | 
					    FD_DIR_SCANE   = 2,
 | 
				
			||||||
    FD_DIR_SCANL   = 3,
 | 
					    FD_DIR_SCANL   = 3,
 | 
				
			||||||
    FD_DIR_SCANH   = 4,
 | 
					    FD_DIR_SCANH   = 4,
 | 
				
			||||||
 | 
					    FD_DIR_VERIFY  = 5,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
    FD_STATE_MULTI  = 0x01,	/* multi track flag */
 | 
					    FD_STATE_MULTI  = 0x01,	/* multi track flag */
 | 
				
			||||||
    FD_STATE_FORMAT = 0x02,	/* format flag */
 | 
					    FD_STATE_FORMAT = 0x02,	/* format flag */
 | 
				
			||||||
    FD_STATE_SEEK   = 0x04,	/* seek flag */
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
@ -496,7 +496,6 @@ enum {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI)
 | 
					#define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI)
 | 
				
			||||||
#define FD_DID_SEEK(state) ((state) & FD_STATE_SEEK)
 | 
					 | 
				
			||||||
#define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT)
 | 
					#define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct FDCtrl {
 | 
					struct FDCtrl {
 | 
				
			||||||
@ -799,6 +798,7 @@ static void fdctrl_handle_tc(void *opaque, int irq, int level)
 | 
				
			|||||||
/* Change IRQ state */
 | 
					/* Change IRQ state */
 | 
				
			||||||
static void fdctrl_reset_irq(FDCtrl *fdctrl)
 | 
					static void fdctrl_reset_irq(FDCtrl *fdctrl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    fdctrl->status0 = 0;
 | 
				
			||||||
    if (!(fdctrl->sra & FD_SRA_INTPEND))
 | 
					    if (!(fdctrl->sra & FD_SRA_INTPEND))
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    FLOPPY_DPRINTF("Reset interrupt\n");
 | 
					    FLOPPY_DPRINTF("Reset interrupt\n");
 | 
				
			||||||
@ -806,14 +806,13 @@ static void fdctrl_reset_irq(FDCtrl *fdctrl)
 | 
				
			|||||||
    fdctrl->sra &= ~FD_SRA_INTPEND;
 | 
					    fdctrl->sra &= ~FD_SRA_INTPEND;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0)
 | 
					static void fdctrl_raise_irq(FDCtrl *fdctrl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* Sparc mutation */
 | 
					    /* Sparc mutation */
 | 
				
			||||||
    if (fdctrl->sun4m && (fdctrl->msr & FD_MSR_CMDBUSY)) {
 | 
					    if (fdctrl->sun4m && (fdctrl->msr & FD_MSR_CMDBUSY)) {
 | 
				
			||||||
        /* XXX: not sure */
 | 
					        /* XXX: not sure */
 | 
				
			||||||
        fdctrl->msr &= ~FD_MSR_CMDBUSY;
 | 
					        fdctrl->msr &= ~FD_MSR_CMDBUSY;
 | 
				
			||||||
        fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
 | 
					        fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
 | 
				
			||||||
        fdctrl->status0 = status0;
 | 
					 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!(fdctrl->sra & FD_SRA_INTPEND)) {
 | 
					    if (!(fdctrl->sra & FD_SRA_INTPEND)) {
 | 
				
			||||||
@ -822,7 +821,6 @@ static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fdctrl->reset_sensei = 0;
 | 
					    fdctrl->reset_sensei = 0;
 | 
				
			||||||
    fdctrl->status0 = status0;
 | 
					 | 
				
			||||||
    FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0);
 | 
					    FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -851,7 +849,8 @@ static void fdctrl_reset(FDCtrl *fdctrl, int do_irq)
 | 
				
			|||||||
        fd_recalibrate(&fdctrl->drives[i]);
 | 
					        fd_recalibrate(&fdctrl->drives[i]);
 | 
				
			||||||
    fdctrl_reset_fifo(fdctrl);
 | 
					    fdctrl_reset_fifo(fdctrl);
 | 
				
			||||||
    if (do_irq) {
 | 
					    if (do_irq) {
 | 
				
			||||||
        fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG);
 | 
					        fdctrl->status0 |= FD_SR0_RDYCHG;
 | 
				
			||||||
 | 
					        fdctrl_raise_irq(fdctrl);
 | 
				
			||||||
        fdctrl->reset_sensei = FD_RESET_SENSEI_COUNT;
 | 
					        fdctrl->reset_sensei = FD_RESET_SENSEI_COUNT;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1079,15 +1078,12 @@ static void fdctrl_reset_fifo(FDCtrl *fdctrl)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Set FIFO status for the host to read */
 | 
					/* Set FIFO status for the host to read */
 | 
				
			||||||
static void fdctrl_set_fifo(FDCtrl *fdctrl, int fifo_len, uint8_t status0)
 | 
					static void fdctrl_set_fifo(FDCtrl *fdctrl, int fifo_len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    fdctrl->data_dir = FD_DIR_READ;
 | 
					    fdctrl->data_dir = FD_DIR_READ;
 | 
				
			||||||
    fdctrl->data_len = fifo_len;
 | 
					    fdctrl->data_len = fifo_len;
 | 
				
			||||||
    fdctrl->data_pos = 0;
 | 
					    fdctrl->data_pos = 0;
 | 
				
			||||||
    fdctrl->msr |= FD_MSR_CMDBUSY | FD_MSR_RQM | FD_MSR_DIO;
 | 
					    fdctrl->msr |= FD_MSR_CMDBUSY | FD_MSR_RQM | FD_MSR_DIO;
 | 
				
			||||||
    if (status0) {
 | 
					 | 
				
			||||||
        fdctrl_raise_irq(fdctrl, status0);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Set an error: unimplemented/unknown command */
 | 
					/* Set an error: unimplemented/unknown command */
 | 
				
			||||||
@ -1096,7 +1092,7 @@ static void fdctrl_unimplemented(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
    qemu_log_mask(LOG_UNIMP, "fdc: unimplemented command 0x%02x\n",
 | 
					    qemu_log_mask(LOG_UNIMP, "fdc: unimplemented command 0x%02x\n",
 | 
				
			||||||
                  fdctrl->fifo[0]);
 | 
					                  fdctrl->fifo[0]);
 | 
				
			||||||
    fdctrl->fifo[0] = FD_SR0_INVCMD;
 | 
					    fdctrl->fifo[0] = FD_SR0_INVCMD;
 | 
				
			||||||
    fdctrl_set_fifo(fdctrl, 1, 0);
 | 
					    fdctrl_set_fifo(fdctrl, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Seek to next sector
 | 
					/* Seek to next sector
 | 
				
			||||||
@ -1126,11 +1122,13 @@ static int fdctrl_seek_to_next_sect(FDCtrl *fdctrl, FDrive *cur_drv)
 | 
				
			|||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                new_head = 0;
 | 
					                new_head = 0;
 | 
				
			||||||
                new_track++;
 | 
					                new_track++;
 | 
				
			||||||
 | 
					                fdctrl->status0 |= FD_SR0_SEEK;
 | 
				
			||||||
                if ((cur_drv->flags & FDISK_DBL_SIDES) == 0) {
 | 
					                if ((cur_drv->flags & FDISK_DBL_SIDES) == 0) {
 | 
				
			||||||
                    ret = 0;
 | 
					                    ret = 0;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
 | 
					            fdctrl->status0 |= FD_SR0_SEEK;
 | 
				
			||||||
            new_track++;
 | 
					            new_track++;
 | 
				
			||||||
            ret = 0;
 | 
					            ret = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -1150,10 +1148,14 @@ static void fdctrl_stop_transfer(FDCtrl *fdctrl, uint8_t status0,
 | 
				
			|||||||
                                 uint8_t status1, uint8_t status2)
 | 
					                                 uint8_t status1, uint8_t status2)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    FDrive *cur_drv;
 | 
					    FDrive *cur_drv;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    cur_drv = get_cur_drv(fdctrl);
 | 
					    cur_drv = get_cur_drv(fdctrl);
 | 
				
			||||||
    fdctrl->status0 = status0 | FD_SR0_SEEK | (cur_drv->head << 2) |
 | 
					
 | 
				
			||||||
                      GET_CUR_DRV(fdctrl);
 | 
					    fdctrl->status0 &= ~(FD_SR0_DS0 | FD_SR0_DS1 | FD_SR0_HEAD);
 | 
				
			||||||
 | 
					    fdctrl->status0 |= GET_CUR_DRV(fdctrl);
 | 
				
			||||||
 | 
					    if (cur_drv->head) {
 | 
				
			||||||
 | 
					        fdctrl->status0 |= FD_SR0_HEAD;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fdctrl->status0 |= status0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n",
 | 
					    FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n",
 | 
				
			||||||
                   status0, status1, status2, fdctrl->status0);
 | 
					                   status0, status1, status2, fdctrl->status0);
 | 
				
			||||||
@ -1170,7 +1172,9 @@ static void fdctrl_stop_transfer(FDCtrl *fdctrl, uint8_t status0,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
 | 
					    fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
 | 
				
			||||||
    fdctrl->msr &= ~FD_MSR_NONDMA;
 | 
					    fdctrl->msr &= ~FD_MSR_NONDMA;
 | 
				
			||||||
    fdctrl_set_fifo(fdctrl, 7, fdctrl->status0);
 | 
					
 | 
				
			||||||
 | 
					    fdctrl_set_fifo(fdctrl, 7);
 | 
				
			||||||
 | 
					    fdctrl_raise_irq(fdctrl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Prepare a data transfer (either DMA or FIFO) */
 | 
					/* Prepare a data transfer (either DMA or FIFO) */
 | 
				
			||||||
@ -1178,7 +1182,6 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    FDrive *cur_drv;
 | 
					    FDrive *cur_drv;
 | 
				
			||||||
    uint8_t kh, kt, ks;
 | 
					    uint8_t kh, kt, ks;
 | 
				
			||||||
    int did_seek = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
 | 
					    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
 | 
				
			||||||
    cur_drv = get_cur_drv(fdctrl);
 | 
					    cur_drv = get_cur_drv(fdctrl);
 | 
				
			||||||
@ -1212,7 +1215,7 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
        fdctrl->fifo[5] = ks;
 | 
					        fdctrl->fifo[5] = ks;
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    case 1:
 | 
					    case 1:
 | 
				
			||||||
        did_seek = 1;
 | 
					        fdctrl->status0 |= FD_SR0_SEEK;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
@ -1234,16 +1237,12 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
    /* Set the FIFO state */
 | 
					    /* Set the FIFO state */
 | 
				
			||||||
    fdctrl->data_dir = direction;
 | 
					    fdctrl->data_dir = direction;
 | 
				
			||||||
    fdctrl->data_pos = 0;
 | 
					    fdctrl->data_pos = 0;
 | 
				
			||||||
    fdctrl->msr |= FD_MSR_CMDBUSY;
 | 
					    assert(fdctrl->msr & FD_MSR_CMDBUSY);
 | 
				
			||||||
    if (fdctrl->fifo[0] & 0x80)
 | 
					    if (fdctrl->fifo[0] & 0x80)
 | 
				
			||||||
        fdctrl->data_state |= FD_STATE_MULTI;
 | 
					        fdctrl->data_state |= FD_STATE_MULTI;
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        fdctrl->data_state &= ~FD_STATE_MULTI;
 | 
					        fdctrl->data_state &= ~FD_STATE_MULTI;
 | 
				
			||||||
    if (did_seek)
 | 
					    if (fdctrl->fifo[5] == 0) {
 | 
				
			||||||
        fdctrl->data_state |= FD_STATE_SEEK;
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        fdctrl->data_state &= ~FD_STATE_SEEK;
 | 
					 | 
				
			||||||
    if (fdctrl->fifo[5] == 00) {
 | 
					 | 
				
			||||||
        fdctrl->data_len = fdctrl->fifo[8];
 | 
					        fdctrl->data_len = fdctrl->fifo[8];
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        int tmp;
 | 
					        int tmp;
 | 
				
			||||||
@ -1266,14 +1265,21 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
        if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL ||
 | 
					        if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL ||
 | 
				
			||||||
              direction == FD_DIR_SCANH) && dma_mode == 0) ||
 | 
					              direction == FD_DIR_SCANH) && dma_mode == 0) ||
 | 
				
			||||||
            (direction == FD_DIR_WRITE && dma_mode == 2) ||
 | 
					            (direction == FD_DIR_WRITE && dma_mode == 2) ||
 | 
				
			||||||
            (direction == FD_DIR_READ && dma_mode == 1)) {
 | 
					            (direction == FD_DIR_READ && dma_mode == 1) ||
 | 
				
			||||||
 | 
					            (direction == FD_DIR_VERIFY)) {
 | 
				
			||||||
            /* No access is allowed until DMA transfer has completed */
 | 
					            /* No access is allowed until DMA transfer has completed */
 | 
				
			||||||
            fdctrl->msr &= ~FD_MSR_RQM;
 | 
					            fdctrl->msr &= ~FD_MSR_RQM;
 | 
				
			||||||
 | 
					            if (direction != FD_DIR_VERIFY) {
 | 
				
			||||||
                /* Now, we just have to wait for the DMA controller to
 | 
					                /* Now, we just have to wait for the DMA controller to
 | 
				
			||||||
                 * recall us...
 | 
					                 * recall us...
 | 
				
			||||||
                 */
 | 
					                 */
 | 
				
			||||||
                DMA_hold_DREQ(fdctrl->dma_chann);
 | 
					                DMA_hold_DREQ(fdctrl->dma_chann);
 | 
				
			||||||
                DMA_schedule(fdctrl->dma_chann);
 | 
					                DMA_schedule(fdctrl->dma_chann);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                /* Start transfer */
 | 
				
			||||||
 | 
					                fdctrl_transfer_handler(fdctrl, fdctrl->dma_chann, 0,
 | 
				
			||||||
 | 
					                                        fdctrl->data_len);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            FLOPPY_DPRINTF("bad dma_mode=%d direction=%d\n", dma_mode,
 | 
					            FLOPPY_DPRINTF("bad dma_mode=%d direction=%d\n", dma_mode,
 | 
				
			||||||
@ -1285,7 +1291,7 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
    if (direction != FD_DIR_WRITE)
 | 
					    if (direction != FD_DIR_WRITE)
 | 
				
			||||||
        fdctrl->msr |= FD_MSR_DIO;
 | 
					        fdctrl->msr |= FD_MSR_DIO;
 | 
				
			||||||
    /* IO based transfer: calculate len */
 | 
					    /* IO based transfer: calculate len */
 | 
				
			||||||
    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
 | 
					    fdctrl_raise_irq(fdctrl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Prepare a transfer of deleted data */
 | 
					/* Prepare a transfer of deleted data */
 | 
				
			||||||
@ -1376,6 +1382,9 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
 | 
				
			|||||||
                goto transfer_error;
 | 
					                goto transfer_error;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					        case FD_DIR_VERIFY:
 | 
				
			||||||
 | 
					            /* VERIFY commands */
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            /* SCAN commands */
 | 
					            /* SCAN commands */
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -1411,8 +1420,6 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
 | 
				
			|||||||
        fdctrl->data_dir == FD_DIR_SCANL ||
 | 
					        fdctrl->data_dir == FD_DIR_SCANL ||
 | 
				
			||||||
        fdctrl->data_dir == FD_DIR_SCANH)
 | 
					        fdctrl->data_dir == FD_DIR_SCANH)
 | 
				
			||||||
        status2 = FD_SR2_SEH;
 | 
					        status2 = FD_SR2_SEH;
 | 
				
			||||||
    if (FD_DID_SEEK(fdctrl->data_state))
 | 
					 | 
				
			||||||
        status0 |= FD_SR0_SEEK;
 | 
					 | 
				
			||||||
    fdctrl->data_len -= len;
 | 
					    fdctrl->data_len -= len;
 | 
				
			||||||
    fdctrl_stop_transfer(fdctrl, status0, status1, status2);
 | 
					    fdctrl_stop_transfer(fdctrl, status0, status1, status2);
 | 
				
			||||||
 transfer_error:
 | 
					 transfer_error:
 | 
				
			||||||
@ -1458,7 +1465,7 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
 | 
				
			|||||||
         * then from status mode to command mode
 | 
					         * then from status mode to command mode
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        if (fdctrl->msr & FD_MSR_NONDMA) {
 | 
					        if (fdctrl->msr & FD_MSR_NONDMA) {
 | 
				
			||||||
            fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
 | 
					            fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            fdctrl_reset_fifo(fdctrl);
 | 
					            fdctrl_reset_fifo(fdctrl);
 | 
				
			||||||
            fdctrl_reset_irq(fdctrl);
 | 
					            fdctrl_reset_irq(fdctrl);
 | 
				
			||||||
@ -1506,7 +1513,7 @@ static void fdctrl_format_sector(FDCtrl *fdctrl)
 | 
				
			|||||||
        fdctrl->fifo[5] = ks;
 | 
					        fdctrl->fifo[5] = ks;
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    case 1:
 | 
					    case 1:
 | 
				
			||||||
        fdctrl->data_state |= FD_STATE_SEEK;
 | 
					        fdctrl->status0 |= FD_SR0_SEEK;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
@ -1520,9 +1527,6 @@ static void fdctrl_format_sector(FDCtrl *fdctrl)
 | 
				
			|||||||
        if (cur_drv->sect == cur_drv->last_sect) {
 | 
					        if (cur_drv->sect == cur_drv->last_sect) {
 | 
				
			||||||
            fdctrl->data_state &= ~FD_STATE_FORMAT;
 | 
					            fdctrl->data_state &= ~FD_STATE_FORMAT;
 | 
				
			||||||
            /* Last sector done */
 | 
					            /* Last sector done */
 | 
				
			||||||
            if (FD_DID_SEEK(fdctrl->data_state))
 | 
					 | 
				
			||||||
                fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
 | 
					            fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            /* More to do */
 | 
					            /* More to do */
 | 
				
			||||||
@ -1536,7 +1540,7 @@ static void fdctrl_handle_lock(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    fdctrl->lock = (fdctrl->fifo[0] & 0x80) ? 1 : 0;
 | 
					    fdctrl->lock = (fdctrl->fifo[0] & 0x80) ? 1 : 0;
 | 
				
			||||||
    fdctrl->fifo[0] = fdctrl->lock << 4;
 | 
					    fdctrl->fifo[0] = fdctrl->lock << 4;
 | 
				
			||||||
    fdctrl_set_fifo(fdctrl, 1, 0);
 | 
					    fdctrl_set_fifo(fdctrl, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fdctrl_handle_dumpreg(FDCtrl *fdctrl, int direction)
 | 
					static void fdctrl_handle_dumpreg(FDCtrl *fdctrl, int direction)
 | 
				
			||||||
@ -1561,20 +1565,20 @@ static void fdctrl_handle_dumpreg(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
        (cur_drv->perpendicular << 2);
 | 
					        (cur_drv->perpendicular << 2);
 | 
				
			||||||
    fdctrl->fifo[8] = fdctrl->config;
 | 
					    fdctrl->fifo[8] = fdctrl->config;
 | 
				
			||||||
    fdctrl->fifo[9] = fdctrl->precomp_trk;
 | 
					    fdctrl->fifo[9] = fdctrl->precomp_trk;
 | 
				
			||||||
    fdctrl_set_fifo(fdctrl, 10, 0);
 | 
					    fdctrl_set_fifo(fdctrl, 10);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fdctrl_handle_version(FDCtrl *fdctrl, int direction)
 | 
					static void fdctrl_handle_version(FDCtrl *fdctrl, int direction)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* Controller's version */
 | 
					    /* Controller's version */
 | 
				
			||||||
    fdctrl->fifo[0] = fdctrl->version;
 | 
					    fdctrl->fifo[0] = fdctrl->version;
 | 
				
			||||||
    fdctrl_set_fifo(fdctrl, 1, 0);
 | 
					    fdctrl_set_fifo(fdctrl, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fdctrl_handle_partid(FDCtrl *fdctrl, int direction)
 | 
					static void fdctrl_handle_partid(FDCtrl *fdctrl, int direction)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    fdctrl->fifo[0] = 0x41; /* Stepping 1 */
 | 
					    fdctrl->fifo[0] = 0x41; /* Stepping 1 */
 | 
				
			||||||
    fdctrl_set_fifo(fdctrl, 1, 0);
 | 
					    fdctrl_set_fifo(fdctrl, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fdctrl_handle_restore(FDCtrl *fdctrl, int direction)
 | 
					static void fdctrl_handle_restore(FDCtrl *fdctrl, int direction)
 | 
				
			||||||
@ -1627,7 +1631,7 @@ static void fdctrl_handle_save(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
    fdctrl->fifo[12] = fdctrl->pwrd;
 | 
					    fdctrl->fifo[12] = fdctrl->pwrd;
 | 
				
			||||||
    fdctrl->fifo[13] = 0;
 | 
					    fdctrl->fifo[13] = 0;
 | 
				
			||||||
    fdctrl->fifo[14] = 0;
 | 
					    fdctrl->fifo[14] = 0;
 | 
				
			||||||
    fdctrl_set_fifo(fdctrl, 15, 0);
 | 
					    fdctrl_set_fifo(fdctrl, 15);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fdctrl_handle_readid(FDCtrl *fdctrl, int direction)
 | 
					static void fdctrl_handle_readid(FDCtrl *fdctrl, int direction)
 | 
				
			||||||
@ -1650,7 +1654,6 @@ static void fdctrl_handle_format_track(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
        fdctrl->data_state |= FD_STATE_MULTI;
 | 
					        fdctrl->data_state |= FD_STATE_MULTI;
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        fdctrl->data_state &= ~FD_STATE_MULTI;
 | 
					        fdctrl->data_state &= ~FD_STATE_MULTI;
 | 
				
			||||||
    fdctrl->data_state &= ~FD_STATE_SEEK;
 | 
					 | 
				
			||||||
    cur_drv->bps =
 | 
					    cur_drv->bps =
 | 
				
			||||||
        fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
 | 
					        fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
 | 
				
			||||||
#if 0
 | 
					#if 0
 | 
				
			||||||
@ -1693,7 +1696,7 @@ static void fdctrl_handle_sense_drive_status(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
        (cur_drv->head << 2) |
 | 
					        (cur_drv->head << 2) |
 | 
				
			||||||
        GET_CUR_DRV(fdctrl) |
 | 
					        GET_CUR_DRV(fdctrl) |
 | 
				
			||||||
        0x28;
 | 
					        0x28;
 | 
				
			||||||
    fdctrl_set_fifo(fdctrl, 1, 0);
 | 
					    fdctrl_set_fifo(fdctrl, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fdctrl_handle_recalibrate(FDCtrl *fdctrl, int direction)
 | 
					static void fdctrl_handle_recalibrate(FDCtrl *fdctrl, int direction)
 | 
				
			||||||
@ -1705,7 +1708,8 @@ static void fdctrl_handle_recalibrate(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
    fd_recalibrate(cur_drv);
 | 
					    fd_recalibrate(cur_drv);
 | 
				
			||||||
    fdctrl_reset_fifo(fdctrl);
 | 
					    fdctrl_reset_fifo(fdctrl);
 | 
				
			||||||
    /* Raise Interrupt */
 | 
					    /* Raise Interrupt */
 | 
				
			||||||
    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
 | 
					    fdctrl->status0 |= FD_SR0_SEEK;
 | 
				
			||||||
 | 
					    fdctrl_raise_irq(fdctrl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fdctrl_handle_sense_interrupt_status(FDCtrl *fdctrl, int direction)
 | 
					static void fdctrl_handle_sense_interrupt_status(FDCtrl *fdctrl, int direction)
 | 
				
			||||||
@ -1718,7 +1722,7 @@ static void fdctrl_handle_sense_interrupt_status(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
        fdctrl->reset_sensei--;
 | 
					        fdctrl->reset_sensei--;
 | 
				
			||||||
    } else if (!(fdctrl->sra & FD_SRA_INTPEND)) {
 | 
					    } else if (!(fdctrl->sra & FD_SRA_INTPEND)) {
 | 
				
			||||||
        fdctrl->fifo[0] = FD_SR0_INVCMD;
 | 
					        fdctrl->fifo[0] = FD_SR0_INVCMD;
 | 
				
			||||||
        fdctrl_set_fifo(fdctrl, 1, 0);
 | 
					        fdctrl_set_fifo(fdctrl, 1);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        fdctrl->fifo[0] =
 | 
					        fdctrl->fifo[0] =
 | 
				
			||||||
@ -1727,7 +1731,7 @@ static void fdctrl_handle_sense_interrupt_status(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fdctrl->fifo[1] = cur_drv->track;
 | 
					    fdctrl->fifo[1] = cur_drv->track;
 | 
				
			||||||
    fdctrl_set_fifo(fdctrl, 2, 0);
 | 
					    fdctrl_set_fifo(fdctrl, 2);
 | 
				
			||||||
    fdctrl_reset_irq(fdctrl);
 | 
					    fdctrl_reset_irq(fdctrl);
 | 
				
			||||||
    fdctrl->status0 = FD_SR0_RDYCHG;
 | 
					    fdctrl->status0 = FD_SR0_RDYCHG;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1744,7 +1748,8 @@ static void fdctrl_handle_seek(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    fd_seek(cur_drv, cur_drv->head, fdctrl->fifo[2], cur_drv->sect, 1);
 | 
					    fd_seek(cur_drv, cur_drv->head, fdctrl->fifo[2], cur_drv->sect, 1);
 | 
				
			||||||
    /* Raise Interrupt */
 | 
					    /* Raise Interrupt */
 | 
				
			||||||
    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
 | 
					    fdctrl->status0 |= FD_SR0_SEEK;
 | 
				
			||||||
 | 
					    fdctrl_raise_irq(fdctrl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fdctrl_handle_perpendicular_mode(FDCtrl *fdctrl, int direction)
 | 
					static void fdctrl_handle_perpendicular_mode(FDCtrl *fdctrl, int direction)
 | 
				
			||||||
@ -1769,7 +1774,7 @@ static void fdctrl_handle_powerdown_mode(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    fdctrl->pwrd = fdctrl->fifo[1];
 | 
					    fdctrl->pwrd = fdctrl->fifo[1];
 | 
				
			||||||
    fdctrl->fifo[0] = fdctrl->fifo[1];
 | 
					    fdctrl->fifo[0] = fdctrl->fifo[1];
 | 
				
			||||||
    fdctrl_set_fifo(fdctrl, 1, 0);
 | 
					    fdctrl_set_fifo(fdctrl, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fdctrl_handle_option(FDCtrl *fdctrl, int direction)
 | 
					static void fdctrl_handle_option(FDCtrl *fdctrl, int direction)
 | 
				
			||||||
@ -1788,7 +1793,7 @@ static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direct
 | 
				
			|||||||
            fdctrl->fifo[0] = fdctrl->fifo[1];
 | 
					            fdctrl->fifo[0] = fdctrl->fifo[1];
 | 
				
			||||||
            fdctrl->fifo[2] = 0;
 | 
					            fdctrl->fifo[2] = 0;
 | 
				
			||||||
            fdctrl->fifo[3] = 0;
 | 
					            fdctrl->fifo[3] = 0;
 | 
				
			||||||
            fdctrl_set_fifo(fdctrl, 4, 0);
 | 
					            fdctrl_set_fifo(fdctrl, 4);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            fdctrl_reset_fifo(fdctrl);
 | 
					            fdctrl_reset_fifo(fdctrl);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -1796,7 +1801,7 @@ static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direct
 | 
				
			|||||||
        /* ERROR */
 | 
					        /* ERROR */
 | 
				
			||||||
        fdctrl->fifo[0] = 0x80 |
 | 
					        fdctrl->fifo[0] = 0x80 |
 | 
				
			||||||
            (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
 | 
					            (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
 | 
				
			||||||
        fdctrl_set_fifo(fdctrl, 1, 0);
 | 
					        fdctrl_set_fifo(fdctrl, 1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1815,7 +1820,8 @@ static void fdctrl_handle_relative_seek_in(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    fdctrl_reset_fifo(fdctrl);
 | 
					    fdctrl_reset_fifo(fdctrl);
 | 
				
			||||||
    /* Raise Interrupt */
 | 
					    /* Raise Interrupt */
 | 
				
			||||||
    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
 | 
					    fdctrl->status0 |= FD_SR0_SEEK;
 | 
				
			||||||
 | 
					    fdctrl_raise_irq(fdctrl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fdctrl_handle_relative_seek_out(FDCtrl *fdctrl, int direction)
 | 
					static void fdctrl_handle_relative_seek_out(FDCtrl *fdctrl, int direction)
 | 
				
			||||||
@ -1832,7 +1838,8 @@ static void fdctrl_handle_relative_seek_out(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    fdctrl_reset_fifo(fdctrl);
 | 
					    fdctrl_reset_fifo(fdctrl);
 | 
				
			||||||
    /* Raise Interrupt */
 | 
					    /* Raise Interrupt */
 | 
				
			||||||
    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
 | 
					    fdctrl->status0 |= FD_SR0_SEEK;
 | 
				
			||||||
 | 
					    fdctrl_raise_irq(fdctrl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct {
 | 
					static const struct {
 | 
				
			||||||
@ -1854,7 +1861,7 @@ static const struct {
 | 
				
			|||||||
    { FD_CMD_SAVE, 0xff, "SAVE", 0, fdctrl_handle_save }, /* part of READ DELETED DATA */
 | 
					    { FD_CMD_SAVE, 0xff, "SAVE", 0, fdctrl_handle_save }, /* part of READ DELETED DATA */
 | 
				
			||||||
    { FD_CMD_READ_DELETED, 0x1f, "READ DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_READ },
 | 
					    { FD_CMD_READ_DELETED, 0x1f, "READ DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_READ },
 | 
				
			||||||
    { FD_CMD_SCAN_EQUAL, 0x1f, "SCAN EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANE },
 | 
					    { FD_CMD_SCAN_EQUAL, 0x1f, "SCAN EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANE },
 | 
				
			||||||
    { FD_CMD_VERIFY, 0x1f, "VERIFY", 8, fdctrl_unimplemented },
 | 
					    { FD_CMD_VERIFY, 0x1f, "VERIFY", 8, fdctrl_start_transfer, FD_DIR_VERIFY },
 | 
				
			||||||
    { FD_CMD_SCAN_LOW_OR_EQUAL, 0x1f, "SCAN LOW OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANL },
 | 
					    { FD_CMD_SCAN_LOW_OR_EQUAL, 0x1f, "SCAN LOW OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANL },
 | 
				
			||||||
    { FD_CMD_SCAN_HIGH_OR_EQUAL, 0x1f, "SCAN HIGH OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANH },
 | 
					    { FD_CMD_SCAN_HIGH_OR_EQUAL, 0x1f, "SCAN HIGH OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANH },
 | 
				
			||||||
    { FD_CMD_WRITE_DELETED, 0x3f, "WRITE DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_WRITE },
 | 
					    { FD_CMD_WRITE_DELETED, 0x3f, "WRITE DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_WRITE },
 | 
				
			||||||
@ -1918,7 +1925,7 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
 | 
				
			|||||||
         * then from status mode to command mode
 | 
					         * then from status mode to command mode
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        if (fdctrl->data_pos == fdctrl->data_len)
 | 
					        if (fdctrl->data_pos == fdctrl->data_len)
 | 
				
			||||||
            fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
 | 
					            fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (fdctrl->data_pos == 0) {
 | 
					    if (fdctrl->data_pos == 0) {
 | 
				
			||||||
 | 
				
			|||||||
@ -336,7 +336,7 @@ static void trim_aio_cancel(BlockDriverAIOCB *acb)
 | 
				
			|||||||
    qemu_aio_release(iocb);
 | 
					    qemu_aio_release(iocb);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool trim_aio_pool = {
 | 
					static const AIOCBInfo trim_aiocb_info = {
 | 
				
			||||||
    .aiocb_size         = sizeof(TrimAIOCB),
 | 
					    .aiocb_size         = sizeof(TrimAIOCB),
 | 
				
			||||||
    .cancel             = trim_aio_cancel,
 | 
					    .cancel             = trim_aio_cancel,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -360,7 +360,7 @@ BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs,
 | 
				
			|||||||
    TrimAIOCB *iocb;
 | 
					    TrimAIOCB *iocb;
 | 
				
			||||||
    int i, j, ret;
 | 
					    int i, j, ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iocb = qemu_aio_get(&trim_aio_pool, bs, cb, opaque);
 | 
					    iocb = qemu_aio_get(&trim_aiocb_info, bs, cb, opaque);
 | 
				
			||||||
    iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
 | 
					    iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
 | 
				
			||||||
    iocb->ret = 0;
 | 
					    iocb->ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1296,7 +1296,7 @@ static int megasas_dcmd_get_properties(MegasasState *s, MegasasCmd *cmd)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int megasas_cache_flush(MegasasState *s, MegasasCmd *cmd)
 | 
					static int megasas_cache_flush(MegasasState *s, MegasasCmd *cmd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    qemu_aio_flush();
 | 
					    bdrv_drain_all();
 | 
				
			||||||
    return MFI_STAT_OK;
 | 
					    return MFI_STAT_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										12
									
								
								qemu-aio.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								qemu-aio.h
									
									
									
									
									
								
							@ -21,21 +21,19 @@
 | 
				
			|||||||
typedef struct BlockDriverAIOCB BlockDriverAIOCB;
 | 
					typedef struct BlockDriverAIOCB BlockDriverAIOCB;
 | 
				
			||||||
typedef void BlockDriverCompletionFunc(void *opaque, int ret);
 | 
					typedef void BlockDriverCompletionFunc(void *opaque, int ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct AIOPool {
 | 
					typedef struct AIOCBInfo {
 | 
				
			||||||
    void (*cancel)(BlockDriverAIOCB *acb);
 | 
					    void (*cancel)(BlockDriverAIOCB *acb);
 | 
				
			||||||
    int aiocb_size;
 | 
					    size_t aiocb_size;
 | 
				
			||||||
    BlockDriverAIOCB *free_aiocb;
 | 
					} AIOCBInfo;
 | 
				
			||||||
} AIOPool;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct BlockDriverAIOCB {
 | 
					struct BlockDriverAIOCB {
 | 
				
			||||||
    AIOPool *pool;
 | 
					    const AIOCBInfo *aiocb_info;
 | 
				
			||||||
    BlockDriverState *bs;
 | 
					    BlockDriverState *bs;
 | 
				
			||||||
    BlockDriverCompletionFunc *cb;
 | 
					    BlockDriverCompletionFunc *cb;
 | 
				
			||||||
    void *opaque;
 | 
					    void *opaque;
 | 
				
			||||||
    BlockDriverAIOCB *next;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
 | 
					void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
 | 
				
			||||||
                   BlockDriverCompletionFunc *cb, void *opaque);
 | 
					                   BlockDriverCompletionFunc *cb, void *opaque);
 | 
				
			||||||
void qemu_aio_release(void *p);
 | 
					void qemu_aio_release(void *p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -421,6 +421,7 @@ snapshots.
 | 
				
			|||||||
* disk_images_nbd::           NBD access
 | 
					* disk_images_nbd::           NBD access
 | 
				
			||||||
* disk_images_sheepdog::      Sheepdog disk images
 | 
					* disk_images_sheepdog::      Sheepdog disk images
 | 
				
			||||||
* disk_images_iscsi::         iSCSI LUNs
 | 
					* disk_images_iscsi::         iSCSI LUNs
 | 
				
			||||||
 | 
					* disk_images_gluster::       GlusterFS disk images
 | 
				
			||||||
@end menu
 | 
					@end menu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@node disk_images_quickstart
 | 
					@node disk_images_quickstart
 | 
				
			||||||
@ -814,7 +815,55 @@ qemu-system-i386 -iscsi initiator-name=iqn.qemu.test:my-initiator \
 | 
				
			|||||||
    -cdrom iscsi://127.0.0.1/iqn.qemu.test/2
 | 
					    -cdrom iscsi://127.0.0.1/iqn.qemu.test/2
 | 
				
			||||||
@end example
 | 
					@end example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@node disk_images_gluster
 | 
				
			||||||
 | 
					@subsection GlusterFS disk images
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GlusterFS is an user space distributed file system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can boot from the GlusterFS disk image with the command:
 | 
				
			||||||
 | 
					@example
 | 
				
			||||||
 | 
					qemu-system-x86_64 -drive file=gluster[+@var{transport}]://[@var{server}[:@var{port}]]/@var{volname}/@var{image}[?socket=...]
 | 
				
			||||||
 | 
					@end example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@var{gluster} is the protocol.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@var{transport} specifies the transport type used to connect to gluster
 | 
				
			||||||
 | 
					management daemon (glusterd). Valid transport types are
 | 
				
			||||||
 | 
					tcp, unix and rdma. If a transport type isn't specified, then tcp
 | 
				
			||||||
 | 
					type is assumed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@var{server} specifies the server where the volume file specification for
 | 
				
			||||||
 | 
					the given volume resides. This can be either hostname, ipv4 address
 | 
				
			||||||
 | 
					or ipv6 address. ipv6 address needs to be within square brackets [ ].
 | 
				
			||||||
 | 
					If transport type is unix, then @var{server} field should not be specifed.
 | 
				
			||||||
 | 
					Instead @var{socket} field needs to be populated with the path to unix domain
 | 
				
			||||||
 | 
					socket.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@var{port} is the port number on which glusterd is listening. This is optional
 | 
				
			||||||
 | 
					and if not specified, QEMU will send 0 which will make gluster to use the
 | 
				
			||||||
 | 
					default port. If the transport type is unix, then @var{port} should not be
 | 
				
			||||||
 | 
					specified.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@var{volname} is the name of the gluster volume which contains the disk image.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@var{image} is the path to the actual disk image that resides on gluster volume.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can create a GlusterFS disk image with the command:
 | 
				
			||||||
 | 
					@example
 | 
				
			||||||
 | 
					qemu-img create gluster://@var{server}/@var{volname}/@var{image} @var{size}
 | 
				
			||||||
 | 
					@end example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Examples
 | 
				
			||||||
 | 
					@example
 | 
				
			||||||
 | 
					qemu-system-x86_64 -drive file=gluster://1.2.3.4/testvol/a.img
 | 
				
			||||||
 | 
					qemu-system-x86_64 -drive file=gluster+tcp://1.2.3.4/testvol/a.img
 | 
				
			||||||
 | 
					qemu-system-x86_64 -drive file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img
 | 
				
			||||||
 | 
					qemu-system-x86_64 -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img
 | 
				
			||||||
 | 
					qemu-system-x86_64 -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img
 | 
				
			||||||
 | 
					qemu-system-x86_64 -drive file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img
 | 
				
			||||||
 | 
					qemu-system-x86_64 -drive file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
 | 
				
			||||||
 | 
					qemu-system-x86_64 -drive file=gluster+rdma://1.2.3.4:24007/testvol/a.img
 | 
				
			||||||
 | 
					@end example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@node pcsys_network
 | 
					@node pcsys_network
 | 
				
			||||||
@section Network emulation
 | 
					@section Network emulation
 | 
				
			||||||
 | 
				
			|||||||
@ -1362,7 +1362,7 @@ static int aio_write_f(int argc, char **argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int aio_flush_f(int argc, char **argv)
 | 
					static int aio_flush_f(int argc, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    qemu_aio_flush();
 | 
					    bdrv_drain_all();
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2054,6 +2054,23 @@ qemu-system-i386 --drive file=sheepdog:192.0.2.1:30000:MyVirtualMachine
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
See also @url{http://http://www.osrg.net/sheepdog/}.
 | 
					See also @url{http://http://www.osrg.net/sheepdog/}.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@item GlusterFS
 | 
				
			||||||
 | 
					GlusterFS is an user space distributed file system.
 | 
				
			||||||
 | 
					QEMU supports the use of GlusterFS volumes for hosting VM disk images using
 | 
				
			||||||
 | 
					TCP, Unix Domain Sockets and RDMA transport protocols.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Syntax for specifying a VM disk image on GlusterFS volume is
 | 
				
			||||||
 | 
					@example
 | 
				
			||||||
 | 
					gluster[+transport]://[server[:port]]/volname/image[?socket=...]
 | 
				
			||||||
 | 
					@end example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example
 | 
				
			||||||
 | 
					@example
 | 
				
			||||||
 | 
					qemu-system-x86_84 --drive file=gluster://192.0.2.1/testvol/a.img
 | 
				
			||||||
 | 
					@end example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					See also @url{http://www.gluster.org}.
 | 
				
			||||||
@end table
 | 
					@end table
 | 
				
			||||||
ETEXI
 | 
					ETEXI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										192
									
								
								tests/fdc-test.c
									
									
									
									
									
								
							
							
						
						
									
										192
									
								
								tests/fdc-test.c
									
									
									
									
									
								
							@ -48,13 +48,17 @@ enum {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
    CMD_SENSE_INT           = 0x08,
 | 
					    CMD_SENSE_INT           = 0x08,
 | 
				
			||||||
 | 
					    CMD_READ_ID             = 0x0a,
 | 
				
			||||||
    CMD_SEEK                = 0x0f,
 | 
					    CMD_SEEK                = 0x0f,
 | 
				
			||||||
 | 
					    CMD_VERIFY              = 0x16,
 | 
				
			||||||
    CMD_READ                = 0xe6,
 | 
					    CMD_READ                = 0xe6,
 | 
				
			||||||
    CMD_RELATIVE_SEEK_OUT   = 0x8f,
 | 
					    CMD_RELATIVE_SEEK_OUT   = 0x8f,
 | 
				
			||||||
    CMD_RELATIVE_SEEK_IN    = 0xcf,
 | 
					    CMD_RELATIVE_SEEK_IN    = 0xcf,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
 | 
					    BUSY    = 0x10,
 | 
				
			||||||
 | 
					    NONDMA  = 0x20,
 | 
				
			||||||
    RQM     = 0x80,
 | 
					    RQM     = 0x80,
 | 
				
			||||||
    DIO     = 0x40,
 | 
					    DIO     = 0x40,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -110,7 +114,7 @@ static void ack_irq(uint8_t *pcn)
 | 
				
			|||||||
    g_assert(!get_irq(FLOPPY_IRQ));
 | 
					    g_assert(!get_irq(FLOPPY_IRQ));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint8_t send_read_command(void)
 | 
					static uint8_t send_read_command(uint8_t cmd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint8_t drive = 0;
 | 
					    uint8_t drive = 0;
 | 
				
			||||||
    uint8_t head = 0;
 | 
					    uint8_t head = 0;
 | 
				
			||||||
@ -126,7 +130,7 @@ static uint8_t send_read_command(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    uint8_t ret = 0;
 | 
					    uint8_t ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    floppy_send(CMD_READ);
 | 
					    floppy_send(cmd);
 | 
				
			||||||
    floppy_send(head << 2 | drive);
 | 
					    floppy_send(head << 2 | drive);
 | 
				
			||||||
    g_assert(!get_irq(FLOPPY_IRQ));
 | 
					    g_assert(!get_irq(FLOPPY_IRQ));
 | 
				
			||||||
    floppy_send(cyl);
 | 
					    floppy_send(cyl);
 | 
				
			||||||
@ -152,7 +156,70 @@ static uint8_t send_read_command(void)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    st0 = floppy_recv();
 | 
					    st0 = floppy_recv();
 | 
				
			||||||
    if (st0 != 0x60) {
 | 
					    if (st0 != 0x40) {
 | 
				
			||||||
 | 
					        ret = 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    floppy_recv();
 | 
				
			||||||
 | 
					    floppy_recv();
 | 
				
			||||||
 | 
					    floppy_recv();
 | 
				
			||||||
 | 
					    floppy_recv();
 | 
				
			||||||
 | 
					    floppy_recv();
 | 
				
			||||||
 | 
					    floppy_recv();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint8_t send_read_no_dma_command(int nb_sect, uint8_t expected_st0)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t drive = 0;
 | 
				
			||||||
 | 
					    uint8_t head = 0;
 | 
				
			||||||
 | 
					    uint8_t cyl = 0;
 | 
				
			||||||
 | 
					    uint8_t sect_addr = 1;
 | 
				
			||||||
 | 
					    uint8_t sect_size = 2;
 | 
				
			||||||
 | 
					    uint8_t eot = nb_sect;
 | 
				
			||||||
 | 
					    uint8_t gap = 0x1b;
 | 
				
			||||||
 | 
					    uint8_t gpl = 0xff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t msr = 0;
 | 
				
			||||||
 | 
					    uint8_t st0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    floppy_send(CMD_READ);
 | 
				
			||||||
 | 
					    floppy_send(head << 2 | drive);
 | 
				
			||||||
 | 
					    g_assert(!get_irq(FLOPPY_IRQ));
 | 
				
			||||||
 | 
					    floppy_send(cyl);
 | 
				
			||||||
 | 
					    floppy_send(head);
 | 
				
			||||||
 | 
					    floppy_send(sect_addr);
 | 
				
			||||||
 | 
					    floppy_send(sect_size);
 | 
				
			||||||
 | 
					    floppy_send(eot);
 | 
				
			||||||
 | 
					    floppy_send(gap);
 | 
				
			||||||
 | 
					    floppy_send(gpl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint16_t i = 0;
 | 
				
			||||||
 | 
					    uint8_t n = 2;
 | 
				
			||||||
 | 
					    for (; i < n; i++) {
 | 
				
			||||||
 | 
					        msr = inb(FLOPPY_BASE + reg_msr);
 | 
				
			||||||
 | 
					        if (msr == (BUSY | NONDMA | DIO | RQM)) {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        sleep(1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (i >= n) {
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Non-DMA mode */
 | 
				
			||||||
 | 
					    for (i = 0; i < 512 * 2 * nb_sect; i++) {
 | 
				
			||||||
 | 
					        msr = inb(FLOPPY_BASE + reg_msr);
 | 
				
			||||||
 | 
					        assert_bit_set(msr, BUSY | RQM | DIO);
 | 
				
			||||||
 | 
					        inb(FLOPPY_BASE + reg_fifo);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    st0 = floppy_recv();
 | 
				
			||||||
 | 
					    if (st0 != expected_st0) {
 | 
				
			||||||
        ret = 1;
 | 
					        ret = 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -213,11 +280,11 @@ static void test_read_without_media(void)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    uint8_t ret;
 | 
					    uint8_t ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = send_read_command();
 | 
					    ret = send_read_command(CMD_READ);
 | 
				
			||||||
    g_assert(ret == 0);
 | 
					    g_assert(ret == 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_media_change(void)
 | 
					static void test_media_insert(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint8_t dir;
 | 
					    uint8_t dir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -245,6 +312,13 @@ static void test_media_change(void)
 | 
				
			|||||||
    assert_bit_clear(dir, DSKCHG);
 | 
					    assert_bit_clear(dir, DSKCHG);
 | 
				
			||||||
    dir = inb(FLOPPY_BASE + reg_dir);
 | 
					    dir = inb(FLOPPY_BASE + reg_dir);
 | 
				
			||||||
    assert_bit_clear(dir, DSKCHG);
 | 
					    assert_bit_clear(dir, DSKCHG);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_media_change(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t dir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test_media_insert();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Eject the floppy and check that DSKCHG is set. Reading it out doesn't
 | 
					    /* Eject the floppy and check that DSKCHG is set. Reading it out doesn't
 | 
				
			||||||
     * reset the bit. */
 | 
					     * reset the bit. */
 | 
				
			||||||
@ -320,6 +394,108 @@ static void test_relative_seek(void)
 | 
				
			|||||||
    g_assert(pcn == 0);
 | 
					    g_assert(pcn == 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_read_id(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t drive = 0;
 | 
				
			||||||
 | 
					    uint8_t head = 0;
 | 
				
			||||||
 | 
					    uint8_t cyl;
 | 
				
			||||||
 | 
					    uint8_t st0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Seek to track 0 and check with READ ID */
 | 
				
			||||||
 | 
					    send_seek(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    floppy_send(CMD_READ_ID);
 | 
				
			||||||
 | 
					    g_assert(!get_irq(FLOPPY_IRQ));
 | 
				
			||||||
 | 
					    floppy_send(head << 2 | drive);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (!get_irq(FLOPPY_IRQ)) {
 | 
				
			||||||
 | 
					        /* qemu involves a timer with READ ID... */
 | 
				
			||||||
 | 
					        clock_step(1000000000LL / 50);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    st0 = floppy_recv();
 | 
				
			||||||
 | 
					    floppy_recv();
 | 
				
			||||||
 | 
					    floppy_recv();
 | 
				
			||||||
 | 
					    cyl = floppy_recv();
 | 
				
			||||||
 | 
					    head = floppy_recv();
 | 
				
			||||||
 | 
					    floppy_recv();
 | 
				
			||||||
 | 
					    floppy_recv();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_assert_cmpint(cyl, ==, 0);
 | 
				
			||||||
 | 
					    g_assert_cmpint(head, ==, 0);
 | 
				
			||||||
 | 
					    g_assert_cmpint(st0, ==, head << 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Seek to track 8 on head 1 and check with READ ID */
 | 
				
			||||||
 | 
					    head = 1;
 | 
				
			||||||
 | 
					    cyl = 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    floppy_send(CMD_SEEK);
 | 
				
			||||||
 | 
					    floppy_send(head << 2 | drive);
 | 
				
			||||||
 | 
					    g_assert(!get_irq(FLOPPY_IRQ));
 | 
				
			||||||
 | 
					    floppy_send(cyl);
 | 
				
			||||||
 | 
					    g_assert(get_irq(FLOPPY_IRQ));
 | 
				
			||||||
 | 
					    ack_irq(NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    floppy_send(CMD_READ_ID);
 | 
				
			||||||
 | 
					    g_assert(!get_irq(FLOPPY_IRQ));
 | 
				
			||||||
 | 
					    floppy_send(head << 2 | drive);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (!get_irq(FLOPPY_IRQ)) {
 | 
				
			||||||
 | 
					        /* qemu involves a timer with READ ID... */
 | 
				
			||||||
 | 
					        clock_step(1000000000LL / 50);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    st0 = floppy_recv();
 | 
				
			||||||
 | 
					    floppy_recv();
 | 
				
			||||||
 | 
					    floppy_recv();
 | 
				
			||||||
 | 
					    cyl = floppy_recv();
 | 
				
			||||||
 | 
					    head = floppy_recv();
 | 
				
			||||||
 | 
					    floppy_recv();
 | 
				
			||||||
 | 
					    floppy_recv();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_assert_cmpint(cyl, ==, 8);
 | 
				
			||||||
 | 
					    g_assert_cmpint(head, ==, 1);
 | 
				
			||||||
 | 
					    g_assert_cmpint(st0, ==, head << 2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_read_no_dma_1(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
 | 
				
			||||||
 | 
					    send_seek(0);
 | 
				
			||||||
 | 
					    ret = send_read_no_dma_command(1, 0x04);
 | 
				
			||||||
 | 
					    g_assert(ret == 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_read_no_dma_18(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
 | 
				
			||||||
 | 
					    send_seek(0);
 | 
				
			||||||
 | 
					    ret = send_read_no_dma_command(18, 0x04);
 | 
				
			||||||
 | 
					    g_assert(ret == 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_read_no_dma_19(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
 | 
				
			||||||
 | 
					    send_seek(0);
 | 
				
			||||||
 | 
					    ret = send_read_no_dma_command(19, 0x20);
 | 
				
			||||||
 | 
					    g_assert(ret == 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_verify(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = send_read_command(CMD_VERIFY);
 | 
				
			||||||
 | 
					    g_assert(ret == 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* success if no crash or abort */
 | 
					/* success if no crash or abort */
 | 
				
			||||||
static void fuzz_registers(void)
 | 
					static void fuzz_registers(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -369,6 +545,12 @@ int main(int argc, char **argv)
 | 
				
			|||||||
    qtest_add_func("/fdc/media_change", test_media_change);
 | 
					    qtest_add_func("/fdc/media_change", test_media_change);
 | 
				
			||||||
    qtest_add_func("/fdc/sense_interrupt", test_sense_interrupt);
 | 
					    qtest_add_func("/fdc/sense_interrupt", test_sense_interrupt);
 | 
				
			||||||
    qtest_add_func("/fdc/relative_seek", test_relative_seek);
 | 
					    qtest_add_func("/fdc/relative_seek", test_relative_seek);
 | 
				
			||||||
 | 
					    qtest_add_func("/fdc/read_id", test_read_id);
 | 
				
			||||||
 | 
					    qtest_add_func("/fdc/verify", test_verify);
 | 
				
			||||||
 | 
					    qtest_add_func("/fdc/media_insert", test_media_insert);
 | 
				
			||||||
 | 
					    qtest_add_func("/fdc/read_no_dma_1", test_read_no_dma_1);
 | 
				
			||||||
 | 
					    qtest_add_func("/fdc/read_no_dma_18", test_read_no_dma_18);
 | 
				
			||||||
 | 
					    qtest_add_func("/fdc/read_no_dma_19", test_read_no_dma_19);
 | 
				
			||||||
    qtest_add_func("/fdc/fuzz-registers", fuzz_registers);
 | 
					    qtest_add_func("/fdc/fuzz-registers", fuzz_registers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = g_test_run();
 | 
					    ret = g_test_run();
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										117
									
								
								tests/qemu-iotests/044
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										117
									
								
								tests/qemu-iotests/044
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Tests growing a large refcount table.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (C) 2012 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/>.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import qcow2
 | 
				
			||||||
 | 
					from qcow2 import QcowHeader
 | 
				
			||||||
 | 
					import iotests
 | 
				
			||||||
 | 
					from iotests import qemu_img, qemu_img_verbose, qemu_io
 | 
				
			||||||
 | 
					import struct
 | 
				
			||||||
 | 
					import subprocess
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_img = os.path.join(iotests.test_dir, 'test.img')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestRefcountTableGrowth(iotests.QMPTestCase):
 | 
				
			||||||
 | 
					    '''Abstract base class for image mirroring test cases'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def preallocate(self, name):
 | 
				
			||||||
 | 
					        fd = open(name, "r+b")
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            off_reftable = 512
 | 
				
			||||||
 | 
					            off_refblock = off_reftable + (512 * 512)
 | 
				
			||||||
 | 
					            off_l1       = off_refblock + (512 * 512 * 64)
 | 
				
			||||||
 | 
					            off_l2       = off_l1 + (512 * 512 * 4 * 8)
 | 
				
			||||||
 | 
					            off_data     = off_l2 + (512 * 512 * 4 * 512)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Write a new header
 | 
				
			||||||
 | 
					            h = QcowHeader(fd)
 | 
				
			||||||
 | 
					            h.refcount_table_offset = off_reftable
 | 
				
			||||||
 | 
					            h.refcount_table_clusters = 512
 | 
				
			||||||
 | 
					            h.l1_table_offset = off_l1
 | 
				
			||||||
 | 
					            h.l1_size = 512 * 512 * 4
 | 
				
			||||||
 | 
					            h.update(fd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Write a refcount table
 | 
				
			||||||
 | 
					            fd.seek(off_reftable)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for i in xrange(0, h.refcount_table_clusters):
 | 
				
			||||||
 | 
					                sector = ''.join(struct.pack('>Q',
 | 
				
			||||||
 | 
					                    off_refblock + i * 64 * 512 + j * 512)
 | 
				
			||||||
 | 
					                    for j in xrange(0, 64))
 | 
				
			||||||
 | 
					                fd.write(sector)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Write the refcount blocks
 | 
				
			||||||
 | 
					            assert(fd.tell() == off_refblock)
 | 
				
			||||||
 | 
					            sector = ''.join(struct.pack('>H', 1) for j in xrange(0, 64 * 256))
 | 
				
			||||||
 | 
					            for block in xrange(0, h.refcount_table_clusters):
 | 
				
			||||||
 | 
					                fd.write(sector)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Write the L1 table
 | 
				
			||||||
 | 
					            assert(fd.tell() == off_l1)
 | 
				
			||||||
 | 
					            assert(off_l2 + 512 * h.l1_size == off_data)
 | 
				
			||||||
 | 
					            table = ''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j)
 | 
				
			||||||
 | 
					                for j in xrange(0, h.l1_size))
 | 
				
			||||||
 | 
					            fd.write(table)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Write the L2 tables
 | 
				
			||||||
 | 
					            assert(fd.tell() == off_l2)
 | 
				
			||||||
 | 
					            img_file_size = h.refcount_table_clusters * 64 * 256 * 512
 | 
				
			||||||
 | 
					            remaining = img_file_size - off_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            off = off_data
 | 
				
			||||||
 | 
					            while remaining > 1024 * 512:
 | 
				
			||||||
 | 
					                pytable = list((1 << 63) | off + 512 * j
 | 
				
			||||||
 | 
					                    for j in xrange(0, 1024))
 | 
				
			||||||
 | 
					                table = struct.pack('>1024Q', *pytable)
 | 
				
			||||||
 | 
					                fd.write(table)
 | 
				
			||||||
 | 
					                remaining = remaining - 1024 * 512
 | 
				
			||||||
 | 
					                off = off + 1024 * 512
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            table = ''.join(struct.pack('>Q', (1 << 63) | off + 512 * j)
 | 
				
			||||||
 | 
					                for j in xrange(0, remaining / 512))
 | 
				
			||||||
 | 
					            fd.write(table)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Data
 | 
				
			||||||
 | 
					            fd.truncate(img_file_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        finally:
 | 
				
			||||||
 | 
					            fd.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def setUp(self):
 | 
				
			||||||
 | 
					        qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=512', test_img, '16G')
 | 
				
			||||||
 | 
					        self.preallocate(test_img)
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def tearDown(self):
 | 
				
			||||||
 | 
					        os.remove(test_img)
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_grow_refcount_table(self):
 | 
				
			||||||
 | 
					        qemu_io('-c', 'write 3800M 1M', test_img)
 | 
				
			||||||
 | 
					        qemu_img_verbose('check' , test_img)
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    iotests.main(supported_fmts=['qcow2'])
 | 
				
			||||||
							
								
								
									
										6
									
								
								tests/qemu-iotests/044.out
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								tests/qemu-iotests/044.out
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					No errors were found on the image.
 | 
				
			||||||
 | 
					.
 | 
				
			||||||
 | 
					----------------------------------------------------------------------
 | 
				
			||||||
 | 
					Ran 1 tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OK
 | 
				
			||||||
@ -136,6 +136,7 @@ check options
 | 
				
			|||||||
    -vmdk               test vmdk
 | 
					    -vmdk               test vmdk
 | 
				
			||||||
    -rbd                test rbd
 | 
					    -rbd                test rbd
 | 
				
			||||||
    -sheepdog           test sheepdog
 | 
					    -sheepdog           test sheepdog
 | 
				
			||||||
 | 
					    -nbd                test nbd
 | 
				
			||||||
    -xdiff		graphical mode diff
 | 
					    -xdiff		graphical mode diff
 | 
				
			||||||
    -nocache		use O_DIRECT on backing file
 | 
					    -nocache		use O_DIRECT on backing file
 | 
				
			||||||
    -misalign		misalign memory allocations
 | 
					    -misalign		misalign memory allocations
 | 
				
			||||||
@ -197,12 +198,14 @@ testlist options
 | 
				
			|||||||
	    IMGPROTO=rbd
 | 
						    IMGPROTO=rbd
 | 
				
			||||||
	    xpand=false
 | 
						    xpand=false
 | 
				
			||||||
	    ;;
 | 
						    ;;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	-sheepdog)
 | 
						-sheepdog)
 | 
				
			||||||
	    IMGPROTO=sheepdog
 | 
						    IMGPROTO=sheepdog
 | 
				
			||||||
	    xpand=false
 | 
						    xpand=false
 | 
				
			||||||
	    ;;
 | 
						    ;;
 | 
				
			||||||
 | 
						-nbd)
 | 
				
			||||||
 | 
						    IMGPROTO=nbd
 | 
				
			||||||
 | 
						    xpand=false
 | 
				
			||||||
 | 
						    ;;
 | 
				
			||||||
	-nocache)
 | 
						-nocache)
 | 
				
			||||||
	    QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --nocache"
 | 
						    QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --nocache"
 | 
				
			||||||
	    xpand=false
 | 
						    xpand=false
 | 
				
			||||||
@ -350,7 +353,11 @@ fi
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[ "$QEMU" = "" ] && _fatal "qemu not found"
 | 
					[ "$QEMU" = "" ] && _fatal "qemu not found"
 | 
				
			||||||
[ "$QEMU_IMG" = "" ] && _fatal "qemu-img not found"
 | 
					[ "$QEMU_IMG" = "" ] && _fatal "qemu-img not found"
 | 
				
			||||||
[ "$QEMU_IO" = "" ] && _fatal "qemu-img not found"
 | 
					[ "$QEMU_IO" = "" ] && _fatal "qemu-io not found"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ "$IMGPROTO" = "nbd" ] ; then
 | 
				
			||||||
 | 
					    [ "$QEMU_NBD" = "" ] && _fatal "qemu-nbd not found"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if $valgrind; then
 | 
					if $valgrind; then
 | 
				
			||||||
    export REAL_QEMU_IO="$QEMU_IO_PROG"
 | 
					    export REAL_QEMU_IO="$QEMU_IO_PROG"
 | 
				
			||||||
 | 
				
			|||||||
@ -90,21 +90,23 @@ export PS_ALL_FLAGS="-ef"
 | 
				
			|||||||
if [ -z "$QEMU_PROG" ]; then
 | 
					if [ -z "$QEMU_PROG" ]; then
 | 
				
			||||||
    export QEMU_PROG="`set_prog_path qemu`"
 | 
					    export QEMU_PROG="`set_prog_path qemu`"
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
[ "$QEMU_PROG" = "" ] && _fatal "qemu not found"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
if [ -z "$QEMU_IMG_PROG" ]; then
 | 
					if [ -z "$QEMU_IMG_PROG" ]; then
 | 
				
			||||||
    export QEMU_IMG_PROG="`set_prog_path qemu-img`"
 | 
					    export QEMU_IMG_PROG="`set_prog_path qemu-img`"
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
[ "$QEMU_IMG_PROG" = "" ] && _fatal "qemu-img not found"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
if [ -z "$QEMU_IO_PROG" ]; then
 | 
					if [ -z "$QEMU_IO_PROG" ]; then
 | 
				
			||||||
    export QEMU_IO_PROG="`set_prog_path qemu-io`"
 | 
					    export QEMU_IO_PROG="`set_prog_path qemu-io`"
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
[ "$QEMU_IO_PROG" = "" ] && _fatal "qemu-io not found"
 | 
					
 | 
				
			||||||
 | 
					if [ -z "$QEMU_NBD_PROG" ]; then
 | 
				
			||||||
 | 
					    export QEMU_NBD_PROG="`set_prog_path qemu-nbd`"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export QEMU=$QEMU_PROG
 | 
					export QEMU=$QEMU_PROG
 | 
				
			||||||
export QEMU_IMG=$QEMU_IMG_PROG
 | 
					export QEMU_IMG=$QEMU_IMG_PROG
 | 
				
			||||||
export QEMU_IO="$QEMU_IO_PROG $QEMU_IO_OPTIONS"
 | 
					export QEMU_IO="$QEMU_IO_PROG $QEMU_IO_OPTIONS"
 | 
				
			||||||
 | 
					export QEMU_NBD=$QEMU_NBD_PROG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[ -f /etc/qemu-iotest.config ]       && . /etc/qemu-iotest.config
 | 
					[ -f /etc/qemu-iotest.config ]       && . /etc/qemu-iotest.config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -49,6 +49,9 @@ umask 022
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
if [ "$IMGPROTO" = "file" ]; then
 | 
					if [ "$IMGPROTO" = "file" ]; then
 | 
				
			||||||
    TEST_IMG=$TEST_DIR/t.$IMGFMT
 | 
					    TEST_IMG=$TEST_DIR/t.$IMGFMT
 | 
				
			||||||
 | 
					elif [ "$IMGPROTO" = "nbd" ]; then
 | 
				
			||||||
 | 
					    TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
 | 
				
			||||||
 | 
					    TEST_IMG="nbd:127.0.0.1:10810"
 | 
				
			||||||
else
 | 
					else
 | 
				
			||||||
    TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
 | 
					    TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
@ -86,6 +89,13 @@ _make_test_img()
 | 
				
			|||||||
    local extra_img_options=""
 | 
					    local extra_img_options=""
 | 
				
			||||||
    local image_size=$*
 | 
					    local image_size=$*
 | 
				
			||||||
    local optstr=""
 | 
					    local optstr=""
 | 
				
			||||||
 | 
					    local img_name=""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if [ -n "$TEST_IMG_FILE" ]; then
 | 
				
			||||||
 | 
					        img_name=$TEST_IMG_FILE
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        img_name=$TEST_IMG
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if [ -n "$IMGOPTS" ]; then
 | 
					    if [ -n "$IMGOPTS" ]; then
 | 
				
			||||||
        optstr=$(_optstr_add "$optstr" "$IMGOPTS")
 | 
					        optstr=$(_optstr_add "$optstr" "$IMGOPTS")
 | 
				
			||||||
@ -104,7 +114,7 @@ _make_test_img()
 | 
				
			|||||||
    fi
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # XXX(hch): have global image options?
 | 
					    # XXX(hch): have global image options?
 | 
				
			||||||
    $QEMU_IMG create -f $IMGFMT $extra_img_options $TEST_IMG $image_size | \
 | 
					    $QEMU_IMG create -f $IMGFMT $extra_img_options $img_name $image_size | \
 | 
				
			||||||
        sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
 | 
					        sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
 | 
				
			||||||
            -e "s#$TEST_DIR#TEST_DIR#g" \
 | 
					            -e "s#$TEST_DIR#TEST_DIR#g" \
 | 
				
			||||||
            -e "s#$IMGFMT#IMGFMT#g" \
 | 
					            -e "s#$IMGFMT#IMGFMT#g" \
 | 
				
			||||||
@ -115,12 +125,23 @@ _make_test_img()
 | 
				
			|||||||
            -e "s# compat6=\\(on\\|off\\)##g" \
 | 
					            -e "s# compat6=\\(on\\|off\\)##g" \
 | 
				
			||||||
            -e "s# static=\\(on\\|off\\)##g" \
 | 
					            -e "s# static=\\(on\\|off\\)##g" \
 | 
				
			||||||
            -e "s# lazy_refcounts=\\(on\\|off\\)##g"
 | 
					            -e "s# lazy_refcounts=\\(on\\|off\\)##g"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Start an NBD server on the image file, which is what we'll be talking to
 | 
				
			||||||
 | 
					    if [ $IMGPROTO = "nbd" ]; then
 | 
				
			||||||
 | 
					        eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810  $TEST_IMG_FILE &"
 | 
				
			||||||
 | 
					        QEMU_NBD_PID=$!
 | 
				
			||||||
 | 
					        sleep 1 # FIXME: qemu-nbd needs to be listening before we continue
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_cleanup_test_img()
 | 
					_cleanup_test_img()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    case "$IMGPROTO" in
 | 
					    case "$IMGPROTO" in
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        nbd)
 | 
				
			||||||
 | 
					            kill $QEMU_NBD_PID
 | 
				
			||||||
 | 
					            rm -f $TEST_IMG_FILE
 | 
				
			||||||
 | 
					            ;;
 | 
				
			||||||
        file)
 | 
					        file)
 | 
				
			||||||
            rm -f $TEST_DIR/t.$IMGFMT
 | 
					            rm -f $TEST_DIR/t.$IMGFMT
 | 
				
			||||||
            rm -f $TEST_DIR/t.$IMGFMT.orig
 | 
					            rm -f $TEST_DIR/t.$IMGFMT.orig
 | 
				
			||||||
 | 
				
			|||||||
@ -50,3 +50,4 @@
 | 
				
			|||||||
041 rw auto backing
 | 
					041 rw auto backing
 | 
				
			||||||
042 rw auto quick
 | 
					042 rw auto quick
 | 
				
			||||||
043 rw auto backing
 | 
					043 rw auto backing
 | 
				
			||||||
 | 
					044 rw auto
 | 
				
			||||||
 | 
				
			|||||||
@ -42,6 +42,10 @@ def qemu_img(*args):
 | 
				
			|||||||
    devnull = open('/dev/null', 'r+')
 | 
					    devnull = open('/dev/null', 'r+')
 | 
				
			||||||
    return subprocess.call(qemu_img_args + list(args), stdin=devnull, stdout=devnull)
 | 
					    return subprocess.call(qemu_img_args + list(args), stdin=devnull, stdout=devnull)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def qemu_img_verbose(*args):
 | 
				
			||||||
 | 
					    '''Run qemu-img without supressing its output and return the exit code'''
 | 
				
			||||||
 | 
					    return subprocess.call(qemu_img_args + list(args))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def qemu_io(*args):
 | 
					def qemu_io(*args):
 | 
				
			||||||
    '''Run qemu-io and return the stdout data'''
 | 
					    '''Run qemu-io and return the stdout data'''
 | 
				
			||||||
    args = qemu_io_args + list(args)
 | 
					    args = qemu_io_args + list(args)
 | 
				
			||||||
@ -182,4 +186,4 @@ def main(supported_fmts=[]):
 | 
				
			|||||||
    try:
 | 
					    try:
 | 
				
			||||||
        unittest.main(testRunner=MyTestRunner)
 | 
					        unittest.main(testRunner=MyTestRunner)
 | 
				
			||||||
    finally:
 | 
					    finally:
 | 
				
			||||||
        sys.stderr.write(re.sub(r'Ran (\d+) test[s] in [\d.]+s', r'Ran \1 tests', output.getvalue()))
 | 
					        sys.stderr.write(re.sub(r'Ran (\d+) tests? in [\d.]+s', r'Ran \1 tests', output.getvalue()))
 | 
				
			||||||
 | 
				
			|||||||
@ -233,6 +233,7 @@ def usage():
 | 
				
			|||||||
    for name, handler, num_args, desc in cmds:
 | 
					    for name, handler, num_args, desc in cmds:
 | 
				
			||||||
        print "    %-20s - %s" % (name, desc)
 | 
					        print "    %-20s - %s" % (name, desc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
    if len(sys.argv) < 3:
 | 
					    if len(sys.argv) < 3:
 | 
				
			||||||
        usage()
 | 
					        usage()
 | 
				
			||||||
        sys.exit(1)
 | 
					        sys.exit(1)
 | 
				
			||||||
 | 
				
			|||||||
@ -216,7 +216,7 @@ static void thread_pool_cancel(BlockDriverAIOCB *acb)
 | 
				
			|||||||
    qemu_mutex_unlock(&lock);
 | 
					    qemu_mutex_unlock(&lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AIOPool thread_pool_cb_pool = {
 | 
					static const AIOCBInfo thread_pool_aiocb_info = {
 | 
				
			||||||
    .aiocb_size         = sizeof(ThreadPoolElement),
 | 
					    .aiocb_size         = sizeof(ThreadPoolElement),
 | 
				
			||||||
    .cancel             = thread_pool_cancel,
 | 
					    .cancel             = thread_pool_cancel,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -226,7 +226,7 @@ BlockDriverAIOCB *thread_pool_submit_aio(ThreadPoolFunc *func, void *arg,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    ThreadPoolElement *req;
 | 
					    ThreadPoolElement *req;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    req = qemu_aio_get(&thread_pool_cb_pool, NULL, cb, opaque);
 | 
					    req = qemu_aio_get(&thread_pool_aiocb_info, NULL, cb, opaque);
 | 
				
			||||||
    req->func = func;
 | 
					    req->func = func;
 | 
				
			||||||
    req->arg = arg;
 | 
					    req->arg = arg;
 | 
				
			||||||
    req->state = THREAD_QUEUED;
 | 
					    req->state = THREAD_QUEUED;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user