diff --git a/block/raw-posix.c b/block/raw-posix.c index c3d7fda7b7..e8d79afe5f 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -59,6 +59,9 @@ #ifdef CONFIG_FIEMAP #include #endif +#ifdef CONFIG_FALLOCATE_PUNCH_HOLE +#include +#endif #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) #include #include @@ -1074,15 +1077,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 + int ret = -EOPNOTSUPP; + +#if defined(CONFIG_FALLOCATE_PUNCH_HOLE) || defined(CONFIG_XFS) BDRVRawState *s = bs->opaque; +#ifdef CONFIG_XFS if (s->is_xfs) { return xfs_discard(s, sector_num, nb_sectors); } #endif - return 0; +#ifdef CONFIG_FALLOCATE_PUNCH_HOLE + do { + if (fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, + sector_num << BDRV_SECTOR_BITS, + (int64_t)nb_sectors << BDRV_SECTOR_BITS) == 0) { + return 0; + } + } while (errno == EINTR); + + ret = -errno; +#endif +#endif + + if (ret == -EOPNOTSUPP) { + return 0; + } + return ret; } static QEMUOptionParameter raw_create_options[] = { diff --git a/configure b/configure index c908f66583..40d250ccac 100755 --- a/configure +++ b/configure @@ -2581,6 +2581,22 @@ if compile_prog "" "" ; then fallocate=yes fi +# check for fallocate hole punching +fallocate_punch_hole=no +cat > $TMPC << EOF +#include +#include + +int main(void) +{ + fallocate(0, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + fallocate_punch_hole=yes +fi + # check for sync_file_range sync_file_range=no cat > $TMPC << EOF @@ -3490,6 +3506,9 @@ fi if test "$fallocate" = "yes" ; then echo "CONFIG_FALLOCATE=y" >> $config_host_mak fi +if test "$fallocate_punch_hole" = "yes" ; then + echo "CONFIG_FALLOCATE_PUNCH_HOLE=y" >> $config_host_mak +fi if test "$sync_file_range" = "yes" ; then echo "CONFIG_SYNC_FILE_RANGE=y" >> $config_host_mak fi