Skip to content

Commit

Permalink
Merge remote branch 'kwolf/for-anthony' into staging
Browse files Browse the repository at this point in the history
  • Loading branch information
Anthony Liguori committed Jun 3, 2010
2 parents 41ef56e + 1a39685 commit 358c360
Show file tree
Hide file tree
Showing 12 changed files with 414 additions and 118 deletions.
13 changes: 7 additions & 6 deletions block.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
static BlockDriver *find_protocol(const char *filename);

static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
QTAILQ_HEAD_INITIALIZER(bdrv_states);
Expand Down Expand Up @@ -210,7 +209,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
{
BlockDriver *drv;

drv = find_protocol(filename);
drv = bdrv_find_protocol(filename);
if (drv == NULL) {
drv = bdrv_find_format("file");
}
Expand Down Expand Up @@ -283,7 +282,7 @@ static BlockDriver *find_hdev_driver(const char *filename)
return drv;
}

static BlockDriver *find_protocol(const char *filename)
BlockDriver *bdrv_find_protocol(const char *filename)
{
BlockDriver *drv1;
char protocol[128];
Expand Down Expand Up @@ -333,8 +332,10 @@ static BlockDriver *find_image_format(const char *filename)
return NULL;

/* Return the raw BlockDriver * to scsi-generic devices */
if (bs->sg)
if (bs->sg) {
bdrv_delete(bs);
return bdrv_find_format("raw");
}

ret = bdrv_pread(bs, 0, buf, sizeof(buf));
bdrv_delete(bs);
Expand Down Expand Up @@ -478,7 +479,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
BlockDriver *drv;
int ret;

drv = find_protocol(filename);
drv = bdrv_find_protocol(filename);
if (!drv) {
return -ENOENT;
}
Expand Down Expand Up @@ -1950,7 +1951,7 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs,
// Add the second request
qemu_iovec_concat(qiov, reqs[i].qiov, reqs[i].qiov->size);

reqs[outidx].nb_sectors += reqs[i].nb_sectors;
reqs[outidx].nb_sectors = qiov->size >> 9;
reqs[outidx].qiov = qiov;

mcb->callbacks[i].free_qiov = reqs[outidx].qiov;
Expand Down
3 changes: 2 additions & 1 deletion block.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ typedef struct QEMUSnapshotInfo {
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_CACHE_WB)

#define BDRV_SECTOR_BITS 9
#define BDRV_SECTOR_SIZE (1 << BDRV_SECTOR_BITS)
#define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS)
#define BDRV_SECTOR_MASK ~(BDRV_SECTOR_SIZE - 1)

typedef enum {
Expand All @@ -54,6 +54,7 @@ void bdrv_info_stats(Monitor *mon, QObject **ret_data);

void bdrv_init(void);
void bdrv_init_with_whitelist(void);
BlockDriver *bdrv_find_protocol(const char *filename);
BlockDriver *bdrv_find_format(const char *format_name);
BlockDriver *bdrv_find_whitelisted_format(const char *format_name);
int bdrv_create(BlockDriver *drv, const char* filename,
Expand Down
94 changes: 56 additions & 38 deletions block/qcow2-cluster.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,31 +157,36 @@ static uint64_t *seek_l2_table(BDRVQcowState *s, uint64_t l2_offset)
* the image file failed.
*/

static uint64_t *l2_load(BlockDriverState *bs, uint64_t l2_offset)
static int l2_load(BlockDriverState *bs, uint64_t l2_offset,
uint64_t **l2_table)
{
BDRVQcowState *s = bs->opaque;
int min_index;
uint64_t *l2_table;
int ret;

/* seek if the table for the given offset is in the cache */

l2_table = seek_l2_table(s, l2_offset);
if (l2_table != NULL)
return l2_table;
*l2_table = seek_l2_table(s, l2_offset);
if (*l2_table != NULL) {
return 0;
}

/* not found: load a new entry in the least used one */

min_index = l2_cache_new_entry(bs);
l2_table = s->l2_cache + (min_index << s->l2_bits);
*l2_table = s->l2_cache + (min_index << s->l2_bits);

BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
if (bdrv_pread(bs->file, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
s->l2_size * sizeof(uint64_t))
return NULL;
ret = bdrv_pread(bs->file, l2_offset, *l2_table,
s->l2_size * sizeof(uint64_t));
if (ret < 0) {
return ret;
}

s->l2_cache_offsets[min_index] = l2_offset;
s->l2_cache_counts[min_index] = 1;

return l2_table;
return 0;
}

/*
Expand Down Expand Up @@ -239,14 +244,6 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
return l2_offset;
}

/* update the L1 entry */

s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
ret = write_l1_entry(bs, l1_index);
if (ret < 0) {
return ret;
}

/* allocate a new entry in the l2 cache */

min_index = l2_cache_new_entry(bs);
Expand All @@ -261,15 +258,22 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
ret = bdrv_pread(bs->file, old_l2_offset, l2_table,
s->l2_size * sizeof(uint64_t));
if (ret < 0) {
return ret;
goto fail;
}
}
/* write the l2 table to the file */
BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_WRITE);
ret = bdrv_pwrite(bs->file, l2_offset, l2_table,
s->l2_size * sizeof(uint64_t));
if (ret < 0) {
return ret;
goto fail;
}

/* update the L1 entry */
s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
ret = write_l1_entry(bs, l1_index);
if (ret < 0) {
goto fail;
}

/* update the l2 cache entry */
Expand All @@ -279,6 +283,10 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)

*table = l2_table;
return 0;

fail:
qcow2_l2_cache_reset(bs);
return ret;
}

