Skip to content

Commit

Permalink
Feat(vhd): implement copyless merging
Browse files Browse the repository at this point in the history
  • Loading branch information
fbeauchamp committed Jun 13, 2022
1 parent 808fc0d commit ca35ed2
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 4 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
<!--packages-start-->

- vhd-lib minor
- xo-server minor
- @vates/read-chunk major
- xo-server patch
- @xen-orchestra/backups minor

<!--packages-end-->
2 changes: 1 addition & 1 deletion packages/vhd-lib/Vhd/VhdDirectory.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ exports.VhdDirectory = class VhdDirectory extends VhdAbstract {
if (!child.isBlockBased() || this._handler !== child._handler || child.compressionType !== this.compressionType) {
return super.coalesceBlock(child, blockId)
}
await this._handler.copy(child.getFullBlockPath(blockId), this.getFullBlockPath(blockId))
await this._handler.rename(child.getFullBlockPath(blockId), this.getFullBlockPath(blockId))
return sectorsToBytes(this.sectorsPerBlock)
}

Expand Down
22 changes: 20 additions & 2 deletions packages/vhd-lib/merge.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ module.exports.mergeVhd = limitConcurrency(2)(async function merge(

return await Disposable.use(async function* () {
let mergeState
let isResuming = false
try {
const mergeStateContent = await parentHandler.readFile(mergeStatePath)
mergeState = JSON.parse(mergeStateContent)
Expand Down Expand Up @@ -122,6 +123,7 @@ module.exports.mergeVhd = limitConcurrency(2)(async function merge(
assert.strictEqual(childVhd.footer.diskType, DISK_TYPES.DIFFERENCING)
assert.strictEqual(childVhd.header.blockSize, parentVhd.header.blockSize)
} else {
isResuming = true
// vhd should not have changed to resume
assert.strictEqual(parentVhd.header.checksum, mergeState.parent.header)
assert.strictEqual(childVhd.header.checksum, mergeState.child.header)
Expand Down Expand Up @@ -162,12 +164,28 @@ module.exports.mergeVhd = limitConcurrency(2)(async function merge(
let counter = 0

const mergeStateWriter = makeThrottledWriter(parentHandler, mergeStatePath, 10e3)

await asyncEach(
toMerge,
async blockId => {
merging.add(blockId)
mergeState.mergedDataSize += await parentVhd.coalesceBlock(childVhd, blockId)
try {
mergeState.mergedDataSize += await parentVhd.coalesceBlock(childVhd, blockId)
} catch (error) {
if (error.code === 'ENOENT' && isResuming === true) {
// when resuming, the blocks moved since the last merge state write are
// not in the child anymore but it should be ok

// it will throw an error if block is missing in parent
// won't detect if the block was already in parent and is broken/missing in child
const { data } = await parentVhd.readBlock(blockId)
assert.strictEqual(data.length, parentVhd.header.blockSize)

mergeState.mergedDataSize += parentVhd.header.blockSize
} else {
throw error
}
}

merging.delete(blockId)

onProgress({
Expand Down

0 comments on commit ca35ed2

Please sign in to comment.