qcow2: Use bytes instead of sectors for QCowL2Meta

In preparation for implementing .bdrv_co_pwritev in qcow2.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
master
Kevin Wolf 2016-06-01 14:08:56 +02:00
parent aaa4d20b49
commit 8556739355
2 changed files with 15 additions and 30 deletions

View File

@ -739,13 +739,12 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m, Qcow2COWRegion *r)
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int ret; int ret;
if (r->nb_sectors == 0) { if (r->nb_bytes == 0) {
return 0; return 0;
} }
qemu_co_mutex_unlock(&s->lock); qemu_co_mutex_unlock(&s->lock);
ret = do_perform_cow(bs, m->offset, m->alloc_offset, ret = do_perform_cow(bs, m->offset, m->alloc_offset, r->offset, r->nb_bytes);
r->offset, r->nb_sectors * BDRV_SECTOR_SIZE);
qemu_co_mutex_lock(&s->lock); qemu_co_mutex_lock(&s->lock);
if (ret < 0) { if (ret < 0) {
@ -1196,25 +1195,20 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
/* /*
* Save info needed for meta data update. * Save info needed for meta data update.
* *
* requested_sectors: Number of sectors from the start of the first * requested_bytes: Number of bytes from the start of the first
* newly allocated cluster to the end of the (possibly shortened * newly allocated cluster to the end of the (possibly shortened
* before) write request. * before) write request.
* *
* avail_sectors: Number of sectors from the start of the first * avail_bytes: Number of bytes from the start of the first
* newly allocated to the end of the last newly allocated cluster. * newly allocated to the end of the last newly allocated cluster.
* *
* nb_sectors: The number of sectors from the start of the first * nb_bytes: The number of bytes from the start of the first
* newly allocated cluster to the end of the area that the write * newly allocated cluster to the end of the area that the write
* request actually writes to (excluding COW at the end) * request actually writes to (excluding COW at the end)
*/ */
int requested_sectors = uint64_t requested_bytes = *bytes + offset_into_cluster(s, guest_offset);
(*bytes + offset_into_cluster(s, guest_offset)) int avail_bytes = MIN(INT_MAX, nb_clusters << s->cluster_bits);
>> BDRV_SECTOR_BITS; int nb_bytes = MIN(requested_bytes, avail_bytes);
int avail_sectors = nb_clusters
<< (s->cluster_bits - BDRV_SECTOR_BITS);
int alloc_n_start = offset_into_cluster(s, guest_offset)
>> BDRV_SECTOR_BITS;
int nb_sectors = MIN(requested_sectors, avail_sectors);
QCowL2Meta *old_m = *m; QCowL2Meta *old_m = *m;
*m = g_malloc0(sizeof(**m)); *m = g_malloc0(sizeof(**m));
@ -1225,23 +1219,21 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
.alloc_offset = alloc_cluster_offset, .alloc_offset = alloc_cluster_offset,
.offset = start_of_cluster(s, guest_offset), .offset = start_of_cluster(s, guest_offset),
.nb_clusters = nb_clusters, .nb_clusters = nb_clusters,
.nb_available = nb_sectors,
.cow_start = { .cow_start = {
.offset = 0, .offset = 0,
.nb_sectors = alloc_n_start, .nb_bytes = offset_into_cluster(s, guest_offset),
}, },
.cow_end = { .cow_end = {
.offset = nb_sectors * BDRV_SECTOR_SIZE, .offset = nb_bytes,
.nb_sectors = avail_sectors - nb_sectors, .nb_bytes = avail_bytes - nb_bytes,
}, },
}; };
qemu_co_queue_init(&(*m)->dependent_requests); qemu_co_queue_init(&(*m)->dependent_requests);
QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight); QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
*host_offset = alloc_cluster_offset + offset_into_cluster(s, guest_offset); *host_offset = alloc_cluster_offset + offset_into_cluster(s, guest_offset);
*bytes = MIN(*bytes, (nb_sectors * BDRV_SECTOR_SIZE) *bytes = MIN(*bytes, nb_bytes - offset_into_cluster(s, guest_offset));
- offset_into_cluster(s, guest_offset));
assert(*bytes != 0); assert(*bytes != 0);
return 1; return 1;

View File

@ -302,8 +302,8 @@ typedef struct Qcow2COWRegion {
*/ */
uint64_t offset; uint64_t offset;
/** Number of sectors to copy */ /** Number of bytes to copy */
int nb_sectors; int nb_bytes;
} Qcow2COWRegion; } Qcow2COWRegion;
/** /**
@ -318,12 +318,6 @@ typedef struct QCowL2Meta
/** Host offset of the first newly allocated cluster */ /** Host offset of the first newly allocated cluster */
uint64_t alloc_offset; uint64_t alloc_offset;
/**
* Number of sectors from the start of the first allocated cluster to
* the end of the (possibly shortened) request
*/
int nb_available;
/** Number of newly allocated clusters */ /** Number of newly allocated clusters */
int nb_clusters; int nb_clusters;
@ -471,8 +465,7 @@ static inline uint64_t l2meta_cow_start(QCowL2Meta *m)
static inline uint64_t l2meta_cow_end(QCowL2Meta *m) static inline uint64_t l2meta_cow_end(QCowL2Meta *m)
{ {
return m->offset + m->cow_end.offset return m->offset + m->cow_end.offset + m->cow_end.nb_bytes;
+ (m->cow_end.nb_sectors << BDRV_SECTOR_BITS);
} }
static inline uint64_t refcount_diff(uint64_t r1, uint64_t r2) static inline uint64_t refcount_diff(uint64_t r1, uint64_t r2)