Skip to content

Commit d230da9

Browse files
committed
initinal commit
Signed-off-by: Wenhao Ren <[email protected]>
1 parent 596492b commit d230da9

File tree

23 files changed

+1080
-22
lines changed

23 files changed

+1080
-22
lines changed

Cargo.lock

+16-15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

builder/src/compact.rs

+11
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,7 @@ mod tests {
669669
use super::*;
670670
use nydus_api::ConfigV2;
671671
use nydus_rafs::metadata::RafsSuperConfig;
672+
use nydus_storage::backend::registry::StreamCallback;
672673
use nydus_storage::backend::{BackendResult, BlobReader};
673674
use nydus_storage::device::v5::BlobV5ChunkInfo;
674675
use nydus_storage::device::{BlobChunkFlags, BlobChunkInfo, BlobFeatures};
@@ -759,6 +760,16 @@ mod tests {
759760
Ok(i)
760761
}
761762

763+
fn try_stream_read(
764+
&self,
765+
_offset: u64,
766+
_size: u32,
767+
_processed: &mut u64,
768+
_f: &mut StreamCallback,
769+
) -> BackendResult<()> {
770+
unimplemented!()
771+
}
772+
762773
fn metrics(&self) -> &BackendMetrics {
763774
// Safe because nydusd must have backend attached with id, only image builder can no id
764775
// but use backend instance to upload blob.

rafs/src/fs.rs

+57-2
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,10 @@ impl Rafs {
175175
}
176176
if self.fs_prefetch {
177177
// Device should be ready before any prefetch.
178-
self.device.start_prefetch();
179-
self.prefetch(r, prefetch_files);
178+
// self.device.start_prefetch();
179+
// self.prefetch(r, prefetch_files);
180+
self.device.init_stream_prefetch();
181+
self.start_stream_prefetch(r, prefetch_files);
180182
}
181183
self.initialized = true;
182184

@@ -327,6 +329,7 @@ impl Rafs {
327329
}
328330

329331
impl Rafs {
332+
#[allow(unused)]
330333
fn prefetch(&self, reader: RafsIoReader, prefetch_files: Option<Vec<PathBuf>>) {
331334
let sb = self.sb.clone();
332335
let device = self.device.clone();
@@ -338,6 +341,18 @@ impl Rafs {
338341
});
339342
}
340343

344+
#[allow(unused)]
345+
fn start_stream_prefetch(&self, reader: RafsIoReader, prefetch_files: Option<Vec<PathBuf>>) {
346+
let sb = self.sb.clone();
347+
let device = self.device.clone();
348+
let prefetch_all = self.prefetch_all;
349+
let root_ino = self.root_ino();
350+
351+
let _ = std::thread::spawn(move || {
352+
Self::do_stream_prefetch(root_ino, reader, prefetch_files, prefetch_all, sb, device);
353+
});
354+
}
355+
341356
/// for blobfs
342357
pub fn fetch_range_synchronous(&self, prefetches: &[BlobPrefetchRequest]) -> Result<()> {
343358
self.device.fetch_range_synchronous(prefetches)
@@ -347,6 +362,7 @@ impl Rafs {
347362
self.sb.superblock.root_ino()
348363
}
349364

365+
#[allow(unused)]
350366
fn do_prefetch(
351367
root_ino: u64,
352368
mut reader: RafsIoReader,
@@ -472,6 +488,45 @@ impl Rafs {
472488
}
473489
}
474490

491+
fn do_stream_prefetch(
492+
root_ino: u64,
493+
mut reader: RafsIoReader,
494+
prefetch_files: Option<Vec<PathBuf>>,
495+
_prefetch_all: bool,
496+
sb: Arc<RafsSuper>,
497+
device: BlobDevice,
498+
) {
499+
// Bootstrap has non-empty prefetch table indicating a full prefetch
500+
let inlay_prefetch_all = sb
501+
.is_inlay_prefetch_all(&mut reader)
502+
.map_err(|e| error!("Detect prefetch table error {}", e))
503+
.unwrap_or_default();
504+
505+
// Nydusd has a CLI option indicating a full prefetch
506+
let startup_prefetch_all = prefetch_files
507+
.as_ref()
508+
.map(|f| f.len() == 1 && f[0].as_os_str() == "/")
509+
.unwrap_or(false);
510+
511+
// User specified prefetch files have high priority to be prefetched.
512+
// Moreover, user specified prefetch files list will override those on-disk prefetch table.
513+
if !startup_prefetch_all && !inlay_prefetch_all {
514+
// Then do file based prefetch based on:
515+
// - prefetch listed passed in by user
516+
// - or file prefetch list in metadata
517+
// TODO: change this to iterator
518+
let inodes = prefetch_files.map(|files| Self::convert_file_list(&files, &sb));
519+
let res = sb.stream_prefetch_files(&device, &mut reader, root_ino, inodes);
520+
match res {
521+
Ok(true) => {
522+
info!("Root inode was found, but it should not prefetch all files!")
523+
}
524+
Ok(false) => {}
525+
Err(e) => error!("No file to be prefetched {:?}", e),
526+
}
527+
}
528+
}
529+
475530
fn convert_file_list(files: &[PathBuf], sb: &Arc<RafsSuper>) -> Vec<Inode> {
476531
let mut inodes = Vec::<Inode>::with_capacity(files.len());
477532

rafs/src/metadata/direct_v6.rs

+1
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,7 @@ impl RafsInode for OndiskInodeWrapper {
847847
curr_chunk_index == tail_chunk_index,
848848
)
849849
.ok_or_else(|| einval!("failed to get chunk information"))?;
850+
//TODO:这里应该考虑某个中间的chunk的blob_index不同的情况
850851
if desc.blob.blob_index() != descs.blob_index() {
851852
vec.push(descs);
852853
descs = BlobIoVec::new(desc.blob.clone());

rafs/src/metadata/md_v6.rs

+60
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,66 @@ impl RafsSuper {
151151

152152
Ok(found_root_inode)
153153
}
154+
155+
pub(crate) fn stream_prefetch_data_v6(
156+
&self,
157+
device: &BlobDevice,
158+
rafs_reader: &mut RafsIoReader,
159+
root_ino: Inode,
160+
) -> RafsResult<bool> {
161+
let hint_entries = self.meta.prefetch_table_entries as usize;
162+
if hint_entries == 0 {
163+
return Ok(false);
164+
}
165+
166+
// Try to prefetch according to the list of files specified by the
167+
// builder's `--prefetch-policy fs` option.
168+
let mut prefetch_table = RafsV6PrefetchTable::new();
169+
prefetch_table
170+
.load_prefetch_table_from(rafs_reader, self.meta.prefetch_table_offset, hint_entries)
171+
.map_err(|e| {
172+
error!("Failed in loading hint prefetch table at offset {}", e);
173+
RafsError::Prefetch(format!(
174+
"Failed in loading hint prefetch table at offset {}. {:?}",
175+
self.meta.prefetch_table_offset, e
176+
))
177+
})?;
178+
debug!("prefetch table contents {:?}", prefetch_table);
179+
180+
let mut hardlinks: HashSet<u64> = HashSet::new();
181+
let mut fetched_ranges: HashMap<u32, HashSet<u64>> = HashMap::new();
182+
let mut found_root_inode = false;
183+
for ino in prefetch_table.inodes {
184+
// Inode number 0 is invalid, it was added because prefetch table has to be aligned.
185+
if ino == 0 {
186+
break;
187+
}
188+
if ino as Inode == root_ino {
189+
found_root_inode = true;
190+
}
191+
// debug!("CMDebug: hint prefetch inode {}", ino);
192+
193+
let ranges = self
194+
.get_inode_ranges(ino as u64, &mut hardlinks, &mut fetched_ranges, device)
195+
.map_err(|e| {
196+
RafsError::Prefetch(format!("Failed in get inode chunk ranges. {:?}", e))
197+
})?;
198+
199+
// debug!("CMDebug: prefetch inode: {}, ranges: {:?}", ino, ranges);
200+
201+
for r in ranges {
202+
device.add_stream_prefetch_range(r).map_err(|e| {
203+
RafsError::Prefetch(format!("Failed to add inode prefetch range. {:?}", e))
204+
})?;
205+
}
206+
}
207+
208+
device.flush_stream_prefetch().map_err(|e| {
209+
RafsError::Prefetch(format!("Failed to flush inode prefetch range. {:?}", e))
210+
})?;
211+
212+
Ok(found_root_inode)
213+
}
154214
}
155215

156216
#[cfg(test)]

0 commit comments

Comments
 (0)