diff mbox series

[RFC] block: always update auto_backing_file to full path

Message ID ce32e1c2-c652-e83b-a6f4-c9773099cf9a@oracle.com
State New
Headers show
Series [RFC] block: always update auto_backing_file to full path | expand

Commit Message

Joe Jin April 1, 2021, 4:22 a.m. UTC
Some time after created snapshot, auto_backing_file only has filename,
this confused overridden check, update it to full path if it is not.

Signed-off-by: Joe Jin <joe.jin@oracle.com>
---
 block.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

Comments

Joe Jin April 1, 2021, 9:47 p.m. UTC | #1
Hi Max,

Thanks very much for your replies.

On 4/1/21 2:57 AM, Max Reitz wrote:
> On 01.04.21 06:22, Joe Jin wrote:
>> Some time after created snapshot, auto_backing_file only has filename,
>> this confused overridden check, update it to full path if it is not.
>>
>> Signed-off-by: Joe Jin <joe.jin@oracle.com>
>> ---
>>   block.c | 13 +++++++++++++
>>   1 file changed, 13 insertions(+)
>
> Do you have a test for this?
My issue is my guest image is on NFS, I could created snapshot from ovirt but I could not delete it, tried to commit it by virsh and it complained qemu internal error:
# virsh blockcommit snap-test sda --active --verbose --pivot
error: internal error: qemu block name 'json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "/rhev/data-center/mnt/nfs_server:_nfsexport/fee77d23-1291-4bdb-9157-12ff6cd5ee96/images/66bb625e-7458-478d-a238-b012f87062b8/919a4cda-bf11-4bb7-a2e3-d9e4515ed646"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "/rhev/data-center/mnt/nfs_server:_nfsexport/fee77d23-1291-4bdb-9157-12ff6cd5ee96/images/66bb625e-7458-478d-a238-b012f87062b8/24d28fcd-67e3-49d2-8860-2110f3a5e796"}}' doesn't match expected '/rhev/data-center/mnt/nfs_server:_nfsexport/fee77d23-1291-4bdb-9157-12ff6cd5ee96/images/66bb625e-7458-478d-a238-b012f87062b8/24d28fcd-67e3-49d2-8860-2110f3a5e796'
Tracked qemu block and I found when issue happened, bdrv_backing_overridden() was tried to compare absolute path(bs->backing->bs->filename) with relative path(bs->auto_backing_file) but they are same filename, then it triggered generated json filename.
Regarding auto_backing_file, it updated by qcow2_do_open(), and read the backing file name from image:
    /* read the backing file name */                                                      
    if (header.backing_file_offset != 0) {                                                
        len = header.backing_file_size;                                                   
        if (len > MIN(1023, s->cluster_size - header.backing_file_offset) ||              
            len >= sizeof(bs->backing_file)) {                                            
            error_setg(errp, "Backing file name too long");                               
            ret = -EINVAL;                                                                
            goto fail;                                                                    
        }                                                                                 
        ret = bdrv_pread(bs->file, header.backing_file_offset,                            
                         bs->auto_backing_file, len);                                     
        if (ret < 0) {                                                                    
            error_setg_errno(errp, -ret, "Could not read backing file name");             
            goto fail;                                                                    
        }                                                                                 
        bs->auto_backing_file[len] = '\0';                                                
        pstrcpy(bs->backing_file, sizeof(bs->backing_file),                               
                bs->auto_backing_file);                                                   
        s->image_backing_file = g_strdup(bs->auto_backing_file);                          
    }                                                                                     

Updated auto_backing_file to absolute path, I could successfully delete snapshot from ovirt, or execute blockcommit by virsh.

>
> The thing is, I’m not sure about this solution, and I think having a test would help me understand better.
> bs->auto_backing_file is meant to track what filename a BDS would have if we opened bs->backing_file.  To this end, we generally set it to whatever bs->backing_file is and then refresh it when we actually do open a BDS from it.
>
> So it seems strange to blindly modify it somewhere that doesn’t have to do with any of these things.
>
> Now, when opening a backing file from bs->backing_file, we first do make it an absolute filename via bdrv_get_full_backing_filename().  So it kind of seems prudent to replicate that elsewhere, but I’m not sure where exactly.  I would think the best place would be whenever auto_backing_file is set to be equal to backing_file (which is generally in the image format drivers, when they read the backing file string from the image metadata), but that might break the strcmp() in bdrv_open_backing_file()...
>
> I don’t think bdrv_refresh_filename() is the right place, though, because I’m afraid that this might modify filenames we’ve already retrieved from the actual backing BDS, or something.
>
> For example, with this patch applied, iotest 024 fails.
Yes after applied my patch, I can reproduced the failure, it caused by bdrv_make_absolute_filename() returned relative path, not sure if this is bdrv_make_absolute_filename() bug?
Added path_is_absolute(backing_filename) check before update auto_backing_file, test passed:
+        backing_filename = bdrv_make_absolute_filename(bs, bs->auto_backing_file, &local_err);
+        if (!local_err && backing_filename && path_is_absolute(backing_filename)) {
+            pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
+                     backing_filename);

>
>> diff --git a/block.c b/block.c
>> index c5b887cec1..8f9a027dee 100644
>> --- a/block.c
>> +++ b/block.c
>> @@ -6969,6 +6969,19 @@ void bdrv_refresh_filename(BlockDriverState *bs)
>>           return;
>>       }
>>   +    /* auto_backing_file only has filename, update it to the full path */
>> +    if (bs->backing && bs->auto_backing_file[0] != '/') {
>> +        char *backing_filename = NULL;
>> +        Error *local_err = NULL;
>> +
>> +        backing_filename = bdrv_make_absolute_filename(bs,
>> +                                     bs->auto_backing_file, &local_err);
>> +        if (!local_err && backing_filename) {
>> +            pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
>> +                     backing_filename);
>> +            g_free(backing_filename);
>> +        }
>> +    }
>
> All spaces here are 0xa0 (non-breaking space), which is kind of broken and makes it difficult to apply this patch.
Sorry about this, I may use git send-email to send it.

>
> Furthermore, if local_err != NULL, we’d need to free it.

Thanks for reminder, will take care of this.

Thanks,
Joe
>
> Max
>
>>       backing_overridden = bdrv_backing_overridden(bs);
>>         if (bs->open_flags & BDRV_O_NO_IO) {
>>
>
diff mbox series

Patch

diff --git a/block.c b/block.c
index c5b887cec1..8f9a027dee 100644
--- a/block.c
+++ b/block.c
@@ -6969,6 +6969,19 @@  void bdrv_refresh_filename(BlockDriverState *bs)
         return;
     }
 
+    /* auto_backing_file only has filename, update it to the full path */
+    if (bs->backing && bs->auto_backing_file[0] != '/') {
+        char *backing_filename = NULL;
+        Error *local_err = NULL;
+
+        backing_filename = bdrv_make_absolute_filename(bs,
+                                     bs->auto_backing_file, &local_err);
+        if (!local_err && backing_filename) {
+            pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
+                     backing_filename);
+            g_free(backing_filename);
+        }
+    }
     backing_overridden = bdrv_backing_overridden(bs);
 
     if (bs->open_flags & BDRV_O_NO_IO) {