fn deallocate_cluster(&mut self, address: u64) -> std::io::Result<()> {
        if address >= self.virtual_size() as u64 {
            return Err(std::io::Error::from_raw_os_error(EINVAL));
        }

        let l1_index = self.l1_table_index(address) as usize;
        let l2_addr_disk = *self
            .l1_table
            .get(l1_index)
            .ok_or_else(|| std::io::Error::from_raw_os_error(EINVAL))?;
        let l2_index = self.l2_table_index(address) as usize;

        if l2_addr_disk == 0 {
            // The whole L2 table for this address is not allocated yet,
            // so the cluster must also be unallocated.
            return Ok(());
        }

        if !self.l2_cache.contains_key(l1_index) {
            // Not in the cache.
            let table =
                VecCache::from_vec(Self::read_l2_cluster(&mut self.raw_file, l2_addr_disk)?);
            let l1_table = &self.l1_table;
            let raw_file = &mut self.raw_file;
            self.l2_cache.insert(l1_index, table, |index, evicted| {
                raw_file.write_pointer_table(
                    l1_table[index],
                    evicted.get_values(),
                    CLUSTER_USED_FLAG,
                )
            })?;
        }

        let cluster_addr = self.l2_cache.get(l1_index).unwrap()[l2_index];
        if cluster_addr == 0 {
            // This cluster is already unallocated; nothing to do.
            return Ok(());
        }

        // Decrement the refcount.
        let refcount = self
            .refcounts
            .get_cluster_refcount(&mut self.raw_file, cluster_addr)
            .map_err(|e| {
                io::Error::new(
                    io::ErrorKind::InvalidData,
                    format!("failed to get cluster refcount: {}", e),
                )
            })?;
        if refcount == 0 {
            return Err(std::io::Error::from_raw_os_error(EINVAL));
        }

        let new_refcount = refcount - 1;
        let mut newly_unref = self.set_cluster_refcount(cluster_addr, new_refcount)?;
        self.unref_clusters.append(&mut newly_unref);

        // Rewrite the L2 entry to remove the cluster mapping.
        // unwrap is safe as we just checked/inserted this entry.
        self.l2_cache.get_mut(l1_index).unwrap()[l2_index] = 0;

        if new_refcount == 0 {
            let cluster_size = self.raw_file.cluster_size();
            // This cluster is no longer in use; deallocate the storage.
            // The underlying FS may not support FALLOC_FL_PUNCH_HOLE,
            // so don't treat an error as fatal.  Future reads will return zeros anyways.
            let _ = self
                .raw_file
                .file_mut()
                .punch_hole(cluster_addr, cluster_size);
            self.unref_clusters.push(cluster_addr);
        }
        Ok(())
    }
// Deallocate the storage for the cluster starting at `address`.
// Any future reads of this cluster will return all zeroes.
Deallocate the storage for the cluster starting at `address`.
Any future reads of this cluster will return all zeroes.
Deallocate the storage for the cluster starting at ` address ` . Any future reads of this cluster will return all zeroes .
fn deallocate_cluster(&mut self, address: u64) -> std::io::Result<()> {
        if address >= self.virtual_size() as u64 {
            return Err(std::io::Error::from_raw_os_error(EINVAL));
        }
        let l1_index = self.l1_table_index(address) as usize;
        let l2_addr_disk = *self
            .l1_table
            .get(l1_index)
            .ok_or_else(|| std::io::Error::from_raw_os_error(EINVAL))?;
        let l2_index = self.l2_table_index(address) as usize;
        if l2_addr_disk == 0 {
            // The whole L2 table for this address is not allocated yet,
            // so the cluster must also be unallocated.
            return Ok(());
        }
        if !self.l2_cache.contains_key(l1_index) {
            // Not in the cache.
            let table =
                VecCache::from_vec(Self::read_l2_cluster(&mut self.raw_file, l2_addr_disk)?);
            let l1_table = &self.l1_table;
            let raw_file = &mut self.raw_file;
            self.l2_cache.insert(l1_index, table, |index, evicted| {
                raw_file.write_pointer_table(
                    l1_table[index],
                    evicted.get_values(),
                    CLUSTER_USED_FLAG,
                )
            })?;
        }
        let cluster_addr = self.l2_cache.get(l1_index).unwrap()[l2_index];
        if cluster_addr == 0 {
            // This cluster is already unallocated; nothing to do.
            return Ok(());
        }
        // Decrement the refcount.
        let refcount = self
            .refcounts
            .get_cluster_refcount(&mut self.raw_file, cluster_addr)
            .map_err(|e| {
                io::Error::new(
                    io::ErrorKind::InvalidData,
                    format!("failed to get cluster refcount: {}", e),
                )
            })?;
        if refcount == 0 {
            return Err(std::io::Error::from_raw_os_error(EINVAL));
        }
        let new_refcount = refcount - 1;
        let mut newly_unref = self.set_cluster_refcount(cluster_addr, new_refcount)?;
        self.unref_clusters.append(&mut newly_unref);
        // Rewrite the L2 entry to remove the cluster mapping.
        // unwrap is safe as we just checked/inserted this entry.
        self.l2_cache.get_mut(l1_index).unwrap()[l2_index] = 0;
        if new_refcount == 0 {
            let cluster_size = self.raw_file.cluster_size();
            // This cluster is no longer in use; deallocate the storage.
            // The underlying FS may not support FALLOC_FL_PUNCH_HOLE,
            // so don't treat an error as fatal.  Future reads will return zeros anyways.
            let _ = self
                .raw_file
                .file_mut()
                .punch_hole(cluster_addr, cluster_size);
            self.unref_clusters.push(cluster_addr);
        }
        Ok(())
    }
