block: Add blockdev-backup to transaction
Signed-off-by: Fam Zheng <famz@redhat.com> Reviewed-by: John Snow <jsnow@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Message-id: 1418899027-8445-4-git-send-email-famz@redhat.com Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
		
				
					committed by
					
						 Stefan Hajnoczi
						Stefan Hajnoczi
					
				
			
			
				
	
			
			
			
						parent
						
							c29c1dd312
						
					
				
				
					commit
					bd8baecddc
				
			
							
								
								
									
										79
									
								
								blockdev.c
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								blockdev.c
									
									
									
									
									
								
							| @@ -1559,6 +1559,79 @@ static void drive_backup_clean(BlkTransactionState *common) | ||||
|     } | ||||
| } | ||||
|  | ||||
| typedef struct BlockdevBackupState { | ||||
|     BlkTransactionState common; | ||||
|     BlockDriverState *bs; | ||||
|     BlockJob *job; | ||||
|     AioContext *aio_context; | ||||
| } BlockdevBackupState; | ||||
|  | ||||
| static void blockdev_backup_prepare(BlkTransactionState *common, Error **errp) | ||||
| { | ||||
|     BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common); | ||||
|     BlockdevBackup *backup; | ||||
|     BlockDriverState *bs, *target; | ||||
|     Error *local_err = NULL; | ||||
|  | ||||
|     assert(common->action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP); | ||||
|     backup = common->action->blockdev_backup; | ||||
|  | ||||
|     bs = bdrv_find(backup->device); | ||||
|     if (!bs) { | ||||
|         error_set(errp, QERR_DEVICE_NOT_FOUND, backup->device); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     target = bdrv_find(backup->target); | ||||
|     if (!target) { | ||||
|         error_set(errp, QERR_DEVICE_NOT_FOUND, backup->target); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     /* AioContext is released in .clean() */ | ||||
|     state->aio_context = bdrv_get_aio_context(bs); | ||||
|     if (state->aio_context != bdrv_get_aio_context(target)) { | ||||
|         state->aio_context = NULL; | ||||
|         error_setg(errp, "Backup between two IO threads is not implemented"); | ||||
|         return; | ||||
|     } | ||||
|     aio_context_acquire(state->aio_context); | ||||
|  | ||||
|     qmp_blockdev_backup(backup->device, backup->target, | ||||
|                         backup->sync, | ||||
|                         backup->has_speed, backup->speed, | ||||
|                         backup->has_on_source_error, backup->on_source_error, | ||||
|                         backup->has_on_target_error, backup->on_target_error, | ||||
|                         &local_err); | ||||
|     if (local_err) { | ||||
|         error_propagate(errp, local_err); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     state->bs = bs; | ||||
|     state->job = state->bs->job; | ||||
| } | ||||
|  | ||||
| static void blockdev_backup_abort(BlkTransactionState *common) | ||||
| { | ||||
|     BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common); | ||||
|     BlockDriverState *bs = state->bs; | ||||
|  | ||||
|     /* Only cancel if it's the job we started */ | ||||
|     if (bs && bs->job && bs->job == state->job) { | ||||
|         block_job_cancel_sync(bs->job); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void blockdev_backup_clean(BlkTransactionState *common) | ||||
| { | ||||
|     BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common); | ||||
|  | ||||
|     if (state->aio_context) { | ||||
|         aio_context_release(state->aio_context); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void abort_prepare(BlkTransactionState *common, Error **errp) | ||||
| { | ||||
|     error_setg(errp, "Transaction aborted using Abort action"); | ||||
| @@ -1582,6 +1655,12 @@ static const BdrvActionOps actions[] = { | ||||
|         .abort = drive_backup_abort, | ||||
|         .clean = drive_backup_clean, | ||||
|     }, | ||||
|     [TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP] = { | ||||
|         .instance_size = sizeof(BlockdevBackupState), | ||||
|         .prepare = blockdev_backup_prepare, | ||||
|         .abort = blockdev_backup_abort, | ||||
|         .clean = blockdev_backup_clean, | ||||
|     }, | ||||
|     [TRANSACTION_ACTION_KIND_ABORT] = { | ||||
|         .instance_size = sizeof(BlkTransactionState), | ||||
|         .prepare = abort_prepare, | ||||
|   | ||||
| @@ -1260,11 +1260,13 @@ | ||||
| # drive-backup since 1.6 | ||||
| # abort since 1.6 | ||||
| # blockdev-snapshot-internal-sync since 1.7 | ||||
| # blockdev-backup since 2.3 | ||||
| ## | ||||
| { 'union': 'TransactionAction', | ||||
|   'data': { | ||||
|        'blockdev-snapshot-sync': 'BlockdevSnapshot', | ||||
|        'drive-backup': 'DriveBackup', | ||||
|        'blockdev-backup': 'BlockdevBackup', | ||||
|        'abort': 'Abort', | ||||
|        'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternal' | ||||
|    } } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user