Use composite disk dir for relative paths instead of crosvm working dir

This allows us to move the composite disks and partitions around instead
of needing to know the paths beforehand.

BUG=b:221887571
TEST=Manual test with composite disk created via mk_payload.

Change-Id: Ifab86bc62509e58cc95b0f8420bffc554d60f380
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3499408
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Richard Fung <richardfung@google.com>
This commit is contained in:
Richard Fung 2022-03-03 19:46:29 +00:00 committed by Commit Bot
parent a141656f6d
commit 9f9f0b7725
5 changed files with 39 additions and 18 deletions

View file

@ -124,7 +124,7 @@ fn range_intersection(a: &Range<u64>, b: &Range<u64>) -> Range<u64> {
}
/// The version of the composite disk format supported by this implementation.
const COMPOSITE_DISK_VERSION: u64 = 1;
const COMPOSITE_DISK_VERSION: u64 = 2;
/// A magic string placed at the beginning of a composite disk file to identify it.
pub const CDISK_MAGIC: &str = "composite_disk\x1d";
@ -157,7 +157,11 @@ impl CompositeDiskFile {
/// Set up a composite disk by reading the specification from a file. The file must consist of
/// the CDISK_MAGIC string followed by one binary instance of the CompositeDisk protocol
/// buffer. Returns an error if it could not read the file or if the specification was invalid.
pub fn from_file(mut file: File, max_nesting_depth: u32) -> Result<CompositeDiskFile> {
pub fn from_file(
mut file: File,
max_nesting_depth: u32,
image_path: &Path,
) -> Result<CompositeDiskFile> {
file.seek(SeekFrom::Start(0))
.map_err(Error::ReadSpecificationError)?;
let mut magic_space = [0u8; CDISK_MAGIC_LEN];
@ -168,22 +172,27 @@ impl CompositeDiskFile {
}
let proto: cdisk_spec::CompositeDisk =
Message::parse_from_reader(&mut file).map_err(Error::InvalidProto)?;
if proto.get_version() != COMPOSITE_DISK_VERSION {
if proto.get_version() > COMPOSITE_DISK_VERSION {
return Err(Error::UnknownVersion(proto.get_version()));
}
let mut disks: Vec<ComponentDiskPart> = proto
.get_component_disks()
.iter()
.map(|disk| {
let file = open_file(
Path::new(disk.get_file_path()),
let path = if proto.get_version() == 1 {
PathBuf::from(disk.get_file_path())
} else {
image_path.parent().unwrap().join(disk.get_file_path())
};
let comp_file = open_file(
&path,
disk.get_read_write_capability() != cdisk_spec::ReadWriteCapability::READ_WRITE,
// TODO(b/190435784): add support for O_DIRECT.
false, /*O_DIRECT*/
)
.map_err(|e| Error::OpenFile(e.into(), disk.get_file_path().to_string()))?;
Ok(ComponentDiskPart {
file: create_disk_file(file, max_nesting_depth)
file: create_disk_file(comp_file, max_nesting_depth, &path)
.map_err(|e| Error::DiskError(Box::new(e)))?,
offset: disk.get_offset(),
length: 0, // Assigned later

View file

@ -6,6 +6,7 @@ use std::cmp::min;
use std::fmt::Debug;
use std::fs::File;
use std::io::{self, Read, Seek, SeekFrom};
use std::path::Path;
use std::sync::Arc;
use async_trait::async_trait;
@ -234,7 +235,11 @@ pub fn create_async_disk_file(raw_image: File) -> Result<Box<dyn ToAsyncDisk>> {
}
/// Inspect the image file type and create an appropriate disk file to match it.
pub fn create_disk_file(raw_image: File, mut max_nesting_depth: u32) -> Result<Box<dyn DiskFile>> {
pub fn create_disk_file(
raw_image: File,
mut max_nesting_depth: u32,
image_path: &Path,
) -> Result<Box<dyn DiskFile>> {
if max_nesting_depth == 0 {
return Err(Error::MaxNestingDepthExceeded);
}
@ -251,7 +256,7 @@ pub fn create_disk_file(raw_image: File, mut max_nesting_depth: u32) -> Result<B
ImageType::CompositeDisk => {
// Valid composite disk header present
Box::new(
CompositeDiskFile::from_file(raw_image, max_nesting_depth)
CompositeDiskFile::from_file(raw_image, max_nesting_depth, image_path)
.map_err(Error::CreateCompositeDisk)?,
) as Box<dyn DiskFile>
}

View file

@ -437,8 +437,9 @@ impl QcowFile {
false, /*O_DIRECT*/
)
.map_err(|e| Error::BackingFileIo(e.into()))?;
let backing_file = create_disk_file(backing_raw_file, max_nesting_depth)
.map_err(|e| Error::BackingFileOpen(Box::new(e)))?;
let backing_file =
create_disk_file(backing_raw_file, max_nesting_depth, Path::new(&path))
.map_err(|e| Error::BackingFileOpen(Box::new(e)))?;
Some(backing_file)
} else {
None
@ -574,15 +575,20 @@ impl QcowFile {
backing_file_name: &str,
backing_file_max_nesting_depth: u32,
) -> Result<QcowFile> {
let backing_path = Path::new(backing_file_name);
let backing_raw_file = open_file(
Path::new(backing_file_name),
backing_path,
true, /*read_only*/
// TODO(b/190435784): add support for O_DIRECT.
false, /*O_DIRECT*/
)
.map_err(|e| Error::BackingFileIo(e.into()))?;
let backing_file = create_disk_file(backing_raw_file, backing_file_max_nesting_depth)
.map_err(|e| Error::BackingFileOpen(Box::new(e)))?;
let backing_file = create_disk_file(
backing_raw_file,
backing_file_max_nesting_depth,
backing_path,
)
.map_err(|e| Error::BackingFileOpen(Box::new(e)))?;
let size = backing_file.get_len().map_err(Error::BackingFileIo)?;
let header = QcowHeader::create_for_size_and_path(size, Some(backing_file_name))?;
let mut result = QcowFile::new_from_header(file, header, backing_file_max_nesting_depth)?;

View file

@ -132,7 +132,7 @@ pub fn create_block_device(
.context("failed to create block device")?,
) as Box<dyn VirtioDevice>
} else {
let disk_file = disk::create_disk_file(raw_image, disk::MAX_NESTING_DEPTH)
let disk_file = disk::create_disk_file(raw_image, disk::MAX_NESTING_DEPTH, &disk.path)
.context("failed to create virtual disk")?;
Box::new(
virtio::Block::new(

View file

@ -3069,10 +3069,11 @@ fn create_composite(mut args: std::env::Args) -> std::result::Result<(), ()> {
if let [label, path] = partition_arg.split(":").collect::<Vec<_>>()[..] {
let partition_file = File::open(path)
.map_err(|e| error!("Failed to open partition image: {}", e))?;
let size = create_disk_file(partition_file, disk::MAX_NESTING_DEPTH)
.map_err(|e| error!("Failed to create DiskFile instance: {}", e))?
.get_len()
.map_err(|e| error!("Failed to get length of partition image: {}", e))?;
let size =
create_disk_file(partition_file, disk::MAX_NESTING_DEPTH, Path::new(path))
.map_err(|e| error!("Failed to create DiskFile instance: {}", e))?
.get_len()
.map_err(|e| error!("Failed to get length of partition image: {}", e))?;
Ok(PartitionInfo {
label: label.to_owned(),
path: Path::new(path).to_owned(),