Skip to content

Commit d5c72c6

Browse files
committed
Checkpoint
1 parent c9cc8d1 commit d5c72c6

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
@@ -80,6 +80,22 @@ impl SnapshotHdr {
8080
version,
8181
}
8282
}
83+
84+
fn load<R: Read>(reader: &mut R) -> Result<Self, SnapshotError> {
85+
let hdr: SnapshotHdr = bincode::DefaultOptions::new()
86+
.with_limit(VM_STATE_DESERIALIZE_LIMIT)
87+
.with_fixint_encoding()
88+
.allow_trailing_bytes() // need this because we deserialize header and snapshot from the same file, so after
89+
// reading the header, there will be trailing bytes.
90+
.deserialize_from(reader)
91+
.map_err(|err| SnapshotError::Serde(err.to_string()))?;
92+
93+
Ok(hdr)
94+
}
95+
96+
fn store<W: Write>(&self, writer: &mut W) -> Result<(), SnapshotError> {
97+
bincode::serialize_into(writer, self).map_err(|err| SnapshotError::Serde(err.to_string()))
98+
}
8399
}
84100

85101
/// Firecracker snapshot type
@@ -91,6 +107,98 @@ pub struct Snapshot {
91107
version: Version,
92108
}
93109

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

0 commit comments

Comments
 (0)