From patchwork Thu Mar 8 17:15:17 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 145607 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 05656B6EE6 for ; Fri, 9 Mar 2012 05:08:13 +1100 (EST) Received: from localhost ([::1]:47003 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S5hl4-0005Br-L1 for incoming@patchwork.ozlabs.org; Thu, 08 Mar 2012 13:08:10 -0500 Received: from eggs.gnu.org ([208.118.235.92]:40961) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S5gww-0005Vd-8j for qemu-devel@nongnu.org; Thu, 08 Mar 2012 12:16:26 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S5gwg-0004tQ-C8 for qemu-devel@nongnu.org; Thu, 08 Mar 2012 12:16:21 -0500 Received: from mail-iy0-f173.google.com ([209.85.210.173]:47906) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S5gwg-0004n5-4p for qemu-devel@nongnu.org; Thu, 08 Mar 2012 12:16:06 -0500 Received: by mail-iy0-f173.google.com with SMTP id j26so1015616iaf.4 for ; Thu, 08 Mar 2012 09:16:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:subject:date:message-id:x-mailer:in-reply-to :references; bh=aGEKrEn1UX/Kxx+vJx7XU53cUpsQOI032vT5V1gxs+A=; b=zHjYsd83BtV3M8O+HtBWiKnOM9+dueT9RJ+5Nx08u/VYm8uI+B0QfotSuyVEHhMA9W kv730dhPs1Al3/5Bvr9mTaWZvPTXqvp01sulj6O7IhP6h8gOgT6heTVS7SUnbZ+7GmXR G0ZJWjPsosDIpSMZh2RjXW2EmatvgsGxn/g0Vylsr6Z2n0wqeqy+sOlIX9FkzwqlEIRc 4WWc0DnS7Q0Pg7lK5+DyPv6cmXI4Z7xUhAo4dsPU0iOd1tV9jRbq/Zxw5OSGDITk1nVH ZlAz0dtA/FhnQ/TcwNNRMQlbY5DOd5ylVQIW34C4gBoRZ5CP9vGBRBcSfKdYgXrDeWp+ vyIw== Received: by 10.50.207.34 with SMTP id lt2mr1394492igc.49.1331226965479; Thu, 08 Mar 2012 09:16:05 -0800 (PST) Received: from yakj.usersys.redhat.com (93-34-182-16.ip50.fastwebnet.it. [93.34.182.16]) by mx.google.com with ESMTPS id s3sm2123819igw.17.2012.03.08.09.16.03 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 08 Mar 2012 09:16:04 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 8 Mar 2012 18:15:17 +0100 Message-Id: <1331226917-6658-18-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.7.6 In-Reply-To: <1331226917-6658-1-git-send-email-pbonzini@redhat.com> References: <1331226917-6658-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.210.173 Subject: [Qemu-devel] [RFC PATCH 17/17] raw: implement is_allocated X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org SEEK_DATA and SEEK_HOLE can be used to implement the is_allocated callback for raw files. These currently work on btrfs, with an XFS implementation also coming soon. Signed-off-by: Paolo Bonzini --- block/raw-posix.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++ block/raw.c | 8 ++++++ 2 files changed, 70 insertions(+), 0 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index 56aabc7..c0b32e1 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -105,6 +105,13 @@ #define O_DIRECT O_DSYNC #endif +#ifndef SEEK_DATA +#define SEEK_DATA 3 +#endif +#ifndef SEEK_HOLE +#define SEEK_HOLE 4 +#endif + #define FTYPE_FILE 0 #define FTYPE_CD 1 #define FTYPE_FD 2 @@ -583,6 +590,60 @@ static int raw_create(const char *filename, QEMUOptionParameter *options) return result; } +/* + * Returns true iff the specified sector is present in the disk image. Drivers + * not implementing the functionality are assumed to not support backing files, + * hence all their sectors are reported as allocated. + * + * If 'sector_num' is beyond the end of the disk image the return value is 0 + * and 'pnum' is set to 0. + * + * 'pnum' is set to the number of sectors (including and immediately following + * the specified sector) that are known to be in the same + * allocated/unallocated state. + * + * 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes + * beyond the end of the disk image it will be clamped. + */ +static int coroutine_fn raw_co_is_allocated(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, int *pnum) +{ + off_t start, data, hole; + int ret, num; + BDRVRawState *s = bs->opaque; + + ret = fd_open(bs); + if (ret < 0) { + return ret; + } + + start = sector_num * BDRV_SECTOR_SIZE; + hole = lseek(s->fd, start, SEEK_HOLE); + if (hole == -1) { + /* -ENXIO indicates that sector_num was past the end of the file. + * There is a virtual hole there. */ + assert(errno != -ENXIO); + + /* Most likely EINVAL. Assume everything is allocated. */ + return 1; + } + + if (hole == start) { + /* On a hole. We need another syscall to find its end. */ + data = lseek(s->fd, start, SEEK_DATA); + assert (data != -1); + num = (data - start) / BDRV_SECTOR_SIZE; + } else { + data = start; + num = (hole - start) / BDRV_SECTOR_SIZE; + } + + /* Clamping to the file size is done by the kernel. */ + *pnum = MIN(nb_sectors, num); + return data == start; +} + #ifdef CONFIG_XFS static int xfs_discard(BDRVRawState *s, int64_t sector_num, int nb_sectors) { @@ -661,6 +722,7 @@ static BlockDriver bdrv_file = { .bdrv_close = raw_close, .bdrv_create = raw_create, .bdrv_co_discard = raw_co_discard, + .bdrv_co_is_allocated = raw_co_is_allocated, .bdrv_aio_readv = raw_aio_readv, .bdrv_aio_writev = raw_aio_writev, diff --git a/block/raw.c b/block/raw.c index 3618c2d..e433bf2 100644 --- a/block/raw.c +++ b/block/raw.c @@ -30,6 +30,13 @@ static int coroutine_fn raw_co_flush(BlockDriverState *bs) return bdrv_co_flush(bs->file); } +static int coroutine_fn raw_co_is_allocated(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, int *pnum) +{ + return bdrv_co_is_allocated(bs->file, sector_num, nb_sectors, pnum); +} + static int64_t raw_getlength(BlockDriverState *bs) { return bdrv_getlength(bs->file); @@ -119,6 +126,7 @@ static BlockDriver bdrv_raw = { .bdrv_co_readv = raw_co_readv, .bdrv_co_writev = raw_co_writev, .bdrv_co_flush_to_disk = raw_co_flush, + .bdrv_co_is_allocated = raw_co_is_allocated, .bdrv_co_discard = raw_co_discard, .bdrv_probe = raw_probe,