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