block: introduce BLOCK_JOB_READY event
Even for jobs that need to be manually completed, management may want to take care itself of the completion, not requiring the user to issue a command to terminate the job. In this case we want to avoid that they poll us continuously, waiting for completion to become available. Thus, add a new event that signals the phase switch and the availability of the block-job-complete command. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
		
							parent
							
								
									aeae883baf
								
							
						
					
					
						commit
						a66a2a3683
					
				| 
						 | 
				
			
			@ -118,6 +118,24 @@ Example:
 | 
			
		|||
              "action": "stop" },
 | 
			
		||||
    "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
 | 
			
		||||
 | 
			
		||||
BLOCK_JOB_READY
 | 
			
		||||
---------------
 | 
			
		||||
 | 
			
		||||
Emitted when a block job is ready to complete.
 | 
			
		||||
 | 
			
		||||
Data:
 | 
			
		||||
 | 
			
		||||
- "device": device name (json-string)
 | 
			
		||||
 | 
			
		||||
Example:
 | 
			
		||||
 | 
			
		||||
{ "event": "BLOCK_JOB_READY",
 | 
			
		||||
    "data": { "device": "ide0-hd1" },
 | 
			
		||||
    "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
 | 
			
		||||
 | 
			
		||||
Note: The "ready to complete" status is always reset by a BLOCK_JOB_ERROR
 | 
			
		||||
event.
 | 
			
		||||
 | 
			
		||||
DEVICE_TRAY_MOVED
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								blockdev.c
								
								
								
								
							
							
						
						
									
										14
									
								
								blockdev.c
								
								
								
								
							| 
						 | 
				
			
			@ -1056,20 +1056,6 @@ void qmp_block_resize(const char *device, int64_t size, Error **errp)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static QObject *qobject_from_block_job(BlockJob *job)
 | 
			
		||||
{
 | 
			
		||||
    return qobject_from_jsonf("{ 'type': %s,"
 | 
			
		||||
                              "'device': %s,"
 | 
			
		||||
                              "'len': %" PRId64 ","
 | 
			
		||||
                              "'offset': %" PRId64 ","
 | 
			
		||||
                              "'speed': %" PRId64 " }",
 | 
			
		||||
                              job->job_type->job_type,
 | 
			
		||||
                              bdrv_get_device_name(job->bs),
 | 
			
		||||
                              job->len,
 | 
			
		||||
                              job->offset,
 | 
			
		||||
                              job->speed);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void block_job_cb(void *opaque, int ret)
 | 
			
		||||
{
 | 
			
		||||
    BlockDriverState *bs = opaque;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										21
									
								
								blockjob.c
								
								
								
								
							
							
						
						
									
										21
									
								
								blockjob.c
								
								
								
								
							| 
						 | 
				
			
			@ -225,6 +225,27 @@ static void block_job_iostatus_set_err(BlockJob *job, int error)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
QObject *qobject_from_block_job(BlockJob *job)
 | 
			
		||||
{
 | 
			
		||||
    return qobject_from_jsonf("{ 'type': %s,"
 | 
			
		||||
                              "'device': %s,"
 | 
			
		||||
                              "'len': %" PRId64 ","
 | 
			
		||||
                              "'offset': %" PRId64 ","
 | 
			
		||||
                              "'speed': %" PRId64 " }",
 | 
			
		||||
                              job->job_type->job_type,
 | 
			
		||||
                              bdrv_get_device_name(job->bs),
 | 
			
		||||
                              job->len,
 | 
			
		||||
                              job->offset,
 | 
			
		||||
                              job->speed);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void block_job_ready(BlockJob *job)
 | 
			
		||||
{
 | 
			
		||||
    QObject *data = qobject_from_block_job(job);
 | 
			
		||||
    monitor_protocol_event(QEVENT_BLOCK_JOB_READY, data);
 | 
			
		||||
    qobject_decref(data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs,
 | 
			
		||||
                                        BlockdevOnError on_err,
 | 
			
		||||
                                        int is_read, int error)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								blockjob.h
								
								
								
								
							
							
						
						
									
										16
									
								
								blockjob.h
								
								
								
								
							| 
						 | 
				
			
			@ -210,6 +210,22 @@ void block_job_pause(BlockJob *job);
 | 
			
		|||
 */
 | 
			
		||||
void block_job_resume(BlockJob *job);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * qobject_from_block_job:
 | 
			
		||||
 * @job: The job whose information is requested.
 | 
			
		||||
 *
 | 
			
		||||
 * Return a QDict corresponding to @job's query-block-jobs entry.
 | 
			
		||||
 */
 | 
			
		||||
QObject *qobject_from_block_job(BlockJob *job);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * block_job_ready:
 | 
			
		||||
 * @job: The job which is now ready to complete.
 | 
			
		||||
 *
 | 
			
		||||
 * Send a BLOCK_JOB_READY event for the specified job.
 | 
			
		||||
 */
 | 
			
		||||
void block_job_ready(BlockJob *job);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * block_job_is_paused:
 | 
			
		||||
 * @job: The job being queried.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -451,6 +451,7 @@ static const char *monitor_event_names[] = {
 | 
			
		|||
    [QEVENT_BLOCK_JOB_COMPLETED] = "BLOCK_JOB_COMPLETED",
 | 
			
		||||
    [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED",
 | 
			
		||||
    [QEVENT_BLOCK_JOB_ERROR] = "BLOCK_JOB_ERROR",
 | 
			
		||||
    [QEVENT_BLOCK_JOB_READY] = "BLOCK_JOB_READY",
 | 
			
		||||
    [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED",
 | 
			
		||||
    [QEVENT_SUSPEND] = "SUSPEND",
 | 
			
		||||
    [QEVENT_SUSPEND_DISK] = "SUSPEND_DISK",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,6 +39,7 @@ typedef enum MonitorEvent {
 | 
			
		|||
    QEVENT_BLOCK_JOB_COMPLETED,
 | 
			
		||||
    QEVENT_BLOCK_JOB_CANCELLED,
 | 
			
		||||
    QEVENT_BLOCK_JOB_ERROR,
 | 
			
		||||
    QEVENT_BLOCK_JOB_READY,
 | 
			
		||||
    QEVENT_DEVICE_TRAY_MOVED,
 | 
			
		||||
    QEVENT_SUSPEND,
 | 
			
		||||
    QEVENT_SUSPEND_DISK,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2037,7 +2037,8 @@
 | 
			
		|||
#
 | 
			
		||||
# Manually trigger completion of an active background block operation.  This
 | 
			
		||||
# is supported for drive mirroring, where it also switches the device to
 | 
			
		||||
# write to the target path only.
 | 
			
		||||
# write to the target path only.  The ability to complete is signaled with
 | 
			
		||||
# a BLOCK_JOB_READY event.
 | 
			
		||||
#
 | 
			
		||||
# This command completes an active background block operation synchronously.
 | 
			
		||||
# The ordering of this command's return with the BLOCK_JOB_COMPLETED event
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue