Signed-off-by: John Snow <js...@redhat.com> --- docs/bitmaps.md | 253 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 docs/bitmaps.md
diff --git a/docs/bitmaps.md b/docs/bitmaps.md new file mode 100644 index 0000000..7cda146 --- /dev/null +++ b/docs/bitmaps.md @@ -0,0 +1,253 @@ +# Dirty Bitmaps + +* Dirty bitmaps can be created at any time and attached to any node +(not just complete drives.) + +## Dirty Bitmap Names + +* A dirty bitmap's name is unique to the node, but bitmaps attached to different +nodes can share the same name. + +## Bitmap Modes + +* A Bitmap can be "enabled" (tracking writes, the default) or "disabled" +(read-only, I/O is ignored.) + +* A Bitmap can be "frozen," which means that it is currently in-use by a backup +operation and cannot be deleted, enabled, disabled, renamed, written to, reset, +etc. + +## Basic QMP Usage + +### Supported Commands ### + +* block-dirty-bitmap-add +* block-dirty-bitmap-remove +* block-dirty-bitmap-enable +* block-dirty-bitmap-disable +* block-dirty-bitmap-clear + +### Creation + +* To create a new bitmap, enabled, on the drive with id=drive0: + +```json +{ "execute": "block-dirty-bitmap-add", + "arguments": { + "node": "drive0", + "name": "bitmap0" + } +} +``` + +* To create a new bitmap that tracks changes in 32KiB segments: + +```json +{ "execute": "block-dirty-bitmap-add", + "arguments": { + "node": "drive0", + "name": "bitmap0", + "granularity": "32768" + } +} +``` + +### Deletion + +* Can be performed on a disabled bitmap, but not a frozen one. + +* Because bitmaps are only unique to the node to which they are attached, +you must specify the node/drive name here, too. + +```json +{ "execute": "block-dirty-bitmap-remove", + "arguments": { + "node": "drive0", + "name": "bitmap0", + } +} +``` + +### Enable/Disable: + +* Not very useful in current cases, but potentially useful for debugging in the +future where we'd like to see what information changed only in a specific +time period: + +* To enable (which is, again, the default state after add) + +```json +{ "execute": "block-dirty-bitmap-enable", + "arguments": { + "node": "drive0", + "name": "bitmap0", + } +} +``` + +* To disable: + +```json +{ "execute": "block-dirty-bitmap-disable", + "arguments": { + "node": "drive0", + "name": "bitmap0", + } +} +``` + +### Resetting + +* Resetting a bitmap will clear all information it holds. +* An incremental backup created from an empty bitmap will copy no data, +as if nothing has changed. + +```json +{ "execute": "block-dirty-bitmap-clear", + "arguments": { + "node": "drive0", + "name": "bitmap0", + } +} +``` + +## Transactions + +### Justification +Bitmaps can be safely modified when the VM is paused or halted by using +the basic QMP commands. For instance, you might perform the following actions: + +1. Boot the VM in a paused state. +2. Create a full drive backup of drive0 +3. Create a new bitmap attached to drive0 +4. resume execution of the VM +5. Incremental backups are ready to be created. + +At this point, the bitmap and drive backup would be correctly in sync, +and incremental backups made from this point forward would be correctly aligned +to the full drive backup. + +This is not particularly useful if we decide we want to start incremental +backups after the VM has been running for a while, which will allow us to +perform actions like the following: + +1. Boot the VM and begin execution +2. Using transactions, perform the following operations: + * Create 'bitmap0' + * Create a full drive backup of drive0 +3. Incremental backups are now ready to be created. + +### Supported Bitmap Transactions + +* block-dirty-bitmap-add +* block-dirty-bitmap-enable +* block-dirty-bitmap-disable +* block-dirty-bitmap-clear + +The usages are identical to their respective QMP commands, but see below +for examples. + +### Example: New Incremental Backup + +As outlined in the justification, perhaps we want to create a new incremental +backup chain attached to a drive. + +```json +{ "execute": "transaction", + "arguments": { + "actions": [ + {"type": "block-dirty-bitmap-add", + "data": {"node": "drive0", "name": "bitmap0"} }, + {"type": "drive-backup", + "data": {"device": "drive0", "target": "/path/to/full_backup.img", + "sync": "full", "format": "qcow2"} } + ] + } +} +``` + +### Example: New Incremental Backup Anchor Point + +Maybe we just want to create a new full backup with an existing bitmap and +want to reset the bitmap to track the new chain. + +```json +{ "execute": "transaction", + "arguments": { + "actions": [ + {"type": "block-dirty-bitmap-clear", + "data": {"node": "drive0", "name": "bitmap0"} }, + {"type": "drive-backup", + "data": {"device": "drive0", "target": "/path/to/new_full_backup.img", + "sync": "full", "format": "qcow2"} } + ] + } +} +``` + +## Incremental Backups + +The star of the show. + +**Nota Bene!** Only incremental backups of entire drives are supported for now. +So despite the fact that you can attach a bitmap to any arbitrary node, they are +only currently useful when attached to the root node. This is because +drive-backup only supports drives/devices instead of arbitrary nodes. + +### Example: First Incremental Backup + +1. Create a full backup and sync it to the dirty bitmap, as in the transactional +examples above; or with the VM offline, manually create a full copy and then +create a new bitmap before the VM begins execution. + + * Let's assume the full backup is named 'full_backup.img.' + * Let's assume the bitmap you created is 'bitmap0' attached to 'drive0'. + +2. Create a destination image for the incremental backup that utilizes the +full backup as a backing image. + + * Let's assume it is named 'incremental.0.img' + +```sh +# qemu-img create -f qcow2 incremental.0.img -b full_backup.img -F qcow2 +``` + +3. Issue the incremental backup command: + +```json +{ "execute": "drive-backup", + "arguments": { + "device": "drive0", + "bitmap": "bitmap0", + "target": "incremental.0.img", + "format": "qcow2", + "sync": "dirty-bitmap", + "mode": "existing" + } +} +``` + +### Example: Second Incremental Backup + +1. Create a new destination image for the incremental backup that points to the +previous one, e.g.: 'incremental.1.img' + +```bash +# qemu-img create -f qcow2 incremental.1.img -b incremental.0.img -F qcow2 +``` + +2. Issue a new incremental backup command. The only difference here is that we +have changed the target image below. + +```json +{ "execute": "drive-backup", + "arguments": { + "device": "drive0", + "bitmap": "bitmap0", + "target": "incremental.1.img", + "format": "qcow2", + "sync": "dirty-bitmap", + "mode": "existing" + } +} +``` -- 1.9.3