mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-12-25 04:14:06 +00:00
qcow: scan for free clusters at startup
During runtime, we track unreferenced clusters (via unref_clusters and avail_clusters) and reuse them before extending the disk image. However, across boots, we did not previously recover the list of unreferenced clusters, so the disk file could grow beyond the range that the reference table count represent. This patch adds a boot-time scan for all unreferenced clusters so that they get reused. BUG=chromium:899273 TEST=Boot with qcow2 image, fill the disk with dd, delete the dd'd file, refill with dd, and so on, repeatedly. Ensure that the disk image does not grow beyond the expected max size and that no clusters beyond the size of the refcount table are used. Change-Id: Idd21b08bb4c55b8244e7ecaccafc4ccc46b7b17a Signed-off-by: Daniel Verkamp <dverkamp@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1327822 Reviewed-by: Dylan Reid <dgreid@chromium.org>
This commit is contained in:
parent
f503276291
commit
2ea8f3d0aa
1 changed files with 26 additions and 1 deletions
|
@ -388,7 +388,7 @@ impl QcowFile {
|
|||
|
||||
let l2_entries = cluster_size / size_of::<u64>() as u64;
|
||||
|
||||
let qcow = QcowFile {
|
||||
let mut qcow = QcowFile {
|
||||
raw_file,
|
||||
header,
|
||||
l1_table,
|
||||
|
@ -410,6 +410,8 @@ impl QcowFile {
|
|||
.checked_add(u64::from(qcow.header.refcount_table_clusters) * cluster_size)
|
||||
.ok_or(Error::InvalidRefcountTableOffset)?;
|
||||
|
||||
qcow.find_avail_clusters()?;
|
||||
|
||||
Ok(qcow)
|
||||
}
|
||||
|
||||
|
@ -517,6 +519,29 @@ impl QcowFile {
|
|||
Ok(None)
|
||||
}
|
||||
|
||||
fn find_avail_clusters(&mut self) -> Result<()> {
|
||||
let cluster_size = self.raw_file.cluster_size();
|
||||
|
||||
let file_size = self
|
||||
.raw_file
|
||||
.file_mut()
|
||||
.metadata()
|
||||
.map_err(Error::GettingFileSize)?
|
||||
.len();
|
||||
|
||||
for i in (0..file_size).step_by(cluster_size as usize) {
|
||||
let refcount = self
|
||||
.refcounts
|
||||
.get_cluster_refcount(&mut self.raw_file, i)
|
||||
.map_err(Error::GettingRefcount)?;
|
||||
if refcount == 0 {
|
||||
self.avail_clusters.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Rebuild the reference count tables.
|
||||
fn rebuild_refcounts(raw_file: &mut QcowRawFile, header: QcowHeader) -> Result<()> {
|
||||
fn add_ref(refcounts: &mut [u16], cluster_size: u64, cluster_address: u64) -> Result<()> {
|
||||
|
|
Loading…
Reference in a new issue