Loading block.c +159 −99 Original line number Diff line number Diff line Loading @@ -53,17 +53,12 @@ static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque); static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque); static BlockDriverAIOCB *bdrv_aio_noop_em(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque); static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *iov); static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *iov); static int coroutine_fn bdrv_co_flush_em(BlockDriverState *bs); static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs, Loading Loading @@ -203,9 +198,6 @@ void bdrv_register(BlockDriver *bdrv) } } if (!bdrv->bdrv_aio_flush) bdrv->bdrv_aio_flush = bdrv_aio_flush_em; QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list); } Loading Loading @@ -1027,11 +1019,6 @@ static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num, nb_sectors * BDRV_SECTOR_SIZE); } static inline bool bdrv_has_async_flush(BlockDriver *drv) { return drv->bdrv_aio_flush != bdrv_aio_flush_em; } typedef struct RwCo { BlockDriverState *bs; int64_t sector_num; Loading Loading @@ -1759,33 +1746,6 @@ const char *bdrv_get_device_name(BlockDriverState *bs) return bs->device_name; } int bdrv_flush(BlockDriverState *bs) { if (bs->open_flags & BDRV_O_NO_FLUSH) { return 0; } if (bs->drv && bdrv_has_async_flush(bs->drv) && qemu_in_coroutine()) { return bdrv_co_flush_em(bs); } if (bs->drv && bs->drv->bdrv_flush) { return bs->drv->bdrv_flush(bs); } /* * Some block drivers always operate in either writethrough or unsafe mode * and don't support bdrv_flush therefore. Usually qemu doesn't know how * the server works (because the behaviour is hardcoded or depends on * server-side configuration), so we can't ensure that everything is safe * on disk. Returning an error doesn't work because that would break guests * even if the server operates in writethrough mode. * * Let's hope the user knows what he's doing. */ return 0; } void bdrv_flush_all(void) { BlockDriverState *bs; Loading @@ -1808,17 +1768,6 @@ int bdrv_has_zero_init(BlockDriverState *bs) return 1; } int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors) { if (!bs->drv) { return -ENOMEDIUM; } if (!bs->drv->bdrv_discard) { return 0; } return bs->drv->bdrv_discard(bs, sector_num, nb_sectors); } /* * Returns true iff the specified sector is present in the disk image. Drivers * not implementing the functionality are assumed to not support backing files, Loading Loading @@ -2610,22 +2559,6 @@ fail: return -1; } BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { BlockDriver *drv = bs->drv; trace_bdrv_aio_flush(bs, opaque); if (bs->open_flags & BDRV_O_NO_FLUSH) { return bdrv_aio_noop_em(bs, cb, opaque); } if (!drv) return NULL; return drv->bdrv_aio_flush(bs, cb, opaque); } void bdrv_aio_cancel(BlockDriverAIOCB *acb) { acb->pool->cancel(acb); Loading Loading @@ -2735,7 +2668,7 @@ static AIOPool bdrv_em_co_aio_pool = { .cancel = bdrv_aio_co_cancel_em, }; static void bdrv_co_rw_bh(void *opaque) static void bdrv_co_em_bh(void *opaque) { BlockDriverAIOCBCoroutine *acb = opaque; Loading @@ -2758,7 +2691,7 @@ static void coroutine_fn bdrv_co_do_rw(void *opaque) acb->req.nb_sectors, acb->req.qiov); } acb->bh = qemu_bh_new(bdrv_co_rw_bh, acb); acb->bh = qemu_bh_new(bdrv_co_em_bh, acb); qemu_bh_schedule(acb->bh); } Loading @@ -2785,41 +2718,56 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs, return &acb->common; } static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs, static void coroutine_fn bdrv_aio_flush_co_entry(void *opaque) { BlockDriverAIOCBCoroutine *acb = opaque; BlockDriverState *bs = acb->common.bs; acb->req.error = bdrv_co_flush(bs); acb->bh = qemu_bh_new(bdrv_co_em_bh, acb); qemu_bh_schedule(acb->bh); } BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { BlockDriverAIOCBSync *acb; trace_bdrv_aio_flush(bs, opaque); acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque); acb->is_write = 1; /* don't bounce in the completion hadler */ acb->qiov = NULL; acb->bounce = NULL; acb->ret = 0; Coroutine *co; BlockDriverAIOCBCoroutine *acb; if (!acb->bh) acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb); acb = qemu_aio_get(&bdrv_em_co_aio_pool, bs, cb, opaque); co = qemu_coroutine_create(bdrv_aio_flush_co_entry); qemu_coroutine_enter(co, acb); bdrv_flush(bs); qemu_bh_schedule(acb->bh); return &acb->common; } static BlockDriverAIOCB *bdrv_aio_noop_em(BlockDriverState *bs, static void coroutine_fn bdrv_aio_discard_co_entry(void *opaque) { BlockDriverAIOCBCoroutine *acb = opaque; BlockDriverState *bs = acb->common.bs; acb->req.error = bdrv_co_discard(bs, acb->req.sector, acb->req.nb_sectors); acb->bh = qemu_bh_new(bdrv_co_em_bh, acb); qemu_bh_schedule(acb->bh); } BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { BlockDriverAIOCBSync *acb; Coroutine *co; BlockDriverAIOCBCoroutine *acb; acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque); acb->is_write = 1; /* don't bounce in the completion handler */ acb->qiov = NULL; acb->bounce = NULL; acb->ret = 0; trace_bdrv_aio_discard(bs, sector_num, nb_sectors, opaque); if (!acb->bh) { acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb); } acb = qemu_aio_get(&bdrv_em_co_aio_pool, bs, cb, opaque); acb->req.sector = sector_num; acb->req.nb_sectors = nb_sectors; co = qemu_coroutine_create(bdrv_aio_discard_co_entry); qemu_coroutine_enter(co, acb); qemu_bh_schedule(acb->bh); return &acb->common; } Loading Loading @@ -2916,20 +2864,132 @@ static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs, return bdrv_co_io_em(bs, sector_num, nb_sectors, iov, true); } static int coroutine_fn bdrv_co_flush_em(BlockDriverState *bs) static void coroutine_fn bdrv_flush_co_entry(void *opaque) { RwCo *rwco = opaque; rwco->ret = bdrv_co_flush(rwco->bs); } int coroutine_fn bdrv_co_flush(BlockDriverState *bs) { if (bs->open_flags & BDRV_O_NO_FLUSH) { return 0; } else if (!bs->drv) { return 0; } else if (bs->drv->bdrv_co_flush) { return bs->drv->bdrv_co_flush(bs); } else if (bs->drv->bdrv_aio_flush) { BlockDriverAIOCB *acb; CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; BlockDriverAIOCB *acb; acb = bdrv_aio_flush(bs, bdrv_co_io_em_complete, &co); if (!acb) { acb = bs->drv->bdrv_aio_flush(bs, bdrv_co_io_em_complete, &co); if (acb == NULL) { return -EIO; } else { qemu_coroutine_yield(); return co.ret; } } else { /* * Some block drivers always operate in either writethrough or unsafe * mode and don't support bdrv_flush therefore. Usually qemu doesn't * know how the server works (because the behaviour is hardcoded or * depends on server-side configuration), so we can't ensure that * everything is safe on disk. Returning an error doesn't work because * that would break guests even if the server operates in writethrough * mode. * * Let's hope the user knows what he's doing. */ return 0; } } int bdrv_flush(BlockDriverState *bs) { Coroutine *co; RwCo rwco = { .bs = bs, .ret = NOT_DONE, }; if (qemu_in_coroutine()) { /* Fast-path if already in coroutine context */ bdrv_flush_co_entry(&rwco); } else { co = qemu_coroutine_create(bdrv_flush_co_entry); qemu_coroutine_enter(co, &rwco); while (rwco.ret == NOT_DONE) { qemu_aio_wait(); } } return rwco.ret; } static void coroutine_fn bdrv_discard_co_entry(void *opaque) { RwCo *rwco = opaque; rwco->ret = bdrv_co_discard(rwco->bs, rwco->sector_num, rwco->nb_sectors); } int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors) { if (!bs->drv) { return -ENOMEDIUM; } else if (bdrv_check_request(bs, sector_num, nb_sectors)) { return -EIO; } else if (bs->read_only) { return -EROFS; } else if (bs->drv->bdrv_co_discard) { return bs->drv->bdrv_co_discard(bs, sector_num, nb_sectors); } else if (bs->drv->bdrv_aio_discard) { BlockDriverAIOCB *acb; CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; acb = bs->drv->bdrv_aio_discard(bs, sector_num, nb_sectors, bdrv_co_io_em_complete, &co); if (acb == NULL) { return -EIO; } else { qemu_coroutine_yield(); return co.ret; } } else { return 0; } } int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors) { Coroutine *co; RwCo rwco = { .bs = bs, .sector_num = sector_num, .nb_sectors = nb_sectors, .ret = NOT_DONE, }; if (qemu_in_coroutine()) { /* Fast-path if already in coroutine context */ bdrv_discard_co_entry(&rwco); } else { co = qemu_coroutine_create(bdrv_discard_co_entry); qemu_coroutine_enter(co, &rwco); while (rwco.ret == NOT_DONE) { qemu_aio_wait(); } } return rwco.ret; } /**************************************************************/ /* removable device support */ Loading block.h +5 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,9 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, BlockDriverCompletionFunc *cb, void *opaque); BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque); BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque); void bdrv_aio_cancel(BlockDriverAIOCB *acb); typedef struct BlockRequest { Loading @@ -191,10 +194,12 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, /* Ensure contents are flushed to disk. */ int bdrv_flush(BlockDriverState *bs); int coroutine_fn bdrv_co_flush(BlockDriverState *bs); void bdrv_flush_all(void); void bdrv_close_all(void); int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors); int bdrv_co_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors); int bdrv_has_zero_init(BlockDriverState *bs); int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum); Loading block/blkdebug.c +0 −6 Original line number Diff line number Diff line Loading @@ -397,11 +397,6 @@ static void blkdebug_close(BlockDriverState *bs) } } static int blkdebug_flush(BlockDriverState *bs) { return bdrv_flush(bs->file); } static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { Loading Loading @@ -454,7 +449,6 @@ static BlockDriver bdrv_blkdebug = { .bdrv_file_open = blkdebug_open, .bdrv_close = blkdebug_close, .bdrv_flush = blkdebug_flush, .bdrv_aio_readv = blkdebug_aio_readv, .bdrv_aio_writev = blkdebug_aio_writev, Loading block/blkverify.c +0 −9 Original line number Diff line number Diff line Loading @@ -116,14 +116,6 @@ static void blkverify_close(BlockDriverState *bs) s->test_file = NULL; } static int blkverify_flush(BlockDriverState *bs) { BDRVBlkverifyState *s = bs->opaque; /* Only flush test file, the raw file is not important */ return bdrv_flush(s->test_file); } static int64_t blkverify_getlength(BlockDriverState *bs) { BDRVBlkverifyState *s = bs->opaque; Loading Loading @@ -368,7 +360,6 @@ static BlockDriver bdrv_blkverify = { .bdrv_file_open = blkverify_open, .bdrv_close = blkverify_close, .bdrv_flush = blkverify_flush, .bdrv_aio_readv = blkverify_aio_readv, .bdrv_aio_writev = blkverify_aio_writev, Loading block/bochs.c +14 −1 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ struct bochs_header { }; typedef struct BDRVBochsState { CoMutex lock; uint32_t *catalog_bitmap; int catalog_size; Loading Loading @@ -150,6 +151,7 @@ static int bochs_open(BlockDriverState *bs, int flags) s->extent_size = le32_to_cpu(bochs.extra.redolog.extent); qemu_co_mutex_init(&s->lock); return 0; fail: return -1; Loading Loading @@ -207,6 +209,17 @@ static int bochs_read(BlockDriverState *bs, int64_t sector_num, return 0; } static coroutine_fn int bochs_co_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors) { int ret; BDRVBochsState *s = bs->opaque; qemu_co_mutex_lock(&s->lock); ret = bochs_read(bs, sector_num, buf, nb_sectors); qemu_co_mutex_unlock(&s->lock); return ret; } static void bochs_close(BlockDriverState *bs) { BDRVBochsState *s = bs->opaque; Loading @@ -218,7 +231,7 @@ static BlockDriver bdrv_bochs = { .instance_size = sizeof(BDRVBochsState), .bdrv_probe = bochs_probe, .bdrv_open = bochs_open, .bdrv_read = bochs_read, .bdrv_read = bochs_co_read, .bdrv_close = bochs_close, }; Loading Loading
block.c +159 −99 Original line number Diff line number Diff line Loading @@ -53,17 +53,12 @@ static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque); static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque); static BlockDriverAIOCB *bdrv_aio_noop_em(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque); static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *iov); static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *iov); static int coroutine_fn bdrv_co_flush_em(BlockDriverState *bs); static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs, Loading Loading @@ -203,9 +198,6 @@ void bdrv_register(BlockDriver *bdrv) } } if (!bdrv->bdrv_aio_flush) bdrv->bdrv_aio_flush = bdrv_aio_flush_em; QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list); } Loading Loading @@ -1027,11 +1019,6 @@ static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num, nb_sectors * BDRV_SECTOR_SIZE); } static inline bool bdrv_has_async_flush(BlockDriver *drv) { return drv->bdrv_aio_flush != bdrv_aio_flush_em; } typedef struct RwCo { BlockDriverState *bs; int64_t sector_num; Loading Loading @@ -1759,33 +1746,6 @@ const char *bdrv_get_device_name(BlockDriverState *bs) return bs->device_name; } int bdrv_flush(BlockDriverState *bs) { if (bs->open_flags & BDRV_O_NO_FLUSH) { return 0; } if (bs->drv && bdrv_has_async_flush(bs->drv) && qemu_in_coroutine()) { return bdrv_co_flush_em(bs); } if (bs->drv && bs->drv->bdrv_flush) { return bs->drv->bdrv_flush(bs); } /* * Some block drivers always operate in either writethrough or unsafe mode * and don't support bdrv_flush therefore. Usually qemu doesn't know how * the server works (because the behaviour is hardcoded or depends on * server-side configuration), so we can't ensure that everything is safe * on disk. Returning an error doesn't work because that would break guests * even if the server operates in writethrough mode. * * Let's hope the user knows what he's doing. */ return 0; } void bdrv_flush_all(void) { BlockDriverState *bs; Loading @@ -1808,17 +1768,6 @@ int bdrv_has_zero_init(BlockDriverState *bs) return 1; } int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors) { if (!bs->drv) { return -ENOMEDIUM; } if (!bs->drv->bdrv_discard) { return 0; } return bs->drv->bdrv_discard(bs, sector_num, nb_sectors); } /* * Returns true iff the specified sector is present in the disk image. Drivers * not implementing the functionality are assumed to not support backing files, Loading Loading @@ -2610,22 +2559,6 @@ fail: return -1; } BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { BlockDriver *drv = bs->drv; trace_bdrv_aio_flush(bs, opaque); if (bs->open_flags & BDRV_O_NO_FLUSH) { return bdrv_aio_noop_em(bs, cb, opaque); } if (!drv) return NULL; return drv->bdrv_aio_flush(bs, cb, opaque); } void bdrv_aio_cancel(BlockDriverAIOCB *acb) { acb->pool->cancel(acb); Loading Loading @@ -2735,7 +2668,7 @@ static AIOPool bdrv_em_co_aio_pool = { .cancel = bdrv_aio_co_cancel_em, }; static void bdrv_co_rw_bh(void *opaque) static void bdrv_co_em_bh(void *opaque) { BlockDriverAIOCBCoroutine *acb = opaque; Loading @@ -2758,7 +2691,7 @@ static void coroutine_fn bdrv_co_do_rw(void *opaque) acb->req.nb_sectors, acb->req.qiov); } acb->bh = qemu_bh_new(bdrv_co_rw_bh, acb); acb->bh = qemu_bh_new(bdrv_co_em_bh, acb); qemu_bh_schedule(acb->bh); } Loading @@ -2785,41 +2718,56 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs, return &acb->common; } static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs, static void coroutine_fn bdrv_aio_flush_co_entry(void *opaque) { BlockDriverAIOCBCoroutine *acb = opaque; BlockDriverState *bs = acb->common.bs; acb->req.error = bdrv_co_flush(bs); acb->bh = qemu_bh_new(bdrv_co_em_bh, acb); qemu_bh_schedule(acb->bh); } BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { BlockDriverAIOCBSync *acb; trace_bdrv_aio_flush(bs, opaque); acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque); acb->is_write = 1; /* don't bounce in the completion hadler */ acb->qiov = NULL; acb->bounce = NULL; acb->ret = 0; Coroutine *co; BlockDriverAIOCBCoroutine *acb; if (!acb->bh) acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb); acb = qemu_aio_get(&bdrv_em_co_aio_pool, bs, cb, opaque); co = qemu_coroutine_create(bdrv_aio_flush_co_entry); qemu_coroutine_enter(co, acb); bdrv_flush(bs); qemu_bh_schedule(acb->bh); return &acb->common; } static BlockDriverAIOCB *bdrv_aio_noop_em(BlockDriverState *bs, static void coroutine_fn bdrv_aio_discard_co_entry(void *opaque) { BlockDriverAIOCBCoroutine *acb = opaque; BlockDriverState *bs = acb->common.bs; acb->req.error = bdrv_co_discard(bs, acb->req.sector, acb->req.nb_sectors); acb->bh = qemu_bh_new(bdrv_co_em_bh, acb); qemu_bh_schedule(acb->bh); } BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { BlockDriverAIOCBSync *acb; Coroutine *co; BlockDriverAIOCBCoroutine *acb; acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque); acb->is_write = 1; /* don't bounce in the completion handler */ acb->qiov = NULL; acb->bounce = NULL; acb->ret = 0; trace_bdrv_aio_discard(bs, sector_num, nb_sectors, opaque); if (!acb->bh) { acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb); } acb = qemu_aio_get(&bdrv_em_co_aio_pool, bs, cb, opaque); acb->req.sector = sector_num; acb->req.nb_sectors = nb_sectors; co = qemu_coroutine_create(bdrv_aio_discard_co_entry); qemu_coroutine_enter(co, acb); qemu_bh_schedule(acb->bh); return &acb->common; } Loading Loading @@ -2916,20 +2864,132 @@ static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs, return bdrv_co_io_em(bs, sector_num, nb_sectors, iov, true); } static int coroutine_fn bdrv_co_flush_em(BlockDriverState *bs) static void coroutine_fn bdrv_flush_co_entry(void *opaque) { RwCo *rwco = opaque; rwco->ret = bdrv_co_flush(rwco->bs); } int coroutine_fn bdrv_co_flush(BlockDriverState *bs) { if (bs->open_flags & BDRV_O_NO_FLUSH) { return 0; } else if (!bs->drv) { return 0; } else if (bs->drv->bdrv_co_flush) { return bs->drv->bdrv_co_flush(bs); } else if (bs->drv->bdrv_aio_flush) { BlockDriverAIOCB *acb; CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; BlockDriverAIOCB *acb; acb = bdrv_aio_flush(bs, bdrv_co_io_em_complete, &co); if (!acb) { acb = bs->drv->bdrv_aio_flush(bs, bdrv_co_io_em_complete, &co); if (acb == NULL) { return -EIO; } else { qemu_coroutine_yield(); return co.ret; } } else { /* * Some block drivers always operate in either writethrough or unsafe * mode and don't support bdrv_flush therefore. Usually qemu doesn't * know how the server works (because the behaviour is hardcoded or * depends on server-side configuration), so we can't ensure that * everything is safe on disk. Returning an error doesn't work because * that would break guests even if the server operates in writethrough * mode. * * Let's hope the user knows what he's doing. */ return 0; } } int bdrv_flush(BlockDriverState *bs) { Coroutine *co; RwCo rwco = { .bs = bs, .ret = NOT_DONE, }; if (qemu_in_coroutine()) { /* Fast-path if already in coroutine context */ bdrv_flush_co_entry(&rwco); } else { co = qemu_coroutine_create(bdrv_flush_co_entry); qemu_coroutine_enter(co, &rwco); while (rwco.ret == NOT_DONE) { qemu_aio_wait(); } } return rwco.ret; } static void coroutine_fn bdrv_discard_co_entry(void *opaque) { RwCo *rwco = opaque; rwco->ret = bdrv_co_discard(rwco->bs, rwco->sector_num, rwco->nb_sectors); } int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors) { if (!bs->drv) { return -ENOMEDIUM; } else if (bdrv_check_request(bs, sector_num, nb_sectors)) { return -EIO; } else if (bs->read_only) { return -EROFS; } else if (bs->drv->bdrv_co_discard) { return bs->drv->bdrv_co_discard(bs, sector_num, nb_sectors); } else if (bs->drv->bdrv_aio_discard) { BlockDriverAIOCB *acb; CoroutineIOCompletion co = { .coroutine = qemu_coroutine_self(), }; acb = bs->drv->bdrv_aio_discard(bs, sector_num, nb_sectors, bdrv_co_io_em_complete, &co); if (acb == NULL) { return -EIO; } else { qemu_coroutine_yield(); return co.ret; } } else { return 0; } } int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors) { Coroutine *co; RwCo rwco = { .bs = bs, .sector_num = sector_num, .nb_sectors = nb_sectors, .ret = NOT_DONE, }; if (qemu_in_coroutine()) { /* Fast-path if already in coroutine context */ bdrv_discard_co_entry(&rwco); } else { co = qemu_coroutine_create(bdrv_discard_co_entry); qemu_coroutine_enter(co, &rwco); while (rwco.ret == NOT_DONE) { qemu_aio_wait(); } } return rwco.ret; } /**************************************************************/ /* removable device support */ Loading
block.h +5 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,9 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, BlockDriverCompletionFunc *cb, void *opaque); BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque); BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque); void bdrv_aio_cancel(BlockDriverAIOCB *acb); typedef struct BlockRequest { Loading @@ -191,10 +194,12 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, /* Ensure contents are flushed to disk. */ int bdrv_flush(BlockDriverState *bs); int coroutine_fn bdrv_co_flush(BlockDriverState *bs); void bdrv_flush_all(void); void bdrv_close_all(void); int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors); int bdrv_co_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors); int bdrv_has_zero_init(BlockDriverState *bs); int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum); Loading
block/blkdebug.c +0 −6 Original line number Diff line number Diff line Loading @@ -397,11 +397,6 @@ static void blkdebug_close(BlockDriverState *bs) } } static int blkdebug_flush(BlockDriverState *bs) { return bdrv_flush(bs->file); } static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { Loading Loading @@ -454,7 +449,6 @@ static BlockDriver bdrv_blkdebug = { .bdrv_file_open = blkdebug_open, .bdrv_close = blkdebug_close, .bdrv_flush = blkdebug_flush, .bdrv_aio_readv = blkdebug_aio_readv, .bdrv_aio_writev = blkdebug_aio_writev, Loading
block/blkverify.c +0 −9 Original line number Diff line number Diff line Loading @@ -116,14 +116,6 @@ static void blkverify_close(BlockDriverState *bs) s->test_file = NULL; } static int blkverify_flush(BlockDriverState *bs) { BDRVBlkverifyState *s = bs->opaque; /* Only flush test file, the raw file is not important */ return bdrv_flush(s->test_file); } static int64_t blkverify_getlength(BlockDriverState *bs) { BDRVBlkverifyState *s = bs->opaque; Loading Loading @@ -368,7 +360,6 @@ static BlockDriver bdrv_blkverify = { .bdrv_file_open = blkverify_open, .bdrv_close = blkverify_close, .bdrv_flush = blkverify_flush, .bdrv_aio_readv = blkverify_aio_readv, .bdrv_aio_writev = blkverify_aio_writev, Loading
block/bochs.c +14 −1 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ struct bochs_header { }; typedef struct BDRVBochsState { CoMutex lock; uint32_t *catalog_bitmap; int catalog_size; Loading Loading @@ -150,6 +151,7 @@ static int bochs_open(BlockDriverState *bs, int flags) s->extent_size = le32_to_cpu(bochs.extra.redolog.extent); qemu_co_mutex_init(&s->lock); return 0; fail: return -1; Loading Loading @@ -207,6 +209,17 @@ static int bochs_read(BlockDriverState *bs, int64_t sector_num, return 0; } static coroutine_fn int bochs_co_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors) { int ret; BDRVBochsState *s = bs->opaque; qemu_co_mutex_lock(&s->lock); ret = bochs_read(bs, sector_num, buf, nb_sectors); qemu_co_mutex_unlock(&s->lock); return ret; } static void bochs_close(BlockDriverState *bs) { BDRVBochsState *s = bs->opaque; Loading @@ -218,7 +231,7 @@ static BlockDriver bdrv_bochs = { .instance_size = sizeof(BDRVBochsState), .bdrv_probe = bochs_probe, .bdrv_open = bochs_open, .bdrv_read = bochs_read, .bdrv_read = bochs_co_read, .bdrv_close = bochs_close, }; Loading