17746cf8aSKashyap Chamarthy.. 290edef80SJohn Snow Copyright 2019 John Snow <jsnow@redhat.com> and Red Hat, Inc. 37746cf8aSKashyap Chamarthy All rights reserved. 47746cf8aSKashyap Chamarthy 57746cf8aSKashyap Chamarthy This file is licensed via The FreeBSD Documentation License, the full 67746cf8aSKashyap Chamarthy text of which is included at the end of this document. 77746cf8aSKashyap Chamarthy 87746cf8aSKashyap Chamarthy==================================== 97746cf8aSKashyap ChamarthyDirty Bitmaps and Incremental Backup 107746cf8aSKashyap Chamarthy==================================== 117746cf8aSKashyap Chamarthy 1290edef80SJohn SnowDirty Bitmaps are in-memory objects that track writes to block devices. They 1390edef80SJohn Snowcan be used in conjunction with various block job operations to perform 1490edef80SJohn Snowincremental or differential backup regimens. 157746cf8aSKashyap Chamarthy 1690edef80SJohn SnowThis document explains the conceptual mechanisms, as well as up-to-date, 1790edef80SJohn Snowcomplete and comprehensive documentation on the API to manipulate them. 1890edef80SJohn Snow(Hopefully, the "why", "what", and "how".) 1990edef80SJohn Snow 2090edef80SJohn SnowThe intended audience for this document is developers who are adding QEMU 2190edef80SJohn Snowbackup features to management applications, or power users who run and 2290edef80SJohn Snowadminister QEMU directly via QMP. 237746cf8aSKashyap Chamarthy 247746cf8aSKashyap Chamarthy.. contents:: 257746cf8aSKashyap Chamarthy 2690edef80SJohn SnowOverview 2790edef80SJohn Snow-------- 2890edef80SJohn Snow 2990edef80SJohn SnowBitmaps are bit vectors where each '1' bit in the vector indicates a modified 3090edef80SJohn Snow("dirty") segment of the corresponding block device. The size of the segment 3190edef80SJohn Snowthat is tracked is the granularity of the bitmap. If the granularity of a 3290edef80SJohn Snowbitmap is 64K, each '1' bit means that a 64K region as a whole may have 3390edef80SJohn Snowchanged in some way, possibly by as little as one byte. 3490edef80SJohn Snow 3590edef80SJohn SnowSmaller granularities mean more accurate tracking of modified disk data, but 3690edef80SJohn Snowrequires more computational overhead and larger bitmap sizes. Larger 3790edef80SJohn Snowgranularities mean smaller bitmap sizes, but less targeted backups. 3890edef80SJohn Snow 3990edef80SJohn SnowThe size of a bitmap (in bytes) can be computed as such: 4090edef80SJohn Snow ``size`` = ceil(ceil(``image_size`` / ``granularity``) / 8) 4190edef80SJohn Snow 4290edef80SJohn Snowe.g. the size of a 64KiB granularity bitmap on a 2TiB image is: 4390edef80SJohn Snow ``size`` = ((2147483648K / 64K) / 8) 4490edef80SJohn Snow = 4194304B = 4MiB. 4590edef80SJohn Snow 4690edef80SJohn SnowQEMU uses these bitmaps when making incremental backups to know which sections 4790edef80SJohn Snowof the file to copy out. They are not enabled by default and must be 4890edef80SJohn Snowexplicitly added in order to begin tracking writes. 4990edef80SJohn Snow 5090edef80SJohn SnowBitmaps can be created at any time and can be attached to any arbitrary block 5190edef80SJohn Snownode in the storage graph, but are most useful conceptually when attached to 5290edef80SJohn Snowthe root node attached to the guest's storage device model. 5390edef80SJohn Snow 5490edef80SJohn SnowThat is to say: It's likely most useful to track the guest's writes to disk, 5590edef80SJohn Snowbut you could theoretically track things like qcow2 metadata changes by 5690edef80SJohn Snowattaching the bitmap elsewhere in the storage graph. This is beyond the scope 5790edef80SJohn Snowof this document. 5890edef80SJohn Snow 5990edef80SJohn SnowQEMU supports persisting these bitmaps to disk via the qcow2 image format. 6090edef80SJohn SnowBitmaps which are stored or loaded in this way are called "persistent", 6190edef80SJohn Snowwhereas bitmaps that are not are called "transient". 6290edef80SJohn Snow 6390edef80SJohn SnowQEMU also supports the migration of both transient bitmaps (tracking any 6490edef80SJohn Snowarbitrary image format) or persistent bitmaps (qcow2) via live migration. 6590edef80SJohn Snow 6690edef80SJohn SnowSupported Image Formats 6790edef80SJohn Snow----------------------- 6890edef80SJohn Snow 6990edef80SJohn SnowQEMU supports all documented features below on the qcow2 image format. 7090edef80SJohn Snow 7190edef80SJohn SnowHowever, qcow2 is only strictly necessary for the persistence feature, which 7290edef80SJohn Snowwrites bitmap data to disk upon close. If persistence is not required for a 7390edef80SJohn Snowspecific use case, all bitmap features excepting persistence are available for 7490edef80SJohn Snowany arbitrary image format. 7590edef80SJohn Snow 7690edef80SJohn SnowFor example, Dirty Bitmaps can be combined with the 'raw' image format, but 7790edef80SJohn Snowany changes to the bitmap will be discarded upon exit. 7890edef80SJohn Snow 7990edef80SJohn Snow.. warning:: Transient bitmaps will not be saved on QEMU exit! Persistent 8090edef80SJohn Snow bitmaps are available only on qcow2 images. 8190edef80SJohn Snow 827746cf8aSKashyap ChamarthyDirty Bitmap Names 837746cf8aSKashyap Chamarthy------------------ 847746cf8aSKashyap Chamarthy 8590edef80SJohn SnowBitmap objects need a method to reference them in the API. All API-created and 8690edef80SJohn Snowmanaged bitmaps have a human-readable name chosen by the user at creation 8790edef80SJohn Snowtime. 887746cf8aSKashyap Chamarthy 8990edef80SJohn Snow- A bitmap's name is unique to the node, but bitmaps attached to different 9090edef80SJohn Snow nodes can share the same name. Therefore, all bitmaps are addressed via 9190edef80SJohn Snow their (node, name) pair. 927746cf8aSKashyap Chamarthy 9390edef80SJohn Snow- The name of a user-created bitmap cannot be empty (""). 947746cf8aSKashyap Chamarthy 9590edef80SJohn Snow- Transient bitmaps can have JSON unicode names that are effectively not 9690edef80SJohn Snow length limited. (QMP protocol may restrict messages to less than 64MiB.) 977746cf8aSKashyap Chamarthy 9890edef80SJohn Snow- Persistent storage formats may impose their own requirements on bitmap names 9990edef80SJohn Snow and namespaces. Presently, only qcow2 supports persistent bitmaps. See 10090edef80SJohn Snow docs/interop/qcow2.txt for more details on restrictions. Notably: 1017746cf8aSKashyap Chamarthy 10290edef80SJohn Snow - qcow2 bitmap names are limited to between 1 and 1023 bytes long. 10390edef80SJohn Snow 10490edef80SJohn Snow - No two bitmaps saved to the same qcow2 file may share the same name. 10590edef80SJohn Snow 10690edef80SJohn Snow- QEMU occasionally uses bitmaps for internal use which have no name. They are 10790edef80SJohn Snow hidden from API query calls, cannot be manipulated by the external API, are 10890edef80SJohn Snow never persistent, nor ever migrated. 10990edef80SJohn Snow 11090edef80SJohn SnowBitmap Status 11190edef80SJohn Snow------------- 11290edef80SJohn Snow 11390edef80SJohn SnowDirty Bitmap objects can be queried with the QMP command `query-block 11490edef80SJohn Snow<qemu-qmp-ref.html#index-query_002dblock>`_, and are visible via the 11590edef80SJohn Snow`BlockDirtyInfo <qemu-qmp-ref.html#index-BlockDirtyInfo>`_ QAPI structure. 11690edef80SJohn Snow 11790edef80SJohn SnowThis struct shows the name, granularity, and dirty byte count for each bitmap. 11890edef80SJohn SnowAdditionally, it shows several boolean status indicators: 11990edef80SJohn Snow 12090edef80SJohn Snow- ``recording``: This bitmap is recording writes. 12190edef80SJohn Snow- ``busy``: This bitmap is in-use by an operation. 12290edef80SJohn Snow- ``persistent``: This bitmap is a persistent type. 12390edef80SJohn Snow- ``inconsistent``: This bitmap is corrupted and cannot be used. 12490edef80SJohn Snow 12590edef80SJohn SnowThe ``+busy`` status prohibits you from deleting, clearing, or otherwise 12690edef80SJohn Snowmodifying a bitmap, and happens when the bitmap is being used for a backup 12790edef80SJohn Snowoperation or is in the process of being loaded from a migration. Many of the 12890edef80SJohn Snowcommands documented below will refuse to work on such bitmaps. 12990edef80SJohn Snow 13090edef80SJohn SnowThe ``+inconsistent`` status similarly prohibits almost all operations, 13190edef80SJohn Snownotably allowing only the ``block-dirty-bitmap-remove`` operation. 13290edef80SJohn Snow 13390edef80SJohn SnowThere is also a deprecated ``status`` field of type `DirtyBitmapStatus 13490edef80SJohn Snow<qemu-qmp-ref.html#index-DirtyBitmapStatus>`_. A bitmap historically had 13590edef80SJohn Snowfive visible states: 13690edef80SJohn Snow 13790edef80SJohn Snow #. ``Frozen``: This bitmap is currently in-use by an operation and is 13890edef80SJohn Snow immutable. It can't be deleted, renamed, reset, etc. 13990edef80SJohn Snow 14090edef80SJohn Snow (This is now ``+busy``.) 14190edef80SJohn Snow 14290edef80SJohn Snow #. ``Disabled``: This bitmap is not recording new writes. 14390edef80SJohn Snow 14490edef80SJohn Snow (This is now ``-recording -busy``.) 14590edef80SJohn Snow 14690edef80SJohn Snow #. ``Active``: This bitmap is recording new writes. 14790edef80SJohn Snow 14890edef80SJohn Snow (This is now ``+recording -busy``.) 14990edef80SJohn Snow 15090edef80SJohn Snow #. ``Locked``: This bitmap is in-use by an operation, and is immutable. 15190edef80SJohn Snow The difference from "Frozen" was primarily implementation details. 15290edef80SJohn Snow 15390edef80SJohn Snow (This is now ``+busy``.) 15490edef80SJohn Snow 15590edef80SJohn Snow #. ``Inconsistent``: This persistent bitmap was not saved to disk 15690edef80SJohn Snow correctly, and can no longer be used. It remains in memory to serve as 15790edef80SJohn Snow an indicator of failure. 15890edef80SJohn Snow 15990edef80SJohn Snow (This is now ``+inconsistent``.) 16090edef80SJohn Snow 16190edef80SJohn SnowThese states are directly replaced by the status indicators and should not be 16290edef80SJohn Snowused. The difference between ``Frozen`` and ``Locked`` is an implementation 16390edef80SJohn Snowdetail and should not be relevant to external users. 1647746cf8aSKashyap Chamarthy 1657746cf8aSKashyap ChamarthyBasic QMP Usage 1667746cf8aSKashyap Chamarthy--------------- 1677746cf8aSKashyap Chamarthy 16890edef80SJohn SnowThe primary interface to manipulating bitmap objects is via the QMP 1693bc8dc8aSMarkus Armbrusterinterface. If you are not familiar, see the :doc:`qmp-spec` for the 170*7cbdabb5SMarkus Armbrusterprotocol, and :doc:`qemu-qmp-ref` for a full reference of all QMP 171*7cbdabb5SMarkus Armbrustercommands. 17290edef80SJohn Snow 1737746cf8aSKashyap ChamarthySupported Commands 1747746cf8aSKashyap Chamarthy~~~~~~~~~~~~~~~~~~ 1757746cf8aSKashyap Chamarthy 17690edef80SJohn SnowThere are six primary bitmap-management API commands: 17790edef80SJohn Snow 1787746cf8aSKashyap Chamarthy- ``block-dirty-bitmap-add`` 1797746cf8aSKashyap Chamarthy- ``block-dirty-bitmap-remove`` 1807746cf8aSKashyap Chamarthy- ``block-dirty-bitmap-clear`` 18190edef80SJohn Snow- ``block-dirty-bitmap-disable`` 18290edef80SJohn Snow- ``block-dirty-bitmap-enable`` 18390edef80SJohn Snow- ``block-dirty-bitmap-merge`` 1847746cf8aSKashyap Chamarthy 18590edef80SJohn SnowAnd one related query command: 1867746cf8aSKashyap Chamarthy 18790edef80SJohn Snow- ``query-block`` 18890edef80SJohn Snow 18990edef80SJohn SnowCreation: block-dirty-bitmap-add 19090edef80SJohn Snow~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19190edef80SJohn Snow 19290edef80SJohn Snow`block-dirty-bitmap-add 19390edef80SJohn Snow<qemu-qmp-ref.html#index-block_002ddirty_002dbitmap_002dadd>`_: 19490edef80SJohn Snow 19590edef80SJohn SnowCreates a new bitmap that tracks writes to the specified node. granularity, 19690edef80SJohn Snowpersistence, and recording state can be adjusted at creation time. 19790edef80SJohn Snow 19890edef80SJohn Snow.. admonition:: Example 19990edef80SJohn Snow 20090edef80SJohn Snow to create a new, actively recording persistent bitmap: 2017746cf8aSKashyap Chamarthy 202a7786bfbSJohn Snow .. code-block:: QMP 2037746cf8aSKashyap Chamarthy 20490edef80SJohn Snow -> { "execute": "block-dirty-bitmap-add", 2057746cf8aSKashyap Chamarthy "arguments": { 2067746cf8aSKashyap Chamarthy "node": "drive0", 2077746cf8aSKashyap Chamarthy "name": "bitmap0", 20890edef80SJohn Snow "persistent": true, 2097746cf8aSKashyap Chamarthy } 2107746cf8aSKashyap Chamarthy } 2117746cf8aSKashyap Chamarthy 21290edef80SJohn Snow <- { "return": {} } 2137746cf8aSKashyap Chamarthy 21490edef80SJohn Snow- This bitmap will have a default granularity that matches the cluster size of 21590edef80SJohn Snow its associated drive, if available, clamped to between [4KiB, 64KiB]. The 21690edef80SJohn Snow current default for qcow2 is 64KiB. 2177746cf8aSKashyap Chamarthy 21890edef80SJohn Snow.. admonition:: Example 21990edef80SJohn Snow 22090edef80SJohn Snow To create a new, disabled (``-recording``), transient bitmap that tracks 22190edef80SJohn Snow changes in 32KiB segments: 22290edef80SJohn Snow 223a7786bfbSJohn Snow .. code-block:: QMP 22490edef80SJohn Snow 22590edef80SJohn Snow -> { "execute": "block-dirty-bitmap-add", 22690edef80SJohn Snow "arguments": { 22790edef80SJohn Snow "node": "drive0", 22890edef80SJohn Snow "name": "bitmap1", 22990edef80SJohn Snow "granularity": 32768, 23090edef80SJohn Snow "disabled": true 23190edef80SJohn Snow } 23290edef80SJohn Snow } 23390edef80SJohn Snow 23490edef80SJohn Snow <- { "return": {} } 23590edef80SJohn Snow 23690edef80SJohn SnowDeletion: block-dirty-bitmap-remove 23790edef80SJohn Snow~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23890edef80SJohn Snow 23990edef80SJohn Snow`block-dirty-bitmap-remove 24090edef80SJohn Snow<qemu-qmp-ref.html#index-block_002ddirty_002dbitmap_002dremove>`_: 24190edef80SJohn Snow 24290edef80SJohn SnowDeletes a bitmap. Bitmaps that are ``+busy`` cannot be removed. 24390edef80SJohn Snow 24490edef80SJohn Snow- Deleting a bitmap does not impact any other bitmaps attached to the same 24590edef80SJohn Snow node, nor does it affect any backups already created from this bitmap or 2467746cf8aSKashyap Chamarthy node. 2477746cf8aSKashyap Chamarthy 24890edef80SJohn Snow- Because bitmaps are only unique to the node to which they are attached, you 24990edef80SJohn Snow must specify the node/drive name here, too. 25090edef80SJohn Snow 25190edef80SJohn Snow- Deleting a persistent bitmap will remove it from the qcow2 file. 25290edef80SJohn Snow 25390edef80SJohn Snow.. admonition:: Example 25490edef80SJohn Snow 25590edef80SJohn Snow Remove a bitmap named ``bitmap0`` from node ``drive0``: 2567746cf8aSKashyap Chamarthy 257a7786bfbSJohn Snow .. code-block:: QMP 2587746cf8aSKashyap Chamarthy 25990edef80SJohn Snow -> { "execute": "block-dirty-bitmap-remove", 2607746cf8aSKashyap Chamarthy "arguments": { 2617746cf8aSKashyap Chamarthy "node": "drive0", 2627746cf8aSKashyap Chamarthy "name": "bitmap0" 2637746cf8aSKashyap Chamarthy } 2647746cf8aSKashyap Chamarthy } 2657746cf8aSKashyap Chamarthy 26690edef80SJohn Snow <- { "return": {} } 2677746cf8aSKashyap Chamarthy 26890edef80SJohn SnowResetting: block-dirty-bitmap-clear 26990edef80SJohn Snow~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2707746cf8aSKashyap Chamarthy 27190edef80SJohn Snow`block-dirty-bitmap-clear 27290edef80SJohn Snow<qemu-qmp-ref.html#index-block_002ddirty_002dbitmap_002dclear>`_: 27390edef80SJohn Snow 27490edef80SJohn SnowClears all dirty bits from a bitmap. ``+busy`` bitmaps cannot be cleared. 27590edef80SJohn Snow 27690edef80SJohn Snow- An incremental backup created from an empty bitmap will copy no data, as if 27790edef80SJohn Snow nothing has changed. 27890edef80SJohn Snow 27990edef80SJohn Snow.. admonition:: Example 28090edef80SJohn Snow 28190edef80SJohn Snow Clear all dirty bits from bitmap ``bitmap0`` on node ``drive0``: 2827746cf8aSKashyap Chamarthy 283a7786bfbSJohn Snow .. code-block:: QMP 2847746cf8aSKashyap Chamarthy 28590edef80SJohn Snow -> { "execute": "block-dirty-bitmap-clear", 2867746cf8aSKashyap Chamarthy "arguments": { 2877746cf8aSKashyap Chamarthy "node": "drive0", 2887746cf8aSKashyap Chamarthy "name": "bitmap0" 2897746cf8aSKashyap Chamarthy } 2907746cf8aSKashyap Chamarthy } 2917746cf8aSKashyap Chamarthy 29290edef80SJohn Snow <- { "return": {} } 29390edef80SJohn Snow 29490edef80SJohn SnowEnabling: block-dirty-bitmap-enable 29590edef80SJohn Snow~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 29690edef80SJohn Snow 29790edef80SJohn Snow`block-dirty-bitmap-enable 29890edef80SJohn Snow<qemu-qmp-ref.html#index-block_002ddirty_002dbitmap_002denable>`_: 29990edef80SJohn Snow 30090edef80SJohn Snow"Enables" a bitmap, setting the ``recording`` bit to true, causing writes to 30190edef80SJohn Snowbegin being recorded. ``+busy`` bitmaps cannot be enabled. 30290edef80SJohn Snow 30390edef80SJohn Snow- Bitmaps default to being enabled when created, unless configured otherwise. 30490edef80SJohn Snow 30590edef80SJohn Snow- Persistent enabled bitmaps will remember their ``+recording`` status on 30690edef80SJohn Snow load. 30790edef80SJohn Snow 30890edef80SJohn Snow.. admonition:: Example 30990edef80SJohn Snow 31090edef80SJohn Snow To set ``+recording`` on bitmap ``bitmap0`` on node ``drive0``: 31190edef80SJohn Snow 312a7786bfbSJohn Snow .. code-block:: QMP 31390edef80SJohn Snow 31490edef80SJohn Snow -> { "execute": "block-dirty-bitmap-enable", 31590edef80SJohn Snow "arguments": { 31690edef80SJohn Snow "node": "drive0", 31790edef80SJohn Snow "name": "bitmap0" 31890edef80SJohn Snow } 31990edef80SJohn Snow } 32090edef80SJohn Snow 32190edef80SJohn Snow <- { "return": {} } 32290edef80SJohn Snow 32390edef80SJohn SnowEnabling: block-dirty-bitmap-disable 32490edef80SJohn Snow~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 32590edef80SJohn Snow 32690edef80SJohn Snow`block-dirty-bitmap-disable 32790edef80SJohn Snow<qemu-qmp-ref.html#index-block_002ddirty_002dbitmap_002ddisable>`_: 32890edef80SJohn Snow 32990edef80SJohn Snow"Disables" a bitmap, setting the ``recording`` bit to false, causing further 33090edef80SJohn Snowwrites to begin being ignored. ``+busy`` bitmaps cannot be disabled. 33190edef80SJohn Snow 33290edef80SJohn Snow.. warning:: 33390edef80SJohn Snow 33490edef80SJohn Snow This is potentially dangerous: QEMU makes no effort to stop any writes if 33590edef80SJohn Snow there are disabled bitmaps on a node, and will not mark any disabled bitmaps 33690edef80SJohn Snow as ``+inconsistent`` if any such writes do happen. Backups made from such 33790edef80SJohn Snow bitmaps will not be able to be used to reconstruct a coherent image. 33890edef80SJohn Snow 33990edef80SJohn Snow- Disabling a bitmap may be useful for examining which sectors of a disk 34090edef80SJohn Snow changed during a specific time period, or for explicit management of 34190edef80SJohn Snow differential backup windows. 34290edef80SJohn Snow 34390edef80SJohn Snow- Persistent disabled bitmaps will remember their ``-recording`` status on 34490edef80SJohn Snow load. 34590edef80SJohn Snow 34690edef80SJohn Snow.. admonition:: Example 34790edef80SJohn Snow 34890edef80SJohn Snow To set ``-recording`` on bitmap ``bitmap0`` on node ``drive0``: 34990edef80SJohn Snow 350a7786bfbSJohn Snow .. code-block:: QMP 35190edef80SJohn Snow 35290edef80SJohn Snow -> { "execute": "block-dirty-bitmap-disable", 35390edef80SJohn Snow "arguments": { 35490edef80SJohn Snow "node": "drive0", 35590edef80SJohn Snow "name": "bitmap0" 35690edef80SJohn Snow } 35790edef80SJohn Snow } 35890edef80SJohn Snow 35990edef80SJohn Snow <- { "return": {} } 36090edef80SJohn Snow 36190edef80SJohn SnowMerging, Copying: block-dirty-bitmap-merge 36290edef80SJohn Snow~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 36390edef80SJohn Snow 36490edef80SJohn Snow`block-dirty-bitmap-merge 36590edef80SJohn Snow<qemu-qmp-ref.html#index-block_002ddirty_002dbitmap_002dmerge>`_: 36690edef80SJohn Snow 36790edef80SJohn SnowMerges one or more bitmaps into a target bitmap. For any segment that is dirty 36890edef80SJohn Snowin any one source bitmap, the target bitmap will mark that segment dirty. 36990edef80SJohn Snow 37090edef80SJohn Snow- Merge takes one or more bitmaps as a source and merges them together into a 37190edef80SJohn Snow single destination, such that any segment marked as dirty in any source 37290edef80SJohn Snow bitmap(s) will be marked dirty in the destination bitmap. 37390edef80SJohn Snow 37490edef80SJohn Snow- Merge does not create the destination bitmap if it does not exist. A blank 37590edef80SJohn Snow bitmap can be created beforehand to achieve the same effect. 37690edef80SJohn Snow 37790edef80SJohn Snow- The destination is not cleared prior to merge, so subsequent merge 37890edef80SJohn Snow operations will continue to cumulatively mark more segments as dirty. 37990edef80SJohn Snow 38090edef80SJohn Snow- If the merge operation should fail, the destination bitmap is guaranteed to 38190edef80SJohn Snow be unmodified. The operation may fail if the source or destination bitmaps 38290edef80SJohn Snow are busy, or have different granularities. 38390edef80SJohn Snow 38490edef80SJohn Snow- Bitmaps can only be merged on the same node. There is only one "node" 38590edef80SJohn Snow argument, so all bitmaps must be attached to that same node. 38690edef80SJohn Snow 38790edef80SJohn Snow- Copy can be achieved by merging from a single source to an empty 38890edef80SJohn Snow destination. 38990edef80SJohn Snow 39090edef80SJohn Snow.. admonition:: Example 39190edef80SJohn Snow 39290edef80SJohn Snow Merge the data from ``bitmap0`` into the bitmap ``new_bitmap`` on node 39390edef80SJohn Snow ``drive0``. If ``new_bitmap`` was empty prior to this command, this achieves 39490edef80SJohn Snow a copy. 39590edef80SJohn Snow 396a7786bfbSJohn Snow .. code-block:: QMP 39790edef80SJohn Snow 39890edef80SJohn Snow -> { "execute": "block-dirty-bitmap-merge", 39990edef80SJohn Snow "arguments": { 40090edef80SJohn Snow "node": "drive0", 40190edef80SJohn Snow "target": "new_bitmap", 402575e6226SJohn Snow "bitmaps": [ "bitmap0" ] 40390edef80SJohn Snow } 40490edef80SJohn Snow } 40590edef80SJohn Snow 40690edef80SJohn Snow <- { "return": {} } 40790edef80SJohn Snow 40890edef80SJohn SnowQuerying: query-block 40990edef80SJohn Snow~~~~~~~~~~~~~~~~~~~~~ 41090edef80SJohn Snow 41190edef80SJohn Snow`query-block 41290edef80SJohn Snow<qemu-qmp-ref.html#index-query_002dblock>`_: 41390edef80SJohn Snow 41490edef80SJohn SnowNot strictly a bitmaps command, but will return information about any bitmaps 41590edef80SJohn Snowattached to nodes serving as the root for guest devices. 41690edef80SJohn Snow 41790edef80SJohn Snow- The "inconsistent" bit will not appear when it is false, appearing only when 41890edef80SJohn Snow the value is true to indicate there is a problem. 41990edef80SJohn Snow 42090edef80SJohn Snow.. admonition:: Example 42190edef80SJohn Snow 42290edef80SJohn Snow Query the block sub-system of QEMU. The following json has trimmed irrelevant 42390edef80SJohn Snow keys from the response to highlight only the bitmap-relevant portions of the 42490edef80SJohn Snow API. This result highlights a bitmap ``bitmap0`` attached to the root node of 42590edef80SJohn Snow device ``drive0``. 42690edef80SJohn Snow 427a7786bfbSJohn Snow .. code-block:: QMP 42890edef80SJohn Snow 42990edef80SJohn Snow -> { 43090edef80SJohn Snow "execute": "query-block", 43190edef80SJohn Snow "arguments": {} 43290edef80SJohn Snow } 43390edef80SJohn Snow 43490edef80SJohn Snow <- { 43590edef80SJohn Snow "return": [ { 43690edef80SJohn Snow "dirty-bitmaps": [ { 43790edef80SJohn Snow "status": "active", 43890edef80SJohn Snow "count": 0, 43990edef80SJohn Snow "busy": false, 44090edef80SJohn Snow "name": "bitmap0", 44190edef80SJohn Snow "persistent": false, 44290edef80SJohn Snow "recording": true, 44390edef80SJohn Snow "granularity": 65536 44490edef80SJohn Snow } ], 44590edef80SJohn Snow "device": "drive0", 44690edef80SJohn Snow } ] 44790edef80SJohn Snow } 44890edef80SJohn Snow 44990edef80SJohn SnowBitmap Persistence 45090edef80SJohn Snow------------------ 45190edef80SJohn Snow 45290edef80SJohn SnowAs outlined in `Supported Image Formats`_, QEMU can persist bitmaps to qcow2 45390edef80SJohn Snowfiles. Demonstrated in `Creation: block-dirty-bitmap-add`_, passing 45490edef80SJohn Snow``persistent: true`` to ``block-dirty-bitmap-add`` will persist that bitmap to 45590edef80SJohn Snowdisk. 45690edef80SJohn Snow 45790edef80SJohn SnowPersistent bitmaps will be automatically loaded into memory upon load, and 45890edef80SJohn Snowwill be written back to disk upon close. Their usage should be mostly 45990edef80SJohn Snowtransparent. 46090edef80SJohn Snow 46190edef80SJohn SnowHowever, if QEMU does not get a chance to close the file cleanly, the bitmap 46290edef80SJohn Snowwill be marked as ``+inconsistent`` at next load and considered unsafe to use 46390edef80SJohn Snowfor any operation. At this point, the only valid operation on such bitmaps is 46490edef80SJohn Snow``block-dirty-bitmap-remove``. 46590edef80SJohn Snow 46690edef80SJohn SnowLosing a bitmap in this way does not invalidate any existing backups that have 46790edef80SJohn Snowbeen made from this bitmap, but no further backups will be able to be issued 46890edef80SJohn Snowfor this chain. 46990edef80SJohn Snow 4707746cf8aSKashyap ChamarthyTransactions 4717746cf8aSKashyap Chamarthy------------ 4727746cf8aSKashyap Chamarthy 47390edef80SJohn SnowTransactions are a QMP feature that allows you to submit multiple QMP commands 47490edef80SJohn Snowat once, being guaranteed that they will all succeed or fail atomically, 47590edef80SJohn Snowtogether. The interaction of bitmaps and transactions are demonstrated below. 47690edef80SJohn Snow 47790edef80SJohn SnowSee `transaction <qemu-qmp.ref.html#index-transaction>`_ in the QMP reference 47890edef80SJohn Snowfor more details. 47990edef80SJohn Snow 4807746cf8aSKashyap ChamarthyJustification 4817746cf8aSKashyap Chamarthy~~~~~~~~~~~~~ 4827746cf8aSKashyap Chamarthy 48390edef80SJohn SnowBitmaps can generally be modified at any time, but certain operations often 48490edef80SJohn Snowonly make sense when paired directly with other commands. When a VM is paused, 48590edef80SJohn Snowit's easy to ensure that no guest writes occur between individual QMP 48690edef80SJohn Snowcommands. When a VM is running, this is difficult to accomplish with 48776ca4b58Szhaolichangindividual QMP commands that may allow guest writes to occur between each 48890edef80SJohn Snowcommand. 4897746cf8aSKashyap Chamarthy 49090edef80SJohn SnowFor example, using only individual QMP commands, we could: 4917746cf8aSKashyap Chamarthy 49290edef80SJohn Snow#. Boot the VM in a paused state. 49390edef80SJohn Snow#. Create a full drive backup of drive0. 49490edef80SJohn Snow#. Create a new bitmap attached to drive0, confident that nothing has been 49590edef80SJohn Snow written to drive0 in the meantime. 49690edef80SJohn Snow#. Resume execution of the VM. 49790edef80SJohn Snow#. At a later point, issue incremental backups from ``bitmap0``. 4987746cf8aSKashyap Chamarthy 49990edef80SJohn SnowAt this point, the bitmap and drive backup would be correctly in sync, and 50090edef80SJohn Snowincremental backups made from this point forward would be correctly aligned to 50190edef80SJohn Snowthe full drive backup. 5027746cf8aSKashyap Chamarthy 50390edef80SJohn SnowThis is not particularly useful if we decide we want to start incremental 50490edef80SJohn Snowbackups after the VM has been running for a while, for which we would want to 50590edef80SJohn Snowperform actions such as the following: 50690edef80SJohn Snow 50790edef80SJohn Snow#. Boot the VM and begin execution. 50890edef80SJohn Snow#. Using a single transaction, perform the following operations: 5097746cf8aSKashyap Chamarthy 5107746cf8aSKashyap Chamarthy - Create ``bitmap0``. 5117746cf8aSKashyap Chamarthy - Create a full drive backup of ``drive0``. 5127746cf8aSKashyap Chamarthy 51390edef80SJohn Snow#. At a later point, issue incremental backups from ``bitmap0``. 51490edef80SJohn Snow 51590edef80SJohn Snow.. note:: As a consideration, if ``bitmap0`` is created prior to the full 51690edef80SJohn Snow drive backup, incremental backups can still be authored from this 51790edef80SJohn Snow bitmap, but they will copy extra segments reflecting writes that 51890edef80SJohn Snow occurred prior to the backup operation. Transactions allow us to 51990edef80SJohn Snow narrow critical points in time to reduce waste, or, in the other 52090edef80SJohn Snow direction, to ensure that no segments are omitted. 5217746cf8aSKashyap Chamarthy 5227746cf8aSKashyap ChamarthySupported Bitmap Transactions 5237746cf8aSKashyap Chamarthy~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5247746cf8aSKashyap Chamarthy 5257746cf8aSKashyap Chamarthy- ``block-dirty-bitmap-add`` 5267746cf8aSKashyap Chamarthy- ``block-dirty-bitmap-clear`` 52790edef80SJohn Snow- ``block-dirty-bitmap-enable`` 52890edef80SJohn Snow- ``block-dirty-bitmap-disable`` 52990edef80SJohn Snow- ``block-dirty-bitmap-merge`` 5307746cf8aSKashyap Chamarthy 53190edef80SJohn SnowThe usages for these commands are identical to their respective QMP commands, 53290edef80SJohn Snowbut see the sections below for concrete examples. 5337746cf8aSKashyap Chamarthy 53490edef80SJohn SnowIncremental Backups - Push Model 53590edef80SJohn Snow-------------------------------- 5367746cf8aSKashyap Chamarthy 53790edef80SJohn SnowIncremental backups are simply partial disk images that can be combined with 53890edef80SJohn Snowother partial disk images on top of a base image to reconstruct a full backup 53990edef80SJohn Snowfrom the point in time at which the incremental backup was issued. 5407746cf8aSKashyap Chamarthy 54190edef80SJohn SnowThe "Push Model" here references the fact that QEMU is "pushing" the modified 54224d6cc1fSVladimir Sementsov-Ogievskiyblocks out to a destination. We will be using the `blockdev-backup 54324d6cc1fSVladimir Sementsov-Ogievskiy<qemu-qmp-ref.html#index-blockdev_002dbackup>`_ QMP command to create both 54490edef80SJohn Snowfull and incremental backups. 5457746cf8aSKashyap Chamarthy 54624d6cc1fSVladimir Sementsov-OgievskiyThe command is a background job, which has its own QMP API for querying and 54790edef80SJohn Snowmanagement documented in `Background jobs 54890edef80SJohn Snow<qemu-qmp-ref.html#Background-jobs>`_. 5497746cf8aSKashyap Chamarthy 5507746cf8aSKashyap ChamarthyExample: New Incremental Backup Anchor Point 5517746cf8aSKashyap Chamarthy~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5527746cf8aSKashyap Chamarthy 55390edef80SJohn SnowAs outlined in the Transactions - `Justification`_ section, perhaps we want to 55490edef80SJohn Snowcreate a new incremental backup chain attached to a drive. 55590edef80SJohn Snow 55690edef80SJohn SnowThis example creates a new, full backup of "drive0" and accompanies it with a 55790edef80SJohn Snownew, empty bitmap that records writes from this point in time forward. 55890edef80SJohn Snow 55924d6cc1fSVladimir Sementsov-OgievskiyThe target can be created with the help of `blockdev-add 56024d6cc1fSVladimir Sementsov-Ogievskiy<qemu-qmp-ref.html#index-blockdev_002dadd>`_ or `blockdev-create 56124d6cc1fSVladimir Sementsov-Ogievskiy<qemu-qmp-ref.html#index-blockdev_002dcreate>`_ command. 56224d6cc1fSVladimir Sementsov-Ogievskiy 56390edef80SJohn Snow.. note:: Any new writes that happen after this command is issued, even while 56490edef80SJohn Snow the backup job runs, will be written locally and not to the backup 56590edef80SJohn Snow destination. These writes will be recorded in the bitmap 56690edef80SJohn Snow accordingly. 5677746cf8aSKashyap Chamarthy 568a7786bfbSJohn Snow.. code-block:: QMP 5697746cf8aSKashyap Chamarthy 57090edef80SJohn Snow -> { 57190edef80SJohn Snow "execute": "transaction", 5727746cf8aSKashyap Chamarthy "arguments": { 5737746cf8aSKashyap Chamarthy "actions": [ 57490edef80SJohn Snow { 57590edef80SJohn Snow "type": "block-dirty-bitmap-add", 57690edef80SJohn Snow "data": { 57790edef80SJohn Snow "node": "drive0", 57890edef80SJohn Snow "name": "bitmap0" 57990edef80SJohn Snow } 58090edef80SJohn Snow }, 58190edef80SJohn Snow { 58224d6cc1fSVladimir Sementsov-Ogievskiy "type": "blockdev-backup", 58390edef80SJohn Snow "data": { 58490edef80SJohn Snow "device": "drive0", 58524d6cc1fSVladimir Sementsov-Ogievskiy "target": "target0", 58624d6cc1fSVladimir Sementsov-Ogievskiy "sync": "full" 58790edef80SJohn Snow } 58890edef80SJohn Snow } 5897746cf8aSKashyap Chamarthy ] 5907746cf8aSKashyap Chamarthy } 5917746cf8aSKashyap Chamarthy } 5927746cf8aSKashyap Chamarthy 59390edef80SJohn Snow <- { "return": {} } 5947746cf8aSKashyap Chamarthy 59590edef80SJohn Snow <- { 59690edef80SJohn Snow "timestamp": { 59790edef80SJohn Snow "seconds": 1555436945, 59890edef80SJohn Snow "microseconds": 179620 59990edef80SJohn Snow }, 60090edef80SJohn Snow "data": { 60190edef80SJohn Snow "status": "created", 60290edef80SJohn Snow "id": "drive0" 60390edef80SJohn Snow }, 60490edef80SJohn Snow "event": "JOB_STATUS_CHANGE" 60590edef80SJohn Snow } 6067746cf8aSKashyap Chamarthy 60790edef80SJohn Snow ... 60890edef80SJohn Snow 60990edef80SJohn Snow <- { 61090edef80SJohn Snow "timestamp": {...}, 61190edef80SJohn Snow "data": { 61290edef80SJohn Snow "device": "drive0", 61390edef80SJohn Snow "type": "backup", 61490edef80SJohn Snow "speed": 0, 61590edef80SJohn Snow "len": 68719476736, 61690edef80SJohn Snow "offset": 68719476736 61790edef80SJohn Snow }, 61890edef80SJohn Snow "event": "BLOCK_JOB_COMPLETED" 61990edef80SJohn Snow } 62090edef80SJohn Snow 62190edef80SJohn Snow <- { 62290edef80SJohn Snow "timestamp": {...}, 62390edef80SJohn Snow "data": { 62490edef80SJohn Snow "status": "concluded", 62590edef80SJohn Snow "id": "drive0" 62690edef80SJohn Snow }, 62790edef80SJohn Snow "event": "JOB_STATUS_CHANGE" 62890edef80SJohn Snow } 62990edef80SJohn Snow 63090edef80SJohn Snow <- { 63190edef80SJohn Snow "timestamp": {...}, 63290edef80SJohn Snow "data": { 63390edef80SJohn Snow "status": "null", 63490edef80SJohn Snow "id": "drive0" 63590edef80SJohn Snow }, 63690edef80SJohn Snow "event": "JOB_STATUS_CHANGE" 63790edef80SJohn Snow } 63890edef80SJohn Snow 63990edef80SJohn SnowA full explanation of the job transition semantics and the JOB_STATUS_CHANGE 64090edef80SJohn Snowevent are beyond the scope of this document and will be omitted in all 64190edef80SJohn Snowsubsequent examples; above, several more events have been omitted for brevity. 64290edef80SJohn Snow 64390edef80SJohn Snow.. note:: Subsequent examples will omit all events except BLOCK_JOB_COMPLETED 64490edef80SJohn Snow except where necessary to illustrate workflow differences. 64590edef80SJohn Snow 64690edef80SJohn Snow Omitted events and json objects will be represented by ellipses: 64790edef80SJohn Snow ``...`` 64890edef80SJohn Snow 64990edef80SJohn SnowExample: Resetting an Incremental Backup Anchor Point 65090edef80SJohn Snow~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 65190edef80SJohn Snow 65290edef80SJohn SnowIf we want to start a new backup chain with an existing bitmap, we can also 65390edef80SJohn Snowuse a transaction to reset the bitmap while making a new full backup: 65490edef80SJohn Snow 655a7786bfbSJohn Snow.. code-block:: QMP 65690edef80SJohn Snow 65790edef80SJohn Snow -> { 65890edef80SJohn Snow "execute": "transaction", 65990edef80SJohn Snow "arguments": { 66090edef80SJohn Snow "actions": [ 66190edef80SJohn Snow { 66290edef80SJohn Snow "type": "block-dirty-bitmap-clear", 66390edef80SJohn Snow "data": { 66490edef80SJohn Snow "node": "drive0", 66590edef80SJohn Snow "name": "bitmap0" 66690edef80SJohn Snow } 66790edef80SJohn Snow }, 66890edef80SJohn Snow { 66924d6cc1fSVladimir Sementsov-Ogievskiy "type": "blockdev-backup", 67090edef80SJohn Snow "data": { 67190edef80SJohn Snow "device": "drive0", 67224d6cc1fSVladimir Sementsov-Ogievskiy "target": "target0", 67324d6cc1fSVladimir Sementsov-Ogievskiy "sync": "full" 67490edef80SJohn Snow } 67590edef80SJohn Snow } 67690edef80SJohn Snow ] 67790edef80SJohn Snow } 67890edef80SJohn Snow } 67990edef80SJohn Snow 68090edef80SJohn Snow <- { "return": {} } 68190edef80SJohn Snow 68290edef80SJohn Snow ... 68390edef80SJohn Snow 68490edef80SJohn Snow <- { 68590edef80SJohn Snow "timestamp": {...}, 68690edef80SJohn Snow "data": { 68790edef80SJohn Snow "device": "drive0", 68890edef80SJohn Snow "type": "backup", 68990edef80SJohn Snow "speed": 0, 69090edef80SJohn Snow "len": 68719476736, 69190edef80SJohn Snow "offset": 68719476736 69290edef80SJohn Snow }, 69390edef80SJohn Snow "event": "BLOCK_JOB_COMPLETED" 69490edef80SJohn Snow } 69590edef80SJohn Snow 69690edef80SJohn Snow ... 69790edef80SJohn Snow 69890edef80SJohn SnowThe result of this example is identical to the first, but we clear an existing 69990edef80SJohn Snowbitmap instead of adding a new one. 70090edef80SJohn Snow 70190edef80SJohn Snow.. tip:: In both of these examples, "bitmap0" is tied conceptually to the 70290edef80SJohn Snow creation of new, full backups. This relationship is not saved or 70390edef80SJohn Snow remembered by QEMU; it is up to the operator or management layer to 70490edef80SJohn Snow remember which bitmaps are associated with which backups. 7057746cf8aSKashyap Chamarthy 7067746cf8aSKashyap ChamarthyExample: First Incremental Backup 7077746cf8aSKashyap Chamarthy~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7087746cf8aSKashyap Chamarthy 70990edef80SJohn Snow#. Create a full backup and sync it to a dirty bitmap using any method: 7107746cf8aSKashyap Chamarthy 71190edef80SJohn Snow - Either of the two live backup method demonstrated above, 71290edef80SJohn Snow - Using QMP commands with the VM paused as in the `Justification`_ section, 71390edef80SJohn Snow or 71490edef80SJohn Snow - With the VM offline, manually copy the image and start the VM in a paused 71590edef80SJohn Snow state, careful to add a new bitmap before the VM begins execution. 7167746cf8aSKashyap Chamarthy 71790edef80SJohn Snow Whichever method is chosen, let's assume that at the end of this step: 7187746cf8aSKashyap Chamarthy 71990edef80SJohn Snow - The full backup is named ``drive0.full.qcow2``. 72090edef80SJohn Snow - The bitmap we created is named ``bitmap0``, attached to ``drive0``. 72190edef80SJohn Snow 72290edef80SJohn Snow#. Create a destination image for the incremental backup that utilizes the 72390edef80SJohn Snow full backup as a backing image. 72490edef80SJohn Snow 72590edef80SJohn Snow - Let's assume the new incremental image is named ``drive0.inc0.qcow2``: 7267746cf8aSKashyap Chamarthy 7277746cf8aSKashyap Chamarthy .. code:: bash 7287746cf8aSKashyap Chamarthy 72990edef80SJohn Snow $ qemu-img create -f qcow2 drive0.inc0.qcow2 \ 73090edef80SJohn Snow -b drive0.full.qcow2 -F qcow2 7317746cf8aSKashyap Chamarthy 73224d6cc1fSVladimir Sementsov-Ogievskiy#. Add target block node: 73324d6cc1fSVladimir Sementsov-Ogievskiy 73424d6cc1fSVladimir Sementsov-Ogievskiy .. code-block:: QMP 73524d6cc1fSVladimir Sementsov-Ogievskiy 73624d6cc1fSVladimir Sementsov-Ogievskiy -> { 73724d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-add", 73824d6cc1fSVladimir Sementsov-Ogievskiy "arguments": { 73924d6cc1fSVladimir Sementsov-Ogievskiy "node-name": "target0", 74024d6cc1fSVladimir Sementsov-Ogievskiy "driver": "qcow2", 74124d6cc1fSVladimir Sementsov-Ogievskiy "file": { 74224d6cc1fSVladimir Sementsov-Ogievskiy "driver": "file", 74324d6cc1fSVladimir Sementsov-Ogievskiy "filename": "drive0.inc0.qcow2" 74424d6cc1fSVladimir Sementsov-Ogievskiy } 74524d6cc1fSVladimir Sementsov-Ogievskiy } 74624d6cc1fSVladimir Sementsov-Ogievskiy } 74724d6cc1fSVladimir Sementsov-Ogievskiy 74824d6cc1fSVladimir Sementsov-Ogievskiy <- { "return": {} } 74924d6cc1fSVladimir Sementsov-Ogievskiy 75090edef80SJohn Snow#. Issue an incremental backup command: 7517746cf8aSKashyap Chamarthy 752a7786bfbSJohn Snow .. code-block:: QMP 7537746cf8aSKashyap Chamarthy 75490edef80SJohn Snow -> { 75524d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-backup", 7567746cf8aSKashyap Chamarthy "arguments": { 7577746cf8aSKashyap Chamarthy "device": "drive0", 7587746cf8aSKashyap Chamarthy "bitmap": "bitmap0", 75924d6cc1fSVladimir Sementsov-Ogievskiy "target": "target0", 76024d6cc1fSVladimir Sementsov-Ogievskiy "sync": "incremental" 7617746cf8aSKashyap Chamarthy } 7627746cf8aSKashyap Chamarthy } 7637746cf8aSKashyap Chamarthy 76490edef80SJohn Snow <- { "return": {} } 76590edef80SJohn Snow 76690edef80SJohn Snow ... 76790edef80SJohn Snow 76890edef80SJohn Snow <- { 76990edef80SJohn Snow "timestamp": {...}, 77090edef80SJohn Snow "data": { 77190edef80SJohn Snow "device": "drive0", 77290edef80SJohn Snow "type": "backup", 77390edef80SJohn Snow "speed": 0, 77490edef80SJohn Snow "len": 68719476736, 77590edef80SJohn Snow "offset": 68719476736 77690edef80SJohn Snow }, 77790edef80SJohn Snow "event": "BLOCK_JOB_COMPLETED" 77890edef80SJohn Snow } 77990edef80SJohn Snow 78090edef80SJohn Snow ... 78190edef80SJohn Snow 78290edef80SJohn SnowThis copies any blocks modified since the full backup was created into the 78390edef80SJohn Snow``drive0.inc0.qcow2`` file. During the operation, ``bitmap0`` is marked 78490edef80SJohn Snow``+busy``. If the operation is successful, ``bitmap0`` will be cleared to 78590edef80SJohn Snowreflect the "incremental" backup regimen, which only copies out new changes 78690edef80SJohn Snowfrom each incremental backup. 78790edef80SJohn Snow 78890edef80SJohn Snow.. note:: Any new writes that occur after the backup operation starts do not 78990edef80SJohn Snow get copied to the destination. The backup's "point in time" is when 79090edef80SJohn Snow the backup starts, not when it ends. These writes are recorded in a 79190edef80SJohn Snow special bitmap that gets re-added to bitmap0 when the backup ends so 79290edef80SJohn Snow that the next incremental backup can copy them out. 79390edef80SJohn Snow 7947746cf8aSKashyap ChamarthyExample: Second Incremental Backup 7957746cf8aSKashyap Chamarthy~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7967746cf8aSKashyap Chamarthy 79790edef80SJohn Snow#. Create a new destination image for the incremental backup that points to 79890edef80SJohn Snow the previous one, e.g.: ``drive0.inc1.qcow2`` 7997746cf8aSKashyap Chamarthy 8007746cf8aSKashyap Chamarthy .. code:: bash 8017746cf8aSKashyap Chamarthy 80290edef80SJohn Snow $ qemu-img create -f qcow2 drive0.inc1.qcow2 \ 80390edef80SJohn Snow -b drive0.inc0.qcow2 -F qcow2 8047746cf8aSKashyap Chamarthy 80524d6cc1fSVladimir Sementsov-Ogievskiy#. Add target block node: 80624d6cc1fSVladimir Sementsov-Ogievskiy 80724d6cc1fSVladimir Sementsov-Ogievskiy .. code-block:: QMP 80824d6cc1fSVladimir Sementsov-Ogievskiy 80924d6cc1fSVladimir Sementsov-Ogievskiy -> { 81024d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-add", 81124d6cc1fSVladimir Sementsov-Ogievskiy "arguments": { 81224d6cc1fSVladimir Sementsov-Ogievskiy "node-name": "target0", 81324d6cc1fSVladimir Sementsov-Ogievskiy "driver": "qcow2", 81424d6cc1fSVladimir Sementsov-Ogievskiy "file": { 81524d6cc1fSVladimir Sementsov-Ogievskiy "driver": "file", 81624d6cc1fSVladimir Sementsov-Ogievskiy "filename": "drive0.inc1.qcow2" 81724d6cc1fSVladimir Sementsov-Ogievskiy } 81824d6cc1fSVladimir Sementsov-Ogievskiy } 81924d6cc1fSVladimir Sementsov-Ogievskiy } 82024d6cc1fSVladimir Sementsov-Ogievskiy 82124d6cc1fSVladimir Sementsov-Ogievskiy <- { "return": {} } 82224d6cc1fSVladimir Sementsov-Ogievskiy 82390edef80SJohn Snow#. Issue a new incremental backup command. The only difference here is that we 82490edef80SJohn Snow have changed the target image below. 8257746cf8aSKashyap Chamarthy 826a7786bfbSJohn Snow .. code-block:: QMP 8277746cf8aSKashyap Chamarthy 82890edef80SJohn Snow -> { 82924d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-backup", 8307746cf8aSKashyap Chamarthy "arguments": { 8317746cf8aSKashyap Chamarthy "device": "drive0", 8327746cf8aSKashyap Chamarthy "bitmap": "bitmap0", 83324d6cc1fSVladimir Sementsov-Ogievskiy "target": "target0", 83424d6cc1fSVladimir Sementsov-Ogievskiy "sync": "incremental" 8357746cf8aSKashyap Chamarthy } 8367746cf8aSKashyap Chamarthy } 8377746cf8aSKashyap Chamarthy 83890edef80SJohn Snow <- { "return": {} } 8397746cf8aSKashyap Chamarthy 84090edef80SJohn Snow ... 8417746cf8aSKashyap Chamarthy 84290edef80SJohn Snow <- { 84390edef80SJohn Snow "timestamp": {...}, 84490edef80SJohn Snow "data": { 84590edef80SJohn Snow "device": "drive0", 84690edef80SJohn Snow "type": "backup", 84790edef80SJohn Snow "speed": 0, 84890edef80SJohn Snow "len": 68719476736, 84990edef80SJohn Snow "offset": 68719476736 85090edef80SJohn Snow }, 85190edef80SJohn Snow "event": "BLOCK_JOB_COMPLETED" 85290edef80SJohn Snow } 8537746cf8aSKashyap Chamarthy 85490edef80SJohn Snow ... 8557746cf8aSKashyap Chamarthy 85690edef80SJohn SnowBecause the first incremental backup from the previous example completed 85790edef80SJohn Snowsuccessfully, ``bitmap0`` was synchronized with ``drive0.inc0.qcow2``. Here, 85890edef80SJohn Snowwe use ``bitmap0`` again to create a new incremental backup that targets the 85990edef80SJohn Snowprevious one, creating a chain of three images: 8607746cf8aSKashyap Chamarthy 86190edef80SJohn Snow.. admonition:: Diagram 8627746cf8aSKashyap Chamarthy 86390edef80SJohn Snow .. code:: text 86490edef80SJohn Snow 86590edef80SJohn Snow +-------------------+ +-------------------+ +-------------------+ 86690edef80SJohn Snow | drive0.full.qcow2 |<--| drive0.inc0.qcow2 |<--| drive0.inc1.qcow2 | 86790edef80SJohn Snow +-------------------+ +-------------------+ +-------------------+ 86890edef80SJohn Snow 86990edef80SJohn SnowEach new incremental backup re-synchronizes the bitmap to the latest backup 87090edef80SJohn Snowauthored, allowing a user to continue to "consume" it to create new backups on 87190edef80SJohn Snowtop of an existing chain. 87290edef80SJohn Snow 87390edef80SJohn SnowIn the above diagram, neither drive0.inc1.qcow2 nor drive0.inc0.qcow2 are 87490edef80SJohn Snowcomplete images by themselves, but rely on their backing chain to reconstruct 87590edef80SJohn Snowa full image. The dependency terminates with each full backup. 87690edef80SJohn Snow 87790edef80SJohn SnowEach backup in this chain remains independent, and is unchanged by new entries 87890edef80SJohn Snowmade later in the chain. For instance, drive0.inc0.qcow2 remains a perfectly 87990edef80SJohn Snowvalid backup of the disk as it was when that backup was issued. 88090edef80SJohn Snow 88190edef80SJohn SnowExample: Incremental Push Backups without Backing Files 88290edef80SJohn Snow~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 88390edef80SJohn Snow 88490edef80SJohn SnowBackup images are best kept off-site, so we often will not have the preceding 88590edef80SJohn Snowbackups in a chain available to link against. This is not a problem at backup 88690edef80SJohn Snowtime; we simply do not set the backing image when creating the destination 88790edef80SJohn Snowimage: 88890edef80SJohn Snow 88990edef80SJohn Snow#. Create a new destination image with no backing file set. We will need to 89090edef80SJohn Snow specify the size of the base image, because the backing file isn't 89190edef80SJohn Snow available for QEMU to use to determine it. 8927746cf8aSKashyap Chamarthy 8937746cf8aSKashyap Chamarthy .. code:: bash 8947746cf8aSKashyap Chamarthy 89590edef80SJohn Snow $ qemu-img create -f qcow2 drive0.inc2.qcow2 64G 8967746cf8aSKashyap Chamarthy 89790edef80SJohn Snow .. note:: Alternatively, you can omit ``mode: "existing"`` from the push 89890edef80SJohn Snow backup commands to have QEMU create an image without a backing 89990edef80SJohn Snow file for you, but you lose control over format options like 90090edef80SJohn Snow compatibility and preallocation presets. 90190edef80SJohn Snow 90224d6cc1fSVladimir Sementsov-Ogievskiy#. Add target block node: 90324d6cc1fSVladimir Sementsov-Ogievskiy 90424d6cc1fSVladimir Sementsov-Ogievskiy .. code-block:: QMP 90524d6cc1fSVladimir Sementsov-Ogievskiy 90624d6cc1fSVladimir Sementsov-Ogievskiy -> { 90724d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-add", 90824d6cc1fSVladimir Sementsov-Ogievskiy "arguments": { 90924d6cc1fSVladimir Sementsov-Ogievskiy "node-name": "target0", 91024d6cc1fSVladimir Sementsov-Ogievskiy "driver": "qcow2", 91124d6cc1fSVladimir Sementsov-Ogievskiy "file": { 91224d6cc1fSVladimir Sementsov-Ogievskiy "driver": "file", 91324d6cc1fSVladimir Sementsov-Ogievskiy "filename": "drive0.inc2.qcow2" 91424d6cc1fSVladimir Sementsov-Ogievskiy } 91524d6cc1fSVladimir Sementsov-Ogievskiy } 91624d6cc1fSVladimir Sementsov-Ogievskiy } 91724d6cc1fSVladimir Sementsov-Ogievskiy 91824d6cc1fSVladimir Sementsov-Ogievskiy <- { "return": {} } 91924d6cc1fSVladimir Sementsov-Ogievskiy 92090edef80SJohn Snow#. Issue a new incremental backup command. Apart from the new destination 92190edef80SJohn Snow image, there is no difference from the last two examples. 9227746cf8aSKashyap Chamarthy 923a7786bfbSJohn Snow .. code-block:: QMP 9247746cf8aSKashyap Chamarthy 92590edef80SJohn Snow -> { 92624d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-backup", 9277746cf8aSKashyap Chamarthy "arguments": { 9287746cf8aSKashyap Chamarthy "device": "drive0", 9297746cf8aSKashyap Chamarthy "bitmap": "bitmap0", 93024d6cc1fSVladimir Sementsov-Ogievskiy "target": "target0", 93124d6cc1fSVladimir Sementsov-Ogievskiy "sync": "incremental" 9327746cf8aSKashyap Chamarthy } 9337746cf8aSKashyap Chamarthy } 9347746cf8aSKashyap Chamarthy 93590edef80SJohn Snow <- { "return": {} } 9367746cf8aSKashyap Chamarthy 93790edef80SJohn Snow ... 9387746cf8aSKashyap Chamarthy 93990edef80SJohn Snow <- { 94090edef80SJohn Snow "timestamp": {...}, 94190edef80SJohn Snow "data": { 94290edef80SJohn Snow "device": "drive0", 94390edef80SJohn Snow "type": "backup", 94490edef80SJohn Snow "speed": 0, 94590edef80SJohn Snow "len": 68719476736, 94690edef80SJohn Snow "offset": 68719476736 94790edef80SJohn Snow }, 94890edef80SJohn Snow "event": "BLOCK_JOB_COMPLETED" 94990edef80SJohn Snow } 9507746cf8aSKashyap Chamarthy 95190edef80SJohn Snow ... 95290edef80SJohn Snow 95390edef80SJohn SnowThe only difference from the perspective of the user is that you will need to 95490edef80SJohn Snowset the backing image when attempting to restore the backup: 9557746cf8aSKashyap Chamarthy 9567746cf8aSKashyap Chamarthy.. code:: bash 9577746cf8aSKashyap Chamarthy 95890edef80SJohn Snow $ qemu-img rebase drive0.inc2.qcow2 \ 95990edef80SJohn Snow -u -b drive0.inc1.qcow2 9607746cf8aSKashyap Chamarthy 96190edef80SJohn SnowThis uses the "unsafe" rebase mode to simply set the backing file to a file 96290edef80SJohn Snowthat isn't present. 96390edef80SJohn Snow 96490edef80SJohn SnowIt is also possible to use ``--image-opts`` to specify the entire backing 96590edef80SJohn Snowchain by hand as an ephemeral property at runtime, but that is beyond the 96690edef80SJohn Snowscope of this document. 96790edef80SJohn Snow 96890edef80SJohn SnowExample: Multi-drive Incremental Backup 96990edef80SJohn Snow~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 97090edef80SJohn Snow 97190edef80SJohn SnowAssume we have a VM with two drives, "drive0" and "drive1" and we wish to back 97290edef80SJohn Snowboth of them up such that the two backups represent the same crash-consistent 97390edef80SJohn Snowpoint in time. 97490edef80SJohn Snow 97590edef80SJohn Snow#. For each drive, create an empty image: 97690edef80SJohn Snow 97790edef80SJohn Snow .. code:: bash 97890edef80SJohn Snow 97990edef80SJohn Snow $ qemu-img create -f qcow2 drive0.full.qcow2 64G 98090edef80SJohn Snow $ qemu-img create -f qcow2 drive1.full.qcow2 64G 98190edef80SJohn Snow 98224d6cc1fSVladimir Sementsov-Ogievskiy#. Add target block nodes: 98324d6cc1fSVladimir Sementsov-Ogievskiy 98424d6cc1fSVladimir Sementsov-Ogievskiy .. code-block:: QMP 98524d6cc1fSVladimir Sementsov-Ogievskiy 98624d6cc1fSVladimir Sementsov-Ogievskiy -> { 98724d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-add", 98824d6cc1fSVladimir Sementsov-Ogievskiy "arguments": { 98924d6cc1fSVladimir Sementsov-Ogievskiy "node-name": "target0", 99024d6cc1fSVladimir Sementsov-Ogievskiy "driver": "qcow2", 99124d6cc1fSVladimir Sementsov-Ogievskiy "file": { 99224d6cc1fSVladimir Sementsov-Ogievskiy "driver": "file", 99324d6cc1fSVladimir Sementsov-Ogievskiy "filename": "drive0.full.qcow2" 99424d6cc1fSVladimir Sementsov-Ogievskiy } 99524d6cc1fSVladimir Sementsov-Ogievskiy } 99624d6cc1fSVladimir Sementsov-Ogievskiy } 99724d6cc1fSVladimir Sementsov-Ogievskiy 99824d6cc1fSVladimir Sementsov-Ogievskiy <- { "return": {} } 99924d6cc1fSVladimir Sementsov-Ogievskiy 100024d6cc1fSVladimir Sementsov-Ogievskiy -> { 100124d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-add", 100224d6cc1fSVladimir Sementsov-Ogievskiy "arguments": { 100324d6cc1fSVladimir Sementsov-Ogievskiy "node-name": "target1", 100424d6cc1fSVladimir Sementsov-Ogievskiy "driver": "qcow2", 100524d6cc1fSVladimir Sementsov-Ogievskiy "file": { 100624d6cc1fSVladimir Sementsov-Ogievskiy "driver": "file", 100724d6cc1fSVladimir Sementsov-Ogievskiy "filename": "drive1.full.qcow2" 100824d6cc1fSVladimir Sementsov-Ogievskiy } 100924d6cc1fSVladimir Sementsov-Ogievskiy } 101024d6cc1fSVladimir Sementsov-Ogievskiy } 101124d6cc1fSVladimir Sementsov-Ogievskiy 101224d6cc1fSVladimir Sementsov-Ogievskiy <- { "return": {} } 101324d6cc1fSVladimir Sementsov-Ogievskiy 101490edef80SJohn Snow#. Create a full (anchor) backup for each drive, with accompanying bitmaps: 10157746cf8aSKashyap Chamarthy 1016a7786bfbSJohn Snow .. code-block:: QMP 10177746cf8aSKashyap Chamarthy 101890edef80SJohn Snow -> { 101990edef80SJohn Snow "execute": "transaction", 10207746cf8aSKashyap Chamarthy "arguments": { 10217746cf8aSKashyap Chamarthy "actions": [ 102290edef80SJohn Snow { 102390edef80SJohn Snow "type": "block-dirty-bitmap-add", 102490edef80SJohn Snow "data": { 102590edef80SJohn Snow "node": "drive0", 102690edef80SJohn Snow "name": "bitmap0" 102790edef80SJohn Snow } 102890edef80SJohn Snow }, 102990edef80SJohn Snow { 103090edef80SJohn Snow "type": "block-dirty-bitmap-add", 103190edef80SJohn Snow "data": { 103290edef80SJohn Snow "node": "drive1", 103390edef80SJohn Snow "name": "bitmap0" 103490edef80SJohn Snow } 103590edef80SJohn Snow }, 103690edef80SJohn Snow { 103724d6cc1fSVladimir Sementsov-Ogievskiy "type": "blockdev-backup", 103890edef80SJohn Snow "data": { 103990edef80SJohn Snow "device": "drive0", 104024d6cc1fSVladimir Sementsov-Ogievskiy "target": "target0", 104124d6cc1fSVladimir Sementsov-Ogievskiy "sync": "full" 104290edef80SJohn Snow } 104390edef80SJohn Snow }, 104490edef80SJohn Snow { 104524d6cc1fSVladimir Sementsov-Ogievskiy "type": "blockdev-backup", 104690edef80SJohn Snow "data": { 104790edef80SJohn Snow "device": "drive1", 104824d6cc1fSVladimir Sementsov-Ogievskiy "target": "target1", 104924d6cc1fSVladimir Sementsov-Ogievskiy "sync": "full" 105090edef80SJohn Snow } 105190edef80SJohn Snow } 10527746cf8aSKashyap Chamarthy ] 10537746cf8aSKashyap Chamarthy } 10547746cf8aSKashyap Chamarthy } 10557746cf8aSKashyap Chamarthy 105690edef80SJohn Snow <- { "return": {} } 10577746cf8aSKashyap Chamarthy 105890edef80SJohn Snow ... 10597746cf8aSKashyap Chamarthy 106090edef80SJohn Snow <- { 106190edef80SJohn Snow "timestamp": {...}, 106290edef80SJohn Snow "data": { 106390edef80SJohn Snow "device": "drive0", 106490edef80SJohn Snow "type": "backup", 106590edef80SJohn Snow "speed": 0, 106690edef80SJohn Snow "len": 68719476736, 106790edef80SJohn Snow "offset": 68719476736 106890edef80SJohn Snow }, 10697746cf8aSKashyap Chamarthy "event": "BLOCK_JOB_COMPLETED" 10707746cf8aSKashyap Chamarthy } 10717746cf8aSKashyap Chamarthy 107290edef80SJohn Snow ... 107390edef80SJohn Snow 107490edef80SJohn Snow <- { 107590edef80SJohn Snow "timestamp": {...}, 107690edef80SJohn Snow "data": { 107790edef80SJohn Snow "device": "drive1", 107890edef80SJohn Snow "type": "backup", 107990edef80SJohn Snow "speed": 0, 108090edef80SJohn Snow "len": 68719476736, 108190edef80SJohn Snow "offset": 68719476736 108290edef80SJohn Snow }, 108390edef80SJohn Snow "event": "BLOCK_JOB_COMPLETED" 108490edef80SJohn Snow } 108590edef80SJohn Snow 108690edef80SJohn Snow ... 108790edef80SJohn Snow 108890edef80SJohn Snow#. Later, create new destination images for each of the incremental backups 108990edef80SJohn Snow that point to their respective full backups: 109090edef80SJohn Snow 109190edef80SJohn Snow .. code:: bash 109290edef80SJohn Snow 109390edef80SJohn Snow $ qemu-img create -f qcow2 drive0.inc0.qcow2 \ 109490edef80SJohn Snow -b drive0.full.qcow2 -F qcow2 109590edef80SJohn Snow $ qemu-img create -f qcow2 drive1.inc0.qcow2 \ 109690edef80SJohn Snow -b drive1.full.qcow2 -F qcow2 109790edef80SJohn Snow 109824d6cc1fSVladimir Sementsov-Ogievskiy#. Add target block nodes: 109924d6cc1fSVladimir Sementsov-Ogievskiy 110024d6cc1fSVladimir Sementsov-Ogievskiy .. code-block:: QMP 110124d6cc1fSVladimir Sementsov-Ogievskiy 110224d6cc1fSVladimir Sementsov-Ogievskiy -> { 110324d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-add", 110424d6cc1fSVladimir Sementsov-Ogievskiy "arguments": { 110524d6cc1fSVladimir Sementsov-Ogievskiy "node-name": "target0", 110624d6cc1fSVladimir Sementsov-Ogievskiy "driver": "qcow2", 110724d6cc1fSVladimir Sementsov-Ogievskiy "file": { 110824d6cc1fSVladimir Sementsov-Ogievskiy "driver": "file", 110924d6cc1fSVladimir Sementsov-Ogievskiy "filename": "drive0.inc0.qcow2" 111024d6cc1fSVladimir Sementsov-Ogievskiy } 111124d6cc1fSVladimir Sementsov-Ogievskiy } 111224d6cc1fSVladimir Sementsov-Ogievskiy } 111324d6cc1fSVladimir Sementsov-Ogievskiy 111424d6cc1fSVladimir Sementsov-Ogievskiy <- { "return": {} } 111524d6cc1fSVladimir Sementsov-Ogievskiy 111624d6cc1fSVladimir Sementsov-Ogievskiy -> { 111724d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-add", 111824d6cc1fSVladimir Sementsov-Ogievskiy "arguments": { 111924d6cc1fSVladimir Sementsov-Ogievskiy "node-name": "target1", 112024d6cc1fSVladimir Sementsov-Ogievskiy "driver": "qcow2", 112124d6cc1fSVladimir Sementsov-Ogievskiy "file": { 112224d6cc1fSVladimir Sementsov-Ogievskiy "driver": "file", 112324d6cc1fSVladimir Sementsov-Ogievskiy "filename": "drive1.inc0.qcow2" 112424d6cc1fSVladimir Sementsov-Ogievskiy } 112524d6cc1fSVladimir Sementsov-Ogievskiy } 112624d6cc1fSVladimir Sementsov-Ogievskiy } 112724d6cc1fSVladimir Sementsov-Ogievskiy 112824d6cc1fSVladimir Sementsov-Ogievskiy <- { "return": {} } 112924d6cc1fSVladimir Sementsov-Ogievskiy 113090edef80SJohn Snow#. Issue a multi-drive incremental push backup transaction: 11317746cf8aSKashyap Chamarthy 1132a7786bfbSJohn Snow .. code-block:: QMP 11337746cf8aSKashyap Chamarthy 113490edef80SJohn Snow -> { 113590edef80SJohn Snow "execute": "transaction", 11367746cf8aSKashyap Chamarthy "arguments": { 11377746cf8aSKashyap Chamarthy "actions": [ 113890edef80SJohn Snow { 113924d6cc1fSVladimir Sementsov-Ogievskiy "type": "blockev-backup", 114090edef80SJohn Snow "data": { 114190edef80SJohn Snow "device": "drive0", 114290edef80SJohn Snow "bitmap": "bitmap0", 114390edef80SJohn Snow "sync": "incremental", 114424d6cc1fSVladimir Sementsov-Ogievskiy "target": "target0" 11457746cf8aSKashyap Chamarthy } 114690edef80SJohn Snow }, 114790edef80SJohn Snow { 114824d6cc1fSVladimir Sementsov-Ogievskiy "type": "blockdev-backup", 114990edef80SJohn Snow "data": { 115090edef80SJohn Snow "device": "drive1", 115190edef80SJohn Snow "bitmap": "bitmap0", 115290edef80SJohn Snow "sync": "incremental", 115324d6cc1fSVladimir Sementsov-Ogievskiy "target": "target1" 115490edef80SJohn Snow } 115590edef80SJohn Snow }, 115690edef80SJohn Snow ] 11577746cf8aSKashyap Chamarthy } 11587746cf8aSKashyap Chamarthy } 11597746cf8aSKashyap Chamarthy 116090edef80SJohn Snow <- { "return": {} } 11617746cf8aSKashyap Chamarthy 116290edef80SJohn Snow ... 116390edef80SJohn Snow 116490edef80SJohn Snow <- { 116590edef80SJohn Snow "timestamp": {...}, 116690edef80SJohn Snow "data": { 116790edef80SJohn Snow "device": "drive0", 116890edef80SJohn Snow "type": "backup", 116990edef80SJohn Snow "speed": 0, 117090edef80SJohn Snow "len": 68719476736, 117190edef80SJohn Snow "offset": 68719476736 117290edef80SJohn Snow }, 117390edef80SJohn Snow "event": "BLOCK_JOB_COMPLETED" 117490edef80SJohn Snow } 117590edef80SJohn Snow 117690edef80SJohn Snow ... 117790edef80SJohn Snow 117890edef80SJohn Snow <- { 117990edef80SJohn Snow "timestamp": {...}, 118090edef80SJohn Snow "data": { 118190edef80SJohn Snow "device": "drive1", 118290edef80SJohn Snow "type": "backup", 118390edef80SJohn Snow "speed": 0, 118490edef80SJohn Snow "len": 68719476736, 118590edef80SJohn Snow "offset": 68719476736 118690edef80SJohn Snow }, 118790edef80SJohn Snow "event": "BLOCK_JOB_COMPLETED" 118890edef80SJohn Snow } 118990edef80SJohn Snow 119090edef80SJohn Snow ... 119190edef80SJohn Snow 119290edef80SJohn SnowPush Backup Errors & Recovery 119390edef80SJohn Snow----------------------------- 119490edef80SJohn Snow 119590edef80SJohn SnowIn the event of an error that occurs after a push backup job is successfully 119690edef80SJohn Snowlaunched, either by an individual QMP command or a QMP transaction, the user 119790edef80SJohn Snowwill receive a ``BLOCK_JOB_COMPLETE`` event with a failure message, 119890edef80SJohn Snowaccompanied by a ``BLOCK_JOB_ERROR`` event. 119990edef80SJohn Snow 120090edef80SJohn SnowIn the case of a job being cancelled, the user will receive a 120190edef80SJohn Snow``BLOCK_JOB_CANCELLED`` event instead of a pair of COMPLETE and ERROR 120290edef80SJohn Snowevents. 120390edef80SJohn Snow 120490edef80SJohn SnowIn either failure case, the bitmap used for the failed operation is not 120590edef80SJohn Snowcleared. It will contain all of the dirty bits it did at the start of the 120690edef80SJohn Snowoperation, plus any new bits that got marked during the operation. 120790edef80SJohn Snow 120890edef80SJohn SnowEffectively, the "point in time" that a bitmap is recording differences 120990edef80SJohn Snowagainst is kept at the issuance of the last successful incremental backup, 121090edef80SJohn Snowinstead of being moved forward to the start of this now-failed backup. 121190edef80SJohn Snow 121290edef80SJohn SnowOnce the underlying problem is addressed (e.g. more storage space is allocated 121390edef80SJohn Snowon the destination), the incremental backup command can be retried with the 121490edef80SJohn Snowsame bitmap. 121590edef80SJohn Snow 121690edef80SJohn SnowExample: Individual Failures 121790edef80SJohn Snow~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 121890edef80SJohn Snow 121990edef80SJohn SnowIncremental Push Backup jobs that fail individually behave simply as 122090edef80SJohn Snowdescribed above. This example demonstrates the single-job failure case: 122190edef80SJohn Snow 122290edef80SJohn Snow#. Create a target image: 122390edef80SJohn Snow 122490edef80SJohn Snow .. code:: bash 122590edef80SJohn Snow 122690edef80SJohn Snow $ qemu-img create -f qcow2 drive0.inc0.qcow2 \ 122790edef80SJohn Snow -b drive0.full.qcow2 -F qcow2 122890edef80SJohn Snow 122924d6cc1fSVladimir Sementsov-Ogievskiy#. Add target block node: 123024d6cc1fSVladimir Sementsov-Ogievskiy 123124d6cc1fSVladimir Sementsov-Ogievskiy .. code-block:: QMP 123224d6cc1fSVladimir Sementsov-Ogievskiy 123324d6cc1fSVladimir Sementsov-Ogievskiy -> { 123424d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-add", 123524d6cc1fSVladimir Sementsov-Ogievskiy "arguments": { 123624d6cc1fSVladimir Sementsov-Ogievskiy "node-name": "target0", 123724d6cc1fSVladimir Sementsov-Ogievskiy "driver": "qcow2", 123824d6cc1fSVladimir Sementsov-Ogievskiy "file": { 123924d6cc1fSVladimir Sementsov-Ogievskiy "driver": "file", 124024d6cc1fSVladimir Sementsov-Ogievskiy "filename": "drive0.inc0.qcow2" 124124d6cc1fSVladimir Sementsov-Ogievskiy } 124224d6cc1fSVladimir Sementsov-Ogievskiy } 124324d6cc1fSVladimir Sementsov-Ogievskiy } 124424d6cc1fSVladimir Sementsov-Ogievskiy 124524d6cc1fSVladimir Sementsov-Ogievskiy <- { "return": {} } 124624d6cc1fSVladimir Sementsov-Ogievskiy 124790edef80SJohn Snow#. Attempt to create an incremental backup via QMP: 124890edef80SJohn Snow 1249a7786bfbSJohn Snow .. code-block:: QMP 125090edef80SJohn Snow 125190edef80SJohn Snow -> { 125224d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-backup", 125390edef80SJohn Snow "arguments": { 125490edef80SJohn Snow "device": "drive0", 125590edef80SJohn Snow "bitmap": "bitmap0", 125624d6cc1fSVladimir Sementsov-Ogievskiy "target": "target0", 125724d6cc1fSVladimir Sementsov-Ogievskiy "sync": "incremental" 125890edef80SJohn Snow } 125990edef80SJohn Snow } 126090edef80SJohn Snow 126190edef80SJohn Snow <- { "return": {} } 126290edef80SJohn Snow 126390edef80SJohn Snow#. Receive a pair of events indicating failure: 126490edef80SJohn Snow 1265a7786bfbSJohn Snow .. code-block:: QMP 126690edef80SJohn Snow 126790edef80SJohn Snow <- { 126890edef80SJohn Snow "timestamp": {...}, 126990edef80SJohn Snow "data": { 127090edef80SJohn Snow "device": "drive0", 127190edef80SJohn Snow "action": "report", 127290edef80SJohn Snow "operation": "write" 127390edef80SJohn Snow }, 127490edef80SJohn Snow "event": "BLOCK_JOB_ERROR" 127590edef80SJohn Snow } 127690edef80SJohn Snow 127790edef80SJohn Snow <- { 127890edef80SJohn Snow "timestamp": {...}, 127990edef80SJohn Snow "data": { 128090edef80SJohn Snow "speed": 0, 128190edef80SJohn Snow "offset": 0, 128290edef80SJohn Snow "len": 67108864, 128390edef80SJohn Snow "error": "No space left on device", 128490edef80SJohn Snow "device": "drive0", 128590edef80SJohn Snow "type": "backup" 128690edef80SJohn Snow }, 128790edef80SJohn Snow "event": "BLOCK_JOB_COMPLETED" 128890edef80SJohn Snow } 128990edef80SJohn Snow 129024d6cc1fSVladimir Sementsov-Ogievskiy#. Remove target node: 129124d6cc1fSVladimir Sementsov-Ogievskiy 129224d6cc1fSVladimir Sementsov-Ogievskiy .. code-block:: QMP 129324d6cc1fSVladimir Sementsov-Ogievskiy 129424d6cc1fSVladimir Sementsov-Ogievskiy -> { 129524d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-del", 129624d6cc1fSVladimir Sementsov-Ogievskiy "arguments": { 129724d6cc1fSVladimir Sementsov-Ogievskiy "node-name": "target0", 129824d6cc1fSVladimir Sementsov-Ogievskiy } 129924d6cc1fSVladimir Sementsov-Ogievskiy } 130024d6cc1fSVladimir Sementsov-Ogievskiy 130124d6cc1fSVladimir Sementsov-Ogievskiy <- { "return": {} } 130224d6cc1fSVladimir Sementsov-Ogievskiy 130390edef80SJohn Snow#. Delete the failed image, and re-create it. 130490edef80SJohn Snow 130590edef80SJohn Snow .. code:: bash 130690edef80SJohn Snow 130790edef80SJohn Snow $ rm drive0.inc0.qcow2 130890edef80SJohn Snow $ qemu-img create -f qcow2 drive0.inc0.qcow2 \ 130990edef80SJohn Snow -b drive0.full.qcow2 -F qcow2 131090edef80SJohn Snow 131124d6cc1fSVladimir Sementsov-Ogievskiy#. Add target block node: 131224d6cc1fSVladimir Sementsov-Ogievskiy 131324d6cc1fSVladimir Sementsov-Ogievskiy .. code-block:: QMP 131424d6cc1fSVladimir Sementsov-Ogievskiy 131524d6cc1fSVladimir Sementsov-Ogievskiy -> { 131624d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-add", 131724d6cc1fSVladimir Sementsov-Ogievskiy "arguments": { 131824d6cc1fSVladimir Sementsov-Ogievskiy "node-name": "target0", 131924d6cc1fSVladimir Sementsov-Ogievskiy "driver": "qcow2", 132024d6cc1fSVladimir Sementsov-Ogievskiy "file": { 132124d6cc1fSVladimir Sementsov-Ogievskiy "driver": "file", 132224d6cc1fSVladimir Sementsov-Ogievskiy "filename": "drive0.inc0.qcow2" 132324d6cc1fSVladimir Sementsov-Ogievskiy } 132424d6cc1fSVladimir Sementsov-Ogievskiy } 132524d6cc1fSVladimir Sementsov-Ogievskiy } 132624d6cc1fSVladimir Sementsov-Ogievskiy 132724d6cc1fSVladimir Sementsov-Ogievskiy <- { "return": {} } 132824d6cc1fSVladimir Sementsov-Ogievskiy 132990edef80SJohn Snow#. Retry the command after fixing the underlying problem, such as 133090edef80SJohn Snow freeing up space on the backup volume: 133190edef80SJohn Snow 1332a7786bfbSJohn Snow .. code-block:: QMP 133390edef80SJohn Snow 133490edef80SJohn Snow -> { 133524d6cc1fSVladimir Sementsov-Ogievskiy "execute": "blockdev-backup", 133690edef80SJohn Snow "arguments": { 133790edef80SJohn Snow "device": "drive0", 133890edef80SJohn Snow "bitmap": "bitmap0", 133924d6cc1fSVladimir Sementsov-Ogievskiy "target": "target0", 134024d6cc1fSVladimir Sementsov-Ogievskiy "sync": "incremental" 134190edef80SJohn Snow } 134290edef80SJohn Snow } 134390edef80SJohn Snow 134490edef80SJohn Snow <- { "return": {} } 134590edef80SJohn Snow 134690edef80SJohn Snow#. Receive confirmation that the job completed successfully: 134790edef80SJohn Snow 1348a7786bfbSJohn Snow .. code-block:: QMP 134990edef80SJohn Snow 135090edef80SJohn Snow <- { 135190edef80SJohn Snow "timestamp": {...}, 135290edef80SJohn Snow "data": { 135390edef80SJohn Snow "device": "drive0", 135490edef80SJohn Snow "type": "backup", 135590edef80SJohn Snow "speed": 0, 135690edef80SJohn Snow "len": 67108864, 135790edef80SJohn Snow "offset": 67108864 135890edef80SJohn Snow }, 135990edef80SJohn Snow "event": "BLOCK_JOB_COMPLETED" 136090edef80SJohn Snow } 136190edef80SJohn Snow 136290edef80SJohn SnowExample: Partial Transactional Failures 136390edef80SJohn Snow~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 136490edef80SJohn Snow 136524d6cc1fSVladimir Sementsov-OgievskiyQMP commands like `blockdev-backup 136624d6cc1fSVladimir Sementsov-Ogievskiy<qemu-qmp-ref.html#index-blockdev_002dbackup>`_ 136790edef80SJohn Snowconceptually only start a job, and so transactions containing these commands 136890edef80SJohn Snowmay succeed even if the job it created later fails. This might have surprising 136990edef80SJohn Snowinteractions with notions of how a "transaction" ought to behave. 137090edef80SJohn Snow 137190edef80SJohn SnowThis distinction means that on occasion, a transaction containing such job 137290edef80SJohn Snowlaunching commands may appear to succeed and return success, but later 137390edef80SJohn Snowindividual jobs associated with the transaction may fail. It is possible that 137490edef80SJohn Snowa management application may have to deal with a partial backup failure after 137590edef80SJohn Snowa "successful" transaction. 137690edef80SJohn Snow 137790edef80SJohn SnowIf multiple backup jobs are specified in a single transaction, if one of those 137890edef80SJohn Snowjobs fails, it will not interact with the other backup jobs in any way by 137990edef80SJohn Snowdefault. The job(s) that succeeded will clear the dirty bitmap associated with 138090edef80SJohn Snowthe operation, but the job(s) that failed will not. It is therefore not safe 138190edef80SJohn Snowto delete any incremental backups that were created successfully in this 138290edef80SJohn Snowscenario, even though others failed. 138390edef80SJohn Snow 138490edef80SJohn SnowThis example illustrates a transaction with two backup jobs, where one fails 138590edef80SJohn Snowand one succeeds: 138690edef80SJohn Snow 138790edef80SJohn Snow#. Issue the transaction to start a backup of both drives. 138890edef80SJohn Snow 1389a7786bfbSJohn Snow .. code-block:: QMP 139090edef80SJohn Snow 139190edef80SJohn Snow -> { 139290edef80SJohn Snow "execute": "transaction", 139390edef80SJohn Snow "arguments": { 139490edef80SJohn Snow "actions": [ 139590edef80SJohn Snow { 139624d6cc1fSVladimir Sementsov-Ogievskiy "type": "blockdev-backup", 139790edef80SJohn Snow "data": { 139890edef80SJohn Snow "device": "drive0", 139990edef80SJohn Snow "bitmap": "bitmap0", 140090edef80SJohn Snow "sync": "incremental", 140124d6cc1fSVladimir Sementsov-Ogievskiy "target": "target0" 140290edef80SJohn Snow } 140390edef80SJohn Snow }, 140490edef80SJohn Snow { 140524d6cc1fSVladimir Sementsov-Ogievskiy "type": "blockdev-backup", 140690edef80SJohn Snow "data": { 140790edef80SJohn Snow "device": "drive1", 140890edef80SJohn Snow "bitmap": "bitmap0", 140990edef80SJohn Snow "sync": "incremental", 141024d6cc1fSVladimir Sementsov-Ogievskiy "target": "target1" 141190edef80SJohn Snow } 141290edef80SJohn Snow }] 141390edef80SJohn Snow } 141490edef80SJohn Snow } 141590edef80SJohn Snow 141690edef80SJohn Snow#. Receive notice that the Transaction was accepted, and jobs were 14177746cf8aSKashyap Chamarthy launched: 14187746cf8aSKashyap Chamarthy 1419a7786bfbSJohn Snow .. code-block:: QMP 14207746cf8aSKashyap Chamarthy 142190edef80SJohn Snow <- { "return": {} } 14227746cf8aSKashyap Chamarthy 142390edef80SJohn Snow#. Receive notice that the first job has completed: 14247746cf8aSKashyap Chamarthy 1425a7786bfbSJohn Snow .. code-block:: QMP 14267746cf8aSKashyap Chamarthy 142790edef80SJohn Snow <- { 142890edef80SJohn Snow "timestamp": {...}, 142990edef80SJohn Snow "data": { 143090edef80SJohn Snow "device": "drive0", 143190edef80SJohn Snow "type": "backup", 143290edef80SJohn Snow "speed": 0, 143390edef80SJohn Snow "len": 67108864, 143490edef80SJohn Snow "offset": 67108864 143590edef80SJohn Snow }, 143690edef80SJohn Snow "event": "BLOCK_JOB_COMPLETED" 143790edef80SJohn Snow } 143890edef80SJohn Snow 143990edef80SJohn Snow#. Receive notice that the second job has failed: 14407746cf8aSKashyap Chamarthy 1441a7786bfbSJohn Snow .. code-block:: QMP 14427746cf8aSKashyap Chamarthy 144390edef80SJohn Snow <- { 144490edef80SJohn Snow "timestamp": {...}, 144590edef80SJohn Snow "data": { 144690edef80SJohn Snow "device": "drive1", 144790edef80SJohn Snow "action": "report", 144890edef80SJohn Snow "operation": "read" 144990edef80SJohn Snow }, 145090edef80SJohn Snow "event": "BLOCK_JOB_ERROR" 145190edef80SJohn Snow } 145290edef80SJohn Snow 145390edef80SJohn Snow ... 145490edef80SJohn Snow 145590edef80SJohn Snow <- { 145690edef80SJohn Snow "timestamp": {...}, 145790edef80SJohn Snow "data": { 145890edef80SJohn Snow "speed": 0, 145990edef80SJohn Snow "offset": 0, 146090edef80SJohn Snow "len": 67108864, 14617746cf8aSKashyap Chamarthy "error": "Input/output error", 146290edef80SJohn Snow "device": "drive1", 146390edef80SJohn Snow "type": "backup" 146490edef80SJohn Snow }, 146590edef80SJohn Snow "event": "BLOCK_JOB_COMPLETED" 146690edef80SJohn Snow } 146790edef80SJohn Snow 146890edef80SJohn SnowAt the conclusion of the above example, ``drive0.inc0.qcow2`` is valid and 146990edef80SJohn Snowmust be kept, but ``drive1.inc0.qcow2`` is incomplete and should be 147090edef80SJohn Snowdeleted. If a VM-wide incremental backup of all drives at a point-in-time is 147190edef80SJohn Snowto be made, new backups for both drives will need to be made, taking into 147290edef80SJohn Snowaccount that a new incremental backup for drive0 needs to be based on top of 147390edef80SJohn Snow``drive0.inc0.qcow2``. 147490edef80SJohn Snow 147590edef80SJohn SnowFor this example, an incremental backup for ``drive0`` was created, but not 147690edef80SJohn Snowfor ``drive1``. The last VM-wide crash-consistent backup that is available in 147790edef80SJohn Snowthis case is the full backup: 147890edef80SJohn Snow 147990edef80SJohn Snow.. code:: text 148090edef80SJohn Snow 148190edef80SJohn Snow [drive0.full.qcow2] <-- [drive0.inc0.qcow2] 148290edef80SJohn Snow [drive1.full.qcow2] 148390edef80SJohn Snow 148490edef80SJohn SnowTo repair this, issue a new incremental backup across both drives. The result 148590edef80SJohn Snowwill be backup chains that resemble the following: 148690edef80SJohn Snow 148790edef80SJohn Snow.. code:: text 148890edef80SJohn Snow 148990edef80SJohn Snow [drive0.full.qcow2] <-- [drive0.inc0.qcow2] <-- [drive0.inc1.qcow2] 149090edef80SJohn Snow [drive1.full.qcow2] <-------------------------- [drive1.inc1.qcow2] 149190edef80SJohn Snow 149290edef80SJohn SnowExample: Grouped Completion Mode 149390edef80SJohn Snow~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 149490edef80SJohn Snow 149590edef80SJohn SnowWhile jobs launched by transactions normally complete or fail individually, 149690edef80SJohn Snowit's possible to instruct them to complete or fail together as a group. QMP 149790edef80SJohn Snowtransactions take an optional properties structure that can affect the 149890edef80SJohn Snowbehavior of the transaction. 149990edef80SJohn Snow 150090edef80SJohn SnowThe ``completion-mode`` transaction property can be either ``individual`` 150190edef80SJohn Snowwhich is the default legacy behavior described above, or ``grouped``, detailed 150290edef80SJohn Snowbelow. 150390edef80SJohn Snow 150490edef80SJohn SnowIn ``grouped`` completion mode, no jobs will report success until all jobs are 150590edef80SJohn Snowready to report success. If any job fails, all other jobs will be cancelled. 150690edef80SJohn Snow 150790edef80SJohn SnowRegardless of if a participating incremental backup job failed or was 150890edef80SJohn Snowcancelled, their associated bitmaps will all be held at their existing 150990edef80SJohn Snowpoints-in-time, as in individual failure cases. 151090edef80SJohn Snow 151190edef80SJohn SnowHere's the same multi-drive backup scenario from `Example: Partial 151290edef80SJohn SnowTransactional Failures`_, but with the ``grouped`` completion-mode property 151390edef80SJohn Snowapplied: 151490edef80SJohn Snow 151590edef80SJohn Snow#. Issue the multi-drive incremental backup transaction: 15167746cf8aSKashyap Chamarthy 1517a7786bfbSJohn Snow .. code-block:: QMP 15187746cf8aSKashyap Chamarthy 151990edef80SJohn Snow -> { 152090edef80SJohn Snow "execute": "transaction", 152190edef80SJohn Snow "arguments": { 152290edef80SJohn Snow "properties": { 152390edef80SJohn Snow "completion-mode": "grouped" 152490edef80SJohn Snow }, 152590edef80SJohn Snow "actions": [ 152690edef80SJohn Snow { 152724d6cc1fSVladimir Sementsov-Ogievskiy "type": "blockdev-backup", 152890edef80SJohn Snow "data": { 152990edef80SJohn Snow "device": "drive0", 153090edef80SJohn Snow "bitmap": "bitmap0", 153190edef80SJohn Snow "sync": "incremental", 153224d6cc1fSVladimir Sementsov-Ogievskiy "target": "target0" 153390edef80SJohn Snow } 153490edef80SJohn Snow }, 153590edef80SJohn Snow { 153624d6cc1fSVladimir Sementsov-Ogievskiy "type": "blockdev-backup", 153790edef80SJohn Snow "data": { 153890edef80SJohn Snow "device": "drive1", 153990edef80SJohn Snow "bitmap": "bitmap0", 154090edef80SJohn Snow "sync": "incremental", 154124d6cc1fSVladimir Sementsov-Ogievskiy "target": "target1" 154290edef80SJohn Snow } 154390edef80SJohn Snow }] 154490edef80SJohn Snow } 154590edef80SJohn Snow } 154690edef80SJohn Snow 154790edef80SJohn Snow#. Receive notice that the Transaction was accepted, and jobs were launched: 154890edef80SJohn Snow 1549a7786bfbSJohn Snow .. code-block:: QMP 155090edef80SJohn Snow 155190edef80SJohn Snow <- { "return": {} } 155290edef80SJohn Snow 155390edef80SJohn Snow#. Receive notification that the backup job for ``drive1`` has failed: 155490edef80SJohn Snow 1555a7786bfbSJohn Snow .. code-block:: QMP 155690edef80SJohn Snow 155790edef80SJohn Snow <- { 155890edef80SJohn Snow "timestamp": {...}, 155990edef80SJohn Snow "data": { 156090edef80SJohn Snow "device": "drive1", 156190edef80SJohn Snow "action": "report", 156290edef80SJohn Snow "operation": "read" 156390edef80SJohn Snow }, 156490edef80SJohn Snow "event": "BLOCK_JOB_ERROR" 156590edef80SJohn Snow } 156690edef80SJohn Snow 156790edef80SJohn Snow <- { 156890edef80SJohn Snow "timestamp": {...}, 156990edef80SJohn Snow "data": { 157090edef80SJohn Snow "speed": 0, 157190edef80SJohn Snow "offset": 0, 157290edef80SJohn Snow "len": 67108864, 157390edef80SJohn Snow "error": "Input/output error", 157490edef80SJohn Snow "device": "drive1", 157590edef80SJohn Snow "type": "backup" 157690edef80SJohn Snow }, 157790edef80SJohn Snow "event": "BLOCK_JOB_COMPLETED" 157890edef80SJohn Snow } 157990edef80SJohn Snow 158090edef80SJohn Snow#. Receive notification that the job for ``drive0`` has been cancelled: 158190edef80SJohn Snow 1582a7786bfbSJohn Snow .. code-block:: QMP 158390edef80SJohn Snow 158490edef80SJohn Snow <- { 1585575e6226SJohn Snow "timestamp": {...}, 158690edef80SJohn Snow "data": { 158790edef80SJohn Snow "device": "drive0", 158890edef80SJohn Snow "type": "backup", 158990edef80SJohn Snow "speed": 0, 159090edef80SJohn Snow "len": 67108864, 159190edef80SJohn Snow "offset": 16777216 159290edef80SJohn Snow }, 159390edef80SJohn Snow "event": "BLOCK_JOB_CANCELLED" 159490edef80SJohn Snow } 159590edef80SJohn Snow 159690edef80SJohn SnowAt the conclusion of *this* example, both jobs have been aborted due to a 159790edef80SJohn Snowfailure. Both destination images should be deleted and are no longer of use. 159890edef80SJohn Snow 159990edef80SJohn SnowThe transaction as a whole can simply be re-issued at a later time. 16007746cf8aSKashyap Chamarthy 16017746cf8aSKashyap Chamarthy.. raw:: html 16027746cf8aSKashyap Chamarthy 16037746cf8aSKashyap Chamarthy <!-- 16047746cf8aSKashyap Chamarthy The FreeBSD Documentation License 16057746cf8aSKashyap Chamarthy 160690edef80SJohn Snow Redistribution and use in source (ReST) and 'compiled' forms (SGML, HTML, 160790edef80SJohn Snow PDF, PostScript, RTF and so forth) with or without modification, are 160890edef80SJohn Snow permitted provided that the following conditions are met: 16097746cf8aSKashyap Chamarthy 161090edef80SJohn Snow Redistributions of source code (ReST) must retain the above copyright notice, 161190edef80SJohn Snow this list of conditions and the following disclaimer of this file unmodified. 16127746cf8aSKashyap Chamarthy 161390edef80SJohn Snow Redistributions in compiled form (transformed to other DTDs, converted to 161490edef80SJohn Snow PDF, PostScript, RTF and other formats) must reproduce the above copyright 161590edef80SJohn Snow notice, this list of conditions and the following disclaimer in the 161690edef80SJohn Snow documentation and/or other materials provided with the distribution. 16177746cf8aSKashyap Chamarthy 161890edef80SJohn Snow THIS DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 161990edef80SJohn Snow IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 162090edef80SJohn Snow IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 162190edef80SJohn Snow ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 162290edef80SJohn Snow LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 162390edef80SJohn Snow CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 162490edef80SJohn Snow SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 162590edef80SJohn Snow INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 162690edef80SJohn Snow CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 162790edef80SJohn Snow ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF 162890edef80SJohn Snow THE POSSIBILITY OF SUCH DAMAGE. 16297746cf8aSKashyap Chamarthy --> 1630