9ae3a8
From 4308c37b2fdabc82803dc9d2d521f564e2f34807 Mon Sep 17 00:00:00 2001
9ae3a8
From: Fam Zheng <famz@redhat.com>
9ae3a8
Date: Wed, 20 Nov 2013 09:16:43 +0100
9ae3a8
Subject: [PATCH 04/14] block: Avoid unecessary drv->bdrv_getlength() calls
9ae3a8
9ae3a8
RH-Author: Fam Zheng <famz@redhat.com>
9ae3a8
Message-id: <1384939004-30831-2-git-send-email-famz@redhat.com>
9ae3a8
Patchwork-id: 55784
9ae3a8
O-Subject: [RHEL-7 qemu-kvm PATCH 1/2] block: Avoid unecessary drv->bdrv_getlength() calls
9ae3a8
Bugzilla: 1025138
9ae3a8
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
9ae3a8
From: Kevin Wolf <kwolf@redhat.com>
9ae3a8
9ae3a8
The block layer generally keeps the size of an image cached in
9ae3a8
bs->total_sectors so that it doesn't have to perform expensive
9ae3a8
operations to get the size whenever it needs it.
9ae3a8
9ae3a8
This doesn't work however when using a backend that can change its size
9ae3a8
without qemu being aware of it, i.e. passthrough of removable media like
9ae3a8
CD-ROMs or floppy disks. For this reason, the caching is disabled when a
9ae3a8
removable device is used.
9ae3a8
9ae3a8
It is obvious that checking whether the _guest_ device has removable
9ae3a8
media isn't the right thing to do when we want to know whether the size
9ae3a8
of the host backend can change. To make things worse, non-top-level
9ae3a8
BlockDriverStates never have any device attached, which makes qemu
9ae3a8
assume they are removable, so drv->bdrv_getlength() is always called on
9ae3a8
the protocol layer. In the case of raw-posix, this causes unnecessary
9ae3a8
lseek() system calls, which turned out to be rather expensive.
9ae3a8
9ae3a8
This patch completely changes the logic and disables bs->total_sectors
9ae3a8
caching only for certain block driver types, for which a size change is
9ae3a8
expected: host_cdrom and host_floppy on POSIX, host_device on win32; also
9ae3a8
the raw format in case it sits on top of one of these protocols, but in
9ae3a8
the common case the nested bdrv_getlength() call on the protocol driver
9ae3a8
will use the cache again and avoid an expensive drv->bdrv_getlength()
9ae3a8
call.
9ae3a8
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
(cherry picked from commit b94a2610573cd9314f244207c8b04cb75e42d7f8)
9ae3a8
9ae3a8
Conflicts:
9ae3a8
	block/raw_bsd.c
9ae3a8
9ae3a8
Conflict because only have block/raw.c.
9ae3a8
9ae3a8
Signed-off-by: Fam Zheng <famz@redhat.com>
9ae3a8
---
9ae3a8
 block.c                   | 7 ++++---
9ae3a8
 block/raw-posix.c         | 9 ++++++---
9ae3a8
 block/raw-win32.c         | 4 +++-
9ae3a8
 block/raw.c               | 1 +
9ae3a8
 include/block/block_int.h | 3 +++
9ae3a8
 5 files changed, 17 insertions(+), 7 deletions(-)
9ae3a8
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 block.c                   |    7 ++++---
9ae3a8
 block/raw-posix.c         |    9 ++++++---
9ae3a8
 block/raw-win32.c         |    4 +++-
9ae3a8
 block/raw.c               |    1 +
9ae3a8
 include/block/block_int.h |    3 +++
9ae3a8
 5 files changed, 17 insertions(+), 7 deletions(-)
9ae3a8
9ae3a8
diff --git a/block.c b/block.c
9ae3a8
index 6913799..301c4fb 100644
9ae3a8
--- a/block.c
9ae3a8
+++ b/block.c
9ae3a8
@@ -2838,9 +2838,10 @@ int64_t bdrv_getlength(BlockDriverState *bs)
9ae3a8
     if (!drv)
9ae3a8
         return -ENOMEDIUM;
9ae3a8
 
