From abc03f998ae377335f85e2228cbd3dcd38802236 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 30 Jun 2026 17:33:19 +0200 Subject: [PATCH] block: qcow: Read refcount rebuild markers positionally The refcount rebuild check issued a seek to the refcount table and to the first refblock before each cursor read. Read the fixed size fields with read_exact_at at their offsets and decode with from_be_bytes. The seeks and the matching error paths go away. The result is unchanged. Signed-off-by: Anatol Belski --- block/src/formats/qcow/internal/mod.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/block/src/formats/qcow/internal/mod.rs b/block/src/formats/qcow/internal/mod.rs index ff3071ff2..41f58fbd0 100644 --- a/block/src/formats/qcow/internal/mod.rs +++ b/block/src/formats/qcow/internal/mod.rs @@ -18,6 +18,7 @@ use std::fmt::{Debug, Formatter, Result as FmtResult}; use std::fs::{OpenOptions, read_link}; use std::io::{self, Seek, SeekFrom}; use std::os::fd::AsRawFd; +use std::os::unix::fs::FileExt; use std::path::Path; use std::{result, str}; @@ -387,15 +388,15 @@ pub(crate) fn parse_qcow( // The first cluster should always have a non-zero refcount, so if it is 0, // this is an old file with broken refcounts, which requires a rebuild. let mut refcount_rebuild_required = true; - file.seek(SeekFrom::Start(header.refcount_table_offset)) - .map_err(|e| BlockError::new(BlockErrorKind::Io, Error::SeekingFile(e)))?; - let first_refblock_addr = u64::read_be(&mut file) + let mut first_refblock_bytes = [0u8; 8]; + file.read_exact_at(&mut first_refblock_bytes, header.refcount_table_offset) .map_err(|e| BlockError::new(BlockErrorKind::Io, Error::ReadingHeader(e)))?; + let first_refblock_addr = u64::from_be_bytes(first_refblock_bytes); if first_refblock_addr != 0 { - file.seek(SeekFrom::Start(first_refblock_addr)) - .map_err(|e| BlockError::new(BlockErrorKind::Io, Error::SeekingFile(e)))?; - let first_cluster_refcount = u16::read_be(&mut file) + let mut refcount_bytes = [0u8; 2]; + file.read_exact_at(&mut refcount_bytes, first_refblock_addr) .map_err(|e| BlockError::new(BlockErrorKind::Io, Error::ReadingHeader(e)))?; + let first_cluster_refcount = u16::from_be_bytes(refcount_bytes); if first_cluster_refcount != 0 { refcount_rebuild_required = false; }