Skip to main content

fxfs/object_store/
data_object_handle.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::errors::FxfsError;
6use crate::log::*;
7use crate::lsm_tree::Query;
8use crate::lsm_tree::types::{ItemRef, LayerIterator};
9use crate::object_handle::{
10    LayerObject, ObjectHandle, ObjectProperties, ReadObjectHandle, WriteBytes, WriteObjectHandle,
11};
12use crate::object_store::extent_record::{ExtentMode, ExtentValue};
13use crate::object_store::object_manager::ObjectManager;
14use crate::object_store::object_record::{
15    AttributeKey, DirType, FsverityMetadata, ObjectAttributes, ObjectItem, ObjectKey,
16    ObjectKeyData, ObjectKind, ObjectValue, Timestamp,
17};
18use crate::object_store::store_object_handle::{MaybeChecksums, NeedsTrim};
19use crate::object_store::transaction::{
20    self, AssocObj, AssociatedObject, LockKey, Mutation, ObjectStoreMutation, Operation, Options,
21    ReadGuard, ReservationOptions, Transaction, lock_keys,
22};
23use crate::object_store::{
24    AttributeId, Extent, HandleOptions, HandleOwner, RootDigest, StoreObjectHandle,
25    TRANSACTION_MUTATION_THRESHOLD, TrimMode, TrimResult,
26};
27use crate::range::RangeExt;
28use anyhow::{Context, Error, anyhow, bail, ensure};
29use fidl_fuchsia_io as fio;
30use fsverity_merkle::{
31    FsVerityDescriptor, FsVerityDescriptorRaw, FsVerityHash, FsVerityHasher, FsVerityHasherOptions,
32    MerkleTree, MerkleTreeBuilder, Sha256Hash, Sha512Hash,
33};
34use fuchsia_sync::Mutex;
35use futures::TryStreamExt;
36use futures::stream::FuturesOrdered;
37use fxfs_trace::trace;
38use std::cmp::min;
39use std::future::Future;
40use std::ops::{Deref, Range};
41use std::pin::Pin;
42use std::sync::Arc;
43use std::sync::atomic::{self, AtomicU64, Ordering};
44use storage_device::WriteFlags;
45use storage_device::buffer::{Buffer, BufferFuture, BufferRef, MutableBufferRef};
46use storage_ptr_slice::PtrByteSlice;
47use storage_units::BlockSize;
48use zerocopy::FromBytes;
49
50mod allocated_ranges;
51pub use allocated_ranges::{AllocatedRanges, RangeType};
52
53/// How much data each transaction will cover when writing an attribute across batches. Pulled from
54/// `FLUSH_BATCH_SIZE` in paged_object_handle.rs.
55pub const WRITE_ATTR_BATCH_SIZE: usize = 524_288;
56
57/// DataObjectHandle is a typed handle for file-like objects that store data in the default data
58/// attribute. In addition to traditional files, this means things like the journal, superblocks,
59/// and layer files.
60///
61/// It caches the content size of the data attribute it was configured for, and has helpers for
62/// complex extent manipulation, as well as implementations of ReadObjectHandle and
63/// WriteObjectHandle.
64pub struct DataObjectHandle<S: HandleOwner> {
65    handle: StoreObjectHandle<S>,
66    attribute_id: AttributeId,
67    content_size: AtomicU64,
68    state: Mutex<DataObjectState>,
69}
70
71/// Represents the mapping of a file's contents to the physical storage backing it.
72#[derive(Debug, Clone)]
73pub struct FileExtent {
74    logical_offset: u64,
75    device_range: Range<u64>,
76}
77
78impl FileExtent {
79    pub fn new(logical_offset: u64, device_range: Range<u64>) -> Result<Self, Error> {
80        // Ensure `device_range` is valid.
81        let length = device_range.length()?;
82        // Ensure no overflow when we calculate the end of the logical range.
83        let _ = logical_offset.checked_add(length).ok_or(FxfsError::OutOfRange)?;
84        Ok(Self { logical_offset, device_range })
85    }
86}
87
88impl FileExtent {
89    pub fn length(&self) -> u64 {
90        // SAFETY: We verified that the device_range's length is valid in Self::new.
91        unsafe { self.device_range.unchecked_length() }
92    }
93
94    pub fn logical_offset(&self) -> u64 {
95        self.logical_offset
96    }
97
98    pub fn logical_range(&self) -> Range<u64> {
99        // SAFETY: We verified logical_offset plus device_range length won't overflow in Self::new.
100        unsafe { self.logical_offset..self.logical_offset.unchecked_add(self.length()) }
101    }
102
103    pub fn device_range(&self) -> &Range<u64> {
104        &self.device_range
105    }
106}
107
108#[derive(Debug)]
109pub enum DataObjectState {
110    Standard(AllocatedRanges),
111    VerityStarted,
112    VerityPending(FsverityStateInner),
113    Verity(FsverityStateInner),
114}
115
116#[derive(Debug)]
117pub struct FsverityStateInner {
118    root_digest: RootDigest,
119    salt: Vec<u8>,
120    // TODO(b/309656632): This should store the entire merkle tree and not just the leaf nodes.
121    // Potentially store a pager-backed vmo instead of passing around a boxed array.
122    merkle_tree: Box<[u8]>,
123}
124
125#[derive(Debug, Default)]
126pub struct OverwriteOptions {
127    // If false, then all the extents for the overwrite range must have been preallocated using
128    // preallocate_range or from existing writes.
129    pub allow_allocations: bool,
130    pub barrier_on_first_write: bool,
131}
132
133impl FsverityStateInner {
134    pub fn new(root_digest: RootDigest, salt: Vec<u8>, merkle_tree: Box<[u8]>) -> Self {
135        FsverityStateInner { root_digest, salt, merkle_tree }
136    }
137
138    fn get_hasher_for_block_size(&self, block_size: BlockSize) -> FsVerityHasher {
139        match self.root_digest {
140            RootDigest::Sha256(_) => FsVerityHasher::Sha256(FsVerityHasherOptions::new(
141                self.salt.clone(),
142                block_size.get() as usize,
143            )),
144            RootDigest::Sha512(_) => FsVerityHasher::Sha512(FsVerityHasherOptions::new(
145                self.salt.clone(),
146                block_size.get() as usize,
147            )),
148        }
149    }
150
151    fn from_ptr_slice(
152        data: PtrByteSlice<'_>,
153        block_size: BlockSize,
154    ) -> Result<(Self, FsVerityHasher), Error> {
155        let descriptor = FsVerityDescriptor::new(data, block_size.get() as usize)
156            .map_err(|e| anyhow!(FxfsError::IntegrityError).context(e))?;
157
158        let root_digest = match descriptor.digest_algorithm() {
159            fio::HashAlgorithm::Sha256 => {
160                RootDigest::Sha256(descriptor.root_digest().try_into().unwrap())
161            }
162            fio::HashAlgorithm::Sha512 => RootDigest::Sha512(descriptor.root_digest().to_vec()),
163            _ => return Err(anyhow!(FxfsError::NotSupported).context("Unsupported hash algorithm")),
164        };
165        let hasher = descriptor.hasher();
166        let leaves =
167            descriptor.leaf_digests().map_err(|e| anyhow!(FxfsError::IntegrityError).context(e))?;
168
169        Ok((Self::new(root_digest, descriptor.salt().to_vec(), leaves.into_boxed_slice()), hasher))
170    }
171}
172
173impl<S: HandleOwner> Deref for DataObjectHandle<S> {
174    type Target = StoreObjectHandle<S>;
175    fn deref(&self) -> &Self::Target {
176        &self.handle
177    }
178}
179
180impl<S: HandleOwner> DataObjectHandle<S> {
181    pub fn new(
182        owner: Arc<S>,
183        object_id: u64,
184        permanent_keys: bool,
185        attribute_id: AttributeId,
186        size: u64,
187        options: HandleOptions,
188        trace: bool,
189        overwrite_ranges: &[Range<u64>],
190    ) -> Self {
191        Self {
192            handle: StoreObjectHandle::new(owner, object_id, permanent_keys, options, trace),
193            attribute_id,
194            content_size: AtomicU64::new(size),
195            state: Mutex::new(DataObjectState::Standard(AllocatedRanges::new(overwrite_ranges))),
196        }
197    }
198
199    pub fn attribute_id(&self) -> AttributeId {
200        self.attribute_id
201    }
202
203    /// Consumes the `DataObjectHandle` and returns the `StoreObjectHandle` that it contained.
204    pub fn into_store_object_handle(self) -> StoreObjectHandle<S> {
205        self.handle
206    }
207
208    pub fn overwrite_ranges_is_empty(&self) -> bool {
209        match &*self.state.lock() {
210            DataObjectState::Standard(ranges) => ranges.is_empty(),
211            _ => true,
212        }
213    }
214
215    pub fn with_overwrite_ranges<R>(&self, f: impl FnOnce(Option<&AllocatedRanges>) -> R) -> R {
216        let state = self.state.lock();
217        match &*state {
218            DataObjectState::Standard(ranges) => f(Some(ranges)),
219            _ => f(None),
220        }
221    }
222
223    pub fn with_overwrite_ranges_mut<R>(
224        &self,
225        f: impl FnOnce(Option<&mut AllocatedRanges>) -> R,
226    ) -> R {
227        let mut state = self.state.lock();
228        match &mut *state {
229            DataObjectState::Standard(ranges) => f(Some(ranges)),
230            _ => f(None),
231        }
232    }
233
234    pub fn is_verified_file(&self) -> bool {
235        matches!(*self.state.lock(), DataObjectState::Verity(_))
236    }
237
238    /// Sets `self.state` to DataObjectState::VerityStarted. Called at the top of `enable_verity`.
239    /// If another caller has already started but not completed `enable_verity`, returns
240    /// FxfsError::AlreadyBound. If another caller has already completed `enable_verity`, returns
241    /// FxfsError::AlreadyExists.
242    ///
243    /// Note: This is called before `enable_verity` acquires its object transaction lock. Any
244    /// ongoing transaction holding the object lock (such as `allocate`) will proceed to commit
245    /// its mutations to disk while `enable_verity` waits for the lock, and `will_apply_mutation`
246    /// will gracefully discard in-memory range updates for the discarded `AllocatedRanges`.
247    pub fn set_fsverity_state_started(&self) -> Result<(), Error> {
248        let mut state = self.state.lock();
249        match *state {
250            DataObjectState::Standard(_) => {
251                *state = DataObjectState::VerityStarted;
252                Ok(())
253            }
254            DataObjectState::VerityStarted | DataObjectState::VerityPending(_) => {
255                Err(anyhow!(FxfsError::Unavailable))
256            }
257            DataObjectState::Verity(_) => Err(anyhow!(FxfsError::AlreadyExists)),
258        }
259    }
260
261    /// Sets `self.state` to VerityPending. Must be called before `finalize_fsverity_state()`.
262    ///
263    /// # Panics
264    ///
265    /// Panics if the prior state was not `DataObjectState::VerityStarted`.
266    pub fn set_fsverity_state_pending(&self, descriptor: FsverityStateInner) {
267        let mut state = self.state.lock();
268        assert!(matches!(*state, DataObjectState::VerityStarted));
269        *state = DataObjectState::VerityPending(descriptor);
270    }
271
272    /// Sets `self.state` to Verity.
273    ///
274    /// # Panics
275    ///
276    /// Panics if the prior state was not `DataObjectState::VerityPending(_)`.
277    pub fn finalize_fsverity_state(&self) {
278        let mut state = self.state.lock();
279        let old_state =
280            std::mem::replace(&mut *state, DataObjectState::Standard(AllocatedRanges::empty()));
281        match old_state {
282            DataObjectState::VerityPending(inner) => *state = DataObjectState::Verity(inner),
283            _ => panic!("Cannot finalize verity state from {old_state:?}"),
284        }
285    }
286
287    /// Sets `self.state` directly to Verity without going through the entire state machine.
288    /// Used to set `self.state` on open of a verified file. The merkle tree data is
289    /// verified against the root digest here, and will return an error if the tree is not correct.
290    ///
291    /// # Panics
292    ///
293    /// Panics if the prior state was not `DataObjectState::Standard(_)`.
294    pub async fn set_fsverity_state_some(&self, descriptor: FsverityMetadata) -> Result<(), Error> {
295        let (metadata, hasher) = match descriptor {
296            FsverityMetadata::Internal(root_digest, salt) => {
297                let merkle_tree = self
298                    .read_attr(AttributeId::FSVERITY_MERKLE)
299                    .await?
300                    .ok_or_else(|| anyhow!(FxfsError::Inconsistent))?;
301                let metadata = FsverityStateInner { root_digest, salt, merkle_tree };
302                let hasher = metadata.get_hasher_for_block_size(self.block_size());
303                (metadata, hasher)
304            }
305            FsverityMetadata::F2fs(verity_range) => {
306                let expected_length = verity_range.length()? as usize;
307                let mut buffer = self
308                    .allocate_buffer(
309                        self.block_size().align_up(expected_length as u64).unwrap() as usize
310                    )
311                    .await;
312                let read = self
313                    .handle
314                    .read_aligned(AttributeId::FSVERITY_MERKLE, verity_range.start, buffer.as_mut())
315                    .await?;
316                ensure!(expected_length == read, FxfsError::Inconsistent);
317                let data = buffer.as_ptr_slice().subslice(0..expected_length);
318                FsverityStateInner::from_ptr_slice(data, self.block_size())?
319            }
320        };
321        // Validate the merkle tree data against the root before applying it.
322        ensure!(metadata.merkle_tree.len() % hasher.hash_size() == 0, FxfsError::Inconsistent);
323        let leaf_chunks = metadata.merkle_tree.chunks_exact(hasher.hash_size());
324
325        let root_hash = match &metadata.root_digest {
326            RootDigest::Sha256(root_hash) => root_hash.as_slice(),
327            RootDigest::Sha512(root_hash) => root_hash.as_slice(),
328        };
329
330        let tree = match hasher {
331            FsVerityHasher::Sha256(_) => {
332                let mut builder = MerkleTreeBuilder::<Sha256Hash>::new(hasher);
333                for leaf in leaf_chunks {
334                    let hash = Sha256Hash::read_from_bytes(leaf).unwrap();
335                    builder.push_data_hash(hash);
336                }
337                builder.finish()
338            }
339            FsVerityHasher::Sha512(_) => {
340                let mut builder = MerkleTreeBuilder::<Sha512Hash>::new(hasher);
341                for leaf in leaf_chunks {
342                    let hash = Sha512Hash::read_from_bytes(leaf).unwrap();
343                    builder.push_data_hash(hash);
344                }
345                builder.finish()
346            }
347        };
348
349        ensure!(root_hash == tree.root(), FxfsError::IntegrityError);
350
351        let mut state = self.state.lock();
352        assert!(matches!(*state, DataObjectState::Standard(_)));
353        *state = DataObjectState::Verity(metadata);
354
355        Ok(())
356    }
357
358    /// Verifies contents of `buffer` against the corresponding hashes in the stored merkle tree.
359    /// `offset` is the logical offset in the file that `buffer` starts at. Fails on non
360    /// fsverity-enabled files.
361    ///
362    /// # Panics
363    ///
364    /// Panics if `offset` is not block-aligned.
365    fn verify_data(&self, mut offset: usize, buffer: PtrByteSlice<'_>) -> Result<(), Error> {
366        let block_size = self.block_size();
367        assert!(block_size.is_aligned(offset as u64));
368        let state = self.state.lock();
369        match &*state {
370            DataObjectState::Standard(_) => {
371                Err(anyhow!("Tried to verify read on a non verity-enabled file"))
372            }
373            DataObjectState::VerityStarted | DataObjectState::VerityPending(_) => {
374                Err(anyhow!("Enable verity has not yet completed, state: {state:?}"))
375            }
376            DataObjectState::Verity(metadata) => {
377                let hasher = metadata.get_hasher_for_block_size(block_size);
378                let leaf_nodes: Vec<&[u8]> =
379                    metadata.merkle_tree.chunks(hasher.hash_size()).collect();
380                fxfs_trace::duration!("fsverity-verify", "len" => buffer.len());
381                // TODO(b/318880297): Consider parallelizing computation.
382                for chunk in buffer.chunks(block_size.get() as usize) {
383                    // SAFETY: Ideally we wouldn't be creating references here as technically this is
384                    // Rust undefined behaviour, but it's difficult for us to fix and mitigated
385                    // because these pointers end up being passed directly to non-Rust code (Mundane).
386                    let b = unsafe { &*chunk.as_raw_slice_ptr() };
387
388                    ensure!(
389                        hasher.hash_block(b) == leaf_nodes[((offset as u64) / block_size) as usize],
390                        anyhow!(FxfsError::Inconsistent).context("Hash mismatch")
391                    );
392                    offset += block_size.get() as usize;
393                }
394                Ok(())
395            }
396        }
397    }
398
399    /// Extend the file with the given extent.  The only use case for this right now is for files
400    /// that must exist at certain offsets on the device, such as super-blocks.
401    pub async fn extend<'a>(
402        &'a self,
403        transaction: &mut Transaction<'a>,
404        device_range: Range<u64>,
405    ) -> Result<(), Error> {
406        let old_end =
407            self.block_size().align_up(self.txn_get_size(transaction)).ok_or(FxfsError::TooBig)?;
408        let new_size = old_end + device_range.end - device_range.start;
409        self.store().allocator().mark_allocated(
410            transaction,
411            self.store().store_object_id(),
412            device_range.clone(),
413        )?;
414        self.txn_update_size(transaction, new_size, None).await?;
415        let key_id = self.get_key(None).await?.0;
416        transaction.add(
417            self.store().store_object_id,
418            Mutation::merge_object(
419                ObjectKey::extent(self.object_id(), self.attribute_id(), old_end..new_size),
420                ObjectValue::Extent(ExtentValue::new_raw(device_range.start, key_id)),
421            ),
422        );
423        self.update_allocated_size(transaction, device_range.end - device_range.start, 0).await
424    }
425
426    // Returns a new aligned buffer (reading the head and tail blocks if necessary) with a copy of
427    // the data from `buf`.
428    async fn align_buffer(
429        &self,
430        offset: u64,
431        buf: BufferRef<'_>,
432    ) -> Result<(std::ops::Range<u64>, Buffer<'_>), Error> {
433        self.handle.align_buffer(self.attribute_id(), offset, buf).await
434    }
435
436    // Writes potentially unaligned data at `device_offset` and returns checksums if requested. The
437    // data will be encrypted if necessary.
438    // `buf` is mutable as an optimization, since the write may require encryption, we can encrypt
439    // the buffer in-place rather than copying to another buffer if the write is already aligned.
440    // `flags` are forwarded to the underlying device write.
441    async fn write_at(
442        &self,
443        offset: u64,
444        buf: MutableBufferRef<'_>,
445        device_offset: u64,
446        flags: WriteFlags,
447    ) -> Result<MaybeChecksums, Error> {
448        self.handle
449            .write_at_with_flags(self.attribute_id(), offset, buf, None, device_offset, flags)
450            .await
451    }
452
453    /// Verifies that the entire range in the file is zeroes, as either uninitialized overwrite
454    /// range, or no extent at all. If a single allocated and written extent is found, this returns
455    /// false.
456    pub async fn check_unwritten_zero(&self, range: Range<u64>) -> Result<bool, Error> {
457        if range.is_empty() {
458            return Ok(true);
459        }
460        let tree = &self.store().tree();
461        let layer_set = tree.layer_set();
462        let key = Extent(range);
463        let query_key = ObjectKey::attribute(
464            self.object_id(),
465            self.attribute_id,
466            AttributeKey::Extent(key.clone()),
467        );
468        let mut merger = layer_set.merger();
469        let mut iter = merger.query(Query::LimitedRange(&query_key)).await?;
470        while let Some(ItemRef {
471            key:
472                ObjectKey {
473                    object_id,
474                    data: ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent_key)),
475                },
476            value: ObjectValue::Extent(value),
477            ..
478        }) = iter.get()
479            && *object_id == self.object_id()
480            && *attr_id == self.attribute_id
481        {
482            let Some(overlap) = key.overlap(extent_key) else {
483                break;
484            };
485            if let ExtentValue::Some { mode, .. } = value {
486                if let ExtentMode::OverwritePartial(bits) = mode {
487                    let starting_index = (overlap.start - extent_key.start) / self.block_size();
488                    for initialized in bits
489                        .iter()
490                        .skip(starting_index as usize)
491                        .take((overlap.length().unwrap() / self.block_size()) as usize)
492                    {
493                        if initialized {
494                            return Ok(false);
495                        }
496                    }
497                } else {
498                    return Ok(false);
499                }
500            }
501            iter.advance().await?;
502        }
503        Ok(true)
504    }
505
506    /// Zeroes the given range.  The range must be aligned.  Returns the amount of data deallocated.
507    pub async fn zero(
508        &self,
509        transaction: &mut Transaction<'_>,
510        range: Range<u64>,
511    ) -> Result<(), Error> {
512        self.handle.zero(transaction, self.attribute_id(), range).await
513    }
514
515    /// The cached value for `self.fsverity_state` is set either in `open_object` or on
516    /// `enable_verity`. If set, translates `self.fsverity_state.descriptor` into an
517    /// fio::VerificationOptions instance and a root hash. Otherwise, returns None.
518    pub fn get_descriptor(&self) -> Option<(fio::VerificationOptions, Vec<u8>)> {
519        let state = self.state.lock();
520        match &*state {
521            DataObjectState::Verity(metadata) => {
522                let (options, root_hash) = match &metadata.root_digest {
523                    RootDigest::Sha256(root_hash) => (
524                        fio::VerificationOptions {
525                            hash_algorithm: Some(fio::HashAlgorithm::Sha256),
526                            salt: Some(metadata.salt.clone()),
527                            ..Default::default()
528                        },
529                        root_hash.to_vec(),
530                    ),
531                    RootDigest::Sha512(root_hash) => (
532                        fio::VerificationOptions {
533                            hash_algorithm: Some(fio::HashAlgorithm::Sha512),
534                            salt: Some(metadata.salt.clone()),
535                            ..Default::default()
536                        },
537                        root_hash.clone(),
538                    ),
539                };
540                Some((options, root_hash))
541            }
542            _ => None,
543        }
544    }
545
546    async fn build_verity_tree(
547        &self,
548        hasher: FsVerityHasher,
549        hash_alg: fio::HashAlgorithm,
550        salt: &[u8],
551    ) -> Result<(MerkleTree, Vec<u8>), Error> {
552        match hasher {
553            FsVerityHasher::Sha256(_) => {
554                self.build_verity_tree_impl::<Sha256Hash>(hasher, hash_alg, salt).await
555            }
556            FsVerityHasher::Sha512(_) => {
557                self.build_verity_tree_impl::<Sha512Hash>(hasher, hash_alg, salt).await
558            }
559        }
560    }
561
562    async fn build_verity_tree_impl<D: FsVerityHash>(
563        &self,
564        hasher: FsVerityHasher,
565        hash_alg: fio::HashAlgorithm,
566        salt: &[u8],
567    ) -> Result<(MerkleTree, Vec<u8>), Error> {
568        let hash_len = hasher.hash_size();
569        let mut builder = MerkleTreeBuilder::<D>::new(hasher);
570        let mut offset = 0;
571        let size = self.get_size();
572        // TODO(b/314836822): Consider further tuning the buffer size to optimize
573        // performance. Experimentally, most verity-enabled files are <256K.
574        let mut buf = self.allocate_buffer(64 * self.block_size().get() as usize).await;
575        while offset < size {
576            // TODO(b/314842875): Consider optimizations for sparse files.
577            let read = self.read_aligned(offset, buf.as_mut()).await? as u64;
578            assert!(offset + read <= size);
579            let slice = buf.as_ptr_slice().subslice(0..read as usize);
580
581            // SAFETY: Ideally we wouldn't be creating references here as technically this is
582            // Rust undefined behaviour, but it's difficult for us to fix and mitigated
583            // because these pointers end up being passed directly to non-Rust code (Mundane).
584            let chunk = unsafe { &*slice.as_raw_slice_ptr() };
585
586            builder.write(chunk);
587            offset += read;
588        }
589        let tree = builder.finish();
590        // This will include a block for the root layer, which will be used to house the descriptor.
591        let tree_data_len = tree
592            .levels()
593            .iter()
594            .map(|layer| self.block_size().align_up(layer.len() as u64).unwrap() as usize)
595            .sum();
596        let mut merkle_tree_data = Vec::<u8>::with_capacity(tree_data_len);
597        // Iterating from the top layers down to the leaves.
598        for layer in tree.levels().iter().rev() {
599            // Skip the root layer.
600            if layer.len() <= hash_len {
601                continue;
602            }
603            merkle_tree_data.extend_from_slice(layer);
604            // Pad to the end of the block.
605            let padded_size =
606                self.block_size().align_up(merkle_tree_data.len() as u64).unwrap() as usize;
607            merkle_tree_data.resize(padded_size, 0);
608        }
609
610        // Zero the last block, then write the descriptor to the start of it.
611        let descriptor_offset = merkle_tree_data.len();
612        merkle_tree_data.resize(descriptor_offset + self.block_size().get() as usize, 0);
613        let descriptor = FsVerityDescriptorRaw::new(
614            hash_alg,
615            self.block_size().get(),
616            self.get_size(),
617            tree.root(),
618            salt,
619        )?;
620        descriptor.write_to_slice(&mut merkle_tree_data[descriptor_offset..])?;
621
622        Ok((tree, merkle_tree_data))
623    }
624
625    /// Reads the data attribute and computes a merkle tree from the data. The values of the
626    /// parameters required to build the merkle tree are supplied by `descriptor` (i.e. salt,
627    /// hash_algorithm, etc.) Writes the leaf nodes of the merkle tree to an attribute with id
628    /// `AttributeId::FSVERITY_MERKLE`. Updates the root_hash of the `descriptor` according to the
629    /// computed merkle tree and then replaces the ObjectValue of the data attribute with
630    /// ObjectValue::VerifiedAttribute, which stores the `descriptor` inline.
631    #[trace]
632    pub async fn enable_verity(&self, options: fio::VerificationOptions) -> Result<(), Error> {
633        self.set_fsverity_state_started()?;
634        // If the merkle attribute was tombstoned in the last attempt of `enable_verity`, flushing
635        // the graveyard should process the tombstone before we start rewriting the attribute.
636        if self
637            .store()
638            .tree()
639            .exists(&ObjectKey::graveyard_attribute_entry(
640                self.store().graveyard_directory_object_id(),
641                self.object_id(),
642                AttributeId::FSVERITY_MERKLE,
643            ))
644            .await?
645        {
646            self.store().filesystem().ensure_local().graveyard().flush().await;
647        }
648        let mut transaction = self.new_transaction().await?;
649        let hash_alg =
650            options.hash_algorithm.ok_or_else(|| anyhow!("No hash algorithm provided"))?;
651        let salt = options.salt.ok_or_else(|| anyhow!("No salt provided"))?;
652        let (root_digest, merkle_tree) = match hash_alg {
653            fio::HashAlgorithm::Sha256 => {
654                let hasher = FsVerityHasher::Sha256(FsVerityHasherOptions::new(
655                    salt.clone(),
656                    self.block_size().get() as usize,
657                ));
658                let (tree, merkle_tree_data) =
659                    self.build_verity_tree(hasher, hash_alg, &salt).await?;
660                let root: [u8; 32] = tree.root().try_into().unwrap();
661                (RootDigest::Sha256(root), merkle_tree_data)
662            }
663            fio::HashAlgorithm::Sha512 => {
664                let hasher = FsVerityHasher::Sha512(FsVerityHasherOptions::new(
665                    salt.clone(),
666                    self.block_size().get() as usize,
667                ));
668                let (tree, merkle_tree_data) =
669                    self.build_verity_tree(hasher, hash_alg, &salt).await?;
670                (RootDigest::Sha512(tree.root().to_vec()), merkle_tree_data)
671            }
672            _ => {
673                bail!(
674                    anyhow!(FxfsError::NotSupported)
675                        .context(format!("hash algorithm not supported"))
676                );
677            }
678        };
679        // TODO(b/314194485): Eventually want streaming writes.
680        // The merkle tree attribute should not require trimming because it should not
681        // exist.
682        self.handle
683            .write_new_attr(&mut transaction, AttributeId::FSVERITY_MERKLE, &merkle_tree)
684            .await?;
685        let descriptor_decoded =
686            FsVerityDescriptor::new(&merkle_tree[..], self.block_size().get() as usize)?;
687        let descriptor = FsverityStateInner {
688            root_digest,
689            salt,
690            merkle_tree: descriptor_decoded.leaf_digests()?.into(),
691        };
692        self.set_fsverity_state_pending(descriptor);
693        transaction.add_with_object(
694            self.store().store_object_id(),
695            Mutation::replace_or_insert_object(
696                ObjectKey::attribute(self.object_id(), AttributeId::DATA, AttributeKey::Attribute),
697                ObjectValue::verified_attribute(
698                    self.get_size(),
699                    FsverityMetadata::F2fs(0..merkle_tree.len() as u64),
700                ),
701            ),
702            AssocObj::Borrowed(self),
703        );
704        transaction.commit().await?;
705        Ok(())
706    }
707
708    /// Pre-allocate disk space for the given logical file range. If any part of the allocation
709    /// range is beyond the end of the file, the file size is updated.
710    pub async fn allocate(&self, range: Range<u64>) -> Result<(), Error> {
711        debug_assert!(range.start < range.end);
712
713        // It's not required that callers of allocate use block aligned ranges, but we need to make
714        // the extents block aligned. Luckily, fallocate in posix is allowed to allocate more than
715        // what was asked for for block alignment purposes. We just need to make sure that the size
716        // NB: FxfsError::TooBig turns into EFBIG when passed through starnix, which is the
717        // required error code when the requested range is larger than the file size.
718        let mut new_range =
719            self.block_size().align_range_outwards(&range).ok_or(FxfsError::TooBig)?;
720
721        let mut transaction = self.new_transaction().await?;
722        // It's safe to check state after acquiring the transaction lock. Note that `enable_verity`
723        // calls `set_fsverity_state_started` before creating its own transaction, which could
724        // transition `self.state` to `VerityStarted` concurrently while this transaction is held.
725        // If that happens, `enable_verity`'s subsequent `new_transaction` call will block until
726        // this allocation transaction finishes, and `will_apply_mutation` will gracefully discard
727        // updates to the in-memory allocated ranges.
728        {
729            let state = self.state.lock();
730            match &*state {
731                DataObjectState::Standard(_) => {}
732                _ => bail!(
733                    anyhow!(FxfsError::AccessDenied).context("Cannot allocate on verity file")
734                ),
735            }
736        }
737        let mut to_allocate = Vec::new();
738        let mut to_switch = Vec::new();
739        let key_id = self.get_key(None).await?.0;
740
741        {
742            let tree = &self.store().tree;
743            let layer_set = tree.layer_set();
744            let offset_key =
745                ObjectKey::extent(self.object_id(), self.attribute_id(), new_range.clone());
746            let mut merger = layer_set.merger();
747            let mut iter = merger.query(Query::LimitedRange(&offset_key)).await?;
748
749            loop {
750                match iter.get() {
751                    Some(ItemRef {
752                        key:
753                            ObjectKey {
754                                object_id,
755                                data:
756                                    ObjectKeyData::Attribute(
757                                        attribute_id,
758                                        AttributeKey::Extent(extent_key),
759                                    ),
760                            },
761                        value: ObjectValue::Extent(extent_value),
762                        ..
763                    }) if *object_id == self.object_id()
764                        && *attribute_id == self.attribute_id() =>
765                    {
766                        // If the start of this extent is beyond the end of the range we are
767                        // allocating, we don't have any more work to do.
768                        if new_range.end <= extent_key.start {
769                            break;
770                        }
771                        // Add any prefix we might need to allocate.
772                        if new_range.start < extent_key.start {
773                            to_allocate.push(new_range.start..extent_key.start);
774                            new_range.start = extent_key.start;
775                        }
776                        let device_offset = match extent_value {
777                            ExtentValue::None => {
778                                // If the extent value is None, it indicates a deleted extent. In
779                                // that case, we just skip it entirely. By keeping the new_range
780                                // where it is, this section will get included in the new
781                                // allocations.
782                                iter.advance().await?;
783                                continue;
784                            }
785                            ExtentValue::Some { mode: ExtentMode::OverwritePartial(_), .. }
786                            | ExtentValue::Some { mode: ExtentMode::Overwrite, .. } => {
787                                // If this extent is already in overwrite mode, we can skip it.
788                                if extent_key.end < new_range.end {
789                                    new_range.start = extent_key.end;
790                                    iter.advance().await?;
791                                    continue;
792                                } else {
793                                    new_range.start = new_range.end;
794                                    break;
795                                }
796                            }
797                            ExtentValue::Some { device_offset, .. } => *device_offset,
798                        };
799
800                        // Figure out how we have to break up the ranges.
801                        let device_offset = device_offset + (new_range.start - extent_key.start);
802                        if extent_key.end < new_range.end {
803                            to_switch.push((new_range.start..extent_key.end, device_offset));
804                            new_range.start = extent_key.end;
805                        } else {
806                            to_switch.push((new_range.start..new_range.end, device_offset));
807                            new_range.start = new_range.end;
808                            break;
809                        }
810                    }
811                    // The records are sorted so if we find something that isn't an extent or
812                    // doesn't match the object id then there are no more extent records for this
813                    // object.
814                    _ => break,
815                }
816                iter.advance().await?;
817            }
818        }
819
820        if new_range.start < new_range.end {
821            to_allocate.push(new_range.clone());
822        }
823
824        // We can update the size in the first transaction because even if subsequent transactions
825        // don't get replayed, the data between the current and new end of the file will be zero
826        // (either sparse zero or allocated zero). On the other hand, if we don't update the size
827        // in the first transaction, overwrite extents may be written past the end of the file
828        // which is an fsck error.
829        //
830        // The potential new size needs to be the non-block-aligned range end - we round up to the
831        // nearest block size for the actual allocation, but shouldn't do that for the file size.
832        let new_size = std::cmp::max(range.end, self.get_size());
833        // Make sure the mutation that flips the has_overwrite_extents advisory flag is in the
834        // first transaction, in case we split transactions. This makes it okay to only replay the
835        // first transaction if power loss occurs - the file will be in an unusual state, but not
836        // an invalid one, if only part of the allocate goes through.
837        transaction.add_with_object(
838            self.store().store_object_id(),
839            Mutation::replace_or_insert_object(
840                ObjectKey::attribute(
841                    self.object_id(),
842                    self.attribute_id(),
843                    AttributeKey::Attribute,
844                ),
845                ObjectValue::Attribute { size: new_size, has_overwrite_extents: true },
846            ),
847            AssocObj::Borrowed(self),
848        );
849
850        // The maximum number of mutations we are going to allow per transaction in allocate. This
851        // is probably quite a bit lower than the actual limit, but it should be large enough to
852        // handle most non-edge-case versions of allocate without splitting the transaction.
853        const MAX_TRANSACTION_SIZE: usize = 256;
854        for (switch_range, device_offset) in to_switch {
855            transaction.add_with_object(
856                self.store().store_object_id(),
857                Mutation::merge_object(
858                    ObjectKey::extent(self.object_id(), self.attribute_id(), switch_range),
859                    ObjectValue::Extent(ExtentValue::initialized_overwrite_extent(
860                        device_offset,
861                        key_id,
862                    )),
863                ),
864                AssocObj::Borrowed(self),
865            );
866            if transaction.mutations().len() >= MAX_TRANSACTION_SIZE {
867                transaction.commit_and_continue().await?;
868            }
869        }
870
871        let mut allocated = 0;
872        let allocator = self.store().allocator();
873        for mut allocate_range in to_allocate {
874            while allocate_range.start < allocate_range.end {
875                let device_range = allocator
876                    .allocate(
877                        &mut transaction,
878                        self.store().store_object_id(),
879                        allocate_range.end - allocate_range.start,
880                    )
881                    .await
882                    .context("allocation failed")?;
883                let device_range_len = device_range.end - device_range.start;
884
885                transaction.add_with_object(
886                    self.store().store_object_id(),
887                    Mutation::merge_object(
888                        ObjectKey::extent(
889                            self.object_id(),
890                            self.attribute_id(),
891                            allocate_range.start..allocate_range.start + device_range_len,
892                        ),
893                        ObjectValue::Extent(ExtentValue::blank_overwrite_extent(
894                            device_range.start,
895                            (device_range_len / self.block_size()) as usize,
896                            key_id,
897                        )),
898                    ),
899                    AssocObj::Borrowed(self),
900                );
901
902                allocate_range.start += device_range_len;
903                allocated += device_range_len;
904
905                if transaction.mutations().len() >= MAX_TRANSACTION_SIZE {
906                    self.update_allocated_size(&mut transaction, allocated, 0).await?;
907                    transaction.commit_and_continue().await?;
908                    allocated = 0;
909                }
910            }
911        }
912
913        self.update_allocated_size(&mut transaction, allocated, 0).await?;
914        transaction.commit().await?;
915
916        Ok(())
917    }
918
919    /// Return information on a contiguous set of extents that has the same allocation status,
920    /// starting from `start_offset`. The information returned is if this set of extents are marked
921    /// allocated/not allocated and also the size of this set (in bytes). This is used when
922    /// querying slices for volumes.
923    /// This function expects `start_offset` to be aligned to block size
924    pub async fn is_allocated(&self, start_offset: u64) -> Result<(bool, u64), Error> {
925        let block_size = self.block_size();
926        assert_eq!(start_offset % block_size, 0);
927
928        if start_offset > self.get_size() {
929            bail!(FxfsError::OutOfRange)
930        }
931
932        if start_offset == self.get_size() {
933            return Ok((false, 0));
934        }
935
936        let tree = &self.store().tree;
937        let layer_set = tree.layer_set();
938        let offset_key = ObjectKey::attribute(
939            self.object_id(),
940            self.attribute_id(),
941            AttributeKey::Extent(Extent::search_key_from_offset(start_offset)),
942        );
943        let mut merger = layer_set.merger();
944        let mut iter = merger.query(Query::FullRange(&offset_key)).await?;
945
946        let mut allocated = None;
947        let mut end = start_offset;
948
949        loop {
950            // Iterate through the extents, each time setting `end` as the end of the previous
951            // extent
952            match iter.get() {
953                Some(ItemRef {
954                    key:
955                        ObjectKey {
956                            object_id,
957                            data:
958                                ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent_key)),
959                        },
960                    value: ObjectValue::Extent(extent_value),
961                    ..
962                }) => {
963                    // Equivalent of getting no extents back
964                    if *object_id != self.object_id() || *attribute_id != self.attribute_id() {
965                        if allocated == Some(false) || allocated.is_none() {
966                            end = self.get_size();
967                            allocated = Some(false);
968                        }
969                        break;
970                    }
971                    ensure!(block_size.is_aligned(extent_key), FxfsError::Inconsistent);
972                    if extent_key.start > end {
973                        // If a previous extent has already been visited and we are tracking an
974                        // allocated set, we are only interested in an extent where the range of the
975                        // current extent follows immediately after the previous one.
976                        if allocated == Some(true) {
977                            break;
978                        } else {
979                            // The gap between the previous `end` and this extent is not allocated
980                            end = extent_key.start;
981                            allocated = Some(false);
982                            // Continue this iteration, except now the `end` is set to the end of
983                            // the "previous" extent which is this gap between the start_offset
984                            // and the current extent
985                        }
986                    }
987
988                    // We can assume that from here, the `end` points to the end of a previous
989                    // extent.
990                    match extent_value {
991                        // The current extent has been allocated
992                        ExtentValue::Some { .. } => {
993                            // Stop searching if previous extent was marked deleted
994                            if allocated == Some(false) {
995                                break;
996                            }
997                            allocated = Some(true);
998                        }
999                        // This extent has been marked deleted
1000                        ExtentValue::None => {
1001                            // Stop searching if previous extent was marked allocated
1002                            if allocated == Some(true) {
1003                                break;
1004                            }
1005                            allocated = Some(false);
1006                        }
1007                    }
1008                    end = extent_key.end;
1009                }
1010                // This occurs when there are no extents left
1011                None => {
1012                    if allocated == Some(false) || allocated.is_none() {
1013                        end = self.get_size();
1014                        allocated = Some(false);
1015                    }
1016                    // Otherwise, we were monitoring extents that were allocated, so just exit.
1017                    break;
1018                }
1019                // Non-extent records (Object, Child, GraveyardEntry) are ignored.
1020                Some(_) => {}
1021            }
1022            iter.advance().await?;
1023        }
1024
1025        Ok((allocated.unwrap(), end - start_offset))
1026    }
1027
1028    pub async fn txn_write<'a>(
1029        &'a self,
1030        transaction: &mut Transaction<'a>,
1031        offset: u64,
1032        buf: BufferRef<'_>,
1033    ) -> Result<(), Error> {
1034        if buf.is_empty() {
1035            return Ok(());
1036        }
1037        let (aligned, mut transfer_buf) = self.align_buffer(offset, buf).await?;
1038        self.multi_write(
1039            transaction,
1040            self.attribute_id(),
1041            std::slice::from_ref(&aligned),
1042            transfer_buf.as_mut(),
1043        )
1044        .await?;
1045        if offset + buf.len() as u64 > self.txn_get_size(transaction) {
1046            self.txn_update_size(transaction, offset + buf.len() as u64, None).await?;
1047        }
1048        Ok(())
1049    }
1050
1051    // Writes to multiple ranges with data provided in `buf`.  The buffer can be modified in place
1052    // if encryption takes place.  The ranges must all be aligned and no change to content size is
1053    // applied; the caller is responsible for updating size if required.
1054    pub async fn multi_write<'a>(
1055        &'a self,
1056        transaction: &mut Transaction<'a>,
1057        attribute_id: AttributeId,
1058        ranges: &[Range<u64>],
1059        buf: MutableBufferRef<'_>,
1060    ) -> Result<(), Error> {
1061        self.handle.multi_write(transaction, attribute_id, None, ranges, buf).await
1062    }
1063
1064    // `buf` is mutable as an optimization, since the write may require encryption, we can
1065    // encrypt the buffer in-place rather than copying to another buffer if the write is
1066    // already aligned.
1067    //
1068    // Note: in the event of power failure during an overwrite() call, it is possible that
1069    // old data (which hasn't been overwritten with new bytes yet) may be exposed to the user.
1070    // Since the old data should be encrypted, it is probably safe to expose, although not ideal.
1071    pub async fn overwrite(
1072        &self,
1073        mut offset: u64,
1074        mut buf: MutableBufferRef<'_>,
1075        options: OverwriteOptions,
1076    ) -> Result<(), Error> {
1077        if buf.is_empty() {
1078            return Ok(());
1079        }
1080        ensure!((buf.len() as u32) % self.store().device.block_size() == 0, FxfsError::InvalidArgs);
1081        let end = offset + buf.len() as u64;
1082
1083        let key_id = self.get_key(None).await?.0;
1084
1085        // The transaction only ends up being used if allow_allocations is true
1086        let mut transaction =
1087            if options.allow_allocations { Some(self.new_transaction().await?) } else { None };
1088
1089        // We build up a list of writes to perform later
1090        let mut writes = FuturesOrdered::new();
1091        let mut first_write = options.barrier_on_first_write;
1092
1093        // We create a new scope here, so that the merger iterator will get dropped before we try to
1094        // commit our transaction. Otherwise the transaction commit would block.
1095        {
1096            let store = self.store();
1097            let store_object_id = store.store_object_id;
1098            let allocator = store.allocator();
1099            let tree = &store.tree;
1100            let layer_set = tree.layer_set();
1101            let mut merger = layer_set.merger();
1102            let mut iter = merger
1103                .query(Query::LimitedRange(&ObjectKey::extent(
1104                    self.object_id(),
1105                    self.attribute_id(),
1106                    offset..end,
1107                )))
1108                .await?;
1109            let block_size = self.block_size();
1110
1111            loop {
1112                let (device_offset, bytes_to_write, should_advance) = match iter.get() {
1113                    Some(ItemRef {
1114                        key:
1115                            ObjectKey {
1116                                object_id,
1117                                data:
1118                                    ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
1119                            },
1120                        value: ObjectValue::Extent(ExtentValue::Some { .. }),
1121                        ..
1122                    }) if *object_id == self.object_id()
1123                        && *attribute_id == self.attribute_id()
1124                        && extent.end == offset =>
1125                    {
1126                        iter.advance().await?;
1127                        continue;
1128                    }
1129                    Some(ItemRef {
1130                        key:
1131                            ObjectKey {
1132                                object_id,
1133                                data:
1134                                    ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
1135                            },
1136                        value,
1137                        ..
1138                    }) if *object_id == self.object_id()
1139                        && *attribute_id == self.attribute_id()
1140                        && extent.start <= offset =>
1141                    {
1142                        match value {
1143                            ObjectValue::Extent(ExtentValue::Some {
1144                                device_offset,
1145                                mode: ExtentMode::Raw,
1146                                ..
1147                            }) => {
1148                                ensure!(
1149                                    block_size.is_aligned(extent)
1150                                        && block_size.is_aligned(device_offset),
1151                                    FxfsError::Inconsistent
1152                                );
1153                                let offset_within_extent = offset - extent.start;
1154                                let remaining_length_of_extent = (extent
1155                                    .end
1156                                    .checked_sub(offset)
1157                                    .ok_or(FxfsError::Inconsistent)?)
1158                                    as usize;
1159                                // Yields (device_offset, bytes_to_write, should_advance)
1160                                (
1161                                    device_offset + offset_within_extent,
1162                                    min(buf.len(), remaining_length_of_extent),
1163                                    true,
1164                                )
1165                            }
1166                            ObjectValue::Extent(ExtentValue::Some { .. }) => {
1167                                // TODO(https://fxbug.dev/42066056): Maybe we should create
1168                                // a new extent without checksums?
1169                                bail!(
1170                                    "extent from ({},{}) which overlaps offset \
1171                                        {} has the wrong extent mode",
1172                                    extent.start,
1173                                    extent.end,
1174                                    offset
1175                                )
1176                            }
1177                            _ => {
1178                                bail!(
1179                                    "overwrite failed: extent overlapping offset {} has \
1180                                      unexpected ObjectValue",
1181                                    offset
1182                                )
1183                            }
1184                        }
1185                    }
1186                    maybe_item_ref => {
1187                        if let Some(transaction) = transaction.as_mut() {
1188                            assert_eq!(options.allow_allocations, true);
1189                            assert_eq!(offset % self.block_size(), 0);
1190
1191                            // We are going to make a new extent, but let's check if there is an
1192                            // extent after us. If there is an extent after us, then we don't want
1193                            // our new extent to bump into it...
1194                            let mut bytes_to_allocate = self
1195                                .block_size()
1196                                .align_up(buf.len() as u64)
1197                                .ok_or(FxfsError::TooBig)?;
1198                            if let Some(ItemRef {
1199                                key:
1200                                    ObjectKey {
1201                                        object_id,
1202                                        data:
1203                                            ObjectKeyData::Attribute(
1204                                                attribute_id,
1205                                                AttributeKey::Extent(extent),
1206                                            ),
1207                                    },
1208                                ..
1209                            }) = maybe_item_ref
1210                            {
1211                                if *object_id == self.object_id()
1212                                    && *attribute_id == self.attribute_id()
1213                                    && offset < extent.start
1214                                {
1215                                    let bytes_until_next_extent = extent.start - offset;
1216                                    bytes_to_allocate =
1217                                        min(bytes_to_allocate, bytes_until_next_extent);
1218                                }
1219                            }
1220
1221                            let device_range = allocator
1222                                .allocate(transaction, store_object_id, bytes_to_allocate)
1223                                .await?;
1224                            let device_range_len = device_range.end - device_range.start;
1225                            transaction.add(
1226                                store_object_id,
1227                                Mutation::insert_object(
1228                                    ObjectKey::extent(
1229                                        self.object_id(),
1230                                        self.attribute_id(),
1231                                        offset..offset + device_range_len,
1232                                    ),
1233                                    ObjectValue::Extent(ExtentValue::new_raw(
1234                                        device_range.start,
1235                                        key_id,
1236                                    )),
1237                                ),
1238                            );
1239
1240                            self.update_allocated_size(transaction, device_range_len, 0).await?;
1241
1242                            // Yields (device_offset, bytes_to_write, should_advance)
1243                            (device_range.start, min(buf.len(), device_range_len as usize), false)
1244                        } else {
1245                            bail!(
1246                                "no extent overlapping offset {}, \
1247                                and new allocations are not allowed",
1248                                offset
1249                            )
1250                        }
1251                    }
1252                };
1253                let (current_buf, remaining_buf) = buf.split_at_mut(bytes_to_write);
1254                let flags = if first_write {
1255                    first_write = false;
1256                    WriteFlags::PRE_BARRIER
1257                } else {
1258                    WriteFlags::empty()
1259                };
1260                writes.push_back(self.write_at(offset, current_buf, device_offset, flags));
1261                if remaining_buf.len() == 0 {
1262                    break;
1263                } else {
1264                    buf = remaining_buf;
1265                    offset += bytes_to_write as u64;
1266                    if should_advance {
1267                        iter.advance().await?;
1268                    }
1269                }
1270            }
1271        }
1272
1273        self.store().logical_write_ops.fetch_add(1, Ordering::Relaxed);
1274        // The checksums are being ignored here, but we don't need to know them
1275        writes.try_collect::<Vec<MaybeChecksums>>().await?;
1276
1277        if let Some(mut transaction) = transaction {
1278            assert_eq!(options.allow_allocations, true);
1279            if !transaction.is_empty() {
1280                if end > self.get_size() {
1281                    self.grow(&mut transaction, self.get_size(), end).await?;
1282                }
1283                transaction.commit().await?;
1284            }
1285        }
1286
1287        Ok(())
1288    }
1289
1290    // Within a transaction, the size of the object might have changed, so get the size from there
1291    // if it exists, otherwise, fall back on the cached size.
1292    fn txn_get_size(&self, transaction: &Transaction<'_>) -> u64 {
1293        transaction
1294            .get_object_mutation(
1295                self.store().store_object_id,
1296                ObjectKey::attribute(
1297                    self.object_id(),
1298                    self.attribute_id(),
1299                    AttributeKey::Attribute,
1300                ),
1301            )
1302            .and_then(|m| {
1303                if let ObjectItem { value: ObjectValue::Attribute { size, .. }, .. } = m.item {
1304                    Some(size)
1305                } else {
1306                    None
1307                }
1308            })
1309            .unwrap_or_else(|| self.get_size())
1310    }
1311
1312    pub async fn txn_update_size<'a>(
1313        &'a self,
1314        transaction: &mut Transaction<'a>,
1315        new_size: u64,
1316        // Allow callers to update the has_overwrite_extents metadata if they want. If this is
1317        // Some it is set to the value, if None it is left unchanged.
1318        update_has_overwrite_extents: Option<bool>,
1319    ) -> Result<(), Error> {
1320        let key =
1321            ObjectKey::attribute(self.object_id(), self.attribute_id(), AttributeKey::Attribute);
1322        let mut mutation = if let Some(mutation) =
1323            transaction.get_object_mutation(self.store().store_object_id(), key.clone())
1324        {
1325            mutation.clone()
1326        } else {
1327            ObjectStoreMutation {
1328                item: self.store().tree().find(&key).await?.ok_or(FxfsError::NotFound)?,
1329                op: Operation::ReplaceOrInsert,
1330            }
1331        };
1332        if let ObjectValue::Attribute { size, has_overwrite_extents } = &mut mutation.item.value {
1333            *size = new_size;
1334            if let Some(update_has_overwrite_extents) = update_has_overwrite_extents {
1335                *has_overwrite_extents = update_has_overwrite_extents;
1336            }
1337        } else {
1338            bail!(anyhow!(FxfsError::Inconsistent).context("Unexpected object value"));
1339        }
1340        transaction.add_with_object(
1341            self.store().store_object_id(),
1342            Mutation::ObjectStore(mutation),
1343            AssocObj::Borrowed(self),
1344        );
1345        Ok(())
1346    }
1347
1348    async fn update_allocated_size(
1349        &self,
1350        transaction: &mut Transaction<'_>,
1351        allocated: u64,
1352        deallocated: u64,
1353    ) -> Result<(), Error> {
1354        self.handle.update_allocated_size(transaction, allocated, deallocated).await
1355    }
1356
1357    pub fn truncate_overwrite_ranges(&self, size: u64) -> Result<Option<bool>, Error> {
1358        let cutoff = self.block_size().align_up(size).ok_or(FxfsError::TooBig)?;
1359        if self.with_overwrite_ranges_mut(|ranges| ranges.map_or(false, |r| r.truncate(cutoff))) {
1360            // This returns true if there were ranges, but this truncate removed them all, which
1361            // indicates that we need to flip the has_overwrite_extents metadata flag to false.
1362            Ok(Some(false))
1363        } else {
1364            Ok(None)
1365        }
1366    }
1367
1368    pub async fn shrink<'a>(
1369        &'a self,
1370        transaction: &mut Transaction<'a>,
1371        size: u64,
1372        update_has_overwrite_extents: Option<bool>,
1373    ) -> Result<NeedsTrim, Error> {
1374        let needs_trim = self.handle.shrink(transaction, self.attribute_id(), size).await?;
1375        self.txn_update_size(transaction, size, update_has_overwrite_extents).await?;
1376        Ok(needs_trim)
1377    }
1378
1379    pub async fn grow<'a>(
1380        &'a self,
1381        transaction: &mut Transaction<'a>,
1382        old_size: u64,
1383        size: u64,
1384    ) -> Result<(), Error> {
1385        // Before growing the file, we must make sure that a previous trim has completed.
1386        let store = self.store();
1387        while matches!(
1388            store
1389                .trim_some(
1390                    transaction,
1391                    self.object_id(),
1392                    self.attribute_id(),
1393                    TrimMode::FromOffset(old_size)
1394                )
1395                .await?,
1396            TrimResult::Incomplete
1397        ) {
1398            transaction.commit_and_continue().await?;
1399        }
1400        // We might need to zero out the tail of the old last block.
1401        let block_size = self.block_size();
1402        if !block_size.is_aligned(old_size) {
1403            let layer_set = store.tree.layer_set();
1404            let mut merger = layer_set.merger();
1405            let aligned_old_size = block_size.align_down(old_size);
1406            let iter = merger
1407                .query(Query::LimitedRange(&ObjectKey::extent(
1408                    self.object_id(),
1409                    self.attribute_id(),
1410                    aligned_old_size..aligned_old_size + block_size,
1411                )))
1412                .await?;
1413            if let Some(ItemRef {
1414                key:
1415                    ObjectKey {
1416                        object_id,
1417                        data:
1418                            ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent_key)),
1419                    },
1420                value: ObjectValue::Extent(ExtentValue::Some { device_offset, key_id, .. }),
1421                ..
1422            }) = iter.get()
1423            {
1424                if *object_id == self.object_id()
1425                    && *attribute_id == self.attribute_id()
1426                    && extent_key.start <= aligned_old_size
1427                {
1428                    let device_offset = device_offset
1429                        .checked_add(aligned_old_size - extent_key.start)
1430                        .ok_or(FxfsError::Inconsistent)?;
1431                    ensure!(block_size.is_aligned(device_offset), FxfsError::Inconsistent);
1432                    let mut buf = self.allocate_buffer(block_size.get() as usize).await;
1433                    // In the case that this extent is in OverwritePartial mode, there is a
1434                    // possibility that the last block is allocated, but not initialized yet, in
1435                    // which case we don't actually need to bother zeroing out the tail. However,
1436                    // it's not strictly incorrect to change uninitialized data, so we skip the
1437                    // check and blindly do it to keep it simpler here.
1438                    self.read_and_decrypt(device_offset, aligned_old_size, buf.as_mut(), *key_id)
1439                        .await?;
1440                    buf.subslice_mut((old_size % block_size) as usize..buf.len()).fill(0);
1441                    self.multi_write(
1442                        transaction,
1443                        *attribute_id,
1444                        &[aligned_old_size..aligned_old_size + block_size],
1445                        buf.as_mut(),
1446                    )
1447                    .await?;
1448                }
1449            }
1450        }
1451        self.txn_update_size(transaction, size, None).await?;
1452        Ok(())
1453    }
1454
1455    /// Attempts to pre-allocate a `file_range` of bytes for this object.
1456    /// Returns a set of device ranges (i.e. potentially multiple extents).
1457    ///
1458    /// It may not be possible to preallocate the entire requested range in one request
1459    /// due to limitations on transaction size. In such cases, we will preallocate as much as
1460    /// we can up to some (arbitrary, internal) limit on transaction size.
1461    ///
1462    /// `file_range.start` is modified to point at the end of the logical range
1463    /// that was preallocated such that repeated calls to `preallocate_range` with new
1464    /// transactions can be used to preallocate ranges of any size.
1465    ///
1466    /// Requested range must be a multiple of block size.
1467    pub async fn preallocate_range<'a>(
1468        &'a self,
1469        transaction: &mut Transaction<'a>,
1470        file_range: &mut Range<u64>,
1471    ) -> Result<Vec<Range<u64>>, Error> {
1472        let block_size = self.block_size();
1473        ensure!(block_size.is_aligned(&*file_range), FxfsError::InvalidArgs);
1474        ensure!(!self.handle.is_encrypted(), FxfsError::NotSupported);
1475        if file_range.is_empty() {
1476            return Ok(Vec::new());
1477        }
1478        let mut ranges = Vec::new();
1479        let tree = &self.store().tree;
1480        let layer_set = tree.layer_set();
1481        let mut merger = layer_set.merger();
1482        let mut iter = merger
1483            .query(Query::LimitedRange(&ObjectKey::extent(
1484                self.object_id(),
1485                self.attribute_id(),
1486                file_range.clone(),
1487            )))
1488            .await?;
1489        let mut allocated = 0;
1490        let key_id = self.get_key(None).await?.0;
1491        'outer: while file_range.start < file_range.end {
1492            let allocate_end = loop {
1493                match iter.get() {
1494                    // Case for allocated extents for the same object that overlap with file_range.
1495                    Some(ItemRef {
1496                        key:
1497                            ObjectKey {
1498                                object_id,
1499                                data:
1500                                    ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
1501                            },
1502                        value: ObjectValue::Extent(ExtentValue::Some { device_offset, .. }),
1503                        ..
1504                    }) if *object_id == self.object_id()
1505                        && *attribute_id == self.attribute_id()
1506                        && extent.start < file_range.end =>
1507                    {
1508                        ensure!(
1509                            extent.is_valid()
1510                                && block_size.is_aligned(extent)
1511                                && block_size.is_aligned(device_offset),
1512                            FxfsError::Inconsistent
1513                        );
1514                        // If the start of the requested file_range overlaps with an existing extent...
1515                        if extent.start <= file_range.start {
1516                            // Record the existing extent and move on.
1517                            let device_range = device_offset
1518                                .checked_add(file_range.start - extent.start)
1519                                .ok_or(FxfsError::Inconsistent)?
1520                                ..device_offset
1521                                    .checked_add(min(extent.end, file_range.end) - extent.start)
1522                                    .ok_or(FxfsError::Inconsistent)?;
1523                            file_range.start += device_range.end - device_range.start;
1524                            ranges.push(device_range);
1525                            if file_range.start >= file_range.end {
1526                                break 'outer;
1527                            }
1528                            iter.advance().await?;
1529                            continue;
1530                        } else {
1531                            // There's nothing allocated between file_range.start and the beginning
1532                            // of this extent.
1533                            break extent.start;
1534                        }
1535                    }
1536                    // Case for deleted extents eclipsed by file_range.
1537                    Some(ItemRef {
1538                        key:
1539                            ObjectKey {
1540                                object_id,
1541                                data:
1542                                    ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
1543                            },
1544                        value: ObjectValue::Extent(ExtentValue::None),
1545                        ..
1546                    }) if *object_id == self.object_id()
1547                        && *attribute_id == self.attribute_id()
1548                        && extent.end < file_range.end =>
1549                    {
1550                        iter.advance().await?;
1551                    }
1552                    _ => {
1553                        // We can just preallocate the rest.
1554                        break file_range.end;
1555                    }
1556                }
1557            };
1558            let device_range = self
1559                .store()
1560                .allocator()
1561                .allocate(
1562                    transaction,
1563                    self.store().store_object_id(),
1564                    allocate_end - file_range.start,
1565                )
1566                .await
1567                .context("Allocation failed")?;
1568            allocated += device_range.end - device_range.start;
1569            let this_file_range =
1570                file_range.start..file_range.start + device_range.end - device_range.start;
1571            file_range.start = this_file_range.end;
1572            transaction.add(
1573                self.store().store_object_id,
1574                Mutation::merge_object(
1575                    ObjectKey::extent(self.object_id(), self.attribute_id(), this_file_range),
1576                    ObjectValue::Extent(ExtentValue::new_raw(device_range.start, key_id)),
1577                ),
1578            );
1579            ranges.push(device_range);
1580            // If we didn't allocate all that we requested, we'll loop around and try again.
1581            // ... unless we have filled the transaction. The caller should check file_range.
1582            if transaction.mutations().len() > TRANSACTION_MUTATION_THRESHOLD {
1583                break;
1584            }
1585        }
1586        // Update the file size if it changed.
1587        if file_range.start > block_size.align_up(self.txn_get_size(transaction)).unwrap() {
1588            self.txn_update_size(transaction, file_range.start, None).await?;
1589        }
1590        self.update_allocated_size(transaction, allocated, 0).await?;
1591        Ok(ranges)
1592    }
1593
1594    pub async fn update_attributes<'a>(
1595        &self,
1596        transaction: &mut Transaction<'a>,
1597        node_attributes: Option<&fio::MutableNodeAttributes>,
1598        change_time: Option<Timestamp>,
1599    ) -> Result<(), Error> {
1600        // This codepath is only called by files, whose wrapping key id users cannot directly set
1601        // as per fscrypt.
1602        ensure!(
1603            !matches!(
1604                node_attributes,
1605                Some(fio::MutableNodeAttributes { encryption_policy: Some(_), .. })
1606            ),
1607            FxfsError::BadPath
1608        );
1609        self.handle.update_attributes(transaction, node_attributes, change_time).await
1610    }
1611
1612    /// Get the default set of transaction options for this object. This is mostly the overall
1613    /// default, modified by any [`HandleOptions`] held by this handle.
1614    pub fn default_transaction_options<'b>(&self) -> Options<'b> {
1615        self.handle.default_transaction_options()
1616    }
1617
1618    pub async fn new_transaction<'b>(&self) -> Result<Transaction<'b>, Error> {
1619        self.new_transaction_with_options(self.default_transaction_options()).await
1620    }
1621
1622    pub async fn new_transaction_with_options<'b>(
1623        &self,
1624        options: Options<'b>,
1625    ) -> Result<Transaction<'b>, Error> {
1626        self.handle.new_transaction_with_options(self.attribute_id(), options).await
1627    }
1628
1629    /// Flushes the underlying device.  This is expensive and should be used sparingly.
1630    pub async fn flush_device(&self) -> Result<(), Error> {
1631        self.handle.flush_device().await
1632    }
1633
1634    /// Reads an entire attribute.
1635    pub async fn read_attr(&self, attribute_id: AttributeId) -> Result<Option<Box<[u8]>>, Error> {
1636        self.handle.read_attr(attribute_id).await
1637    }
1638
1639    /// Writes an entire attribute.  This *always* uses the volume data key.
1640    pub async fn write_attr(&self, attribute_id: AttributeId, data: &[u8]) -> Result<(), Error> {
1641        // Must be different attribute otherwise cached size gets out of date.
1642        assert_ne!(attribute_id, self.attribute_id());
1643        let store = self.store();
1644        let mut transaction = self.new_transaction().await?;
1645        if self.handle.write_attr(&mut transaction, attribute_id, data).await?.0 {
1646            transaction.commit_and_continue().await?;
1647            while matches!(
1648                store
1649                    .trim_some(
1650                        &mut transaction,
1651                        self.object_id(),
1652                        attribute_id,
1653                        TrimMode::FromOffset(data.len() as u64),
1654                    )
1655                    .await?,
1656                TrimResult::Incomplete
1657            ) {
1658                transaction.commit_and_continue().await?;
1659            }
1660        }
1661        transaction.commit().await?;
1662        Ok(())
1663    }
1664
1665    async fn read_and_decrypt(
1666        &self,
1667        device_offset: u64,
1668        file_offset: u64,
1669        buffer: MutableBufferRef<'_>,
1670        key_id: u64,
1671    ) -> Result<(), Error> {
1672        self.handle
1673            .read_and_decrypt(self.attribute_id, device_offset, file_offset, buffer, key_id)
1674            .await
1675    }
1676
1677    /// Truncates a file to a given size (growing/shrinking as required).
1678    ///
1679    /// Nb: Most code will want to call truncate() instead. This method is used
1680    /// to update the super block -- a case where we must borrow metadata space.
1681    pub async fn truncate_with_options(
1682        &self,
1683        mut options: Options<'_>,
1684        size: u64,
1685    ) -> Result<(), Error> {
1686        let borrowed_for_shrink =
1687            size < self.get_size() && matches!(options.reservation, ReservationOptions::New);
1688        if borrowed_for_shrink {
1689            options.reservation = ReservationOptions::Borrowed;
1690        }
1691        let mut transaction = self.new_transaction_with_options(options).await?;
1692        let mut old_size = self.get_size();
1693        if size > old_size && borrowed_for_shrink {
1694            // The file shrank while we were waiting for the lock and we now need to grow it,
1695            // which might require allocating space.
1696            drop(transaction);
1697            options.reservation = ReservationOptions::New;
1698            transaction = self.new_transaction_with_options(options).await?;
1699            old_size = self.get_size();
1700        }
1701        {
1702            let state = self.state.lock();
1703            match &*state {
1704                DataObjectState::Standard(_) => {}
1705                _ => bail!(anyhow!(FxfsError::AccessDenied).context("Cannot truncate verity file")),
1706            }
1707        }
1708        if size == old_size {
1709            return Ok(());
1710        }
1711        if size < old_size {
1712            let update_has_overwrite_ranges = self.truncate_overwrite_ranges(size)?;
1713            if self.shrink(&mut transaction, size, update_has_overwrite_ranges).await?.0 {
1714                // The file needs to be trimmed.
1715                transaction.commit_and_continue().await?;
1716                let store = self.store();
1717                while matches!(
1718                    store
1719                        .trim_some(
1720                            &mut transaction,
1721                            self.object_id(),
1722                            self.attribute_id(),
1723                            TrimMode::FromOffset(size)
1724                        )
1725                        .await?,
1726                    TrimResult::Incomplete
1727                ) {
1728                    if let Err(error) = transaction.commit_and_continue().await {
1729                        warn!(error:?; "Failed to trim after truncate");
1730                        return Ok(());
1731                    }
1732                }
1733                if let Err(error) = transaction.commit().await {
1734                    warn!(error:?; "Failed to trim after truncate");
1735                }
1736                return Ok(());
1737            }
1738        } else {
1739            self.grow(&mut transaction, old_size, size).await?;
1740        }
1741        transaction.commit().await?;
1742        Ok(())
1743    }
1744
1745    pub async fn get_properties(&self) -> Result<ObjectProperties, Error> {
1746        // We don't take a read guard here since the object properties are contained in a single
1747        // object, which cannot be inconsistent with itself. The LSM tree does not return
1748        // intermediate states for a single object.
1749        let value = self
1750            .store()
1751            .tree
1752            .find_value(&ObjectKey::object(self.object_id()))
1753            .await?
1754            .expect("Unable to find object record");
1755        match value {
1756            ObjectValue::Object {
1757                kind: ObjectKind::File { refs, .. },
1758                attributes:
1759                    ObjectAttributes {
1760                        creation_time,
1761                        modification_time,
1762                        posix_attributes,
1763                        allocated_size,
1764                        access_time,
1765                        change_time,
1766                        ..
1767                    },
1768            } => Ok(ObjectProperties {
1769                refs,
1770                allocated_size,
1771                data_attribute_size: self.get_size(),
1772                creation_time,
1773                modification_time,
1774                access_time,
1775                change_time,
1776                sub_dirs: 0,
1777                posix_attributes,
1778                dir_type: DirType::Normal,
1779            }),
1780            _ => bail!(FxfsError::NotFile),
1781        }
1782    }
1783
1784    /// Returns the set of file_offset->extent mappings for this file. The extents will be sorted by
1785    /// their logical offset within the file.
1786    ///
1787    /// *NOTE*: This operation is potentially expensive and should generally be avoided.
1788    pub async fn device_extents(&self) -> Result<Vec<FileExtent>, Error> {
1789        let tree = &self.store().tree;
1790        let layer_set = tree.layer_set();
1791        let mut merger = layer_set.merger();
1792        let stream = self.handle.extent_stream(&mut merger, self.attribute_id()).await?;
1793        let extents: Vec<FileExtent> = stream.try_collect().await?;
1794        Ok(extents)
1795    }
1796
1797    /// Returns the contents of this object. This object must be < |limit| bytes in size.
1798    pub async fn contents(&self, limit: usize) -> Result<Box<[u8]>, Error> {
1799        let size = self.get_size();
1800        if size > limit as u64 {
1801            bail!("Object too big ({} > {})", size, limit);
1802        }
1803        self.read_bytes(0..size).await
1804    }
1805
1806    /// Reads the contents of this object within `range`. `range` does not need to be block aligned.
1807    ///
1808    /// This method should be avoided in high-performance contexts. Use `read_aligned` instead.
1809    pub async fn read_bytes(&self, range: Range<u64>) -> Result<Box<[u8]>, Error> {
1810        const MAX_READ_BYTES_CHUNK_SIZE: usize = 2 * 1024 * 1024; // 2 MiB
1811
1812        ensure!(range.start <= range.end, FxfsError::InvalidArgs);
1813        if range.is_empty() {
1814            return Ok(Box::default());
1815        }
1816        let fs = self.store().filesystem();
1817        let guard = fs
1818            .lock_manager()
1819            .read_lock(lock_keys![LockKey::object_attribute(
1820                self.store().store_object_id,
1821                self.object_id(),
1822                self.attribute_id(),
1823            )])
1824            .await;
1825
1826        let size = self.get_size();
1827        if range.start >= size {
1828            return Ok(Box::default());
1829        }
1830        let end = std::cmp::min(range.end, size);
1831        let total_to_read = (end - range.start) as usize;
1832        let block_size = self.block_size();
1833        let aligned_start = block_size.align_down(range.start);
1834        let aligned_end = block_size.align_up(end).ok_or(FxfsError::TooBig)?;
1835        let total_aligned_len = aligned_end - aligned_start;
1836
1837        let buf_size = std::cmp::min(total_aligned_len, MAX_READ_BYTES_CHUNK_SIZE as u64) as usize;
1838        let mut buf = self.allocate_buffer(buf_size).await;
1839        let mut out = Vec::with_capacity(total_to_read);
1840        let mut current_block_offset = aligned_start;
1841
1842        while current_block_offset < end {
1843            let bytes_read =
1844                self.read_aligned_locked(current_block_offset, buf.as_mut(), &guard).await?;
1845            let chunk_start = current_block_offset;
1846            let chunk_end = current_block_offset + bytes_read as u64;
1847            let slice_start = std::cmp::max(range.start, chunk_start);
1848            let slice_end = std::cmp::min(end, chunk_end);
1849            let buf_offset = (slice_start - chunk_start) as usize;
1850            let to_copy = (slice_end - slice_start) as usize;
1851            buf.subslice(buf_offset..buf_offset + to_copy).append_to(&mut out);
1852            current_block_offset = current_block_offset.saturating_add(buf_size as u64);
1853        }
1854        Ok(out.into_boxed_slice())
1855    }
1856
1857    /// Reads up to `buf.len()` bytes from `offset` while holding `guard`.
1858    ///
1859    /// Both `offset` and `buf.len()` must be aligned to the object's `block_size()`.
1860    ///
1861    /// `guard` must be an active read lock for this object's attribute.
1862    ///
1863    /// Returns the number of bytes read up to the object's size (or 0 if `offset >= size`). Holes/
1864    /// sparse extents within the read range are zero-filled. Callers should not make any
1865    /// assumptions about the contents of the buffer past the returned read amount. If this is a
1866    /// verified file (fs-verity), the data is validated against the Merkle tree before returning.
1867    async fn read_aligned_locked(
1868        &self,
1869        offset: u64,
1870        mut buf: MutableBufferRef<'_>,
1871        guard: &ReadGuard<'_>,
1872    ) -> Result<usize, Error> {
1873        let block_size = self.block_size();
1874        debug_assert!(block_size.is_aligned(offset));
1875        debug_assert!(block_size.is_aligned(buf.len() as u64));
1876
1877        let size = self.get_size();
1878        if offset >= size {
1879            return Ok(0);
1880        }
1881        let length = min(buf.len() as u64, size - offset) as usize;
1882        let aligned_length =
1883            block_size.align_up(length as u64).ok_or(FxfsError::Inconsistent)? as usize;
1884        buf = buf.subslice_mut(0..aligned_length);
1885
1886        self.handle
1887            .read_aligned_unchecked(self.attribute_id(), offset, buf.reborrow(), guard)
1888            .await?;
1889        if self.is_verified_file() {
1890            self.verify_data(offset as usize, buf.subslice(0..length).as_ptr_slice())?;
1891        }
1892        Ok(length)
1893    }
1894
1895    /// Fills `buf` with bytes read from `offset` on the underlying device.
1896    ///
1897    /// Both `offset` and `buf.len()` must be aligned to the object's `block_size()`.
1898    ///
1899    /// Returns the number of bytes read. If `offset >= size`, returns 0. Holes/sparse extents
1900    /// within the read range are zero-filled. Callers should not make any assumptions about the
1901    /// contents of the buffer past the returned read amount.
1902    ///
1903    /// If the object is a verified file (fs-verity), the read data is validated against the Merkle
1904    /// tree before returning.
1905    ///
1906    /// This is an inherent version of the `ReadObjectHandle::read_aligned` trait method which
1907    /// avoids boxing the returned `Future`.
1908    pub async fn read_aligned(
1909        &self,
1910        offset: u64,
1911        buf: MutableBufferRef<'_>,
1912    ) -> Result<usize, Error> {
1913        let block_size = self.block_size();
1914        ensure!(block_size.is_aligned(offset), FxfsError::InvalidArgs);
1915        ensure!(block_size.is_aligned(buf.len() as u64), FxfsError::InvalidArgs);
1916        let fs = self.store().filesystem();
1917        let guard = fs
1918            .lock_manager()
1919            .read_lock(lock_keys![LockKey::object_attribute(
1920                self.store().store_object_id,
1921                self.object_id(),
1922                self.attribute_id(),
1923            )])
1924            .await;
1925        self.read_aligned_locked(offset, buf, &guard).await
1926    }
1927}
1928
1929impl<S: HandleOwner> AssociatedObject for DataObjectHandle<S> {
1930    fn will_apply_mutation(&self, mutation: &Mutation, _object_id: u64, _manager: &ObjectManager) {
1931        match mutation {
1932            Mutation::ObjectStore(ObjectStoreMutation {
1933                item: ObjectItem { value: ObjectValue::Attribute { size, .. }, .. },
1934                ..
1935            }) => self.content_size.store(*size, atomic::Ordering::Relaxed),
1936            Mutation::ObjectStore(ObjectStoreMutation {
1937                item: ObjectItem { value: ObjectValue::VerifiedAttribute { size, .. }, .. },
1938                ..
1939            }) => {
1940                debug_assert_eq!(
1941                    self.get_size(),
1942                    *size,
1943                    "size should be set when verity is enabled and must not change"
1944                );
1945                self.finalize_fsverity_state()
1946            }
1947            Mutation::ObjectStore(ObjectStoreMutation {
1948                item:
1949                    ObjectItem {
1950                        key:
1951                            ObjectKey {
1952                                object_id,
1953                                data:
1954                                    ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent)),
1955                            },
1956                        value: ObjectValue::Extent(ExtentValue::Some { mode, .. }),
1957                        ..
1958                    },
1959                ..
1960            }) if self.object_id() == *object_id && self.attribute_id() == *attr_id => match mode {
1961                ExtentMode::Overwrite | ExtentMode::OverwritePartial(_) => {
1962                    // If `enable_verity` transitioned state to `VerityStarted` concurrently while a
1963                    // transaction was in progress, `with_overwrite_ranges_mut` will return `None`
1964                    // and safely discard in-memory range updates, since verity files do not track
1965                    // overwrite ranges.
1966                    self.with_overwrite_ranges_mut(|ranges| {
1967                        if let Some(ranges) = ranges {
1968                            ranges.apply_range(extent.clone().into());
1969                        }
1970                    });
1971                }
1972                ExtentMode::Raw | ExtentMode::Cow(_) => (),
1973            },
1974            _ => {}
1975        }
1976    }
1977}
1978
1979impl<S: HandleOwner> ObjectHandle for DataObjectHandle<S> {
1980    fn set_trace(&self, v: bool) {
1981        self.handle.set_trace(v)
1982    }
1983
1984    fn object_id(&self) -> u64 {
1985        self.handle.object_id()
1986    }
1987
1988    fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
1989        self.handle.allocate_buffer(size)
1990    }
1991
1992    fn block_size(&self) -> BlockSize {
1993        self.handle.block_size()
1994    }
1995}
1996
1997impl<S: HandleOwner> ReadObjectHandle for DataObjectHandle<S> {
1998    fn read_aligned<'a, 'b, 'c>(
1999        &'a self,
2000        offset: u64,
2001        buf: MutableBufferRef<'b>,
2002    ) -> Pin<Box<dyn Future<Output = Result<usize, Error>> + Send + 'c>>
2003    where
2004        'a: 'c,
2005        'b: 'c,
2006        Self: 'c,
2007    {
2008        Box::pin(DataObjectHandle::read_aligned(self, offset, buf))
2009    }
2010
2011    fn get_size(&self) -> u64 {
2012        self.content_size.load(atomic::Ordering::Relaxed)
2013    }
2014}
2015
2016impl<S: HandleOwner> LayerObject for DataObjectHandle<S> {}
2017
2018impl<S: HandleOwner> WriteObjectHandle for DataObjectHandle<S> {
2019    async fn write_or_append(&self, offset: Option<u64>, buf: BufferRef<'_>) -> Result<u64, Error> {
2020        let offset = offset.unwrap_or_else(|| self.get_size());
2021        let mut transaction = self.new_transaction().await?;
2022        self.txn_write(&mut transaction, offset, buf).await?;
2023        let new_size = self.txn_get_size(&transaction);
2024        transaction.commit().await?;
2025        Ok(new_size)
2026    }
2027
2028    async fn truncate(&self, size: u64) -> Result<(), Error> {
2029        self.truncate_with_options(self.default_transaction_options(), size).await
2030    }
2031
2032    async fn flush(&self) -> Result<(), Error> {
2033        Ok(())
2034    }
2035}
2036
2037/// Like object_handle::Writer, but allows custom transaction options to be set, and makes every
2038/// write go directly to the handle in a transaction.
2039pub struct DirectWriter<'a, S: HandleOwner> {
2040    handle: &'a DataObjectHandle<S>,
2041    options: transaction::Options<'a>,
2042    buffer: Buffer<'a>,
2043    offset: u64,
2044    buf_offset: usize,
2045}
2046
2047const BUFFER_SIZE: usize = 1_048_576;
2048
2049impl<S: HandleOwner> Drop for DirectWriter<'_, S> {
2050    fn drop(&mut self) {
2051        if self.buf_offset != 0 {
2052            warn!("DirectWriter: dropping data, did you forget to call complete?");
2053        }
2054    }
2055}
2056
2057impl<'a, S: HandleOwner> DirectWriter<'a, S> {
2058    pub async fn new(
2059        handle: &'a DataObjectHandle<S>,
2060        options: transaction::Options<'a>,
2061    ) -> DirectWriter<'a, S> {
2062        Self {
2063            handle,
2064            options,
2065            buffer: handle.allocate_buffer(BUFFER_SIZE).await,
2066            offset: 0,
2067            buf_offset: 0,
2068        }
2069    }
2070
2071    async fn flush(&mut self) -> Result<(), Error> {
2072        let mut transaction = self.handle.new_transaction_with_options(self.options).await?;
2073        self.handle
2074            .txn_write(&mut transaction, self.offset, self.buffer.subslice(0..self.buf_offset))
2075            .await?;
2076        transaction.commit().await?;
2077        self.offset += self.buf_offset as u64;
2078        self.buf_offset = 0;
2079        Ok(())
2080    }
2081}
2082
2083impl<'a, S: HandleOwner> WriteBytes for DirectWriter<'a, S> {
2084    fn block_size(&self) -> BlockSize {
2085        self.handle.block_size()
2086    }
2087
2088    async fn write_bytes(&mut self, mut buf: &[u8]) -> Result<(), Error> {
2089        while buf.len() > 0 {
2090            let to_do = std::cmp::min(buf.len(), BUFFER_SIZE - self.buf_offset);
2091            self.buffer
2092                .subslice_mut(self.buf_offset..self.buf_offset + to_do)
2093                .copy_from_slice(&buf[..to_do]);
2094            self.buf_offset += to_do;
2095            if self.buf_offset == BUFFER_SIZE {
2096                self.flush().await?;
2097            }
2098            buf = &buf[to_do..];
2099        }
2100        Ok(())
2101    }
2102
2103    async fn complete(mut self) -> Result<u64, Error> {
2104        self.flush().await?;
2105        Ok(self.offset + self.buf_offset as u64)
2106    }
2107
2108    async fn skip(&mut self, amount: u64) -> Result<(), Error> {
2109        if (BUFFER_SIZE - self.buf_offset) as u64 > amount {
2110            self.buffer.subslice_mut(self.buf_offset..self.buf_offset + amount as usize).fill(0);
2111            self.buf_offset += amount as usize;
2112        } else {
2113            self.flush().await?;
2114            self.offset += amount;
2115        }
2116        Ok(())
2117    }
2118}
2119
2120#[cfg(test)]
2121mod tests {
2122    use crate::errors::FxfsError;
2123    use crate::filesystem::{FxFilesystem, FxFilesystemBuilder, OpenFxFilesystem, SyncOptions};
2124    use crate::fsck::{
2125        FsckOptions, fsck, fsck_volume, fsck_volume_with_options, fsck_with_options,
2126    };
2127    use crate::lsm_tree::Query;
2128    use crate::lsm_tree::types::{ItemRef, LayerIterator};
2129    use crate::object_handle::{
2130        ObjectHandle, ObjectProperties, ReadObjectHandle, WriteObjectHandle,
2131    };
2132    use crate::object_store::data_object_handle::{OverwriteOptions, WRITE_ATTR_BATCH_SIZE};
2133    use crate::object_store::directory::replace_child;
2134    use crate::object_store::object_record::{FsverityMetadata, ObjectKey, ObjectValue, Timestamp};
2135    use crate::object_store::transaction::{Mutation, Options, ReservationOptions, lock_keys};
2136    use crate::object_store::volume::root_volume;
2137    use crate::object_store::{
2138        AttributeId, AttributeKey, DataObjectHandle, DirType, Directory, Extent, ExtentMode,
2139        ExtentValue, HandleOptions, LockKey, NewChildStoreOptions, ObjectKeyData, ObjectStore,
2140        PosixAttributes, StoreOptions, TRANSACTION_MUTATION_THRESHOLD,
2141    };
2142    use crate::range::RangeExt;
2143    use crate::round::{round_down, round_up};
2144    use assert_matches::assert_matches;
2145    use bit_vec::BitVec;
2146    use fidl_fuchsia_io as fio;
2147    use fsverity_merkle::{FsVerityDescriptor, FsVerityDescriptorRaw};
2148    use fuchsia_async as fasync;
2149    use fuchsia_sync::Mutex;
2150    use futures::FutureExt;
2151    use futures::channel::oneshot::channel;
2152    use futures::stream::{FuturesUnordered, StreamExt};
2153    use fxfs_crypto::{Crypt, EncryptionKey, KeyPurpose};
2154    use fxfs_insecure_crypto::new_insecure_crypt;
2155    use std::ops::Range;
2156    use std::sync::{Arc, Weak};
2157    use std::time::Duration;
2158    use storage_device::DeviceHolder;
2159    use storage_device::fake_device::FakeDevice;
2160
2161    const TEST_DEVICE_BLOCK_SIZE: u32 = 512;
2162
2163    // Some tests (the preallocate_range ones) currently assume that the data only occupies a single
2164    // device block.
2165    const TEST_DATA_OFFSET: u64 = 5000;
2166    const TEST_DATA: &[u8] = b"hello";
2167    const TEST_OBJECT_SIZE: u64 = 5678;
2168    const TEST_OBJECT_ALLOCATED_SIZE: u64 = 4096;
2169    const TEST_OBJECT_NAME: &str = "foo";
2170
2171    async fn test_filesystem() -> OpenFxFilesystem {
2172        let device = DeviceHolder::new(FakeDevice::new(8192, TEST_DEVICE_BLOCK_SIZE));
2173        FxFilesystem::new_empty(device).await.expect("new_empty failed")
2174    }
2175
2176    async fn create_object_with_key(
2177        fs: Arc<FxFilesystem>,
2178        crypt: Option<&dyn Crypt>,
2179        write_object_test_data: bool,
2180    ) -> DataObjectHandle<ObjectStore> {
2181        let store = fs.root_store();
2182        let object;
2183
2184        let mut transaction = fs
2185            .root_store()
2186            .new_transaction(
2187                lock_keys![LockKey::object(
2188                    store.store_object_id(),
2189                    store.root_directory_object_id()
2190                )],
2191                Options::default(),
2192            )
2193            .await
2194            .expect("new_transaction failed");
2195
2196        object = if let Some(crypt) = crypt {
2197            let object_id = store.get_next_object_id(&transaction).await.unwrap();
2198            let (key, unwrapped_key) =
2199                crypt.create_key(object_id.get(), KeyPurpose::Data).await.unwrap();
2200            ObjectStore::create_object_with_key(
2201                &store,
2202                &mut transaction,
2203                object_id,
2204                HandleOptions::default(),
2205                EncryptionKey::Fxfs(key),
2206                unwrapped_key,
2207            )
2208            .await
2209            .expect("create_object failed")
2210        } else {
2211            ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
2212                .await
2213                .expect("create_object failed")
2214        };
2215
2216        let root_directory =
2217            Directory::open(&store, store.root_directory_object_id()).await.expect("open failed");
2218        root_directory
2219            .add_child_file(&mut transaction, TEST_OBJECT_NAME, &object)
2220            .await
2221            .expect("add_child_file failed");
2222
2223        if write_object_test_data {
2224            let align = TEST_DATA_OFFSET as usize % TEST_DEVICE_BLOCK_SIZE as usize;
2225            let mut buf = object.allocate_buffer(align + TEST_DATA.len()).await;
2226            buf.subslice_mut(align..buf.len()).copy_from_slice(TEST_DATA);
2227            object
2228                .txn_write(&mut transaction, TEST_DATA_OFFSET, buf.subslice(align..buf.len()))
2229                .await
2230                .expect("write failed");
2231        }
2232        transaction.commit().await.expect("commit failed");
2233        object.truncate(TEST_OBJECT_SIZE).await.expect("truncate failed");
2234        object
2235    }
2236
2237    async fn test_filesystem_and_object_with_key(
2238        crypt: Option<&dyn Crypt>,
2239        write_object_test_data: bool,
2240    ) -> (OpenFxFilesystem, DataObjectHandle<ObjectStore>) {
2241        let fs = test_filesystem().await;
2242        let object = create_object_with_key(fs.clone(), crypt, write_object_test_data).await;
2243        (fs, object)
2244    }
2245
2246    async fn test_filesystem_and_object() -> (OpenFxFilesystem, DataObjectHandle<ObjectStore>) {
2247        test_filesystem_and_object_with_key(Some(&new_insecure_crypt()), true).await
2248    }
2249
2250    async fn test_filesystem_and_empty_object() -> (OpenFxFilesystem, DataObjectHandle<ObjectStore>)
2251    {
2252        test_filesystem_and_object_with_key(Some(&new_insecure_crypt()), false).await
2253    }
2254
2255    #[fuchsia::test]
2256    async fn test_zero_buf_len_read() {
2257        let (fs, object) = test_filesystem_and_object().await;
2258        let mut buf = object.allocate_buffer(0).await;
2259        assert_eq!(object.read_aligned(0u64, buf.as_mut()).await.expect("read failed"), 0);
2260        fs.close().await.expect("Close failed");
2261    }
2262
2263    #[fuchsia::test]
2264    async fn test_beyond_eof_read() {
2265        let (fs, object) = test_filesystem_and_object().await;
2266        let offset = TEST_OBJECT_SIZE as usize - 2;
2267        let align = (offset as u64 % fs.block_size()) as usize;
2268        let len: usize = 2;
2269        let block_size = fs.block_size().get() as usize;
2270
2271        // Unaligned buffer should fail.
2272        let mut unaligned_buf = object.allocate_buffer(align + len + 1).await;
2273        assert_matches!(
2274            object.read_aligned((offset - align) as u64, unaligned_buf.as_mut()).await,
2275            Err(e) if FxfsError::InvalidArgs.matches(&e)
2276        );
2277
2278        let mut buf = object.allocate_buffer(block_size).await;
2279        buf.fill(123u8);
2280        assert_eq!(
2281            object.read_aligned((offset - align) as u64, buf.as_mut()).await.expect("read failed"),
2282            align + len
2283        );
2284        assert_eq!(&buf.as_ptr_slice().subslice(align..align + len).to_vec()[..], &vec![0u8; len]);
2285
2286        // Unaligned offset should fail.
2287        assert_matches!(
2288            object.read_aligned((offset - align + 1) as u64, buf.as_mut()).await,
2289            Err(e) if FxfsError::InvalidArgs.matches(&e)
2290        );
2291
2292        // Reading starting at or after EOF should return 0.
2293        let aligned_eof = fs.block_size().align_up(TEST_OBJECT_SIZE).unwrap();
2294        assert_eq!(object.read_aligned(aligned_eof, buf.as_mut()).await.expect("read failed"), 0);
2295
2296        // Also test read_bytes past EOF.
2297        let data = object
2298            .read_bytes(offset as u64..offset as u64 + len as u64 + 1)
2299            .await
2300            .expect("read_bytes failed");
2301        assert_eq!(&data[..], &vec![0u8; len]);
2302
2303        fs.close().await.expect("Close failed");
2304    }
2305
2306    #[fuchsia::test]
2307    async fn test_beyond_eof_read_from() {
2308        let (fs, object) = test_filesystem_and_object().await;
2309        let handle = &*object;
2310        let offset = TEST_OBJECT_SIZE as usize - 2;
2311        let align = (offset as u64 % fs.block_size()) as usize;
2312        let len: usize = 2;
2313        let block_size = fs.block_size().get() as usize;
2314
2315        // Unaligned buffer should fail.
2316        let mut unaligned_buf = object.allocate_buffer(align + len + 1).await;
2317        assert_matches!(
2318            handle
2319                .read_aligned(AttributeId::DATA, (offset - align) as u64, unaligned_buf.as_mut())
2320                .await,
2321            Err(e) if FxfsError::InvalidArgs.matches(&e)
2322        );
2323
2324        let mut buf = object.allocate_buffer(block_size).await;
2325        buf.fill(123u8);
2326        assert_eq!(
2327            handle
2328                .read_aligned(AttributeId::DATA, (offset - align) as u64, buf.as_mut())
2329                .await
2330                .expect("read failed"),
2331            align + len
2332        );
2333        assert_eq!(&buf.as_ptr_slice().subslice(align..align + len).to_vec()[..], &vec![0u8; len]);
2334
2335        // Unaligned offset should fail.
2336        assert_matches!(
2337            handle
2338                .read_aligned(AttributeId::DATA, (offset - align + 1) as u64, buf.as_mut())
2339                .await,
2340            Err(e) if FxfsError::InvalidArgs.matches(&e)
2341        );
2342
2343        // Reading starting at or after EOF should return 0.
2344        let aligned_eof = fs.block_size().align_up(TEST_OBJECT_SIZE).unwrap();
2345        assert_eq!(
2346            handle
2347                .read_aligned(AttributeId::DATA, aligned_eof, buf.as_mut())
2348                .await
2349                .expect("read failed"),
2350            0
2351        );
2352
2353        fs.close().await.expect("Close failed");
2354    }
2355
2356    #[fuchsia::test]
2357    async fn test_beyond_eof_read_aligned_unchecked() {
2358        let (fs, object) = test_filesystem_and_object().await;
2359        let offset = TEST_OBJECT_SIZE as usize - 2;
2360        let align = (offset as u64 % fs.block_size()) as usize;
2361        let block_size = fs.block_size().get() as usize;
2362        let mut buf = object.allocate_buffer(block_size).await;
2363        buf.fill(123u8);
2364        let guard = fs
2365            .lock_manager()
2366            .read_lock(lock_keys![LockKey::object_attribute(
2367                object.store().store_object_id,
2368                object.object_id(),
2369                AttributeId::DATA,
2370            )])
2371            .await;
2372        object
2373            .read_aligned_unchecked(
2374                AttributeId::DATA,
2375                (offset - align) as u64,
2376                buf.as_mut(),
2377                &guard,
2378            )
2379            .await
2380            .expect("read failed");
2381        assert_eq!(
2382            &buf.as_ptr_slice().subslice(align..block_size).to_vec()[..],
2383            &vec![0u8; block_size - align]
2384        );
2385
2386        // Reading entirely past EOF with read_aligned_unchecked fills with zeros.
2387        let aligned_eof = fs.block_size().align_up(TEST_OBJECT_SIZE).unwrap();
2388        buf.fill(123u8);
2389        object
2390            .read_aligned_unchecked(AttributeId::DATA, aligned_eof, buf.as_mut(), &guard)
2391            .await
2392            .expect("read failed");
2393        assert_eq!(buf.to_vec(), vec![0u8; block_size]);
2394        fs.close().await.expect("Close failed");
2395    }
2396
2397    #[fuchsia::test]
2398    async fn test_read_sparse() {
2399        let (fs, object) = test_filesystem_and_object().await;
2400        // Deliberately read not right to eof.
2401        let len = TEST_OBJECT_SIZE as usize - 1;
2402        let data = object.read_bytes(0..len as u64).await.expect("read failed");
2403        let mut expected = vec![0; len];
2404        let offset = TEST_DATA_OFFSET as usize;
2405        expected[offset..offset + TEST_DATA.len()].copy_from_slice(TEST_DATA);
2406        assert_eq!(&data[..], &expected[..]);
2407
2408        let aligned_len = fs.block_size().align_up(TEST_OBJECT_SIZE).unwrap() as usize;
2409        let mut buf = object.allocate_buffer(aligned_len).await;
2410        buf.fill(123u8);
2411        assert_eq!(
2412            object.read_aligned(0, buf.as_mut()).await.expect("read failed"),
2413            TEST_OBJECT_SIZE as usize
2414        );
2415        let mut expected_aligned = vec![0; TEST_OBJECT_SIZE as usize];
2416        expected_aligned[offset..offset + TEST_DATA.len()].copy_from_slice(TEST_DATA);
2417        assert_eq!(
2418            &buf.as_ptr_slice().subslice(0..TEST_OBJECT_SIZE as usize).to_vec()[..],
2419            &expected_aligned[..]
2420        );
2421        fs.close().await.expect("Close failed");
2422    }
2423
2424    #[fuchsia::test]
2425    async fn test_read_after_writes_interspersed_with_flush() {
2426        let (fs, object) = test_filesystem_and_object().await;
2427
2428        object.owner().flush().await.expect("flush failed");
2429
2430        // Write more test data to the first block fo the file.
2431        let mut buf = object.allocate_buffer(TEST_DATA.len()).await;
2432        buf.copy_from_slice(TEST_DATA);
2433        object.write_or_append(Some(0u64), buf.as_ref()).await.expect("write failed");
2434
2435        let len = TEST_OBJECT_SIZE as usize - 1;
2436        let data = object.read_bytes(0..len as u64).await.expect("read failed");
2437
2438        let mut expected = vec![0u8; len];
2439        let offset = TEST_DATA_OFFSET as usize;
2440        expected[offset..offset + TEST_DATA.len()].copy_from_slice(TEST_DATA);
2441        expected[..TEST_DATA.len()].copy_from_slice(TEST_DATA);
2442        assert_eq!(&data[..], &expected);
2443        fs.close().await.expect("Close failed");
2444    }
2445
2446    #[fuchsia::test]
2447    async fn test_read_after_truncate_and_extend() {
2448        let (fs, object) = test_filesystem_and_object().await;
2449
2450        // Arrange for there to be <extent><deleted-extent><extent>.
2451        let mut buf = object.allocate_buffer(TEST_DATA.len()).await;
2452        buf.copy_from_slice(TEST_DATA);
2453        // This adds an extent at 0..512.
2454        object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
2455        // This deletes 512..1024.
2456        object.truncate(3).await.expect("truncate failed");
2457        let data = b"foo";
2458        let offset = 1500u64;
2459        let align = (offset % fs.block_size()) as usize;
2460        let mut buf = object.allocate_buffer(align + data.len()).await;
2461        buf.subslice_mut(align..buf.len()).copy_from_slice(data);
2462        // This adds 1024..1536.
2463        object
2464            .write_or_append(Some(1500), buf.subslice(align..buf.len()))
2465            .await
2466            .expect("write failed");
2467
2468        const LEN1: usize = 1503;
2469        let data1 = object.read_bytes(0..LEN1 as u64).await.expect("read failed");
2470        let mut expected = [0; LEN1];
2471        expected[..3].copy_from_slice(&TEST_DATA[..3]);
2472        expected[1500..].copy_from_slice(b"foo");
2473        assert_eq!(&data1[..], &expected);
2474
2475        // Also test a read that ends midway through the deleted extent.
2476        const LEN2: usize = 601;
2477        let data2 = object.read_bytes(0..LEN2 as u64).await.expect("read failed");
2478        assert_eq!(&data2[..], &expected[..LEN2]);
2479        fs.close().await.expect("Close failed");
2480    }
2481
2482    #[fuchsia::test]
2483    async fn test_read_whole_blocks_with_multiple_objects() {
2484        let (fs, object) = test_filesystem_and_object().await;
2485        let block_size = object.block_size().get() as usize;
2486        let mut buffer = object.allocate_buffer(block_size).await;
2487        buffer.fill(0xaf);
2488        object.write_or_append(Some(0), buffer.as_ref()).await.expect("write failed");
2489
2490        let store = object.owner();
2491        let mut transaction = fs
2492            .root_store()
2493            .new_transaction(lock_keys![], Options::default())
2494            .await
2495            .expect("new_transaction failed");
2496        let object2 =
2497            ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
2498                .await
2499                .expect("create_object failed");
2500        transaction.commit().await.expect("commit failed");
2501        let mut ef_buffer = object.allocate_buffer(block_size).await;
2502        ef_buffer.fill(0xef);
2503        object2.write_or_append(Some(0), ef_buffer.as_ref()).await.expect("write failed");
2504
2505        let mut buffer = object.allocate_buffer(block_size).await;
2506        buffer.fill(0xaf);
2507        object
2508            .write_or_append(Some(block_size as u64), buffer.as_ref())
2509            .await
2510            .expect("write failed");
2511        object.truncate(3 * block_size as u64).await.expect("truncate failed");
2512        object2
2513            .write_or_append(Some(block_size as u64), ef_buffer.as_ref())
2514            .await
2515            .expect("write failed");
2516
2517        let mut buffer = object.allocate_buffer(4 * block_size).await;
2518        buffer.fill(123);
2519        assert_eq!(
2520            object.read_aligned(0, buffer.as_mut()).await.expect("read failed"),
2521            3 * block_size
2522        );
2523        assert_eq!(
2524            &buffer.as_ptr_slice().subslice(0..2 * block_size).to_vec()[..],
2525            &vec![0xaf; 2 * block_size]
2526        );
2527        assert_eq!(
2528            &buffer.as_ptr_slice().subslice(2 * block_size..3 * block_size).to_vec()[..],
2529            &vec![0; block_size]
2530        );
2531        assert_eq!(
2532            object2.read_aligned(0, buffer.as_mut()).await.expect("read failed"),
2533            2 * block_size
2534        );
2535        assert_eq!(
2536            &buffer.as_ptr_slice().subslice(0..2 * block_size).to_vec()[..],
2537            &vec![0xef; 2 * block_size]
2538        );
2539        fs.close().await.expect("Close failed");
2540    }
2541
2542    #[fuchsia::test]
2543    async fn test_alignment() {
2544        let (fs, object) = test_filesystem_and_object().await;
2545
2546        struct AlignTest {
2547            fill: u8,
2548            object: DataObjectHandle<ObjectStore>,
2549            mirror: Vec<u8>,
2550        }
2551
2552        impl AlignTest {
2553            async fn new(object: DataObjectHandle<ObjectStore>) -> Self {
2554                let mirror =
2555                    object.read_bytes(0..object.get_size()).await.expect("read failed").into_vec();
2556                Self { fill: 0, object, mirror }
2557            }
2558
2559            // Fills |range| of self.object with a byte value (self.fill) and mirrors the same
2560            // operation to an in-memory copy of the object.
2561            // Each subsequent call bumps the value of fill.
2562            // It is expected that the object and its mirror maintain identical content.
2563            async fn test(&mut self, range: Range<u64>) {
2564                let mut buf = self.object.allocate_buffer((range.end - range.start) as usize).await;
2565                self.fill += 1;
2566                buf.fill(self.fill);
2567                self.object
2568                    .write_or_append(Some(range.start), buf.as_ref())
2569                    .await
2570                    .expect("write_or_append failed");
2571                if range.end > self.mirror.len() as u64 {
2572                    self.mirror.resize(range.end as usize, 0);
2573                }
2574                self.mirror[range.start as usize..range.end as usize].fill(self.fill);
2575                let data = self
2576                    .object
2577                    .read_bytes(0..self.mirror.len() as u64 + 1)
2578                    .await
2579                    .expect("read failed");
2580                assert_eq!(&data[..], self.mirror.as_slice());
2581            }
2582        }
2583
2584        let block_size = object.block_size().get();
2585        let mut align = AlignTest::new(object).await;
2586
2587        // Fill the object to start with (with 1).
2588        align.test(0..2 * block_size + 1).await;
2589
2590        // Unaligned head (fills with 2, overwrites that with 3).
2591        align.test(1..block_size).await;
2592        align.test(1..2 * block_size).await;
2593
2594        // Unaligned tail (fills with 4 and 5).
2595        align.test(0..block_size - 1).await;
2596        align.test(0..2 * block_size - 1).await;
2597
2598        // Both unaligned (fills with 6 and 7).
2599        align.test(1..block_size - 1).await;
2600        align.test(1..2 * block_size - 1).await;
2601
2602        fs.close().await.expect("Close failed");
2603    }
2604
2605    #[fuchsia::test]
2606    async fn test_read_bytes_chunked() {
2607        // 16MiB device size.
2608        let device = DeviceHolder::new(FakeDevice::new(32768, TEST_DEVICE_BLOCK_SIZE));
2609        let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
2610        let object = create_object_with_key(fs.clone(), Some(&new_insecure_crypt()), false).await;
2611
2612        const FILE_SIZE: usize = 5 * 1024 * 1024;
2613        let mut data = vec![0u8; FILE_SIZE];
2614        for (i, byte) in data.iter_mut().enumerate() {
2615            *byte = (i % 251) as u8;
2616        }
2617
2618        const WRITE_CHUNK_SIZE: usize = 1024 * 1024;
2619        let mut buf = object.allocate_buffer(WRITE_CHUNK_SIZE).await;
2620        for chunk in (0..FILE_SIZE).step_by(WRITE_CHUNK_SIZE) {
2621            let end = std::cmp::min(chunk + WRITE_CHUNK_SIZE, FILE_SIZE);
2622            buf.subslice_mut(..end - chunk).copy_from_slice(&data[chunk..end]);
2623            object
2624                .write_or_append(Some(chunk as u64), buf.subslice(..end - chunk))
2625                .await
2626                .expect("write failed");
2627        }
2628
2629        // Read full file (> 2 MiB, requires multiple 2 MiB chunks).
2630        let read_data = object.read_bytes(0..FILE_SIZE as u64).await.expect("read_bytes failed");
2631        assert_eq!(&read_data[..], &data[..]);
2632
2633        // Read an unaligned range that spans multiple 2 MiB chunks.
2634        let range = 123_456..4_718_592;
2635        let read_data = object.read_bytes(range.clone()).await.expect("read_bytes failed");
2636        assert_eq!(&read_data[..], &data[range.start as usize..range.end as usize]);
2637
2638        // Read an unaligned range that straddles the 2 MiB boundary.
2639        let range = (2 * 1024 * 1024 - 500)..(2 * 1024 * 1024 + 500);
2640        let read_data = object.read_bytes(range.clone()).await.expect("read_bytes failed");
2641        assert_eq!(&read_data[..], &data[range.start as usize..range.end as usize]);
2642
2643        // Read past EOF.
2644        let range = (FILE_SIZE as u64 - 100)..(FILE_SIZE as u64 + 1000);
2645        let read_data = object.read_bytes(range).await.expect("read_bytes failed");
2646        assert_eq!(&read_data[..], &data[(FILE_SIZE - 100)..]);
2647
2648        // Read entirely past EOF.
2649        let range = (FILE_SIZE as u64 + 10)..(FILE_SIZE as u64 + 100);
2650        let read_data = object.read_bytes(range).await.expect("read_bytes failed");
2651        assert!(read_data.is_empty());
2652
2653        // Test contents() method.
2654        assert!(object.contents(FILE_SIZE - 1).await.is_err());
2655        let contents = object.contents(usize::MAX).await.expect("contents failed");
2656        assert_eq!(&contents[..], &data[..]);
2657
2658        // Test read_bytes with empty ranges.
2659        let empty = object.read_bytes(0..0).await.expect("read_bytes failed");
2660        assert!(empty.is_empty());
2661        let empty = object.read_bytes(100..100).await.expect("read_bytes failed");
2662        assert!(empty.is_empty());
2663
2664        fs.close().await.expect("Close failed");
2665    }
2666
2667    async fn test_preallocate_common(fs: &FxFilesystem, object: DataObjectHandle<ObjectStore>) {
2668        let allocator = fs.allocator();
2669        let allocated_before = allocator.get_allocated_bytes();
2670        let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2671        object
2672            .preallocate_range(&mut transaction, &mut (0..fs.block_size().get()))
2673            .await
2674            .expect("preallocate_range failed");
2675        transaction.commit().await.expect("commit failed");
2676        assert!(object.get_size() < 1048576);
2677        let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2678        object
2679            .preallocate_range(&mut transaction, &mut (0..1048576))
2680            .await
2681            .expect("preallocate_range failed");
2682        transaction.commit().await.expect("commit failed");
2683        assert_eq!(object.get_size(), 1048576);
2684        // Check that it didn't reallocate the space for the existing extent
2685        let allocated_after = allocator.get_allocated_bytes();
2686        assert_eq!(allocated_after - allocated_before, 1048576 - fs.block_size());
2687
2688        let mut buf = object
2689            .allocate_buffer(fs.block_size().align_up(TEST_DATA_OFFSET).unwrap() as usize)
2690            .await;
2691        buf.fill(47);
2692        object
2693            .write_or_append(Some(0), buf.subslice(0..TEST_DATA_OFFSET as usize))
2694            .await
2695            .expect("write failed");
2696        buf.fill(95);
2697        let offset = fs.block_size().align_up(TEST_OBJECT_SIZE).unwrap();
2698        object
2699            .overwrite(offset, buf.as_mut(), OverwriteOptions::default())
2700            .await
2701            .expect("write failed");
2702
2703        // Make sure there were no more allocations.
2704        assert_eq!(allocator.get_allocated_bytes(), allocated_after);
2705
2706        // Read back the data and make sure it is what we expect.
2707        let mut buf = object.allocate_buffer(1048576).await;
2708        assert_eq!(object.read_aligned(0, buf.as_mut()).await.expect("read failed"), buf.len());
2709        assert_eq!(
2710            &buf.as_ptr_slice().subslice(0..TEST_DATA_OFFSET as usize).to_vec()[..],
2711            &[47; TEST_DATA_OFFSET as usize]
2712        );
2713        assert_eq!(
2714            &buf.as_ptr_slice()
2715                .subslice(TEST_DATA_OFFSET as usize..TEST_DATA_OFFSET as usize + TEST_DATA.len())
2716                .to_vec()[..],
2717            TEST_DATA
2718        );
2719        assert_eq!(
2720            &buf.as_ptr_slice().subslice(offset as usize..offset as usize + 2048).to_vec()[..],
2721            &[95; 2048]
2722        );
2723    }
2724
2725    #[fuchsia::test]
2726    async fn test_unaligned_overwrite_returns_error() {
2727        let (fs, object) = test_filesystem_and_object().await;
2728        let mut buf = object.allocate_buffer(100).await;
2729        let res = object.overwrite(0, buf.as_mut(), OverwriteOptions::default()).await;
2730        assert!(matches!(res, Err(e) if FxfsError::InvalidArgs.matches(&e)));
2731        fs.close().await.expect("Close failed");
2732    }
2733
2734    #[fuchsia::test]
2735    async fn test_unaligned_preallocate_returns_error() {
2736        let (fs, object) = test_filesystem_and_object().await;
2737        let mut transaction = fs
2738            .root_store()
2739            .new_transaction(lock_keys![], Options::default())
2740            .await
2741            .expect("new failed");
2742        let res = object.preallocate_range(&mut transaction, &mut (0..100)).await;
2743        assert!(matches!(res, Err(e) if FxfsError::InvalidArgs.matches(&e)));
2744        fs.close().await.expect("Close failed");
2745    }
2746
2747    #[fuchsia::test]
2748    async fn test_encrypted_preallocate_returns_error() {
2749        let (fs, object) = test_filesystem_and_object().await;
2750        let mut transaction = fs
2751            .root_store()
2752            .new_transaction(lock_keys![], Options::default())
2753            .await
2754            .expect("new failed");
2755        let bs = fs.block_size();
2756        let res = object.preallocate_range(&mut transaction, &mut (0..bs.get())).await;
2757        assert!(matches!(res, Err(e) if FxfsError::NotSupported.matches(&e)));
2758        fs.close().await.expect("Close failed");
2759    }
2760
2761    #[fuchsia::test]
2762    async fn test_preallocate_range() {
2763        let (fs, object) = test_filesystem_and_object_with_key(None, true).await;
2764        test_preallocate_common(&fs, object).await;
2765        fs.close().await.expect("Close failed");
2766    }
2767
2768    // This is identical to the previous test except that we flush so that extents end up in
2769    // different layers.
2770    #[fuchsia::test]
2771    async fn test_preallocate_succeeds_when_extents_are_in_different_layers() {
2772        let (fs, object) = test_filesystem_and_object_with_key(None, true).await;
2773        object.owner().flush().await.expect("flush failed");
2774        test_preallocate_common(&fs, object).await;
2775        fs.close().await.expect("Close failed");
2776    }
2777
2778    #[fuchsia::test]
2779    async fn test_already_preallocated() {
2780        let (fs, object) = test_filesystem_and_object_with_key(None, true).await;
2781        let allocator = fs.allocator();
2782        let allocated_before = allocator.get_allocated_bytes();
2783        let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2784        let offset = fs.block_size().align_down(TEST_DATA_OFFSET);
2785        object
2786            .preallocate_range(&mut transaction, &mut (offset..offset + fs.block_size()))
2787            .await
2788            .expect("preallocate_range failed");
2789        transaction.commit().await.expect("commit failed");
2790        // Check that it didn't reallocate any new space.
2791        assert_eq!(allocator.get_allocated_bytes(), allocated_before);
2792        fs.close().await.expect("Close failed");
2793    }
2794
2795    #[fuchsia::test]
2796    async fn test_overwrite_when_preallocated_at_start_of_file() {
2797        // The standard test data we put in the test object would cause an extent with checksums
2798        // to be created, which overwrite() doesn't support. So we create an empty object instead.
2799        let (fs, object) = test_filesystem_and_empty_object().await;
2800
2801        let object = ObjectStore::open_object(
2802            object.owner(),
2803            object.object_id(),
2804            HandleOptions::default(),
2805            None,
2806        )
2807        .await
2808        .expect("open_object failed");
2809
2810        assert_eq!(fs.block_size(), 4096);
2811
2812        let mut write_buf = object.allocate_buffer(4096).await;
2813        write_buf.fill(95);
2814
2815        // First try to overwrite without allowing allocations
2816        // We expect this to fail, since nothing is allocated yet
2817        object
2818            .overwrite(0, write_buf.as_mut(), OverwriteOptions::default())
2819            .await
2820            .expect_err("overwrite succeeded");
2821
2822        // Now preallocate some space (exactly one block)
2823        let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2824        object
2825            .preallocate_range(&mut transaction, &mut (0..4096 as u64))
2826            .await
2827            .expect("preallocate_range failed");
2828        transaction.commit().await.expect("commit failed");
2829
2830        // Now try the same overwrite command as before, it should work this time,
2831        // even with allocations disabled...
2832        {
2833            let mut read_buf = object.allocate_buffer(4096).await;
2834            object.read_aligned(0, read_buf.as_mut()).await.expect("read failed");
2835            assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2836        }
2837        object
2838            .overwrite(0, write_buf.as_mut(), OverwriteOptions::default())
2839            .await
2840            .expect("overwrite failed");
2841        {
2842            let mut read_buf = object.allocate_buffer(4096).await;
2843            object.read_aligned(0, read_buf.as_mut()).await.expect("read failed");
2844            assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2845        }
2846
2847        // Now try to overwrite at offset 4096. We expect this to fail, since we only preallocated
2848        // one block earlier at offset 0
2849        object
2850            .overwrite(4096, write_buf.as_mut(), OverwriteOptions::default())
2851            .await
2852            .expect_err("overwrite succeeded");
2853
2854        // We can't assert anything about the existing bytes, because they haven't been allocated
2855        // yet and they could contain any values
2856        object
2857            .overwrite(
2858                4096,
2859                write_buf.as_mut(),
2860                OverwriteOptions { allow_allocations: true, ..Default::default() },
2861            )
2862            .await
2863            .expect("overwrite failed");
2864        {
2865            let mut read_buf = object.allocate_buffer(4096).await;
2866            object.read_aligned(4096, read_buf.as_mut()).await.expect("read failed");
2867            assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2868        }
2869
2870        // Check that the overwrites haven't messed up the filesystem state
2871        let fsck_options = FsckOptions {
2872            fail_on_warning: true,
2873            no_lock: true,
2874            on_error: Box::new(|err| println!("fsck error: {:?}", err)),
2875            ..Default::default()
2876        };
2877        fsck_with_options(fs.clone(), &fsck_options).await.expect("fsck failed");
2878
2879        fs.close().await.expect("Close failed");
2880    }
2881
2882    #[fuchsia::test]
2883    async fn test_overwrite_large_buffer_and_file_with_many_holes() {
2884        // The standard test data we put in the test object would cause an extent with checksums
2885        // to be created, which overwrite() doesn't support. So we create an empty object instead.
2886        let (fs, object) = test_filesystem_and_empty_object().await;
2887
2888        let object = ObjectStore::open_object(
2889            object.owner(),
2890            object.object_id(),
2891            HandleOptions::default(),
2892            None,
2893        )
2894        .await
2895        .expect("open_object failed");
2896
2897        assert_eq!(fs.block_size(), 4096);
2898        assert_eq!(object.get_size(), TEST_OBJECT_SIZE);
2899
2900        // Let's create some non-holes
2901        let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2902        object
2903            .preallocate_range(&mut transaction, &mut (4096..8192 as u64))
2904            .await
2905            .expect("preallocate_range failed");
2906        object
2907            .preallocate_range(&mut transaction, &mut (16384..32768 as u64))
2908            .await
2909            .expect("preallocate_range failed");
2910        object
2911            .preallocate_range(&mut transaction, &mut (65536..131072 as u64))
2912            .await
2913            .expect("preallocate_range failed");
2914        object
2915            .preallocate_range(&mut transaction, &mut (262144..524288 as u64))
2916            .await
2917            .expect("preallocate_range failed");
2918        transaction.commit().await.expect("commit failed");
2919
2920        assert_eq!(object.get_size(), 524288);
2921
2922        let mut write_buf = object.allocate_buffer(4096).await;
2923        write_buf.fill(95);
2924
2925        // We shouldn't be able to overwrite in the holes if new allocations aren't enabled
2926        object
2927            .overwrite(0, write_buf.as_mut(), OverwriteOptions::default())
2928            .await
2929            .expect_err("overwrite succeeded");
2930        object
2931            .overwrite(8192, write_buf.as_mut(), OverwriteOptions::default())
2932            .await
2933            .expect_err("overwrite succeeded");
2934        object
2935            .overwrite(32768, write_buf.as_mut(), OverwriteOptions::default())
2936            .await
2937            .expect_err("overwrite succeeded");
2938        object
2939            .overwrite(131072, write_buf.as_mut(), OverwriteOptions::default())
2940            .await
2941            .expect_err("overwrite succeeded");
2942
2943        // But we should be able to overwrite in the prealloc'd areas without needing allocations
2944        {
2945            let mut read_buf = object.allocate_buffer(4096).await;
2946            object.read_aligned(4096, read_buf.as_mut()).await.expect("read failed");
2947            assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2948        }
2949        object
2950            .overwrite(4096, write_buf.as_mut(), OverwriteOptions::default())
2951            .await
2952            .expect("overwrite failed");
2953        {
2954            let mut read_buf = object.allocate_buffer(4096).await;
2955            object.read_aligned(4096, read_buf.as_mut()).await.expect("read failed");
2956            assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2957        }
2958        {
2959            let mut read_buf = object.allocate_buffer(4096).await;
2960            object.read_aligned(16384, read_buf.as_mut()).await.expect("read failed");
2961            assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2962        }
2963        object
2964            .overwrite(16384, write_buf.as_mut(), OverwriteOptions::default())
2965            .await
2966            .expect("overwrite failed");
2967        {
2968            let mut read_buf = object.allocate_buffer(4096).await;
2969            object.read_aligned(16384, read_buf.as_mut()).await.expect("read failed");
2970            assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2971        }
2972        {
2973            let mut read_buf = object.allocate_buffer(4096).await;
2974            object.read_aligned(65536, read_buf.as_mut()).await.expect("read failed");
2975            assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2976        }
2977        object
2978            .overwrite(65536, write_buf.as_mut(), OverwriteOptions::default())
2979            .await
2980            .expect("overwrite failed");
2981        {
2982            let mut read_buf = object.allocate_buffer(4096).await;
2983            object.read_aligned(65536, read_buf.as_mut()).await.expect("read failed");
2984            assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2985        }
2986        {
2987            let mut read_buf = object.allocate_buffer(4096).await;
2988            object.read_aligned(262144, read_buf.as_mut()).await.expect("read failed");
2989            assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2990        }
2991        object
2992            .overwrite(262144, write_buf.as_mut(), OverwriteOptions::default())
2993            .await
2994            .expect("overwrite failed");
2995        {
2996            let mut read_buf = object.allocate_buffer(4096).await;
2997            object.read_aligned(262144, read_buf.as_mut()).await.expect("read failed");
2998            assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2999        }
3000
3001        // Now let's try to do a huge overwrite, that spans over many holes and non-holes
3002        let mut huge_write_buf = object.allocate_buffer(524288).await;
3003        huge_write_buf.fill(96);
3004
3005        // With allocations disabled, the big overwrite should fail...
3006        object
3007            .overwrite(0, huge_write_buf.as_mut(), OverwriteOptions::default())
3008            .await
3009            .expect_err("overwrite succeeded");
3010        // ... but it should work when allocations are enabled
3011        object
3012            .overwrite(
3013                0,
3014                huge_write_buf.as_mut(),
3015                OverwriteOptions { allow_allocations: true, ..Default::default() },
3016            )
3017            .await
3018            .expect("overwrite failed");
3019        {
3020            let mut read_buf = object.allocate_buffer(524288).await;
3021            object.read_aligned(0, read_buf.as_mut()).await.expect("read failed");
3022            assert_eq!(&read_buf.to_vec()[..], &[96; 524288]);
3023        }
3024
3025        // Check that the overwrites haven't messed up the filesystem state
3026        let fsck_options = FsckOptions {
3027            fail_on_warning: true,
3028            no_lock: true,
3029            on_error: Box::new(|err| println!("fsck error: {:?}", err)),
3030            ..Default::default()
3031        };
3032        fsck_with_options(fs.clone(), &fsck_options).await.expect("fsck failed");
3033
3034        fs.close().await.expect("Close failed");
3035    }
3036
3037    #[fuchsia::test]
3038    async fn test_overwrite_when_unallocated_at_start_of_file() {
3039        // The standard test data we put in the test object would cause an extent with checksums
3040        // to be created, which overwrite() doesn't support. So we create an empty object instead.
3041        let (fs, object) = test_filesystem_and_empty_object().await;
3042
3043        let object = ObjectStore::open_object(
3044            object.owner(),
3045            object.object_id(),
3046            HandleOptions::default(),
3047            None,
3048        )
3049        .await
3050        .expect("open_object failed");
3051
3052        assert_eq!(fs.block_size(), 4096);
3053
3054        let mut write_buf = object.allocate_buffer(4096).await;
3055        write_buf.fill(95);
3056
3057        // First try to overwrite without allowing allocations
3058        // We expect this to fail, since nothing is allocated yet
3059        object
3060            .overwrite(0, write_buf.as_mut(), OverwriteOptions::default())
3061            .await
3062            .expect_err("overwrite succeeded");
3063
3064        // Now try the same overwrite command as before, but allow allocations
3065        object
3066            .overwrite(
3067                0,
3068                write_buf.as_mut(),
3069                OverwriteOptions { allow_allocations: true, ..Default::default() },
3070            )
3071            .await
3072            .expect("overwrite failed");
3073        {
3074            let mut read_buf = object.allocate_buffer(4096).await;
3075            object.read_aligned(0, read_buf.as_mut()).await.expect("read failed");
3076            assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
3077        }
3078
3079        // Now try to overwrite at the next block. This should fail if allocations are disabled
3080        object
3081            .overwrite(4096, write_buf.as_mut(), OverwriteOptions::default())
3082            .await
3083            .expect_err("overwrite succeeded");
3084
3085        // ... but it should work if allocations are enabled
3086        object
3087            .overwrite(
3088                4096,
3089                write_buf.as_mut(),
3090                OverwriteOptions { allow_allocations: true, ..Default::default() },
3091            )
3092            .await
3093            .expect("overwrite failed");
3094        {
3095            let mut read_buf = object.allocate_buffer(4096).await;
3096            object.read_aligned(4096, read_buf.as_mut()).await.expect("read failed");
3097            assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
3098        }
3099
3100        // Check that the overwrites haven't messed up the filesystem state
3101        let fsck_options = FsckOptions {
3102            fail_on_warning: true,
3103            no_lock: true,
3104            on_error: Box::new(|err| println!("fsck error: {:?}", err)),
3105            ..Default::default()
3106        };
3107        fsck_with_options(fs.clone(), &fsck_options).await.expect("fsck failed");
3108
3109        fs.close().await.expect("Close failed");
3110    }
3111
3112    #[fuchsia::test]
3113    async fn test_overwrite_can_extend_a_file() {
3114        // The standard test data we put in the test object would cause an extent with checksums
3115        // to be created, which overwrite() doesn't support. So we create an empty object instead.
3116        let (fs, object) = test_filesystem_and_empty_object().await;
3117
3118        let object = ObjectStore::open_object(
3119            object.owner(),
3120            object.object_id(),
3121            HandleOptions::default(),
3122            None,
3123        )
3124        .await
3125        .expect("open_object failed");
3126
3127        assert_eq!(fs.block_size(), 4096);
3128        assert_eq!(object.get_size(), TEST_OBJECT_SIZE);
3129
3130        let mut write_buf = object.allocate_buffer(4096).await;
3131        write_buf.fill(95);
3132
3133        // Let's try to fill up the last block, and increase the file size in doing so
3134        let last_block_offset = round_down(TEST_OBJECT_SIZE, 4096 as u32);
3135
3136        // Expected to fail with allocations disabled
3137        object
3138            .overwrite(last_block_offset, write_buf.as_mut(), OverwriteOptions::default())
3139            .await
3140            .expect_err("overwrite succeeded");
3141        // ... but expected to succeed with allocations enabled
3142        object
3143            .overwrite(
3144                last_block_offset,
3145                write_buf.as_mut(),
3146                OverwriteOptions { allow_allocations: true, ..Default::default() },
3147            )
3148            .await
3149            .expect("overwrite failed");
3150        {
3151            let mut read_buf = object.allocate_buffer(4096).await;
3152            object.read_aligned(last_block_offset, read_buf.as_mut()).await.expect("read failed");
3153            assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
3154        }
3155
3156        assert_eq!(object.get_size(), 8192);
3157
3158        // Let's try to write at the next block, too
3159        let next_block_offset = round_up(TEST_OBJECT_SIZE, 4096 as u32).unwrap();
3160
3161        // Expected to fail with allocations disabled
3162        object
3163            .overwrite(next_block_offset, write_buf.as_mut(), OverwriteOptions::default())
3164            .await
3165            .expect_err("overwrite succeeded");
3166        // ... but expected to succeed with allocations enabled
3167        object
3168            .overwrite(
3169                next_block_offset,
3170                write_buf.as_mut(),
3171                OverwriteOptions { allow_allocations: true, ..Default::default() },
3172            )
3173            .await
3174            .expect("overwrite failed");
3175        {
3176            let mut read_buf = object.allocate_buffer(4096).await;
3177            object.read_aligned(next_block_offset, read_buf.as_mut()).await.expect("read failed");
3178            assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
3179        }
3180
3181        assert_eq!(object.get_size(), 12288);
3182
3183        // Check that the overwrites haven't messed up the filesystem state
3184        let fsck_options = FsckOptions {
3185            fail_on_warning: true,
3186            no_lock: true,
3187            on_error: Box::new(|err| println!("fsck error: {:?}", err)),
3188            ..Default::default()
3189        };
3190        fsck_with_options(fs.clone(), &fsck_options).await.expect("fsck failed");
3191
3192        fs.close().await.expect("Close failed");
3193    }
3194
3195    #[fuchsia::test]
3196    async fn test_enable_verity() {
3197        let fs: OpenFxFilesystem = test_filesystem().await;
3198        let mut transaction = fs
3199            .root_store()
3200            .new_transaction(lock_keys![], Options::default())
3201            .await
3202            .expect("new_transaction failed");
3203        let store = fs.root_store();
3204        let object = Arc::new(
3205            ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3206                .await
3207                .expect("create_object failed"),
3208        );
3209
3210        transaction.commit().await.unwrap();
3211
3212        object
3213            .enable_verity(fio::VerificationOptions {
3214                hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3215                salt: Some(vec![]),
3216                ..Default::default()
3217            })
3218            .await
3219            .expect("set verified file metadata failed");
3220
3221        let handle =
3222            ObjectStore::open_object(&store, object.object_id(), HandleOptions::default(), None)
3223                .await
3224                .expect("open_object failed");
3225
3226        assert!(handle.is_verified_file());
3227
3228        fs.close().await.expect("Close failed");
3229    }
3230
3231    #[fuchsia::test]
3232    async fn test_enable_verity_large_file() {
3233        // Need to make a large FakeDevice to create space for a 67 MB file.
3234        let device = DeviceHolder::new(FakeDevice::new(262144, TEST_DEVICE_BLOCK_SIZE));
3235        let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
3236        let root_store = fs.root_store();
3237        let mut transaction = fs
3238            .root_store()
3239            .new_transaction(lock_keys![], Options::default())
3240            .await
3241            .expect("new_transaction failed");
3242
3243        let handle = ObjectStore::create_object(
3244            &root_store,
3245            &mut transaction,
3246            HandleOptions::default(),
3247            None,
3248        )
3249        .await
3250        .expect("failed to create object");
3251        transaction.commit().await.expect("commit failed");
3252        let mut offset = 0;
3253
3254        // Write a file big enough to trigger multiple transactions on enable_verity().
3255        let mut buf = handle.allocate_buffer(WRITE_ATTR_BATCH_SIZE).await;
3256        buf.fill(1);
3257        for _ in 0..130 {
3258            handle.write_or_append(Some(offset), buf.as_ref()).await.expect("write failed");
3259            offset += WRITE_ATTR_BATCH_SIZE as u64;
3260        }
3261
3262        handle
3263            .enable_verity(fio::VerificationOptions {
3264                hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3265                salt: Some(vec![]),
3266                ..Default::default()
3267            })
3268            .await
3269            .expect("set verified file metadata failed");
3270
3271        let mut buf = handle.allocate_buffer(WRITE_ATTR_BATCH_SIZE).await;
3272        offset = 0;
3273        for _ in 0..130 {
3274            handle
3275                .read_aligned(offset, buf.as_mut())
3276                .await
3277                .expect("verification during read should fail");
3278            assert_eq!(buf.to_vec(), &[1; WRITE_ATTR_BATCH_SIZE]);
3279            offset += WRITE_ATTR_BATCH_SIZE as u64;
3280        }
3281
3282        fsck(fs.clone()).await.expect("fsck failed");
3283        fs.close().await.expect("Close failed");
3284    }
3285
3286    #[fuchsia::test]
3287    async fn test_retry_enable_verity_on_reboot() {
3288        let device = DeviceHolder::new(FakeDevice::new(8192, TEST_DEVICE_BLOCK_SIZE));
3289        let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
3290        let root_store = fs.root_store();
3291        let mut transaction = fs
3292            .root_store()
3293            .new_transaction(lock_keys![], Options::default())
3294            .await
3295            .expect("new_transaction failed");
3296
3297        let handle = ObjectStore::create_object(
3298            &root_store,
3299            &mut transaction,
3300            HandleOptions::default(),
3301            None,
3302        )
3303        .await
3304        .expect("failed to create object");
3305        transaction.commit().await.expect("commit failed");
3306
3307        let object_id = {
3308            let mut transaction = handle.new_transaction().await.expect("new_transaction failed");
3309            transaction.add(
3310                root_store.store_object_id(),
3311                Mutation::replace_or_insert_object(
3312                    ObjectKey::graveyard_attribute_entry(
3313                        root_store.graveyard_directory_object_id(),
3314                        handle.object_id(),
3315                        AttributeId::FSVERITY_MERKLE,
3316                    ),
3317                    ObjectValue::Some,
3318                ),
3319            );
3320
3321            // This write should span three transactions. This test mimics the behavior when the
3322            // last transaction gets interrupted by a filesystem.close().
3323            handle
3324                .write_new_attr(
3325                    &mut transaction,
3326                    AttributeId::FSVERITY_MERKLE,
3327                    &vec![0; 2 * WRITE_ATTR_BATCH_SIZE],
3328                )
3329                .await
3330                .expect("failed to write merkle attribute");
3331
3332            handle.object_id()
3333            // Drop the transaction to simulate interrupting the merkle tree creation as well as to
3334            // release the transaction locks.
3335        };
3336
3337        fs.close().await.expect("failed to close filesystem");
3338        let device = fs.take_device().await;
3339        device.reopen(false);
3340
3341        let fs =
3342            FxFilesystemBuilder::new().read_only(true).open(device).await.expect("open failed");
3343        fsck(fs.clone()).await.expect("fsck failed");
3344        fs.close().await.expect("failed to close filesystem");
3345        let device = fs.take_device().await;
3346        device.reopen(false);
3347
3348        // On open, the filesystem will call initial_reap which will call queue_tombstone().
3349        let fs = FxFilesystem::open(device).await.expect("open failed");
3350        let root_store = fs.root_store();
3351        let handle =
3352            ObjectStore::open_object(&root_store, object_id, HandleOptions::default(), None)
3353                .await
3354                .expect("open_object failed");
3355        handle
3356            .enable_verity(fio::VerificationOptions {
3357                hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3358                salt: Some(vec![]),
3359                ..Default::default()
3360            })
3361            .await
3362            .expect("set verified file metadata failed");
3363
3364        // `flush` will ensure that initial reap fully processes all the graveyard entries. This
3365        // isn't strictly necessary for the test to pass (the graveyard marker was already
3366        // processed during `enable_verity`), but it does help catch bugs, such as the attribute
3367        // graveyard entry not being removed upon processing.
3368        fs.graveyard().flush().await;
3369        let merkle_data = handle
3370            .read_attr(AttributeId::FSVERITY_MERKLE)
3371            .await
3372            .expect("read_attr failed")
3373            .expect("No attr found");
3374        assert!(
3375            FsVerityDescriptor::new(&merkle_data[..], handle.block_size().get() as usize).is_ok()
3376        );
3377        fsck(fs.clone()).await.expect("fsck failed");
3378        fs.close().await.expect("Close failed");
3379    }
3380
3381    #[fuchsia::test]
3382    async fn test_verify_data_corrupt_file() {
3383        let fs: OpenFxFilesystem = test_filesystem().await;
3384        let mut transaction = fs
3385            .root_store()
3386            .new_transaction(lock_keys![], Options::default())
3387            .await
3388            .expect("new_transaction failed");
3389        let store = fs.root_store();
3390        let object = Arc::new(
3391            ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3392                .await
3393                .expect("create_object failed"),
3394        );
3395
3396        transaction.commit().await.unwrap();
3397
3398        let mut buf = object.allocate_buffer(5 * fs.block_size().get() as usize).await;
3399        buf.fill(123);
3400        object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3401
3402        object
3403            .enable_verity(fio::VerificationOptions {
3404                hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3405                salt: Some(vec![]),
3406                ..Default::default()
3407            })
3408            .await
3409            .expect("set verified file metadata failed");
3410
3411        // Change file contents and ensure verification fails
3412        buf.fill(234);
3413        object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3414        object
3415            .read_aligned(0, buf.as_mut())
3416            .await
3417            .expect_err("verification during read should fail");
3418        object
3419            .read_bytes(0..buf.len() as u64)
3420            .await
3421            .expect_err("verification during read_bytes should fail");
3422
3423        fs.close().await.expect("Close failed");
3424    }
3425
3426    // TODO(https://fxbug.dev/450398331): More tests to be added when this can support writing the
3427    // f2fs format natively. For now, relying on tests inside of the f2fs_reader to exercise more
3428    // paths.
3429    #[fuchsia::test]
3430    async fn test_parse_f2fs_verity() {
3431        let fs: OpenFxFilesystem = test_filesystem().await;
3432        let mut transaction = fs
3433            .root_store()
3434            .new_transaction(lock_keys![], Options::default())
3435            .await
3436            .expect("new_transaction failed");
3437        let store = fs.root_store();
3438        let object = Arc::new(
3439            ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3440                .await
3441                .expect("create_object failed"),
3442        );
3443
3444        transaction.commit().await.unwrap();
3445        let file_size = fs.block_size() * 2;
3446        // Write over one block to make there be leaf hashes.
3447        {
3448            let mut buf = object.allocate_buffer(file_size as usize).await;
3449            buf.fill(64);
3450            assert_eq!(
3451                object.write_or_append(None, buf.as_ref()).await.expect("Writing to file."),
3452                file_size
3453            );
3454        }
3455
3456        // Enable verity normally, then shift the type.
3457        object
3458            .enable_verity(fio::VerificationOptions {
3459                hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3460                salt: Some(vec![]),
3461                ..Default::default()
3462            })
3463            .await
3464            .expect("set verified file metadata failed");
3465        let (verity_info, root_hash) = object.get_descriptor().unwrap();
3466
3467        let mut transaction = fs
3468            .root_store()
3469            .new_transaction(
3470                lock_keys![LockKey::Object {
3471                    store_object_id: store.store_object_id(),
3472                    object_id: object.object_id()
3473                }],
3474                Options::default(),
3475            )
3476            .await
3477            .expect("new_transaction failed");
3478        transaction.add(
3479            store.store_object_id(),
3480            Mutation::replace_or_insert_object(
3481                ObjectKey::attribute(
3482                    object.object_id(),
3483                    AttributeId::DATA,
3484                    AttributeKey::Attribute,
3485                ),
3486                ObjectValue::verified_attribute(
3487                    file_size,
3488                    FsverityMetadata::F2fs(0..(fs.block_size() * 2)),
3489                ),
3490            ),
3491        );
3492        transaction.add(
3493            store.store_object_id(),
3494            Mutation::replace_or_insert_object(
3495                ObjectKey::attribute(
3496                    object.object_id(),
3497                    AttributeId::FSVERITY_MERKLE,
3498                    AttributeKey::Attribute,
3499                ),
3500                ObjectValue::attribute(fs.block_size() * 2, false),
3501            ),
3502        );
3503        {
3504            let descriptor = FsVerityDescriptorRaw::new(
3505                fio::HashAlgorithm::Sha256,
3506                fs.block_size().get(),
3507                file_size,
3508                root_hash.as_slice(),
3509                match &verity_info.salt {
3510                    Some(salt) => salt.as_slice(),
3511                    None => [0u8; 0].as_slice(),
3512                },
3513            )
3514            .expect("Creating descriptor");
3515            let mut buf = object.allocate_buffer(fs.block_size().get() as usize).await;
3516            let mut temp = vec![0u8; fs.block_size().get() as usize];
3517            descriptor.write_to_slice(&mut temp).expect("Writing descriptor to buf");
3518            buf.copy_from_slice(&temp);
3519            object
3520                .multi_write(
3521                    &mut transaction,
3522                    AttributeId::FSVERITY_MERKLE,
3523                    &[fs.block_size().get()..(fs.block_size() * 2)],
3524                    buf.as_mut(),
3525                )
3526                .await
3527                .expect("Writing descriptor");
3528        }
3529        transaction.commit().await.unwrap();
3530
3531        let handle =
3532            ObjectStore::open_object(&store, object.object_id(), HandleOptions::default(), None)
3533                .await
3534                .expect("open_object failed");
3535
3536        assert!(handle.is_verified_file());
3537
3538        let mut buf = object.allocate_buffer(file_size as usize).await;
3539        assert_eq!(
3540            handle.read_aligned(0, buf.as_mut()).await.expect("Read whole file."),
3541            file_size as usize
3542        );
3543
3544        fs.close().await.expect("Close failed");
3545    }
3546
3547    #[fuchsia::test]
3548    async fn test_verify_data_corrupt_tree() {
3549        let fs: OpenFxFilesystem = test_filesystem().await;
3550        let object_id = {
3551            let store = fs.root_store();
3552            let mut transaction = fs
3553                .root_store()
3554                .new_transaction(lock_keys![], Options::default())
3555                .await
3556                .expect("new_transaction failed");
3557            let object = Arc::new(
3558                ObjectStore::create_object(
3559                    &store,
3560                    &mut transaction,
3561                    HandleOptions::default(),
3562                    None,
3563                )
3564                .await
3565                .expect("create_object failed"),
3566            );
3567            let object_id = object.object_id();
3568
3569            transaction.commit().await.unwrap();
3570
3571            let mut buf = object.allocate_buffer(5 * fs.block_size().get() as usize).await;
3572            buf.fill(123);
3573            object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3574
3575            object
3576                .enable_verity(fio::VerificationOptions {
3577                    hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3578                    salt: Some(vec![]),
3579                    ..Default::default()
3580                })
3581                .await
3582                .expect("set verified file metadata failed");
3583            object.read_aligned(0, buf.as_mut()).await.expect("verified read");
3584
3585            // Corrupt the merkle tree before closing.
3586            let mut merkle = object
3587                .read_attr(AttributeId::FSVERITY_MERKLE)
3588                .await
3589                .unwrap()
3590                .expect("Reading merkle tree");
3591            merkle[0] = merkle[0].wrapping_add(1);
3592            object
3593                .write_attr(AttributeId::FSVERITY_MERKLE, &*merkle)
3594                .await
3595                .expect("Overwriting merkle");
3596
3597            object_id
3598        }; // Close object.
3599
3600        // Reopening the object should complain about the corrupted merkle tree.
3601        assert!(
3602            ObjectStore::open_object(&fs.root_store(), object_id, HandleOptions::default(), None)
3603                .await
3604                .is_err()
3605        );
3606        fs.close().await.expect("Close failed");
3607    }
3608
3609    #[fuchsia::test]
3610    async fn test_allocate_verity_file() {
3611        let fs: OpenFxFilesystem = test_filesystem().await;
3612        let mut transaction = fs
3613            .root_store()
3614            .new_transaction(lock_keys![], Options::default())
3615            .await
3616            .expect("new_transaction failed");
3617        let store = fs.root_store();
3618        let object = Arc::new(
3619            ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3620                .await
3621                .expect("create_object failed"),
3622        );
3623        transaction.commit().await.unwrap();
3624
3625        let mut buf = object.allocate_buffer(8192).await;
3626        buf.fill(0xAA);
3627        object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3628
3629        object
3630            .enable_verity(fio::VerificationOptions {
3631                hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3632                salt: Some(vec![]),
3633                ..Default::default()
3634            })
3635            .await
3636            .expect("enable_verity failed");
3637
3638        assert!(object.is_verified_file());
3639
3640        // Calling allocate on a verity-enabled file should return an error.
3641        assert!(object.allocate(0..8192).await.is_err());
3642
3643        // Even after opening the object again (simulating cache eviction), it must remain verified.
3644        let reopened =
3645            ObjectStore::open_object(&store, object.object_id(), HandleOptions::default(), None)
3646                .await
3647                .expect("open_object failed");
3648        assert!(reopened.is_verified_file());
3649
3650        fs.close().await.expect("Close failed");
3651    }
3652
3653    #[fuchsia::test]
3654    async fn test_extend() {
3655        let fs = test_filesystem().await;
3656        let handle;
3657        let mut transaction = fs
3658            .root_store()
3659            .new_transaction(lock_keys![], Options::default())
3660            .await
3661            .expect("new_transaction failed");
3662        let store = fs.root_store();
3663        handle =
3664            ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3665                .await
3666                .expect("create_object failed");
3667
3668        // As of writing, an empty filesystem has two 512kiB superblock extents and a little over
3669        // 256kiB of additional allocations (journal, etc) so we start use a 'magic' starting point
3670        // of 2MiB here.
3671        const START_OFFSET: u64 = 2048 * 1024;
3672        handle
3673            .extend(&mut transaction, START_OFFSET..START_OFFSET + 5 * fs.block_size())
3674            .await
3675            .expect("extend failed");
3676        transaction.commit().await.expect("commit failed");
3677        let mut buf = handle.allocate_buffer(5 * fs.block_size().get() as usize).await;
3678        buf.fill(123);
3679        handle.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3680        buf.fill(67);
3681        handle.read_aligned(0, buf.as_mut()).await.expect("read failed");
3682        assert_eq!(buf.to_vec(), vec![123; 5 * fs.block_size().get() as usize]);
3683        fs.close().await.expect("Close failed");
3684    }
3685
3686    #[fuchsia::test]
3687    async fn test_truncate_deallocates_old_extents() {
3688        let (fs, object) = test_filesystem_and_object().await;
3689        let mut buf = object.allocate_buffer(5 * fs.block_size().get() as usize).await;
3690        buf.fill(0xaa);
3691        object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3692
3693        let allocator = fs.allocator();
3694        let allocated_before = allocator.get_allocated_bytes();
3695        object.truncate(fs.block_size().get()).await.expect("truncate failed");
3696        let allocated_after = allocator.get_allocated_bytes();
3697        assert!(
3698            allocated_after < allocated_before,
3699            "before = {} after = {}",
3700            allocated_before,
3701            allocated_after
3702        );
3703        fs.close().await.expect("Close failed");
3704    }
3705
3706    #[fuchsia::test]
3707    async fn test_truncate_zeroes_tail_block() {
3708        let (fs, object) = test_filesystem_and_object().await;
3709
3710        WriteObjectHandle::truncate(&object, TEST_DATA_OFFSET + 3).await.expect("truncate failed");
3711        WriteObjectHandle::truncate(&object, TEST_DATA_OFFSET + TEST_DATA.len() as u64)
3712            .await
3713            .expect("truncate failed");
3714
3715        let mut buf = object.allocate_buffer(fs.block_size().get() as usize).await;
3716        let offset = (TEST_DATA_OFFSET % fs.block_size()) as usize;
3717        object
3718            .read_aligned(TEST_DATA_OFFSET - offset as u64, buf.as_mut())
3719            .await
3720            .expect("read failed");
3721
3722        let mut expected = TEST_DATA.to_vec();
3723        expected[3..].fill(0);
3724        assert_eq!(
3725            &buf.as_ptr_slice().subslice(offset..offset + expected.len()).to_vec()[..],
3726            &expected
3727        );
3728    }
3729
3730    #[fuchsia::test]
3731    async fn test_trim() {
3732        // Format a new filesystem.
3733        let device = DeviceHolder::new(FakeDevice::new(8192, TEST_DEVICE_BLOCK_SIZE));
3734        let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
3735        let block_size = fs.block_size();
3736        root_volume(fs.clone())
3737            .await
3738            .expect("root_volume failed")
3739            .new_volume("test", NewChildStoreOptions::default())
3740            .await
3741            .expect("volume failed");
3742        fs.close().await.expect("close failed");
3743        let device = fs.take_device().await;
3744        device.reopen(false);
3745
3746        // To test trim, we open the filesystem and set up a post commit hook that runs after every
3747        // transaction.  When the hook triggers, we can fsck the volume, take a snapshot of the
3748        // device and check that it gets replayed correctly on the snapshot.  We can check that the
3749        // graveyard trims the file as expected.
3750        #[derive(Default)]
3751        struct Context {
3752            fs: Option<Weak<FxFilesystem>>,
3753            store: Option<Arc<ObjectStore>>,
3754            object_id: Option<u64>,
3755        }
3756        let shared_context = Arc::new(Mutex::new(Context::default()));
3757
3758        let object_size = (TRANSACTION_MUTATION_THRESHOLD as u64 + 10) * 2 * block_size;
3759
3760        // Wait for an object to get tombstoned by the graveyard.
3761        async fn expect_tombstoned(store: &Arc<ObjectStore>, object_id: u64) {
3762            loop {
3763                if let Err(e) =
3764                    ObjectStore::open_object(store, object_id, HandleOptions::default(), None).await
3765                {
3766                    assert!(
3767                        FxfsError::NotFound.matches(&e),
3768                        "open_object didn't fail with NotFound: {:?}",
3769                        e
3770                    );
3771                    break;
3772                }
3773                // The graveyard should eventually tombstone the object.
3774                fasync::Timer::new(std::time::Duration::from_millis(100)).await;
3775            }
3776        }
3777
3778        // Checks to see if the object needs to be trimmed.
3779        async fn needs_trim(store: &Arc<ObjectStore>) -> Option<DataObjectHandle<ObjectStore>> {
3780            let root_directory = Directory::open(store, store.root_directory_object_id())
3781                .await
3782                .expect("open failed");
3783            let oid = root_directory.lookup("foo").await.expect("lookup failed");
3784            if let Some((oid, _, _)) = oid {
3785                let object = ObjectStore::open_object(store, oid, HandleOptions::default(), None)
3786                    .await
3787                    .expect("open_object failed");
3788                let props = object.get_properties().await.expect("get_properties failed");
3789                if props.allocated_size > 0 && props.data_attribute_size == 0 {
3790                    Some(object)
3791                } else {
3792                    None
3793                }
3794            } else {
3795                None
3796            }
3797        }
3798
3799        let shared_context_clone = shared_context.clone();
3800        let post_commit = move || {
3801            let (fs, store) = {
3802                let context = shared_context_clone.lock();
3803                (
3804                    context.fs.as_ref().unwrap().upgrade().unwrap(),
3805                    context.store.as_ref().cloned().unwrap(),
3806                )
3807            };
3808            let shared_context = shared_context_clone.clone();
3809            async move {
3810                // First run fsck on the current filesystem.
3811                let options = FsckOptions {
3812                    fail_on_warning: true,
3813                    no_lock: true,
3814                    on_error: Box::new(|err| println!("fsck error: {:?}", err)),
3815                    ..Default::default()
3816                };
3817
3818                fsck_with_options(fs.clone(), &options).await.expect("fsck_with_options failed");
3819                fsck_volume_with_options(fs.as_ref(), &options, store.store_object_id(), None)
3820                    .await
3821                    .expect("fsck_volume_with_options failed");
3822
3823                // Now check that we can replay this correctly.
3824                fs.sync(SyncOptions { flush_device: true, ..Default::default() })
3825                    .await
3826                    .expect("sync failed");
3827                let device = fs.device().snapshot().expect("snapshot failed");
3828
3829                let object_id = shared_context.lock().object_id.clone();
3830
3831                let fs2 = FxFilesystemBuilder::new()
3832                    .skip_initial_reap(object_id.is_none())
3833                    .open(device)
3834                    .await
3835                    .expect("open failed");
3836
3837                // If the "foo" file exists check that allocated size matches content size.
3838                let root_vol = root_volume(fs2.clone()).await.expect("root_volume failed");
3839                let store =
3840                    root_vol.volume("test", StoreOptions::default()).await.expect("volume failed");
3841
3842                if let Some(oid) = object_id {
3843                    // For the second pass, the object should get tombstoned.
3844                    expect_tombstoned(&store, oid).await;
3845                } else if let Some(object) = needs_trim(&store).await {
3846                    // Extend the file and make sure that it is correctly trimmed.
3847                    object.truncate(object_size).await.expect("truncate failed");
3848                    let mut buf = object.allocate_buffer(block_size.get() as usize).await;
3849                    object
3850                        .read_aligned(object_size - block_size * 2, buf.as_mut())
3851                        .await
3852                        .expect("read failed");
3853                    assert_eq!(buf.to_vec(), vec![0; block_size.get() as usize]);
3854
3855                    // Remount, this time with the graveyard performing an initial reap and the
3856                    // object should get trimmed.
3857                    let fs = FxFilesystem::open(fs.device().snapshot().expect("snapshot failed"))
3858                        .await
3859                        .expect("open failed");
3860                    let root_vol = root_volume(fs.clone()).await.expect("root_volume failed");
3861                    let store = root_vol
3862                        .volume("test", StoreOptions::default())
3863                        .await
3864                        .expect("volume failed");
3865                    while needs_trim(&store).await.is_some() {
3866                        // The object has been truncated, but still has some data allocated to
3867                        // it.  The graveyard should trim the object eventually.
3868                        fasync::Timer::new(std::time::Duration::from_millis(100)).await;
3869                    }
3870
3871                    // Run fsck.
3872                    fsck_with_options(fs.clone(), &options)
3873                        .await
3874                        .expect("fsck_with_options failed");
3875                    fsck_volume_with_options(fs.as_ref(), &options, store.store_object_id(), None)
3876                        .await
3877                        .expect("fsck_volume_with_options failed");
3878                    fs.close().await.expect("close failed");
3879                }
3880
3881                // Run fsck on fs2.
3882                fsck_with_options(fs2.clone(), &options).await.expect("fsck_with_options failed");
3883                fsck_volume_with_options(fs2.as_ref(), &options, store.store_object_id(), None)
3884                    .await
3885                    .expect("fsck_volume_with_options failed");
3886                fs2.close().await.expect("close failed");
3887            }
3888            .boxed()
3889        };
3890
3891        let fs = FxFilesystemBuilder::new()
3892            .post_commit_hook(post_commit)
3893            .open(device)
3894            .await
3895            .expect("open failed");
3896
3897        let root_vol = root_volume(fs.clone()).await.expect("root_volume failed");
3898        let store = root_vol.volume("test", StoreOptions::default()).await.expect("volume failed");
3899
3900        {
3901            let mut context = shared_context.lock();
3902            context.fs = Some(Arc::downgrade(&fs));
3903            context.store = Some(store.clone());
3904        }
3905
3906        let root_directory =
3907            Directory::open(&store, store.root_directory_object_id()).await.expect("open failed");
3908
3909        let object;
3910        let mut transaction = fs
3911            .root_store()
3912            .new_transaction(
3913                lock_keys![LockKey::object(
3914                    store.store_object_id(),
3915                    store.root_directory_object_id()
3916                )],
3917                Options::default(),
3918            )
3919            .await
3920            .expect("new_transaction failed");
3921        object = root_directory
3922            .create_child_file(&mut transaction, "foo")
3923            .await
3924            .expect("create_object failed");
3925        transaction.commit().await.expect("commit failed");
3926
3927        let mut transaction = fs
3928            .root_store()
3929            .new_transaction(
3930                lock_keys![LockKey::object(store.store_object_id(), object.object_id())],
3931                Options::default(),
3932            )
3933            .await
3934            .expect("new_transaction failed");
3935
3936        // Two passes: first with a regular object, and then with that object moved into the
3937        // graveyard.
3938        let mut pass = 0;
3939        loop {
3940            // Create enough extents in it such that when we truncate the object it will require
3941            // more than one transaction.
3942            let mut buf = object.allocate_buffer(5).await;
3943            buf.fill(1);
3944            // Write every other block.
3945            for offset in (0..object_size).into_iter().step_by((2 * block_size) as usize) {
3946                object
3947                    .txn_write(&mut transaction, offset, buf.as_ref())
3948                    .await
3949                    .expect("write failed");
3950            }
3951            transaction.commit().await.expect("commit failed");
3952            // This should take up more than one transaction.
3953            WriteObjectHandle::truncate(&object, 0).await.expect("truncate failed");
3954
3955            if pass == 1 {
3956                break;
3957            }
3958
3959            // Store the object ID so that we can make sure the object is always tombstoned
3960            // after remount (see above).
3961            shared_context.lock().object_id = Some(object.object_id());
3962
3963            transaction = fs
3964                .root_store()
3965                .new_transaction(
3966                    lock_keys![
3967                        LockKey::object(store.store_object_id(), store.root_directory_object_id()),
3968                        LockKey::object(store.store_object_id(), object.object_id()),
3969                    ],
3970                    Options::default(),
3971                )
3972                .await
3973                .expect("new_transaction failed");
3974
3975            // Move the object into the graveyard.
3976            replace_child(&mut transaction, None, (&root_directory, "foo"))
3977                .await
3978                .expect("replace_child failed");
3979            store.add_to_graveyard(&mut transaction, object.object_id());
3980
3981            pass += 1;
3982        }
3983
3984        fs.close().await.expect("Close failed");
3985    }
3986
3987    #[fuchsia::test]
3988    async fn test_adjust_refs() {
3989        let (fs, object) = test_filesystem_and_object().await;
3990        let store = object.owner();
3991        let mut transaction = fs
3992            .root_store()
3993            .new_transaction(
3994                lock_keys![LockKey::object(store.store_object_id(), object.object_id())],
3995                Options::default(),
3996            )
3997            .await
3998            .expect("new_transaction failed");
3999        assert_eq!(
4000            store
4001                .adjust_refs(&mut transaction, object.object_id(), 1)
4002                .await
4003                .expect("adjust_refs failed"),
4004            false
4005        );
4006        transaction.commit().await.expect("commit failed");
4007
4008        let allocator = fs.allocator();
4009        let allocated_before = allocator.get_allocated_bytes();
4010        let mut transaction = fs
4011            .root_store()
4012            .new_transaction(
4013                lock_keys![LockKey::object(store.store_object_id(), object.object_id())],
4014                Options::default(),
4015            )
4016            .await
4017            .expect("new_transaction failed");
4018        assert_eq!(
4019            store
4020                .adjust_refs(&mut transaction, object.object_id(), -2)
4021                .await
4022                .expect("adjust_refs failed"),
4023            true
4024        );
4025        transaction.commit().await.expect("commit failed");
4026
4027        assert_eq!(allocator.get_allocated_bytes(), allocated_before);
4028
4029        store
4030            .tombstone_object(object.object_id(), Options::default(), None)
4031            .await
4032            .expect("purge failed");
4033
4034        assert_eq!(allocated_before - allocator.get_allocated_bytes(), fs.block_size());
4035
4036        // We need to remove the directory entry, too, otherwise fsck will complain
4037        {
4038            let mut transaction = fs
4039                .root_store()
4040                .new_transaction(
4041                    lock_keys![LockKey::object(
4042                        store.store_object_id(),
4043                        store.root_directory_object_id()
4044                    )],
4045                    Options::default(),
4046                )
4047                .await
4048                .expect("new_transaction failed");
4049            let root_directory = Directory::open(&store, store.root_directory_object_id())
4050                .await
4051                .expect("open failed");
4052            transaction.add(
4053                store.store_object_id(),
4054                Mutation::replace_or_insert_object(
4055                    ObjectKey::child(root_directory.object_id(), TEST_OBJECT_NAME, DirType::Normal),
4056                    ObjectValue::None,
4057                ),
4058            );
4059            transaction.commit().await.expect("commit failed");
4060        }
4061
4062        fsck_with_options(
4063            fs.clone(),
4064            &FsckOptions {
4065                fail_on_warning: true,
4066                on_error: Box::new(|err| println!("fsck error: {:?}", err)),
4067                ..Default::default()
4068            },
4069        )
4070        .await
4071        .expect("fsck_with_options failed");
4072
4073        fs.close().await.expect("Close failed");
4074    }
4075
4076    #[fuchsia::test]
4077    async fn test_locks() {
4078        let (fs, object) = test_filesystem_and_object().await;
4079        let (send1, recv1) = channel();
4080        let (send2, recv2) = channel();
4081        let (send3, recv3) = channel();
4082        let done = Mutex::new(false);
4083        let mut futures = FuturesUnordered::new();
4084        futures.push(
4085            async {
4086                let mut t = object.new_transaction().await.expect("new_transaction failed");
4087                send1.send(()).unwrap(); // Tell the next future to continue.
4088                send3.send(()).unwrap(); // Tell the last future to continue.
4089                recv2.await.unwrap();
4090                let mut buf = object.allocate_buffer(5).await;
4091                buf.copy_from_slice(b"hello");
4092                object.txn_write(&mut t, 0, buf.as_ref()).await.expect("write failed");
4093                // This is a halting problem so all we can do is sleep.
4094                fasync::Timer::new(Duration::from_millis(100)).await;
4095                assert!(!*done.lock());
4096                t.commit().await.expect("commit failed");
4097            }
4098            .boxed(),
4099        );
4100        futures.push(
4101            async {
4102                recv1.await.unwrap();
4103                // Reads should not block.
4104                let data = object
4105                    .read_bytes(TEST_DATA_OFFSET..(TEST_DATA_OFFSET + TEST_DATA.len() as u64))
4106                    .await
4107                    .expect("read failed");
4108                assert_eq!(&*data, TEST_DATA);
4109                // Tell the first future to continue.
4110                send2.send(()).unwrap();
4111            }
4112            .boxed(),
4113        );
4114        futures.push(
4115            async {
4116                // This should block until the first future has completed.
4117                recv3.await.unwrap();
4118                let _t = object.new_transaction().await.expect("new_transaction failed");
4119                let data = object.read_bytes(0..5).await.expect("read failed");
4120                assert_eq!(&*data, b"hello");
4121            }
4122            .boxed(),
4123        );
4124        while let Some(()) = futures.next().await {}
4125        fs.close().await.expect("Close failed");
4126    }
4127
4128    #[fuchsia::test(threads = 10)]
4129    async fn test_racy_reads() {
4130        let fs = test_filesystem().await;
4131        let object;
4132        let mut transaction = fs
4133            .root_store()
4134            .new_transaction(lock_keys![], Options::default())
4135            .await
4136            .expect("new_transaction failed");
4137        let store = fs.root_store();
4138        object = Arc::new(
4139            ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
4140                .await
4141                .expect("create_object failed"),
4142        );
4143        transaction.commit().await.expect("commit failed");
4144        for _ in 0..100 {
4145            let cloned_object = object.clone();
4146            let writer = fasync::Task::spawn(async move {
4147                let mut buf = cloned_object.allocate_buffer(10).await;
4148                buf.fill(123);
4149                cloned_object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
4150            });
4151            let cloned_object = object.clone();
4152            let reader = fasync::Task::spawn(async move {
4153                let wait_time = rand::random_range(0..5);
4154                fasync::Timer::new(Duration::from_millis(wait_time)).await;
4155                let mut buf =
4156                    cloned_object.allocate_buffer(cloned_object.block_size().get() as usize).await;
4157                buf.fill(23);
4158                let amount =
4159                    cloned_object.read_aligned(0, buf.as_mut()).await.expect("read failed");
4160                // If we succeed in reading data, it must include the write; i.e. if we see the size
4161                // change, we should see the data too.  For this to succeed it requires locking on
4162                // the read size to ensure that when we read the size, we get the extents changed in
4163                // that same transaction.
4164                if amount != 0 {
4165                    assert_eq!(amount, 10);
4166                    assert_eq!(&buf.as_ptr_slice().subslice(0..10).to_vec()[..], &[123; 10]);
4167                }
4168            });
4169            writer.await;
4170            reader.await;
4171            object.truncate(0).await.expect("truncate failed");
4172        }
4173        fs.close().await.expect("Close failed");
4174    }
4175
4176    #[fuchsia::test]
4177    async fn test_allocated_size() {
4178        let (fs, object) = test_filesystem_and_object_with_key(None, true).await;
4179
4180        let before = object.get_properties().await.expect("get_properties failed").allocated_size;
4181        let mut buf = object.allocate_buffer(5).await;
4182        buf.copy_from_slice(b"hello");
4183        object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
4184        let after = object.get_properties().await.expect("get_properties failed").allocated_size;
4185        assert_eq!(after, before + fs.block_size());
4186
4187        // Do the same write again and there should be no change.
4188        object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
4189        assert_eq!(
4190            object.get_properties().await.expect("get_properties failed").allocated_size,
4191            after
4192        );
4193
4194        // extend...
4195        let mut transaction = object.new_transaction().await.expect("new_transaction failed");
4196        let offset = 1000 * fs.block_size();
4197        let before = after;
4198        object
4199            .extend(&mut transaction, offset..offset + fs.block_size())
4200            .await
4201            .expect("extend failed");
4202        transaction.commit().await.expect("commit failed");
4203        let after = object.get_properties().await.expect("get_properties failed").allocated_size;
4204        assert_eq!(after, before + fs.block_size());
4205
4206        // truncate...
4207        let before = after;
4208        let size = object.get_size();
4209        object.truncate(size - fs.block_size()).await.expect("extend failed");
4210        let after = object.get_properties().await.expect("get_properties failed").allocated_size;
4211        assert_eq!(after, before - fs.block_size());
4212
4213        // preallocate_range...
4214        let mut transaction = object.new_transaction().await.expect("new_transaction failed");
4215        let before = after;
4216        let mut file_range = offset..offset + fs.block_size();
4217        object.preallocate_range(&mut transaction, &mut file_range).await.expect("extend failed");
4218        transaction.commit().await.expect("commit failed");
4219        let after = object.get_properties().await.expect("get_properties failed").allocated_size;
4220        assert_eq!(after, before + fs.block_size());
4221        fs.close().await.expect("Close failed");
4222    }
4223
4224    #[fuchsia::test(threads = 10)]
4225    async fn test_zero() {
4226        let (fs, object) = test_filesystem_and_object().await;
4227        let expected_size = object.get_size();
4228        let mut transaction = object.new_transaction().await.expect("new_transaction failed");
4229        object.zero(&mut transaction, 0..fs.block_size() * 10).await.expect("zero failed");
4230        transaction.commit().await.expect("commit failed");
4231        assert_eq!(object.get_size(), expected_size);
4232        let mut buf = object.allocate_buffer((fs.block_size() * 10) as usize).await;
4233        assert_eq!(
4234            object.read_aligned(0, buf.as_mut()).await.expect("read failed") as u64,
4235            expected_size
4236        );
4237        assert_eq!(
4238            &buf.as_ptr_slice().subslice(0..expected_size as usize).to_vec()[..],
4239            vec![0u8; expected_size as usize].as_slice()
4240        );
4241        fs.close().await.expect("Close failed");
4242    }
4243
4244    #[fuchsia::test]
4245    async fn test_properties() {
4246        let (fs, object) = test_filesystem_and_object().await;
4247        const CRTIME: Timestamp = Timestamp::from_nanos(1234);
4248        const MTIME: Timestamp = Timestamp::from_nanos(5678);
4249        const CTIME: Timestamp = Timestamp::from_nanos(8765);
4250
4251        // ObjectProperties can be updated through `update_attributes`.
4252        // `get_properties` should reflect the latest changes.
4253        let mut transaction = object.new_transaction().await.expect("new_transaction failed");
4254        object
4255            .update_attributes(
4256                &mut transaction,
4257                Some(&fio::MutableNodeAttributes {
4258                    creation_time: Some(CRTIME.as_nanos()),
4259                    modification_time: Some(MTIME.as_nanos()),
4260                    mode: Some(111),
4261                    gid: Some(222),
4262                    ..Default::default()
4263                }),
4264                None,
4265            )
4266            .await
4267            .expect("update_attributes failed");
4268        const MTIME_NEW: Timestamp = Timestamp::from_nanos(12345678);
4269        object
4270            .update_attributes(
4271                &mut transaction,
4272                Some(&fio::MutableNodeAttributes {
4273                    modification_time: Some(MTIME_NEW.as_nanos()),
4274                    gid: Some(333),
4275                    rdev: Some(444),
4276                    ..Default::default()
4277                }),
4278                Some(CTIME),
4279            )
4280            .await
4281            .expect("update_timestamps failed");
4282        transaction.commit().await.expect("commit failed");
4283
4284        let properties = object.get_properties().await.expect("get_properties failed");
4285        assert_matches!(
4286            properties,
4287            ObjectProperties {
4288                refs: 1u64,
4289                allocated_size: TEST_OBJECT_ALLOCATED_SIZE,
4290                data_attribute_size: TEST_OBJECT_SIZE,
4291                creation_time: CRTIME,
4292                modification_time: MTIME_NEW,
4293                posix_attributes: Some(PosixAttributes { mode: 111, gid: 333, rdev: 444, .. }),
4294                change_time: CTIME,
4295                ..
4296            }
4297        );
4298        fs.close().await.expect("Close failed");
4299    }
4300
4301    #[fuchsia::test]
4302    async fn test_is_allocated() {
4303        let (fs, object) = test_filesystem_and_object().await;
4304
4305        // `test_filesystem_and_object()` wrote the buffer `TEST_DATA` to the device at offset
4306        // `TEST_DATA_OFFSET` where the length and offset are aligned to the block size.
4307        let aligned_offset = fs.block_size().align_down(TEST_DATA_OFFSET);
4308        let aligned_length = fs.block_size().align_up(TEST_DATA.len() as u64).unwrap();
4309
4310        // Check for the case where where we have the following extent layout
4311        //       [ unallocated ][ `TEST_DATA` ]
4312        // The extents before `aligned_offset` should not be allocated
4313        let (allocated, count) = object.is_allocated(0).await.expect("is_allocated failed");
4314        assert_eq!(count, aligned_offset);
4315        assert_eq!(allocated, false);
4316
4317        let (allocated, count) =
4318            object.is_allocated(aligned_offset).await.expect("is_allocated failed");
4319        assert_eq!(count, aligned_length);
4320        assert_eq!(allocated, true);
4321
4322        // Check for the case where where we query out of range
4323        let end = aligned_offset + aligned_length;
4324        object
4325            .is_allocated(end)
4326            .await
4327            .expect_err("is_allocated should have returned ERR_OUT_OF_RANGE");
4328
4329        // Check for the case where where we start querying for allocation starting from
4330        // an allocated range to the end of the device
4331        let size = 50 * fs.block_size();
4332        object.truncate(size).await.expect("extend failed");
4333
4334        let (allocated, count) = object.is_allocated(end).await.expect("is_allocated failed");
4335        assert_eq!(count, size - end);
4336        assert_eq!(allocated, false);
4337
4338        // Check for the case where where we have the following extent layout
4339        //      [ unallocated ][ `buf` ][ `buf` ]
4340        let buf_length = 5 * fs.block_size();
4341        let mut buf = object.allocate_buffer(buf_length as usize).await;
4342        buf.fill(123);
4343        let new_offset = end + 20 * fs.block_size();
4344        object.write_or_append(Some(new_offset), buf.as_ref()).await.expect("write failed");
4345        object
4346            .write_or_append(Some(new_offset + buf_length), buf.as_ref())
4347            .await
4348            .expect("write failed");
4349
4350        let (allocated, count) = object.is_allocated(end).await.expect("is_allocated failed");
4351        assert_eq!(count, new_offset - end);
4352        assert_eq!(allocated, false);
4353
4354        let (allocated, count) =
4355            object.is_allocated(new_offset).await.expect("is_allocated failed");
4356        assert_eq!(count, 2 * buf_length);
4357        assert_eq!(allocated, true);
4358
4359        // Check the case where we query from the middle of an extent
4360        let (allocated, count) = object
4361            .is_allocated(new_offset + 4 * fs.block_size())
4362            .await
4363            .expect("is_allocated failed");
4364        assert_eq!(count, 2 * buf_length - 4 * fs.block_size());
4365        assert_eq!(allocated, true);
4366
4367        // Now, write buffer to a location already written to.
4368        // Check for the case when we the following extent layout
4369        //      [ unallocated ][ `other_buf` ][ (part of) `buf` ][ `buf` ]
4370        let other_buf_length = 3 * fs.block_size();
4371        let mut other_buf = object.allocate_buffer(other_buf_length as usize).await;
4372        other_buf.fill(231);
4373        object.write_or_append(Some(new_offset), other_buf.as_ref()).await.expect("write failed");
4374
4375        // We still expect that `is_allocated(..)` will return that  there are 2*`buf_length bytes`
4376        // allocated from `new_offset`
4377        let (allocated, count) =
4378            object.is_allocated(new_offset).await.expect("is_allocated failed");
4379        assert_eq!(count, 2 * buf_length);
4380        assert_eq!(allocated, true);
4381
4382        // Check for the case when we the following extent layout
4383        //   [ unallocated ][ deleted ][ unallocated ][ deleted ][ allocated ]
4384        // Mark TEST_DATA as deleted
4385        let mut transaction = object.new_transaction().await.expect("new_transaction failed");
4386        object
4387            .zero(&mut transaction, aligned_offset..aligned_offset + aligned_length)
4388            .await
4389            .expect("zero failed");
4390        // Mark `other_buf` as deleted
4391        object
4392            .zero(&mut transaction, new_offset..new_offset + buf_length)
4393            .await
4394            .expect("zero failed");
4395        transaction.commit().await.expect("commit transaction failed");
4396
4397        let (allocated, count) = object.is_allocated(0).await.expect("is_allocated failed");
4398        assert_eq!(count, new_offset + buf_length);
4399        assert_eq!(allocated, false);
4400
4401        let (allocated, count) =
4402            object.is_allocated(new_offset + buf_length).await.expect("is_allocated failed");
4403        assert_eq!(count, buf_length);
4404        assert_eq!(allocated, true);
4405
4406        let new_end = new_offset + buf_length + count;
4407
4408        // Check for the case where there are objects with different keys.
4409        // Case that we're checking for:
4410        //      [ unallocated ][ extent (object with different key) ][ unallocated ]
4411        let store = object.owner();
4412        let mut transaction = fs
4413            .root_store()
4414            .new_transaction(lock_keys![], Options::default())
4415            .await
4416            .expect("new_transaction failed");
4417        let object2 =
4418            ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
4419                .await
4420                .expect("create_object failed");
4421        transaction.commit().await.expect("commit failed");
4422
4423        object2
4424            .write_or_append(Some(new_end + fs.block_size()), buf.as_ref())
4425            .await
4426            .expect("write failed");
4427
4428        // Expecting that the extent with a different key is treated like unallocated extent
4429        let (allocated, count) = object.is_allocated(new_end).await.expect("is_allocated failed");
4430        assert_eq!(count, size - new_end);
4431        assert_eq!(allocated, false);
4432
4433        fs.close().await.expect("close failed");
4434    }
4435
4436    #[fuchsia::test(threads = 10)]
4437    async fn test_read_write_attr() {
4438        let (_fs, object) = test_filesystem_and_object().await;
4439        let data = [0xffu8; 16_384];
4440        object.write_attr(AttributeId(20), &data).await.expect("write_attr failed");
4441        let rdata = object
4442            .read_attr(AttributeId(20))
4443            .await
4444            .expect("read_attr failed")
4445            .expect("no attribute data found");
4446        assert_eq!(&data[..], &rdata[..]);
4447
4448        assert_eq!(object.read_attr(AttributeId(21)).await.expect("read_attr failed"), None);
4449    }
4450
4451    #[fuchsia::test(threads = 10)]
4452    async fn test_read_write_attr_unaligned() {
4453        let (_fs, object) = test_filesystem_and_object().await;
4454        let data_unaligned = [0x55u8; 5000];
4455        object.write_attr(AttributeId(22), &data_unaligned).await.expect("write_attr failed");
4456        let rdata = object
4457            .read_attr(AttributeId(22))
4458            .await
4459            .expect("read_attr failed")
4460            .expect("no attribute data found");
4461        assert_eq!(&data_unaligned[..], &rdata[..]);
4462    }
4463
4464    #[fuchsia::test(threads = 10)]
4465    async fn test_read_write_attr_empty() {
4466        let (_fs, object) = test_filesystem_and_object().await;
4467        object.write_attr(AttributeId(23), &[]).await.expect("write_attr failed");
4468        let rdata = object
4469            .read_attr(AttributeId(23))
4470            .await
4471            .expect("read_attr failed")
4472            .expect("no attribute data found");
4473        assert!(rdata.is_empty());
4474    }
4475
4476    #[fuchsia::test(threads = 10)]
4477    async fn test_allocate_basic() {
4478        let (fs, object) = test_filesystem_and_empty_object().await;
4479        let block_size = fs.block_size();
4480        let file_size = block_size * 10;
4481        object.truncate(file_size).await.unwrap();
4482
4483        let small_buf_size = block_size.get() as usize;
4484        let medium_buf_size = (block_size * 2) as usize;
4485        let large_buf_size = (block_size * 3) as usize;
4486
4487        let mut small_buf = object.allocate_buffer(small_buf_size).await;
4488        let mut medium_buf = object.allocate_buffer(medium_buf_size).await;
4489        let mut large_buf = object.allocate_buffer(large_buf_size).await;
4490
4491        assert_eq!(object.read_aligned(0, small_buf.as_mut()).await.unwrap(), small_buf_size);
4492        assert_eq!(small_buf.to_vec(), vec![0; small_buf_size]);
4493        assert_eq!(object.read_aligned(0, large_buf.as_mut()).await.unwrap(), large_buf_size);
4494        assert_eq!(large_buf.to_vec(), vec![0; large_buf_size]);
4495        assert_eq!(object.read_aligned(0, medium_buf.as_mut()).await.unwrap(), medium_buf_size);
4496        assert_eq!(medium_buf.to_vec(), vec![0; medium_buf_size]);
4497
4498        // Allocation succeeds, and without any writes to the location it shows up as zero.
4499        object.allocate(block_size.get()..block_size * 3).await.unwrap();
4500
4501        // Test starting before, inside, and after the allocated section with every sized buffer.
4502        for (buf_index, buf) in [small_buf, large_buf, medium_buf].iter_mut().enumerate() {
4503            for offset in 0..4 {
4504                assert_eq!(
4505                    object.read_aligned(block_size * offset, buf.as_mut()).await.unwrap(),
4506                    buf.len(),
4507                    "buf_index: {}, read offset: {}",
4508                    buf_index,
4509                    offset,
4510                );
4511                assert_eq!(
4512                    &buf.to_vec(),
4513                    &vec![0; buf.len()],
4514                    "buf_index: {}, read offset: {}",
4515                    buf_index,
4516                    offset,
4517                );
4518            }
4519        }
4520
4521        fs.close().await.expect("close failed");
4522    }
4523
4524    #[fuchsia::test(threads = 10)]
4525    async fn test_allocate_extends_file() {
4526        let (fs, object) = test_filesystem_and_empty_object().await;
4527        let block_size = fs.block_size();
4528        let buf_size = block_size.get() as usize;
4529        let mut buf = object.allocate_buffer(buf_size).await;
4530
4531        assert_eq!(object.read_aligned(0, buf.as_mut()).await.unwrap(), buf.len());
4532        assert_eq!(buf.to_vec(), vec![0; buf_size]);
4533
4534        assert!(TEST_OBJECT_SIZE < block_size * 4);
4535        // Allocation succeeds, and without any writes to the location it shows up as zero.
4536        object.allocate(0..block_size * 4).await.unwrap();
4537        assert_eq!(object.read_aligned(0, buf.as_mut()).await.unwrap(), buf.len());
4538        assert_eq!(buf.to_vec(), vec![0; buf_size]);
4539        assert_eq!(object.read_aligned(block_size.get(), buf.as_mut()).await.unwrap(), buf.len());
4540        assert_eq!(buf.to_vec(), vec![0; buf_size]);
4541        assert_eq!(object.read_aligned(block_size * 3, buf.as_mut()).await.unwrap(), buf.len());
4542        assert_eq!(buf.to_vec(), vec![0; buf_size]);
4543
4544        fs.close().await.expect("close failed");
4545    }
4546
4547    #[fuchsia::test(threads = 10)]
4548    async fn test_allocate_past_end() {
4549        let (fs, object) = test_filesystem_and_empty_object().await;
4550        let block_size = fs.block_size();
4551        let buf_size = block_size.get() as usize;
4552        let mut buf = object.allocate_buffer(buf_size).await;
4553
4554        assert_eq!(object.read_aligned(0, buf.as_mut()).await.unwrap(), buf.len());
4555        assert_eq!(buf.to_vec(), vec![0; buf_size]);
4556
4557        assert!(TEST_OBJECT_SIZE < block_size * 4);
4558        // Allocation succeeds, and without any writes to the location it shows up as zero.
4559        object.allocate(block_size * 4..block_size * 6).await.unwrap();
4560        assert_eq!(object.read_aligned(0, buf.as_mut()).await.unwrap(), buf.len());
4561        assert_eq!(buf.to_vec(), vec![0; buf_size]);
4562        assert_eq!(object.read_aligned(block_size * 4, buf.as_mut()).await.unwrap(), buf.len());
4563        assert_eq!(buf.to_vec(), vec![0; buf_size]);
4564        assert_eq!(object.read_aligned(block_size * 5, buf.as_mut()).await.unwrap(), buf.len());
4565        assert_eq!(buf.to_vec(), vec![0; buf_size]);
4566
4567        fs.close().await.expect("close failed");
4568    }
4569
4570    #[fuchsia::test(threads = 10)]
4571    async fn test_allocate_read_attr() {
4572        let (fs, object) = test_filesystem_and_empty_object().await;
4573        let block_size = fs.block_size();
4574        let file_size = block_size * 4;
4575        object.truncate(file_size).await.unwrap();
4576
4577        let content = object
4578            .read_attr(object.attribute_id())
4579            .await
4580            .expect("failed to read attr")
4581            .expect("attr returned none");
4582        assert_eq!(content.as_ref(), &vec![0; file_size as usize]);
4583
4584        object.allocate(block_size.get()..block_size * 3).await.unwrap();
4585
4586        let content = object
4587            .read_attr(object.attribute_id())
4588            .await
4589            .expect("failed to read attr")
4590            .expect("attr returned none");
4591        assert_eq!(content.as_ref(), &vec![0; file_size as usize]);
4592
4593        fs.close().await.expect("close failed");
4594    }
4595
4596    #[fuchsia::test(threads = 10)]
4597    async fn test_allocate_existing_data() {
4598        struct Case {
4599            written_ranges: Vec<Range<usize>>,
4600            allocate_range: Range<u64>,
4601        }
4602        let cases = [
4603            Case { written_ranges: vec![4..7], allocate_range: 4..7 },
4604            Case { written_ranges: vec![4..7], allocate_range: 3..8 },
4605            Case { written_ranges: vec![4..7], allocate_range: 5..6 },
4606            Case { written_ranges: vec![4..7], allocate_range: 5..8 },
4607            Case { written_ranges: vec![4..7], allocate_range: 3..5 },
4608            Case { written_ranges: vec![0..1, 2..3, 4..5, 6..7, 8..9], allocate_range: 0..10 },
4609            Case { written_ranges: vec![0..2, 4..6, 7..10], allocate_range: 1..8 },
4610        ];
4611
4612        for case in cases {
4613            let (fs, object) = test_filesystem_and_empty_object().await;
4614            let block_size = fs.block_size();
4615            let file_size = block_size * 10;
4616            object.truncate(file_size).await.unwrap();
4617
4618            for write in &case.written_ranges {
4619                let write_len = (write.end - write.start) * block_size.get() as usize;
4620                let mut write_buf = object.allocate_buffer(write_len).await;
4621                write_buf.fill(0xff);
4622                assert_eq!(
4623                    object
4624                        .write_or_append(Some(block_size * write.start as u64), write_buf.as_ref())
4625                        .await
4626                        .unwrap(),
4627                    file_size
4628                );
4629            }
4630
4631            let mut expected_buf = object.allocate_buffer(file_size as usize).await;
4632            assert_eq!(
4633                object.read_aligned(0, expected_buf.as_mut()).await.unwrap(),
4634                expected_buf.len()
4635            );
4636
4637            object
4638                .allocate(
4639                    case.allocate_range.start * block_size..case.allocate_range.end * block_size,
4640                )
4641                .await
4642                .unwrap();
4643
4644            let mut read_buf = object.allocate_buffer(file_size as usize).await;
4645            assert_eq!(object.read_aligned(0, read_buf.as_mut()).await.unwrap(), read_buf.len());
4646            assert_eq!(read_buf.to_vec(), expected_buf.to_vec());
4647
4648            fs.close().await.expect("close failed");
4649        }
4650    }
4651
4652    async fn get_modes(
4653        obj: &DataObjectHandle<ObjectStore>,
4654        mut search_range: Range<u64>,
4655    ) -> Vec<(Range<u64>, ExtentMode)> {
4656        let mut modes = Vec::new();
4657        let store = obj.store();
4658        let tree = store.tree();
4659        let layer_set = tree.layer_set();
4660        let mut merger = layer_set.merger();
4661        let mut iter = merger
4662            .query(Query::FullRange(&ObjectKey::attribute(
4663                obj.object_id(),
4664                AttributeId::DATA,
4665                AttributeKey::Extent(Extent::search_key_from_offset(search_range.start)),
4666            )))
4667            .await
4668            .unwrap();
4669        loop {
4670            match iter.get() {
4671                Some(ItemRef {
4672                    key:
4673                        ObjectKey {
4674                            object_id,
4675                            data:
4676                                ObjectKeyData::Attribute(
4677                                    AttributeId::DATA,
4678                                    AttributeKey::Extent(extent),
4679                                ),
4680                        },
4681                    value: ObjectValue::Extent(ExtentValue::Some { mode, .. }),
4682                    ..
4683                }) if *object_id == obj.object_id() => {
4684                    if search_range.end <= extent.start {
4685                        break;
4686                    }
4687                    let found_range = std::cmp::max(search_range.start, extent.start)
4688                        ..std::cmp::min(search_range.end, extent.end);
4689                    search_range.start = found_range.end;
4690                    modes.push((found_range, mode.clone()));
4691                    if search_range.start == search_range.end {
4692                        break;
4693                    }
4694                    iter.advance().await.unwrap();
4695                }
4696                x => panic!("looking for extent record, found this {:?}", x),
4697            }
4698        }
4699        modes
4700    }
4701
4702    async fn assert_all_overwrite(
4703        obj: &DataObjectHandle<ObjectStore>,
4704        mut search_range: Range<u64>,
4705    ) {
4706        let modes = get_modes(obj, search_range.clone()).await;
4707        for mode in modes {
4708            assert_eq!(
4709                mode.0.start, search_range.start,
4710                "missing mode in range {}..{}",
4711                search_range.start, mode.0.start
4712            );
4713            match mode.1 {
4714                ExtentMode::Overwrite | ExtentMode::OverwritePartial(_) => (),
4715                m => panic!("mode at range {:?} was not overwrite, instead found {:?}", mode.0, m),
4716            }
4717            assert!(
4718                mode.0.end <= search_range.end,
4719                "mode ends beyond search range (bug in test) - search_range: {:?}, mode: {:?}",
4720                search_range,
4721                mode,
4722            );
4723            search_range.start = mode.0.end;
4724        }
4725        assert_eq!(
4726            search_range.start, search_range.end,
4727            "missing mode in range {:?}",
4728            search_range
4729        );
4730    }
4731
4732    #[fuchsia::test(threads = 10)]
4733    async fn test_multi_overwrite() {
4734        #[derive(Debug)]
4735        struct Case {
4736            pre_writes: Vec<Range<usize>>,
4737            allocate_ranges: Vec<Range<u64>>,
4738            overwrites: Vec<Vec<Range<u64>>>,
4739        }
4740        let cases = [
4741            Case {
4742                pre_writes: Vec::new(),
4743                allocate_ranges: vec![1..3],
4744                overwrites: vec![vec![1..3]],
4745            },
4746            Case {
4747                pre_writes: Vec::new(),
4748                allocate_ranges: vec![0..1, 1..2, 2..3, 3..4],
4749                overwrites: vec![vec![0..4]],
4750            },
4751            Case {
4752                pre_writes: Vec::new(),
4753                allocate_ranges: vec![0..4],
4754                overwrites: vec![vec![0..1], vec![1..2], vec![3..4]],
4755            },
4756            Case {
4757                pre_writes: Vec::new(),
4758                allocate_ranges: vec![0..4],
4759                overwrites: vec![vec![3..4]],
4760            },
4761            Case {
4762                pre_writes: Vec::new(),
4763                allocate_ranges: vec![0..4],
4764                overwrites: vec![vec![3..4], vec![2..3], vec![1..2]],
4765            },
4766            Case {
4767                pre_writes: Vec::new(),
4768                allocate_ranges: vec![1..2, 5..6, 7..8],
4769                overwrites: vec![vec![5..6]],
4770            },
4771            Case {
4772                pre_writes: Vec::new(),
4773                allocate_ranges: vec![1..3],
4774                overwrites: vec![
4775                    vec![1..3],
4776                    vec![1..3],
4777                    vec![1..3],
4778                    vec![1..3],
4779                    vec![1..3],
4780                    vec![1..3],
4781                    vec![1..3],
4782                    vec![1..3],
4783                ],
4784            },
4785            Case {
4786                pre_writes: Vec::new(),
4787                allocate_ranges: vec![0..5],
4788                overwrites: vec![
4789                    vec![1..3],
4790                    vec![1..3],
4791                    vec![1..3],
4792                    vec![1..3],
4793                    vec![1..3],
4794                    vec![1..3],
4795                    vec![1..3],
4796                    vec![1..3],
4797                ],
4798            },
4799            Case {
4800                pre_writes: Vec::new(),
4801                allocate_ranges: vec![0..5],
4802                overwrites: vec![vec![0..2, 2..4, 4..5]],
4803            },
4804            Case {
4805                pre_writes: Vec::new(),
4806                allocate_ranges: vec![0..5, 5..10],
4807                overwrites: vec![vec![1..2, 2..3, 4..7, 7..8]],
4808            },
4809            Case {
4810                pre_writes: Vec::new(),
4811                allocate_ranges: vec![0..4, 6..10],
4812                overwrites: vec![vec![2..3, 7..9]],
4813            },
4814            Case {
4815                pre_writes: Vec::new(),
4816                allocate_ranges: vec![0..10],
4817                overwrites: vec![vec![1..2, 5..10], vec![0..1, 5..10], vec![0..5, 5..10]],
4818            },
4819            Case {
4820                pre_writes: Vec::new(),
4821                allocate_ranges: vec![0..10],
4822                overwrites: vec![vec![0..2, 2..4, 4..6, 6..8, 8..10], vec![0..5, 5..10]],
4823            },
4824            Case {
4825                pre_writes: vec![1..3],
4826                allocate_ranges: vec![1..3],
4827                overwrites: vec![vec![1..3]],
4828            },
4829            Case {
4830                pre_writes: vec![1..3],
4831                allocate_ranges: vec![4..6],
4832                overwrites: vec![vec![5..6]],
4833            },
4834            Case {
4835                pre_writes: vec![1..3],
4836                allocate_ranges: vec![0..4],
4837                overwrites: vec![vec![0..4]],
4838            },
4839            Case {
4840                pre_writes: vec![1..3],
4841                allocate_ranges: vec![2..4],
4842                overwrites: vec![vec![2..4]],
4843            },
4844            Case {
4845                pre_writes: vec![3..5],
4846                allocate_ranges: vec![1..3, 6..7],
4847                overwrites: vec![vec![1..3, 6..7]],
4848            },
4849            Case {
4850                pre_writes: vec![1..3, 5..7, 8..9],
4851                allocate_ranges: vec![0..5],
4852                overwrites: vec![vec![0..2, 2..5], vec![0..5]],
4853            },
4854            Case {
4855                pre_writes: Vec::new(),
4856                allocate_ranges: vec![0..10, 4..6],
4857                overwrites: Vec::new(),
4858            },
4859            Case {
4860                pre_writes: Vec::new(),
4861                allocate_ranges: vec![3..8, 5..10],
4862                overwrites: Vec::new(),
4863            },
4864            Case {
4865                pre_writes: Vec::new(),
4866                allocate_ranges: vec![5..10, 3..8],
4867                overwrites: Vec::new(),
4868            },
4869        ];
4870
4871        for (i, case) in cases.into_iter().enumerate() {
4872            log::info!("running case {} - {:?}", i, case);
4873            let (fs, object) = test_filesystem_and_empty_object().await;
4874            let block_size = fs.block_size();
4875            let file_size = block_size * 10;
4876            object.truncate(file_size).await.unwrap();
4877
4878            for write in case.pre_writes {
4879                let write_len = (write.end - write.start) * block_size.get() as usize;
4880                let mut write_buf = object.allocate_buffer(write_len).await;
4881                write_buf.fill(0xff);
4882                assert_eq!(
4883                    object
4884                        .write_or_append(Some(block_size * write.start as u64), write_buf.as_ref())
4885                        .await
4886                        .unwrap(),
4887                    file_size
4888                );
4889            }
4890
4891            for allocate_range in &case.allocate_ranges {
4892                object
4893                    .allocate(allocate_range.start * block_size..allocate_range.end * block_size)
4894                    .await
4895                    .unwrap();
4896            }
4897
4898            for allocate_range in case.allocate_ranges {
4899                assert_all_overwrite(
4900                    &object,
4901                    allocate_range.start * block_size..allocate_range.end * block_size,
4902                )
4903                .await;
4904            }
4905
4906            for overwrite in case.overwrites {
4907                let mut write_len = 0;
4908                let overwrite = overwrite
4909                    .into_iter()
4910                    .map(|r| {
4911                        write_len += (r.end - r.start) * block_size;
4912                        r.start * block_size..r.end * block_size
4913                    })
4914                    .collect::<Vec<_>>();
4915                let mut write_buf = object.allocate_buffer(write_len as usize).await;
4916                let data = (0..20).cycle().take(write_len as usize).collect::<Vec<_>>();
4917                write_buf.copy_from_slice(&data);
4918
4919                let mut expected_buf = object.allocate_buffer(file_size as usize).await;
4920                assert_eq!(
4921                    object.read_aligned(0, expected_buf.as_mut()).await.unwrap(),
4922                    expected_buf.len()
4923                );
4924                let mut expected_buf_slice = expected_buf.as_mut_ptr_slice();
4925                let mut data_slice = data.as_slice();
4926                for r in &overwrite {
4927                    let len = r.length().unwrap() as usize;
4928                    let (copy_from, rest) = data_slice.split_at(len);
4929                    expected_buf_slice
4930                        .subslice_mut(r.start as usize..r.end as usize)
4931                        .copy_from_slice(&copy_from);
4932                    data_slice = rest;
4933                }
4934
4935                let mut transaction = object.new_transaction().await.unwrap();
4936                object
4937                    .multi_overwrite(
4938                        &mut transaction,
4939                        AttributeId::DATA,
4940                        &overwrite,
4941                        write_buf.as_mut(),
4942                    )
4943                    .await
4944                    .unwrap_or_else(|_| panic!("multi_overwrite error on case {}", i));
4945                // Double check the emitted checksums. We should have one u64 checksum for every
4946                // block we wrote to disk.
4947                let mut checksummed_range_length = 0;
4948                let mut num_checksums = 0;
4949                for (_, device_range, checksums, _) in transaction.checksums() {
4950                    let range_len = device_range.end - device_range.start;
4951                    let checksums_len = checksums.len() as u64;
4952                    assert_eq!(range_len / checksums_len, block_size);
4953                    checksummed_range_length += range_len;
4954                    num_checksums += checksums_len;
4955                }
4956                assert_eq!(checksummed_range_length, write_len);
4957                assert_eq!(num_checksums, write_len / block_size);
4958                transaction.commit().await.unwrap();
4959
4960                let mut buf = object.allocate_buffer(file_size as usize).await;
4961                assert_eq!(
4962                    object.read_aligned(0, buf.as_mut()).await.unwrap(),
4963                    buf.len(),
4964                    "failed length check on case {}",
4965                    i,
4966                );
4967                assert_eq!(buf.to_vec(), expected_buf.to_vec(), "failed on case {}", i);
4968            }
4969
4970            fsck_volume(&fs, object.store().store_object_id(), None).await.expect("fsck failed");
4971            fs.close().await.expect("close failed");
4972        }
4973    }
4974
4975    #[fuchsia::test(threads = 10)]
4976    async fn test_multi_overwrite_mode_updates() {
4977        let (fs, object) = test_filesystem_and_empty_object().await;
4978        let block_size = fs.block_size();
4979        let file_size = block_size * 10;
4980        object.truncate(file_size).await.unwrap();
4981
4982        let mut expected_bitmap = BitVec::from_elem(10, false);
4983
4984        object.allocate(0..10 * block_size).await.unwrap();
4985        assert_eq!(
4986            get_modes(&object, 0..10 * block_size).await,
4987            vec![(0..10 * block_size, ExtentMode::OverwritePartial(expected_bitmap.clone()))]
4988        );
4989
4990        let mut write_buf = object.allocate_buffer((2 * block_size) as usize).await;
4991        let data = (0..20).cycle().take(write_buf.len()).collect::<Vec<_>>();
4992        write_buf.copy_from_slice(&data);
4993        let mut transaction = object.new_transaction().await.unwrap();
4994        object
4995            .multi_overwrite(
4996                &mut transaction,
4997                AttributeId::DATA,
4998                &[2 * block_size..4 * block_size],
4999                write_buf.as_mut(),
5000            )
5001            .await
5002            .unwrap();
5003        transaction.commit().await.unwrap();
5004
5005        expected_bitmap.set(2, true);
5006        expected_bitmap.set(3, true);
5007        assert_eq!(
5008            get_modes(&object, 0..10 * block_size).await,
5009            vec![(0..10 * block_size, ExtentMode::OverwritePartial(expected_bitmap.clone()))]
5010        );
5011
5012        let mut write_buf = object.allocate_buffer((3 * block_size) as usize).await;
5013        let data = (0..20).cycle().take(write_buf.len()).collect::<Vec<_>>();
5014        write_buf.copy_from_slice(&data);
5015        let mut transaction = object.new_transaction().await.unwrap();
5016        object
5017            .multi_overwrite(
5018                &mut transaction,
5019                AttributeId::DATA,
5020                &[3 * block_size..5 * block_size, 6 * block_size..7 * block_size],
5021                write_buf.as_mut(),
5022            )
5023            .await
5024            .unwrap();
5025        transaction.commit().await.unwrap();
5026
5027        expected_bitmap.set(4, true);
5028        expected_bitmap.set(6, true);
5029        assert_eq!(
5030            get_modes(&object, 0..10 * block_size).await,
5031            vec![(0..10 * block_size, ExtentMode::OverwritePartial(expected_bitmap.clone()))]
5032        );
5033
5034        let mut write_buf = object.allocate_buffer((6 * block_size) as usize).await;
5035        let data = (0..20).cycle().take(write_buf.len()).collect::<Vec<_>>();
5036        write_buf.copy_from_slice(&data);
5037        let mut transaction = object.new_transaction().await.unwrap();
5038        object
5039            .multi_overwrite(
5040                &mut transaction,
5041                AttributeId::DATA,
5042                &[
5043                    0..2 * block_size,
5044                    5 * block_size..6 * block_size,
5045                    7 * block_size..10 * block_size,
5046                ],
5047                write_buf.as_mut(),
5048            )
5049            .await
5050            .unwrap();
5051        transaction.commit().await.unwrap();
5052
5053        assert_eq!(
5054            get_modes(&object, 0..10 * block_size).await,
5055            vec![(0..10 * block_size, ExtentMode::Overwrite)]
5056        );
5057
5058        fs.close().await.expect("close failed");
5059    }
5060
5061    #[fuchsia::test(threads = 10)]
5062    async fn test_check_unwritten_zero() {
5063        let device = DeviceHolder::new(FakeDevice::new(256 * 1024, TEST_DEVICE_BLOCK_SIZE));
5064        let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
5065        let object = create_object_with_key(fs.clone(), Some(&new_insecure_crypt()), false).await;
5066        let block_size = fs.block_size();
5067
5068        // Set up a file with eight blocks to look like this:
5069        // | None | COW | COW | None | Overwrite(unwritten) | Overwrite(written) | None |
5070        let file_size = block_size * 7;
5071        object.truncate(file_size).await.unwrap();
5072        assert!(object.check_unwritten_zero(0..file_size).await.unwrap());
5073
5074        let mut buffer = object.allocate_buffer(block_size.get() as usize).await;
5075        buffer.fill(1);
5076        object
5077            .write_or_append(Some(block_size.get()), buffer.as_ref())
5078            .await
5079            .expect("write failed");
5080        object.write_or_append(Some(block_size * 2), buffer.as_ref()).await.expect("write failed");
5081
5082        object.allocate((block_size * 4)..(block_size * 6)).await.expect("Allocate failed");
5083        let mut transaction = fs
5084            .root_store()
5085            .new_transaction(
5086                lock_keys![LockKey::object(object.store().store_object_id(), object.object_id(),)],
5087                Options::default(),
5088            )
5089            .await
5090            .expect("new_transaction failed");
5091        object
5092            .multi_overwrite(
5093                &mut transaction,
5094                AttributeId::DATA,
5095                &vec![(block_size * 5)..(block_size * 6)],
5096                buffer.as_mut(),
5097            )
5098            .await
5099            .expect("Multi overwrite");
5100        transaction.commit().await.expect("Committing overwrite");
5101
5102        // Anything touching the COW ranges should fail.
5103        assert!(!object.check_unwritten_zero(0..(block_size * 2)).await.unwrap());
5104        assert!(!object.check_unwritten_zero(block_size.get()..(block_size * 3)).await.unwrap());
5105        assert!(!object.check_unwritten_zero((block_size * 2)..(block_size * 4)).await.unwrap());
5106
5107        // This should be fine, as the OverwritePartial should only touch the unwritten block.
5108        assert!(object.check_unwritten_zero((block_size * 3)..(block_size * 5)).await.unwrap());
5109
5110        // These should touch the written overwrite block and fail.
5111        assert!(!object.check_unwritten_zero((block_size * 4)..(block_size * 6)).await.unwrap());
5112        assert!(!object.check_unwritten_zero((block_size * 5)..(block_size * 7)).await.unwrap());
5113
5114        fs.close().await.expect("close failed");
5115    }
5116
5117    #[fuchsia::test]
5118    async fn test_allocate_large_file() {
5119        let device = DeviceHolder::new(FakeDevice::new(8192, 4096));
5120        let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
5121        let object = create_object_with_key(fs.clone(), Some(&new_insecure_crypt()), false).await;
5122        let block_size = fs.block_size().get();
5123
5124        for i in (0..1600).step_by(2) {
5125            object.allocate(i * block_size..(i + 1) * block_size).await.expect("allocate failed");
5126        }
5127        object.allocate(0..1600 * block_size).await.expect("allocate failed");
5128
5129        fs.close().await.expect("close failed");
5130    }
5131
5132    #[fuchsia::test]
5133    async fn test_bounded_extent_queries_skip_layers() {
5134        let device = DeviceHolder::new(FakeDevice::new(8192, TEST_DEVICE_BLOCK_SIZE));
5135        let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
5136        let store = fs.root_store();
5137        let block_size = fs.block_size().get();
5138
5139        // Populate enough objects and flush so the base persistent layer has a bloom filter.
5140        for _ in 0..200 {
5141            let _ = create_object_with_key(fs.clone(), Some(&new_insecure_crypt()), false).await;
5142        }
5143        store.flush().await.expect("flush failed");
5144
5145        let object = create_object_with_key(fs.clone(), Some(&new_insecure_crypt()), true).await;
5146        let mut buf = object.allocate_buffer(block_size as usize).await;
5147        buf.fill(0xab);
5148
5149        let skipped = || {
5150            store.tree().counters().layer_files_skipped.load(std::sync::atomic::Ordering::Relaxed)
5151        };
5152
5153        // 1. write_or_append calls deallocate_old_extents (LimitedRange).
5154        let before = skipped();
5155        object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
5156        assert!(skipped() > before);
5157
5158        // 2. check_unwritten_zero (LimitedRange) and stopping at a deleted extent past range.end.
5159        object.write_or_append(Some(block_size * 2), buf.as_ref()).await.expect("write failed");
5160        // Insert an extent tombstone at block 1 (block_size..block_size * 2) while block 2 remains
5161        // allocated. Checking unwritten zero on block 0..block 1 must stop at block 1's tombstone
5162        // rather than advancing into block 2.
5163        let mut transaction = object.new_transaction().await.expect("new_transaction failed");
5164        transaction.add(
5165            store.store_object_id(),
5166            Mutation::merge_object(
5167                ObjectKey::extent(
5168                    object.object_id(),
5169                    AttributeId::DATA,
5170                    block_size..block_size * 2,
5171                ),
5172                ObjectValue::deleted_extent(),
5173            ),
5174        );
5175        transaction.commit().await.expect("commit failed");
5176
5177        let before = skipped();
5178        assert!(!object.check_unwritten_zero(0..block_size).await.expect("check failed"));
5179        assert!(
5180            object.check_unwritten_zero(block_size..block_size * 2).await.expect("check failed")
5181        );
5182        assert!(skipped() >= before + 2);
5183
5184        // 3. allocate and multi_overwrite (LimitedRange).
5185        let before = skipped();
5186        object.allocate(0..block_size * 2).await.expect("allocate failed");
5187        assert!(skipped() > before);
5188
5189        let mut transaction = object.new_transaction().await.expect("new_transaction failed");
5190        let before = skipped();
5191        object
5192            .multi_overwrite(&mut transaction, AttributeId::DATA, &[0..block_size], buf.as_mut())
5193            .await
5194            .expect("multi_overwrite failed");
5195        transaction.commit().await.expect("commit failed");
5196        assert!(skipped() > before);
5197
5198        // 4. unaligned grow (LimitedRange).
5199        object.truncate(block_size / 2).await.expect("truncate failed");
5200        let before = skipped();
5201        object.truncate(block_size * 2).await.expect("grow failed");
5202        assert!(skipped() > before);
5203
5204        fs.close().await.expect("close failed");
5205    }
5206
5207    #[fuchsia::test]
5208    async fn test_truncate_shrink_when_disk_full() {
5209        let device = DeviceHolder::new(FakeDevice::new(16384, TEST_DEVICE_BLOCK_SIZE));
5210        let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
5211        let root_volume = root_volume(fs.clone()).await.expect("root_volume failed");
5212        let store = root_volume
5213            .new_volume("test", NewChildStoreOptions::default())
5214            .await
5215            .expect("new_volume failed");
5216        let root_dir =
5217            Directory::open(&store, store.root_directory_object_id()).await.expect("open failed");
5218
5219        let (victim, filler) = {
5220            let mut transaction = store
5221                .new_transaction(
5222                    lock_keys![LockKey::object(store.store_object_id(), root_dir.object_id())],
5223                    Options::default(),
5224                )
5225                .await
5226                .expect("new_txn");
5227            let v = root_dir.create_child_file(&mut transaction, "victim").await.expect("create");
5228            let f = root_dir.create_child_file(&mut transaction, "filler").await.expect("create");
5229            transaction.commit().await.expect("commit");
5230            (v, f)
5231        };
5232        {
5233            let mut buf = victim.allocate_buffer(1_048_576).await;
5234            buf.fill(0x55);
5235            victim.write_or_append(Some(0), buf.as_ref()).await.expect("write victim");
5236        }
5237
5238        fs.journal().force_compact().await.expect("compact");
5239
5240        let mut offset = 0;
5241        for chunk_size in [65536usize, 4096, 512] {
5242            let mut buf = filler.allocate_buffer(chunk_size).await;
5243            buf.fill(0xAA);
5244            while filler.write_or_append(Some(offset), buf.as_ref()).await.is_ok() {
5245                offset += chunk_size as u64;
5246            }
5247        }
5248        while let Ok(mut transaction) = store
5249            .new_transaction(
5250                lock_keys![LockKey::object(store.store_object_id(), root_dir.object_id())],
5251                Options::default(),
5252            )
5253            .await
5254        {
5255            root_dir
5256                .create_child_file(&mut transaction, &format!("pad_{offset}"))
5257                .await
5258                .expect("pad");
5259            transaction.commit().await.expect("commit pad");
5260            offset += 1;
5261        }
5262
5263        let free_when_full = fs.allocator().get_disk_bytes() - fs.allocator().get_used_bytes().0;
5264        assert!(
5265            free_when_full < crate::object_store::transaction::TRANSACTION_METADATA_MAX_AMOUNT,
5266            "Remaining unallocated space ({free_when_full}) is less than \
5267             TRANSACTION_METADATA_MAX_AMOUNT"
5268        );
5269
5270        let sys_object = {
5271            let root_store = fs.root_store();
5272            let mut transaction = root_store
5273                .new_transaction(
5274                    lock_keys![],
5275                    Options { reservation: ReservationOptions::Borrowed, ..Default::default() },
5276                )
5277                .await
5278                .expect("new_txn borrowed");
5279            let obj = ObjectStore::create_object(
5280                &root_store,
5281                &mut transaction,
5282                HandleOptions::default(),
5283                None,
5284            )
5285            .await
5286            .expect("create system store object");
5287            root_store.add_to_graveyard(&mut transaction, obj.object_id());
5288            transaction.commit().await.expect("commit system store object");
5289            obj
5290        };
5291        // Growing a system store object with `ReservationOptions::Borrowed` must not overwrite the
5292        // reservation to `ReservationOptions::New` and fail with `NoSpace` when the disk is full.
5293        sys_object
5294            .truncate_with_options(
5295                Options { reservation: ReservationOptions::Borrowed, ..Default::default() },
5296                4096,
5297            )
5298            .await
5299            .expect("Growing a system store object with Borrowed reservation should succeed");
5300        assert_eq!(sys_object.get_size(), 4096);
5301
5302        // Shrinking `victim` via `DataObjectHandle::truncate(0)` must succeed even when the disk is
5303        // 100% full because shrinking borrows metadata space.
5304        victim.truncate(0).await.expect("DataObjectHandle::truncate(0) should succeed when full");
5305        assert_eq!(victim.get_size(), 0);
5306        let free_after_truncate =
5307            fs.allocator().get_disk_bytes() - fs.allocator().get_used_bytes().0;
5308        assert!(free_after_truncate >= free_when_full + 1_048_576);
5309
5310        fs.close().await.expect("close failed");
5311    }
5312}