All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/4] qcow2: Save another common flush
@ 2010-09-17 16:18 Kevin Wolf
  2010-09-17 16:18 ` [Qemu-devel] [PATCH 1/4] qcow2: Move sync out of write_refcount_block_entries Kevin Wolf
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Kevin Wolf @ 2010-09-17 16:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

For copy on write (this includes any cluster allocations that don't fill the
whole cluster with one request), what qcow2 does looks like this:

1. Allocate new clusters (increase refcounts)
2. bdrv_flush
3. Copy sectors before the first touched one
4. bdrv_flush
5. Copy sectors after the last touched one
6. bdrv_flush
7. Update the L2 table to point to the new clusters

Step 2 and 4 are not necessary. This series moves flushes around to get all
of these three bdrv_flush calls merged into one.

Kevin Wolf (4):
  qcow2: Move sync out of write_refcount_block_entries
  qcow2: Move sync out of update_refcount
  qcow2: Move sync out of qcow2_alloc_clusters
  qcow2: Get rid of additional sync on COW

 block/qcow2-cluster.c  |   11 ++++++++++-
 block/qcow2-refcount.c |   13 ++++++++++++-
 block/qcow2-snapshot.c |    2 ++
 3 files changed, 24 insertions(+), 2 deletions(-)

-- 
1.7.2.2

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH 1/4] qcow2: Move sync out of write_refcount_block_entries
  2010-09-17 16:18 [Qemu-devel] [PATCH 0/4] qcow2: Save another common flush Kevin Wolf
@ 2010-09-17 16:18 ` Kevin Wolf
  2010-09-17 16:18 ` [Qemu-devel] [PATCH 2/4] qcow2: Move sync out of update_refcount Kevin Wolf
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Kevin Wolf @ 2010-09-17 16:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow2-refcount.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 4c19e7e..7dc75d1 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -444,7 +444,7 @@ static int write_refcount_block_entries(BlockDriverState *bs,
     size = (last_index - first_index) << REFCOUNT_SHIFT;
 
     BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART);
-    ret = bdrv_pwrite_sync(bs->file,
+    ret = bdrv_pwrite(bs->file,
         refcount_block_offset + (first_index << REFCOUNT_SHIFT),
         &s->refcount_block_cache[first_index], size);
     if (ret < 0) {
@@ -551,6 +551,8 @@ fail:
         dummy = update_refcount(bs, offset, cluster_offset - offset, -addend);
     }
 
+    bdrv_flush(bs->file);
+
     return ret;
 }
 
-- 
1.7.2.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH 2/4] qcow2: Move sync out of update_refcount
  2010-09-17 16:18 [Qemu-devel] [PATCH 0/4] qcow2: Save another common flush Kevin Wolf
  2010-09-17 16:18 ` [Qemu-devel] [PATCH 1/4] qcow2: Move sync out of write_refcount_block_entries Kevin Wolf
@ 2010-09-17 16:18 ` Kevin Wolf
  2010-09-17 17:06   ` Anthony Liguori
  2010-09-17 16:18 ` [Qemu-devel] [PATCH 3/4] qcow2: Move sync out of qcow2_alloc_clusters Kevin Wolf
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Kevin Wolf @ 2010-09-17 16:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

Note that the flush is omitted intentionally in qcow2_free_clusters. If
anything, we can leak clusters here if we lose the writes.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow2-refcount.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 7dc75d1..4fc3f80 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -261,6 +261,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
             goto fail_block;
         }
 
+        bdrv_flush(bs->file);
+
         /* 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);
@@ -551,8 +553,6 @@ fail:
         dummy = update_refcount(bs, offset, cluster_offset - offset, -addend);
     }
 
-    bdrv_flush(bs->file);
-
     return ret;
 }
 
@@ -575,6 +575,8 @@ static int update_cluster_refcount(BlockDriverState *bs,
         return ret;
     }
 
+    bdrv_flush(bs->file);
+
     return get_refcount(bs, cluster_index);
 }
 
@@ -626,6 +628,9 @@ int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size)
     if (ret < 0) {
         return ret;
     }
+
+    bdrv_flush(bs->file);
+
     return offset;
 }
 
@@ -803,6 +808,10 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
                             if (ret < 0) {
                                 goto fail;
                             }
+
+                            /* TODO Flushing once for the whole function should
+                             * be enough */
+                            bdrv_flush(bs->file);
                         }
                         /* compressed clusters are never modified */
                         refcount = 2;
-- 
1.7.2.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH 3/4] qcow2: Move sync out of qcow2_alloc_clusters
  2010-09-17 16:18 [Qemu-devel] [PATCH 0/4] qcow2: Save another common flush Kevin Wolf
  2010-09-17 16:18 ` [Qemu-devel] [PATCH 1/4] qcow2: Move sync out of write_refcount_block_entries Kevin Wolf
  2010-09-17 16:18 ` [Qemu-devel] [PATCH 2/4] qcow2: Move sync out of update_refcount Kevin Wolf
@ 2010-09-17 16:18 ` Kevin Wolf
  2010-09-17 16:18 ` [Qemu-devel] [PATCH 4/4] qcow2: Get rid of additional sync on COW Kevin Wolf
  2010-09-17 17:05 ` [Qemu-devel] [PATCH 0/4] qcow2: Save another common flush Anthony Liguori
  4 siblings, 0 replies; 8+ messages in thread
