Struct FormatAccess

Source
pub struct FormatAccess<S: Storage + 'static> {
    inner: Box<dyn FormatDriverInstance<Storage = S>>,
    writable: bool,
    read_parallelization: usize,
    write_parallelization: usize,
}
Expand description

Provides access to a disk image.

Fields§

§inner: Box<dyn FormatDriverInstance<Storage = S>>

Image format driver.

§writable: bool

Whether this image may be modified.

§read_parallelization: usize

How many asynchronous requests to perform per read request in parallel.

§write_parallelization: usize

How many asynchronous requests to perform per write request in parallel.

Implementations§

Source§

impl<S: Storage + 'static> FormatAccess<S>

Source

pub fn new<D: FormatDriverInstance<Storage = S> + 'static>(inner: D) -> Self

Wrap a format driver instance in FormatAccess.

FormatAccess provides I/O access to disk images, based on the functionality offered by the individual format drivers via FormatDriverInstance.

Source

pub fn inner(&self) -> &dyn FormatDriverInstance<Storage = S>

Return the contained format driver instance.

Source

pub fn inner_mut(&mut self) -> &mut dyn FormatDriverInstance<Storage = S>

Return the contained format driver instance.

Source

pub fn size(&self) -> u64

Return the disk size in bytes.

Source

pub fn set_async_read_parallelization(&mut self, count: usize)

Set the number of simultaneous async requests per read.

When issuing read requests, issue this many async requests in parallel (still in a single thread). The default count is 1, i.e. no parallel requests.

Source

pub fn set_async_write_parallelization(&mut self, count: usize)

Set the number of simultaneous async requests per write.

When issuing write requests, issue this many async requests in parallel (still in a single thread). The default count is 1, i.e. no parallel requests.

Source

pub(crate) fn collect_storage_dependencies(&self) -> Vec<&S>

Return all storage dependencies of this image.

Includes recursive dependencies, i.e. those from other image dependencies like backing images.

Source

pub fn req_align(&self) -> usize

Minimal I/O alignment, for both length and offset.

All requests to this image should be aligned to this value, both in length and offset.

Requests that do not match this alignment will be realigned internally, which requires creating bounce buffers and read-modify-write cycles for write requests, which is costly, so should be avoided.

Source

pub fn mem_align(&self) -> usize

Minimal memory buffer alignment, for both address and length.

All buffers used in requests to this image should be aligned to this value, both their address and length.

Request buffers that do not match this alignment will be realigned internally, which requires creating bounce buffers, which is costly, so should be avoided.

Source

async fn read_chunk( &self, bufv: IoVectorMut<'_>, mapping: Mapping<'_, S>, ) -> Result<()>

Read the data from the given mapping.

Source

