This will enable discard on more filesystems, including ext4. Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- block/raw-posix.c | 29 ++++++++++++++++++++++++----- 1 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/block/raw-posix.c b/block/raw-posix.c index 2d1bc13..f23d92b 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -52,6 +52,7 @@ #include <sys/param.h> #include <linux/cdrom.h> #include <linux/fd.h> +#include <linux/falloc.h> #endif #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) #include <sys/disk.h> @@ -131,6 +132,7 @@ typedef struct BDRVRawState { #endif uint8_t *aligned_buf; unsigned aligned_buf_size; + bool has_discard : 1; #ifdef CONFIG_XFS bool is_xfs : 1; #endif @@ -257,11 +259,9 @@ static int raw_open_common(BlockDriverState *bs, const char *filename, } #ifdef CONFIG_XFS - if (platform_test_xfs_fd(s->fd)) { - s->is_xfs = 1; - } + s->is_xfs = platform_test_xfs_fd(s->fd); #endif - + s->has_discard = 1; return 0; out_free_buf: @@ -605,15 +605,34 @@ static int xfs_discard(BDRVRawState *s, int64_t sector_num, int nb_sectors) static coroutine_fn int raw_co_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors) { -#ifdef CONFIG_XFS BDRVRawState *s = bs->opaque; + int retval; + if (s->has_discard == 0) { + return -ENOTSUP; + } +#ifdef CONFIG_XFS if (s->is_xfs) { return xfs_discard(s, sector_num, nb_sectors); } #endif +#ifdef FALLOC_FL_PUNCH_HOLE + retval = fallocate(s->fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, + sector_num << 9, (int64_t)nb_sectors << 9); + if (retval == -1) { + if (errno == ENODEV || errno == ENOSYS || errno == EOPNOTSUPP) { + s->has_discard = 0; + return -ENOTSUP; + } else { + return -errno; + } + } return 0; +#else + s->has_discard = 0; + return -ENOTSUP; +#endif } static QEMUOptionParameter raw_create_options[] = { -- 1.7.7.6