Resize the virtual size of the QCOW2 image. This supports growing the image, including growing the L1 table if needed. Shrinking is not supported, as it could lead to data loss. Not supported when a backing file is present in that case an error is returned.
(&mut self, new_size: u64)
| 888 | /// loss. Not supported when a backing file is present in that case |
| 889 | /// an error is returned. |
| 890 | pub fn resize(&mut self, new_size: u64) -> BlockResult<()> { |
| 891 | let current_size = self.virtual_size(); |
| 892 | |
| 893 | if new_size == current_size { |
| 894 | return Ok(()); |
| 895 | } |
| 896 | |
| 897 | if new_size < current_size { |
| 898 | return Err(BlockError::new( |
| 899 | BlockErrorKind::UnsupportedFeature, |
| 900 | Error::ShrinkNotSupported, |
| 901 | )); |
| 902 | } |
| 903 | |
| 904 | if self.backing_file.is_some() { |
| 905 | return Err(BlockError::new( |
| 906 | BlockErrorKind::UnsupportedFeature, |
| 907 | Error::ResizeWithBackingFile, |
| 908 | )); |
| 909 | } |
| 910 | |
| 911 | // Grow the L1 table if needed |
| 912 | let cluster_size = self.raw_file.cluster_size(); |
| 913 | let entries_per_cluster = cluster_size / size_of::<u64>() as u64; |
| 914 | let new_clusters = div_round_up_u64(new_size, cluster_size); |
| 915 | let needed_l1_entries = div_round_up_u64(new_clusters, entries_per_cluster) as u32; |
| 916 | |
| 917 | if needed_l1_entries > self.header.l1_size { |
| 918 | self.grow_l1_table(needed_l1_entries)?; |
| 919 | } |
| 920 | |
| 921 | self.header.size = new_size; |
| 922 | |
| 923 | self.raw_file |
| 924 | .file_mut() |
| 925 | .rewind() |
| 926 | .map_err(|e| BlockError::new(BlockErrorKind::Io, Error::SeekingFile(e)))?; |
| 927 | self.header |
| 928 | .write_to(self.raw_file.file_mut()) |
| 929 | .map_err(|e| match e { |
| 930 | Error::WritingHeader(io_err) => { |
| 931 | BlockError::new(BlockErrorKind::Io, Error::ResizeIo(io_err)) |
| 932 | } |
| 933 | other => BlockError::new(BlockErrorKind::Io, other), |
| 934 | })?; |
| 935 | |
| 936 | self.raw_file |
| 937 | .file_mut() |
| 938 | .sync_all() |
| 939 | .map_err(|e| BlockError::new(BlockErrorKind::Io, Error::SyncingHeader(e)))?; |
| 940 | |
| 941 | Ok(()) |
| 942 | } |
| 943 | |
| 944 | /// Grow the L1 table to accommodate at least `new_l1_size` entries. |
| 945 | /// |