Skip to main content

L2Table

Struct L2Table 

Source
pub(super) struct L2Table {
    cluster: Option<HostCluster>,
    data: Box<[AtomicL2Entry]>,
    cluster_bits: u32,
    external_data_file: bool,
    modified: AtomicBool,
    writer_lock: OwnedRwLock<()>,
    writeback_lock: Mutex<()>,
}
Expand description

L2 table.

Fields§

§cluster: Option<HostCluster>

Cluster of the L2 table.

§data: Box<[AtomicL2Entry]>

Table data.

§cluster_bits: u32

log2 of the cluster size.

§external_data_file: bool

Whether this image uses an external data file.

§modified: AtomicBool

Whether this table has been modified since it was last written.

§writer_lock: OwnedRwLock<()>

Lock for creating L2TableWriteGuard (write) and CompressedClusterReadGuard (read).

This is an owning (Arc-backed) lock, i.e. any access guard will have a strong reference to it and can thus be held independently of lifetime concerns, e.g. across a data write while a prepared mapping is not yet committed (see Qcow2::prepare_data_mapping()).

Consequently, it may be held outside of qcow2 code paths, e.g. while a data write is in flight (between preparing and committing a data mapping for it). Thus, writing this table to disk must work without the lock because otherwise flushing the table would deadlock against such writes.

§writeback_lock: Mutex<()>

Serializes writing this table back to disk (see L2Table::write_if_modified()).

Implementations§

Source§

impl L2Table

Source

pub fn new_cleared(header: &Header) -> Self

Create a new zeroed L2 table.

Source

pub fn get_mapping(&self, lookup_cluster: GuestCluster) -> Result<L2Mapping>

Look up a cluster mapping.

Source

pub async fn lock_write(self: &Arc<Self>) -> L2TableWriteGuard

Allow modifying this L2 table.

Note that readers are allowed to exist while modifications are happening, unless they hold a CompressedClusterReadGuard.

The returned guard keeps the table pinned in the L2 cache.

Source

pub async fn lock_compressed_read( &self, cluster: GuestCluster, ) -> Result<Option<CompressedClusterReadGuard<'_>>>

Lock the given compressed cluster for reading.

Prevent modifications of this L2 table while the returned guard is held.

Return None if cluster is not compressed (checked under the guard).

Source

pub async fn write_if_modified<S: Storage>( &self, image: &S, cluster: HostCluster, ) -> Result<()>

Write this table to disk if it has been modified since it was last written.

This is the entry point for writing back a table that is part of the L2 cache; it serializes such write-backs against each other via writeback_lock. Writing the table clears the modified flag before copying the entries, so without that lock, two concurrent write-backs could race such that the one with the older copy writes last, leaving that older copy on disk while the table no longer appears modified. Holding the lock across the modified check means that a write-back which has to wait only writes again if something changed after the preceding write-back’s copy.

cluster is the cluster this table is expected to belong to; an assert!() verifies that it really is the table’s cluster.

Trait Implementations§

Source§

impl Clone for L2Table

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for L2Table

Source§

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

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

impl Drop for L2Table

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl Table for L2Table

Source§

const NAME: &'static str = "L2 table"

User-readable struct name.
Source§

const MAX_ENTRIES: usize

Maximum allowable number of entries.
Source§

type InternalEntry = AtomicL2Entry

Internal type for each table entry.
Source§

type Entry = L2Entry

Externally visible type for each table entry.
Source§

fn from_data(data: Box<[AtomicL2Entry]>, header: &Header) -> Self

Create a new table with the given contents
Source§

fn entries(&self) -> usize

Number of entries.
Source§

fn get_ref(&self, index: usize) -> Option<&AtomicL2Entry>

Get the given entry (as reference).
Source§

fn get(&self, index: usize) -> L2Entry

Get the given entry (copied).
Source§

fn get_cluster(&self) -> Option<HostCluster>

Get this table’s (first) cluster in the image file.
Source§

fn get_offset(&self) -> Option<HostOffset>

Get this table’s offset in the image file.
Source§

fn set_cluster(&mut self, cluster: HostCluster)

Set this table’s (first) cluster in the image file (for writing).
Source§

fn unset_cluster(&mut self)

Remove the table’s association with any cluster in the image file.
Source§

fn is_modified(&self) -> bool

Check whether this table has been modified since it was last written.
Source§

fn clear_modified(&self)

Clear the modified flag.
Source§

fn set_modified(&self)

Set the modified flag.
Source§

fn cluster_bits(&self) -> u32

Return log2 of the cluster size. Read more
Source§

fn byte_size(&self) -> usize

Table size in bytes.
Source§

fn cluster_count(&self) -> ClusterCount

Number of clusters used by this table.
Source§

async fn load<S: Storage>( image: &S, header: &Header, cluster: HostCluster, entries: usize, ) -> Result<Self>

Load a table from the image file.
Source§

async fn write<S: Storage>(&self, image: &S) -> Result<()>

Write a table to the image file. Read more
Source§

async fn write_entry<S: Storage>(&self, image: &S, index: usize) -> Result<()>

Write at least the given single (modified) entry to the image file. Read more

Auto Trait Implementations§

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. 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