From: Kevin Wolf <kwolf@redhat.com>
To: anthony@codemonkey.ws
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 09/19] cow: stop using mmap
Date: Tue, 15 Jun 2010 16:19:31 +0200 [thread overview]
Message-ID: <1276611581-3757-10-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1276611581-3757-1-git-send-email-kwolf@redhat.com>
From: Christoph Hellwig <hch@lst.de>
We don't have an equivalent to mmap in the qemu block API, so read and
write the bitmap directly. At least in the dumb implementation added
in this patch this is a lot less efficient, but it means cow can also
work on windows, and over nbd or curl. And it fixes qemu-iotests testcase
012 which did not work properly due to issues with read-only mmap access.
In addition we can also get rid of the now unused get_mmap_addr function.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/cow.c | 98 +++++++++++++++++++++++++++++++++++---------------------
qemu-common.h | 3 --
qemu-malloc.c | 5 ---
3 files changed, 61 insertions(+), 45 deletions(-)
diff --git a/block/cow.c b/block/cow.c
index 1a48ac0..ec9a9f7 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -21,11 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#ifndef _WIN32
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
-#include <sys/mman.h>
/**************************************************************/
/* COW block driver using file system holes */
@@ -45,9 +43,6 @@ struct cow_header_v2 {
typedef struct BDRVCowState {
int fd;
- uint8_t *cow_bitmap; /* if non NULL, COW mappings are used first */
- uint8_t *cow_bitmap_addr; /* mmap address of cow_bitmap */
- int cow_bitmap_size;
int64_t cow_sectors_offset;
} BDRVCowState;
@@ -68,6 +63,7 @@ static int cow_open(BlockDriverState *bs, const char *filename, int flags)
BDRVCowState *s = bs->opaque;
int fd;
struct cow_header_v2 cow_header;
+ int bitmap_size;
int64_t size;
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
@@ -94,61 +90,92 @@ static int cow_open(BlockDriverState *bs, const char *filename, int flags)
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
cow_header.backing_file);
- /* mmap the bitmap */
- s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
- s->cow_bitmap_addr = (void *)mmap(get_mmap_addr(s->cow_bitmap_size),
- s->cow_bitmap_size,
- PROT_READ | PROT_WRITE,
- MAP_SHARED, s->fd, 0);
- if (s->cow_bitmap_addr == MAP_FAILED)
- goto fail;
- s->cow_bitmap = s->cow_bitmap_addr + sizeof(cow_header);
- s->cow_sectors_offset = (s->cow_bitmap_size + 511) & ~511;
+ bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
+ s->cow_sectors_offset = (bitmap_size + 511) & ~511;
return 0;
fail:
close(fd);
return -1;
}
-static inline void cow_set_bit(uint8_t *bitmap, int64_t bitnum)
+/*
+ * XXX(hch): right now these functions are extremly ineffcient.
+ * 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)
{
- bitmap[bitnum / 8] |= (1 << (bitnum%8));
+ BDRVCowState *s = bs->opaque;
+ uint64_t offset = sizeof(struct cow_header_v2) + bitnum / 8;
+ uint8_t bitmap;
+
+ if (pread(s->fd, &bitmap, sizeof(bitmap), offset) !=
+ sizeof(bitmap)) {
+ return -errno;
+ }
+
+ bitmap |= (1 << (bitnum % 8));
+
+ if (pwrite(s->fd, &bitmap, sizeof(bitmap), offset) !=
+ sizeof(bitmap)) {
+ return -errno;
+ }
+ return 0;
}
-static inline int is_bit_set(const uint8_t *bitmap, int64_t bitnum)
+static inline int is_bit_set(BlockDriverState *bs, int64_t bitnum)
{
- return !!(bitmap[bitnum / 8] & (1 << (bitnum%8)));
-}
+ BDRVCowState *s = bs->opaque;
+ uint64_t offset = sizeof(struct cow_header_v2) + bitnum / 8;
+ uint8_t bitmap;
+ if (pread(s->fd, &bitmap, sizeof(bitmap), offset) !=
+ sizeof(bitmap)) {
+ return -errno;
+ }
+
+ return !!(bitmap & (1 << (bitnum % 8)));
+}
/* Return true if first block has been changed (ie. current version is
* in COW file). Set the number of continuous blocks for which that
* is true. */
-static inline int is_changed(uint8_t *bitmap,
- int64_t sector_num, int nb_sectors,
- int *num_same)
+static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors, int *num_same)
{
int changed;
- if (!bitmap || nb_sectors == 0) {
+ if (nb_sectors == 0) {
*num_same = nb_sectors;
return 0;
}
- changed = is_bit_set(bitmap, sector_num);
+ changed = is_bit_set(bs, sector_num);
+ if (changed < 0) {
+ return 0; /* XXX: how to return I/O errors? */
+ }
+
for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) {
- if (is_bit_set(bitmap, sector_num + *num_same) != changed)
+ if (is_bit_set(bs, sector_num + *num_same) != changed)
break;
}
return changed;
}
-static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
- int nb_sectors, int *pnum)
+static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors)
{
- BDRVCowState *s = bs->opaque;
- return is_changed(s->cow_bitmap, sector_num, nb_sectors, pnum);
+ int error = 0;
+ int i;
+
+ for (i = 0; i < nb_sectors; i++) {
+ error = cow_set_bit(bs, sector_num + i);
+ if (error) {
+ break;
+ }
+ }
+
+ return error;
}
static int cow_read(BlockDriverState *bs, int64_t sector_num,
@@ -158,7 +185,7 @@ static int cow_read(BlockDriverState *bs, int64_t sector_num,
int ret, n;
while (nb_sectors > 0) {
- if (is_changed(s->cow_bitmap, sector_num, nb_sectors, &n)) {
+ if (cow_is_allocated(bs, sector_num, nb_sectors, &n)) {
ret = pread(s->fd, buf, n * 512,
s->cow_sectors_offset + sector_num * 512);
if (ret != n * 512)
@@ -184,21 +211,19 @@ static int cow_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVCowState *s = bs->opaque;
- int ret, i;
+ int ret;
ret = pwrite(s->fd, buf, nb_sectors * 512,
s->cow_sectors_offset + sector_num * 512);
if (ret != nb_sectors * 512)
return -1;
- for (i = 0; i < nb_sectors; i++)
- cow_set_bit(s->cow_bitmap, sector_num + i);
- return 0;
+
+ return cow_update_bitmap(bs, sector_num, nb_sectors);
}
static void cow_close(BlockDriverState *bs)
{
BDRVCowState *s = bs->opaque;
- munmap((void *)s->cow_bitmap_addr, s->cow_bitmap_size);
close(s->fd);
}
@@ -308,4 +333,3 @@ static void bdrv_cow_init(void)
}
block_init(bdrv_cow_init);
-#endif
diff --git a/qemu-common.h b/qemu-common.h
index d133f35..00998c3 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -164,9 +164,6 @@ void qemu_free(void *ptr);
char *qemu_strdup(const char *str);
char *qemu_strndup(const char *str, size_t size);
-void *get_mmap_addr(unsigned long size);
-
-
void qemu_mutex_lock_iothread(void);
void qemu_mutex_unlock_iothread(void);
diff --git a/qemu-malloc.c b/qemu-malloc.c
index 1b33e04..36b0b36 100644
--- a/qemu-malloc.c
+++ b/qemu-malloc.c
@@ -32,11 +32,6 @@ static void *oom_check(void *ptr)
return ptr;
}
-void *get_mmap_addr(unsigned long size)
-{
- return NULL;
-}
-
void qemu_free(void *ptr)
{
free(ptr);
--
1.6.6.1
next prev parent reply other threads:[~2010-06-15 14:20 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-15 14:19 [Qemu-devel] [PULL 00/19] Block patches Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 01/19] vpc: Read/write multiple sectors at once Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 02/19] qcow2: Allow get_refcount to return errors Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 03/19] qcow2: Allow alloc_clusters_noref " Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 04/19] qcow2: Return real error code in load_refcount_block Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 05/19] savevm: Really verify if a drive supports snapshots Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 06/19] Fix regression for "-drive file=" Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 07/19] qcow2: Restore L1 entry on l2_allocate failure Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 08/19] cow: use pread/pwrite Kevin Wolf
2010-06-15 14:19 ` Kevin Wolf [this message]
2010-06-15 14:19 ` [Qemu-devel] [PATCH 10/19] cow: use qemu block API Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 11/19] block: Move error actions from DriveInfo to BlockDriverState Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 12/19] block: Decouple block device "commit all" from DriveInfo Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 13/19] monitor: Make "commit FOO" complain when FOO doesn't exist Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 14/19] block: New bdrv_next() Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 15/19] block: Decouple savevm from DriveInfo Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 16/19] blockdev: Give drives internal linkage Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 17/19] Correct definitions for FD_CMD_SAVE and FD_CMD_RESTORE Kevin Wolf
2010-06-15 14:28 ` [Qemu-devel] " Anthony Liguori
2010-06-15 14:42 ` Kevin Wolf
2010-06-15 14:47 ` Jes Sorensen
2010-06-15 14:52 ` Kevin Wolf
2010-06-15 14:54 ` Jes Sorensen
2010-06-15 14:19 ` [Qemu-devel] [PATCH 18/19] block: fix a warning and possible truncation Kevin Wolf
2010-06-15 14:19 ` [Qemu-devel] [PATCH 19/19] xen: Fix build error due to missing include Kevin Wolf
2010-06-15 14:26 ` [Qemu-devel] [PULL 00/19] Block patches Anthony Liguori
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=1276611581-3757-10-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 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).