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: u32log2 of the cluster size.
external_data_file: boolWhether this image uses an external data file.
modified: AtomicBoolWhether 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
impl L2Table
Sourcepub fn new_cleared(header: &Header) -> Self
pub fn new_cleared(header: &Header) -> Self
Create a new zeroed L2 table.
Sourcepub fn get_mapping(&self, lookup_cluster: GuestCluster) -> Result<L2Mapping>
pub fn get_mapping(&self, lookup_cluster: GuestCluster) -> Result<L2Mapping>
Look up a cluster mapping.
Sourcepub async fn lock_write(self: &Arc<Self>) -> L2TableWriteGuard
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.
Sourcepub async fn lock_compressed_read(
&self,
cluster: GuestCluster,
) -> Result<Option<CompressedClusterReadGuard<'_>>>
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).
Sourcepub async fn write_if_modified<S: Storage>(
&self,
image: &S,
cluster: HostCluster,
) -> Result<()>
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.