Skip to content

Commit 239b0a7

Browse files
committed
bug fix
Signed-off-by: Wenhao Ren <[email protected]>
1 parent 5f26f8e commit 239b0a7

File tree

18 files changed

+1386
-109
lines changed

18 files changed

+1386
-109
lines changed

Cargo.lock

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

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

+68
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,74 @@ 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 blob_ccis = device.get_all_blob_cci();
183+
184+
let mut found_root_inode = false;
185+
for ino in prefetch_table.inodes {
186+
// Inode number 0 is invalid, it was added because prefetch table has to be aligned.
187+
if ino == 0 {
188+
break;
189+
}
190+
if ino as Inode == root_ino {
191+
found_root_inode = true;
192+
}
193+
// debug!("CMDebug: hint prefetch inode {}", ino);
194+
195+
let ranges = self
196+
.get_inode_ranges(
197+
ino as u64,
198+
&mut hardlinks,
199+
&mut fetched_ranges,
200+
device,
201+
&blob_ccis,
202+
)
203+
.map_err(|e| {
204+
RafsError::Prefetch(format!("Failed in get inode chunk ranges. {:?}", e))
205+
})?;
206+
207+
// debug!("CMDebug: prefetch inode: {}, ranges: {:?}", ino, ranges);
208+
209+
for r in ranges {
210+
device.add_stream_prefetch_range(r).map_err(|e| {
211+
RafsError::Prefetch(format!("Failed to add inode prefetch range. {:?}", e))
212+
})?;
213+
}
214+
}
215+
216+
device.flush_stream_prefetch().map_err(|e| {
217+
RafsError::Prefetch(format!("Failed to flush inode prefetch range. {:?}", e))
218+
})?;
219+
220+
Ok(found_root_inode)
221+
}
154222
}
155223

156224
#[cfg(test)]

0 commit comments

Comments
 (0)