block: bind FD lifetime of DiskFile

As we can't use BorrowedFd, we should at least create a similar
safe alternative.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This commit is contained in:
Philipp Schuster 2025-05-14 10:55:52 +02:00 committed by Rob Bradford
parent a647d7863c
commit 2da5e10689
8 changed files with 66 additions and 29 deletions

View file

@ -2,7 +2,8 @@
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use std::os::fd::RawFd;
use std::marker::PhantomData;
use std::os::fd::{AsRawFd, OwnedFd, RawFd};
use thiserror::Error;
use vmm_sys_util::eventfd::EventFd;
@ -21,6 +22,39 @@ pub enum DiskFileError {
pub type DiskFileResult<T> = std::result::Result<T, DiskFileError>;
/// A wrapper for [`RawFd`] capturing the lifetime of a corresponding [`DiskFile`].
///
/// This fulfills the same role as [`BorrowedFd`] but is tailored to the limitations
/// by some implementations of [`DiskFile`], which wrap the effective [`File`]
/// in an `Arc<Mutex<T>>`, making the use of [`BorrowedFd`] impossible.
///
/// [`BorrowedFd`]: std::os::fd::BorrowedFd
#[derive(Copy, Clone, Debug)]
pub struct BorrowedDiskFd<'fd> {
raw_fd: RawFd,
_lifetime: PhantomData<&'fd OwnedFd>,
}
impl BorrowedDiskFd<'_> {
pub(super) fn new(raw_fd: RawFd) -> Self {
Self {
raw_fd,
_lifetime: PhantomData,
}
}
}
impl AsRawFd for BorrowedDiskFd<'_> {
fn as_raw_fd(&self) -> RawFd {
self.raw_fd
}
}
/// Abstraction over the effective [`File`] backing up a block device,
/// with support for synchronous and asynchronous I/O.
///
/// This allows abstracting over raw image formats as well as structured
/// image formats.
pub trait DiskFile: Send {
fn size(&mut self) -> DiskFileResult<u64>;
fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>>;
@ -28,11 +62,10 @@ pub trait DiskFile: Send {
DiskTopology::default()
}
/// Returns the file descriptor of the underlying disk image file.
// Impl Note:
// This must be `RawFd` instead of `BorrowedFd` or `&File`, as some
// implementations wrap the file in an `Arc<Mutex<T>>`, which makes it
// impossible to return a reference.
fn fd(&mut self) -> RawFd;
///
/// The file descriptor is supposed to be used for `fcntl()` calls but no
/// other operation.
fn fd(&mut self) -> BorrowedDiskFd;
}
#[derive(Error, Debug)]

View file

@ -8,7 +8,7 @@ use std::os::unix::io::{AsRawFd, RawFd};
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::fixed_vhd::FixedVhd;
use crate::raw_async::RawFileAsync;
@ -34,8 +34,8 @@ impl DiskFile for FixedVhdDiskAsync {
) as Box<dyn AsyncIo>)
}
fn fd(&mut self) -> RawFd {
self.0.as_raw_fd()
fn fd(&mut self) -> BorrowedDiskFd {
BorrowedDiskFd::new(self.0.as_raw_fd())
}
}

View file

@ -8,7 +8,7 @@ use std::os::unix::io::{AsRawFd, RawFd};
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::fixed_vhd::FixedVhd;
use crate::raw_sync::RawFileSync;
@ -34,8 +34,8 @@ impl DiskFile for FixedVhdDiskSync {
) as Box<dyn AsyncIo>)
}
fn fd(&mut self) -> RawFd {
self.0.as_raw_fd()
fn fd(&mut self) -> BorrowedDiskFd {
BorrowedDiskFd::new(self.0.as_raw_fd())
}
}

View file

@ -5,12 +5,14 @@
use std::collections::VecDeque;
use std::fs::File;
use std::io::{Seek, SeekFrom};
use std::os::fd::{AsRawFd, RawFd};
use std::os::fd::AsRawFd;
use std::sync::{Arc, Mutex, MutexGuard};
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult};
use crate::async_io::{
AsyncIo, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::qcow::{QcowFile, RawFile, Result as QcowResult};
use crate::AsyncAdaptor;
@ -37,9 +39,9 @@ impl DiskFile for QcowDiskSync {
Ok(Box::new(QcowSync::new(self.qcow_file.clone())) as Box<dyn AsyncIo>)
}
fn fd(&mut self) -> RawFd {
fn fd(&mut self) -> BorrowedDiskFd {
let lock = self.qcow_file.lock().unwrap();
lock.as_raw_fd()
BorrowedDiskFd::new(lock.as_raw_fd())
}
}

View file

@ -10,7 +10,7 @@ use io_uring::{opcode, types, IoUring};
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::DiskTopology;
@ -47,8 +47,8 @@ impl DiskFile for RawFileDisk {
}
}
fn fd(&mut self) -> RawFd {
self.file.as_raw_fd()
fn fd(&mut self) -> BorrowedDiskFd {
BorrowedDiskFd::new(self.file.as_raw_fd())
}
}

View file

@ -13,7 +13,7 @@ use vmm_sys_util::aio;
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::DiskTopology;
@ -50,8 +50,8 @@ impl DiskFile for RawFileDiskAio {
}
}
fn fd(&mut self) -> RawFd {
self.file.as_raw_fd()
fn fd(&mut self) -> BorrowedDiskFd {
BorrowedDiskFd::new(self.file.as_raw_fd())
}
}

View file

@ -10,7 +10,7 @@ use std::os::unix::io::{AsRawFd, RawFd};
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::DiskTopology;
@ -44,8 +44,8 @@ impl DiskFile for RawFileDiskSync {
}
}
fn fd(&mut self) -> RawFd {
self.file.as_raw_fd()
fn fd(&mut self) -> BorrowedDiskFd {
BorrowedDiskFd::new(self.file.as_raw_fd())
}
}

View file

@ -4,12 +4,14 @@
use std::collections::VecDeque;
use std::fs::File;
use std::os::fd::{AsRawFd, RawFd};
use std::os::fd::AsRawFd;
use std::sync::{Arc, Mutex, MutexGuard};
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult};
use crate::async_io::{
AsyncIo, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::vhdx::{Result as VhdxResult, Vhdx};
use crate::AsyncAdaptor;
@ -37,9 +39,9 @@ impl DiskFile for VhdxDiskSync {
)
}
fn fd(&mut self) -> RawFd {
fn fd(&mut self) -> BorrowedDiskFd {
let lock = self.vhdx_file.lock().unwrap();
lock.as_raw_fd()
BorrowedDiskFd::new(lock.as_raw_fd())
}
}