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