From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
Jan Kiszka <jan.kiszka@siemens.com>,
Christoph Hellwig <hch@lst.de>,
Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Subject: [Qemu-devel] [PATCH 2/2] block: Cache total_sectors to reduce bdrv_getlength calls
Date: Mon, 19 Apr 2010 13:34:12 +0100 [thread overview]
Message-ID: <1271680452-24121-2-git-send-email-stefanha@linux.vnet.ibm.com> (raw)
In-Reply-To: <1271680452-24121-1-git-send-email-stefanha@linux.vnet.ibm.com>
The BlockDriver bdrv_getlength function is called from the I/O code path
when checking that the request falls within the device. Unfortunately
this involves an lseek system call in the raw protocol; every read or
write request will incur this lseek cost.
Jan Kiszka <jan.kiszka@siemens.com> identified this issue and its
latency overhead. This patch caches device length in the existing
total_sectors variable so lseek calls can be avoided for fixed size
devices.
Growable devices fall back to the full bdrv_getlength code path because
I have not added logic to detect extending the size of the device in a
write.
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
---
block.c | 28 ++++++++++++++++++++++------
1 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/block.c b/block.c
index def3400..d5a3ba7 100644
--- a/block.c
+++ b/block.c
@@ -363,6 +363,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
assert(drv != NULL);
bs->file = NULL;
+ bs->total_sectors = 0;
bs->is_temporary = 0;
bs->encrypted = 0;
bs->valid_key = 0;
@@ -416,9 +417,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
}
bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);
- if (drv->bdrv_getlength) {
- bs->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
- }
+ bs->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
#ifndef _WIN32
if (bs->is_temporary) {
unlink(filename);
@@ -959,13 +958,26 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
int bdrv_truncate(BlockDriverState *bs, int64_t offset)
{
BlockDriver *drv = bs->drv;
+ int ret;
if (!drv)
return -ENOMEDIUM;
if (!drv->bdrv_truncate)
return -ENOTSUP;
if (bs->read_only)
return -EACCES;
- return drv->bdrv_truncate(bs, offset);
+ ret = drv->bdrv_truncate(bs, offset);
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* refresh total sectors */
+ if (drv->bdrv_getlength) {
+ bs->total_sectors = 0; /* discard cached value */
+ bs->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
+ } else {
+ bs->total_sectors = offset >> BDRV_SECTOR_BITS;
+ }
+ return ret;
}
/**
@@ -976,8 +988,12 @@ int64_t bdrv_getlength(BlockDriverState *bs)
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_getlength) {
- /* legacy mode */
+
+ /* Fixed size devices use the total_sectors value for speed instead of
+ issuing a length query (like lseek) on each call. Also, legacy block
+ drivers don't provide a bdrv_getlength function and must use
+ total_sectors. */
+ if ((bs->total_sectors && !bs->growable) || !drv->bdrv_getlength) {
return bs->total_sectors * BDRV_SECTOR_SIZE;
}
return drv->bdrv_getlength(bs);
--
1.7.0
next prev parent reply other threads:[~2010-04-19 12:34 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-04-19 12:34 [Qemu-devel] [PATCH 1/2] raw-posix: Use pread/pwrite instead of lseek+read/write Stefan Hajnoczi
2010-04-19 12:34 ` Stefan Hajnoczi [this message]
2010-04-19 14:10 ` [Qemu-devel] Re: [PATCH 2/2] block: Cache total_sectors to reduce bdrv_getlength calls Kevin Wolf
2010-04-19 14:26 ` Stefan Hajnoczi
2010-04-19 14:31 ` Kevin Wolf
2010-04-20 8:37 ` [Qemu-devel] [PATCH 1/2] raw-posix: Use pread/pwrite instead of lseek+read/write 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=1271680452-24121-2-git-send-email-stefanha@linux.vnet.ibm.com \
--to=stefanha@linux.vnet.ibm.com \
--cc=hch@lst.de \
--cc=jan.kiszka@siemens.com \
--cc=kwolf@redhat.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).