[v2,01/10] qcow2: Fix error handling in qcow2_grow_l1_table

Submitted by Kevin Wolf on Jan. 20, 2010, 2:02 p.m.

Details

Message ID 1263996186-6623-2-git-send-email-kwolf@redhat.com
State New
Headers show

Commit Message

Kevin Wolf Jan. 20, 2010, 2:02 p.m.
Return the appropriate error value instead of always using EIO. Don't free the
L1 table on errors, we still need it.

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

Comments

Anthony Liguori Jan. 26, 2010, 9:37 p.m.
On 01/20/2010 08:02 AM, Kevin Wolf wrote:
> Return the appropriate error value instead of always using EIO. Don't free the
> L1 table on errors, we still need it.
>
> Signed-off-by: Kevin Wolf<kwolf@redhat.com>
>    

Applied all.  Thanks.

Do you think this is stable-0.12 material?  Is there any reasonable 
scenario where this could fix a user visible bug?

Regards,

Anthony Liguori
Kevin Wolf Jan. 27, 2010, 8:56 a.m.
Am 26.01.2010 22:37, schrieb Anthony Liguori:
> On 01/20/2010 08:02 AM, Kevin Wolf wrote:
>> Return the appropriate error value instead of always using EIO. Don't free the
>> L1 table on errors, we still need it.
>>
>> Signed-off-by: Kevin Wolf<kwolf@redhat.com>
>>    
> 
> Applied all.  Thanks.
> 
> Do you think this is stable-0.12 material?  Is there any reasonable 
> scenario where this could fix a user visible bug?

Yes, I think this is something for stable. Obviously the patches are
meant to only make a difference if something has gone wrong in the first
place, but in these cases it's expected to fix possible causes of
corruption (things like data written to clusters with refcount 0). Also
if someone relies on werror=enospc he'll need the right error codes.

Kevin

Patch hide | download patch | download mbox

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index f88118c..cb46376 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -67,9 +67,10 @@  int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
     /* set new table */
     cpu_to_be32w((uint32_t*)data, new_l1_size);
     cpu_to_be64w((uint64_t*)(data + 4), new_l1_table_offset);
-    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size), data,
-                sizeof(data)) != sizeof(data))
+    ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size), data,sizeof(data));
+    if (ret != sizeof(data)) {
         goto fail;
+    }
     qemu_free(s->l1_table);
     qcow2_free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t));
     s->l1_table_offset = new_l1_table_offset;
@@ -77,8 +78,9 @@  int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
     s->l1_size = new_l1_size;
     return 0;
  fail:
-    qemu_free(s->l1_table);
-    return -EIO;
+    qemu_free(new_l1_table);
+    qcow2_free_clusters(bs, new_l1_table_offset, new_l1_size2);
+    return ret < 0 ? ret : -EIO;
 }
 
 void qcow2_l2_cache_reset(BlockDriverState *bs)