Skip to content

Commit aa354d7

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

File tree

23 files changed

+1245
-22
lines changed

23 files changed

+1245
-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_read_stream(
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

+66-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.start_stream_prefetch();
181+
self.new_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,26 @@ impl Rafs {
338341
});
339342
}
340343

344+
#[allow(unused)]
345+
fn new_stream_prefetch(&self, reader: RafsIoReader, prefetch_files: Option<Vec<PathBuf>>) {
346+
debug!("CMDebug: new_stream_prefetch2");
347+
let sb = self.sb.clone();
348+
let device = self.device.clone();
349+
let prefetch_all = self.prefetch_all;
350+
let root_ino = self.root_ino();
351+
352+
let _ = std::thread::spawn(move || {
353+
Self::new_do_stream_prefetch(
354+
root_ino,
355+
reader,
356+
prefetch_files,
357+
prefetch_all,
358+
sb,
359+
device,
360+
);
361+
});
362+
}
363+
341364
/// for blobfs
342365
pub fn fetch_range_synchronous(&self, prefetches: &[BlobPrefetchRequest]) -> Result<()> {
343366
self.device.fetch_range_synchronous(prefetches)
@@ -347,6 +370,7 @@ impl Rafs {
347370
self.sb.superblock.root_ino()
348371
}
349372

373+
#[allow(unused)]
350374
fn do_prefetch(
351375
root_ino: u64,
352376
mut reader: RafsIoReader,
@@ -472,6 +496,46 @@ impl Rafs {
472496
}
473497
}
474498

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

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

+61
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,67 @@ impl RafsSuper {
151151

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

156217
#[cfg(test)]

0 commit comments

Comments
 (0)