Skip to content

Commit 87fedb9

Browse files
committed
pldm-file: Read file in chunks
Previously the host implementation would read the entire file at once, which could run out of memory. Instead read individual chunks. A Host::read() implementation can implement readahead/caching if desired. Signed-off-by: Matt Johnston <[email protected]>
1 parent 8f60d28 commit 87fedb9

File tree

1 file changed

+20
-18
lines changed

1 file changed

+20
-18
lines changed

pldm-file/src/host.rs

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ pub trait Host {
2626
// Created at the first stage (XFER_FIRST_PART) of a MultpartReceive,
2727
// where we have the offset and size.
2828
struct FileTransferContext {
29-
buf: Vec<u8>,
29+
// File starting offset
30+
start: usize,
31+
len: usize,
32+
// Current transfer 0..len
3033
offset: usize,
3134
}
3235

@@ -345,14 +348,14 @@ impl<const N: usize> Responder<N> {
345348
if let Some(ctx) = file_ctx.xfer_ctx.as_mut() {
346349
ctx.offset = 0;
347350
} else {
348-
let new_ctx = Self::init_read(&cmd, host)?;
351+
let new_ctx = Self::init_read(&cmd)?;
349352
// a repeated FIRST_PART is valid, and restarts the transfer
350353
file_ctx.xfer_ctx.replace(new_ctx);
351354
};
352355
}
353356

354357
let xfer_ctx = file_ctx.xfer_ctx.as_mut().ok_or(CCode::ERROR)?;
355-
let full_len = xfer_ctx.buf.len();
358+
let full_len = xfer_ctx.len;
356359

357360
let offset = match cmd.xfer_op {
358361
pldm::control::xfer_op::FIRST_PART
@@ -361,7 +364,7 @@ impl<const N: usize> Responder<N> {
361364
_ => Err(CCode::ERROR_INVALID_DATA)?,
362365
};
363366

364-
if offset >= xfer_ctx.buf.len() {
367+
if offset >= xfer_ctx.len {
365368
Err(CCode::ERROR_INVALID_DATA)?;
366369
}
367370

@@ -394,11 +397,13 @@ impl<const N: usize> Responder<N> {
394397
let mut resp_data = Vec::new();
395398
resp_data.extend_from_slice(&dfread_resp.to_bytes()?);
396399

397-
let data = &xfer_ctx.buf[offset..offset + len];
400+
let l = resp_data.len();
401+
resp_data.resize(resp_data.len() + len, 0);
402+
let data = &mut resp_data[l..];
403+
host.read(data, xfer_ctx.start + offset)
404+
.map_err(|_| CCode::ERROR)?;
398405
let crc32 = crc::Crc::<u32>::new(&crc::CRC_32_ISO_HDLC);
399406
let cs = crc32.checksum(data);
400-
401-
resp_data.extend_from_slice(data);
402407
resp_data.extend_from_slice(&cs.to_le_bytes());
403408

404409
xfer_ctx.offset = offset;
@@ -409,18 +414,15 @@ impl<const N: usize> Responder<N> {
409414

410415
fn init_read(
411416
req: &pldm::control::MultipartReceiveReq,
412-
host: &mut impl Host,
413417
) -> Result<FileTransferContext> {
414-
let offset = req.req_offset;
415-
let len = req.req_length;
416-
417-
let mut buf = vec![0; len as usize];
418-
let read_len =
419-
host.read(&mut buf, offset as usize).or(Err(CCode::ERROR))?;
420-
421-
buf.truncate(read_len);
422-
423-
Ok(FileTransferContext { buf, offset: 0 })
418+
trace!("init_read {req:?}");
419+
let start = req.req_offset as usize;
420+
let len = req.req_length as usize;
421+
Ok(FileTransferContext {
422+
start,
423+
len,
424+
offset: 0,
425+
})
424426
}
425427
}
426428

0 commit comments

Comments
 (0)