From: Kevin Wolf @ 2010-09-17 16:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow2-cluster.c  |    3 +++
 block/qcow2-refcount.c |    4 ++--
 block/qcow2-snapshot.c |    2 ++
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 91fa9ac..66969c2 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -60,6 +60,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
         qemu_free(new_l1_table);
         return new_l1_table_offset;
     }
+    bdrv_flush(bs->file);
 
     BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE);
     for(i = 0; i < s->l1_size; i++)
@@ -244,6 +245,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
     if (l2_offset < 0) {
         return l2_offset;
     }
+    bdrv_flush(bs->file);
 
     /* allocate a new entry in the l2 cache */
 
@@ -870,6 +872,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
         QLIST_REMOVE(m, next_in_flight);
         return cluster_offset;
     }
+    bdrv_flush(bs->file);
 
     /* save info needed for meta data update */
     m->offset = offset;
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 4fc3f80..7082601 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -629,8 +629,6 @@ int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size)
         return ret;
     }
 
-    bdrv_flush(bs->file);
-
     return offset;
 }
 
@@ -678,6 +676,8 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
             goto redo;
         }
     }
+
+    bdrv_flush(bs->file);
     return offset;
 }
 
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index e663e8b..e429920 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -138,6 +138,7 @@ static int qcow_write_snapshots(BlockDriverState *bs)
     snapshots_size = offset;
 
     snapshots_offset = qcow2_alloc_clusters(bs, snapshots_size);
+    bdrv_flush(bs->file);
     offset = snapshots_offset;
     if (offset < 0) {
         return offset;
@@ -271,6 +272,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     if (l1_table_offset < 0) {
         goto fail;
     }
+    bdrv_flush(bs->file);
 
     sn->l1_table_offset = l1_table_offset;
     sn->l1_size = s->l1_size;
-- 
1.7.2.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH 4/4] qcow2: Get rid of additional sync on COW
  2010-09-17 16:18 [Qemu-devel] [PATCH 0/4] qcow2: Save another common flush Kevin Wolf
                   ` (2 preceding siblings ...)
  2010-09-17 16:18 ` [Qemu-devel] [PATCH 3/4] qcow2: Move sync out of qcow2_alloc_clusters Kevin Wolf
@ 2010-09-17 16:18 ` Kevin Wolf
  2010-09-17 17:05 ` [Qemu-devel] [PATCH 0/4] qcow2: Save another common flush Anthony Liguori
  4 siblings, 0 replies; 8+ messages in thread
From: Kevin Wolf @ 2010-09-17 16:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf

We always have a sync for the refcount update when a new cluster is
allocated. If we move this past the COW, we can save an additional sync.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow2-cluster.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 66969c2..634ccef 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -422,7 +422,7 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
                         &s->aes_encrypt_key);
     }
     BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE);
-    ret = bdrv_write_sync(bs->file, (cluster_offset >> 9) + n_start,
+    ret = bdrv_write(bs->file, (cluster_offset >> 9) + n_start,
         s->cluster_data, n);
     if (ret < 0)
         return ret;
@@ -721,6 +721,13 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
                     (i << s->cluster_bits)) | QCOW_OFLAG_COPIED);
      }
 
+    /*
+     * Before we update the L2 table to actually point to the new cluster, we
+     * need to be sure that the refcounts have been increased and COW was
+     * handled.
+     */
+    bdrv_flush(bs->file);
+
     ret = write_l2_entries(bs, l2_table, l2_offset, l2_index, m->nb_clusters);
     if (ret < 0) {
         qcow2_l2_cache_reset(bs);
@@ -872,7 +879,6 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
         QLIST_REMOVE(m, next_in_flight);
         return cluster_offset;
     }
-    bdrv_flush(bs->file);
 
     /* save info needed for meta data update */
     m->offset = offset;
-- 
1.7.2.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH 0/4] qcow2: Save another common flush
  2010-09-17 16:18 [Qemu-devel] [PATCH 0/4] qcow2: Save another common flush Kevin Wolf
                   ` (3 preceding siblings ...)
  2010-09-17 16:18 ` [Qemu-devel] [PATCH 4/4] qcow2: Get rid of additional sync on COW Kevin Wolf
