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 {
|
||||
ResizeSize(BLOCKS_PER_GIG * n)
|
||||
|
||||
}
|
||||
|
||||
pub fn megs(n: usize) -> Self {
|
||||
ResizeSize(BLOCKS_PER_MEG * n)
|
||||
}
|
||||
@ -45,8 +45,8 @@ impl ResizeSize {
|
||||
self.0 / BLOCKS_PER_MEG
|
||||
}
|
||||
|
||||
/// If the RealmFS needs to be resized to a larger size, returns the
|
||||
/// recommended size.
|
||||
/// If the RealmFS has less than `AUTO_RESIZE_MINIMUM_FREE` blocks free then choose a new
|
||||
/// size to resize the filesystem to and return it. Otherwise, return `None`
|
||||
pub fn auto_resize_size(realmfs: &RealmFS) -> Option<ResizeSize> {
|
||||
let sb = match Superblock::load(realmfs.path(), 4096) {
|
||||
Ok(sb) => sb,
|
||||
@ -56,22 +56,37 @@ impl ResizeSize {
|
||||
},
|
||||
};
|
||||
|
||||
sb.free_block_count();
|
||||
let free_blocks = sb.free_block_count() as usize;
|
||||
if free_blocks < AUTO_RESIZE_MINIMUM_FREE.nblocks() {
|
||||
let metainfo_nblocks = realmfs.metainfo().nblocks() + 1;
|
||||
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 grow_blocks = (free_blocks + mask) & !mask;
|
||||
Some(ResizeSize::blocks(grow_blocks))
|
||||
if free_blocks >= AUTO_RESIZE_MINIMUM_FREE.nblocks() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let metainfo_nblocks = realmfs.metainfo().nblocks();
|
||||
|
||||
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 {
|
||||
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;
|
||||
|
||||
/// 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]);
|
||||
|
||||
impl Superblock {
|
||||
|
@ -76,8 +76,6 @@ impl <'a> Update<'a> {
|
||||
}
|
||||
self.realmfs.copy_image_file(self.target())?;
|
||||
|
||||
self.truncate_verity()?;
|
||||
self.resize_image_file()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -115,9 +113,8 @@ impl <'a> Update<'a> {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
self.realmfs.metainfo().nblocks() + 1
|
||||
self.realmfs.metainfo().nblocks()
|
||||
}
|
||||
|
||||
fn unmount_update_image(&mut self) {
|
||||
@ -159,7 +156,8 @@ impl <'a> Update<'a> {
|
||||
}
|
||||
|
||||
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()
|
||||
.write(true)
|
||||
.open(&self.target)
|
||||
@ -176,7 +174,7 @@ impl <'a> Update<'a> {
|
||||
|
||||
if self.realmfs.header().has_flag(ImageHeader::FLAG_HASH_TREE) {
|
||||
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");
|
||||
}
|
||||
Ok(())
|
||||
@ -185,7 +183,7 @@ impl <'a> Update<'a> {
|
||||
// If resize was requested, adjust size of update copy of image file.
|
||||
fn resize_image_file(&self) -> Result<()> {
|
||||
let nblocks = match self.resize {
|
||||
Some(rs) => rs.nblocks() + 1,
|
||||
Some(rs) => rs.nblocks(),
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
@ -224,7 +222,7 @@ impl <'a> Update<'a> {
|
||||
fn seal(&mut self) -> Result<()> {
|
||||
let nblocks = match self.resize {
|
||||
Some(rs) => rs.nblocks(),
|
||||
None => self.metainfo_nblock_size() - 1,
|
||||
None => self.metainfo_nblock_size(),
|
||||
};
|
||||
|
||||
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()))?;
|
||||
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()))?;
|
||||
// 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()
|
||||
.ok_or_else(|| format_err!("no root hash returned from verity format operation"))?;
|
||||
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");
|
||||
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");
|
||||
|
Loading…
Reference in New Issue
Block a user