From 7cf2d4a2d70c1445f549ab151c76cea8c5984839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B3=B0=E5=8F=8B?= Date: Mon, 4 Mar 2024 10:02:36 +0000 Subject: [PATCH] fix: bad read by wrong data region MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User io may involve discontinuous segments in different chunks. Bad read is produced by merging them into continuous one. That is what Region does. This pr separate discontinuous segments into different regions, avoiding merging forcibly. Signed-off-by: 泰友 --- storage/src/cache/cachedfile.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/storage/src/cache/cachedfile.rs b/storage/src/cache/cachedfile.rs index 4122384a250..d30bcb1762b 100644 --- a/storage/src/cache/cachedfile.rs +++ b/storage/src/cache/cachedfile.rs @@ -1662,6 +1662,20 @@ impl FileIoMergeState { tag: BlobIoTag, chunk: Option>, ) -> Result<()> { + // Make sure user io of same region continuous + if !self.regions.is_empty() && self.joinable(region_type) { + let region = &self.regions[self.regions.len() - 1]; + if !region.seg.is_empty() && tag.is_user_io() { + if let BlobIoTag::User(ref seg) = tag { + if seg.offset as u64 + start + != region.blob_address + region.seg.offset as u64 + region.seg.len as u64 + { + self.commit(); + } + } + } + } + if self.regions.is_empty() || !self.joinable(region_type) { self.regions.push(Region::new(region_type)); self.last_region_joinable = true; @@ -1793,7 +1807,7 @@ mod tests { let tag = BlobIoTag::User(BlobIoSegment { offset: 0x1800, - len: 0x1800, + len: 0x800, }); state .push(RegionType::CacheFast, 0x1000, 0x2000, tag, None) @@ -1810,8 +1824,8 @@ mod tests { assert_eq!(state.regions.len(), 1); let tag = BlobIoTag::User(BlobIoSegment { - offset: 0x0000, - len: 0x2000, + offset: 0x0001, + len: 0x1fff, }); state .push(RegionType::CacheSlow, 0x5000, 0x2000, tag, None)