Skip to content

Commit 3221e31

Browse files
committed
refactor: seed assembly response from fast path partial data, avoid redundant try_serve calls
1 parent 15cedd4 commit 3221e31

1 file changed

Lines changed: 29 additions & 42 deletions

File tree

src/virtual_fs/mod.rs

Lines changed: 29 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,58 +1258,38 @@ impl VirtualFs {
12581258
// Maximum bytes we should return (capped at file boundary).
12591259
let to_read = ((size as u64).min(file_size - offset)) as usize;
12601260

1261-
// Fast path: forward buffer has enough data (common case, zero-copy).
12621261
// IMPORTANT: Never return a short read unless at real EOF.
12631262
// The Linux FUSE kernel module shrinks i_size on short reads
12641263
// (fuse_read_update_size), which makes subsequent reads return
12651264
// 0 bytes and truncates the file from the application's view.
1266-
if let Some(data) = prefetch_state.try_serve_forward(offset, size)
1267-
&& data.len() == to_read
1268-
{
1269-
debug!("prefetch hit (forward): offset={}, len={}", offset, data.len());
1270-
let eof = offset + data.len() as u64 >= file_size;
1271-
return Ok((data, eof));
1272-
}
12731265

1274-
// Seek window fast path (also zero-copy)
1275-
if let Some(data) = prefetch_state.try_serve_seek(offset, size)
1276-
&& data.len() == to_read
1277-
{
1278-
debug!("prefetch hit (seek): offset={}, len={}", offset, data.len());
1279-
let eof = offset + data.len() as u64 >= file_size;
1280-
return Ok((data, eof));
1281-
}
1282-
1283-
// Assembly loop: serve available bytes, fetch more, repeat.
1284-
// Only reached at prefetch window boundaries or cache misses.
12851266
let mut response = BytesMut::with_capacity(to_read);
12861267
let mut cursor = offset;
12871268

1288-
loop {
1289-
// Drain forward buffer into response
1290-
let remaining = (to_read - response.len()) as u32;
1291-
if let Some(data) = prefetch_state.try_serve_forward(cursor, remaining) {
1292-
cursor += data.len() as u64;
1293-
response.extend_from_slice(&data);
1294-
if response.len() == to_read {
1295-
break;
1296-
}
1269+
// Fast path: forward buffer has enough data (common case, zero-copy).
1270+
if let Some(data) = prefetch_state.try_serve_forward(offset, size) {
1271+
if data.len() == to_read {
1272+
debug!("prefetch hit (forward): offset={}, len={}", offset, data.len());
1273+
let eof = offset + data.len() as u64 >= file_size;
1274+
return Ok((data, eof));
12971275
}
1298-
1299-
// Also try seek window; if it produces data, loop back to
1300-
// retry try_serve_forward at the new cursor before fetching.
1301-
if response.len() < to_read {
1302-
let remaining = (to_read - response.len()) as u32;
1303-
if let Some(data) = prefetch_state.try_serve_seek(cursor, remaining) {
1304-
cursor += data.len() as u64;
1305-
response.extend_from_slice(&data);
1306-
if response.len() == to_read {
1307-
break;
1308-
}
1309-
continue;
1310-
}
1276+
cursor += data.len() as u64;
1277+
response.extend_from_slice(&data);
1278+
} else if let Some(data) = prefetch_state.try_serve_seek(offset, size) {
1279+
// Seek window: only reachable when forward buffer has no data
1280+
// at this offset (backward seek). Zero-copy on full hit.
1281+
if data.len() == to_read {
1282+
debug!("prefetch hit (seek): offset={}, len={}", offset, data.len());
1283+
let eof = offset + data.len() as u64 >= file_size;
1284+
return Ok((data, eof));
13111285
}
1286+
cursor += data.len() as u64;
1287+
response.extend_from_slice(&data);
1288+
}
13121289

1290+
// Assembly loop: fetch more data until we have to_read bytes.
1291+
// Only reached at prefetch window boundaries or cache misses.
1292+
while response.len() < to_read {
13131293
// Fetch more data
13141294
let remaining = (to_read - response.len()) as u32;
13151295
let plan = prefetch_state.prepare_fetch(cursor, remaining);
@@ -1478,7 +1458,7 @@ impl VirtualFs {
14781458
}
14791459
};
14801460

1481-
// Store fetched chunks and loop back to drain them
1461+
// Store fetched chunks
14821462
prefetch_state.store_fetched(cursor, chunks, total);
14831463

14841464
// No-progress guard: return EIO rather than a short read
@@ -1494,6 +1474,13 @@ impl VirtualFs {
14941474
);
14951475
return Err(libc::EIO);
14961476
}
1477+
1478+
// Drain freshly filled buffer into response
1479+
let remaining = (to_read - response.len()) as u32;
1480+
if let Some(data) = prefetch_state.try_serve_forward(cursor, remaining) {
1481+
cursor += data.len() as u64;
1482+
response.extend_from_slice(&data);
1483+
}
14971484
}
14981485

14991486
let eof = cursor >= file_size;

0 commit comments

Comments
 (0)