/// This is not thread-safe; the caller is responsible for making sure that only one thread is
/// mutating the cache at any point in time.
This is not thread-safe; the caller is responsible for making sure that only one thread is
mutating the cache at any point in time.
This is not thread - safe ; the caller is responsible for making sure that only one thread is mutating the cache at any point in time .
pub async fn resize(
        &self,
        size: u64,
        block_size: u64,
        reserver: &dyn StorageReservation,
    ) -> Result<(), Error> {
        {
            let mut inner = self.inner.lock().unwrap();
            let old_size = *inner.content_size.as_ref().unwrap_or(&(self.data.size() as u64));
            let aligned_size = round_up(size, block_size).unwrap();
            if size < old_size {
                let removed = inner.intervals.remove_interval(&(aligned_size..u64::MAX)).unwrap();
                let reserved_before = reserver.reservation_needed(inner.dirty_bytes);
                for interval in removed {
                    if let CacheState::Dirty = interval.state {
                        inner.dirty_bytes = inner
                            .dirty_bytes
                            .checked_sub(interval.range.end - interval.range.start)
                            .unwrap();
                    }
                }
                let reserved_after = reserver.reservation_needed(inner.dirty_bytes);
                if reserved_after < reserved_before {
                    // Give back whatever reservation we no longer need.
                    let _ = reserver.wrap_reservation(reserved_before - reserved_after);
                }
            }
            if size != old_size {
                inner.content_size = Some(size);
            }
        }
        // Resize the buffer after making changes to |inner| to avoid a race when truncating (where
        // we could have intervals that reference nonexistent parts of the buffer).
        // Note that there's a similar race for extending when we do things in this order, but we
        // don't think that is problematic since there are no intervals (since we're expanding).
        // If that turns out to be problematic, we'll have to atomically update both the buffer and
        // the interval tree at once.
        self.data.resize(size).await;
        // We must update min_size *after* we've resized the buffer since if we do it beforehand, we
        // might end up servicing page requests that are expected to succeed for the old size, but
        // because min_size has changed, it'll return zeroed data when rather than actually issue a
        // read.  It's safe to change this afterwards because any page requests that the kernel
        // handles should already be shortened and min_size only exists for the case where the VMO
        // grows again later, which can't happen because the caller should be holding a lock.  This
        // doesn't need to be synchronized with `content_size` because it's used to handle races
        // with between shrinking and page-ins; unlike `content_size`, it isn't used for flushing.
        // TODO(csuter): When we support discardable pages, this will need to be updated *after* a
        // successful flush but *before* pages are marked as discardable.
        let mut inner = self.inner.lock().unwrap();
        if size < inner.min_size {
            inner.min_size = size;
        }
        Ok(())
    }
pub async fn resize ( & self , size : u64 , block_size : u64 , reserver : & dyn StorageReservation , ) -> Result < ( ) , Error > { { let mut inner = self . inner . lock ( ) . unwrap ( ) ; let old_size = * inner . content_size . as_ref ( ) . unwrap_or ( & ( self . data . size ( ) as u64 ) ) ; let aligned_size = round_up ( size , block_size ) . unwrap ( ) ; if size < old_size { let removed = inner . intervals . remove_interval ( & ( aligned_size .. u64 :: MAX ) ) . unwrap ( ) ; let reserved_before = reserver . reservation_needed ( inner . dirty_bytes ) ; for interval in removed { if let CacheState :: Dirty = interval . state { inner . dirty_bytes = inner . dirty_bytes . checked_sub ( interval . range . end - interval . range . start ) . unwrap ( ) ; } } let reserved_after = reserver . reservation_needed ( inner . dirty_bytes ) ; if reserved_after < reserved_before { // Give back whatever reservation we no longer need. let _ = reserver . wrap_reservation ( reserved_before - reserved_after ) ; } } if size != old_size { inner . content_size = Some ( size ) ; } } // Resize the buffer after making changes to |inner| to avoid a race when truncating (where // we could have intervals that reference nonexistent parts of the buffer). // Note that there's a similar race for extending when we do things in this order, but we // don't think that is problematic since there are no intervals (since we're expanding). // If that turns out to be problematic, we'll have to atomically update both the buffer and // the interval tree at once. self . data . resize ( size ) . await ; // We must update min_size *after* we've resized the buffer since if we do it beforehand, we // might end up servicing page requests that are expected to succeed for the old size, but // because min_size has changed, it'll return zeroed data when rather than actually issue a // read.  It's safe to change this afterwards because any page requests that the kernel // handles should already be shortened and min_size only exists for the case where the VMO // grows again later, which can't happen because the caller should be holding a lock.  This // doesn't need to be synchronized with `content_size` because it's used to handle races // with between shrinking and page-ins; unlike `content_size`, it isn't used for flushing. // TODO(csuter): When we support discardable pages, this will need to be updated *after* a // successful flush but *before* pages are marked as discardable. let mut inner = self . inner . lock ( ) . unwrap ( ) ; if size < inner . min_size { inner . min_size = size ; } Ok ( ( ) ) }
This is not thread-safe; the caller is responsible for making sure that only one thread is
mutating the cache at any point in time.
This is not thread - safe ; the caller is responsible for making sure that only one thread is mutating the cache at any point in time .
&self
size
u64
block_size
u64
reserver
&dyn StorageReservation