@ 2010-09-17 17:05 ` Anthony Liguori
  4 siblings, 0 replies; 8+ messages in thread
From: Anthony Liguori @ 2010-09-17 17:05 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 09/17/2010 11:18 AM, Kevin Wolf wrote:
> For copy on write (this includes any cluster allocations that don't fill the
> whole cluster with one request), what qcow2 does looks like this:
>
> 1. Allocate new clusters (increase refcounts)
> 2. bdrv_flush
> 3. Copy sectors before the first touched one
> 4. bdrv_flush
> 5. Copy sectors after the last touched one
> 6. bdrv_flush
> 7. Update the L2 table to point to the new clusters
>
> Step 2 and 4 are not necessary. This series moves flushes around to get all
> of these three bdrv_flush calls merged into one.
>    

Makes sense to me.

Regards,

Anthony Liguori

> Kevin Wolf (4):
>    qcow2: Move sync out of write_refcount_block_entries
>    qcow2: Move sync out of update_refcount
>    qcow2: Move sync out of qcow2_alloc_clusters
>    qcow2: Get rid of additional sync on COW
>
>   block/qcow2-cluster.c  |   11 ++++++++++-
>   block/qcow2-refcount.c |   13 ++++++++++++-
>   block/qcow2-snapshot.c |    2 ++
>   3 files changed, 24 insertions(+), 2 deletions(-)
>
>    

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH 2/4] qcow2: Move sync out of update_refcount
  2010-09-17 16:18 ` [Qemu-devel] [PATCH 2/4] qcow2: Move sync out of update_refcount Kevin Wolf
@ 2010-09-17 17:06   ` Anthony Liguori
  2010-09-17 17:19     ` Kevin Wolf
  0 siblings, 1 reply; 8+ messages in thread
From: Anthony Liguori @ 2010-09-17 17:06 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel

On 09/17/2010 11:18 AM, Kevin Wolf wrote:
> Note that the flush is omitted intentionally in qcow2_free_clusters. If
> anything, we can leak clusters here if we lose the writes.
>
> Signed-off-by: Kevin Wolf<kwolf@redhat.com>
>    

Cluster leaking gets picked up by bdrv_check though, right?

I think I've convinced myself that leaking clusters is not an acceptable 
behavior from a security perspective but as long as it's detectable via 
bdrv_check, qcow2 could implement an online check to address it.

Regards,

Anthony Liguori

> ---
>   block/qcow2-refcount.c |   13 +++++++++++--
>   1 files changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
> index 7dc75d1..4fc3f80 100644
> --- a/block/qcow2-refcount.c
> +++ b/block/qcow2-refcount.c
> @@ -261,6 +261,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
>               goto fail_block;
>           }
>
> +        bdrv_flush(bs->file);
> +
>           /* 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);
> @@ -551,8 +553,6 @@ fail:
>           dummy = update_refcount(bs, offset, cluster_offset - offset, -addend);
>       }
>
> -    bdrv_flush(bs->file);
> -
>       return ret;
>   }
>
> @@ -575,6 +575,8 @@ static int update_cluster_refcount(BlockDriverState *bs,
>           return ret;
>       }
>
> +    bdrv_flush(bs->file);
> +
>       return get_refcount(bs, cluster_index);
>   }
>
> @@ -626,6 +628,9 @@ int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size)
>       if (ret<  0) {
>           return ret;
>       }
> +
> +    bdrv_flush(bs->file);
> +
>       return offset;
>   }
>
> @@ -803,6 +808,10 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
>                               if (ret<  0) {
>                                   goto fail;
>                               }
> +
> +                            /* TODO Flushing once for the whole function should
> +                             * be enough */
> +                            bdrv_flush(bs->file);
>                           }
>                           /* compressed clusters are never modified */
>                           refcount = 2;
>    

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH 2/4] qcow2: Move sync out of update_refcount
  2010-09-17 17:06   ` Anthony Liguori
@ 2010-09-17 17:19     ` Kevin Wolf
  0 siblings, 0 replies; 8+ messages in thread
From: Kevin Wolf @ 2010-09-17 17:19 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel

Am 17.09.2010 19:06, schrieb Anthony Liguori:
> On 09/17/2010 11:18 AM, Kevin Wolf wrote:
>> Note that the flush is omitted intentionally in qcow2_free_clusters. If
>> anything, we can leak clusters here if we lose the writes.
>>
>> Signed-off-by: Kevin Wolf<kwolf@redhat.com>
>>    
> 
> Cluster leaking gets picked up by bdrv_check though, right?
> 
> I think I've convinced myself that leaking clusters is not an acceptable 
> behavior from a security perspective but as long as it's detectable via 
> bdrv_check, qcow2 could implement an online check to address it.

Leaking clusters on crashes is unavoidable. But yes, qemu-img check does
detect this.

Kevin

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2010-09-17 17:19 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-17 16:18 [Qemu-devel] [PATCH 0/4] qcow2: Save another common flush Kevin Wolf
2010-09-17 16:18 ` [Qemu-devel] [PATCH 1/4] qcow2: Move sync out of write_refcount_block_entries Kevin Wolf
2010-09-17 16:18 ` [Qemu-devel] [PATCH 2/4] qcow2: Move sync out of update_refcount Kevin Wolf
2010-09-17 17:06   ` Anthony Liguori
2010-09-17 17:19     ` Kevin Wolf
2010-09-17 16:18 ` [Qemu-devel] [PATCH 3/4] qcow2: Move sync out of qcow2_alloc_clusters Kevin Wolf
2010-09-17 16:18 ` [Qemu-devel] [PATCH 4/4] qcow2: Get rid of additional sync on COW Kevin Wolf
2010-09-17 17:05 ` [Qemu-devel] [PATCH 0/4] qcow2: Save another common flush Anthony Liguori

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.