Skip to content

Commit 22439be

Browse files
authored
Merge pull request #11 from AkihiroSuda/dev
Fix random read
2 parents 0824f16 + 6ab548d commit 22439be

File tree

2 files changed

+37
-13
lines changed

2 files changed

+37
-13
lines changed

hack/compare-with-qemu-img.sh

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ set -x
1414
go-qcow2reader-example -info "${name_qcow2}"
1515
set +x
1616

17+
echo "===== Phase 1: full read ====="
1718
if [ ! -e "${name_raw_a}" ]; then
1819
echo "Converting ${name_qcow2} to ${name_raw_a} with qemu-img"
1920
set -x
@@ -46,7 +47,26 @@ else
4647
exit 1
4748
fi
4849

49-
echo "Cleaning up..."
50+
echo "===== Phase 2: random read ====="
51+
for offset in 1 22 333 4444 55555 666666 7777777 88888888; do
52+
for length in 1 22 333 4444 55555 666666 7777777 88888888; do
53+
set -x
54+
set +o pipefail
55+
expected="$(tail -c "+$((${offset} + 1))" "${name_raw_a}" | head -c "${length}" | sha256sum - | cut -d " " -f 1)"
56+
set -o pipefail
57+
got="$(go-qcow2reader-example -offset="${offset}" -length="${length}" "${name_qcow2}" | sha256sum - | cut -d " " -f 1)"
58+
set +x
59+
echo "Comparing: ${expected} vs ${got}"
60+
if [ "${expected}" = "${got}" ]; then
61+
echo "OK"
62+
else
63+
echo "FAIL"
64+
exit 1
65+
fi
66+
done
67+
done
68+
69+
echo "===== Cleaning up... ====="
5070
set -x
5171
rm -f "${name_raw_b}" "${name_raw_b}.sha256"
5272
set +x

image/qcow2/qcow2.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -802,10 +802,17 @@ func (img *Qcow2) readAtAlignedStandardExtendedL2(p []byte, off int64, desc stan
802802
var n int
803803
subclusterSize := img.clusterSize / 32
804804
hostClusterOffset := desc.hostClusterOffset()
805-
subclusterNo := (int(off) % img.clusterSize) / subclusterSize
806-
for i := subclusterNo; i < 32; i++ {
805+
subclusterNoBegin := (int(off) % img.clusterSize) / subclusterSize
806+
for i := subclusterNoBegin; i < 32; i++ { // i is the subcluster number
807+
currentOff := off + int64(n)
808+
clusterNo := currentOff / int64(img.clusterSize)
809+
clusterBegin := clusterNo * int64(img.clusterSize)
810+
subclusterBegin := clusterBegin + int64(i)*int64(subclusterSize)
811+
subclusterEnd := subclusterBegin + int64(subclusterSize)
812+
readSize := subclusterEnd - currentOff
813+
807814
pIdxBegin := n
808-
pIdxEnd := n + subclusterSize
815+
pIdxEnd := n + int(readSize)
809816
if pIdxEnd > len(p) {
810817
pIdxEnd = len(p)
811818
}
@@ -823,7 +830,6 @@ func (img *Qcow2) readAtAlignedStandardExtendedL2(p []byte, off int64, desc stan
823830
return n, fmt.Errorf("failed to read from the raw offset %d: %w", currentRawOff, err)
824831
}
825832
} else {
826-
currentOff := off + int64(n)
827833
if ((extL2Entry.ZeroStatusBitmap >> i) & 0b1) == 0b1 {
828834
currentN, err = img.readZero(p[pIdxBegin:pIdxEnd], currentOff)
829835
if err != nil {
@@ -902,15 +908,13 @@ func (img *Qcow2) ReadAt(p []byte, off int64) (n int, err error) {
902908

903909
for remaining > 0 {
904910
currentOff := off + int64(n)
905-
pIndexBegin := n
906-
pIndexEnd := n + int(img.clusterSize)
907-
908-
clusterBegin := (off + int64(pIndexBegin)) / int64(img.clusterSize)
909-
if clusterEnd := (off + int64(pIndexEnd)) / int64(img.clusterSize); clusterEnd != clusterBegin {
910-
currentSize := off + int64(img.clusterSize) - int64(n)
911-
pIndexEnd = pIndexBegin + int(currentSize)
912-
}
911+
clusterNo := currentOff / int64(img.clusterSize)
912+
clusterBegin := clusterNo * int64(img.clusterSize)
913+
clusterEnd := clusterBegin + int64(img.clusterSize)
914+
readSize := clusterEnd - currentOff
913915

916+
pIndexBegin := n
917+
pIndexEnd := n + int(readSize)
914918
if pIndexEnd > len(p) {
915919
pIndexEnd = len(p)
916920
}

0 commit comments

Comments
 (0)