fn deallocate_cluster ( & mut self , address : u64 ) -> std :: io :: Result < ( ) > { if address >= self . virtual_size ( ) as u64 { return Err ( std :: io :: Error :: from_raw_os_error ( EINVAL ) ) ; } let l1_index = self . l1_table_index ( address ) as usize ; let l2_addr_disk = * self . l1_table . get ( l1_index ) . ok_or_else ( | | std :: io :: Error :: from_raw_os_error ( EINVAL ) ) ? ; let l2_index = self . l2_table_index ( address ) as usize ; if l2_addr_disk == 0 { // The whole L2 table for this address is not allocated yet, // so the cluster must also be unallocated. return Ok ( ( ) ) ; } if ! self . l2_cache . contains_key ( l1_index ) { // Not in the cache. let table = VecCache :: from_vec ( Self :: read_l2_cluster ( & mut self . raw_file , l2_addr_disk ) ? ) ; let l1_table = & self . l1_table ; let raw_file = & mut self . raw_file ; self . l2_cache . insert ( l1_index , table , | index , evicted | { raw_file . write_pointer_table ( l1_table [ index ] , evicted . get_values ( ) , CLUSTER_USED_FLAG , ) } ) ? ; } let cluster_addr = self . l2_cache . get ( l1_index ) . unwrap ( ) [ l2_index ] ; if cluster_addr == 0 { // This cluster is already unallocated; nothing to do. return Ok ( ( ) ) ; } // Decrement the refcount. let refcount = self . refcounts . get_cluster_refcount ( & mut self . raw_file , cluster_addr ) . map_err ( | e | { io :: Error :: new ( io :: ErrorKind :: InvalidData , format ! ( " " e ) , ) } ) ? ; if refcount == 0 { return Err ( std :: io :: Error :: from_raw_os_error ( EINVAL ) ) ; } let new_refcount = refcount - 1 ; let mut newly_unref = self . set_cluster_refcount ( cluster_addr , new_refcount ) ? ; self . unref_clusters . append ( & mut newly_unref ) ; // Rewrite the L2 entry to remove the cluster mapping. // unwrap is safe as we just checked/inserted this entry. self . l2_cache . get_mut ( l1_index ) . unwrap ( ) [ l2_index ] = 0 ; if new_refcount == 0 { let cluster_size = self . raw_file . cluster_size ( ) ; // This cluster is no longer in use; deallocate the storage. // The underlying FS may not support FALLOC_FL_PUNCH_HOLE, // so don't treat an error as fatal.  Future reads will return zeros anyways. let _ = self . raw_file . file_mut ( ) . punch_hole ( cluster_addr , cluster_size ) ; self . unref_clusters . push ( cluster_addr ) ; } Ok ( ( ) ) }
Deallocate the storage for the cluster starting at `address`.
Deallocate the storage for the cluster starting at ` address ` .
&mut self
address
u64
&mut self
address
u64