@@ -86,6 +86,22 @@ impl SnapshotHdr {
86
86
version,
87
87
}
88
88
}
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
+ }
89
105
}
90
106
91
107
/// Firecracker snapshot type
@@ -97,6 +113,98 @@ pub struct Snapshot {
97
113
version : Version ,
98
114
}
99
115
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
+
100
208
impl Snapshot {
101
209
/// Creates a new instance which can only be used to save a new snapshot.
102
210
pub fn new ( version : Version ) -> Snapshot {
0 commit comments