Fix broken realmfs autoresize
This commit is contained in:
parent
2dc8bf2922
commit
24f786cf75
@ -23,8 +23,8 @@ impl ResizeSize {
|
|||||||
|
|
||||||
pub fn gigs(n: usize) -> Self {
|
pub fn gigs(n: usize) -> Self {
|
||||||
ResizeSize(BLOCKS_PER_GIG * n)
|
ResizeSize(BLOCKS_PER_GIG * n)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn megs(n: usize) -> Self {
|
pub fn megs(n: usize) -> Self {
|
||||||
ResizeSize(BLOCKS_PER_MEG * n)
|
ResizeSize(BLOCKS_PER_MEG * n)
|
||||||
}
|
}
|
||||||
@ -45,8 +45,8 @@ impl ResizeSize {
|
|||||||
self.0 / BLOCKS_PER_MEG
|
self.0 / BLOCKS_PER_MEG
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the RealmFS needs to be resized to a larger size, returns the
|
/// If the RealmFS has less than `AUTO_RESIZE_MINIMUM_FREE` blocks free then choose a new
|
||||||
/// recommended size.
|
/// size to resize the filesystem to and return it. Otherwise, return `None`
|
||||||
pub fn auto_resize_size(realmfs: &RealmFS) -> Option<ResizeSize> {
|
pub fn auto_resize_size(realmfs: &RealmFS) -> Option<ResizeSize> {
|
||||||
let sb = match Superblock::load(realmfs.path(), 4096) {
|
let sb = match Superblock::load(realmfs.path(), 4096) {
|
||||||
Ok(sb) => sb,
|
Ok(sb) => sb,
|
||||||
@ -56,22 +56,37 @@ impl ResizeSize {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
sb.free_block_count();
|
|
||||||
let free_blocks = sb.free_block_count() as usize;
|
let free_blocks = sb.free_block_count() as usize;
|
||||||
if free_blocks < AUTO_RESIZE_MINIMUM_FREE.nblocks() {
|
if free_blocks >= AUTO_RESIZE_MINIMUM_FREE.nblocks() {
|
||||||
let metainfo_nblocks = realmfs.metainfo().nblocks() + 1;
|
return None;
|
||||||
let increase_multiple = metainfo_nblocks / AUTO_RESIZE_INCREASE_SIZE.nblocks();
|
}
|
||||||
let grow_size = (increase_multiple + 1) * AUTO_RESIZE_INCREASE_SIZE.nblocks();
|
|
||||||
let mask = grow_size - 1;
|
let metainfo_nblocks = realmfs.metainfo().nblocks();
|
||||||
let grow_blocks = (free_blocks + mask) & !mask;
|
|
||||||
Some(ResizeSize::blocks(grow_blocks))
|
if metainfo_nblocks >= AUTO_RESIZE_INCREASE_SIZE.nblocks() {
|
||||||
|
return Some(ResizeSize::blocks(metainfo_nblocks + AUTO_RESIZE_INCREASE_SIZE.nblocks()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// If current size is under 4GB (AUTO_RESIZE_INCREASE_SIZE) and raising size to 4GB will create more than the
|
||||||
|
// minimum free space (1GB) then just do that.
|
||||||
|
if free_blocks + (AUTO_RESIZE_INCREASE_SIZE.nblocks() - metainfo_nblocks) >= AUTO_RESIZE_MINIMUM_FREE.nblocks() {
|
||||||
|
Some(AUTO_RESIZE_INCREASE_SIZE)
|
||||||
} else {
|
} else {
|
||||||
None
|
// Otherwise for original size under 4GB, since raising to 4GB is not enough,
|
||||||
|
// raise size to 8GB
|
||||||
|
Some(ResizeSize::blocks(AUTO_RESIZE_INCREASE_SIZE.nblocks() * 2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const SUPERBLOCK_SIZE: usize = 1024;
|
const SUPERBLOCK_SIZE: usize = 1024;
|
||||||
|
|
||||||
|
/// An EXT4 superblock structure.
|
||||||
|
///
|
||||||
|
/// A class for reading the first superblock from an EXT4 filesystem
|
||||||
|
/// and parsing the Free Block Count field. No other fields are parsed
|
||||||
|
/// since this is the only information needed for the resize operation.
|
||||||
|
///
|
||||||
pub struct Superblock([u8; SUPERBLOCK_SIZE]);
|
pub struct Superblock([u8; SUPERBLOCK_SIZE]);
|
||||||
|
|
||||||
impl Superblock {
|
impl Superblock {
|
||||||
|
@ -76,8 +76,6 @@ impl <'a> Update<'a> {
|
|||||||
}
|
}
|
||||||
self.realmfs.copy_image_file(self.target())?;
|
self.realmfs.copy_image_file(self.target())?;
|
||||||
|
|
||||||
self.truncate_verity()?;
|
|
||||||
self.resize_image_file()?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,9 +113,8 @@ impl <'a> Update<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return size of image file in blocks based on metainfo `nblocks` field.
|
// Return size of image file in blocks based on metainfo `nblocks` field.
|
||||||
// Include header block in count so add one block
|
|
||||||
fn metainfo_nblock_size(&self) -> usize {
|
fn metainfo_nblock_size(&self) -> usize {
|
||||||
self.realmfs.metainfo().nblocks() + 1
|
self.realmfs.metainfo().nblocks()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unmount_update_image(&mut self) {
|
fn unmount_update_image(&mut self) {
|
||||||
@ -159,7 +156,8 @@ impl <'a> Update<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_target_len(&self, nblocks: usize) -> Result<()> {
|
fn set_target_len(&self, nblocks: usize) -> Result<()> {
|
||||||
let len = (nblocks * BLOCK_SIZE) as u64;
|
// add one block for header block
|
||||||
|
let len = ((nblocks + 1) * BLOCK_SIZE) as u64;
|
||||||
let f = fs::OpenOptions::new()
|
let f = fs::OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
.open(&self.target)
|
.open(&self.target)
|
||||||
@ -176,7 +174,7 @@ impl <'a> Update<'a> {
|
|||||||
|
|
||||||
if self.realmfs.header().has_flag(ImageHeader::FLAG_HASH_TREE) {
|
if self.realmfs.header().has_flag(ImageHeader::FLAG_HASH_TREE) {
|
||||||
self.set_target_len(metainfo_nblocks)?;
|
self.set_target_len(metainfo_nblocks)?;
|
||||||
} else if file_nblocks > metainfo_nblocks {
|
} else if file_nblocks > (metainfo_nblocks + 1) {
|
||||||
warn!("RealmFS image size was greater than length indicated by metainfo.nblocks but FLAG_HASH_TREE not set");
|
warn!("RealmFS image size was greater than length indicated by metainfo.nblocks but FLAG_HASH_TREE not set");
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -185,7 +183,7 @@ impl <'a> Update<'a> {
|
|||||||
// If resize was requested, adjust size of update copy of image file.
|
// If resize was requested, adjust size of update copy of image file.
|
||||||
fn resize_image_file(&self) -> Result<()> {
|
fn resize_image_file(&self) -> Result<()> {
|
||||||
let nblocks = match self.resize {
|
let nblocks = match self.resize {
|
||||||
Some(rs) => rs.nblocks() + 1,
|
Some(rs) => rs.nblocks(),
|
||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -224,7 +222,7 @@ impl <'a> Update<'a> {
|
|||||||
fn seal(&mut self) -> Result<()> {
|
fn seal(&mut self) -> Result<()> {
|
||||||
let nblocks = match self.resize {
|
let nblocks = match self.resize {
|
||||||
Some(rs) => rs.nblocks(),
|
Some(rs) => rs.nblocks(),
|
||||||
None => self.metainfo_nblock_size() - 1,
|
None => self.metainfo_nblock_size(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let salt = hex::encode(randombytes(32));
|
let salt = hex::encode(randombytes(32));
|
||||||
@ -232,20 +230,11 @@ impl <'a> Update<'a> {
|
|||||||
.map_err(context!("failed to create verity context for realmfs update image {:?}", self.target()))?;
|
.map_err(context!("failed to create verity context for realmfs update image {:?}", self.target()))?;
|
||||||
let output = verity.generate_image_hashtree_with_salt(&salt, nblocks)
|
let output = verity.generate_image_hashtree_with_salt(&salt, nblocks)
|
||||||
.map_err(context!("failed to generate dm-verity hashtree for realmfs update image {:?}", self.target()))?;
|
.map_err(context!("failed to generate dm-verity hashtree for realmfs update image {:?}", self.target()))?;
|
||||||
// XXX passes metainfo for nblocks
|
|
||||||
//let output = Verity::new(&self.target).generate_image_hashtree_with_salt(&self.realmfs.metainfo(), &salt)?;
|
|
||||||
let root_hash = output.root_hash()
|
let root_hash = output.root_hash()
|
||||||
.ok_or_else(|| format_err!("no root hash returned from verity format operation"))?;
|
.ok_or_else(|| format_err!("no root hash returned from verity format operation"))?;
|
||||||
info!("root hash is {}", output.root_hash().unwrap());
|
info!("root hash is {}", output.root_hash().unwrap());
|
||||||
|
|
||||||
/*
|
|
||||||
let nblocks = match self.resize {
|
|
||||||
Some(rs) => rs.nblocks(),
|
|
||||||
None => self.metainfo_nblock_size() - 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
info!("Signing new image with user realmfs keys");
|
info!("Signing new image with user realmfs keys");
|
||||||
let metainfo_bytes = RealmFS::generate_metainfo(self.realmfs.name(), nblocks, salt.as_str(), root_hash);
|
let metainfo_bytes = RealmFS::generate_metainfo(self.realmfs.name(), nblocks, salt.as_str(), root_hash);
|
||||||
let keys = self.realmfs.sealing_keys().expect("No sealing keys");
|
let keys = self.realmfs.sealing_keys().expect("No sealing keys");
|
||||||
|
Loading…
Reference in New Issue
Block a user