)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"6bb9556fe72ec59d8f1eabc54165a27704096fcc","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"6c6a04ed_239c8429","updated":"2026-06-01 14:43:08.000000000","message":"WIP","commit_id":"7403ceaf0890392862c30bd0e4c10319c1bbdbcb"},{"author":{"_account_id":36171,"name":"jayaanand borra","display_name":"jayaanand borra","email":"jayaanand.borra@netapp.com","username":"jayaanan","status":"netapp"},"change_message_id":"a4e897c472c1e9df17f3940f35082a571154b175","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"4e9e571b_de4d6152","updated":"2026-06-14 14:03:10.000000000","message":"big patch to review :-)","commit_id":"b885608b63e30f63d2a015aeba58cc84b3fff47a"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"6e53a0b562f529258aacbe44f2694c9e6f13a8b9","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"b2c4fd62_dc04b538","updated":"2026-06-12 19:17:32.000000000","message":"recheck","commit_id":"b885608b63e30f63d2a015aeba58cc84b3fff47a"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"630440bec76b6732bbc9736fdfc57904184ebdae","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":10,"id":"1fbb5961_e8303fe3","updated":"2026-06-15 23:52:28.000000000","message":"recheck","commit_id":"7247a057d48f32103437883b929386ee4cc57491"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"3fc47c0d1e817ffe6365b4e8deebcb12425ef84d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":10,"id":"94b5cd0f_5b2cce78","updated":"2026-06-15 20:32:04.000000000","message":"recheck","commit_id":"7247a057d48f32103437883b929386ee4cc57491"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"6a596cb7ee5241cf86ba313cfe09ce453fbe6755","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":10,"id":"a4979e8d_ceda6fe7","updated":"2026-06-15 17:37:25.000000000","message":"recheck","commit_id":"7247a057d48f32103437883b929386ee4cc57491"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"6854ef93b9ce0bac11ddaa1c225dfd66002846a6","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":11,"id":"32a56600_deba6b0d","updated":"2026-06-16 16:19:58.000000000","message":"recheck","commit_id":"96e3057ef2ea43cdf73bc8577be6c1a47b0d279e"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"940c123e97759aab273402dbdb18ac6324e1fe98","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":11,"id":"d05c735e_4226fac8","updated":"2026-06-27 16:43:16.000000000","message":"recheck","commit_id":"96e3057ef2ea43cdf73bc8577be6c1a47b0d279e"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"8ecb3f9bef17a653b0e894c0beca556d93282eed","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"00a9dae3_119c09dd","updated":"2026-07-01 19:46:19.000000000","message":"recheck","commit_id":"03fce4168c73a6ee931e00fa8d061c7ffb5c2b30"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"a82d6672468f09751cb6ab06de5a949bab94d133","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"6ed3ea04_9327b127","updated":"2026-07-02 21:46:19.000000000","message":"recheck","commit_id":"6d20efd048836a21a5ad18c58e5b852b8a711ad2"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"5f4296a274d8ae4ea7915f851db11378b1e38723","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"7ecf4e6c_17c23a0d","updated":"2026-07-02 18:52:21.000000000","message":"recheck","commit_id":"6d20efd048836a21a5ad18c58e5b852b8a711ad2"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"87ec26eeb34f4bd148c6ed4be680f54e78c39bb5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"dbc8ea00_e21143ef","updated":"2026-07-03 01:43:44.000000000","message":"recheck","commit_id":"6d20efd048836a21a5ad18c58e5b852b8a711ad2"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"a865c4169301b070cd2bf0dd912719896fe2cf22","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"3941ef75_e0539ea9","updated":"2026-07-02 20:35:39.000000000","message":"run Pure Storage CI","commit_id":"6d20efd048836a21a5ad18c58e5b852b8a711ad2"},{"author":{"_account_id":36686,"name":"Inyong Hong","display_name":"hongp","email":"inyong.hong@samsung.com","username":"hong-p"},"change_message_id":"c23d3910982cc24c73c7b8e9d6d60a0301c1dd9e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":23,"id":"18877119_d4f14ea3","updated":"2026-07-12 11:00:52.000000000","message":"Overall looks good. The two doc/reference gaps are handled in the dependent changes — see https://review.opendev.org/c/openstack/cinder/+/995703 (reference driver) and https://review.opendev.org/c/openstack/cinder/+/995964 (api-ref/admin docs).","commit_id":"5069b31d50f6776e6f13c9a423378d078cd44d6f"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"66497b4f6310f629263649385c7d359e6d118cff","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":23,"id":"4c6da4fd_db0de5ce","updated":"2026-07-07 20:44:14.000000000","message":"run Everpure CI","commit_id":"5069b31d50f6776e6f13c9a423378d078cd44d6f"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"2d1afdc07d1f0a36f26d79318d4d1a6667c76ad0","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":23,"id":"c0eb9912_5995371f","updated":"2026-07-07 18:44:20.000000000","message":"run Everpure CI","commit_id":"5069b31d50f6776e6f13c9a423378d078cd44d6f"},{"author":{"_account_id":34860,"name":"Amit Uniyal","email":"auniyal@redhat.com","username":"auniyal"},"change_message_id":"c0e66dbfea6bd19dde884d3ea9438b80a4c0c33f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":23,"id":"29343119_7d531544","updated":"2026-07-27 14:28:56.000000000","message":"this patch is too big for a single commit. I think it could be split into smaller and independent patches in a single relation chain.\n\nbugfix, volume driver  changes, backup manager + chunked driver CBT framework then API micrversion with final releasenote.","commit_id":"5069b31d50f6776e6f13c9a423378d078cd44d6f"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"f1fccd51340a8f2a22f5f641bc689c03dd6f3a3e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":23,"id":"dc4d69a7_ca5ee822","in_reply_to":"29343119_7d531544","updated":"2026-08-05 22:44:03.000000000","message":"bugfix extracted. i\u0027ll dfer to the CinderPTL if we need to break this into a relation chain","commit_id":"5069b31d50f6776e6f13c9a423378d078cd44d6f"},{"author":{"_account_id":4523,"name":"Eric Harney","email":"eharney@redhat.com","username":"eharney"},"change_message_id":"4012d2d85d392f996873881cecc3b3972094dc34","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":26,"id":"76f06d45_7e5f711a","updated":"2026-08-12 14:23:59.000000000","message":"IMO this should really be split into at least two changes: one for the changed blocks API (both driver and REST API) and one for the cinder-backup service consuming it when creating backups.","commit_id":"4e5c4d53ab4e4a02e5533a56d3375661274b3883"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"5140558a4dea4e6c20a09b22d53870501399bb96","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":26,"id":"fd04f6f9_85e7a90e","updated":"2026-08-06 16:45:45.000000000","message":"recheck","commit_id":"4e5c4d53ab4e4a02e5533a56d3375661274b3883"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"ffd21e53a4c47f5db6f74dea1d5762f3c05e9b08","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":26,"id":"61e7a4e2_ba7d5912","in_reply_to":"76f06d45_7e5f711a","updated":"2026-08-12 16:09:20.000000000","message":"Split as suggested: 990923 is now just the changed-blocks contract + `os-list_changed_blocks` API, and the cinder-backup consumption moved to a follow-on (I7ce598b6 / 1000747) stacked on top. The data→zero restore bugfix was already extracted separately as 999911.","commit_id":"4e5c4d53ab4e4a02e5533a56d3375661274b3883"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"1792f708999012ed22376c77f0f681ca534a0307","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":30,"id":"d0dc267f_fb9889ba","updated":"2026-08-16 16:02:23.000000000","message":"Addressing jayaanand\u0027s question about an unbounded \u0027limit\u0027.\n\nEric, this slightly qualifies your \"the most typical use case would be\nthat the caller wants the whole list\" -- flagging it explicitly in case\nyou\u0027d rather it went another way.\n\nlimit now defaults to and is capped at a new changed_blocks_max_limit\noption (default 1000). The whole list is still available, just paged via\nchanged_blocks_next_marker as with our other list APIs. My reasoning for\nenforcing the cap rather than leaving it optional: next_marker is only\ncomputed when a limit is applied, so without one, any driver that\ntruncated its own result to protect its backend would report a partial\nlist as complete -- silently dropping changed blocks from an incremental\nbackup. Capping makes that failure mode unrepresentable, and the driver\ncontract now forbids self-truncation outright.\n\nHappy to make the cap opt-in (0 \u003d unlimited) instead if you\u0027d prefer the\ndefault to stay unbounded.","commit_id":"e44b984b323f22c6b1526a287a4807f4aaa11f5f"}],"cinder/api/schemas/volume_actions.py":[{"author":{"_account_id":36171,"name":"jayaanand borra","display_name":"jayaanand borra","email":"jayaanand.borra@netapp.com","username":"jayaanan","status":"netapp"},"change_message_id":"1f5cdeeb78feb4e74e9e697ed93ce37b36102c50","unresolved":true,"context_lines":[{"line_number":274,"context_line":"                \u0027length\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 1},"},{"line_number":275,"context_line":"                \u0027marker\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 0},"},{"line_number":276,"context_line":"                \u0027limit\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 1},"},{"line_number":277,"context_line":"            },"},{"line_number":278,"context_line":"            \u0027required\u0027: [\u0027target_snapshot_id\u0027],"},{"line_number":279,"context_line":"            \u0027additionalProperties\u0027: False,"},{"line_number":280,"context_line":"        },"}],"source_content_type":"text/x-python","patch_set":28,"id":"2576f084_e8cf70cc","line":277,"updated":"2026-08-14 16:11:44.000000000","message":"limit has a minimum but no default or maximum. If the caller omits it, the request can return the complete changed-block extent list. For a highly fragmented volume, that list can be extremely large. Is this OK?","commit_id":"be1cb90fbb1beb0846e9d5ad2fd8a3678a62d4dd"},{"author":{"_account_id":4523,"name":"Eric Harney","email":"eharney@redhat.com","username":"eharney"},"change_message_id":"454c5dc083b7721e6f7d1c05c3b95dade99caa97","unresolved":true,"context_lines":[{"line_number":274,"context_line":"                \u0027length\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 1},"},{"line_number":275,"context_line":"                \u0027marker\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 0},"},{"line_number":276,"context_line":"                \u0027limit\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 1},"},{"line_number":277,"context_line":"            },"},{"line_number":278,"context_line":"            \u0027required\u0027: [\u0027target_snapshot_id\u0027],"},{"line_number":279,"context_line":"            \u0027additionalProperties\u0027: False,"},{"line_number":280,"context_line":"        },"}],"source_content_type":"text/x-python","patch_set":28,"id":"d1704bc8_d53b870b","line":277,"in_reply_to":"2576f084_e8cf70cc","updated":"2026-08-14 16:17:37.000000000","message":"The most typical use case would be that the caller wants the whole list.","commit_id":"be1cb90fbb1beb0846e9d5ad2fd8a3678a62d4dd"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"9527c659a1dd26f631c3b50f7e9b7f055d36d89b","unresolved":false,"context_lines":[{"line_number":274,"context_line":"                \u0027length\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 1},"},{"line_number":275,"context_line":"                \u0027marker\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 0},"},{"line_number":276,"context_line":"                \u0027limit\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 1},"},{"line_number":277,"context_line":"            },"},{"line_number":278,"context_line":"            \u0027required\u0027: [\u0027target_snapshot_id\u0027],"},{"line_number":279,"context_line":"            \u0027additionalProperties\u0027: False,"},{"line_number":280,"context_line":"        },"}],"source_content_type":"text/x-python","patch_set":28,"id":"9a65d21d_8b7a363d","line":277,"in_reply_to":"659cb606_42647b09","updated":"2026-08-16 16:02:46.000000000","message":"Done","commit_id":"be1cb90fbb1beb0846e9d5ad2fd8a3678a62d4dd"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"1792f708999012ed22376c77f0f681ca534a0307","unresolved":true,"context_lines":[{"line_number":274,"context_line":"                \u0027length\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 1},"},{"line_number":275,"context_line":"                \u0027marker\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 0},"},{"line_number":276,"context_line":"                \u0027limit\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 1},"},{"line_number":277,"context_line":"            },"},{"line_number":278,"context_line":"            \u0027required\u0027: [\u0027target_snapshot_id\u0027],"},{"line_number":279,"context_line":"            \u0027additionalProperties\u0027: False,"},{"line_number":280,"context_line":"        },"}],"source_content_type":"text/x-python","patch_set":28,"id":"659cb606_42647b09","line":277,"in_reply_to":"874d7475_d2eb2944","updated":"2026-08-16 16:02:23.000000000","message":"Good catch -- this turned out to be a real gap, so I\u0027ve changed the\nbehaviour rather than leaving limit unbounded.\n\nDigging into it, a driver whose backend can\u0027t enumerate everything in one\ncall had no safe option. apply_cbt_window() only computes next_marker when\na limit was supplied, so a driver that truncated its own result to protect\nitself would return a short list with changed_blocks_next_marker: null --\ni.e. \"this is the complete set of changed blocks\". A backup tool would\nthen treat the missing extents as unchanged and write a corrupt\nincremental. So the only alternatives were \"fail opaquely\" (the 409 you\nhit) or \"corrupt data silently\".\n\nThis patchset adds a changed_blocks_max_limit option (default 1000).\nlimit now both defaults to and is capped at it, clipped rather than\nrejected, as elsewhere in the API. Drivers therefore never see limit\u003dNone\nfrom this path, next_marker is always meaningful, and callers who want the\nwhole list page through it. The driver contract and contributor guide now\nalso explicitly forbid self-truncation.\n\nFor the case where even a bounded page is too much for the backend, there\u0027s\na follow-up: https://review.opendev.org/c/openstack/cinder/+/1001037\nIt adds exception.CBTPagingRequired, which a driver raises to mean \"the\ndiff exists, just ask for less\". That surfaces as a 413 (with a\nsuggested_limit if the driver offers one) instead of the 409 that means\nCBT is unavailable, so a client knows to retry smaller. It also adds\nchanged_blocks_rpc_timeout for the get_cbt_extents RPC, since a\nsynchronous backend diff can legitimately outlast rpc_response_timeout --\nwhich sounded like the other half of what you were describing. Backups are\nunaffected: cinder-backup has no caller to retry, so it treats it like any\nother failure and falls back to a full scan.","commit_id":"be1cb90fbb1beb0846e9d5ad2fd8a3678a62d4dd"},{"author":{"_account_id":36171,"name":"jayaanand borra","display_name":"jayaanand borra","email":"jayaanand.borra@netapp.com","username":"jayaanan","status":"netapp"},"change_message_id":"8ee718d9a36da2a351ec930c54696cc46d4408b1","unresolved":true,"context_lines":[{"line_number":274,"context_line":"                \u0027length\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 1},"},{"line_number":275,"context_line":"                \u0027marker\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 0},"},{"line_number":276,"context_line":"                \u0027limit\u0027: {\u0027type\u0027: \u0027integer\u0027, \u0027minimum\u0027: 1},"},{"line_number":277,"context_line":"            },"},{"line_number":278,"context_line":"            \u0027required\u0027: [\u0027target_snapshot_id\u0027],"},{"line_number":279,"context_line":"            \u0027additionalProperties\u0027: False,"},{"line_number":280,"context_line":"        },"}],"source_content_type":"text/x-python","patch_set":28,"id":"874d7475_d2eb2944","line":277,"in_reply_to":"d1704bc8_d53b870b","updated":"2026-08-16 04:09:55.000000000","message":"Ack, that makes sense for the backup-tool case. Our API is synchronous and there are limits in REST and RPC timeouts and current code handles as 409 \"Changed block information is not available\"","commit_id":"be1cb90fbb1beb0846e9d5ad2fd8a3678a62d4dd"}],"cinder/backup/chunkeddriver.py":[{"author":{"_account_id":34860,"name":"Amit Uniyal","email":"auniyal@redhat.com","username":"auniyal"},"change_message_id":"20c0cd6743d07a239c7b3dd33018f5ba85d6b430","unresolved":true,"context_lines":[{"line_number":104,"context_line":"       drivers."},{"line_number":105,"context_line":"    \"\"\""},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"    DRIVER_VERSION \u003d \u00271.0.0\u0027"},{"line_number":108,"context_line":"    DRIVER_VERSION_MAPPING \u003d {\u00271.0.0\u0027: \u0027_restore_v1\u0027}"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    def _get_compressor(self, algorithm):"}],"source_content_type":"text/x-python","patch_set":26,"id":"03487e97_cf8ab46c","line":107,"updated":"2026-09-01 05:48:44.000000000","message":"should this be bumped? as new-key is written in metadata \nmetadata[\u0027sparse\u0027] \u003d True","commit_id":"4e5c4d53ab4e4a02e5533a56d3375661274b3883"},{"author":{"_account_id":4523,"name":"Eric Harney","email":"eharney@redhat.com","username":"eharney"},"change_message_id":"89a95e4780fc81ab6719d9757e334b263decf5b9","unresolved":true,"context_lines":[{"line_number":104,"context_line":"       drivers."},{"line_number":105,"context_line":"    \"\"\""},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"    DRIVER_VERSION \u003d \u00271.0.0\u0027"},{"line_number":108,"context_line":"    DRIVER_VERSION_MAPPING \u003d {\u00271.0.0\u0027: \u0027_restore_v1\u0027}"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    def _get_compressor(self, algorithm):"}],"source_content_type":"text/x-python","patch_set":26,"id":"e2431275_23a6eb4e","line":107,"in_reply_to":"03487e97_cf8ab46c","updated":"2026-09-03 14:37:27.000000000","message":"I don\u0027t think we generally try to track versions in this base driver class, only in actual drivers. It looks like this would change if we needed to update the restore method to be different from _restore_v1.","commit_id":"4e5c4d53ab4e4a02e5533a56d3375661274b3883"}],"cinder/backup/manager.py":[{"author":{"_account_id":36171,"name":"jayaanand borra","display_name":"jayaanand borra","email":"jayaanand.borra@netapp.com","username":"jayaanan","status":"netapp"},"change_message_id":"a4e897c472c1e9df17f3940f35082a571154b175","unresolved":true,"context_lines":[{"line_number":740,"context_line":"        # so that get_cbt_extents stays side-effect-free -- it only diffs two"},{"line_number":741,"context_line":"        # snapshots that already exist.  This keeps the driver contract shared"},{"line_number":742,"context_line":"        # with the changed-blocks API, which diffs two pre-existing snapshots."},{"line_number":743,"context_line":"        to_snapshot \u003d self._cbt_snapshot_name(backup)"},{"line_number":744,"context_line":"        try:"},{"line_number":745,"context_line":"            ref \u003d self.volume_rpcapi.create_cbt_snapshot("},{"line_number":746,"context_line":"                context, volume, to_snapshot)"}],"source_content_type":"text/x-python","patch_set":8,"id":"1079d3fd_bb2413df","line":743,"updated":"2026-06-14 14:03:10.000000000","message":"duplicate code block","commit_id":"b885608b63e30f63d2a015aeba58cc84b3fff47a"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"445131b51d7051b5ff52e13e5958545abffca8e7","unresolved":false,"context_lines":[{"line_number":740,"context_line":"        # so that get_cbt_extents stays side-effect-free -- it only diffs two"},{"line_number":741,"context_line":"        # snapshots that already exist.  This keeps the driver contract shared"},{"line_number":742,"context_line":"        # with the changed-blocks API, which diffs two pre-existing snapshots."},{"line_number":743,"context_line":"        to_snapshot \u003d self._cbt_snapshot_name(backup)"},{"line_number":744,"context_line":"        try:"},{"line_number":745,"context_line":"            ref \u003d self.volume_rpcapi.create_cbt_snapshot("},{"line_number":746,"context_line":"                context, volume, to_snapshot)"}],"source_content_type":"text/x-python","patch_set":8,"id":"16b70931_ab8ef692","line":743,"in_reply_to":"1079d3fd_bb2413df","updated":"2026-06-15 13:49:42.000000000","message":"Done","commit_id":"b885608b63e30f63d2a015aeba58cc84b3fff47a"}],"doc/source/contributor/cbt-backup-driver-guide.rst":[{"author":{"_account_id":34860,"name":"Amit Uniyal","email":"auniyal@redhat.com","username":"auniyal"},"change_message_id":"c0e66dbfea6bd19dde884d3ea9438b80a4c0c33f","unresolved":true,"context_lines":[{"line_number":217,"context_line":"Reference implementation"},{"line_number":218,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":219,"context_line":""},{"line_number":220,"context_line":"A minimal, fully commented worked example lives at"},{"line_number":221,"context_line":"``cinder/tests/fake_cbt_driver.py`` (``FakeCBTVolumeDriver``), with tests in"},{"line_number":222,"context_line":"``cinder/tests/unit/volume/drivers/test_fake_cbt_driver.py``. It models the"},{"line_number":223,"context_line":"\"backend\" as an in-memory map of written blocks and implements the three"},{"line_number":224,"context_line":"methods against it, so you can read the whole contract -- allocation-map"},{"line_number":225,"context_line":"(``from_snapshot\u003dNone``) diffs, incremental diffs including the data-\u003ezero"}],"source_content_type":"text/x-rst","patch_set":23,"id":"006f048f_8f3f02a2","line":222,"range":{"start_line":220,"start_character":42,"end_line":222,"end_character":61},"updated":"2026-07-27 14:28:56.000000000","message":"both of these don\u0027t exists yet. as not part of this commit or merged already.\nI guess they were planned but missed.","commit_id":"5069b31d50f6776e6f13c9a423378d078cd44d6f"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"9b10f49b809ecc09ec65b3f85bee17cb2b3e8780","unresolved":false,"context_lines":[{"line_number":217,"context_line":"Reference implementation"},{"line_number":218,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":219,"context_line":""},{"line_number":220,"context_line":"A minimal, fully commented worked example lives at"},{"line_number":221,"context_line":"``cinder/tests/fake_cbt_driver.py`` (``FakeCBTVolumeDriver``), with tests in"},{"line_number":222,"context_line":"``cinder/tests/unit/volume/drivers/test_fake_cbt_driver.py``. It models the"},{"line_number":223,"context_line":"\"backend\" as an in-memory map of written blocks and implements the three"},{"line_number":224,"context_line":"methods against it, so you can read the whole contract -- allocation-map"},{"line_number":225,"context_line":"(``from_snapshot\u003dNone``) diffs, incremental diffs including the data-\u003ezero"}],"source_content_type":"text/x-rst","patch_set":23,"id":"a2ef6205_8936c98c","line":222,"range":{"start_line":220,"start_character":42,"end_line":222,"end_character":61},"in_reply_to":"006f048f_8f3f02a2","updated":"2026-08-05 22:41:37.000000000","message":"added some clarity to the comment that this is covered in a companion patch","commit_id":"5069b31d50f6776e6f13c9a423378d078cd44d6f"}],"releasenotes/notes/fix-incremental-restore-data-to-zero-6f3b9c2d1a4e0b7c.yaml":[{"author":{"_account_id":34860,"name":"Amit Uniyal","email":"auniyal@redhat.com","username":"auniyal"},"change_message_id":"c0e66dbfea6bd19dde884d3ea9438b80a4c0c33f","unresolved":true,"context_lines":[{"line_number":9,"context_line":"    changed from data to zero between backups was skipped instead of being"},{"line_number":10,"context_line":"    zeroed -- leaving the base backup\u0027s stale data at that offset in the"},{"line_number":11,"context_line":"    restored volume.  Incrementals are now always written in full; only the"},{"line_number":12,"context_line":"    base backup skips zero chunks."}],"source_content_type":"text/x-yaml","patch_set":23,"id":"2a87b896_fb870662","line":12,"updated":"2026-07-27 14:28:56.000000000","message":"this is too big to have bug fixes included.\nI think this fix should be in separate patch before this feature-patch\n\nit should be separated to easily backport bugfix independently, as this affects existing chunked backup restores regardless of CBT.","commit_id":"5069b31d50f6776e6f13c9a423378d078cd44d6f"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"9b10f49b809ecc09ec65b3f85bee17cb2b3e8780","unresolved":false,"context_lines":[{"line_number":9,"context_line":"    changed from data to zero between backups was skipped instead of being"},{"line_number":10,"context_line":"    zeroed -- leaving the base backup\u0027s stale data at that offset in the"},{"line_number":11,"context_line":"    restored volume.  Incrementals are now always written in full; only the"},{"line_number":12,"context_line":"    base backup skips zero chunks."}],"source_content_type":"text/x-yaml","patch_set":23,"id":"7c09c1ec_f4202c9f","line":12,"in_reply_to":"2a87b896_fb870662","updated":"2026-08-05 22:41:37.000000000","message":"bugfix seperated - see 999911 in the relation chain","commit_id":"5069b31d50f6776e6f13c9a423378d078cd44d6f"}]}
