diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-01-14 16:26:54 +0100 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2013-01-15 10:03:47 +0100 |
commit | fcd9d4555252c47a337357dfce0806e5dde99d96 (patch) | |
tree | 71de3991a898bad3054eddd106a411d0683dc7bf | |
parent | c85191e5c9e14d65cc4281ef3b31f480227aa6dd (diff) |
raw: support discard on block devices
Block devices use a ioctl instead of fallocate, so add a separate
implementation.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-rw-r--r-- | block/raw-posix.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/block/raw-posix.c b/block/raw-posix.c index b647cfbb2f..1d32139c9b 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -1345,6 +1345,40 @@ static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs, return thread_pool_submit_aio(aio_worker, acb, cb, opaque); } +static coroutine_fn int hdev_co_discard(BlockDriverState *bs, + int64_t sector_num, int nb_sectors) +{ + BDRVRawState *s = bs->opaque; + int ret; + + if (s->has_discard == 0) { + return 0; + } + ret = fd_open(bs); + if (ret < 0) { + return ret; + } + + ret = -EOPNOTSUPP; +#ifdef BLKDISCARD + do { + uint64_t range[2] = { sector_num * 512, (uint64_t)nb_sectors * 512 }; + if (ioctl(s->fd, BLKDISCARD, range) == 0) { + return 0; + } + } while (errno == EINTR); + + ret = -errno; +#endif + if (ret == -ENODEV || ret == -ENOSYS || ret == -EOPNOTSUPP || + ret == -ENOTTY) { + s->has_discard = 0; + ret = 0; + } + return ret; + +} + #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) static int fd_open(BlockDriverState *bs) { @@ -1413,6 +1447,8 @@ static BlockDriver bdrv_host_device = { .create_options = raw_create_options, .bdrv_has_zero_init = hdev_has_zero_init, + .bdrv_co_discard = hdev_co_discard, + .bdrv_aio_readv = raw_aio_readv, .bdrv_aio_writev = raw_aio_writev, .bdrv_aio_flush = raw_aio_flush, |