[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 1/3] COW: Speed up writes
From: |
Charlie Shepherd |
Subject: |
[Qemu-devel] [PATCH v2 1/3] COW: Speed up writes |
Date: |
Wed, 6 Nov 2013 13:56:55 +0100 |
Process a whole sector's worth of COW bits by reading a sector, setting the
bits, then writing it
out again. Make sure we only flush once, before writing metadata.
Signed-off-by: Charlie Shepherd <address@hidden>
---
block/cow.c | 79 ++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 41 insertions(+), 38 deletions(-)
diff --git a/block/cow.c b/block/cow.c
index 909c3e7..5dfffb0 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -103,40 +103,18 @@ static int cow_open(BlockDriverState *bs, QDict *options,
int flags,
return ret;
}
-/*
- * XXX(hch): right now these functions are extremely inefficient.
- * We should just read the whole bitmap we'll need in one go instead.
- */
-static inline int cow_set_bit(BlockDriverState *bs, int64_t bitnum, bool
*first)
+static inline void cow_set_bits(uint8_t *bitmap, int start, int64_t nb_sectors)
{
- uint64_t offset = sizeof(struct cow_header_v2) + bitnum / 8;
- uint8_t bitmap;
- int ret;
-
- ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
- if (ret < 0) {
- return ret;
- }
-
- if (bitmap & (1 << (bitnum % 8))) {
- return 0;
- }
-
- if (*first) {
- ret = bdrv_flush(bs->file);
- if (ret < 0) {
- return ret;
+ int64_t bitnum = start, last = start + nb_sectors;
+ while (bitnum < last) {
+ if ((bitnum & 7) == 0 && bitnum + 8 <= last) {
+ bitmap[bitnum / 8] = 0xFF;
+ bitnum += 8;
+ continue;
}
- *first = false;
- }
-
- bitmap |= (1 << (bitnum % 8));
-
- ret = bdrv_pwrite(bs->file, offset, &bitmap, sizeof(bitmap));
- if (ret < 0) {
- return ret;
+ bitmap[bitnum/8] |= (1 << (bitnum % 8));
+ bitnum++;
}
- return 0;
}
#define BITS_PER_BITMAP_SECTOR (512 * 8)
@@ -204,18 +182,43 @@ static int64_t coroutine_fn
cow_co_get_block_status(BlockDriverState *bs,
static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num,
int nb_sectors)
{
- int error = 0;
- int i;
+ int64_t bitnum = sector_num + sizeof(struct cow_header_v2) * 8;
+ uint64_t offset = (bitnum / 8) & -BDRV_SECTOR_SIZE;
bool first = true;
- for (i = 0; i < nb_sectors; i++) {
- error = cow_set_bit(bs, sector_num + i, &first);
- if (error) {
- break;
+ while (nb_sectors) {
+ int ret;
+ uint8_t bitmap[BDRV_SECTOR_SIZE];
+
+ bitnum &= BITS_PER_BITMAP_SECTOR - 1;
+ int sector_bits = MIN(nb_sectors, BITS_PER_BITMAP_SECTOR - bitnum);
+
+ ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
+ if (ret < 0) {
+ return ret;
}
+
+ if (first) {
+ ret = bdrv_flush(bs->file);
+ if (ret < 0) {
+ return ret;
+ }
+ first = false;
+ }
+
+ cow_set_bits(bitmap, bitnum, sector_bits);
+
+ ret = bdrv_pwrite(bs->file, offset, &bitmap, sizeof(bitmap));
+ if (ret < 0) {
+ return ret;
+ }
+
+ bitnum += sector_bits;
+ nb_sectors -= sector_bits;
+ offset += BDRV_SECTOR_SIZE;
}
- return error;
+ return 0;
}
static int coroutine_fn cow_read(BlockDriverState *bs, int64_t sector_num,
--
1.8.4.rc3