iotests: add transactional failure race test
Add a regression test for the case found by Vladimir. Reported-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-id: 1478587839-9834-7-git-send-email-jsnow@redhat.com Signed-off-by: Jeff Cody <jcody@redhat.com>
This commit is contained in:
parent
111049a4ec
commit
0aef09b9c9
|
@ -395,19 +395,7 @@ class TestIncrementalBackup(TestIncrementalBackupBase):
|
||||||
self.check_backups()
|
self.check_backups()
|
||||||
|
|
||||||
|
|
||||||
def test_transaction_failure(self):
|
def do_transaction_failure_test(self, race=False):
|
||||||
'''Test: Verify backups made from a transaction that partially fails.
|
|
||||||
|
|
||||||
Add a second drive with its own unique pattern, and add a bitmap to each
|
|
||||||
drive. Use blkdebug to interfere with the backup on just one drive and
|
|
||||||
attempt to create a coherent incremental backup across both drives.
|
|
||||||
|
|
||||||
verify a failure in one but not both, then delete the failed stubs and
|
|
||||||
re-run the same transaction.
|
|
||||||
|
|
||||||
verify that both incrementals are created successfully.
|
|
||||||
'''
|
|
||||||
|
|
||||||
# Create a second drive, with pattern:
|
# Create a second drive, with pattern:
|
||||||
drive1 = self.add_node('drive1')
|
drive1 = self.add_node('drive1')
|
||||||
self.img_create(drive1['file'], drive1['fmt'])
|
self.img_create(drive1['file'], drive1['fmt'])
|
||||||
|
@ -451,6 +439,7 @@ class TestIncrementalBackup(TestIncrementalBackupBase):
|
||||||
self.assertFalse(self.vm.get_qmp_events(wait=False))
|
self.assertFalse(self.vm.get_qmp_events(wait=False))
|
||||||
|
|
||||||
# Emulate some writes
|
# Emulate some writes
|
||||||
|
if not race:
|
||||||
self.hmp_io_writes(drive0['id'], (('0xab', 0, 512),
|
self.hmp_io_writes(drive0['id'], (('0xab', 0, 512),
|
||||||
('0xfe', '16M', '256k'),
|
('0xfe', '16M', '256k'),
|
||||||
('0x64', '32736k', '64k')))
|
('0x64', '32736k', '64k')))
|
||||||
|
@ -463,7 +452,8 @@ class TestIncrementalBackup(TestIncrementalBackupBase):
|
||||||
target1 = self.prepare_backup(dr1bm0)
|
target1 = self.prepare_backup(dr1bm0)
|
||||||
|
|
||||||
# Ask for a new incremental backup per-each drive,
|
# Ask for a new incremental backup per-each drive,
|
||||||
# expecting drive1's backup to fail:
|
# expecting drive1's backup to fail. In the 'race' test,
|
||||||
|
# we expect drive1 to attempt to cancel the empty drive0 job.
|
||||||
transaction = [
|
transaction = [
|
||||||
transaction_drive_backup(drive0['id'], target0, sync='incremental',
|
transaction_drive_backup(drive0['id'], target0, sync='incremental',
|
||||||
format=drive0['fmt'], mode='existing',
|
format=drive0['fmt'], mode='existing',
|
||||||
|
@ -488,9 +478,15 @@ class TestIncrementalBackup(TestIncrementalBackupBase):
|
||||||
self.assert_no_active_block_jobs()
|
self.assert_no_active_block_jobs()
|
||||||
|
|
||||||
# Delete drive0's successful target and eliminate our record of the
|
# Delete drive0's successful target and eliminate our record of the
|
||||||
# unsuccessful drive1 target. Then re-run the same transaction.
|
# unsuccessful drive1 target.
|
||||||
dr0bm0.del_target()
|
dr0bm0.del_target()
|
||||||
dr1bm0.del_target()
|
dr1bm0.del_target()
|
||||||
|
if race:
|
||||||
|
# Don't re-run the transaction, we only wanted to test the race.
|
||||||
|
self.vm.shutdown()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Re-run the same transaction:
|
||||||
target0 = self.prepare_backup(dr0bm0)
|
target0 = self.prepare_backup(dr0bm0)
|
||||||
target1 = self.prepare_backup(dr1bm0)
|
target1 = self.prepare_backup(dr1bm0)
|
||||||
|
|
||||||
|
@ -511,6 +507,27 @@ class TestIncrementalBackup(TestIncrementalBackupBase):
|
||||||
self.vm.shutdown()
|
self.vm.shutdown()
|
||||||
self.check_backups()
|
self.check_backups()
|
||||||
|
|
||||||
|
def test_transaction_failure(self):
|
||||||
|
'''Test: Verify backups made from a transaction that partially fails.
|
||||||
|
|
||||||
|
Add a second drive with its own unique pattern, and add a bitmap to each
|
||||||
|
drive. Use blkdebug to interfere with the backup on just one drive and
|
||||||
|
attempt to create a coherent incremental backup across both drives.
|
||||||
|
|
||||||
|
verify a failure in one but not both, then delete the failed stubs and
|
||||||
|
re-run the same transaction.
|
||||||
|
|
||||||
|
verify that both incrementals are created successfully.
|
||||||
|
'''
|
||||||
|
self.do_transaction_failure_test()
|
||||||
|
|
||||||
|
def test_transaction_failure_race(self):
|
||||||
|
'''Test: Verify that transactions with jobs that have no data to
|
||||||
|
transfer do not cause race conditions in the cancellation of the entire
|
||||||
|
transaction job group.
|
||||||
|
'''
|
||||||
|
self.do_transaction_failure_test(race=True)
|
||||||
|
|
||||||
|
|
||||||
def test_sync_dirty_bitmap_missing(self):
|
def test_sync_dirty_bitmap_missing(self):
|
||||||
self.assert_no_active_block_jobs()
|
self.assert_no_active_block_jobs()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
..........
|
...........
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
Ran 10 tests
|
Ran 11 tests
|
||||||
|
|
||||||
OK
|
OK
|
||||||
|
|
Loading…
Reference in a new issue