pub(super) struct Allocator<S: Storage> {
file: Arc<S>,
reftable: RefTable,
first_free_cluster: HostCluster,
header: Arc<Header>,
rb_cache: AsyncLruCache<HostCluster, RefBlock, RefBlockCacheBackend<S>>,
}
Expand description
Central facility for cluster allocation.
Fields§
§file: Arc<S>
Qcow2 metadata file.
reftable: RefTable
Qcow2 refcount table.
first_free_cluster: HostCluster
The first free cluster index in the qcow2 file, to speed up allocation.
header: Arc<Header>
Qcow2 image header.
rb_cache: AsyncLruCache<HostCluster, RefBlock, RefBlockCacheBackend<S>>
Refblock cache.
Implementations§
Source§impl<S: Storage> Allocator<S>
impl<S: Storage> Allocator<S>
Sourcepub async fn new(image: Arc<S>, header: Arc<Header>) -> Result<Self>
pub async fn new(image: Arc<S>, header: Arc<Header>) -> Result<Self>
Create a new allocator for the given image file.
Sourcepub async fn flush_rb_cache(&self) -> Result<()>
pub async fn flush_rb_cache(&self) -> Result<()>
Flush the refcount block cache.
Sourcepub async unsafe fn invalidate_rb_cache(&self) -> Result<()>
pub async unsafe fn invalidate_rb_cache(&self) -> Result<()>
Invaidate the refcount block cache.
§Safety
May cause image corruption, you must guarantee the on-disk state is consistent.
Sourceasync fn allocate_clusters(
&mut self,
count: ClusterCount,
end_cluster: Option<HostCluster>,
) -> Result<HostCluster>
async fn allocate_clusters( &mut self, count: ClusterCount, end_cluster: Option<HostCluster>, ) -> Result<HostCluster>
Allocate clusters in the image file.
end_cluster
should only be used when allocating refblocks. When reaching this cluster
index, abort trying to allocate. (This is used for allocating refblocks, to prevent
infinite recursion and speed things up.)
Sourceasync fn allocate_clusters_at(
&mut self,
index: HostCluster,
count: ClusterCount,
) -> Result<ClusterCount>
async fn allocate_clusters_at( &mut self, index: HostCluster, count: ClusterCount, ) -> Result<ClusterCount>
Allocate the given clusters in the image file.
Allocate up to count
unallocated clusters starting from index
. When encountering an
already allocated cluster (or any other error), stop, and free the clusters that were just
newly allocated.
Returns the number of clusters that could be allocated (starting from index
), which may
be 0 if index
has already been allocated. Note again that in case this is less than
count
, those clusters will have been freed again already, so this is just a hint to
callers that the cluster at index + count
is already allocated.
Sourceasync fn allocate_cluster_at(&mut self, index: HostCluster) -> Result<bool>
async fn allocate_cluster_at(&mut self, index: HostCluster) -> Result<bool>
Allocate the given cluster in the image file.
Return Ok(true)
if allocation was successful, or Ok(false)
if the cluster was already
allocated before.
Sourceasync fn get_rb(&mut self, rt_index: usize) -> Result<Option<Arc<RefBlock>>>
async fn get_rb(&mut self, rt_index: usize) -> Result<Option<Arc<RefBlock>>>
Get the refblock referenced by the given reftable index, if any.
If there is no refblock for the given reftable index, return Ok(None)
.
Sourceasync fn ensure_rb(&mut self, rt_index: usize) -> Result<Arc<RefBlock>>
async fn ensure_rb(&mut self, rt_index: usize) -> Result<Arc<RefBlock>>
Get a refblock for the given reftable index.
If there already is a refblock at that index, return it. Otherwise, create one and hook it up.
Sourceasync fn grow_reftable(&mut self, at_least_index: usize) -> Result<()>
async fn grow_reftable(&mut self, at_least_index: usize) -> Result<()>
Create a new refcount table covering at least at_least_index
.
Create a new reftable of the required size, copy all existing refblock references into it, ensure it is refcounted itself (also creating new refblocks if necessary), and have the image header reference the new refcount table.
Sourceasync fn free_clusters(&mut self, start: HostCluster, count: ClusterCount)
async fn free_clusters(&mut self, start: HostCluster, count: ClusterCount)
Free clusters (i.e. decrement their refcount).
Best-effort operation. On error, the given clusters may be leaked, but no errors are ever returned (because there is no good way to handle such errors anyway).