Use less memory when decompressing images for install
1. Delete source image before decompressing temporary file 2. Decompress the images serially instead of spawning a thread for each one.
This commit is contained in:
parent
0832ddfa9f
commit
3dbfda2c40
@ -20,7 +20,7 @@ pub fn live_rootfs() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn live_setup() -> Result<()> {
|
pub fn live_setup() -> Result<()> {
|
||||||
decompress_images()?;
|
decompress_images(true)?;
|
||||||
info!("Starting live setup");
|
info!("Starting live setup");
|
||||||
let live = Installer::new_livesetup();
|
let live = Installer::new_livesetup();
|
||||||
live.run()
|
live.run()
|
||||||
@ -131,37 +131,50 @@ fn find_rootfs_image() -> Result<ResourceImage> {
|
|||||||
bail!("unable to find rootfs resource image in {}", IMAGE_DIRECTORY)
|
bail!("unable to find rootfs resource image in {}", IMAGE_DIRECTORY)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decompress_images() -> Result<()> {
|
fn decompress_images(sync: bool) -> Result<()> {
|
||||||
info!("Decompressing images");
|
info!("Decompressing images");
|
||||||
let mut threads = Vec::new();
|
let mut threads = Vec::new();
|
||||||
util::read_directory("/run/citadel/images", |dent| {
|
util::read_directory("/run/citadel/images", |dent| {
|
||||||
if dent.path().extension() == Some(OsStr::new("img")) {
|
if dent.path().extension() == Some(OsStr::new("img")) {
|
||||||
if let Ok(image) = ResourceImage::from_path(&dent.path()) {
|
if let Ok(image) = ResourceImage::from_path(&dent.path()) {
|
||||||
if image.is_compressed() {
|
if image.is_compressed() {
|
||||||
|
if sync {
|
||||||
|
if let Err(err) = decompress_one_image_sync(image) {
|
||||||
|
warn!("Error: {}", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
threads.push(decompress_one_image(image));
|
threads.push(decompress_one_image(image));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
for t in threads {
|
for t in threads {
|
||||||
t.join().unwrap()?;
|
if let Err(err) = t.join().unwrap() {
|
||||||
|
warn!("Error: {}", err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
info!("Finished decompressing images");
|
info!("Finished decompressing images");
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decompress_one_image(image: ResourceImage) -> JoinHandle<Result<()>> {
|
fn decompress_one_image_sync(image: ResourceImage) -> Result<()> {
|
||||||
thread::spawn(move || {
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
info!("Decompressing {}", image.path().display());
|
info!("Decompressing {}", image.path().display());
|
||||||
image.decompress()?;
|
image.decompress(true)
|
||||||
|
.map_err(|e| format_err!("Failed to decompress image file {}: {}", image.path().display(), e))?;
|
||||||
cmd!("/usr/bin/du", "-h {}", image.path().display())?;
|
cmd!("/usr/bin/du", "-h {}", image.path().display())?;
|
||||||
info!("Decompress {:?} finished in {} seconds",
|
info!("Decompress {:?} finished in {} seconds",
|
||||||
image.path().file_name().unwrap(),
|
image.path().file_name().unwrap(),
|
||||||
start.elapsed().as_secs());
|
start.elapsed().as_secs());
|
||||||
Ok(())
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decompress_one_image(image: ResourceImage) -> JoinHandle<Result<()>> {
|
||||||
|
thread::spawn(move || {
|
||||||
|
decompress_one_image_sync(image)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ pub fn setup_rootfs_resource(rootfs: &ResourceImage) -> Result<()> {
|
|||||||
|
|
||||||
fn setup_resource_unverified(img: &ResourceImage) -> Result<()> {
|
fn setup_resource_unverified(img: &ResourceImage) -> Result<()> {
|
||||||
if img.is_compressed() {
|
if img.is_compressed() {
|
||||||
img.decompress()?;
|
img.decompress(false)?;
|
||||||
}
|
}
|
||||||
let loopdev = LoopDevice::create(img.path(), Some(4096), true)?;
|
let loopdev = LoopDevice::create(img.path(), Some(4096), true)?;
|
||||||
info!("Loop device created: {}", loopdev);
|
info!("Loop device created: {}", loopdev);
|
||||||
|
@ -275,7 +275,7 @@ fn decompress(arg_matches: &ArgMatches) -> Result<()> {
|
|||||||
if !img.is_compressed() {
|
if !img.is_compressed() {
|
||||||
info!("Image is not compressed, not decompressing.");
|
info!("Image is not compressed, not decompressing.");
|
||||||
} else {
|
} else {
|
||||||
img.decompress()?;
|
img.decompress(false)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ fn install_image(path: &Path, flags: u32) -> Result<()> {
|
|||||||
// dmverity hash tree.
|
// dmverity hash tree.
|
||||||
fn prepare_image(image: &ResourceImage, flags: u32) -> Result<()> {
|
fn prepare_image(image: &ResourceImage, flags: u32) -> Result<()> {
|
||||||
if image.is_compressed() {
|
if image.is_compressed() {
|
||||||
image.decompress()?;
|
image.decompress(false)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags & FLAG_SKIP_SHA == 0 {
|
if flags & FLAG_SKIP_SHA == 0 {
|
||||||
|
@ -54,7 +54,7 @@ impl Exec {
|
|||||||
.map_err(context!("failed to execute command {}", self.cmd_name))?;
|
.map_err(context!("failed to execute command {}", self.cmd_name))?;
|
||||||
|
|
||||||
for line in BufReader::new(result.stderr.as_slice()).lines() {
|
for line in BufReader::new(result.stderr.as_slice()).lines() {
|
||||||
verbose!(" {}", line.unwrap());
|
warn!(" {}", line.unwrap());
|
||||||
}
|
}
|
||||||
self.check_cmd_status(result.status)
|
self.check_cmd_status(result.status)
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ impl ResourceImage {
|
|||||||
self.header.has_flag(ImageHeader::FLAG_HASH_TREE)
|
self.header.has_flag(ImageHeader::FLAG_HASH_TREE)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decompress(&self) -> Result<()> {
|
pub fn decompress(&self, early_remove: bool) -> Result<()> {
|
||||||
if !self.is_compressed() {
|
if !self.is_compressed() {
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
@ -154,6 +154,10 @@ impl ResourceImage {
|
|||||||
io::copy(&mut reader, &mut out)
|
io::copy(&mut reader, &mut out)
|
||||||
.map_err(context!("error copying image file {:?} to temporary file", self.path()))?;
|
.map_err(context!("error copying image file {:?} to temporary file", self.path()))?;
|
||||||
|
|
||||||
|
if early_remove {
|
||||||
|
util::remove_file(self.path())?;
|
||||||
|
}
|
||||||
|
|
||||||
util::xz_decompress(xzfile)?;
|
util::xz_decompress(xzfile)?;
|
||||||
let tmpfile = self.path.with_extension("tmp");
|
let tmpfile = self.path.with_extension("tmp");
|
||||||
util::rename(&tmpfile, self.path())?;
|
util::rename(&tmpfile, self.path())?;
|
||||||
@ -218,7 +222,7 @@ impl ResourceImage {
|
|||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
if self.is_compressed() {
|
if self.is_compressed() {
|
||||||
self.decompress()?;
|
self.decompress(false)?;
|
||||||
}
|
}
|
||||||
info!("Generating dm-verity hash tree for image {}", self.path.display());
|
info!("Generating dm-verity hash tree for image {}", self.path.display());
|
||||||
let verity = self.verity()?;
|
let verity = self.verity()?;
|
||||||
@ -239,7 +243,7 @@ impl ResourceImage {
|
|||||||
|
|
||||||
pub fn generate_shasum(&self) -> Result<String> {
|
pub fn generate_shasum(&self) -> Result<String> {
|
||||||
if self.is_compressed() {
|
if self.is_compressed() {
|
||||||
self.decompress()?;
|
self.decompress(false)?;
|
||||||
}
|
}
|
||||||
info!("Calculating sha256 of image");
|
info!("Calculating sha256 of image");
|
||||||
let output = util::exec_cmdline_pipe_input("sha256sum", "-", self.path(), util::FileRange::Range{offset: 4096, len: self.metainfo().nblocks() * 4096})
|
let output = util::exec_cmdline_pipe_input("sha256sum", "-", self.path(), util::FileRange::Range{offset: 4096, len: self.metainfo().nblocks() * 4096})
|
||||||
@ -256,7 +260,7 @@ impl ResourceImage {
|
|||||||
info!("loop mounting image to {} (noverity)", self.mount_path().display());
|
info!("loop mounting image to {} (noverity)", self.mount_path().display());
|
||||||
|
|
||||||
if self.is_compressed() {
|
if self.is_compressed() {
|
||||||
self.decompress()?;
|
self.decompress(false)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let loopdev = LoopDevice::create(self.path(), Some(4096), true)?;
|
let loopdev = LoopDevice::create(self.path(), Some(4096), true)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user