* [Qemu-devel] [PATCH 0/5 v2] qcow2 info: show highest-allocation and num-free-bytes
@ 2009-01-22 10:43 Uri Lublin
2009-01-22 10:43 ` [Qemu-devel] [PATCH 1/5 v2] block-qcow2: keep highest allocated byte Uri Lublin
2009-01-22 18:58 ` [Qemu-devel] [PATCH 0/5 v2] qcow2 info: show highest-allocation and num-free-bytes Anthony Liguori
0 siblings, 2 replies; 7+ messages in thread
From: Uri Lublin @ 2009-01-22 10:43 UTC (permalink / raw)
To: qemu-devel; +Cc: Uri Lublin
Hello,
The following 5 enhance "info blockstats" for qcow2 images (and
other formats that implement bdrv_get_info), to show
higest-allocated-offset and number-of-free-bytes (below
the higest-allocated-offset) of the image.
One of the main usage for this information is to know and act
upon a case of end-of-storage-space. Instead of waiting for
-ENOSPACE (which now may cause the VM to stop), one can
define a threshold and extend the diskspace allocated for
the image.
This info is also good for management systems, so they
can report the user disk space status.
Also with highest_alloc and num_free_bytes, we can have a pretty
good idea about how fragmented a qcow2 images is, and try to
defragment it later.
Patches 1,2,3, Provides information about the highest allocated byte (offset)
Patch 4, Provides information about the number of free bytes
below highest_alloc.
Patch 5, Provides info about highest_alloc and num_free_bytes through
qemu-img info
Changes from v1: better description of use cases.
Regards,
Uri.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 1/5 v2] block-qcow2: keep highest allocated byte
2009-01-22 10:43 [Qemu-devel] [PATCH 0/5 v2] qcow2 info: show highest-allocation and num-free-bytes Uri Lublin
@ 2009-01-22 10:43 ` Uri Lublin
2009-01-22 10:43 ` [Qemu-devel] [PATCH 2/5 v2] block-qcow2: export highest_allocated through BlockDriverInfo and get_info() Uri Lublin
2009-01-22 18:58 ` [Qemu-devel] [PATCH 0/5 v2] qcow2 info: show highest-allocation and num-free-bytes Anthony Liguori
1 sibling, 1 reply; 7+ messages in thread
From: Uri Lublin @ 2009-01-22 10:43 UTC (permalink / raw)
To: qemu-devel; +Cc: Uri Lublin
We want to know the highest written offset for qcow2 images.
This gives a pretty good (and easy to calculate) estimation to how
much more allocation can be done for the block device.
It can be usefull for allocating more diskspace for that image
(if possible, e.g. lvm) before we run out-of-disk-space
Signed-off-by: Uri Lublin <uril@redhat.com>
---
block-qcow2.c | 34 ++++++++++++++++++++++++++++++++++
1 files changed, 34 insertions(+), 0 deletions(-)
diff --git a/block-qcow2.c b/block-qcow2.c
index d4556ef..e016e8f 100644
--- a/block-qcow2.c
+++ b/block-qcow2.c
@@ -143,6 +143,9 @@ typedef struct BDRVQcowState {
uint32_t crypt_method_header;
AES_KEY aes_encrypt_key;
AES_KEY aes_decrypt_key;
+
+ int64_t highest_alloc; /* highest cluester allocated (in clusters) */
+
uint64_t snapshots_offset;
int snapshots_size;
int nb_snapshots;
@@ -170,6 +173,8 @@ static void free_clusters(BlockDriverState *bs,
#ifdef DEBUG_ALLOC
static void check_refcounts(BlockDriverState *bs);
#endif
+static void scan_refcount(BlockDriverState *bs, int64_t *high);
+
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
{
@@ -278,6 +283,8 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
if (refcount_init(bs) < 0)
goto fail;
+ scan_refcount(bs, &s->highest_alloc);
+
/* read the backing file name */
if (header.backing_file_offset != 0) {
len = header.backing_file_size;
@@ -2206,6 +2213,29 @@ static int load_refcount_block(BlockDriverState *bs,
return 0;
}
+static void scan_refcount(BlockDriverState *bs, int64_t *high)
+{
+ BDRVQcowState *s = bs->opaque;
+ int64_t refcnt_index, cluster_index, cluster_end, h = 0;
+
+ for (refcnt_index=0; refcnt_index < s->refcount_table_size; refcnt_index++){
+ if (s->refcount_table[refcnt_index] == 0) {
+ continue;
+ }
+ cluster_index = refcnt_index << (s->cluster_bits - REFCOUNT_SHIFT);
+ cluster_end = (refcnt_index + 1) << (s->cluster_bits - REFCOUNT_SHIFT);
+ for ( ; cluster_index < cluster_end; cluster_index++) {
+ if (get_refcount(bs, cluster_index) == 0)
+ /* do nothing -- reserved for free counting */;
+ else
+ h = cluster_index;
+ }
+ }
+
+ if (high)
+ *high = (h+1);
+}
+
static int get_refcount(BlockDriverState *bs, int64_t cluster_index)
{
BDRVQcowState *s = bs->opaque;
@@ -2246,6 +2276,10 @@ retry:
size,
(s->free_cluster_index - nb_clusters) << s->cluster_bits);
#endif
+
+ if (s->highest_alloc < s->free_cluster_index)
+ s->highest_alloc = s->free_cluster_index;
+
return (s->free_cluster_index - nb_clusters) << s->cluster_bits;
}
--
1.6.0.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 2/5 v2] block-qcow2: export highest_allocated through BlockDriverInfo and get_info()
2009-01-22 10:43 ` [Qemu-devel] [PATCH 1/5 v2] block-qcow2: keep highest allocated byte Uri Lublin
@ 2009-01-22 10:43 ` Uri Lublin
2009-01-22 10:43 ` [Qemu-devel] [PATCH 3/5 v2] info blockstats: show highest_allocated if exists Uri Lublin
0 siblings, 1 reply; 7+ messages in thread
From: Uri Lublin @ 2009-01-22 10:43 UTC (permalink / raw)
To: qemu-devel; +Cc: Uri Lublin
Signed-off-by: Uri Lublin <uril@redhat.com>
---
block-qcow2.c | 1 +
block.h | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/block-qcow2.c b/block-qcow2.c
index e016e8f..7c00ee8 100644
--- a/block-qcow2.c
+++ b/block-qcow2.c
@@ -1671,6 +1671,7 @@ static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
bdi->cluster_size = s->cluster_size;
bdi->vm_state_offset = (int64_t)s->l1_vm_state_index <<
(s->cluster_bits + s->l2_bits);
+ bdi->highest_alloc = s->highest_alloc << s->cluster_bits;
return 0;
}
diff --git a/block.h b/block.h
index c3314a1..9c64af3 100644
--- a/block.h
+++ b/block.h
@@ -25,6 +25,7 @@ typedef struct BlockDriverInfo {
int cluster_size;
/* offset at which the VM state can be saved (0 if not possible) */
int64_t vm_state_offset;
+ int64_t highest_alloc; /* highest allocated block offset (in bytes) */
} BlockDriverInfo;
typedef struct QEMUSnapshotInfo {
--
1.6.0.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 3/5 v2] info blockstats: show highest_allocated if exists
2009-01-22 10:43 ` [Qemu-devel] [PATCH 2/5 v2] block-qcow2: export highest_allocated through BlockDriverInfo and get_info() Uri Lublin
@ 2009-01-22 10:43 ` Uri Lublin
2009-01-22 10:43 ` [Qemu-devel] [PATCH 4/5 v2] qcow2 format: keep 'num_free_bytes', and show it upon 'info blockstats' Uri Lublin
0 siblings, 1 reply; 7+ messages in thread
From: Uri Lublin @ 2009-01-22 10:43 UTC (permalink / raw)
To: qemu-devel; +Cc: Uri Lublin
Signed-off-by: Uri Lublin <uril@redhat.com>
---
block.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/block.c b/block.c
index 3250327..0058531 100644
--- a/block.c
+++ b/block.c
@@ -1077,6 +1077,7 @@ void bdrv_info(void)
void bdrv_info_stats (void)
{
BlockDriverState *bs;
+ BlockDriverInfo bdi;
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
term_printf ("%s:"
@@ -1084,10 +1085,14 @@ void bdrv_info_stats (void)
" wr_bytes=%" PRIu64
" rd_operations=%" PRIu64
" wr_operations=%" PRIu64
- "\n",
+ ,
bs->device_name,
bs->rd_bytes, bs->wr_bytes,
bs->rd_ops, bs->wr_ops);
+ if (bdrv_get_info(bs, &bdi) == 0)
+ term_printf(" high=%" PRIu64,
+ bdi.highest_alloc);
+ term_printf("\n");
}
}
--
1.6.0.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 4/5 v2] qcow2 format: keep 'num_free_bytes', and show it upon 'info blockstats'
2009-01-22 10:43 ` [Qemu-devel] [PATCH 3/5 v2] info blockstats: show highest_allocated if exists Uri Lublin
@ 2009-01-22 10:43 ` Uri Lublin
2009-01-22 10:43 ` [Qemu-devel] [PATCH 5/5 v2] qemu-img: info: show highest_alloc and num_free_bytes if exist Uri Lublin
0 siblings, 1 reply; 7+ messages in thread
From: Uri Lublin @ 2009-01-22 10:43 UTC (permalink / raw)
To: qemu-devel; +Cc: Uri Lublin
'num_free_bytes' is the number of non-allocated bytes below highest-allocation.
It's useful, together with the highest-allocation, to figure out how
fragmented the image is, and how likely it will run out-of-space soon.
For example when the highest allocation is high (almost end-of-disk), but
many bytes (clusters) are free, and can be re-allocated when neeeded, than
we know it's probably not going to reach end-of-disk-space soon.
Added bookkeeping to block-qcow2.c
Export it using BlockDeviceInfo
Show it upon 'info blockstats' if BlockDeviceInfo exists
Signed-off-by: Uri Lublin <uril@redhat.com>
---
block-qcow2.c | 36 ++++++++++++++++++++++++++++--------
block.c | 5 +++--
block.h | 1 +
3 files changed, 32 insertions(+), 10 deletions(-)
diff --git a/block-qcow2.c b/block-qcow2.c
index 7c00ee8..8a5b621 100644
--- a/block-qcow2.c
+++ b/block-qcow2.c
@@ -145,6 +145,7 @@ typedef struct BDRVQcowState {
AES_KEY aes_decrypt_key;
int64_t highest_alloc; /* highest cluester allocated (in clusters) */
+ int64_t nc_free; /* num of free clusters below highest_alloc */
uint64_t snapshots_offset;
int snapshots_size;
@@ -173,7 +174,7 @@ static void free_clusters(BlockDriverState *bs,
#ifdef DEBUG_ALLOC
static void check_refcounts(BlockDriverState *bs);
#endif
-static void scan_refcount(BlockDriverState *bs, int64_t *high);
+static void scan_refcount(BlockDriverState *bs, int64_t *high, int64_t *free);
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
@@ -283,7 +284,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
if (refcount_init(bs) < 0)
goto fail;
- scan_refcount(bs, &s->highest_alloc);
+ scan_refcount(bs, &s->highest_alloc, &s->nc_free);
/* read the backing file name */
if (header.backing_file_offset != 0) {
@@ -1672,6 +1673,7 @@ static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
bdi->vm_state_offset = (int64_t)s->l1_vm_state_index <<
(s->cluster_bits + s->l2_bits);
bdi->highest_alloc = s->highest_alloc << s->cluster_bits;
+ bdi->num_free_bytes = s->nc_free << s->cluster_bits;
return 0;
}
@@ -2214,25 +2216,35 @@ static int load_refcount_block(BlockDriverState *bs,
return 0;
}
-static void scan_refcount(BlockDriverState *bs, int64_t *high)
+static void scan_refcount(BlockDriverState *bs, int64_t *high, int64_t *free)
{
BDRVQcowState *s = bs->opaque;
- int64_t refcnt_index, cluster_index, cluster_end, h = 0;
+ int64_t refcnt_index, cluster_index, cluster_end, h = 0, f = 0;
+ int64_t tail = 0; /* do not count last consecutive free entries */
for (refcnt_index=0; refcnt_index < s->refcount_table_size; refcnt_index++){
if (s->refcount_table[refcnt_index] == 0) {
+ f += 1 << (s->cluster_bits - REFCOUNT_SHIFT);
+ tail += 1 << (s->cluster_bits - REFCOUNT_SHIFT);
continue;
}
cluster_index = refcnt_index << (s->cluster_bits - REFCOUNT_SHIFT);
cluster_end = (refcnt_index + 1) << (s->cluster_bits - REFCOUNT_SHIFT);
for ( ; cluster_index < cluster_end; cluster_index++) {
- if (get_refcount(bs, cluster_index) == 0)
- /* do nothing -- reserved for free counting */;
- else
+ if (get_refcount(bs, cluster_index) == 0) {
+ f++;
+ tail++;
+ }
+ else {
h = cluster_index;
+ tail = 0;
+ }
}
}
+ f -= tail;
+ if (free)
+ *free = f;
if (high)
*high = (h+1);
}
@@ -2278,8 +2290,10 @@ retry:
(s->free_cluster_index - nb_clusters) << s->cluster_bits);
#endif
- if (s->highest_alloc < s->free_cluster_index)
+ if (s->highest_alloc < s->free_cluster_index) {
+ s->nc_free += (s->free_cluster_index - s->highest_alloc);
s->highest_alloc = s->free_cluster_index;
+ }
return (s->free_cluster_index - nb_clusters) << s->cluster_bits;
}
@@ -2456,6 +2470,12 @@ static int update_cluster_refcount(BlockDriverState *bs,
block_index = cluster_index &
((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
refcount = be16_to_cpu(s->refcount_block_cache[block_index]);
+
+ if (refcount == 1 && addend == -1)
+ s->nc_free += 1;
+ else if (refcount == 0 && addend == 1)
+ s->nc_free -= 1;
+
refcount += addend;
if (refcount < 0 || refcount > 0xffff)
return -EINVAL;
diff --git a/block.c b/block.c
index 0058531..589c67a 100644
--- a/block.c
+++ b/block.c
@@ -1090,8 +1090,9 @@ void bdrv_info_stats (void)
bs->rd_bytes, bs->wr_bytes,
bs->rd_ops, bs->wr_ops);
if (bdrv_get_info(bs, &bdi) == 0)
- term_printf(" high=%" PRIu64,
- bdi.highest_alloc);
+ term_printf(" high=%" PRId64
+ " bytes_free=%" PRId64,
+ bdi.highest_alloc, bdi.num_free_bytes);
term_printf("\n");
}
}
diff --git a/block.h b/block.h
index 9c64af3..dca17db 100644
--- a/block.h
+++ b/block.h
@@ -26,6 +26,7 @@ typedef struct BlockDriverInfo {
/* offset at which the VM state can be saved (0 if not possible) */
int64_t vm_state_offset;
int64_t highest_alloc; /* highest allocated block offset (in bytes) */
+ int64_t num_free_bytes; /* below highest_alloc */
} BlockDriverInfo;
typedef struct QEMUSnapshotInfo {
--
1.6.0.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 5/5 v2] qemu-img: info: show highest_alloc and num_free_bytes if exist
2009-01-22 10:43 ` [Qemu-devel] [PATCH 4/5 v2] qcow2 format: keep 'num_free_bytes', and show it upon 'info blockstats' Uri Lublin
@ 2009-01-22 10:43 ` Uri Lublin
0 siblings, 0 replies; 7+ messages in thread
From: Uri Lublin @ 2009-01-22 10:43 UTC (permalink / raw)
To: qemu-devel; +Cc: Uri Lublin
Signed-off-by: Uri Lublin <uril@redhat.com>
---
qemu-img.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 555ab5f..41ff13b 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -727,6 +727,10 @@ static int img_info(int argc, char **argv)
if (bdrv_get_info(bs, &bdi) >= 0) {
if (bdi.cluster_size != 0)
printf("cluster_size: %d\n", bdi.cluster_size);
+ if (bdi.highest_alloc)
+ printf("highest_alloc: %ld\n", bdi.highest_alloc);
+ if (bdi.num_free_bytes)
+ printf("num_free_bytes: %ld\n", bdi.num_free_bytes);
}
bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
if (backing_filename[0] != '\0') {
--
1.6.0.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH 0/5 v2] qcow2 info: show highest-allocation and num-free-bytes
2009-01-22 10:43 [Qemu-devel] [PATCH 0/5 v2] qcow2 info: show highest-allocation and num-free-bytes Uri Lublin
2009-01-22 10:43 ` [Qemu-devel] [PATCH 1/5 v2] block-qcow2: keep highest allocated byte Uri Lublin
@ 2009-01-22 18:58 ` Anthony Liguori
1 sibling, 0 replies; 7+ messages in thread
From: Anthony Liguori @ 2009-01-22 18:58 UTC (permalink / raw)
To: qemu-devel; +Cc: Uri Lublin
Uri Lublin wrote:
> Hello,
>
> The following 5 enhance "info blockstats" for qcow2 images (and
> other formats that implement bdrv_get_info), to show
> higest-allocated-offset and number-of-free-bytes (below
> the higest-allocated-offset) of the image.
>
> One of the main usage for this information is to know and act
> upon a case of end-of-storage-space. Instead of waiting for
> -ENOSPACE (which now may cause the VM to stop), one can
> define a threshold and extend the diskspace allocated for
> the image.
> This info is also good for management systems, so they
> can report the user disk space status.
>
> Also with highest_alloc and num_free_bytes, we can have a pretty
> good idea about how fragmented a qcow2 images is, and try to
> defragment it later.
>
> Patches 1,2,3, Provides information about the highest allocated byte (offset)
> Patch 4, Provides information about the number of free bytes
> below highest_alloc.
> Patch 5, Provides info about highest_alloc and num_free_bytes through
> qemu-img info
>
>
> Changes from v1: better description of use cases.
>
Applied all. Thanks.
Regards,
Anthony Liguori
> Regards,
> Uri.
>
>
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-01-22 18:58 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-22 10:43 [Qemu-devel] [PATCH 0/5 v2] qcow2 info: show highest-allocation and num-free-bytes Uri Lublin
2009-01-22 10:43 ` [Qemu-devel] [PATCH 1/5 v2] block-qcow2: keep highest allocated byte Uri Lublin
2009-01-22 10:43 ` [Qemu-devel] [PATCH 2/5 v2] block-qcow2: export highest_allocated through BlockDriverInfo and get_info() Uri Lublin
2009-01-22 10:43 ` [Qemu-devel] [PATCH 3/5 v2] info blockstats: show highest_allocated if exists Uri Lublin
2009-01-22 10:43 ` [Qemu-devel] [PATCH 4/5 v2] qcow2 format: keep 'num_free_bytes', and show it upon 'info blockstats' Uri Lublin
2009-01-22 10:43 ` [Qemu-devel] [PATCH 5/5 v2] qemu-img: info: show highest_alloc and num_free_bytes if exist Uri Lublin
2009-01-22 18:58 ` [Qemu-devel] [PATCH 0/5 v2] qcow2 info: show highest-allocation and num-free-bytes Anthony Liguori
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).