Skip to content

Commit 55300a5

Browse files
beamandalagjkeller
authored andcommitted
Checkpoint
Signed-off-by: Gabriel Keller <gabrieljameskeller@gmail.com>
1 parent 52ea507 commit 55300a5

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

src/vmm/src/snapshot/mod.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,22 @@ impl SnapshotHdr {
8686
version,
8787
}
8888
}
89+
90+
fn load<R: Read>(reader: &mut R) -> Result<Self, SnapshotError> {
91+
let hdr: SnapshotHdr = bincode::DefaultOptions::new()
92+
.with_limit(VM_STATE_DESERIALIZE_LIMIT)
93+
.with_fixint_encoding()
94+
.allow_trailing_bytes() // need this because we deserialize header and snapshot from the same file, so after
95+
// reading the header, there will be trailing bytes.
96+
.deserialize_from(reader)
97+
.map_err(|err| SnapshotError::Serde(err.to_string()))?;
98+
99+
Ok(hdr)
100+
}
101+
102+
fn store<W: Write>(&self, writer: &mut W) -> Result<(), SnapshotError> {
103+
bincode::serialize_into(writer, self).map_err(|err| SnapshotError::Serde(err.to_string()))
104+
}
89105
}
90106

91107
/// Firecracker snapshot type
@@ -97,6 +113,98 @@ pub struct Snapshot {
97113
version: Version,
98114
}
99115

116+
#[derive(Debug, Serialize, Deserialize)]
117+
pub struct SnapshotNew<Data> {
118+
// The snapshot version we can handle
119+
version: Version,
120+
data: Data,
121+
}
122+
123+
impl<Data: for<'a> Deserialize<'a>> SnapshotNew<Data> {
124+
/// Helper function to deserialize an object from a reader
125+
pub fn deserialize<T, O>(reader: &mut T) -> Result<O, SnapshotError>
126+
where
127+
T: Read,
128+
O: DeserializeOwned + Debug,
129+
{
130+
// flags below are those used by default by bincode::deserialize_from, plus `with_limit`.
131+
bincode::DefaultOptions::new()
132+
.with_limit(VM_STATE_DESERIALIZE_LIMIT)
133+
.with_fixint_encoding()
134+
.allow_trailing_bytes() // need this because we deserialize header and snapshot from the same file, so after
135+
// reading the header, there will be trailing bytes.
136+
.deserialize_from(reader)
137+
.map_err(|err| SnapshotError::Serde(err.to_string()))
138+
}
139+
140+
pub fn load_unchecked<R: Read>(reader: &mut R) -> Result<Self, SnapshotError> where Data: DeserializeOwned + Debug {
141+
let hdr: SnapshotHdr = Self::deserialize(reader)?;
142+
if hdr.magic != SNAPSHOT_MAGIC_ID {
143+
return Err(SnapshotError::InvalidMagic(hdr.magic));
144+
}
145+
146+
let data: Data = Self::deserialize(reader)?;
147+
Ok(Self {
148+
version: hdr.version,
149+
data
150+
})
151+
}
152+
153+
pub fn load<R: Read>(reader: &mut R, snapshot_len: usize) -> Result<Self, SnapshotError> where Data: DeserializeOwned + Debug {
154+
let mut crc_reader = CRC64Reader::new(reader);
155+
156+
// Fail-fast if the snapshot length is too small
157+
let raw_snapshot_len = snapshot_len
158+
.checked_sub(std::mem::size_of::<u64>())
159+
.ok_or(SnapshotError::InvalidSnapshotSize)?;
160+
161+
// Read everything apart from the CRC.
162+
let mut snapshot = vec![0u8; raw_snapshot_len];
163+
crc_reader
164+
.read_exact(&mut snapshot)
165+
.map_err(|ref err| SnapshotError::Io(err.raw_os_error().unwrap_or(libc::EINVAL)))?;
166+
167+
// Since the reader updates the checksum as bytes ar being read from it, the order of these
168+
// 2 statements is important, we first get the checksum computed on the read bytes
169+
// then read the stored checksum.
170+
let computed_checksum = crc_reader.checksum();
171+
let stored_checksum: u64 = Self::deserialize(&mut crc_reader)?;
172+
if computed_checksum != stored_checksum {
173+
return Err(SnapshotError::Crc64(computed_checksum));
174+
}
175+
176+
let mut snapshot_slice: &[u8] = snapshot.as_mut_slice();
177+
SnapshotNew::load_unchecked::<_>(&mut snapshot_slice)
178+
}
179+
}
180+
181+
impl<Data: Serialize> SnapshotNew<Data> {
182+
/// Helper function to serialize an object to a writer
183+
pub fn serialize<T, O>(writer: &mut T, data: &O) -> Result<(), SnapshotError>
184+
where
185+
T: Write,
186+
O: Serialize + Debug,
187+
{
188+
bincode::serialize_into(writer, data).map_err(|err| SnapshotError::Serde(err.to_string()))
189+
}
190+
191+
pub fn save<W: Write>(&self, writer: &mut W) -> Result<usize, SnapshotError> {
192+
// Write magic value and snapshot version
193+
Self::serialize(&mut writer, &SnapshotHdr::new(self.version.clone()))?;
194+
// Write data
195+
Self::serialize(&mut writer, self.data)
196+
}
197+
198+
pub fn save_with_crc<W: Write>(&self, writer: &mut W) -> Result<usize, SnapshotError> {
199+
let mut crc_writer = CRC64Writer::new(writer);
200+
self.save(&mut crc_writer)?;
201+
202+
// Now write CRC value
203+
let checksum = crc_writer.checksum();
204+
Self::serialize(&mut crc_writer, &checksum)
205+
}
206+
}
207+
100208
impl Snapshot {
101209
/// Creates a new instance which can only be used to save a new snapshot.
102210
pub fn new(version: Version) -> Snapshot {

0 commit comments

Comments
 (0)