- Op Blockers
- Finer granularity - more parallelism
- Safer blocking
- Safe(r) commit
Safe(r) Commit
Sectors in "active" differ from those in "base"
Safe(r) Commit
Normal commit: push sectors into "base"
Safe(r) Commit
Images "snap-a" and "snap-b" now invalid
Safe(r) Commit
Let's try to be safer
Safe(r) Commit
First, stream affected sectors to overlay image
Safe(r) Commit
Now commit sectors from "active"
Safe(r) Commit
All backing files in the chain are now still valid
Key Components
-
QMP command definition
- JSON file (qapi/*.json)
- qmp_commands.hx
-
Command handler
-
Block Job coroutine
-
Schedule job completion / cleanup
A sample Block Job:
- block-null
- Simple block job
- Reads all sectors in BDS
QMP Command Definition
{ 'enum': 'BlockJobType',
'data': ['commit', 'stream', 'mirror', 'backup', 'null'] }
{ 'command': 'block-null',
'data': { 'device': 'str', '*speed': 'int' } }
void qmp_block_null(const char *device,
bool has_speed, int64_t speed,
Error **errp)
{
BlockBackend *blk;
BlockDriverState *bs;
AioContext *aio_context;
Error *local_err = NULL;
if (!has_speed) {
speed = 0;
}
blk = blk_by_name(device);
if (!blk) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"device '%s' not found", device);
return;
}
bs = blk_bs(blk);
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
if (local_err != NULL) {
error_propagate(errp, local_err);
goto out;
}
null_start(bs, speed, block_job_cb, bs, &local_err);
out:
aio_context_release(aio_context);
}
Block Job Coroutine
- Coroutine loop
- Cooperative - must yield
- Sleep time derived from throttle speed
block_job_sleep_ns()
- Perform I/O
- e.g., loop & read sectors
Block Job Events
- BLOCK_JOB_COMPLETED
- BLOCK_JOB_CANCELLED
- BLOCK_JOB_ERROR
- BLOCK_JOB_READY
Block Job Control
- block-job-set-speed
- Set maximum speed of block job
- block-job-cancel
- QEMU will emit BLOCK_JOB_CANCELLED
- block-job-pause
- block-job-resume
- block-job-complete
- Send after BLOCK_JOB_READY event
Questions?