fn file_offset_write(&mut self, address: u64) -> std::io::Result<u64> {
        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;

        let mut set_refcounts = Vec::new();

        if !self.l2_cache.contains_key(l1_index) {
            // Not in the cache.
            let l2_table = if l2_addr_disk == 0 {
                // Allocate a new cluster to store the L2 table and update the L1 table to point
                // to the new table.
                let new_addr: u64 = self.get_new_cluster()?;
                // The cluster refcount starts at one meaning it is used but doesn't need COW.
                set_refcounts.push((new_addr, 1));
                self.l1_table[l1_index] = new_addr;
                VecCache::new(self.l2_entries as usize)
            } else {
                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, l2_table, |index, evicted| {
                raw_file.write_pointer_table(
                    l1_table[index],
                    evicted.get_values(),
                    CLUSTER_USED_FLAG,
                )
            })?;
        }

        let cluster_addr = match self.l2_cache.get(l1_index).unwrap()[l2_index] {
            0 => {
                // Need to allocate a data cluster
                let cluster_addr = self.append_data_cluster()?;
                self.update_cluster_addr(l1_index, l2_index, cluster_addr, &mut set_refcounts)?;
                cluster_addr
            }
            a => a,
        };

        for (addr, count) in set_refcounts {
            let mut newly_unref = self.set_cluster_refcount(addr, count)?;
            self.unref_clusters.append(&mut newly_unref);
        }

        Ok(cluster_addr + self.raw_file.cluster_offset(address))
    }
// Gets the offset of the given guest address in the host file. If L1, L2, or data clusters need
// to be allocated, they will be.
Gets the offset of the given guest address in the host file. If L1, L2, or data clusters need
to be allocated, they will be.
Gets the offset of the given guest address in the host file . If L1 L2 or data clusters need to be allocated they will be .
fn file_offset_write(&mut self, address: u64) -> std::io::Result<u64> {
        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;
        let mut set_refcounts = Vec::new();
        if !self.l2_cache.contains_key(l1_index) {
            // Not in the cache.
            let l2_table = if l2_addr_disk == 0 {
                // Allocate a new cluster to store the L2 table and update the L1 table to point
                // to the new table.
                let new_addr: u64 = self.get_new_cluster()?;
                // The cluster refcount starts at one meaning it is used but doesn't need COW.
                set_refcounts.push((new_addr, 1));
                self.l1_table[l1_index] = new_addr;
                VecCache::new(self.l2_entries as usize)
            } else {
                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, l2_table, |index, evicted| {
                raw_file.write_pointer_table(
                    l1_table[index],
                    evicted.get_values(),
                    CLUSTER_USED_FLAG,
                )
            })?;
        }
        let cluster_addr = match self.l2_cache.get(l1_index).unwrap()[l2_index] {
            0 => {
                // Need to allocate a data cluster
                let cluster_addr = self.append_data_cluster()?;
                self.update_cluster_addr(l1_index, l2_index, cluster_addr, &mut set_refcounts)?;
                cluster_addr
            }
            a => a,
        };
        for (addr, count) in set_refcounts {
            let mut newly_unref = self.set_cluster_refcount(addr, count)?;
            self.unref_clusters.append(&mut newly_unref);
        }
        Ok(cluster_addr + self.raw_file.cluster_offset(address))
    }
fn file_offset_write ( & mut self , address : u64 ) -> std :: io :: Result < u64 > { 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 ; let mut set_refcounts = Vec :: new ( ) ; if ! self . l2_cache . contains_key ( l1_index ) { // Not in the cache. let l2_table = if l2_addr_disk == 0 { // Allocate a new cluster to store the L2 table and update the L1 table to point // to the new table. let new_addr : u64 = self . get_new_cluster ( ) ? ; // The cluster refcount starts at one meaning it is used but doesn't need COW. set_refcounts . push ( ( new_addr , 1 ) ) ; self . l1_table [ l1_index ] = new_addr ; VecCache :: new ( self . l2_entries as usize ) } else { 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 , l2_table , | index , evicted | { raw_file . write_pointer_table ( l1_table [ index ] , evicted . get_values ( ) , CLUSTER_USED_FLAG , ) } ) ? ; } let cluster_addr = match self . l2_cache . get ( l1_index ) . unwrap ( ) [ l2_index ] { 0 => { // Need to allocate a data cluster let cluster_addr = self . append_data_cluster ( ) ? ; self . update_cluster_addr ( l1_index , l2_index , cluster_addr , & mut set_refcounts ) ? ; cluster_addr } a => a , } ; for ( addr , count ) in set_refcounts { let mut newly_unref = self . set_cluster_refcount ( addr , count ) ? ; self . unref_clusters . append ( & mut newly_unref ) ; } Ok ( cluster_addr + self . raw_file . cluster_offset ( address ) ) }
Gets the offset of the given guest address in the host file.
Gets the offset of the given guest address in the host file .
&mut self
address
u64
&mut self
address
u64