aboutsummaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2013-01-14 16:26:54 +0100
committerStefan Hajnoczi <stefanha@redhat.com>2013-01-15 10:03:47 +0100
commitfcd9d4555252c47a337357dfce0806e5dde99d96 (patch)
tree71de3991a898bad3054eddd106a411d0683dc7bf /block
parentc85191e5c9e14d65cc4281ef3b31f480227aa6dd (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>
Diffstat (limited to 'block')
-rw-r--r--block/raw-posix.c36
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,