9ae3a8
-    if (bdrv_dev_has_removable_media(bs)) {
9ae3a8
-        if (drv->bdrv_getlength) {
9ae3a8
-            return drv->bdrv_getlength(bs);
9ae3a8
+    if (drv->has_variable_length) {
9ae3a8
+        int ret = refresh_total_sectors(bs, bs->total_sectors);
9ae3a8
+        if (ret < 0) {
9ae3a8
+            return ret;
9ae3a8
         }
9ae3a8
     }
9ae3a8
     return bs->total_sectors * BDRV_SECTOR_SIZE;
9ae3a8
diff --git a/block/raw-posix.c b/block/raw-posix.c
9ae3a8
index 74b15da..eae1b40 100644
9ae3a8
--- a/block/raw-posix.c
9ae3a8
+++ b/block/raw-posix.c
9ae3a8
@@ -1718,7 +1718,8 @@ static BlockDriver bdrv_host_floppy = {
9ae3a8
     .bdrv_aio_flush	= raw_aio_flush,
9ae3a8
 
9ae3a8
     .bdrv_truncate      = raw_truncate,
9ae3a8
-    .bdrv_getlength	= raw_getlength,
9ae3a8
+    .bdrv_getlength      = raw_getlength,
9ae3a8
+    .has_variable_length = true,
9ae3a8
     .bdrv_get_allocated_file_size
9ae3a8
                         = raw_get_allocated_file_size,
9ae3a8
 
9ae3a8
@@ -1827,7 +1828,8 @@ static BlockDriver bdrv_host_cdrom = {
9ae3a8
     .bdrv_aio_flush	= raw_aio_flush,
9ae3a8
 
9ae3a8
     .bdrv_truncate      = raw_truncate,
9ae3a8
-    .bdrv_getlength     = raw_getlength,
9ae3a8
+    .bdrv_getlength      = raw_getlength,
9ae3a8
+    .has_variable_length = true,
9ae3a8
     .bdrv_get_allocated_file_size
9ae3a8
                         = raw_get_allocated_file_size,
9ae3a8
 
9ae3a8
@@ -1954,7 +1956,8 @@ static BlockDriver bdrv_host_cdrom = {
9ae3a8
     .bdrv_aio_flush	= raw_aio_flush,
9ae3a8
 
9ae3a8
     .bdrv_truncate      = raw_truncate,
9ae3a8
-    .bdrv_getlength     = raw_getlength,
9ae3a8
+    .bdrv_getlength      = raw_getlength,
9ae3a8
+    .has_variable_length = true,
9ae3a8
     .bdrv_get_allocated_file_size
9ae3a8
                         = raw_get_allocated_file_size,
9ae3a8
 
9ae3a8
diff --git a/block/raw-win32.c b/block/raw-win32.c
9ae3a8
index 3e0251f..584790f 100644
9ae3a8
--- a/block/raw-win32.c
9ae3a8
+++ b/block/raw-win32.c
9ae3a8
@@ -618,7 +618,9 @@ static BlockDriver bdrv_host_device = {
9ae3a8
     .bdrv_aio_writev    = raw_aio_writev,
9ae3a8
     .bdrv_aio_flush     = raw_aio_flush,
9ae3a8
 
9ae3a8
-    .bdrv_getlength	= raw_getlength,
9ae3a8
+    .bdrv_getlength      = raw_getlength,
9ae3a8
+    .has_variable_length = true,
9ae3a8
+
9ae3a8
     .bdrv_get_allocated_file_size
9ae3a8
                         = raw_get_allocated_file_size,
9ae3a8
 };
9ae3a8
diff --git a/block/raw.c b/block/raw.c
9ae3a8
index 66eda91..e1ed8cc 100644
9ae3a8
--- a/block/raw.c
9ae3a8
+++ b/block/raw.c
9ae3a8
@@ -151,6 +151,7 @@ static BlockDriver bdrv_raw = {
9ae3a8
 
9ae3a8
     .bdrv_probe         = raw_probe,
9ae3a8
     .bdrv_getlength     = raw_getlength,
9ae3a8
+    .has_variable_length = true,
9ae3a8
     .bdrv_truncate      = raw_truncate,
9ae3a8
 
9ae3a8
     .bdrv_is_inserted   = raw_is_inserted,
9ae3a8
diff --git a/include/block/block_int.h b/include/block/block_int.h
9ae3a8
index 0dbc34f..54708c6 100644
9ae3a8
--- a/include/block/block_int.h
9ae3a8
+++ b/include/block/block_int.h
9ae3a8
@@ -151,8 +151,11 @@ struct BlockDriver {
9ae3a8
 
9ae3a8
     const char *protocol_name;
9ae3a8
     int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
9ae3a8
+
9ae3a8
     int64_t (*bdrv_getlength)(BlockDriverState *bs);
9ae3a8
+    bool has_variable_length;
9ae3a8
     int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs);
9ae3a8
+
9ae3a8
     int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
9ae3a8
                                  const uint8_t *buf, int nb_sectors);
9ae3a8
 
9ae3a8
-- 
9ae3a8
1.7.1
9ae3a8