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