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