Skip to content

Commit

Permalink
block: add bdrv_co_discard and bdrv_aio_discard support
Browse files Browse the repository at this point in the history
This similarly adds support for coroutine and asynchronous discard.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
  • Loading branch information
bonzini authored and kevmw committed Oct 21, 2011
1 parent 6f6dc65 commit 4265d62
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 17 deletions.
102 changes: 91 additions & 11 deletions block.c
Original file line number Diff line number Diff line change
Expand Up @@ -1768,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,
Expand Down Expand Up @@ -2754,6 +2743,34 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
return &acb->common;
}

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)
{
Coroutine *co;
BlockDriverAIOCBCoroutine *acb;

trace_bdrv_aio_discard(bs, sector_num, nb_sectors, opaque);

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);

return &acb->common;
}

void bdrv_init(void)
{
module_call_init(MODULE_INIT_BLOCK);
Expand Down Expand Up @@ -2915,6 +2932,69 @@ int bdrv_flush(BlockDriverState *bs)
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 if (bs->drv->bdrv_discard) {
return bs->drv->bdrv_discard(bs, sector_num, nb_sectors);
} 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 */

Expand Down
4 changes: 4 additions & 0 deletions block.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -196,6 +199,7 @@ 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);
Expand Down
10 changes: 6 additions & 4 deletions block/raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
return 1; /* everything can be opened as raw image */
}

static int raw_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
static int coroutine_fn raw_co_discard(BlockDriverState *bs,
int64_t sector_num, int nb_sectors)
{
return bdrv_discard(bs->file, sector_num, nb_sectors);
return bdrv_co_discard(bs->file, sector_num, nb_sectors);
}

static int raw_is_inserted(BlockDriverState *bs)
Expand Down Expand Up @@ -109,15 +110,16 @@ static BlockDriver bdrv_raw = {

.bdrv_open = raw_open,
.bdrv_close = raw_close,

.bdrv_co_readv = raw_co_readv,
.bdrv_co_writev = raw_co_writev,
.bdrv_co_flush = raw_co_flush,
.bdrv_co_discard = raw_co_discard,

.bdrv_probe = raw_probe,
.bdrv_getlength = raw_getlength,
.bdrv_truncate = raw_truncate,

.bdrv_discard = raw_discard,

.bdrv_is_inserted = raw_is_inserted,
.bdrv_media_changed = raw_media_changed,
.bdrv_eject = raw_eject,
Expand Down
9 changes: 7 additions & 2 deletions block_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ struct BlockDriver {
void (*bdrv_close)(BlockDriverState *bs);
int (*bdrv_create)(const char *filename, QEMUOptionParameter *options);
int (*bdrv_flush)(BlockDriverState *bs);
int (*bdrv_discard)(BlockDriverState *bs, int64_t sector_num,
int nb_sectors);
int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum);
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
Expand All @@ -76,14 +78,17 @@ struct BlockDriver {
BlockDriverCompletionFunc *cb, void *opaque);
BlockDriverAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs,
BlockDriverCompletionFunc *cb, void *opaque);
int (*bdrv_discard)(BlockDriverState *bs, int64_t sector_num,
int nb_sectors);
BlockDriverAIOCB *(*bdrv_aio_discard)(BlockDriverState *bs,
int64_t sector_num, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);

int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
int coroutine_fn (*bdrv_co_flush)(BlockDriverState *bs);
int coroutine_fn (*bdrv_co_discard)(BlockDriverState *bs,
int64_t sector_num, int nb_sectors);

int (*bdrv_aio_multiwrite)(BlockDriverState *bs, BlockRequest *reqs,
int num_reqs);
Expand Down
1 change: 1 addition & 0 deletions trace-events
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ multiwrite_cb(void *mcb, int ret) "mcb %p ret %d"
bdrv_aio_multiwrite(void *mcb, int num_callbacks, int num_reqs) "mcb %p num_callbacks %d num_reqs %d"
bdrv_aio_multiwrite_earlyfail(void *mcb) "mcb %p"
bdrv_aio_multiwrite_latefail(void *mcb, int i) "mcb %p i %d"
bdrv_aio_discard(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
bdrv_aio_flush(void *bs, void *opaque) "bs %p opaque %p"
bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
bdrv_aio_writev(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
Expand Down

0 comments on commit 4265d62

Please sign in to comment.