Summary
sync.CopyPartitionRaw is intended to support copying a smaller source partition into a larger target — e.g. as the byte-level copy step when growing a partition before renaming it into place. But the post-copy verification in sync/verify.go rejects this case:
if size != expectedSize {
return fmt.Errorf("target partition size %d is different than expected size %d", size, expectedSize)
}
targetPart.ReadContents reads the full target partition's bytes and returns the full size, even when paired with a NewLimitWriter(...) that only feeds the leading expectedSize bytes into the hasher. So whenever targetSize > sourceSize, the size assertion fails and CopyPartitionRaw returns an error even though the actual byte copy succeeded.
Reproducer
// Two-partition GPT, source=8MB, target=24MB, both filled
// with arbitrary bytes. Then:
err := sync.CopyPartitionRaw(d, sourcePartIdx, targetPartIdx)
// err: "verification failed for partition N: target partition size 25165824
// is different than expected size 8388608"
A real reproducer is in diskfs/partitionresizer (its raw-copy path is the same CopyPartitionRaw call); the partition-grow flow there is currently blocked end-to-end on this verification.
Suggested fix
In verifyBlockCopy (sync/verify.go:14), when reading the target's bytes for hashing, either:
- Use a size-limited reader that only reads
expectedSize bytes from the target (and asserts the limit was reached), or
- Hash both source and target only over their leading
expectedSize bytes, and drop the size-equality check for the target.
Either keeps the byte-equality verification intact while making the function correct for the "target larger than source" case, which is the natural shape when growing a partition.
Impact
Any caller using CopyPartitionRaw to copy a smaller filesystem into a larger partition (squashfs / unknown-FS grow workflows) hits this. partitionresizer's grow-with-raw-copy path is blocked until this is fixed.
Summary
sync.CopyPartitionRawis intended to support copying a smaller source partition into a larger target — e.g. as the byte-level copy step when growing a partition before renaming it into place. But the post-copy verification insync/verify.gorejects this case:targetPart.ReadContentsreads the full target partition's bytes and returns the full size, even when paired with aNewLimitWriter(...)that only feeds the leadingexpectedSizebytes into the hasher. So whenevertargetSize > sourceSize, the size assertion fails andCopyPartitionRawreturns an error even though the actual byte copy succeeded.Reproducer
A real reproducer is in
diskfs/partitionresizer(its raw-copy path is the sameCopyPartitionRawcall); the partition-grow flow there is currently blocked end-to-end on this verification.Suggested fix
In
verifyBlockCopy(sync/verify.go:14), when reading the target's bytes for hashing, either:expectedSizebytes from the target (and asserts the limit was reached), orexpectedSizebytes, and drop the size-equality check for the target.Either keeps the byte-equality verification intact while making the function correct for the "target larger than source" case, which is the natural shape when growing a partition.
Impact
Any caller using
CopyPartitionRawto copy a smaller filesystem into a larger partition (squashfs / unknown-FS grow workflows) hits this.partitionresizer's grow-with-raw-copy path is blocked until this is fixed.