pub async fn get_shallow_mapping( &self, offset: u64, max_length: u64, ) -> Result<(ShallowMapping<'_, S>, u64)>

Return the shallow mapping at offset.

Find what offset is mapped to, which may be another format layer, return that information, and the length of the continuous mapping (from offset).

Use FormatAccess::get_mapping() to recursively fully resolve references to other format layers.

Source

pub async fn get_mapping( &self, offset: u64, max_length: u64, ) -> Result<(Mapping<'_, S>, u64)>

Return the recursively resolved mapping at offset.

Find what offset is mapped to, return that mapping information, and the length of that continuous mapping (from offset).

All data references to other format layers are automatically resolved (recursively), so that the result are more “trivial” mappings (unless prevented by special mappings like compressed clusters).

Source

pub async fn ensure_data_mapping( &self, offset: u64, length: u64, overwrite: bool, ) -> Result<(&S, u64, u64)>

Create a raw data mapping at offset.

Ensure that offset is directly mapped to some storage object, up to a length of length. Return the storage object, the corresponding offset there, and the continuous length that we were able to map (less than or equal to length).

If overwrite is true, the contents in the range are supposed to be overwritten and may be discarded. Otherwise, they are kept.

Source

pub async fn readv(&self, bufv: IoVectorMut<'_>, offset: u64) -> Result<()>

Read data at offset into bufv.

Reads until bufv is filled completely, i.e. will not do short reads. When reaching the end of file, the rest of bufv is filled with 0.

Source

pub async fn read( &self, buf: impl Into<IoVectorMut<'_>>, offset: u64, ) -> Result<()>

Read data at offset into buf.

Reads until buf is filled completely, i.e. will not do short reads. When reaching the end of file, the rest of buf is filled with 0.

Source

pub async fn writev(&self, bufv: IoVector<'_>, offset: u64) -> Result<()>

Write data from bufv to offset.

Writes all data from bufv (or returns an error), i.e. will not do short writes. Reaching the end of file before the end of the buffer results in an error.

Source

pub async fn write( &self, buf: impl Into<IoVector<'_>>, offset: u64, ) -> Result<()>

Write data from buf to offset.

Writes all data from bufv (or returns an error), i.e. will not do short writes. Reaching the end of file before the end of the buffer results in an error.

Source

async fn is_range_zero(&self, offset: u64, length: u64) -> bool

Check whether the given range is zero.

Checks for zero mappings, not zero data (although this might be changed in the future).

Errors are treated as non-zero areas.

Source

async fn soft_ensure_zero(&self, offset: u64, length: u64) -> Result<()>

Ensure the given range reads as zeroes, without write-zeroes support.

Does not require support for efficient zeroing, instead writing zeroes when the range is not zero yet. If allocate is true, areas that are not currently allocated will be allocated to write zeroes there; if it is false, unallocated areas that currently read as zero are left alone.

However, can still use efficient zero support if present.

The main use case is to handle unaligned zero requests. Quite inefficient for large areas.

Source

pub async fn write_zeroes(&self, offset: u64, length: u64) -> Result<()>

Ensure the given range reads as zeroes.

May use efficient zeroing for a subset of the given range, if supported by the format. Will not discard anything, which keeps existing data mappings usable, albeit writing to mappings that are now zeroed may have no effect.

Check if FormatAccess::discard_to_zero() better suits your needs: It may work better on a wider range of formats (write_zeroes() requires support for preallocated zero clusters, which qcow2 does have, but other formats may not), and can actually free up space. However, because it can break existing data mappings, it requires a mutable self reference.

Source

pub async fn discard_to_zero(&mut self, offset: u64, length: u64) -> Result<()>

Discard the given range, ensure it is read back as zeroes.

Effectively the same as FormatAccess::write_zeroes(), but discard as much of the existing allocation as possible. This breaks existing data mappings, so needs a mutable reference to self, which ensures that existing data references (which have the lifetime of an immutable self reference) cannot be kept.

Areas that cannot be discarded (because of format-inherent alignment restrictions) are still overwritten with zeroes, unless discarding is not supported altogether.

Source

pub async fn discard_to_any(&mut self, offset: u64, length: u64) -> Result<()>

Discard the given range, not guaranteeing specific data on read-back.

Discard as much of the given range as possible, and keep the rest as-is. Does not guarantee any specific data on read-back, in contrast to FormatAccess::discard_to_zero().

Discarding being unsupported by this format is still returned as an error (std::io::ErrorKind::Unsupported)

Source

pub async fn discard_to_backing( &mut self, offset: u64, length: u64, ) -> Result<()>

Discard the given range, such that the backing image becomes visible.

Discard as much of the given range as possible so that a backing image’s data becomes visible, and keep the rest as-is. This breaks existing data mappings, so needs a mutable reference to self, which ensures that existing data references (which have the lifetime of an immutable self reference) cannot be kept.

Source

pub async fn flush(&self) -> Result<()>

Flush internal buffers. Always call this before drop!

Does not necessarily sync those buffers to disk. When using flush(), consider whether you want to call sync() afterwards.

Because of the current lack of stable async_drop, you must manually call this before dropping a FormatAccess instance! (Not necessarily for read-only images, though.)

Note that this will not drop the buffers, so they may still be used to serve later accesses. Use FormatAccess::invalidate_cache() to drop all buffers.

Source

pub async fn sync(&self) -> Result<()>

Sync data already written to the storage hardware.

This does not necessarily include flushing internal buffers, i.e. flush. When using sync(), consider whether you want to call flush() before it.

Source

pub async unsafe fn invalidate_cache(&self) -> Result<()>

Drop internal buffers.

This drops all internal buffers, but does not flush them! All cached data is reloaded from disk on subsequent accesses.

§Safety

Not flushing internal buffers may cause image corruption. You must ensure the on-disk state is consistent.

Source

pub async fn resize( &mut self, new_size: u64, prealloc_mode: PreallocateMode, ) -> Result<()>

Resize to the given size.

Set the disk size to new_size. If new_size is smaller than the current size, ignore both preallocation modes and discard the data after new_size.

If new_size is larger than the current size, prealloc_mode determines whether and how the new range should be allocated; depending on the image format, is possible some preallocation modes are not supported, in which case an std::io::ErrorKind::Unsupported is returned.

This may break existing data mappings, so needs a mutable reference to self, which ensures that existing data references (which have the lifetime of an immutable self reference) cannot be kept.

See also FormatAccess::resize_grow() and FormatAccess::resize_shrink(), whose more specialized interface may be useful when you know whether you want to grow or shrink the image.

Source

pub async fn resize_grow( &self, new_size: u64, prealloc_mode: PreallocateMode, ) -> Result<()>

Resize to the given size, which must be greater than the current size.

Set the disk size to new_size, preallocating the new space according to prealloc_mode. Depending on the image format, it is possible some preallocation modes are not supported, in which case an std::io::ErrorKind::Unsupported is returned.

If the current size is already new_size or greater, do nothing.

Source

pub async fn resize_shrink(&mut self, new_size: u64) -> Result<()>

Truncate to the given size, which must be smaller than the current size.

Set the disk size to new_size, discarding the data after new_size.

May break existing data mappings thanks to the mutable self reference.

If the current size is already new_size or smaller, do nothing.

Trait Implementations§

Source§

impl<S: Debug + Storage + 'static> Debug for FormatAccess<S>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<S: Storage> Display for FormatAccess<S>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<S: Storage> TryFrom<FormatAccess<S>> for SyncFormatAccess<S>

Source§

type Error = Error

The type returned in the event of a conversion error.
Source§

fn try_from(async_access: FormatAccess<S>) -> Result<Self>

Performs the conversion.
Source§

impl<S: Storage> WrappedFormat<S> for FormatAccess<S>

Source§

fn wrap(inner: FormatAccess<S>) -> Self

Construct this WrappedFormat.
Source§

fn inner(&self) -> &FormatAccess<S>

Access the inner format instance.

Auto Trait Implementations§

§

impl<S> Freeze for FormatAccess<S>

§

impl<S> !RefUnwindSafe for FormatAccess<S>

§

impl<S> Send for FormatAccess<S>

§

impl<S> Sync for FormatAccess<S>

§

impl<S> Unpin for FormatAccess<S>

§

impl<S> !UnwindSafe for FormatAccess<S>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more