block/backup: Fix hang for unaligned image size
When doing a block backup of an image with an unaligned size (with respect to the BACKUP_CLUSTER_SIZE), qemu would check the allocation status of sectors after the end of the image. bdrv_is_allocated() returns a result that is valid for 0 sectors in this case, so the backup job ran into an endless loop. Stop looping when seeing a result valid for 0 sectors, we're at EOF then. The test case looks somewhat unrelated at first sight because I originally tried to reproduce a different suspected bug that turned out to not exist. Still a good test case and it accidentally found this one. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
		
							parent
							
								
									675879f6f3
								
							
						
					
					
						commit
						d40593dd90
					
				@ -307,7 +307,7 @@ static void coroutine_fn backup_run(void *opaque)
 | 
				
			|||||||
                                BACKUP_SECTORS_PER_CLUSTER - i, &n);
 | 
					                                BACKUP_SECTORS_PER_CLUSTER - i, &n);
 | 
				
			||||||
                    i += n;
 | 
					                    i += n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (alloced == 1) {
 | 
					                    if (alloced == 1 || n == 0) {
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
				
			|||||||
@ -33,6 +33,7 @@ status=1	# failure is the default!
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
_cleanup()
 | 
					_cleanup()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    rm -f "${TEST_IMG}.copy"
 | 
				
			||||||
    _cleanup_test_img
 | 
					    _cleanup_test_img
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
trap "_cleanup; exit \$status" 0 1 2 3 15
 | 
					trap "_cleanup; exit \$status" 0 1 2 3 15
 | 
				
			||||||
@ -41,6 +42,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 | 
				
			|||||||
. ./common.rc
 | 
					. ./common.rc
 | 
				
			||||||
. ./common.filter
 | 
					. ./common.filter
 | 
				
			||||||
. ./common.pattern
 | 
					. ./common.pattern
 | 
				
			||||||
 | 
					. ./common.qemu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Any format supporting backing files except vmdk and qcow which do not support
 | 
					# Any format supporting backing files except vmdk and qcow which do not support
 | 
				
			||||||
# smaller backing files.
 | 
					# smaller backing files.
 | 
				
			||||||
@ -99,6 +101,29 @@ _check_test_img
 | 
				
			|||||||
# Rebase it on top of its base image
 | 
					# Rebase it on top of its base image
 | 
				
			||||||
$QEMU_IMG rebase -b "$TEST_IMG.base" "$TEST_IMG"
 | 
					$QEMU_IMG rebase -b "$TEST_IMG.base" "$TEST_IMG"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo
 | 
				
			||||||
 | 
					echo block-backup
 | 
				
			||||||
 | 
					echo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qemu_comm_method="monitor"
 | 
				
			||||||
 | 
					_launch_qemu -drive file="${TEST_IMG}",cache=${CACHEMODE},id=disk
 | 
				
			||||||
 | 
					h=$QEMU_HANDLE
 | 
				
			||||||
 | 
					QEMU_COMM_TIMEOUT=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)"
 | 
				
			||||||
 | 
					qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs"
 | 
				
			||||||
 | 
					_send_qemu_cmd $h 'quit' ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Base image sectors
 | 
				
			||||||
 | 
					TEST_IMG="${TEST_IMG}.copy" io readv $(( offset )) 512 1024 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Image sectors
 | 
				
			||||||
 | 
					TEST_IMG="${TEST_IMG}.copy" io readv $(( offset + 512 )) 512 1024 64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Zero sectors beyond end of base image
 | 
				
			||||||
 | 
					TEST_IMG="${TEST_IMG}.copy" io_zero readv $(( offset + 32 * 1024 )) 512 1024 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_check_test_img
 | 
					_check_test_img
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# success, all done
 | 
					# success, all done
 | 
				
			||||||
 | 
				
			|||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user