static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
Expand Down Expand Up @@ -342,7 +350,13 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,

while (nb_sectors > 0) {
n = nb_sectors;
cluster_offset = qcow2_get_cluster_offset(bs, sector_num << 9, &n);

ret = qcow2_get_cluster_offset(bs, sector_num << 9, &n,
&cluster_offset);
if (ret < 0) {
return ret;
}

index_in_cluster = sector_num & (s->cluster_sectors - 1);
if (!cluster_offset) {
if (bs->backing_hd) {
Expand Down Expand Up @@ -409,28 +423,29 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
/*
* get_cluster_offset
*
* For a given offset of the disk image, return cluster offset in
* qcow2 file.
* For a given offset of the disk image, find the cluster offset in
* qcow2 file. The offset is stored in *cluster_offset.
*
* on entry, *num is the number of contiguous clusters we'd like to
* access following offset.
*
* on exit, *num is the number of contiguous clusters we can read.
*
* Return 1, if the offset is found
* Return 0, otherwise.
* Return 0, if the offset is found
* Return -errno, otherwise.
*
*/

uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
int *num)
int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
int *num, uint64_t *cluster_offset)
{
BDRVQcowState *s = bs->opaque;
unsigned int l1_index, l2_index;
uint64_t l2_offset, *l2_table, cluster_offset;
uint64_t l2_offset, *l2_table;
int l1_bits, c;
unsigned int index_in_cluster, nb_clusters;
uint64_t nb_available, nb_needed;
int ret;

index_in_cluster = (offset >> 9) & (s->cluster_sectors - 1);
nb_needed = *num + index_in_cluster;
Expand All @@ -451,7 +466,7 @@ uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
nb_needed = nb_available;
}

cluster_offset = 0;
*cluster_offset = 0;

/* seek the the l2 offset in the l1 table */

Expand All @@ -469,17 +484,18 @@ uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
/* load the l2 table in memory */

l2_offset &= ~QCOW_OFLAG_COPIED;
l2_table = l2_load(bs, l2_offset);
if (l2_table == NULL)
return 0;
ret = l2_load(bs, l2_offset, &l2_table);
if (ret < 0) {
return ret;
}

/* find the cluster offset for the given disk offset */

l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
cluster_offset = be64_to_cpu(l2_table[l2_index]);
*cluster_offset = be64_to_cpu(l2_table[l2_index]);
nb_clusters = size_to_clusters(s, nb_needed << 9);

if (!cluster_offset) {
if (!*cluster_offset) {
/* how many empty clusters ? */
c = count_contiguous_free_clusters(nb_clusters, &l2_table[l2_index]);
} else {
Expand All @@ -495,7 +511,8 @@ uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,

*num = nb_available - index_in_cluster;

return cluster_offset & ~QCOW_OFLAG_COPIED;
*cluster_offset &=~QCOW_OFLAG_COPIED;
return 0;
}

/*
Expand Down Expand Up @@ -536,9 +553,9 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
if (l2_offset & QCOW_OFLAG_COPIED) {
/* load the l2 table in memory */
l2_offset &= ~QCOW_OFLAG_COPIED;
l2_table = l2_load(bs, l2_offset);
if (l2_table == NULL) {
return -EIO;
ret = l2_load(bs, l2_offset, &l2_table);
if (ret < 0) {
return ret;
}
} else {
if (l2_offset)
Expand Down Expand Up @@ -696,6 +713,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)

ret = write_l2_entries(bs, l2_table, l2_offset, l2_index, m->nb_clusters);
if (ret < 0) {
qcow2_l2_cache_reset(bs);
goto err;
}

Expand Down
42 changes: 28 additions & 14 deletions block/qcow2-refcount.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,6 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)

/* Allocate the refcount block itself and mark it as used */
uint64_t new_block = alloc_clusters_noref(bs, s->cluster_size);
memset(s->refcount_block_cache, 0, s->cluster_size);
s->refcount_block_cache_offset = new_block;

#ifdef DEBUG_ALLOC2
fprintf(stderr, "qcow2: Allocate refcount block %d for %" PRIx64
Expand All @@ -231,6 +229,10 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
#endif

if (in_same_refcount_block(s, new_block, cluster_index << s->cluster_bits)) {
/* Zero the new refcount block before updating it */
memset(s->refcount_block_cache, 0, s->cluster_size);
s->refcount_block_cache_offset = new_block;

/* The block describes itself, need to update the cache */
int block_index = (new_block >> s->cluster_bits) &
((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
Expand All @@ -242,6 +244,11 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
if (ret < 0) {
goto fail_block;
}

/* Initialize the new refcount block only after updating its refcount,
* update_refcount uses the refcount cache itself */
memset(s->refcount_block_cache, 0, s->cluster_size);
s->refcount_block_cache_offset = new_block;
}

/* Now the new refcount block needs to be written to disk */
Expand Down Expand Up @@ -404,22 +411,28 @@ static int write_refcount_block_entries(BlockDriverState *bs,
{
BDRVQcowState *s = bs->opaque;
size_t size;
int ret;

if (cache_refcount_updates) {
return 0;
}

if (first_index < 0) {
return 0;
}

first_index &= ~(REFCOUNTS_PER_SECTOR - 1);
last_index = (last_index + REFCOUNTS_PER_SECTOR)
& ~(REFCOUNTS_PER_SECTOR - 1);

size = (last_index - first_index) << REFCOUNT_SHIFT;

BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART);
if (bdrv_pwrite(bs->file,
ret = bdrv_pwrite(bs->file,
refcount_block_offset + (first_index << REFCOUNT_SHIFT),
&s->refcount_block_cache[first_index], size) != size)
{
return -EIO;
&s->refcount_block_cache[first_index], size);
if (ret < 0) {
return ret;
}

return 0;
Expand Down Expand Up @@ -460,10 +473,10 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
if ((old_table_index >= 0) && (table_index != old_table_index)) {

if (write_refcount_block_entries(bs, refcount_block_offset,
first_index, last_index) < 0)
{
return -EIO;
ret = write_refcount_block_entries(bs, refcount_block_offset,
first_index, last_index);
if (ret < 0) {
return ret;
}

first_index = -1;
Expand Down Expand Up @@ -505,10 +518,11 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,

/* Write last changed block to disk */
if (refcount_block_offset != 0) {
if (write_refcount_block_entries(bs, refcount_block_offset,
first_index, last_index) < 0)
{
return ret < 0 ? ret : -EIO;
int wret;
wret = write_refcount_block_entries(bs, refcount_block_offset,
first_index, last_index);
if (wret < 0) {
return ret < 0 ? ret : wret;
}
}

Expand Down
Loading

0 comments on commit 358c360

Please sign in to comment.