Skip to content

Commit 76a5a8e

Browse files
committed
storage: a series fixups for stargz chunks
Signed-off-by: Yan Song <[email protected]>
1 parent 25989f5 commit 76a5a8e

File tree

7 files changed

+70
-13
lines changed

7 files changed

+70
-13
lines changed

rafs/src/fs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,10 +1072,10 @@ pub(crate) mod tests {
10721072
config.fs_prefetch.threads_count = 1;
10731073
assert!(BlobPrefetchConfig::try_from(&config).is_ok());
10741074

1075-
config.fs_prefetch.merging_size = RAFS_MAX_CHUNK_SIZE as usize + 1;
1075+
config.fs_prefetch.merging_size = RAFS_DEFAULT_CHUNK_SIZE as usize + 1;
10761076
assert!(BlobPrefetchConfig::try_from(&config).is_err());
10771077

1078-
config.fs_prefetch.merging_size = RAFS_MAX_CHUNK_SIZE as usize;
1078+
config.fs_prefetch.merging_size = RAFS_DEFAULT_CHUNK_SIZE as usize;
10791079
config.fs_prefetch.bandwidth_rate = 1;
10801080
config.fs_prefetch.prefetch_all = true;
10811081
assert!(BlobPrefetchConfig::try_from(&config).is_ok());

rafs/src/metadata/layout/v6.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use lazy_static::lazy_static;
1717
use nydus_utils::{compress, digest, round_up, ByteSize};
1818
use storage::device::{BlobFeatures, BlobInfo};
1919
use storage::meta::{BlobMetaHeaderOndisk, BLOB_FEATURE_4K_ALIGNED};
20+
use storage::RAFS_MAX_CHUNK_SIZE;
2021

2122
use crate::metadata::{layout::RafsXAttrs, RafsStore, RafsSuperFlags};
2223
use crate::{impl_bootstrap_converter, impl_pub_getter_setter, RafsIoReader, RafsIoWrite};
@@ -352,7 +353,10 @@ impl RafsV6SuperBlockExt {
352353
}
353354

354355
let chunk_size = u32::from_le(self.s_chunk_size) as u64;
355-
if !chunk_size.is_power_of_two() || chunk_size < EROFS_BLOCK_SIZE {
356+
if !chunk_size.is_power_of_two()
357+
|| chunk_size < EROFS_BLOCK_SIZE
358+
|| chunk_size > RAFS_MAX_CHUNK_SIZE
359+
{
356360
return Err(einval!("invalid chunk size in Rafs v6 extended superblock"));
357361
}
358362

@@ -1292,7 +1296,11 @@ impl RafsV6Blob {
12921296
}
12931297

12941298
let c_size = u32::from_le(self.chunk_size) as u64;
1295-
if c_size.count_ones() != 1 || c_size < EROFS_BLOCK_SIZE || c_size != chunk_size as u64 {
1299+
if c_size.count_ones() != 1
1300+
|| c_size < EROFS_BLOCK_SIZE
1301+
|| c_size > RAFS_MAX_CHUNK_SIZE
1302+
|| c_size != chunk_size as u64
1303+
{
12961304
error!(
12971305
"RafsV6Blob: idx {} invalid c_size {}, count_ones() {}",
12981306
blob_index,

src/bin/nydusd/fs_cache.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,16 @@ impl FsCacheHandler {
584584
}
585585
Some(obj) => match obj.fetch_range_uncompressed(msg.off, msg.len) {
586586
Ok(v) if v == msg.len as usize => {}
587-
_ => debug!("fscache: failed to read data from blob object"),
587+
Ok(v) => {
588+
warn!(
589+
"fscache: read data from blob object not matched: {} != {}",
590+
v, msg.len
591+
);
592+
}
593+
Err(e) => error!(
594+
"{}",
595+
format!("fscache: failed to read data from blob object: {}", e,)
596+
),
588597
},
589598
}
590599
}

storage/src/cache/cachedfile.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,22 @@ impl BlobObject for FileCacheEntry {
359359

360360
impl FileCacheEntry {
361361
fn do_fetch_chunks(&self, chunks: &[BlobIoChunk]) -> Result<usize> {
362+
if self.is_stargz() {
363+
for chunk in chunks {
364+
let mut buf = alloc_buf(chunk.uncompress_size() as usize);
365+
self.read_raw_chunk(chunk, &mut buf, false, None)?;
366+
if self.dio_enabled {
367+
self.adjust_buffer_for_dio(&mut buf)
368+
}
369+
Self::persist_chunk(&self.file, chunk.uncompress_offset(), &buf)
370+
.map_err(|e| eio!(format!("do_fetch_chunk failed to persist data, {:?}", e)))?;
371+
self.chunk_map
372+
.set_ready_and_clear_pending(chunk.as_base())
373+
.unwrap_or_else(|e| error!("set ready failed, {}", e));
374+
}
375+
return Ok(0);
376+
}
377+
362378
debug_assert!(!chunks.is_empty());
363379
let bitmap = self
364380
.chunk_map

storage/src/cache/fscache/mod.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,6 @@ impl FileCacheEntry {
166166
if blob_info.has_feature(BlobFeatures::V5_NO_EXT_BLOB_TABLE) {
167167
return Err(einval!("fscache does not support Rafs v5 blobs"));
168168
}
169-
if blob_info.is_stargz() {
170-
return Err(einval!("fscache does not support stargz blob file"));
171-
}
172169
let file = blob_info
173170
.get_fscache_file()
174171
.ok_or_else(|| einval!("No fscache file associated with the blob_info"))?;
@@ -211,7 +208,7 @@ impl FileCacheEntry {
211208
is_get_blob_object_supported: true,
212209
is_compressed: false,
213210
is_direct_chunkmap: true,
214-
is_stargz: false,
211+
is_stargz: blob_info.is_stargz(),
215212
dio_enabled: true,
216213
need_validate: mgr.validate,
217214
prefetch_config,

storage/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ macro_rules! impl_getter {
7272

7373
/// Default blob chunk size.
7474
pub const RAFS_DEFAULT_CHUNK_SIZE: u64 = 1024 * 1024;
75-
/// Maximum blob chunk size.
76-
pub const RAFS_MAX_CHUNK_SIZE: u64 = 1024 * 1024;
75+
/// Maximum blob chunk size, 16MB.
76+
pub const RAFS_MAX_CHUNK_SIZE: u64 = 1024 * 1024 * 16;
7777

7878
/// Error codes related to storage subsystem.
7979
#[derive(Debug)]

storage/src/meta/mod.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ impl BlobMetaInfo {
412412
chunks: chunk_infos,
413413
base: base as *const u8,
414414
unmap_len: expected_size,
415+
is_stargz: blob_info.is_stargz(),
415416
});
416417

417418
Ok(BlobMetaInfo { state })
@@ -470,7 +471,9 @@ impl BlobMetaInfo {
470471
index += 1;
471472
let entry = &infos[index];
472473
self.validate_chunk(entry)?;
473-
if entry.uncompressed_offset() != last_end {
474+
475+
// For stargz chunks, disable this check.
476+
if !self.state.is_stargz && entry.uncompressed_offset() != last_end {
474477
return Err(einval!(format!(
475478
"mismatch uncompressed {} size {} last_end {}",
476479
entry.uncompressed_offset(),
@@ -567,7 +570,8 @@ impl BlobMetaInfo {
567570

568571
#[inline]
569572
fn validate_chunk(&self, entry: &BlobChunkInfoOndisk) -> Result<()> {
570-
if entry.compressed_end() > self.state.compressed_size
573+
// For stargz blob, self.state.compressed_size == 0, so don't validate it.
574+
if (!self.state.is_stargz && entry.compressed_end() > self.state.compressed_size)
571575
|| entry.uncompressed_end() > self.state.uncompressed_size
572576
{
573577
Err(einval!())
@@ -651,6 +655,8 @@ pub struct BlobMetaState {
651655
chunks: ManuallyDrop<Vec<BlobChunkInfoOndisk>>,
652656
base: *const u8,
653657
unmap_len: usize,
658+
/// The blob meta is for an stargz image.
659+
is_stargz: bool,
654660
}
655661

656662
// // Safe to Send/Sync because the underlying data structures are readonly
@@ -676,6 +682,25 @@ impl BlobMetaState {
676682
let mut start = 0;
677683
let mut end = 0;
678684

685+
if self.is_stargz {
686+
// FIXME: since stargz chunks are not currently allocated chunk index in the order of uncompressed_offset,
687+
// a binary search is not available for now, here is a heavy overhead workaround, need to be fixed.
688+
for i in 0..self.chunk_count {
689+
let off = if compressed {
690+
chunks[i as usize].compressed_offset()
691+
} else {
692+
chunks[i as usize].uncompressed_offset()
693+
};
694+
if addr == off {
695+
return Ok(i as usize);
696+
}
697+
}
698+
return Err(einval!(format!(
699+
"can't find stargz chunk by offset {}",
700+
addr,
701+
)));
702+
}
703+
679704
while left < right {
680705
let mid = left + size / 2;
681706
// SAFETY: the call is made safe by the following invariants:
@@ -804,6 +829,7 @@ mod tests {
804829
]),
805830
base: std::ptr::null(),
806831
unmap_len: 0,
832+
is_stargz: false,
807833
};
808834

809835
assert_eq!(state.get_chunk_index_nocheck(0, false).unwrap(), 0);
@@ -888,6 +914,7 @@ mod tests {
888914
]),
889915
base: std::ptr::null(),
890916
unmap_len: 0,
917+
is_stargz: false,
891918
};
892919
let info = BlobMetaInfo {
893920
state: Arc::new(state),

0 commit comments

Comments
 (0)