From: Kevin Wolf <kwolf@redhat.com>
To: anthony@codemonkey.ws
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 03/12] block: implement is_allocated for raw
Date: Mon, 4 Jun 2012 13:13:20 +0200 [thread overview]
Message-ID: <1338808409-19501-4-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1338808409-19501-1-git-send-email-kwolf@redhat.com>
From: Paolo Bonzini <pbonzini@redhat.com>
Either FIEMAP, or SEEK_DATA+SEEK_HOLE can be used to implement the
is_allocated callback for raw files. On Linux ext4, btrfs and XFS
all support it.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/raw-posix.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++
block/raw.c | 8 ++++
2 files changed, 106 insertions(+), 0 deletions(-)
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 03fcfcc..bf7700a 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -52,6 +52,10 @@
#include <sys/param.h>
#include <linux/cdrom.h>
#include <linux/fd.h>
+#include <linux/fs.h>
+#endif
+#ifdef CONFIG_FIEMAP
+#include <linux/fiemap.h>
#endif
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <sys/disk.h>
@@ -583,6 +587,99 @@ 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)
+{
+ BDRVRawState *s = bs->opaque;
+ off_t start, data, hole;
+ int ret;
+
+ ret = fd_open(bs);
+ if (ret < 0) {
+ return ret;
+ }
+
+ start = sector_num * BDRV_SECTOR_SIZE;
+#ifdef CONFIG_FIEMAP
+ struct {
+ struct fiemap fm;
+ struct fiemap_extent fe;
+ } f;
+ 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) {
+ /* Assume everything is allocated. */
+ *pnum = nb_sectors;
+ return 1;
+ }
+
+ if (f.fm.fm_mapped_extents == 0) {
+ /* No extents found, data is beyond f.fm.fm_start + f.fm.fm_length.
+ * f.fm.fm_start + f.fm.fm_length must be clamped to the file size!
+ */
+ off_t length = lseek(s->fd, 0, SEEK_END);
+ hole = f.fm.fm_start;
+ data = MIN(f.fm.fm_start + f.fm.fm_length, length);
+ } else {
+ data = f.fe.fe_logical;
+ hole = f.fe.fe_logical + f.fe.fe_length;
+ }
+#elif defined SEEK_HOLE && defined SEEK_DATA
+ 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. */
+ *pnum = nb_sectors;
+ return 1;
+ }
+
+ if (hole > start) {
+ data = start;
+ } else {
+ /* On a hole. We need another syscall to find its end. */
+ data = lseek(s->fd, start, SEEK_DATA);
+ if (data == -1) {
+ data = lseek(s->fd, 0, SEEK_END);
+ }
+ }
+#else
+ *pnum = nb_sectors;
+ return 1;
+#endif
+
+ if (data <= start) {
+ /* On a data extent, compute sectors to the end of the extent. */
+ *pnum = MIN(nb_sectors, (hole - start) / BDRV_SECTOR_SIZE);
+ return 1;
+ } else {
+ /* On a hole, compute sectors to the beginning of the next extent. */
+ *pnum = MIN(nb_sectors, (data - start) / BDRV_SECTOR_SIZE);
+ return 0;
+ }
+}
+
#ifdef CONFIG_XFS
static int xfs_discard(BDRVRawState *s, int64_t sector_num, int nb_sectors)
{
@@ -634,6 +731,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 7086e31..09d9b48 100644
--- a/block/raw.c
+++ b/block/raw.c
@@ -25,6 +25,13 @@ static void raw_close(BlockDriverState *bs)
{
}
+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);
@@ -108,6 +115,7 @@ static BlockDriver bdrv_raw = {
.bdrv_co_readv = raw_co_readv,
.bdrv_co_writev = raw_co_writev,
+ .bdrv_co_is_allocated = raw_co_is_allocated,
.bdrv_co_discard = raw_co_discard,
.bdrv_probe = raw_probe,
--
1.7.6.5
next prev parent reply other threads:[~2012-06-04 11:13 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-06-04 11:13 [Qemu-devel] [PULL 00/12] Block patches Kevin Wolf
2012-06-04 11:13 ` [Qemu-devel] [PATCH 01/12] qcow2: remove a line of unnecessary code Kevin Wolf
2012-06-04 11:13 ` [Qemu-devel] [PATCH 02/12] qcow2: fix the byte endian convertion Kevin Wolf
2012-06-04 16:43 ` Eric Blake
2012-06-04 17:23 ` Kevin Wolf
2012-06-07 7:13 ` Michael Tokarev
2012-06-08 8:27 ` Kevin Wolf
2012-06-04 11:13 ` Kevin Wolf [this message]
2012-06-04 11:13 ` [Qemu-devel] [PATCH 04/12] stream: tweak usage of bdrv_co_is_allocated Kevin Wolf
2012-06-04 11:13 ` [Qemu-devel] [PATCH 05/12] stream: move is_allocated_above to block.c Kevin Wolf
2012-06-04 11:13 ` [Qemu-devel] [PATCH 06/12] stream: move rate limiting to a separate header file Kevin Wolf
2012-06-04 11:13 ` [Qemu-devel] [PATCH 07/12] Un-inline fdctrl_init_isa() Kevin Wolf
2012-06-04 11:13 ` [Qemu-devel] [PATCH 08/12] qemu-img check -r for repairing images Kevin Wolf
2012-06-04 11:13 ` [Qemu-devel] [PATCH 09/12] qemu-img check: Print fixed clusters and recheck Kevin Wolf
2012-06-04 11:13 ` [Qemu-devel] [PATCH 10/12] qcow2: Support for fixing refcount inconsistencies Kevin Wolf
2012-06-04 11:13 ` [Qemu-devel] [PATCH 11/12] rbd: hook up cache options Kevin Wolf
2012-06-04 11:13 ` [Qemu-devel] [PATCH 12/12] sheepdog: add coroutine_fn markers to coroutine functions Kevin Wolf
2012-06-07 1:17 ` [Qemu-devel] [PULL 00/12] Block patches Anthony Liguori
2012-06-08 9:48 ` Kevin Wolf
2012-06-08 14:07 ` Anthony Liguori
2012-06-08 14:57 ` Kevin Wolf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1338808409-19501-4-git-send-email-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=anthony@codemonkey.ws \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.