From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48502) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WhP56-0004sO-EP for qemu-devel@nongnu.org; Mon, 05 May 2014 16:01:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WhP55-0007VL-Dl for qemu-devel@nongnu.org; Mon, 05 May 2014 16:01:44 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60548) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WhP55-0007VF-73 for qemu-devel@nongnu.org; Mon, 05 May 2014 16:01:43 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s45K1gh1017546 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 5 May 2014 16:01:42 -0400 From: Max Reitz Date: Mon, 5 May 2014 22:01:39 +0200 Message-Id: <1399320099-32457-1-git-send-email-mreitz@redhat.com> Subject: [Qemu-devel] [PATCH] block/raw-posix: Fall back to SEEK_HOLE/SEEK_DATA List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Kevin Wolf , Stefan Hajnoczi , Max Reitz The current version of raw-posix always uses ioctl(FS_IOC_FIEMAP) if FIEMAP is available; lseek with SEEK_HOLE/SEEK_DATA are not even compiled in in this case. However, there may be implementations which support the latter but not the former (e.g., NFSv4.2). In this case, raw-posix should fall back to lseek with SEEK_HOLE/SEEK_DATA if FIEMAP does not work. Signed-off-by: Max Reitz --- As Linux does not yet implement NFSv4.2 (I don't even know whether the specification is complete), I have no way of testing whether this actually works for the proposed case. But as it doesn't break any of the existing test cases, it should be fine. --- block/raw-posix.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index 3ce026d..e523633 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -146,6 +146,9 @@ typedef struct BDRVRawState { bool has_discard:1; bool has_write_zeroes:1; bool discard_zeroes:1; +#if defined CONFIG_FIEMAP && defined SEEK_HOLE && defined SEEK_DATA + bool use_seek_hole_data; +#endif } BDRVRawState; typedef struct BDRVRawReopenState { @@ -1291,6 +1294,7 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum) { + BDRVRawState *s = bs->opaque; off_t start, data, hole; int64_t ret; @@ -1303,22 +1307,31 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start; #ifdef CONFIG_FIEMAP - - BDRVRawState *s = bs->opaque; struct { struct fiemap fm; struct fiemap_extent fe; } f; +#if defined SEEK_HOLE && defined SEEK_DATA + if (s->use_seek_hole_data) { + goto try_seek_hole_data; + } +#endif + f.fm.fm_start = start; f.fm.fm_length = (int64_t)nb_sectors * BDRV_SECTOR_SIZE; f.fm.fm_flags = 0; f.fm.fm_extent_count = 1; f.fm.fm_reserved = 0; if (ioctl(s->fd, FS_IOC_FIEMAP, &f) == -1) { +#if defined SEEK_HOLE && defined SEEK_DATA + s->use_seek_hole_data = true; + goto try_seek_hole_data; +#else /* Assume everything is allocated. */ *pnum = nb_sectors; return ret; +#endif } if (f.fm.fm_mapped_extents == 0) { @@ -1336,10 +1349,11 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, } } -#elif defined SEEK_HOLE && defined SEEK_DATA - - BDRVRawState *s = bs->opaque; + goto done; +#endif +#if defined SEEK_HOLE && defined SEEK_DATA +try_seek_hole_data: hole = lseek(s->fd, start, SEEK_HOLE); if (hole == -1) { /* -ENXIO indicates that sector_num was past the end of the file. @@ -1360,11 +1374,12 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, data = lseek(s->fd, 0, SEEK_END); } } -#else +#elif !defined CONFIG_FIEMAP data = 0; hole = start + nb_sectors * BDRV_SECTOR_SIZE; #endif +done: if (data <= start) { /* On a data extent, compute sectors to the end of the extent. */ *pnum = MIN(nb_sectors, (hole - start) / BDRV_SECTOR_SIZE); -- 1.9.2