@@ -80,6 +80,22 @@ impl SnapshotHdr {
80
80
version,
81
81
}
82
82
}
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
+ }
83
99
}
84
100
85
101
/// Firecracker snapshot type
@@ -91,6 +107,98 @@ pub struct Snapshot {
91
107
version : Version ,
92
108
}
93
109
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
+
94
202
impl Snapshot {
95
203
/// Creates a new instance which can only be used to save a new snapshot.
96
204
pub fn new ( version : Version ) -> Snapshot {
0 commit comments