Skip to main content

fxfs/object_store/
store_object_handle.rs

1// Copyright 2023 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::checksum::{Checksum, Checksums, fletcher64};
6use crate::errors::FxfsError;
7use crate::log::*;
8use crate::lsm_tree::Query;
9use crate::lsm_tree::merge::MergerIterator;
10use crate::lsm_tree::types::{Item, ItemRef, LayerIterator};
11use crate::object_handle::ObjectHandle;
12use crate::object_store::extent_record::{ExtentMode, ExtentValue};
13use crate::object_store::object_manager::ObjectManager;
14use crate::object_store::object_record::{
15    AttributeKey, ExtendedAttributeValue, ObjectAttributes, ObjectItem, ObjectKey, ObjectKeyData,
16    ObjectValue, Timestamp,
17};
18use crate::object_store::transaction::{
19    AssocObj, AssociatedObject, LockKey, Mutation, ObjectStoreMutation, Options, ReadGuard,
20    Transaction, lock_keys,
21};
22use crate::object_store::{
23    AttributeId, Extent, HandleOptions, HandleOwner, ObjectStore, TrimMode, TrimResult,
24    VOLUME_DATA_KEY_ID,
25};
26use crate::range::RangeExt;
27use crate::round::{round_down, round_up};
28use anyhow::{Context, Error, anyhow, bail, ensure};
29use assert_matches::assert_matches;
30use bit_vec::BitVec;
31use futures::stream::{FuturesOrdered, FuturesUnordered};
32use futures::{TryStreamExt, try_join};
33use fxfs_crypto::{
34    Cipher, CipherHolder, CipherSet, EncryptionKey, FindKeyResult, FxfsCipher, KeyPurpose,
35};
36use fxfs_trace::{TraceFutureExt, trace, trace_future_args};
37use static_assertions::const_assert;
38use std::cmp::min;
39use std::future::Future;
40use std::ops::Range;
41use std::sync::Arc;
42use std::sync::atomic::{self, AtomicBool, Ordering};
43use storage_device::buffer::{Buffer, BufferFuture, BufferRef, MutableBufferRef};
44use storage_device::{InlineCryptoOptions, ReadOptions, WriteOptions};
45
46use fidl_fuchsia_io as fio;
47use fuchsia_async as fasync;
48
49/// Maximum size for an extended attribute name.
50pub const MAX_XATTR_NAME_SIZE: usize = 255;
51/// Maximum size an extended attribute can be before it's stored in an object attribute instead of
52/// inside the record directly.
53pub const MAX_INLINE_XATTR_SIZE: usize = 256;
54/// Maximum size for an extended attribute value. NB: the maximum size for an extended attribute is
55/// 64kB, which we rely on for correctness when deleting attributes, so ensure it's always
56/// enforced.
57pub const MAX_XATTR_VALUE_SIZE: usize = 64000;
58
59/// Zeroes blocks in 'buffer' based on `bitmap`, one bit per block from start of buffer.
60fn apply_bitmap_zeroing(
61    block_size: usize,
62    bitmap: &bit_vec::BitVec,
63    mut buffer: MutableBufferRef<'_>,
64) {
65    let buf = buffer.as_mut_slice();
66    debug_assert_eq!(bitmap.len() * block_size, buf.len());
67    for (i, block) in bitmap.iter().enumerate() {
68        if !block {
69            let start = i * block_size;
70            buf[start..start + block_size].fill(0);
71        }
72    }
73}
74
75/// When writing, often the logic should be generic over whether or not checksums are generated.
76/// This provides that and a handy way to convert to the more general ExtentMode that eventually
77/// stores it on disk.
78#[derive(Debug, Clone, PartialEq)]
79pub enum MaybeChecksums {
80    None,
81    Fletcher(Vec<Checksum>),
82}
83
84impl MaybeChecksums {
85    pub fn maybe_as_ref(&self) -> Option<&[Checksum]> {
86        match self {
87            Self::None => None,
88            Self::Fletcher(sums) => Some(&sums),
89        }
90    }
91
92    pub fn split_off(&mut self, at: usize) -> Self {
93        match self {
94            Self::None => Self::None,
95            Self::Fletcher(sums) => Self::Fletcher(sums.split_off(at)),
96        }
97    }
98
99    pub fn to_mode(self) -> ExtentMode {
100        match self {
101            Self::None => ExtentMode::Raw,
102            Self::Fletcher(sums) => ExtentMode::Cow(Checksums::fletcher(sums)),
103        }
104    }
105
106    pub fn into_option(self) -> Option<Vec<Checksum>> {
107        match self {
108            Self::None => None,
109            Self::Fletcher(sums) => Some(sums),
110        }
111    }
112}
113
114/// The mode of operation when setting extended attributes. This is the same as the fidl definition
115/// but is replicated here so we don't have fuchsia.io structures in the api, so this can be used
116/// on host.
117#[derive(Debug, Clone, Copy, PartialEq, Eq)]
118pub enum SetExtendedAttributeMode {
119    /// Create the extended attribute if it doesn't exist, replace the value if it does.
120    Set,
121    /// Create the extended attribute if it doesn't exist, fail if it does.
122    Create,
123    /// Replace the extended attribute value if it exists, fail if it doesn't.
124    Replace,
125}
126
127impl From<fio::SetExtendedAttributeMode> for SetExtendedAttributeMode {
128    fn from(other: fio::SetExtendedAttributeMode) -> SetExtendedAttributeMode {
129        match other {
130            fio::SetExtendedAttributeMode::Set => SetExtendedAttributeMode::Set,
131            fio::SetExtendedAttributeMode::Create => SetExtendedAttributeMode::Create,
132            fio::SetExtendedAttributeMode::Replace => SetExtendedAttributeMode::Replace,
133        }
134    }
135}
136
137enum Encryption {
138    /// The object doesn't use encryption.
139    None,
140
141    /// The object has keys that are cached (which means unwrapping occurs on-demand) with
142    /// KeyManager.
143    CachedKeys,
144
145    /// The object has permanent keys registered with KeyManager.
146    PermanentKeys,
147}
148
149#[derive(PartialEq, Debug)]
150enum OverwriteBitmaps {
151    None,
152    Some {
153        /// The block bitmap of a partial overwrite extent in the tree.
154        extent_bitmap: BitVec,
155        /// A bitmap of the blocks written to by the current overwrite.
156        write_bitmap: BitVec,
157        /// BitVec doesn't have a slice equivalent, so for a particular section of the write we
158        /// keep track of an offset in the bitmaps to operate on.
159        bitmap_offset: usize,
160    },
161}
162
163impl OverwriteBitmaps {
164    fn new(extent_bitmap: BitVec) -> Self {
165        OverwriteBitmaps::Some {
166            write_bitmap: BitVec::from_elem(extent_bitmap.len(), false),
167            extent_bitmap,
168            bitmap_offset: 0,
169        }
170    }
171
172    fn is_none(&self) -> bool {
173        *self == OverwriteBitmaps::None
174    }
175
176    fn set_offset(&mut self, new_offset: usize) {
177        match self {
178            OverwriteBitmaps::None => (),
179            OverwriteBitmaps::Some { bitmap_offset, .. } => *bitmap_offset = new_offset,
180        }
181    }
182
183    fn get_from_extent_bitmap(&self, i: usize) -> Option<bool> {
184        match self {
185            OverwriteBitmaps::None => None,
186            OverwriteBitmaps::Some { extent_bitmap, bitmap_offset, .. } => {
187                extent_bitmap.get(*bitmap_offset + i)
188            }
189        }
190    }
191
192    fn set_in_write_bitmap(&mut self, i: usize, x: bool) {
193        match self {
194            OverwriteBitmaps::None => (),
195            OverwriteBitmaps::Some { write_bitmap, bitmap_offset, .. } => {
196                write_bitmap.set(*bitmap_offset + i, x)
197            }
198        }
199    }
200
201    fn take_bitmaps(self) -> Option<(BitVec, BitVec)> {
202        match self {
203            OverwriteBitmaps::None => None,
204            OverwriteBitmaps::Some { extent_bitmap, write_bitmap, .. } => {
205                Some((extent_bitmap, write_bitmap))
206            }
207        }
208    }
209}
210
211/// When writing to Overwrite ranges, we need to emit whether a set of checksums for a device range
212/// is the first write to that region or not. This tracks one such range so we can use it after the
213/// write to break up the returned checksum list.
214#[derive(PartialEq, Debug)]
215struct ChecksumRangeChunk {
216    checksum_range: Range<usize>,
217    device_range: Range<u64>,
218    is_first_write: bool,
219}
220
221impl ChecksumRangeChunk {
222    fn group_first_write_ranges(
223        bitmaps: &mut OverwriteBitmaps,
224        block_size: u64,
225        write_device_range: Range<u64>,
226    ) -> Vec<ChecksumRangeChunk> {
227        let write_block_len = (write_device_range.length().unwrap() / block_size) as usize;
228        if bitmaps.is_none() {
229            // If there is no bitmap, then the overwrite range is fully written to. However, we
230            // could still be within the journal flush window where one of the blocks was written
231            // to for the first time to put it in this state, so we still need to emit the
232            // checksums in case replay needs them.
233            vec![ChecksumRangeChunk {
234                checksum_range: 0..write_block_len,
235                device_range: write_device_range,
236                is_first_write: false,
237            }]
238        } else {
239            let mut checksum_ranges = vec![ChecksumRangeChunk {
240                checksum_range: 0..0,
241                device_range: write_device_range.start..write_device_range.start,
242                is_first_write: !bitmaps.get_from_extent_bitmap(0).unwrap(),
243            }];
244            let mut working_range = checksum_ranges.last_mut().unwrap();
245            for i in 0..write_block_len {
246                bitmaps.set_in_write_bitmap(i, true);
247
248                // bitmap.get returning true means the block is initialized and therefore has been
249                // written to before.
250                if working_range.is_first_write != bitmaps.get_from_extent_bitmap(i).unwrap() {
251                    // is_first_write is tracking opposite of what comes back from the bitmap, so
252                    // if the are still opposites we continue our current range.
253                    working_range.checksum_range.end += 1;
254                    working_range.device_range.end += block_size;
255                } else {
256                    // If they are the same, then we need to make a new chunk.
257                    let new_chunk = ChecksumRangeChunk {
258                        checksum_range: working_range.checksum_range.end
259                            ..working_range.checksum_range.end + 1,
260                        device_range: working_range.device_range.end
261                            ..working_range.device_range.end + block_size,
262                        is_first_write: !working_range.is_first_write,
263                    };
264                    checksum_ranges.push(new_chunk);
265                    working_range = checksum_ranges.last_mut().unwrap();
266                }
267            }
268            checksum_ranges
269        }
270    }
271}
272
273/// StoreObjectHandle is the lowest-level, untyped handle to an object with the id [`object_id`] in
274/// a particular store, [`owner`]. It provides functionality shared across all objects, such as
275/// reading and writing attributes and managing encryption keys.
276///
277/// Since it's untyped, it doesn't do any object kind validation, and is generally meant to
278/// implement higher-level typed handles.
279///
280/// For file-like objects with a data attribute, DataObjectHandle implements traits and helpers for
281/// doing more complex extent management and caches the content size.
282///
283/// For directory-like objects, Directory knows how to add and remove child objects and enumerate
284/// its children.
285pub struct StoreObjectHandle<S: HandleOwner> {
286    owner: Arc<S>,
287    object_id: u64,
288    options: HandleOptions,
289    trace: AtomicBool,
290    encryption: Encryption,
291}
292
293impl<S: HandleOwner> ObjectHandle for StoreObjectHandle<S> {
294    fn set_trace(&self, v: bool) {
295        info!(store_id = self.store().store_object_id, oid = self.object_id(), trace = v; "trace");
296        self.trace.store(v, atomic::Ordering::Relaxed);
297    }
298
299    fn object_id(&self) -> u64 {
300        return self.object_id;
301    }
302
303    fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
304        self.store().device.allocate_buffer(size)
305    }
306
307    fn block_size(&self) -> u64 {
308        self.store().block_size()
309    }
310}
311
312struct Watchdog {
313    _task: fasync::Task<()>,
314}
315
316impl Watchdog {
317    fn new(increment_seconds: u64, cb: impl Fn(u64) + Send + 'static) -> Self {
318        Self {
319            _task: fasync::Task::spawn(
320                async move {
321                    let increment = increment_seconds.try_into().unwrap();
322                    let mut fired_counter = 0;
323                    let mut next_wake = fasync::MonotonicInstant::now();
324                    loop {
325                        next_wake += std::time::Duration::from_secs(increment).into();
326                        // If this isn't being scheduled this will purposely result in fast looping
327                        // when it does. This will be insightful about the state of the thread and
328                        // task scheduling.
329                        if fasync::MonotonicInstant::now() < next_wake {
330                            fasync::Timer::new(next_wake).await;
331                        }
332                        fired_counter += 1;
333                        cb(fired_counter);
334                    }
335                }
336                .trace(trace_future_args!("StoreObjectHandle::Watchdog")),
337            ),
338        }
339    }
340}
341
342impl<S: HandleOwner> StoreObjectHandle<S> {
343    /// Make a new StoreObjectHandle for the object with id [`object_id`] in store [`owner`].
344    pub fn new(
345        owner: Arc<S>,
346        object_id: u64,
347        permanent_keys: bool,
348        options: HandleOptions,
349        trace: bool,
350    ) -> Self {
351        let encryption = if permanent_keys {
352            Encryption::PermanentKeys
353        } else if owner.as_ref().as_ref().is_encrypted() {
354            Encryption::CachedKeys
355        } else {
356            Encryption::None
357        };
358        Self { owner, object_id, encryption, options, trace: AtomicBool::new(trace) }
359    }
360
361    pub fn owner(&self) -> &Arc<S> {
362        &self.owner
363    }
364
365    pub fn store(&self) -> &ObjectStore {
366        self.owner.as_ref().as_ref()
367    }
368
369    pub fn trace(&self) -> bool {
370        self.trace.load(atomic::Ordering::Relaxed)
371    }
372
373    pub fn is_encrypted(&self) -> bool {
374        !matches!(self.encryption, Encryption::None)
375    }
376
377    /// Get the default set of transaction options for this object. This is mostly the overall
378    /// default, modified by any [`HandleOptions`] held by this handle.
379    pub fn default_transaction_options<'b>(&self) -> Options<'b> {
380        Options { skip_journal_checks: self.options.skip_journal_checks, ..Default::default() }
381    }
382
383    pub async fn new_transaction_with_options<'b>(
384        &self,
385        attribute_id: AttributeId,
386        options: Options<'b>,
387    ) -> Result<Transaction<'b>, Error> {
388        Ok(self
389            .store()
390            .new_transaction(
391                lock_keys![
392                    LockKey::object_attribute(
393                        self.store().store_object_id(),
394                        self.object_id(),
395                        attribute_id,
396                    ),
397                    LockKey::object(self.store().store_object_id(), self.object_id()),
398                ],
399                options,
400            )
401            .await?)
402    }
403
404    pub async fn new_transaction<'b>(
405        &self,
406        attribute_id: AttributeId,
407    ) -> Result<Transaction<'b>, Error> {
408        self.new_transaction_with_options(attribute_id, self.default_transaction_options()).await
409    }
410
411    // If |transaction| has an impending mutation for the underlying object, returns that.
412    // Otherwise, looks up the object from the tree.
413    async fn txn_get_object_mutation(
414        &self,
415        transaction: &Transaction<'_>,
416    ) -> Result<ObjectStoreMutation, Error> {
417        self.store().txn_get_object_mutation(transaction, self.object_id()).await
418    }
419
420    // Returns the amount deallocated.
421    async fn deallocate_old_extents(
422        &self,
423        transaction: &mut Transaction<'_>,
424        attribute_id: AttributeId,
425        range: Range<u64>,
426    ) -> Result<u64, Error> {
427        let block_size = self.block_size();
428        assert_eq!(range.start % block_size, 0);
429        assert_eq!(range.end % block_size, 0);
430        if range.start == range.end {
431            return Ok(0);
432        }
433        let tree = &self.store().tree;
434        let layer_set = tree.layer_set();
435        let key = Extent(range);
436        let lower_bound = ObjectKey::attribute(
437            self.object_id(),
438            attribute_id,
439            AttributeKey::Extent(key.search_key()),
440        );
441        let mut merger = layer_set.merger();
442        let mut iter = merger.query(Query::FullRange(&lower_bound)).await?;
443        let allocator = self.store().allocator();
444        let mut deallocated = 0;
445        let trace = self.trace();
446        while let Some(ItemRef {
447            key:
448                ObjectKey {
449                    object_id,
450                    data: ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent_key)),
451                },
452            value: ObjectValue::Extent(value),
453            ..
454        }) = iter.get()
455        {
456            if *object_id != self.object_id() || *attr_id != attribute_id {
457                break;
458            }
459            if let ExtentValue::Some { device_offset, .. } = value {
460                if let Some(overlap) = key.overlap(extent_key) {
461                    let range = device_offset + overlap.start - extent_key.start
462                        ..device_offset + overlap.end - extent_key.start;
463                    ensure!(range.is_aligned(block_size), FxfsError::Inconsistent);
464                    if trace {
465                        info!(
466                            store_id = self.store().store_object_id(),
467                            oid = self.object_id(),
468                            device_range:? = range,
469                            len = range.end - range.start,
470                            extent_key:?;
471                            "D",
472                        );
473                    }
474                    allocator
475                        .deallocate(transaction, self.store().store_object_id(), range)
476                        .await?;
477                    deallocated += overlap.end - overlap.start;
478                } else {
479                    break;
480                }
481            }
482            iter.advance().await?;
483        }
484        Ok(deallocated)
485    }
486
487    // Writes aligned data (that should already be encrypted) to the given offset and computes
488    // checksums if requested. The aligned data must be from a single logical file range.
489    async fn write_aligned(
490        &self,
491        buf: BufferRef<'_>,
492        device_offset: u64,
493        crypt_ctx: Option<(u32, u8)>,
494    ) -> Result<MaybeChecksums, Error> {
495        if self.trace() {
496            info!(
497                store_id = self.store().store_object_id(),
498                oid = self.object_id(),
499                device_range:? = (device_offset..device_offset + buf.len() as u64),
500                len = buf.len();
501                "W",
502            );
503        }
504        let store = self.store();
505        store.device_write_ops.fetch_add(1, Ordering::Relaxed);
506        let mut checksums = Vec::new();
507        let _watchdog = Watchdog::new(10, |count| {
508            warn!("Write has been stalled for {} seconds", count * 10);
509        });
510
511        match crypt_ctx {
512            Some((dun, slot)) => {
513                if !store.filesystem().options().barriers_enabled {
514                    return Err(anyhow!(FxfsError::InvalidArgs)
515                        .context("Barriers must be enabled for inline encrypted writes."));
516                }
517                store
518                    .device
519                    .write_with_opts(
520                        device_offset as u64,
521                        buf,
522                        WriteOptions {
523                            inline_crypto: InlineCryptoOptions::enabled(slot, dun),
524                            ..Default::default()
525                        },
526                    )
527                    .await?;
528                Ok(MaybeChecksums::None)
529            }
530            None => {
531                if self.options.skip_checksums {
532                    store
533                        .device
534                        .write_with_opts(device_offset as u64, buf, WriteOptions::default())
535                        .await?;
536                    Ok(MaybeChecksums::None)
537                } else {
538                    try_join!(store.device.write(device_offset, buf), async {
539                        let block_size = self.block_size();
540                        for chunk in buf.as_slice().chunks_exact(block_size as usize) {
541                            checksums.push(fletcher64(chunk, 0));
542                        }
543                        Ok(())
544                    })?;
545                    Ok(MaybeChecksums::Fletcher(checksums))
546                }
547            }
548        }
549    }
550
551    /// Flushes the underlying device.  This is expensive and should be used sparingly.
552    pub async fn flush_device(&self) -> Result<(), Error> {
553        self.store().device().flush().await
554    }
555
556    pub async fn update_allocated_size(
557        &self,
558        transaction: &mut Transaction<'_>,
559        allocated: u64,
560        deallocated: u64,
561    ) -> Result<(), Error> {
562        if allocated == deallocated {
563            return Ok(());
564        }
565        let mut mutation = self.txn_get_object_mutation(transaction).await?;
566        if let ObjectValue::Object {
567            attributes: ObjectAttributes { project_id, allocated_size, .. },
568            ..
569        } = &mut mutation.item.value
570        {
571            // The only way for these to fail are if the volume is inconsistent.
572            *allocated_size = allocated_size
573                .checked_add(allocated)
574                .ok_or_else(|| anyhow!(FxfsError::Inconsistent).context("Allocated size overflow"))?
575                .checked_sub(deallocated)
576                .ok_or_else(|| {
577                    anyhow!(FxfsError::Inconsistent).context("Allocated size underflow")
578                })?;
579
580            if let Some(project_id) = project_id {
581                // The allocated and deallocated shouldn't exceed the max size of the file which is
582                // bound within i64.
583                let diff = i64::try_from(allocated).unwrap() - i64::try_from(deallocated).unwrap();
584                transaction.add(
585                    self.store().store_object_id(),
586                    Mutation::merge_object(
587                        ObjectKey::project_usage(
588                            self.store().root_directory_object_id(),
589                            *project_id,
590                        ),
591                        ObjectValue::BytesAndNodes { bytes: diff, nodes: 0 },
592                    ),
593                );
594            }
595        } else {
596            // This can occur when the object mutation is created from an object in the tree which
597            // was corrupt.
598            bail!(anyhow!(FxfsError::Inconsistent).context("Unexpected object value"));
599        }
600        transaction.add(self.store().store_object_id, Mutation::ObjectStore(mutation));
601        Ok(())
602    }
603
604    pub async fn update_attributes<'a>(
605        &self,
606        transaction: &mut Transaction<'a>,
607        node_attributes: Option<&fio::MutableNodeAttributes>,
608        change_time: Option<Timestamp>,
609    ) -> Result<(), Error> {
610        if let Some(&fio::MutableNodeAttributes { selinux_context: Some(ref context), .. }) =
611            node_attributes
612        {
613            if let fio::SelinuxContext::Data(context) = context {
614                self.set_extended_attribute_impl(
615                    "security.selinux".into(),
616                    context.clone(),
617                    SetExtendedAttributeMode::Set,
618                    transaction,
619                )
620                .await?;
621            } else {
622                return Err(anyhow!(FxfsError::InvalidArgs)
623                    .context("Only set SELinux context with `data` member."));
624            }
625        }
626        self.store()
627            .update_attributes(transaction, self.object_id, node_attributes, change_time)
628            .await
629    }
630
631    /// Zeroes the given range.  The range must be aligned.  Returns the amount of data deallocated.
632    pub async fn zero(
633        &self,
634        transaction: &mut Transaction<'_>,
635        attribute_id: AttributeId,
636        range: Range<u64>,
637    ) -> Result<(), Error> {
638        let deallocated =
639            self.deallocate_old_extents(transaction, attribute_id, range.clone()).await?;
640        if deallocated > 0 {
641            self.update_allocated_size(transaction, 0, deallocated).await?;
642            transaction.add(
643                self.store().store_object_id,
644                Mutation::merge_object(
645                    ObjectKey::extent(self.object_id(), attribute_id, range),
646                    ObjectValue::Extent(ExtentValue::deleted_extent()),
647                ),
648            );
649        }
650        Ok(())
651    }
652
653    // Returns a new aligned buffer (reading the head and tail blocks if necessary) with a copy of
654    // the data from `buf`.
655    pub async fn align_buffer(
656        &self,
657        attribute_id: AttributeId,
658        offset: u64,
659        buf: BufferRef<'_>,
660    ) -> Result<(std::ops::Range<u64>, Buffer<'_>), Error> {
661        let block_size = self.block_size();
662        let end = offset + buf.len() as u64;
663        let aligned =
664            round_down(offset, block_size)..round_up(end, block_size).ok_or(FxfsError::TooBig)?;
665
666        let mut aligned_buf =
667            self.store().device.allocate_buffer((aligned.end - aligned.start) as usize).await;
668
669        // Deal with head alignment.
670        if aligned.start < offset {
671            let mut head_block = aligned_buf.subslice_mut(..block_size as usize);
672            let read = self.read(attribute_id, aligned.start, head_block.reborrow()).await?;
673            head_block.as_mut_slice()[read..].fill(0);
674        }
675
676        // Deal with tail alignment.
677        if aligned.end > end {
678            let end_block_offset = aligned.end - block_size;
679            // There's no need to read the tail block if we read it as part of the head block.
680            if offset <= end_block_offset {
681                let mut tail_block =
682                    aligned_buf.subslice_mut(aligned_buf.len() - block_size as usize..);
683                let read = self.read(attribute_id, end_block_offset, tail_block.reborrow()).await?;
684                tail_block.as_mut_slice()[read..].fill(0);
685            }
686        }
687
688        aligned_buf.as_mut_slice()
689            [(offset - aligned.start) as usize..(end - aligned.start) as usize]
690            .copy_from_slice(buf.as_slice());
691
692        Ok((aligned, aligned_buf))
693    }
694
695    /// Trim an attribute's extents, potentially adding a graveyard trim entry if more trimming is
696    /// needed, so the transaction can be committed without worrying about leaking data.
697    ///
698    /// This doesn't update the size stored in the attribute value - the caller is responsible for
699    /// doing that to keep the size up to date.
700    pub async fn shrink(
701        &self,
702        transaction: &mut Transaction<'_>,
703        attribute_id: AttributeId,
704        size: u64,
705    ) -> Result<NeedsTrim, Error> {
706        let store = self.store();
707        let needs_trim = matches!(
708            store
709                .trim_some(transaction, self.object_id(), attribute_id, TrimMode::FromOffset(size))
710                .await?,
711            TrimResult::Incomplete
712        );
713        if needs_trim {
714            // Add the object to the graveyard in case the following transactions don't get
715            // replayed.
716            let graveyard_id = store.graveyard_directory_object_id();
717            match store
718                .tree
719                .find(&ObjectKey::graveyard_entry(graveyard_id, self.object_id()))
720                .await?
721            {
722                Some(ObjectItem { value: ObjectValue::Some, .. })
723                | Some(ObjectItem { value: ObjectValue::Trim, .. }) => {
724                    // This object is already in the graveyard so we don't need to do anything.
725                }
726                _ => {
727                    transaction.add(
728                        store.store_object_id,
729                        Mutation::replace_or_insert_object(
730                            ObjectKey::graveyard_entry(graveyard_id, self.object_id()),
731                            ObjectValue::Trim,
732                        ),
733                    );
734                }
735            }
736        }
737        Ok(NeedsTrim(needs_trim))
738    }
739
740    /// Reads and decrypts a singular logical range.
741    pub async fn read_and_decrypt(
742        &self,
743        attribute_id: AttributeId,
744        device_offset: u64,
745        file_offset: u64,
746        mut buffer: MutableBufferRef<'_>,
747        key_id: u64,
748    ) -> Result<(), Error> {
749        let store = self.store();
750        store.device_read_ops.fetch_add(1, Ordering::Relaxed);
751
752        let _watchdog = Watchdog::new(10, |count| {
753            warn!("Read has been stalled for {} seconds", count * 10);
754        });
755
756        let (_key_id, key) = self.get_key(Some(key_id)).await?;
757        if let Some(key) = key {
758            if let Some((dun, slot)) =
759                key.crypt_ctx(self.object_id, attribute_id.raw(), file_offset)
760            {
761                store
762                    .device
763                    .read_with_opts(
764                        device_offset as u64,
765                        buffer.reborrow(),
766                        ReadOptions { inline_crypto: InlineCryptoOptions::enabled(slot, dun) },
767                    )
768                    .await?;
769            } else {
770                store.device.read(device_offset, buffer.reborrow()).await?;
771                key.decrypt(
772                    self.object_id,
773                    attribute_id.raw(),
774                    device_offset,
775                    file_offset,
776                    buffer.as_mut_slice(),
777                )?;
778            }
779        } else {
780            store.device.read(device_offset, buffer.reborrow()).await?;
781        }
782
783        Ok(())
784    }
785
786    /// Returns the specified key. If `key_id` is None, it will try and return the fscrypt key if
787    /// it is present, or the volume key if it isn't. If the fscrypt key is present, but the key
788    /// cannot be unwrapped, then this will return `FxfsError::NoKey`. If the volume is not
789    /// encrypted, this returns None.
790    pub async fn get_key(
791        &self,
792        key_id: Option<u64>,
793    ) -> Result<(u64, Option<Arc<dyn Cipher>>), Error> {
794        let store = self.store();
795        let result = match self.encryption {
796            Encryption::None => (VOLUME_DATA_KEY_ID, None),
797            Encryption::CachedKeys => {
798                if let Some(key_id) = key_id {
799                    (
800                        key_id,
801                        Some(
802                            store
803                                .key_manager
804                                .get_key(
805                                    self.object_id,
806                                    store.crypt().ok_or_else(|| anyhow!("No crypt!"))?.as_ref(),
807                                    async || store.get_keys(self.object_id).await,
808                                    key_id,
809                                )
810                                .await?,
811                        ),
812                    )
813                } else {
814                    let (key_id, key) = store
815                        .key_manager
816                        .get_fscrypt_key_if_present(
817                            self.object_id,
818                            store.crypt().ok_or_else(|| anyhow!("No crypt!"))?.as_ref(),
819                            async || store.get_keys(self.object_id).await,
820                        )
821                        .await?;
822                    (key_id, Some(key))
823                }
824            }
825            Encryption::PermanentKeys => {
826                (VOLUME_DATA_KEY_ID, Some(store.key_manager.get(self.object_id).await?.unwrap()))
827            }
828        };
829
830        // Ensure that if the key we receive uses inline encryption, barriers should be enabled.
831        if let Some(ref key) = result.1 {
832            if key.crypt_ctx(self.object_id, 0, 0).is_some() {
833                if !store.filesystem().options().barriers_enabled {
834                    return Err(anyhow!(FxfsError::InvalidArgs)
835                        .context("Barriers must be enabled for inline encrypted writes."));
836                }
837            }
838        }
839
840        Ok(result)
841    }
842
843    /// This will only work for a non-permanent volume data key. This is designed to be used with
844    /// extended attributes where we'll only create the key on demand for directories and encrypted
845    /// files.
846    async fn get_or_create_key(
847        &self,
848        transaction: &mut Transaction<'_>,
849    ) -> Result<Arc<dyn Cipher>, Error> {
850        let store = self.store();
851
852        // Fast path: try and get keys from the cache.
853        if let Some(key) = store.key_manager.get(self.object_id).await.context("get failed")? {
854            return Ok(key);
855        }
856
857        let crypt = store.crypt().ok_or_else(|| anyhow!("No crypt!"))?;
858
859        // Next, see if the keys are already created.
860        let (mut encryption_keys, mut cipher_set) = if let Some(item) =
861            store.tree.find(&ObjectKey::keys(self.object_id)).await.context("find failed")?
862        {
863            if let ObjectValue::Keys(encryption_keys) = item.value {
864                let cipher_set = store
865                    .key_manager
866                    .get_keys(
867                        self.object_id,
868                        crypt.as_ref(),
869                        &mut Some(async || Ok(encryption_keys.clone())),
870                        /* permanent= */ false,
871                        /* force= */ false,
872                    )
873                    .await
874                    .context("get_keys failed")?;
875                match cipher_set.find_key(VOLUME_DATA_KEY_ID) {
876                    FindKeyResult::NotFound => {}
877                    FindKeyResult::Unavailable => return Err(FxfsError::NoKey.into()),
878                    FindKeyResult::Key(key) => return Ok(key),
879                }
880                (encryption_keys, (*cipher_set).clone())
881            } else {
882                return Err(anyhow!(FxfsError::Inconsistent));
883            }
884        } else {
885            Default::default()
886        };
887
888        // Proceed to create the key.  The transaction holds the required locks.
889        let (key, unwrapped_key) = crypt.create_key(self.object_id, KeyPurpose::Data).await?;
890        let cipher: Arc<dyn Cipher> = Arc::new(FxfsCipher::new(&unwrapped_key));
891
892        // Add new cipher to cloned cipher set. This will replace existing one
893        // if transaction is successful.
894        cipher_set.add_key(VOLUME_DATA_KEY_ID, CipherHolder::Cipher(cipher.clone()));
895        let cipher_set = Arc::new(cipher_set);
896
897        // Arrange for the CipherSet to be added to the cache when (and if) the transaction
898        // commits.
899        struct UnwrappedKeys {
900            object_id: u64,
901            new_keys: Arc<CipherSet>,
902        }
903
904        impl AssociatedObject for UnwrappedKeys {
905            fn will_apply_mutation(
906                &self,
907                _mutation: &Mutation,
908                object_id: u64,
909                manager: &ObjectManager,
910            ) {
911                manager.store(object_id).unwrap().key_manager.insert(
912                    self.object_id,
913                    self.new_keys.clone(),
914                    /* permanent= */ false,
915                );
916            }
917        }
918
919        encryption_keys.insert(VOLUME_DATA_KEY_ID, EncryptionKey::Fxfs(key).into());
920
921        transaction.add_with_object(
922            store.store_object_id(),
923            Mutation::replace_or_insert_object(
924                ObjectKey::keys(self.object_id),
925                ObjectValue::keys(encryption_keys),
926            ),
927            AssocObj::Owned(Box::new(UnwrappedKeys {
928                object_id: self.object_id,
929                new_keys: cipher_set,
930            })),
931        );
932
933        Ok(cipher)
934    }
935
936    pub async fn read(
937        &self,
938        attribute_id: AttributeId,
939        offset: u64,
940        mut buf: MutableBufferRef<'_>,
941    ) -> Result<usize, Error> {
942        let fs = self.store().filesystem();
943        let guard = fs
944            .lock_manager()
945            .read_lock(lock_keys![LockKey::object_attribute(
946                self.store().store_object_id(),
947                self.object_id(),
948                attribute_id,
949            )])
950            .await;
951
952        let key = ObjectKey::attribute(self.object_id(), attribute_id, AttributeKey::Attribute);
953        let item = self.store().tree().find(&key).await?;
954        let size = match item {
955            Some(item) if item.key == key => match item.value {
956                ObjectValue::Attribute { size, .. } => size,
957                _ => bail!(FxfsError::Inconsistent),
958            },
959            _ => return Ok(0),
960        };
961        if offset >= size {
962            return Ok(0);
963        }
964        let length = min(buf.len() as u64, size - offset) as usize;
965        buf = buf.subslice_mut(0..length);
966        self.read_unchecked(attribute_id, offset, buf, &guard).await?;
967        Ok(length)
968    }
969
970    /// Read `buf.len()` bytes from the attribute `attribute_id`, starting at `offset`, into `buf`.
971    /// It's required that a read lock on this attribute id is taken before this is called.
972    ///
973    /// This function doesn't do any size checking - any portion of `buf` past the end of the file
974    /// will be filled with zeros. The caller is responsible for enforcing the file size on reads.
975    /// This is because, just looking at the extents, we can't tell the difference between the file
976    /// actually ending and there just being a section at the end with no data (since attributes
977    /// are sparse).
978    pub async fn read_unchecked(
979        &self,
980        attribute_id: AttributeId,
981        mut offset: u64,
982        mut buf: MutableBufferRef<'_>,
983        _guard: &ReadGuard<'_>,
984    ) -> Result<(), Error> {
985        if buf.len() == 0 {
986            return Ok(());
987        }
988        let end_offset = offset + buf.len() as u64;
989
990        self.store().logical_read_ops.fetch_add(1, Ordering::Relaxed);
991
992        // Whilst the read offset must be aligned to the filesystem block size, the buffer need only
993        // be aligned to the device's block size.
994        let block_size = self.block_size() as u64;
995        let device_block_size = self.store().device.block_size() as u64;
996        assert_eq!(offset % block_size, 0);
997        assert_eq!(buf.range().start as u64 % device_block_size, 0);
998        let tree = &self.store().tree;
999        let layer_set = tree.layer_set();
1000        let mut merger = layer_set.merger();
1001        let mut iter = merger
1002            .query(Query::LimitedRange(&ObjectKey::extent(
1003                self.object_id(),
1004                attribute_id,
1005                offset..end_offset,
1006            )))
1007            .await?;
1008        let end_align = ((offset + buf.len() as u64) % block_size) as usize;
1009        let trace = self.trace();
1010        let reads = FuturesUnordered::new();
1011        while let Some(ItemRef {
1012            key:
1013                ObjectKey {
1014                    object_id,
1015                    data: ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent_key)),
1016                },
1017            value: ObjectValue::Extent(extent_value),
1018            ..
1019        }) = iter.get()
1020        {
1021            if *object_id != self.object_id() || *attr_id != attribute_id {
1022                break;
1023            }
1024            ensure!(
1025                extent_key.is_valid() && extent_key.is_aligned(block_size),
1026                FxfsError::Inconsistent
1027            );
1028            if extent_key.start > offset {
1029                // Zero everything up to the start of the extent.
1030                let to_zero = min(extent_key.start - offset, buf.len() as u64) as usize;
1031                buf.as_mut_slice()[..to_zero].fill(0);
1032                buf = buf.subslice_mut(to_zero..);
1033                if buf.is_empty() {
1034                    break;
1035                }
1036                offset += to_zero as u64;
1037            }
1038
1039            if let ExtentValue::Some { device_offset, key_id, mode } = extent_value {
1040                let mut device_offset = device_offset + (offset - extent_key.start);
1041                let key_id = *key_id;
1042
1043                let to_copy = min(buf.len() - end_align, (extent_key.end - offset) as usize);
1044                if to_copy > 0 {
1045                    if trace {
1046                        info!(
1047                            store_id = self.store().store_object_id(),
1048                            oid = self.object_id(),
1049                            device_range:? = (device_offset..device_offset + to_copy as u64),
1050                            offset,
1051                            range:? = **extent_key,
1052                            block_size;
1053                            "R",
1054                        );
1055                    }
1056                    let (mut head, tail) = buf.split_at_mut(to_copy);
1057                    let maybe_bitmap = match mode {
1058                        ExtentMode::OverwritePartial(bitmap) => {
1059                            let mut read_bitmap = bitmap
1060                                .clone()
1061                                .split_off(((offset - extent_key.start) / block_size) as usize);
1062                            read_bitmap.truncate(to_copy / block_size as usize);
1063                            Some(read_bitmap)
1064                        }
1065                        _ => None,
1066                    };
1067                    reads.push(async move {
1068                        self.read_and_decrypt(
1069                            attribute_id,
1070                            device_offset,
1071                            offset,
1072                            head.reborrow(),
1073                            key_id,
1074                        )
1075                        .await?;
1076                        if let Some(bitmap) = maybe_bitmap {
1077                            apply_bitmap_zeroing(self.block_size() as usize, &bitmap, head);
1078                        }
1079                        Ok::<(), Error>(())
1080                    });
1081                    buf = tail;
1082                    if buf.is_empty() {
1083                        break;
1084                    }
1085                    offset += to_copy as u64;
1086                    device_offset += to_copy as u64;
1087                }
1088
1089                // Deal with end alignment by reading the existing contents into an alignment
1090                // buffer.
1091                if offset < extent_key.end && end_align > 0 {
1092                    if let ExtentMode::OverwritePartial(bitmap) = mode {
1093                        let bitmap_offset = (offset - extent_key.start) / block_size;
1094                        if !bitmap.get(bitmap_offset as usize).ok_or(FxfsError::Inconsistent)? {
1095                            // If this block isn't actually initialized, skip it.
1096                            break;
1097                        }
1098                    }
1099                    let mut align_buf =
1100                        self.store().device.allocate_buffer(block_size as usize).await;
1101                    if trace {
1102                        info!(
1103                            store_id = self.store().store_object_id(),
1104                            oid = self.object_id(),
1105                            device_range:? = (device_offset..device_offset + align_buf.len() as u64);
1106                            "RT",
1107                        );
1108                    }
1109                    self.read_and_decrypt(
1110                        attribute_id,
1111                        device_offset,
1112                        offset,
1113                        align_buf.as_mut(),
1114                        key_id,
1115                    )
1116                    .await?;
1117                    buf.as_mut_slice().copy_from_slice(&align_buf.as_slice()[..end_align]);
1118                    buf = buf.subslice_mut(0..0);
1119                    break;
1120                }
1121            } else if extent_key.end >= offset + buf.len() as u64 {
1122                // Deleted extent covers remainder, so we're done.
1123                break;
1124            }
1125
1126            iter.advance().await?;
1127        }
1128        reads.try_collect::<()>().await?;
1129        buf.as_mut_slice().fill(0);
1130        Ok(())
1131    }
1132
1133    /// Reads an entire attribute.
1134    pub async fn read_attr(&self, attribute_id: AttributeId) -> Result<Option<Box<[u8]>>, Error> {
1135        let store = self.store();
1136        let tree = &store.tree;
1137        let layer_set = tree.layer_set();
1138        let mut merger = layer_set.merger();
1139        let key = ObjectKey::attribute(self.object_id(), attribute_id, AttributeKey::Attribute);
1140        let iter = merger.query(Query::FullRange(&key)).await?;
1141        match iter.get() {
1142            Some(item) if item.key == &key => match item.value {
1143                ObjectValue::Attribute { .. } => Ok(Some(self.read_attr_from_iter(iter).await?)),
1144                // Attribute was deleted.
1145                ObjectValue::None => Ok(None),
1146                _ => Err(FxfsError::Inconsistent.into()),
1147            },
1148            _ => Ok(None),
1149        }
1150    }
1151
1152    /// Reads an entire attribute pointed to by `iter`. `iter` must be pointing to the
1153    /// `AttributeKey::Attribute` of the attribute.
1154    pub async fn read_attr_from_iter(
1155        &self,
1156        mut iter: MergerIterator<'_, '_, ObjectKey, ObjectValue>,
1157    ) -> Result<Box<[u8]>, Error> {
1158        let (mut buffer, size, attribute_id) = match iter.get() {
1159            Some(ItemRef {
1160                key:
1161                    ObjectKey {
1162                        object_id,
1163                        data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Attribute),
1164                    },
1165                value: ObjectValue::Attribute { size, .. },
1166                ..
1167            }) if *object_id == self.object_id => {
1168                // TODO(https://fxbug.dev/42073113): size > max buffer size
1169                (
1170                    self.store()
1171                        .device
1172                        .allocate_buffer(round_up(*size, self.block_size()).unwrap() as usize)
1173                        .await,
1174                    *size as usize,
1175                    *attribute_id,
1176                )
1177            }
1178            _ => bail!(FxfsError::InvalidArgs),
1179        };
1180
1181        self.store().logical_read_ops.fetch_add(1, Ordering::Relaxed);
1182        let mut last_offset = 0;
1183        loop {
1184            iter.advance().await?;
1185            match iter.get() {
1186                Some(ItemRef {
1187                    key:
1188                        ObjectKey {
1189                            object_id,
1190                            data:
1191                                ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent_key)),
1192                        },
1193                    value: ObjectValue::Extent(extent_value),
1194                    ..
1195                }) if *object_id == self.object_id() && *attr_id == attribute_id => {
1196                    if let ExtentValue::Some { device_offset, key_id, mode } = extent_value {
1197                        let offset = extent_key.start as usize;
1198                        buffer.as_mut_slice()[last_offset..offset].fill(0);
1199                        let end = std::cmp::min(extent_key.end as usize, buffer.len());
1200                        let maybe_bitmap = match mode {
1201                            ExtentMode::OverwritePartial(bitmap) => {
1202                                // The caller has to adjust the bitmap if necessary, but we always
1203                                // start from the beginning of any extent, so we only truncate.
1204                                let mut read_bitmap = bitmap.clone();
1205                                read_bitmap.truncate(
1206                                    (end - extent_key.start as usize) / self.block_size() as usize,
1207                                );
1208                                Some(read_bitmap)
1209                            }
1210                            _ => None,
1211                        };
1212                        self.read_and_decrypt(
1213                            attribute_id,
1214                            *device_offset,
1215                            extent_key.start,
1216                            buffer.subslice_mut(offset..end as usize),
1217                            *key_id,
1218                        )
1219                        .await?;
1220                        if let Some(bitmap) = maybe_bitmap {
1221                            apply_bitmap_zeroing(
1222                                self.block_size() as usize,
1223                                &bitmap,
1224                                buffer.subslice_mut(offset..end as usize),
1225                            );
1226                        }
1227                        last_offset = end;
1228                        if last_offset >= size {
1229                            break;
1230                        }
1231                    }
1232                }
1233                _ => break,
1234            }
1235        }
1236        buffer.as_mut_slice()[std::cmp::min(last_offset, size)..].fill(0);
1237        Ok(buffer.as_slice()[..size].into())
1238    }
1239
1240    /// Writes potentially unaligned data at `device_offset` and returns checksums if requested.
1241    /// The data will be encrypted if necessary.  `buf` is mutable as an optimization, since the
1242    /// write may require encryption, we can encrypt the buffer in-place rather than copying to
1243    /// another buffer if the write is already aligned.
1244    ///
1245    /// NOTE: This will not create keys if they are missing (it will fail with an error if that
1246    /// happens to be the case).
1247    pub async fn write_at(
1248        &self,
1249        attribute_id: AttributeId,
1250        offset: u64,
1251        buf: MutableBufferRef<'_>,
1252        key_id: Option<u64>,
1253        mut device_offset: u64,
1254    ) -> Result<MaybeChecksums, Error> {
1255        let mut transfer_buf;
1256        let block_size = self.block_size();
1257        let (range, mut transfer_buf_ref) =
1258            if offset % block_size == 0 && buf.len() as u64 % block_size == 0 {
1259                (offset..offset + buf.len() as u64, buf)
1260            } else {
1261                let (range, buf) = self.align_buffer(attribute_id, offset, buf.as_ref()).await?;
1262                transfer_buf = buf;
1263                device_offset -= offset - range.start;
1264                (range, transfer_buf.as_mut())
1265            };
1266
1267        let mut crypt_ctx = None;
1268        if let (_, Some(key)) = self.get_key(key_id).await? {
1269            if let Some(ctx) = key.crypt_ctx(self.object_id, attribute_id.raw(), range.start) {
1270                crypt_ctx = Some(ctx);
1271            } else {
1272                key.encrypt(
1273                    self.object_id,
1274                    attribute_id.raw(),
1275                    device_offset,
1276                    range.start,
1277                    transfer_buf_ref.as_mut_slice(),
1278                )?;
1279            }
1280        }
1281        self.write_aligned(transfer_buf_ref.as_ref(), device_offset, crypt_ctx).await
1282    }
1283
1284    /// Writes to multiple ranges with data provided in `buf`. This function is specifically
1285    /// designed for migration purposes, allowing raw writes to the device without updating
1286    /// object metadata like allocated size or mtime. It's essential for scenarios where
1287    /// data needs to be transferred directly without triggering standard filesystem operations.
1288    #[cfg(feature = "migration")]
1289    pub async fn raw_multi_write(
1290        &self,
1291        transaction: &mut Transaction<'_>,
1292        attribute_id: AttributeId,
1293        key_id: Option<u64>,
1294        ranges: &[Range<u64>],
1295        buf: MutableBufferRef<'_>,
1296    ) -> Result<(), Error> {
1297        self.multi_write_internal(transaction, attribute_id, key_id, ranges, buf).await?;
1298        Ok(())
1299    }
1300
1301    /// This is a low-level write function that writes to multiple ranges. Users should generally
1302    /// use `multi_write` instead of this function as this does not update the object's allocated
1303    /// size, mtime, atime, etc.
1304    ///
1305    /// Returns (allocated, deallocated) bytes on success.
1306    async fn multi_write_internal(
1307        &self,
1308        transaction: &mut Transaction<'_>,
1309        attribute_id: AttributeId,
1310        key_id: Option<u64>,
1311        ranges: &[Range<u64>],
1312        mut buf: MutableBufferRef<'_>,
1313    ) -> Result<(u64, u64), Error> {
1314        if buf.is_empty() {
1315            return Ok((0, 0));
1316        }
1317        let block_size = self.block_size();
1318        let store = self.store();
1319        let store_id = store.store_object_id();
1320
1321        // The only key we allow to be created on-the-fly is a non permanent key wrapped with the
1322        // volume data key.
1323        let (key_id, key) = if key_id == Some(VOLUME_DATA_KEY_ID)
1324            && matches!(self.encryption, Encryption::CachedKeys)
1325        {
1326            (
1327                VOLUME_DATA_KEY_ID,
1328                Some(
1329                    self.get_or_create_key(transaction)
1330                        .await
1331                        .context("get_or_create_key failed")?,
1332                ),
1333            )
1334        } else {
1335            self.get_key(key_id).await?
1336        };
1337        if let Some(key) = &key {
1338            if !key.supports_inline_encryption() {
1339                let mut slice = buf.as_mut_slice();
1340                for r in ranges {
1341                    let l = r.end - r.start;
1342                    let (head, tail) = slice.split_at_mut(l as usize);
1343                    key.encrypt(
1344                        self.object_id,
1345                        attribute_id.raw(),
1346                        0, /* TODO(https://fxbug.dev/421269588): plumb through device_offset. */
1347                        r.start,
1348                        head,
1349                    )?;
1350                    slice = tail;
1351                }
1352            }
1353        }
1354
1355        let mut allocated = 0;
1356        let allocator = store.allocator();
1357        let trace = self.trace();
1358        let mut writes = FuturesOrdered::new();
1359
1360        let mut logical_ranges = ranges.iter();
1361        let mut current_range = logical_ranges.next().unwrap().clone();
1362
1363        while !buf.is_empty() {
1364            let mut device_range = allocator
1365                .allocate(transaction, store_id, buf.len() as u64)
1366                .await
1367                .context("allocation failed")?;
1368            if trace {
1369                info!(
1370                    store_id,
1371                    oid = self.object_id(),
1372                    device_range:?,
1373                    len = device_range.end - device_range.start;
1374                    "A",
1375                );
1376            }
1377            let mut device_range_len = device_range.end - device_range.start;
1378            allocated += device_range_len;
1379            // If inline encryption is NOT supported, this loop should only happen once.
1380            while device_range_len > 0 {
1381                if current_range.end <= current_range.start {
1382                    current_range = logical_ranges.next().unwrap().clone();
1383                }
1384                let (crypt_ctx, split) = if let Some(key) = &key {
1385                    if key.supports_inline_encryption() {
1386                        let split = std::cmp::min(
1387                            current_range.end - current_range.start,
1388                            device_range_len,
1389                        );
1390                        let crypt_ctx =
1391                            key.crypt_ctx(self.object_id, attribute_id.raw(), current_range.start);
1392                        current_range.start += split;
1393                        (crypt_ctx, split)
1394                    } else {
1395                        (None, device_range_len)
1396                    }
1397                } else {
1398                    (None, device_range_len)
1399                };
1400
1401                let (head, tail) = buf.split_at_mut(split as usize);
1402                buf = tail;
1403
1404                writes.push_back(async move {
1405                    let len = head.len() as u64;
1406                    Result::<_, Error>::Ok((
1407                        device_range.start,
1408                        len,
1409                        self.write_aligned(head.as_ref(), device_range.start, crypt_ctx).await?,
1410                    ))
1411                });
1412                device_range.start += split;
1413                device_range_len = device_range.end - device_range.start;
1414            }
1415        }
1416
1417        self.store().logical_write_ops.fetch_add(1, Ordering::Relaxed);
1418        let ((mutations, checksums), deallocated) = try_join!(
1419            async {
1420                let mut current_range = 0..0;
1421                let mut mutations = Vec::new();
1422                let mut out_checksums = Vec::new();
1423                let mut ranges = ranges.iter();
1424                while let Some((mut device_offset, mut len, mut checksums)) =
1425                    writes.try_next().await?
1426                {
1427                    while len > 0 {
1428                        if current_range.end <= current_range.start {
1429                            current_range = ranges.next().unwrap().clone();
1430                        }
1431                        let chunk_len = std::cmp::min(len, current_range.end - current_range.start);
1432                        let tail = checksums.split_off((chunk_len / block_size) as usize);
1433                        if let Some(checksums) = checksums.maybe_as_ref() {
1434                            out_checksums.push((
1435                                device_offset..device_offset + chunk_len,
1436                                checksums.to_owned(),
1437                            ));
1438                        }
1439                        mutations.push(Mutation::merge_object(
1440                            ObjectKey::extent(
1441                                self.object_id(),
1442                                attribute_id,
1443                                current_range.start..current_range.start + chunk_len,
1444                            ),
1445                            ObjectValue::Extent(ExtentValue::new(
1446                                device_offset,
1447                                checksums.to_mode(),
1448                                key_id,
1449                            )),
1450                        ));
1451                        checksums = tail;
1452                        device_offset += chunk_len;
1453                        len -= chunk_len;
1454                        current_range.start += chunk_len;
1455                    }
1456                }
1457                Result::<_, Error>::Ok((mutations, out_checksums))
1458            },
1459            async {
1460                let mut deallocated = 0;
1461                for r in ranges {
1462                    deallocated +=
1463                        self.deallocate_old_extents(transaction, attribute_id, r.clone()).await?;
1464                }
1465                Result::<_, Error>::Ok(deallocated)
1466            }
1467        )?;
1468
1469        for m in mutations {
1470            transaction.add(store_id, m);
1471        }
1472
1473        // Only store checksums in the journal if barriers are not enabled.
1474        if !store.filesystem().options().barriers_enabled {
1475            for (r, c) in checksums {
1476                transaction.add_checksum(r, c, true);
1477            }
1478        }
1479        Ok((allocated, deallocated))
1480    }
1481
1482    /// Writes to multiple ranges with data provided in `buf`.  The buffer can be modified in place
1483    /// if encryption takes place.  The ranges must all be aligned and no change to content size is
1484    /// applied; the caller is responsible for updating size if required.  If `key_id` is None, it
1485    /// means pick the default key for the object which is the fscrypt key if present, or the volume
1486    /// data key, or no key if it's an unencrypted file.
1487    pub async fn multi_write(
1488        &self,
1489        transaction: &mut Transaction<'_>,
1490        attribute_id: AttributeId,
1491        key_id: Option<u64>,
1492        ranges: &[Range<u64>],
1493        buf: MutableBufferRef<'_>,
1494    ) -> Result<(), Error> {
1495        let (allocated, deallocated) =
1496            self.multi_write_internal(transaction, attribute_id, key_id, ranges, buf).await?;
1497        if allocated == 0 && deallocated == 0 {
1498            return Ok(());
1499        }
1500        self.update_allocated_size(transaction, allocated, deallocated).await
1501    }
1502
1503    /// Write data to overwrite extents with the provided set of ranges. This makes a strong
1504    /// assumption that the ranges are actually going to be already allocated overwrite extents and
1505    /// will error out or do something wrong if they aren't. It also assumes the ranges passed to
1506    /// it are sorted.
1507    pub async fn multi_overwrite<'a>(
1508        &'a self,
1509        transaction: &mut Transaction<'a>,
1510        attr_id: AttributeId,
1511        ranges: &[Range<u64>],
1512        mut buf: MutableBufferRef<'_>,
1513    ) -> Result<(), Error> {
1514        if buf.is_empty() {
1515            return Ok(());
1516        }
1517        let block_size = self.block_size();
1518        let store = self.store();
1519        let tree = store.tree();
1520        let store_id = store.store_object_id();
1521
1522        let (key_id, key) = self.get_key(None).await?;
1523        if let Some(key) = &key {
1524            if !key.supports_inline_encryption() {
1525                let mut slice = buf.as_mut_slice();
1526                for r in ranges {
1527                    let l = r.end - r.start;
1528                    let (head, tail) = slice.split_at_mut(l as usize);
1529                    key.encrypt(
1530                        self.object_id,
1531                        attr_id.raw(),
1532                        0, /* TODO(https://fxbug.dev/421269588): plumb through device_offset. */
1533                        r.start,
1534                        head,
1535                    )?;
1536                    slice = tail;
1537                }
1538            }
1539        }
1540
1541        let mut range_iter = ranges.iter();
1542        // There should be at least one range if the buffer has data in it
1543        let mut target_range = range_iter.next().unwrap().clone();
1544        let mut mutations = Vec::new();
1545        let writes = FuturesUnordered::new();
1546
1547        let layer_set = tree.layer_set();
1548        let mut merger = layer_set.merger();
1549        let mut iter = merger
1550            .query(Query::FullRange(&ObjectKey::attribute(
1551                self.object_id(),
1552                attr_id,
1553                AttributeKey::Extent(Extent::search_key_from_offset(target_range.start)),
1554            )))
1555            .await?;
1556
1557        loop {
1558            match iter.get() {
1559                Some(ItemRef {
1560                    key:
1561                        ObjectKey {
1562                            object_id,
1563                            data:
1564                                ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
1565                        },
1566                    value: ObjectValue::Extent(extent_value),
1567                    ..
1568                }) if *object_id == self.object_id() && *attribute_id == attr_id => {
1569                    // If this extent ends before the target range starts (not possible on the
1570                    // first loop because of the query parameters but possible on further loops),
1571                    // advance until we find a the next one we care about.
1572                    if extent.end <= target_range.start {
1573                        iter.advance().await?;
1574                        continue;
1575                    }
1576                    let (device_offset, mode) = match extent_value {
1577                        ExtentValue::None => {
1578                            return Err(anyhow!(FxfsError::Inconsistent)).with_context(|| {
1579                                format!(
1580                                    "multi_overwrite failed: target_range ({}, {}) overlaps with \
1581                                deleted extent found at ({}, {})",
1582                                    target_range.start, target_range.end, extent.start, extent.end,
1583                                )
1584                            });
1585                        }
1586                        ExtentValue::Some { device_offset, mode, .. } => (device_offset, mode),
1587                    };
1588                    // The ranges passed to this function should already by allocated, so
1589                    // extent records should exist for them.
1590                    if extent.start > target_range.start {
1591                        return Err(anyhow!(FxfsError::Inconsistent)).with_context(|| {
1592                            format!(
1593                                "multi_overwrite failed: target range ({}, {}) starts before first \
1594                            extent found at ({}, {})",
1595                                target_range.start, target_range.end, extent.start, extent.end,
1596                            )
1597                        });
1598                    }
1599                    let mut bitmap = match mode {
1600                        ExtentMode::Raw | ExtentMode::Cow(_) => {
1601                            return Err(anyhow!(FxfsError::Inconsistent)).with_context(|| {
1602                                format!(
1603                                    "multi_overwrite failed: \
1604                            extent from ({}, {}) which overlaps target range ({}, {}) had the \
1605                            wrong extent mode",
1606                                    extent.start, extent.end, target_range.start, target_range.end,
1607                                )
1608                            });
1609                        }
1610                        ExtentMode::OverwritePartial(bitmap) => {
1611                            OverwriteBitmaps::new(bitmap.clone())
1612                        }
1613                        ExtentMode::Overwrite => OverwriteBitmaps::None,
1614                    };
1615                    loop {
1616                        let offset_within_extent = target_range.start - extent.start;
1617                        let bitmap_offset = offset_within_extent / block_size;
1618                        let write_device_offset = *device_offset + offset_within_extent;
1619                        let write_end = min(extent.end, target_range.end);
1620                        let write_len = write_end - target_range.start;
1621                        let write_device_range =
1622                            write_device_offset..write_device_offset + write_len;
1623                        let (current_buf, remaining_buf) = buf.split_at_mut(write_len as usize);
1624
1625                        bitmap.set_offset(bitmap_offset as usize);
1626                        let checksum_ranges = ChecksumRangeChunk::group_first_write_ranges(
1627                            &mut bitmap,
1628                            block_size,
1629                            write_device_range,
1630                        );
1631
1632                        let crypt_ctx = if let Some(key) = &key {
1633                            key.crypt_ctx(self.object_id, attr_id.raw(), target_range.start)
1634                        } else {
1635                            None
1636                        };
1637
1638                        writes.push(async move {
1639                            let maybe_checksums = self
1640                                .write_aligned(current_buf.as_ref(), write_device_offset, crypt_ctx)
1641                                .await?;
1642                            Ok::<_, Error>(match maybe_checksums {
1643                                MaybeChecksums::None => Vec::new(),
1644                                MaybeChecksums::Fletcher(checksums) => checksum_ranges
1645                                    .into_iter()
1646                                    .map(
1647                                        |ChecksumRangeChunk {
1648                                             checksum_range,
1649                                             device_range,
1650                                             is_first_write,
1651                                         }| {
1652                                            (
1653                                                device_range,
1654                                                checksums[checksum_range].to_vec(),
1655                                                is_first_write,
1656                                            )
1657                                        },
1658                                    )
1659                                    .collect(),
1660                            })
1661                        });
1662                        buf = remaining_buf;
1663                        target_range.start += write_len;
1664                        if target_range.start == target_range.end {
1665                            match range_iter.next() {
1666                                None => break,
1667                                Some(next_range) => target_range = next_range.clone(),
1668                            }
1669                        }
1670                        if extent.end <= target_range.start {
1671                            break;
1672                        }
1673                    }
1674                    if let Some((mut bitmap, write_bitmap)) = bitmap.take_bitmaps() {
1675                        if bitmap.or(&write_bitmap) {
1676                            let mode = if bitmap.all() {
1677                                ExtentMode::Overwrite
1678                            } else {
1679                                ExtentMode::OverwritePartial(bitmap)
1680                            };
1681                            mutations.push(Mutation::merge_object(
1682                                ObjectKey::extent(self.object_id(), attr_id, extent.clone().into()),
1683                                ObjectValue::Extent(ExtentValue::new(*device_offset, mode, key_id)),
1684                            ))
1685                        }
1686                    }
1687                    if target_range.start == target_range.end {
1688                        break;
1689                    }
1690                    iter.advance().await?;
1691                }
1692                // We've either run past the end of the existing extents or something is wrong with
1693                // the tree. The main section should break if it finishes the ranges, so either
1694                // case, this is an error.
1695                _ => bail!(anyhow!(FxfsError::Internal).context(
1696                    "found a non-extent object record while there were still ranges to process"
1697                )),
1698            }
1699        }
1700
1701        let checksums = writes.try_collect::<Vec<_>>().await?;
1702        // Only store checksums in the journal if barriers are not enabled.
1703        if !store.filesystem().options().barriers_enabled {
1704            for (r, c, first_write) in checksums.into_iter().flatten() {
1705                transaction.add_checksum(r, c, first_write);
1706            }
1707        }
1708
1709        for m in mutations {
1710            transaction.add(store_id, m);
1711        }
1712
1713        Ok(())
1714    }
1715
1716    /// Writes an attribute that should not already exist and therefore does not require trimming.
1717    /// Breaks up the write into multiple transactions if `data.len()` is larger than `batch_size`.
1718    /// If writing the attribute requires multiple transactions, adds the attribute to the
1719    /// graveyard. The caller is responsible for removing the attribute from the graveyard when it
1720    /// commits the last transaction.  This always writes using a key wrapped with the volume data
1721    /// key.
1722    #[trace]
1723    pub async fn write_new_attr_in_batches<'a>(
1724        &'a self,
1725        transaction: &mut Transaction<'a>,
1726        attribute_id: AttributeId,
1727        data: &[u8],
1728        batch_size: usize,
1729    ) -> Result<(), Error> {
1730        transaction.add(
1731            self.store().store_object_id,
1732            Mutation::replace_or_insert_object(
1733                ObjectKey::attribute(self.object_id(), attribute_id, AttributeKey::Attribute),
1734                ObjectValue::attribute(data.len() as u64, false),
1735            ),
1736        );
1737        let chunks = data.chunks(batch_size);
1738        let num_chunks = chunks.len();
1739        if num_chunks > 1 {
1740            transaction.add(
1741                self.store().store_object_id,
1742                Mutation::replace_or_insert_object(
1743                    ObjectKey::graveyard_attribute_entry(
1744                        self.store().graveyard_directory_object_id(),
1745                        self.object_id(),
1746                        attribute_id,
1747                    ),
1748                    ObjectValue::Some,
1749                ),
1750            );
1751        }
1752        let mut start_offset = 0;
1753        for (i, chunk) in chunks.enumerate() {
1754            let rounded_len = round_up(chunk.len() as u64, self.block_size()).unwrap();
1755            let mut buffer = self.store().device.allocate_buffer(rounded_len as usize).await;
1756            let slice = buffer.as_mut_slice();
1757            slice[..chunk.len()].copy_from_slice(chunk);
1758            slice[chunk.len()..].fill(0);
1759            self.multi_write(
1760                transaction,
1761                attribute_id,
1762                Some(VOLUME_DATA_KEY_ID),
1763                &[start_offset..start_offset + rounded_len],
1764                buffer.as_mut(),
1765            )
1766            .await?;
1767            start_offset += rounded_len;
1768            // Do not commit the last chunk.
1769            if i < num_chunks - 1 {
1770                transaction.commit_and_continue().await?;
1771            }
1772        }
1773        Ok(())
1774    }
1775
1776    /// Writes an entire attribute. Returns whether or not the attribute needs to continue being
1777    /// trimmed - if the new data is shorter than the old data, this will trim any extents beyond
1778    /// the end of the new size, but if there were too many for a single transaction, a commit
1779    /// needs to be made before trimming again, so the responsibility is left to the caller so as
1780    /// to not accidentally split the transaction when it's not in a consistent state.  This will
1781    /// write using the volume data key; the fscrypt key is not supported.
1782    pub async fn write_attr(
1783        &self,
1784        transaction: &mut Transaction<'_>,
1785        attribute_id: AttributeId,
1786        data: &[u8],
1787    ) -> Result<NeedsTrim, Error> {
1788        let rounded_len = round_up(data.len() as u64, self.block_size()).unwrap();
1789        let store = self.store();
1790        let tree = store.tree();
1791        let should_trim = if let Some(item) = tree
1792            .find(&ObjectKey::attribute(self.object_id(), attribute_id, AttributeKey::Attribute))
1793            .await?
1794        {
1795            match item.value {
1796                ObjectValue::Attribute { size: _, has_overwrite_extents: true } => {
1797                    bail!(
1798                        anyhow!(FxfsError::Inconsistent)
1799                            .context("write_attr on an attribute with overwrite extents")
1800                    )
1801                }
1802                ObjectValue::Attribute { size, .. } => (data.len() as u64) < size,
1803                _ => bail!(FxfsError::Inconsistent),
1804            }
1805        } else {
1806            false
1807        };
1808        let mut buffer = self.store().device.allocate_buffer(rounded_len as usize).await;
1809        let slice = buffer.as_mut_slice();
1810        slice[..data.len()].copy_from_slice(data);
1811        slice[data.len()..].fill(0);
1812        self.multi_write(
1813            transaction,
1814            attribute_id,
1815            Some(VOLUME_DATA_KEY_ID),
1816            &[0..rounded_len],
1817            buffer.as_mut(),
1818        )
1819        .await?;
1820        transaction.add(
1821            self.store().store_object_id,
1822            Mutation::replace_or_insert_object(
1823                ObjectKey::attribute(self.object_id(), attribute_id, AttributeKey::Attribute),
1824                ObjectValue::attribute(data.len() as u64, false),
1825            ),
1826        );
1827        if should_trim {
1828            self.shrink(transaction, attribute_id, data.len() as u64).await
1829        } else {
1830            Ok(NeedsTrim(false))
1831        }
1832    }
1833
1834    pub async fn list_extended_attributes(&self) -> Result<Vec<Vec<u8>>, Error> {
1835        let layer_set = self.store().tree().layer_set();
1836        let mut merger = layer_set.merger();
1837        // Seek to the first extended attribute key for this object.
1838        let mut iter = merger
1839            .query(Query::FullRange(&ObjectKey::extended_attribute(self.object_id(), Vec::new())))
1840            .await?;
1841        let mut out = Vec::new();
1842        while let Some(item) = iter.get() {
1843            // Skip deleted extended attributes.
1844            if item.value != &ObjectValue::None {
1845                match item.key {
1846                    ObjectKey { object_id, data: ObjectKeyData::ExtendedAttribute { name } }
1847                        if *object_id == self.object_id() =>
1848                    {
1849                        out.push(name.clone());
1850                    }
1851                    // Once we hit a record belonging to another object, or one that is not an
1852                    // extended attribute key, we have reached the end of this object's extended
1853                    // attributes. Subsequent objects' records will start with lower variants
1854                    // (e.g. ObjectKeyData::Object) which trigger this break.
1855                    _ => break,
1856                }
1857            }
1858            iter.advance().await?;
1859        }
1860        Ok(out)
1861    }
1862
1863    /// Looks up the values for the extended attribute `fio::SELINUX_CONTEXT_NAME`, returning it
1864    /// if it is found inline. If it is not inline, it will request use of the
1865    /// `get_extended_attributes` method. If the entry doesn't exist at all, returns None.
1866    pub async fn get_inline_selinux_context(&self) -> Result<Option<fio::SelinuxContext>, Error> {
1867        // This optimization is only useful as long as the attribute is smaller than inline sizes.
1868        // Avoid reading the data out of the attributes.
1869        const_assert!(fio::MAX_SELINUX_CONTEXT_ATTRIBUTE_LEN as usize <= MAX_INLINE_XATTR_SIZE);
1870        let item = match self
1871            .store()
1872            .tree()
1873            .find(&ObjectKey::extended_attribute(
1874                self.object_id(),
1875                fio::SELINUX_CONTEXT_NAME.into(),
1876            ))
1877            .await?
1878        {
1879            Some(item) => item,
1880            None => return Ok(None),
1881        };
1882        match item.value {
1883            ObjectValue::ExtendedAttribute(ExtendedAttributeValue::Inline(value)) => {
1884                Ok(Some(fio::SelinuxContext::Data(value)))
1885            }
1886            ObjectValue::ExtendedAttribute(ExtendedAttributeValue::AttributeId(_)) => {
1887                Ok(Some(fio::SelinuxContext::UseExtendedAttributes(fio::EmptyStruct {})))
1888            }
1889            _ => {
1890                bail!(
1891                    anyhow!(FxfsError::Inconsistent)
1892                        .context("get_inline_extended_attribute: Expected ExtendedAttribute value")
1893                )
1894            }
1895        }
1896    }
1897
1898    pub async fn get_extended_attribute(&self, name: Vec<u8>) -> Result<Vec<u8>, Error> {
1899        let item = self
1900            .store()
1901            .tree()
1902            .find(&ObjectKey::extended_attribute(self.object_id(), name))
1903            .await?
1904            .ok_or(FxfsError::NotFound)?;
1905        match item.value {
1906            ObjectValue::ExtendedAttribute(ExtendedAttributeValue::Inline(value)) => Ok(value),
1907            ObjectValue::ExtendedAttribute(ExtendedAttributeValue::AttributeId(id)) => {
1908                Ok(self.read_attr(id).await?.ok_or(FxfsError::Inconsistent)?.into_vec())
1909            }
1910            _ => {
1911                bail!(
1912                    anyhow!(FxfsError::Inconsistent)
1913                        .context("get_extended_attribute: Expected ExtendedAttribute value")
1914                )
1915            }
1916        }
1917    }
1918
1919    pub async fn set_extended_attribute(
1920        &self,
1921        name: Vec<u8>,
1922        value: Vec<u8>,
1923        mode: SetExtendedAttributeMode,
1924    ) -> Result<(), Error> {
1925        let store = self.store();
1926        // NB: We need to take this lock before we potentially look up the value to prevent racing
1927        // with another set.
1928        let keys = lock_keys![LockKey::object(store.store_object_id(), self.object_id())];
1929        let mut transaction = store.new_transaction(keys, Options::default()).await?;
1930        self.set_extended_attribute_impl(name, value, mode, &mut transaction).await?;
1931        transaction.commit().await?;
1932        Ok(())
1933    }
1934
1935    async fn set_extended_attribute_impl(
1936        &self,
1937        name: Vec<u8>,
1938        value: Vec<u8>,
1939        mode: SetExtendedAttributeMode,
1940        transaction: &mut Transaction<'_>,
1941    ) -> Result<(), Error> {
1942        ensure!(name.len() <= MAX_XATTR_NAME_SIZE, FxfsError::TooBig);
1943        ensure!(value.len() <= MAX_XATTR_VALUE_SIZE, FxfsError::TooBig);
1944        let tree = self.store().tree();
1945        let object_key = ObjectKey::extended_attribute(self.object_id(), name);
1946
1947        let existing_attribute_id = {
1948            let (found, existing_attribute_id) = match tree.find(&object_key).await? {
1949                None => (false, None),
1950                Some(Item { value, .. }) => (
1951                    true,
1952                    match value {
1953                        ObjectValue::ExtendedAttribute(ExtendedAttributeValue::Inline(..)) => None,
1954                        ObjectValue::ExtendedAttribute(ExtendedAttributeValue::AttributeId(id)) => {
1955                            Some(id)
1956                        }
1957                        _ => bail!(
1958                            anyhow!(FxfsError::Inconsistent)
1959                                .context("expected extended attribute value")
1960                        ),
1961                    },
1962                ),
1963            };
1964            match mode {
1965                SetExtendedAttributeMode::Create if found => {
1966                    bail!(FxfsError::AlreadyExists)
1967                }
1968                SetExtendedAttributeMode::Replace if !found => {
1969                    bail!(FxfsError::NotFound)
1970                }
1971                _ => (),
1972            }
1973            existing_attribute_id
1974        };
1975
1976        if let Some(attribute_id) = existing_attribute_id {
1977            // If we already have an attribute id allocated for this extended attribute, we always
1978            // use it, even if the value has shrunk enough to be stored inline. We don't need to
1979            // worry about trimming here for the same reason we don't need to worry about it when
1980            // we delete xattrs - they simply aren't large enough to ever need more than one
1981            // transaction.
1982            let _ = self.write_attr(transaction, attribute_id, &value).await?;
1983        } else if value.len() <= MAX_INLINE_XATTR_SIZE {
1984            transaction.add(
1985                self.store().store_object_id(),
1986                Mutation::replace_or_insert_object(
1987                    object_key,
1988                    ObjectValue::inline_extended_attribute(value),
1989                ),
1990            );
1991        } else {
1992            // If there isn't an existing attribute id and we are going to store the value in
1993            // an attribute, find the next empty attribute id in the range. We search for fxfs
1994            // attribute records specifically, instead of the extended attribute records, because
1995            // even if the extended attribute record is removed the attribute may not be fully
1996            // trimmed yet.
1997            let mut attribute_id = AttributeId::XATTR_RANGE_START;
1998            let layer_set = tree.layer_set();
1999            let mut merger = layer_set.merger();
2000            let key = ObjectKey::attribute(self.object_id(), attribute_id, AttributeKey::Attribute);
2001            let mut iter = merger.query(Query::FullRange(&key)).await?;
2002            loop {
2003                match iter.get() {
2004                    // None means the key passed to seek wasn't found. That means the first
2005                    // attribute is available and we can just stop right away.
2006                    None => break,
2007                    Some(ItemRef {
2008                        key: ObjectKey { object_id, data: ObjectKeyData::Attribute(attr_id, _) },
2009                        value,
2010                        ..
2011                    }) if *object_id == self.object_id() => {
2012                        if matches!(value, ObjectValue::None) {
2013                            // This attribute was once used but is now deleted, so it's safe to use
2014                            // again.
2015                            break;
2016                        }
2017                        if attribute_id < *attr_id {
2018                            // We found a gap - use it.
2019                            break;
2020                        } else if attribute_id == *attr_id {
2021                            // This attribute id is in use, try the next one.
2022                            attribute_id = attribute_id.next();
2023                            if attribute_id == AttributeId::XATTR_RANGE_END {
2024                                bail!(FxfsError::NoSpace);
2025                            }
2026                        }
2027                        // If we don't hit either of those cases, we are still moving through the
2028                        // extent keys for the current attribute, so just keep advancing until the
2029                        // attribute id changes.
2030                    }
2031                    // As we are working our way through the iterator, if we hit anything that
2032                    // doesn't have our object id or attribute key data, we've gone past the end of
2033                    // this section and can stop.
2034                    _ => break,
2035                }
2036                iter.advance().await?;
2037            }
2038
2039            // We know this won't need trimming because it's a new attribute.
2040            let _ = self.write_attr(transaction, attribute_id, &value).await?;
2041            transaction.add(
2042                self.store().store_object_id(),
2043                Mutation::replace_or_insert_object(
2044                    object_key,
2045                    ObjectValue::extended_attribute(attribute_id),
2046                ),
2047            );
2048        }
2049
2050        Ok(())
2051    }
2052
2053    pub async fn remove_extended_attribute(&self, name: Vec<u8>) -> Result<(), Error> {
2054        let store = self.store();
2055        let tree = store.tree();
2056        let object_key = ObjectKey::extended_attribute(self.object_id(), name);
2057
2058        // NB: The API says we have to return an error if the attribute doesn't exist, so we have
2059        // to look it up first to make sure we have a record of it before we delete it. Make sure
2060        // we take a lock and make a transaction before we do so we don't race with other
2061        // operations.
2062        let keys = lock_keys![LockKey::object(store.store_object_id(), self.object_id())];
2063        let mut transaction = store.new_transaction(keys, Options::default()).await?;
2064
2065        let attribute_to_delete =
2066            match tree.find(&object_key).await?.ok_or(FxfsError::NotFound)?.value {
2067                ObjectValue::ExtendedAttribute(ExtendedAttributeValue::AttributeId(id)) => Some(id),
2068                ObjectValue::ExtendedAttribute(ExtendedAttributeValue::Inline(..)) => None,
2069                _ => {
2070                    bail!(
2071                        anyhow!(FxfsError::Inconsistent)
2072                            .context("remove_extended_attribute: Expected ExtendedAttribute value")
2073                    )
2074                }
2075            };
2076
2077        transaction.add(
2078            store.store_object_id(),
2079            Mutation::replace_or_insert_object(object_key, ObjectValue::None),
2080        );
2081
2082        // If the attribute wasn't stored inline, we need to deallocate all the extents too. This
2083        // would normally need to interact with the graveyard for correctness - if there are too
2084        // many extents to delete to fit in a single transaction then we could potentially have
2085        // consistency issues. However, the maximum size of an extended attribute is small enough
2086        // that it will never come close to that limit even in the worst case, so we just delete
2087        // everything in one shot.
2088        if let Some(attribute_id) = attribute_to_delete {
2089            let trim_result = store
2090                .trim_some(
2091                    &mut transaction,
2092                    self.object_id(),
2093                    attribute_id,
2094                    TrimMode::FromOffset(0),
2095                )
2096                .await?;
2097            // In case you didn't read the comment above - this should not be used to delete
2098            // arbitrary attributes!
2099            assert_matches!(trim_result, TrimResult::Done(_));
2100            transaction.add(
2101                store.store_object_id(),
2102                Mutation::replace_or_insert_object(
2103                    ObjectKey::attribute(self.object_id, attribute_id, AttributeKey::Attribute),
2104                    ObjectValue::None,
2105                ),
2106            );
2107        }
2108
2109        transaction.commit().await?;
2110        Ok(())
2111    }
2112
2113    /// Returns a future that will pre-fetches the keys so as to avoid paying the performance
2114    /// penalty later. Must ensure that the object is not removed before the future completes.
2115    pub fn pre_fetch_keys(&self) -> Option<impl Future<Output = ()> + use<S>> {
2116        if let Encryption::CachedKeys = self.encryption {
2117            let owner = self.owner.clone();
2118            let object_id = self.object_id;
2119            Some(async move {
2120                let store = owner.as_ref().as_ref();
2121                if let Some(crypt) = store.crypt() {
2122                    let _ = store
2123                        .key_manager
2124                        .get_keys(
2125                            object_id,
2126                            crypt.as_ref(),
2127                            &mut Some(async || store.get_keys(object_id).await),
2128                            /* permanent= */ false,
2129                            /* force= */ false,
2130                        )
2131                        .await;
2132                }
2133            })
2134        } else {
2135            None
2136        }
2137    }
2138}
2139
2140impl<S: HandleOwner> Drop for StoreObjectHandle<S> {
2141    fn drop(&mut self) {
2142        if self.is_encrypted() {
2143            let _ = self.store().key_manager.remove(self.object_id);
2144        }
2145    }
2146}
2147
2148/// When truncating an object, sometimes it might not be possible to complete the transaction in a
2149/// single transaction, in which case the caller needs to finish trimming the object in subsequent
2150/// transactions (by calling ObjectStore::trim).
2151#[must_use]
2152pub struct NeedsTrim(pub bool);
2153
2154#[cfg(test)]
2155mod tests {
2156    use super::{ChecksumRangeChunk, OverwriteBitmaps};
2157    use crate::errors::FxfsError;
2158    use crate::filesystem::{FxFilesystem, OpenFxFilesystem};
2159    use crate::object_handle::ObjectHandle;
2160    use crate::object_store::data_object_handle::WRITE_ATTR_BATCH_SIZE;
2161    use crate::object_store::transaction::{Mutation, Options, lock_keys};
2162    use crate::object_store::{
2163        AttributeId, AttributeKey, DataObjectHandle, Directory, HandleOptions, LockKey, ObjectKey,
2164        ObjectStore, ObjectValue, SetExtendedAttributeMode, StoreObjectHandle,
2165    };
2166    use bit_vec::BitVec;
2167    use fuchsia_async as fasync;
2168    use futures::join;
2169    use std::sync::Arc;
2170    use storage_device::DeviceHolder;
2171    use storage_device::fake_device::FakeDevice;
2172
2173    const TEST_DEVICE_BLOCK_SIZE: u32 = 512;
2174    const TEST_OBJECT_NAME: &str = "foo";
2175
2176    fn is_error(actual: anyhow::Error, expected: FxfsError) {
2177        assert_eq!(*actual.root_cause().downcast_ref::<FxfsError>().unwrap(), expected)
2178    }
2179
2180    async fn test_filesystem() -> OpenFxFilesystem {
2181        let device = DeviceHolder::new(FakeDevice::new(16384, TEST_DEVICE_BLOCK_SIZE));
2182        FxFilesystem::new_empty(device).await.expect("new_empty failed")
2183    }
2184
2185    async fn test_filesystem_and_empty_object() -> (OpenFxFilesystem, DataObjectHandle<ObjectStore>)
2186    {
2187        let fs = test_filesystem().await;
2188        let store = fs.root_store();
2189
2190        let mut transaction = fs
2191            .root_store()
2192            .new_transaction(
2193                lock_keys![LockKey::object(
2194                    store.store_object_id(),
2195                    store.root_directory_object_id()
2196                )],
2197                Options::default(),
2198            )
2199            .await
2200            .expect("new_transaction failed");
2201
2202        let object =
2203            ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
2204                .await
2205                .expect("create_object failed");
2206
2207        let root_directory =
2208            Directory::open(&store, store.root_directory_object_id()).await.expect("open failed");
2209        root_directory
2210            .add_child_file(&mut transaction, TEST_OBJECT_NAME, &object)
2211            .await
2212            .expect("add_child_file failed");
2213
2214        transaction.commit().await.expect("commit failed");
2215
2216        (fs, object)
2217    }
2218
2219    #[fuchsia::test(threads = 3)]
2220    async fn extended_attribute_double_remove() {
2221        // This test is intended to trip a potential race condition in remove. Removing an
2222        // attribute that doesn't exist is an error, so we need to check before we remove, but if
2223        // we aren't careful, two parallel removes might both succeed in the check and then both
2224        // remove the value.
2225        let (fs, object) = test_filesystem_and_empty_object().await;
2226        let basic = Arc::new(StoreObjectHandle::new(
2227            object.owner().clone(),
2228            object.object_id(),
2229            /* permanent_keys: */ false,
2230            HandleOptions::default(),
2231            false,
2232        ));
2233        let basic_a = basic.clone();
2234        let basic_b = basic.clone();
2235
2236        basic
2237            .set_extended_attribute(
2238                b"security.selinux".to_vec(),
2239                b"bar".to_vec(),
2240                SetExtendedAttributeMode::Set,
2241            )
2242            .await
2243            .expect("failed to set attribute");
2244
2245        // Try to remove the attribute twice at the same time. One should succeed in the race and
2246        // return Ok, and the other should fail the race and return NOT_FOUND.
2247        let a_task = fasync::Task::spawn(async move {
2248            basic_a.remove_extended_attribute(b"security.selinux".to_vec()).await
2249        });
2250        let b_task = fasync::Task::spawn(async move {
2251            basic_b.remove_extended_attribute(b"security.selinux".to_vec()).await
2252        });
2253        match join!(a_task, b_task) {
2254            (Ok(()), Ok(())) => panic!("both remove calls succeeded"),
2255            (Err(_), Err(_)) => panic!("both remove calls failed"),
2256
2257            (Ok(()), Err(e)) => is_error(e, FxfsError::NotFound),
2258            (Err(e), Ok(())) => is_error(e, FxfsError::NotFound),
2259        }
2260
2261        fs.close().await.expect("Close failed");
2262    }
2263
2264    #[fuchsia::test(threads = 3)]
2265    async fn extended_attribute_double_create() {
2266        // This test is intended to trip a potential race in set when using the create flag,
2267        // similar to above. If the create mode is set, we need to check that the attribute isn't
2268        // already created, but if two parallel creates both succeed in that check, and we aren't
2269        // careful with locking, they will both succeed and one will overwrite the other.
2270        let (fs, object) = test_filesystem_and_empty_object().await;
2271        let basic = Arc::new(StoreObjectHandle::new(
2272            object.owner().clone(),
2273            object.object_id(),
2274            /* permanent_keys: */ false,
2275            HandleOptions::default(),
2276            false,
2277        ));
2278        let basic_a = basic.clone();
2279        let basic_b = basic.clone();
2280
2281        // Try to set the attribute twice at the same time. One should succeed in the race and
2282        // return Ok, and the other should fail the race and return ALREADY_EXISTS.
2283        let a_task = fasync::Task::spawn(async move {
2284            basic_a
2285                .set_extended_attribute(
2286                    b"security.selinux".to_vec(),
2287                    b"one".to_vec(),
2288                    SetExtendedAttributeMode::Create,
2289                )
2290                .await
2291        });
2292        let b_task = fasync::Task::spawn(async move {
2293            basic_b
2294                .set_extended_attribute(
2295                    b"security.selinux".to_vec(),
2296                    b"two".to_vec(),
2297                    SetExtendedAttributeMode::Create,
2298                )
2299                .await
2300        });
2301        match join!(a_task, b_task) {
2302            (Ok(()), Ok(())) => panic!("both set calls succeeded"),
2303            (Err(_), Err(_)) => panic!("both set calls failed"),
2304
2305            (Ok(()), Err(e)) => {
2306                assert_eq!(
2307                    basic
2308                        .get_extended_attribute(b"security.selinux".to_vec())
2309                        .await
2310                        .expect("failed to get xattr"),
2311                    b"one"
2312                );
2313                is_error(e, FxfsError::AlreadyExists);
2314            }
2315            (Err(e), Ok(())) => {
2316                assert_eq!(
2317                    basic
2318                        .get_extended_attribute(b"security.selinux".to_vec())
2319                        .await
2320                        .expect("failed to get xattr"),
2321                    b"two"
2322                );
2323                is_error(e, FxfsError::AlreadyExists);
2324            }
2325        }
2326
2327        fs.close().await.expect("Close failed");
2328    }
2329
2330    struct TestAttr {
2331        name: Vec<u8>,
2332        value: Vec<u8>,
2333    }
2334
2335    impl TestAttr {
2336        fn new(name: impl AsRef<[u8]>, value: impl AsRef<[u8]>) -> Self {
2337            Self { name: name.as_ref().to_vec(), value: value.as_ref().to_vec() }
2338        }
2339        fn name(&self) -> Vec<u8> {
2340            self.name.clone()
2341        }
2342        fn value(&self) -> Vec<u8> {
2343            self.value.clone()
2344        }
2345    }
2346
2347    #[fuchsia::test]
2348    async fn extended_attributes() {
2349        let (fs, object) = test_filesystem_and_empty_object().await;
2350
2351        let test_attr = TestAttr::new(b"security.selinux", b"foo");
2352
2353        assert_eq!(object.list_extended_attributes().await.unwrap(), Vec::<Vec<u8>>::new());
2354        is_error(
2355            object.get_extended_attribute(test_attr.name()).await.unwrap_err(),
2356            FxfsError::NotFound,
2357        );
2358
2359        object
2360            .set_extended_attribute(
2361                test_attr.name(),
2362                test_attr.value(),
2363                SetExtendedAttributeMode::Set,
2364            )
2365            .await
2366            .unwrap();
2367        assert_eq!(object.list_extended_attributes().await.unwrap(), vec![test_attr.name()]);
2368        assert_eq!(
2369            object.get_extended_attribute(test_attr.name()).await.unwrap(),
2370            test_attr.value()
2371        );
2372
2373        object.remove_extended_attribute(test_attr.name()).await.unwrap();
2374        assert_eq!(object.list_extended_attributes().await.unwrap(), Vec::<Vec<u8>>::new());
2375        is_error(
2376            object.get_extended_attribute(test_attr.name()).await.unwrap_err(),
2377            FxfsError::NotFound,
2378        );
2379
2380        // Make sure we can object the same attribute being set again.
2381        object
2382            .set_extended_attribute(
2383                test_attr.name(),
2384                test_attr.value(),
2385                SetExtendedAttributeMode::Set,
2386            )
2387            .await
2388            .unwrap();
2389        assert_eq!(object.list_extended_attributes().await.unwrap(), vec![test_attr.name()]);
2390        assert_eq!(
2391            object.get_extended_attribute(test_attr.name()).await.unwrap(),
2392            test_attr.value()
2393        );
2394
2395        object.remove_extended_attribute(test_attr.name()).await.unwrap();
2396        assert_eq!(object.list_extended_attributes().await.unwrap(), Vec::<Vec<u8>>::new());
2397        is_error(
2398            object.get_extended_attribute(test_attr.name()).await.unwrap_err(),
2399            FxfsError::NotFound,
2400        );
2401
2402        fs.close().await.expect("close failed");
2403    }
2404
2405    #[fuchsia::test]
2406    async fn large_extended_attribute() {
2407        let (fs, object) = test_filesystem_and_empty_object().await;
2408
2409        let test_attr = TestAttr::new(b"security.selinux", vec![3u8; 300]);
2410
2411        object
2412            .set_extended_attribute(
2413                test_attr.name(),
2414                test_attr.value(),
2415                SetExtendedAttributeMode::Set,
2416            )
2417            .await
2418            .unwrap();
2419        assert_eq!(
2420            object.get_extended_attribute(test_attr.name()).await.unwrap(),
2421            test_attr.value()
2422        );
2423
2424        // Probe the fxfs attributes to make sure it did the expected thing. This relies on inside
2425        // knowledge of how the attribute id is chosen.
2426        assert_eq!(
2427            object
2428                .read_attr(AttributeId::XATTR_RANGE_START)
2429                .await
2430                .expect("read_attr failed")
2431                .expect("read_attr returned none")
2432                .into_vec(),
2433            test_attr.value()
2434        );
2435
2436        object.remove_extended_attribute(test_attr.name()).await.unwrap();
2437        is_error(
2438            object.get_extended_attribute(test_attr.name()).await.unwrap_err(),
2439            FxfsError::NotFound,
2440        );
2441
2442        // Make sure we can object the same attribute being set again.
2443        object
2444            .set_extended_attribute(
2445                test_attr.name(),
2446                test_attr.value(),
2447                SetExtendedAttributeMode::Set,
2448            )
2449            .await
2450            .unwrap();
2451        assert_eq!(
2452            object.get_extended_attribute(test_attr.name()).await.unwrap(),
2453            test_attr.value()
2454        );
2455        object.remove_extended_attribute(test_attr.name()).await.unwrap();
2456        is_error(
2457            object.get_extended_attribute(test_attr.name()).await.unwrap_err(),
2458            FxfsError::NotFound,
2459        );
2460
2461        fs.close().await.expect("close failed");
2462    }
2463
2464    #[fuchsia::test]
2465    async fn multiple_extended_attributes() {
2466        let (fs, object) = test_filesystem_and_empty_object().await;
2467
2468        let attrs = [
2469            TestAttr::new(b"security.selinux", b"foo"),
2470            TestAttr::new(b"large.attribute", vec![3u8; 300]),
2471            TestAttr::new(b"an.attribute", b"asdf"),
2472            TestAttr::new(b"user.big", vec![5u8; 288]),
2473            TestAttr::new(b"user.tiny", b"smol"),
2474            TestAttr::new(b"this string doesn't matter", b"the quick brown fox etc"),
2475            TestAttr::new(b"also big", vec![7u8; 500]),
2476            TestAttr::new(b"all.ones", vec![1u8; 11111]),
2477        ];
2478
2479        for i in 0..attrs.len() {
2480            object
2481                .set_extended_attribute(
2482                    attrs[i].name(),
2483                    attrs[i].value(),
2484                    SetExtendedAttributeMode::Set,
2485                )
2486                .await
2487                .unwrap();
2488            assert_eq!(
2489                object.get_extended_attribute(attrs[i].name()).await.unwrap(),
2490                attrs[i].value()
2491            );
2492        }
2493
2494        for i in 0..attrs.len() {
2495            // Make sure expected attributes are still available.
2496            let mut found_attrs = object.list_extended_attributes().await.unwrap();
2497            let mut expected_attrs: Vec<Vec<u8>> = attrs.iter().skip(i).map(|a| a.name()).collect();
2498            found_attrs.sort();
2499            expected_attrs.sort();
2500            assert_eq!(found_attrs, expected_attrs);
2501            for j in i..attrs.len() {
2502                assert_eq!(
2503                    object.get_extended_attribute(attrs[j].name()).await.unwrap(),
2504                    attrs[j].value()
2505                );
2506            }
2507
2508            object.remove_extended_attribute(attrs[i].name()).await.expect("failed to remove");
2509            is_error(
2510                object.get_extended_attribute(attrs[i].name()).await.unwrap_err(),
2511                FxfsError::NotFound,
2512            );
2513        }
2514
2515        fs.close().await.expect("close failed");
2516    }
2517
2518    #[fuchsia::test]
2519    async fn multiple_extended_attributes_delete() {
2520        let (fs, object) = test_filesystem_and_empty_object().await;
2521        let store = object.owner().clone();
2522
2523        let attrs = [
2524            TestAttr::new(b"security.selinux", b"foo"),
2525            TestAttr::new(b"large.attribute", vec![3u8; 300]),
2526            TestAttr::new(b"an.attribute", b"asdf"),
2527            TestAttr::new(b"user.big", vec![5u8; 288]),
2528            TestAttr::new(b"user.tiny", b"smol"),
2529            TestAttr::new(b"this string doesn't matter", b"the quick brown fox etc"),
2530            TestAttr::new(b"also big", vec![7u8; 500]),
2531            TestAttr::new(b"all.ones", vec![1u8; 11111]),
2532        ];
2533
2534        for i in 0..attrs.len() {
2535            object
2536                .set_extended_attribute(
2537                    attrs[i].name(),
2538                    attrs[i].value(),
2539                    SetExtendedAttributeMode::Set,
2540                )
2541                .await
2542                .unwrap();
2543            assert_eq!(
2544                object.get_extended_attribute(attrs[i].name()).await.unwrap(),
2545                attrs[i].value()
2546            );
2547        }
2548
2549        // Unlink the file
2550        let root_directory =
2551            Directory::open(object.owner(), object.store().root_directory_object_id())
2552                .await
2553                .expect("open failed");
2554        let mut transaction = fs
2555            .root_store()
2556            .new_transaction(
2557                lock_keys![
2558                    LockKey::object(store.store_object_id(), store.root_directory_object_id()),
2559                    LockKey::object(store.store_object_id(), object.object_id()),
2560                ],
2561                Options::default(),
2562            )
2563            .await
2564            .expect("new_transaction failed");
2565        crate::object_store::directory::replace_child(
2566            &mut transaction,
2567            None,
2568            (&root_directory, TEST_OBJECT_NAME),
2569        )
2570        .await
2571        .expect("replace_child failed");
2572        transaction.commit().await.unwrap();
2573        store.tombstone_object(object.object_id(), Options::default()).await.unwrap();
2574
2575        crate::fsck::fsck(fs.clone()).await.unwrap();
2576
2577        fs.close().await.expect("close failed");
2578    }
2579
2580    #[fuchsia::test]
2581    async fn extended_attribute_changing_sizes() {
2582        let (fs, object) = test_filesystem_and_empty_object().await;
2583
2584        let test_name = b"security.selinux";
2585        let test_small_attr = TestAttr::new(test_name, b"smol");
2586        let test_large_attr = TestAttr::new(test_name, vec![3u8; 300]);
2587
2588        object
2589            .set_extended_attribute(
2590                test_small_attr.name(),
2591                test_small_attr.value(),
2592                SetExtendedAttributeMode::Set,
2593            )
2594            .await
2595            .unwrap();
2596        assert_eq!(
2597            object.get_extended_attribute(test_small_attr.name()).await.unwrap(),
2598            test_small_attr.value()
2599        );
2600
2601        // With a small attribute, we don't expect it to write to an fxfs attribute.
2602        assert!(
2603            object
2604                .read_attr(AttributeId::XATTR_RANGE_START)
2605                .await
2606                .expect("read_attr failed")
2607                .is_none()
2608        );
2609
2610        crate::fsck::fsck(fs.clone()).await.unwrap();
2611
2612        object
2613            .set_extended_attribute(
2614                test_large_attr.name(),
2615                test_large_attr.value(),
2616                SetExtendedAttributeMode::Set,
2617            )
2618            .await
2619            .unwrap();
2620        assert_eq!(
2621            object.get_extended_attribute(test_large_attr.name()).await.unwrap(),
2622            test_large_attr.value()
2623        );
2624
2625        // Once the value is above the threshold, we expect it to get upgraded to an fxfs
2626        // attribute.
2627        assert_eq!(
2628            object
2629                .read_attr(AttributeId::XATTR_RANGE_START)
2630                .await
2631                .expect("read_attr failed")
2632                .expect("read_attr returned none")
2633                .into_vec(),
2634            test_large_attr.value()
2635        );
2636
2637        crate::fsck::fsck(fs.clone()).await.unwrap();
2638
2639        object
2640            .set_extended_attribute(
2641                test_small_attr.name(),
2642                test_small_attr.value(),
2643                SetExtendedAttributeMode::Set,
2644            )
2645            .await
2646            .unwrap();
2647        assert_eq!(
2648            object.get_extended_attribute(test_small_attr.name()).await.unwrap(),
2649            test_small_attr.value()
2650        );
2651
2652        // Even though we are back under the threshold, we still expect it to be stored in an fxfs
2653        // attribute, because we don't downgrade to inline once we've allocated one.
2654        assert_eq!(
2655            object
2656                .read_attr(AttributeId::XATTR_RANGE_START)
2657                .await
2658                .expect("read_attr failed")
2659                .expect("read_attr returned none")
2660                .into_vec(),
2661            test_small_attr.value()
2662        );
2663
2664        crate::fsck::fsck(fs.clone()).await.unwrap();
2665
2666        object.remove_extended_attribute(test_small_attr.name()).await.expect("failed to remove");
2667
2668        crate::fsck::fsck(fs.clone()).await.unwrap();
2669
2670        fs.close().await.expect("close failed");
2671    }
2672
2673    #[fuchsia::test]
2674    async fn extended_attribute_max_size() {
2675        let (fs, object) = test_filesystem_and_empty_object().await;
2676
2677        let test_attr = TestAttr::new(
2678            vec![3u8; super::MAX_XATTR_NAME_SIZE],
2679            vec![1u8; super::MAX_XATTR_VALUE_SIZE],
2680        );
2681
2682        object
2683            .set_extended_attribute(
2684                test_attr.name(),
2685                test_attr.value(),
2686                SetExtendedAttributeMode::Set,
2687            )
2688            .await
2689            .unwrap();
2690        assert_eq!(
2691            object.get_extended_attribute(test_attr.name()).await.unwrap(),
2692            test_attr.value()
2693        );
2694        assert_eq!(object.list_extended_attributes().await.unwrap(), vec![test_attr.name()]);
2695        object.remove_extended_attribute(test_attr.name()).await.unwrap();
2696
2697        fs.close().await.expect("close failed");
2698    }
2699
2700    #[fuchsia::test]
2701    async fn extended_attribute_remove_then_create() {
2702        let (fs, object) = test_filesystem_and_empty_object().await;
2703
2704        let test_attr = TestAttr::new(
2705            vec![3u8; super::MAX_XATTR_NAME_SIZE],
2706            vec![1u8; super::MAX_XATTR_VALUE_SIZE],
2707        );
2708
2709        object
2710            .set_extended_attribute(
2711                test_attr.name(),
2712                test_attr.value(),
2713                SetExtendedAttributeMode::Create,
2714            )
2715            .await
2716            .unwrap();
2717        fs.journal().force_compact().await.unwrap();
2718        object.remove_extended_attribute(test_attr.name()).await.unwrap();
2719        object
2720            .set_extended_attribute(
2721                test_attr.name(),
2722                test_attr.value(),
2723                SetExtendedAttributeMode::Create,
2724            )
2725            .await
2726            .unwrap();
2727
2728        assert_eq!(
2729            object.get_extended_attribute(test_attr.name()).await.unwrap(),
2730            test_attr.value()
2731        );
2732
2733        fs.close().await.expect("close failed");
2734    }
2735
2736    #[fuchsia::test]
2737    async fn large_extended_attribute_max_number() {
2738        let (fs, object) = test_filesystem_and_empty_object().await;
2739
2740        let max_xattrs = AttributeId::XATTR_RANGE_END.raw() - AttributeId::XATTR_RANGE_START.raw();
2741        for i in 0..max_xattrs {
2742            let test_attr = TestAttr::new(format!("{}", i).as_bytes(), vec![0x3; 300]);
2743            object
2744                .set_extended_attribute(
2745                    test_attr.name(),
2746                    test_attr.value(),
2747                    SetExtendedAttributeMode::Set,
2748                )
2749                .await
2750                .unwrap_or_else(|_| panic!("failed to set xattr number {}", i));
2751        }
2752
2753        // That should have taken up all the attributes we've allocated to extended attributes, so
2754        // this one should return ERR_NO_SPACE.
2755        match object
2756            .set_extended_attribute(
2757                b"one.too.many".to_vec(),
2758                vec![0x3; 300],
2759                SetExtendedAttributeMode::Set,
2760            )
2761            .await
2762        {
2763            Ok(()) => panic!("set should not succeed"),
2764            Err(e) => is_error(e, FxfsError::NoSpace),
2765        }
2766
2767        // But inline attributes don't need an attribute number, so it should work fine.
2768        object
2769            .set_extended_attribute(
2770                b"this.is.okay".to_vec(),
2771                b"small value".to_vec(),
2772                SetExtendedAttributeMode::Set,
2773            )
2774            .await
2775            .unwrap();
2776
2777        // And updating existing ones should be okay.
2778        object
2779            .set_extended_attribute(b"11".to_vec(), vec![0x4; 300], SetExtendedAttributeMode::Set)
2780            .await
2781            .unwrap();
2782        object
2783            .set_extended_attribute(
2784                b"12".to_vec(),
2785                vec![0x1; 300],
2786                SetExtendedAttributeMode::Replace,
2787            )
2788            .await
2789            .unwrap();
2790
2791        // And we should be able to remove an attribute and set another one.
2792        object.remove_extended_attribute(b"5".to_vec()).await.unwrap();
2793        object
2794            .set_extended_attribute(
2795                b"new attr".to_vec(),
2796                vec![0x3; 300],
2797                SetExtendedAttributeMode::Set,
2798            )
2799            .await
2800            .unwrap();
2801
2802        fs.close().await.expect("close failed");
2803    }
2804
2805    #[fuchsia::test]
2806    async fn write_attr_trims_beyond_new_end() {
2807        // When writing, multi_write will deallocate old extents that overlap with the new data,
2808        // but it doesn't trim anything beyond that, since it doesn't know what the total size will
2809        // be. write_attr does know, because it writes the whole attribute at once, so we need to
2810        // make sure it cleans up properly.
2811        let (fs, object) = test_filesystem_and_empty_object().await;
2812
2813        let block_size = fs.block_size();
2814        let buf_size = block_size * 2;
2815        let attribute_id = AttributeId::TEST_ID;
2816
2817        let mut transaction = (*object).new_transaction(attribute_id).await.unwrap();
2818        let mut buffer = object.allocate_buffer(buf_size as usize).await;
2819        buffer.as_mut_slice().fill(3);
2820        // Writing two separate ranges, even if they are contiguous, forces them to be separate
2821        // extent records.
2822        object
2823            .multi_write(
2824                &mut transaction,
2825                attribute_id,
2826                &[0..block_size, block_size..block_size * 2],
2827                buffer.as_mut(),
2828            )
2829            .await
2830            .unwrap();
2831        transaction.add(
2832            object.store().store_object_id,
2833            Mutation::replace_or_insert_object(
2834                ObjectKey::attribute(object.object_id(), attribute_id, AttributeKey::Attribute),
2835                ObjectValue::attribute(block_size * 2, false),
2836            ),
2837        );
2838        transaction.commit().await.unwrap();
2839
2840        crate::fsck::fsck(fs.clone()).await.unwrap();
2841
2842        let mut transaction = (*object).new_transaction(attribute_id).await.unwrap();
2843        let needs_trim = (*object)
2844            .write_attr(&mut transaction, attribute_id, &vec![3u8; block_size as usize])
2845            .await
2846            .unwrap();
2847        assert!(!needs_trim.0);
2848        transaction.commit().await.unwrap();
2849
2850        crate::fsck::fsck(fs.clone()).await.unwrap();
2851
2852        fs.close().await.expect("close failed");
2853    }
2854
2855    #[fuchsia::test]
2856    async fn write_new_attr_in_batches_multiple_txns() {
2857        let (fs, object) = test_filesystem_and_empty_object().await;
2858        let merkle_tree = vec![1; 3 * WRITE_ATTR_BATCH_SIZE];
2859        let mut transaction = (*object).new_transaction(AttributeId::TEST_ID).await.unwrap();
2860        object
2861            .write_new_attr_in_batches(
2862                &mut transaction,
2863                AttributeId::TEST_ID,
2864                &merkle_tree,
2865                WRITE_ATTR_BATCH_SIZE,
2866            )
2867            .await
2868            .expect("failed to write merkle attribute");
2869
2870        transaction.add(
2871            object.store().store_object_id,
2872            Mutation::replace_or_insert_object(
2873                ObjectKey::graveyard_attribute_entry(
2874                    object.store().graveyard_directory_object_id(),
2875                    object.object_id(),
2876                    AttributeId::TEST_ID,
2877                ),
2878                ObjectValue::None,
2879            ),
2880        );
2881        transaction.commit().await.unwrap();
2882        assert_eq!(
2883            object.read_attr(AttributeId::TEST_ID).await.expect("read_attr failed"),
2884            Some(merkle_tree.into())
2885        );
2886
2887        fs.close().await.expect("close failed");
2888    }
2889
2890    // Running on target only, to use fake time features in the executor.
2891    #[cfg(target_os = "fuchsia")]
2892    #[fuchsia::test(allow_stalls = false)]
2893    async fn test_watchdog() {
2894        use super::Watchdog;
2895        use fuchsia_async::{MonotonicDuration, MonotonicInstant, TestExecutor};
2896        use std::sync::mpsc::channel;
2897
2898        TestExecutor::advance_to(make_time(0)).await;
2899        let (sender, receiver) = channel();
2900
2901        fn make_time(time_secs: i64) -> MonotonicInstant {
2902            MonotonicInstant::from_nanos(0) + MonotonicDuration::from_seconds(time_secs)
2903        }
2904
2905        {
2906            let _watchdog = Watchdog::new(10, move |count| {
2907                sender.send(count).expect("Sending value");
2908            });
2909
2910            // Too early.
2911            TestExecutor::advance_to(make_time(5)).await;
2912            receiver.try_recv().expect_err("Should not have message");
2913
2914            // First message.
2915            TestExecutor::advance_to(make_time(10)).await;
2916            assert_eq!(1, receiver.recv().expect("Receiving"));
2917
2918            // Too early for the next.
2919            TestExecutor::advance_to(make_time(15)).await;
2920            receiver.try_recv().expect_err("Should not have message");
2921
2922            // Missed one. They'll be spooled up.
2923            TestExecutor::advance_to(make_time(30)).await;
2924            assert_eq!(2, receiver.recv().expect("Receiving"));
2925            assert_eq!(3, receiver.recv().expect("Receiving"));
2926        }
2927
2928        // Watchdog is dropped, nothing should trigger.
2929        TestExecutor::advance_to(make_time(100)).await;
2930        receiver.recv().expect_err("Watchdog should be gone");
2931    }
2932
2933    #[fuchsia::test]
2934    fn test_checksum_range_chunk() {
2935        let block_size = 4096;
2936
2937        // No bitmap means one chunk that covers the whole range
2938        assert_eq!(
2939            ChecksumRangeChunk::group_first_write_ranges(
2940                &mut OverwriteBitmaps::None,
2941                block_size,
2942                block_size * 2..block_size * 5,
2943            ),
2944            vec![ChecksumRangeChunk {
2945                checksum_range: 0..3,
2946                device_range: block_size * 2..block_size * 5,
2947                is_first_write: false,
2948            }],
2949        );
2950
2951        let mut bitmaps = OverwriteBitmaps::new(BitVec::from_bytes(&[0b11110000]));
2952        assert_eq!(
2953            ChecksumRangeChunk::group_first_write_ranges(
2954                &mut bitmaps,
2955                block_size,
2956                block_size * 2..block_size * 5,
2957            ),
2958            vec![ChecksumRangeChunk {
2959                checksum_range: 0..3,
2960                device_range: block_size * 2..block_size * 5,
2961                is_first_write: false,
2962            }],
2963        );
2964        assert_eq!(
2965            bitmaps.take_bitmaps(),
2966            Some((BitVec::from_bytes(&[0b11110000]), BitVec::from_bytes(&[0b11100000])))
2967        );
2968
2969        let mut bitmaps = OverwriteBitmaps::new(BitVec::from_bytes(&[0b11110000]));
2970        bitmaps.set_offset(2);
2971        assert_eq!(
2972            ChecksumRangeChunk::group_first_write_ranges(
2973                &mut bitmaps,
2974                block_size,
2975                block_size * 2..block_size * 5,
2976            ),
2977            vec![
2978                ChecksumRangeChunk {
2979                    checksum_range: 0..2,
2980                    device_range: block_size * 2..block_size * 4,
2981                    is_first_write: false,
2982                },
2983                ChecksumRangeChunk {
2984                    checksum_range: 2..3,
2985                    device_range: block_size * 4..block_size * 5,
2986                    is_first_write: true,
2987                },
2988            ],
2989        );
2990        assert_eq!(
2991            bitmaps.take_bitmaps(),
2992            Some((BitVec::from_bytes(&[0b11110000]), BitVec::from_bytes(&[0b00111000])))
2993        );
2994
2995        let mut bitmaps = OverwriteBitmaps::new(BitVec::from_bytes(&[0b11110000]));
2996        bitmaps.set_offset(4);
2997        assert_eq!(
2998            ChecksumRangeChunk::group_first_write_ranges(
2999                &mut bitmaps,
3000                block_size,
3001                block_size * 2..block_size * 5,
3002            ),
3003            vec![ChecksumRangeChunk {
3004                checksum_range: 0..3,
3005                device_range: block_size * 2..block_size * 5,
3006                is_first_write: true,
3007            }],
3008        );
3009        assert_eq!(
3010            bitmaps.take_bitmaps(),
3011            Some((BitVec::from_bytes(&[0b11110000]), BitVec::from_bytes(&[0b00001110])))
3012        );
3013
3014        let mut bitmaps = OverwriteBitmaps::new(BitVec::from_bytes(&[0b01010101]));
3015        assert_eq!(
3016            ChecksumRangeChunk::group_first_write_ranges(
3017                &mut bitmaps,
3018                block_size,
3019                block_size * 2..block_size * 10,
3020            ),
3021            vec![
3022                ChecksumRangeChunk {
3023                    checksum_range: 0..1,
3024                    device_range: block_size * 2..block_size * 3,
3025                    is_first_write: true,
3026                },
3027                ChecksumRangeChunk {
3028                    checksum_range: 1..2,
3029                    device_range: block_size * 3..block_size * 4,
3030                    is_first_write: false,
3031                },
3032                ChecksumRangeChunk {
3033                    checksum_range: 2..3,
3034                    device_range: block_size * 4..block_size * 5,
3035                    is_first_write: true,
3036                },
3037                ChecksumRangeChunk {
3038                    checksum_range: 3..4,
3039                    device_range: block_size * 5..block_size * 6,
3040                    is_first_write: false,
3041                },
3042                ChecksumRangeChunk {
3043                    checksum_range: 4..5,
3044                    device_range: block_size * 6..block_size * 7,
3045                    is_first_write: true,
3046                },
3047                ChecksumRangeChunk {
3048                    checksum_range: 5..6,
3049                    device_range: block_size * 7..block_size * 8,
3050                    is_first_write: false,
3051                },
3052                ChecksumRangeChunk {
3053                    checksum_range: 6..7,
3054                    device_range: block_size * 8..block_size * 9,
3055                    is_first_write: true,
3056                },
3057                ChecksumRangeChunk {
3058                    checksum_range: 7..8,
3059                    device_range: block_size * 9..block_size * 10,
3060                    is_first_write: false,
3061                },
3062            ],
3063        );
3064        assert_eq!(
3065            bitmaps.take_bitmaps(),
3066            Some((BitVec::from_bytes(&[0b01010101]), BitVec::from_bytes(&[0b11111111])))
3067        );
3068    }
3069}