From d5aa9954237f9eb9c7ec468362fb8262f0975429 Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Tue, 7 Jan 2020 17:51:04 -0800 Subject: disk: use seek to determine file length Add a new disk-specific DiskGetLen trait which uses io::Seek instead of File::metadata() to determine the length so that it works on raw block devices (e.g. /dev/sda) as well as regular files. BUG=b:146811529 TEST=`crosvm run --disk /dev/sda` and verify block device length Change-Id: I6936863490efaa479a3c8745c75c373748c800a1 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1990855 Reviewed-by: Zach Reizner Tested-by: kokoro Tested-by: Trent Begin Commit-Queue: Daniel Verkamp --- disk/src/composite.rs | 8 +++----- disk/src/disk.rs | 23 +++++++++++++++++++---- disk/src/qcow/mod.rs | 7 ++++--- 3 files changed, 26 insertions(+), 12 deletions(-) (limited to 'disk') diff --git a/disk/src/composite.rs b/disk/src/composite.rs index bd21b33..06c1545 100644 --- a/disk/src/composite.rs +++ b/disk/src/composite.rs @@ -9,13 +9,11 @@ use std::io::{self, ErrorKind, Read, Seek, SeekFrom}; use std::ops::Range; use std::os::unix::io::RawFd; -use crate::{create_disk_file, DiskFile, ImageType}; +use crate::{create_disk_file, DiskFile, DiskGetLen, ImageType}; use data_model::VolatileSlice; use protos::cdisk_spec; use remain::sorted; -use sys_util::{ - AsRawFds, FileGetLen, FileReadWriteAtVolatile, FileSetLen, FileSync, PunchHole, WriteZeroesAt, -}; +use sys_util::{AsRawFds, FileReadWriteAtVolatile, FileSetLen, FileSync, PunchHole, WriteZeroesAt}; #[sorted] #[derive(Debug)] @@ -210,7 +208,7 @@ impl CompositeDiskFile { } } -impl FileGetLen for CompositeDiskFile { +impl DiskGetLen for CompositeDiskFile { fn get_len(&self) -> io::Result { Ok(self.length()) } diff --git a/disk/src/disk.rs b/disk/src/disk.rs index e3e7e63..a67d91a 100644 --- a/disk/src/disk.rs +++ b/disk/src/disk.rs @@ -10,8 +10,7 @@ use std::io::{self, Read, Seek, SeekFrom, Write}; use libc::EINVAL; use remain::sorted; use sys_util::{ - AsRawFds, FileGetLen, FileReadWriteAtVolatile, FileSetLen, FileSync, PunchHole, SeekHole, - WriteZeroesAt, + AsRawFds, FileReadWriteAtVolatile, FileSetLen, FileSync, PunchHole, SeekHole, WriteZeroesAt, }; mod qcow; @@ -40,11 +39,27 @@ pub enum Error { pub type Result = std::result::Result; +/// A trait for getting the length of a disk image or raw block device. +pub trait DiskGetLen { + /// Get the current length of the disk in bytes. + fn get_len(&self) -> io::Result; +} + +impl DiskGetLen for File { + fn get_len(&self) -> io::Result { + let mut s = self; + let orig_seek = s.seek(SeekFrom::Current(0))?; + let end = s.seek(SeekFrom::End(0))? as u64; + s.seek(SeekFrom::Start(orig_seek))?; + Ok(end) + } +} + /// The prerequisites necessary to support a block device. #[rustfmt::skip] // rustfmt won't wrap the long list of trait bounds. pub trait DiskFile: FileSetLen - + FileGetLen + + DiskGetLen + FileSync + FileReadWriteAtVolatile + PunchHole @@ -55,7 +70,7 @@ pub trait DiskFile: } impl< D: FileSetLen - + FileGetLen + + DiskGetLen + FileSync + PunchHole + FileReadWriteAtVolatile diff --git a/disk/src/qcow/mod.rs b/disk/src/qcow/mod.rs index f449d1d..6bd9719 100644 --- a/disk/src/qcow/mod.rs +++ b/disk/src/qcow/mod.rs @@ -10,8 +10,8 @@ use data_model::{VolatileMemory, VolatileSlice}; use libc::{EINVAL, ENOSPC, ENOTSUP}; use remain::sorted; use sys_util::{ - error, FileGetLen, FileReadWriteAtVolatile, FileReadWriteVolatile, FileSetLen, FileSync, - PunchHole, SeekHole, WriteZeroesAt, + error, FileReadWriteAtVolatile, FileReadWriteVolatile, FileSetLen, FileSync, PunchHole, + SeekHole, WriteZeroesAt, }; use std::cmp::{max, min}; @@ -24,6 +24,7 @@ use std::os::unix::io::{AsRawFd, RawFd}; use crate::qcow::qcow_raw_file::QcowRawFile; use crate::qcow::refcount::RefCount; use crate::qcow::vec_cache::{CacheMap, Cacheable, VecCache}; +use crate::DiskGetLen; #[sorted] #[derive(Debug)] @@ -1571,7 +1572,7 @@ impl FileSetLen for QcowFile { } } -impl FileGetLen for QcowFile { +impl DiskGetLen for QcowFile { fn get_len(&self) -> io::Result { Ok(self.virtual_size()) } -- cgit 1.4.1