1use 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::{ItemRef, LayerIterator};
11use crate::object_handle::ObjectHandle;
12use crate::object_store::data_object_handle::WRITE_ATTR_BATCH_SIZE;
13use crate::object_store::extent_record::{
14 ExtentMode, ExtentValue, JOURNAL_CHECKSUM_BYTES_PER_BLOCK, MAX_JOURNAL_BYTES_PER_RANGE,
15};
16use crate::object_store::object_manager::ObjectManager;
17use crate::object_store::object_record::{
18 AttributeKey, BytesAndNodes, ExtendedAttributeValue, ObjectAttributes, ObjectItem, ObjectKey,
19 ObjectKeyData, ObjectKind, ObjectValue, Timestamp,
20};
21use crate::object_store::transaction::{
22 AssocObj, AssociatedObject, LockKey, Mutation, ObjectStoreMutation, Options, ReadGuard,
23 TRANSACTION_MAX_JOURNAL_USAGE, Transaction, lock_keys,
24};
25use crate::object_store::{
26 AttributeId, Extent, FSCRYPT_KEY_ID, FileExtent, HandleOptions, HandleOwner, ObjectStore,
27 TrimMode, TrimResult, VOLUME_DATA_KEY_ID,
28};
29use crate::range::RangeExt;
30use anyhow::{Context, Error, anyhow, bail, ensure};
31use assert_matches::assert_matches;
32use bit_vec::BitVec;
33use futures::future::try_join_all;
34use futures::stream::{FuturesOrdered, FuturesUnordered, unfold};
35use futures::{Stream, TryStreamExt, try_join};
36use fxfs_crypto::{
37 Cipher, CipherHolder, CipherSet, EncryptionKey, FindKeyResult, FxfsCipher, KeyPurpose,
38 MutPtrByteSlice,
39};
40use fxfs_trace::{TraceFutureExt, trace, trace_future_args};
41use static_assertions::const_assert;
42use std::cmp::min;
43use std::future::Future;
44use std::ops::Range;
45use std::sync::Arc;
46use std::sync::atomic::{self, AtomicBool, Ordering};
47use storage_device::buffer::{Buffer, BufferFuture, BufferRef, MutableBufferRef};
48use storage_device::{InlineCryptoOptions, ReadOptions, WriteFlags, WriteOptions};
49use storage_units::BlockSize;
50
51use fidl_fuchsia_io as fio;
52use fuchsia_async as fasync;
53
54pub const MAX_XATTR_NAME_SIZE: usize = 255;
56pub const MAX_INLINE_XATTR_SIZE: usize = 256;
59pub const MAX_XATTR_VALUE_SIZE: usize = 64000;
63
64fn apply_bitmap_zeroing(
66 block_size: BlockSize,
67 bitmap: &bit_vec::BitVec,
68 mut buffer: MutableBufferRef<'_>,
69) {
70 let mut buf = buffer.as_mut_ptr_slice();
71 debug_assert_eq!(bitmap.len() as u64 * block_size, buf.len() as u64);
72 for (i, block) in bitmap.iter().enumerate() {
73 if !block {
74 let start = (i as u64 * block_size) as usize;
75 buf.subslice_mut(start..start + block_size.get() as usize).fill(0);
76 }
77 }
78}
79
80#[derive(Debug, Clone, PartialEq)]
84pub enum MaybeChecksums {
85 None,
86 Fletcher(Vec<Checksum>),
87}
88
89impl MaybeChecksums {
90 pub fn maybe_as_ref(&self) -> Option<&[Checksum]> {
91 match self {
92 Self::None => None,
93 Self::Fletcher(sums) => Some(&sums),
94 }
95 }
96
97 pub fn split_off(&mut self, at: usize) -> Self {
98 match self {
99 Self::None => Self::None,
100 Self::Fletcher(sums) => Self::Fletcher(sums.split_off(at)),
101 }
102 }
103
104 pub fn to_mode(self) -> ExtentMode {
105 match self {
106 Self::None => ExtentMode::Raw,
107 Self::Fletcher(sums) => ExtentMode::Cow(Checksums::fletcher(sums)),
108 }
109 }
110
111 pub fn into_option(self) -> Option<Vec<Checksum>> {
112 match self {
113 Self::None => None,
114 Self::Fletcher(sums) => Some(sums),
115 }
116 }
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
123pub enum SetExtendedAttributeMode {
124 Set,
126 Create,
128 Replace,
130}
131
132impl From<fio::SetExtendedAttributeMode> for SetExtendedAttributeMode {
133 fn from(other: fio::SetExtendedAttributeMode) -> SetExtendedAttributeMode {
134 match other {
135 fio::SetExtendedAttributeMode::Set => SetExtendedAttributeMode::Set,
136 fio::SetExtendedAttributeMode::Create => SetExtendedAttributeMode::Create,
137 fio::SetExtendedAttributeMode::Replace => SetExtendedAttributeMode::Replace,
138 }
139 }
140}
141
142enum Encryption {
143 None,
145
146 CachedKeys,
149
150 PermanentKeys,
152}
153
154#[derive(PartialEq, Debug)]
155enum OverwriteBitmaps {
156 None,
157 Some {
158 extent_bitmap: BitVec,
160 write_bitmap: BitVec,
162 bitmap_offset: usize,
165 },
166}
167
168impl OverwriteBitmaps {
169 fn new(extent_bitmap: BitVec) -> Self {
170 OverwriteBitmaps::Some {
171 write_bitmap: BitVec::from_elem(extent_bitmap.len(), false),
172 extent_bitmap,
173 bitmap_offset: 0,
174 }
175 }
176
177 fn is_none(&self) -> bool {
178 *self == OverwriteBitmaps::None
179 }
180
181 fn set_offset(&mut self, new_offset: usize) {
182 match self {
183 OverwriteBitmaps::None => (),
184 OverwriteBitmaps::Some { bitmap_offset, .. } => *bitmap_offset = new_offset,
185 }
186 }
187
188 fn get_from_extent_bitmap(&self, i: usize) -> Option<bool> {
189 match self {
190 OverwriteBitmaps::None => None,
191 OverwriteBitmaps::Some { extent_bitmap, bitmap_offset, .. } => {
192 extent_bitmap.get(*bitmap_offset + i)
193 }
194 }
195 }
196
197 fn set_in_write_bitmap(&mut self, i: usize, x: bool) {
198 match self {
199 OverwriteBitmaps::None => (),
200 OverwriteBitmaps::Some { write_bitmap, bitmap_offset, .. } => {
201 write_bitmap.set(*bitmap_offset + i, x)
202 }
203 }
204 }
205
206 fn take_bitmaps(self) -> Option<(BitVec, BitVec)> {
207 match self {
208 OverwriteBitmaps::None => None,
209 OverwriteBitmaps::Some { extent_bitmap, write_bitmap, .. } => {
210 Some((extent_bitmap, write_bitmap))
211 }
212 }
213 }
214}
215
216#[derive(PartialEq, Debug)]
220struct ChecksumRangeChunk {
221 checksum_range: Range<usize>,
222 device_range: Range<u64>,
223 is_first_write: bool,
224}
225
226impl ChecksumRangeChunk {
227 fn group_first_write_ranges(
228 bitmaps: &mut OverwriteBitmaps,
229 block_size: BlockSize,
230 write_device_range: Range<u64>,
231 ) -> Vec<ChecksumRangeChunk> {
232 let write_block_len = (write_device_range.length().unwrap() / block_size) as usize;
233 if bitmaps.is_none() {
234 vec![ChecksumRangeChunk {
239 checksum_range: 0..write_block_len,
240 device_range: write_device_range,
241 is_first_write: false,
242 }]
243 } else {
244 let mut checksum_ranges = vec![ChecksumRangeChunk {
245 checksum_range: 0..0,
246 device_range: write_device_range.start..write_device_range.start,
247 is_first_write: !bitmaps.get_from_extent_bitmap(0).unwrap(),
248 }];
249 let mut working_range = checksum_ranges.last_mut().unwrap();
250 for i in 0..write_block_len {
251 bitmaps.set_in_write_bitmap(i, true);
252
253 if working_range.is_first_write != bitmaps.get_from_extent_bitmap(i).unwrap() {
256 working_range.checksum_range.end += 1;
259 working_range.device_range.end += block_size;
260 } else {
261 let new_chunk = ChecksumRangeChunk {
263 checksum_range: working_range.checksum_range.end
264 ..working_range.checksum_range.end + 1,
265 device_range: working_range.device_range.end
266 ..working_range.device_range.end + block_size,
267 is_first_write: !working_range.is_first_write,
268 };
269 checksum_ranges.push(new_chunk);
270 working_range = checksum_ranges.last_mut().unwrap();
271 }
272 }
273 checksum_ranges
274 }
275 }
276}
277
278pub struct StoreObjectHandle<S: HandleOwner> {
291 owner: Arc<S>,
292 object_id: u64,
293 options: HandleOptions,
294 trace: AtomicBool,
295 encryption: Encryption,
296}
297
298impl<S: HandleOwner> ObjectHandle for StoreObjectHandle<S> {
299 fn set_trace(&self, v: bool) {
300 info!(store_id = self.store().store_object_id, oid = self.object_id(), trace = v; "trace");
301 self.trace.store(v, atomic::Ordering::Relaxed);
302 }
303
304 fn object_id(&self) -> u64 {
305 return self.object_id;
306 }
307
308 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
309 self.store().device.allocate_buffer(size)
310 }
311
312 fn block_size(&self) -> BlockSize {
313 self.store().block_size()
314 }
315}
316
317static WATCHDOG_BACKTRACE_ENABLED: AtomicBool = AtomicBool::new(false);
318
319pub fn enable_watchdog_backtrace(enabled: bool) {
322 WATCHDOG_BACKTRACE_ENABLED.store(enabled, Ordering::Relaxed);
323}
324
325struct Watchdog {
326 _task: fasync::Task<()>,
327}
328
329impl Watchdog {
330 fn new(increment_seconds: u64, cb: impl Fn(u64) + Send + 'static) -> Self {
331 Self {
332 _task: fasync::Task::spawn(
333 async move {
334 let increment = increment_seconds.try_into().unwrap();
335 let mut fired_counter = 0;
336 let mut next_wake = fasync::MonotonicInstant::now();
337 loop {
338 next_wake += std::time::Duration::from_secs(increment).into();
339 if fasync::MonotonicInstant::now() < next_wake {
343 fasync::Timer::new(next_wake).await;
344 }
345 fired_counter += 1;
346 cb(fired_counter);
347 }
348 }
349 .trace(trace_future_args!("StoreObjectHandle::Watchdog")),
350 ),
351 }
352 }
353
354 fn io(op: &'static str) -> Self {
359 Self::new(10, move |count| {
360 warn!("{op} I/O request blocked for {} seconds", count * 10);
361 #[cfg(all(target_os = "fuchsia", not(doc)))]
362 if count == 30 && WATCHDOG_BACKTRACE_ENABLED.load(Ordering::Relaxed) {
363 let _ = std::thread::Builder::new()
364 .name(format!("fxfs-watchdog:{op}-{}s", count * 10))
365 .spawn(::debug::backtrace_request_all_threads);
366 }
367 })
368 }
369}
370
371impl<S: HandleOwner> StoreObjectHandle<S> {
372 pub fn new(
374 owner: Arc<S>,
375 object_id: u64,
376 permanent_keys: bool,
377 options: HandleOptions,
378 trace: bool,
379 ) -> Self {
380 let encryption = if permanent_keys {
381 Encryption::PermanentKeys
382 } else if owner.as_ref().as_ref().is_encrypted() {
383 Encryption::CachedKeys
384 } else {
385 Encryption::None
386 };
387 Self { owner, object_id, encryption, options, trace: AtomicBool::new(trace) }
388 }
389
390 pub fn owner(&self) -> &Arc<S> {
391 &self.owner
392 }
393
394 pub fn store(&self) -> &ObjectStore {
395 self.owner.as_ref().as_ref()
396 }
397
398 pub fn trace(&self) -> bool {
399 self.trace.load(atomic::Ordering::Relaxed)
400 }
401
402 pub fn is_encrypted(&self) -> bool {
403 !matches!(self.encryption, Encryption::None)
404 }
405
406 pub fn default_transaction_options<'b>(&self) -> Options<'b> {
409 Options { skip_journal_checks: self.options.skip_journal_checks, ..Default::default() }
410 }
411
412 pub async fn new_transaction_with_options<'b>(
413 &self,
414 attribute_id: AttributeId,
415 options: Options<'b>,
416 ) -> Result<Transaction<'b>, Error> {
417 Ok(self
418 .store()
419 .new_transaction(
420 lock_keys![
421 LockKey::object_attribute(
422 self.store().store_object_id(),
423 self.object_id(),
424 attribute_id,
425 ),
426 LockKey::object(self.store().store_object_id(), self.object_id()),
427 ],
428 options,
429 )
430 .await?)
431 }
432
433 pub async fn new_transaction<'b>(
434 &self,
435 attribute_id: AttributeId,
436 ) -> Result<Transaction<'b>, Error> {
437 self.new_transaction_with_options(attribute_id, self.default_transaction_options()).await
438 }
439
440 async fn txn_get_object_mutation(
443 &self,
444 transaction: &Transaction<'_>,
445 ) -> Result<ObjectStoreMutation, Error> {
446 self.store().txn_get_object_mutation(transaction, self.object_id()).await
447 }
448
449 async fn deallocate_old_extents(
451 &self,
452 transaction: &mut Transaction<'_>,
453 attribute_id: AttributeId,
454 range: Range<u64>,
455 ) -> Result<u64, Error> {
456 let block_size = self.block_size();
457 assert!(block_size.is_aligned(&range));
458 if range.start == range.end {
459 return Ok(0);
460 }
461 let tree = &self.store().tree;
462 let layer_set = tree.layer_set();
463 let key = Extent(range);
464 let query_key =
465 ObjectKey::attribute(self.object_id(), attribute_id, AttributeKey::Extent(key.clone()));
466 let mut merger = layer_set.merger();
467 let mut iter = merger.query(Query::LimitedRange(&query_key)).await?;
468 let allocator = self.store().allocator();
469 let mut deallocated = 0;
470 let trace = self.trace();
471 while let Some(ItemRef {
472 key:
473 ObjectKey {
474 object_id,
475 data: ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent_key)),
476 },
477 value: ObjectValue::Extent(value),
478 ..
479 }) = iter.get()
480 {
481 if *object_id != self.object_id() || *attr_id != attribute_id {
482 break;
483 }
484 let Some(overlap) = key.overlap(extent_key) else {
485 break;
486 };
487 if let ExtentValue::Some { device_offset, .. } = value {
488 let range = device_offset + overlap.start - extent_key.start
489 ..device_offset + overlap.end - extent_key.start;
490 ensure!(block_size.is_aligned(&range), FxfsError::Inconsistent);
491 if trace {
492 info!(
493 store_id = self.store().store_object_id(),
494 oid = self.object_id(),
495 device_range:? = range,
496 len = range.end - range.start,
497 extent_key:?;
498 "D",
499 );
500 }
501 allocator.deallocate(transaction, self.store().store_object_id(), range).await?;
502 deallocated += overlap.end - overlap.start;
503 }
504 iter.advance().await?;
505 }
506 Ok(deallocated)
507 }
508
509 async fn write_aligned(
515 &self,
516 buf: BufferRef<'_>,
517 device_offset: u64,
518 crypt_ctx: Option<(u64, u8)>,
519 flags: WriteFlags,
520 ) -> Result<MaybeChecksums, Error> {
521 if self.trace() {
522 info!(
523 store_id = self.store().store_object_id(),
524 oid = self.object_id(),
525 device_range:? = (device_offset..device_offset + buf.len() as u64),
526 len = buf.len();
527 "W",
528 );
529 }
530 let store = self.store();
531 store.device_write_ops.fetch_add(1, Ordering::Relaxed);
532 let _watchdog = Watchdog::io("Write");
533
534 let (opts, compute_checksums) = match crypt_ctx {
535 Some((dun, slot)) => {
536 if !store.filesystem().options().barriers_enabled {
537 return Err(anyhow!(FxfsError::InvalidArgs)
538 .context("Barriers must be enabled for inline encrypted writes."));
539 }
540 (
541 WriteOptions { inline_crypto: InlineCryptoOptions::enabled(slot, dun), flags },
542 false,
543 )
544 }
545 None => (WriteOptions { flags, ..Default::default() }, !self.options.skip_checksums),
546 };
547
548 if compute_checksums {
549 let mut checksums = Vec::new();
550 try_join!(store.device.write_with_opts(device_offset, buf, opts), async {
551 let block_size = self.block_size().get() as usize;
552 for chunk in buf.as_ptr_slice().chunks(block_size) {
553 checksums.push(crate::checksum::fletcher64_ptr(chunk, 0));
554 }
555 Ok(())
556 })?;
557 Ok(MaybeChecksums::Fletcher(checksums))
558 } else {
559 store.device.write_with_opts(device_offset, buf, opts).await?;
560 Ok(MaybeChecksums::None)
561 }
562 }
563
564 pub async fn flush_device(&self) -> Result<(), Error> {
566 let _watchdog = Watchdog::io("Flush");
567 self.store().device().flush().await
568 }
569
570 pub async fn update_allocated_size(
571 &self,
572 transaction: &mut Transaction<'_>,
573 allocated: u64,
574 deallocated: u64,
575 ) -> Result<(), Error> {
576 if allocated == deallocated {
577 return Ok(());
578 }
579 let mut mutation = self.txn_get_object_mutation(transaction).await?;
580 if let ObjectValue::Object {
581 attributes: ObjectAttributes { project_id, allocated_size, .. },
582 ..
583 } = &mut mutation.item.value
584 {
585 *allocated_size = allocated_size
587 .checked_add(allocated)
588 .ok_or_else(|| anyhow!(FxfsError::Inconsistent).context("Allocated size overflow"))?
589 .checked_sub(deallocated)
590 .ok_or_else(|| {
591 anyhow!(FxfsError::Inconsistent).context("Allocated size underflow")
592 })?;
593
594 if let Some(project_id) = project_id {
595 let diff = i64::try_from(allocated).unwrap() - i64::try_from(deallocated).unwrap();
598 transaction.merge_bytes_and_nodes(
599 self.store().store_object_id(),
600 ObjectKey::project_usage(self.store().root_directory_object_id(), *project_id),
601 BytesAndNodes { bytes: diff, nodes: 0 },
602 );
603 }
604 } else {
605 bail!(anyhow!(FxfsError::Inconsistent).context("Unexpected object value"));
608 }
609 transaction.add(self.store().store_object_id, Mutation::ObjectStore(mutation));
610 Ok(())
611 }
612
613 pub async fn update_attributes<'a>(
614 &self,
615 transaction: &mut Transaction<'a>,
616 node_attributes: Option<&fio::MutableNodeAttributes>,
617 change_time: Option<Timestamp>,
618 ) -> Result<(), Error> {
619 if let Some(&fio::MutableNodeAttributes { selinux_context: Some(ref context), .. }) =
620 node_attributes
621 {
622 if let fio::SelinuxContext::Data(context) = context {
623 self.set_extended_attribute_impl(
624 "security.selinux".into(),
625 context.clone(),
626 SetExtendedAttributeMode::Set,
627 transaction,
628 )
629 .await?;
630 } else {
631 return Err(anyhow!(FxfsError::InvalidArgs)
632 .context("Only set SELinux context with `data` member."));
633 }
634 }
635 self.store()
636 .update_attributes(transaction, self.object_id, node_attributes, change_time)
637 .await
638 }
639
640 pub async fn zero(
642 &self,
643 transaction: &mut Transaction<'_>,
644 attribute_id: AttributeId,
645 range: Range<u64>,
646 ) -> Result<(), Error> {
647 let deallocated =
648 self.deallocate_old_extents(transaction, attribute_id, range.clone()).await?;
649 if deallocated > 0 {
650 self.update_allocated_size(transaction, 0, deallocated).await?;
651 transaction.add(
652 self.store().store_object_id,
653 Mutation::merge_object(
654 ObjectKey::extent(self.object_id(), attribute_id, range),
655 ObjectValue::Extent(ExtentValue::deleted_extent()),
656 ),
657 );
658 }
659 Ok(())
660 }
661
662 pub async fn align_buffer(
665 &self,
666 attribute_id: AttributeId,
667 offset: u64,
668 buf: BufferRef<'_>,
669 ) -> Result<(std::ops::Range<u64>, Buffer<'_>), Error> {
670 let block_size = self.block_size();
671 let end = offset + buf.len() as u64;
672 let aligned = block_size.align_range_outwards(offset..end).ok_or(FxfsError::TooBig)?;
673
674 let mut aligned_buf =
675 self.store().device.allocate_buffer((aligned.end - aligned.start) as usize).await;
676
677 if aligned.start < offset {
679 let mut head_block = aligned_buf.subslice_mut(0..block_size.get() as usize);
680 let read =
681 self.read_aligned(attribute_id, aligned.start, head_block.reborrow()).await?;
682 let len = head_block.len();
683 head_block.subslice_mut(read..len).fill(0);
684 }
685
686 if aligned.end > end {
688 let end_block_offset = aligned.end - block_size;
689 if offset <= end_block_offset {
691 let mut tail_block =
692 aligned_buf.subslice_mut(aligned_buf.len() - block_size.get() as usize..);
693 let read = self
694 .read_aligned(attribute_id, end_block_offset, tail_block.reborrow())
695 .await?;
696 let len = tail_block.len();
697 tail_block.subslice_mut(read..len).fill(0);
698 }
699 }
700
701 aligned_buf
702 .subslice_mut((offset - aligned.start) as usize..(end - aligned.start) as usize)
703 .copy_from_buffer(buf);
704
705 Ok((aligned, aligned_buf))
706 }
707
708 pub async fn shrink(
714 &self,
715 transaction: &mut Transaction<'_>,
716 attribute_id: AttributeId,
717 size: u64,
718 ) -> Result<NeedsTrim, Error> {
719 let store = self.store();
720 let needs_trim = matches!(
721 store
722 .trim_some(transaction, self.object_id(), attribute_id, TrimMode::FromOffset(size))
723 .await?,
724 TrimResult::Incomplete
725 );
726 if needs_trim {
727 let graveyard_id = store.graveyard_directory_object_id();
730 let in_graveyard = store
732 .tree
733 .find_map(&ObjectKey::graveyard_entry(graveyard_id, self.object_id()), |item| {
734 matches!(item.value, ObjectValue::Some | ObjectValue::Trim)
735 })
736 .await?
737 .unwrap_or(false);
738 if !in_graveyard {
739 transaction.add(
740 store.store_object_id,
741 Mutation::replace_or_insert_object(
742 ObjectKey::graveyard_entry(graveyard_id, self.object_id()),
743 ObjectValue::Trim,
744 ),
745 );
746 }
747 }
748 Ok(NeedsTrim(needs_trim))
749 }
750
751 pub async fn read_and_decrypt(
753 &self,
754 attribute_id: AttributeId,
755 device_offset: u64,
756 file_offset: u64,
757 mut buffer: MutableBufferRef<'_>,
758 key_id: u64,
759 ) -> Result<(), Error> {
760 let store = self.store();
761 store.device_read_ops.fetch_add(1, Ordering::Relaxed);
762
763 let _watchdog = Watchdog::io("Read");
764
765 let (_key_id, key) = self.get_key(Some(key_id)).await?;
766 if let Some(key) = key {
767 if let Some((dun, slot)) =
768 key.crypt_ctx(self.object_id, attribute_id.raw(), file_offset)
769 {
770 store
771 .device
772 .read_with_opts(
773 device_offset as u64,
774 buffer.reborrow(),
775 ReadOptions { inline_crypto: InlineCryptoOptions::enabled(slot, dun) },
776 )
777 .await?;
778 } else {
779 store.device.read(device_offset, buffer.reborrow()).await?;
780 key.decrypt(
781 self.object_id,
782 attribute_id.raw(),
783 device_offset,
784 file_offset,
785 buffer.as_mut_ptr_slice(),
786 )?;
787 }
788 } else {
789 store.device.read(device_offset, buffer.reborrow()).await?;
790 }
791
792 Ok(())
793 }
794
795 pub async fn get_key(
800 &self,
801 key_id: Option<u64>,
802 ) -> Result<(u64, Option<Arc<dyn Cipher>>), Error> {
803 let store = self.store();
804 let result = match self.encryption {
805 Encryption::None => (VOLUME_DATA_KEY_ID, None),
806 Encryption::CachedKeys => {
807 if let Some(key_id) = key_id {
808 (
809 key_id,
810 Some(
811 store
812 .key_manager
813 .get_key(
814 self.object_id,
815 store.crypt().ok_or_else(|| anyhow!("No crypt!"))?.as_ref(),
816 async || store.get_keys(self.object_id).await,
817 key_id,
818 )
819 .await?,
820 ),
821 )
822 } else {
823 let (key_id, key) = store
824 .key_manager
825 .get_fscrypt_key_if_present(
826 self.object_id,
827 store.crypt().ok_or_else(|| anyhow!("No crypt!"))?.as_ref(),
828 async || store.get_keys(self.object_id).await,
829 )
830 .await?;
831 (key_id, Some(key))
832 }
833 }
834 Encryption::PermanentKeys => {
835 (VOLUME_DATA_KEY_ID, Some(store.key_manager.get(self.object_id).await?.unwrap()))
836 }
837 };
838
839 if let Some(ref key) = result.1 {
841 if key.crypt_ctx(self.object_id, 0, 0).is_some() {
842 if !store.filesystem().options().barriers_enabled {
843 return Err(anyhow!(FxfsError::InvalidArgs)
844 .context("Barriers must be enabled for inline encrypted writes."));
845 }
846 }
847 }
848
849 Ok(result)
850 }
851
852 pub async fn extent_stream<'a, 'b>(
856 &'a self,
857 merger: &'b mut Merger<'a, ObjectKey, ObjectValue>,
858 attribute_id: AttributeId,
859 ) -> Result<impl Stream<Item = Result<FileExtent, Error>> + 'b, Error> {
860 let object_id = self.object_id();
861 let iter = merger
862 .query(Query::FullRange(&ObjectKey::attribute(
863 object_id,
864 attribute_id,
865 AttributeKey::Extent(Extent::search_key_from_offset(0)),
866 )))
867 .await?;
868 Ok(unfold(
869 (iter, object_id, attribute_id),
870 |(mut iter, object_id, attribute_id)| async move {
871 loop {
872 match iter.get() {
873 Some(ItemRef {
874 key:
875 ObjectKey {
876 object_id: id,
877 data:
878 ObjectKeyData::Attribute(
879 attr_id,
880 AttributeKey::Extent(extent_key),
881 ),
882 },
883 value: ObjectValue::Extent(extent_value),
884 ..
885 }) if *id == object_id && *attr_id == attribute_id => {
886 let logical_range = extent_key.0.clone();
887 let device_range = match extent_value {
888 ExtentValue::Some { device_offset, .. } => {
889 let len = logical_range.end - logical_range.start;
890 Some(*device_offset..*device_offset + len)
891 }
892 ExtentValue::None => None,
894 };
895
896 if let Err(e) = iter.advance().await {
899 return Some((Err(e.into()), (iter, object_id, attribute_id)));
900 }
901
902 if let Some(device_range) = device_range {
903 return Some((
904 Ok(FileExtent::new(logical_range.start, device_range).unwrap()),
905 (iter, object_id, attribute_id),
906 ));
907 } else {
908 continue;
911 }
912 }
913 _ => return None,
915 }
916 }
917 },
918 ))
919 }
920
921 async fn get_or_create_key(
925 &self,
926 transaction: &mut Transaction<'_>,
927 ) -> Result<Arc<dyn Cipher>, Error> {
928 let store = self.store();
929
930 if let Some(key) = store.key_manager.get(self.object_id).await.context("get failed")? {
932 return Ok(key);
933 }
934
935 let crypt = store.crypt().ok_or_else(|| anyhow!("No crypt!"))?;
936
937 let (mut encryption_keys, mut cipher_set) = if let Some(value) =
939 store.tree.find_value(&ObjectKey::keys(self.object_id)).await.context("find failed")?
940 {
941 if let ObjectValue::Keys(encryption_keys) = value {
942 let cipher_set = store
943 .key_manager
944 .get_keys(
945 self.object_id,
946 crypt.as_ref(),
947 &mut Some(async || Ok(encryption_keys.clone())),
948 false,
949 false,
950 )
951 .await
952 .context("get_keys failed")?;
953 match cipher_set.find_key(VOLUME_DATA_KEY_ID) {
954 FindKeyResult::NotFound => {}
955 FindKeyResult::Unavailable => return Err(FxfsError::NoKey.into()),
956 FindKeyResult::Key(key) => return Ok(key),
957 }
958 (encryption_keys, (*cipher_set).clone())
959 } else {
960 return Err(anyhow!(FxfsError::Inconsistent));
961 }
962 } else {
963 Default::default()
964 };
965
966 let (key, unwrapped_key) = crypt.create_key(self.object_id, KeyPurpose::Data).await?;
968 let cipher: Arc<dyn Cipher> = Arc::new(FxfsCipher::new(&unwrapped_key));
969
970 cipher_set.add_key(VOLUME_DATA_KEY_ID, CipherHolder::Cipher(cipher.clone()));
973 let cipher_set = Arc::new(cipher_set);
974
975 struct UnwrappedKeys {
978 object_id: u64,
979 new_keys: Arc<CipherSet>,
980 }
981
982 impl AssociatedObject for UnwrappedKeys {
983 fn will_apply_mutation(
984 &self,
985 _mutation: &Mutation,
986 object_id: u64,
987 manager: &ObjectManager,
988 ) {
989 manager.store(object_id).unwrap().key_manager.insert(
990 self.object_id,
991 self.new_keys.clone(),
992 false,
993 );
994 }
995 }
996
997 encryption_keys.insert(VOLUME_DATA_KEY_ID, EncryptionKey::Fxfs(key).into());
998
999 transaction.add_with_object(
1000 store.store_object_id(),
1001 Mutation::replace_or_insert_object(
1002 ObjectKey::keys(self.object_id),
1003 ObjectValue::keys(encryption_keys),
1004 ),
1005 AssocObj::Owned(Box::new(UnwrappedKeys {
1006 object_id: self.object_id,
1007 new_keys: cipher_set,
1008 })),
1009 );
1010
1011 Ok(cipher)
1012 }
1013
1014 pub async fn read_aligned(
1022 &self,
1023 attribute_id: AttributeId,
1024 offset: u64,
1025 mut buf: MutableBufferRef<'_>,
1026 ) -> Result<usize, Error> {
1027 let block_size = self.block_size();
1028 ensure!(block_size.is_aligned(offset), FxfsError::InvalidArgs);
1029 ensure!(block_size.is_aligned(buf.len() as u64), FxfsError::InvalidArgs);
1030 let fs = self.store().filesystem();
1031 let guard = fs
1032 .lock_manager()
1033 .read_lock(lock_keys![LockKey::object_attribute(
1034 self.store().store_object_id(),
1035 self.object_id(),
1036 attribute_id,
1037 )])
1038 .await;
1039
1040 let key = ObjectKey::attribute(self.object_id(), attribute_id, AttributeKey::Attribute);
1041 let size = self
1042 .store()
1043 .tree()
1044 .find_map(&key, |item| match item.value {
1045 ObjectValue::Attribute { size, .. } => Ok(*size),
1046 _ => Err(anyhow!(FxfsError::Inconsistent)),
1047 })
1048 .await?
1049 .transpose()?
1050 .unwrap_or(0);
1051 if offset >= size {
1052 return Ok(0);
1053 }
1054 let length = min(buf.len() as u64, size - offset) as usize;
1055 let aligned_length =
1056 block_size.align_up(length as u64).ok_or(FxfsError::Inconsistent)? as usize;
1057 buf = buf.subslice_mut(0..aligned_length);
1058 self.read_aligned_unchecked(attribute_id, offset, buf, &guard).await?;
1059 Ok(length)
1060 }
1061
1062 pub async fn read_aligned_unchecked(
1073 &self,
1074 attribute_id: AttributeId,
1075 offset: u64,
1076 buf: MutableBufferRef<'_>,
1077 _guard: &ReadGuard<'_>,
1078 ) -> Result<(), Error> {
1079 if buf.is_empty() {
1080 return Ok(());
1081 }
1082 let end_offset = offset + buf.len() as u64;
1083 let tree = &self.store().tree;
1084 let layer_set = tree.layer_set();
1085 let mut merger = layer_set.merger();
1086 let iter = merger
1087 .query(Query::LimitedRange(&ObjectKey::extent(
1088 self.object_id(),
1089 attribute_id,
1090 offset..end_offset,
1091 )))
1092 .await?;
1093 self.read_aligned_impl(attribute_id, offset, buf, iter, true).await
1094 }
1095
1096 pub async fn read_attr(&self, attribute_id: AttributeId) -> Result<Option<Box<[u8]>>, Error> {
1098 let store = self.store();
1099 let tree = &store.tree;
1100 let layer_set = tree.layer_set();
1101 let mut merger = layer_set.merger();
1102 let key = ObjectKey::attribute(self.object_id(), attribute_id, AttributeKey::Attribute);
1103 let iter = merger.query(Query::FullRange(&key)).await?;
1104 match iter.get() {
1105 Some(item) if item.key == &key => match item.value {
1106 ObjectValue::Attribute { .. } => Ok(Some(self.read_attr_from_iter(iter).await?)),
1107 ObjectValue::None => Ok(None),
1109 _ => Err(FxfsError::Inconsistent.into()),
1110 },
1111 _ => Ok(None),
1112 }
1113 }
1114
1115 pub async fn read_attr_from_iter(
1118 &self,
1119 iter: MergerIterator<'_, '_, ObjectKey, ObjectValue>,
1120 ) -> Result<Box<[u8]>, Error> {
1121 self.read_attr_from_iter_impl(iter, true).await
1122 }
1123
1124 pub async fn read_raw_attr_from_iter(
1127 &self,
1128 iter: MergerIterator<'_, '_, ObjectKey, ObjectValue>,
1129 ) -> Result<Box<[u8]>, Error> {
1130 self.read_attr_from_iter_impl(iter, false).await
1131 }
1132
1133 async fn read_attr_from_iter_impl(
1134 &self,
1135 mut iter: MergerIterator<'_, '_, ObjectKey, ObjectValue>,
1136 decrypt: bool,
1137 ) -> Result<Box<[u8]>, Error> {
1138 let (mut buffer, size, attribute_id) = match iter.get() {
1139 Some(ItemRef {
1140 key:
1141 ObjectKey {
1142 object_id,
1143 data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Attribute),
1144 },
1145 value: ObjectValue::Attribute { size, .. },
1146 ..
1147 }) if *object_id == self.object_id => {
1148 (
1150 self.store()
1151 .device
1152 .allocate_buffer(self.block_size().align_up(*size).unwrap() as usize)
1153 .await,
1154 *size as usize,
1155 *attribute_id,
1156 )
1157 }
1158 _ => bail!(FxfsError::InvalidArgs),
1159 };
1160 iter.advance().await?;
1161 self.read_aligned_impl(attribute_id, 0, buffer.as_mut(), iter, decrypt).await?;
1162 Ok(buffer.as_ref().subslice(0..size).to_vec().into_boxed_slice())
1163 }
1164
1165 async fn read_aligned_impl(
1173 &self,
1174 attribute_id: AttributeId,
1175 mut offset: u64,
1176 mut buf: MutableBufferRef<'_>,
1177 mut iter: MergerIterator<'_, '_, ObjectKey, ObjectValue>,
1178 decrypt: bool,
1179 ) -> Result<(), Error> {
1180 if buf.is_empty() {
1181 return Ok(());
1182 }
1183 let block_size = self.block_size();
1184 debug_assert!(block_size.is_aligned(offset));
1185 debug_assert!(block_size.is_aligned(buf.len() as u64));
1186 let device_block_size = self.store().device.block_size() as u64;
1187 debug_assert!(buf.range().start as u64 % device_block_size == 0);
1188
1189 self.store().logical_read_ops.fetch_add(1, Ordering::Relaxed);
1190
1191 let mut reads = Vec::new();
1192 loop {
1193 let (mut extent_key, mut device_offset, key_id, mode) = match iter.get() {
1194 Some(ItemRef {
1195 key:
1196 ObjectKey {
1197 object_id,
1198 data:
1199 ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent_key)),
1200 },
1201 value: ObjectValue::Extent(extent_value),
1202 ..
1203 }) if *object_id == self.object_id && *attr_id == attribute_id => {
1204 match extent_value {
1205 ExtentValue::Some { device_offset, mode, key_id } => {
1206 ensure!(extent_key.is_valid(), FxfsError::Inconsistent);
1207 ensure!(block_size.is_aligned(extent_key), FxfsError::Inconsistent);
1208 ensure!(
1209 device_offset % device_block_size == 0,
1210 FxfsError::Inconsistent
1211 );
1212 ensure!(extent_key.end > offset, FxfsError::Inconsistent);
1214 (extent_key.0.clone(), *device_offset, *key_id, mode)
1215 }
1216 ExtentValue::None => {
1217 iter.advance().await?;
1219 continue;
1220 }
1221 }
1222 }
1223 _ => break,
1224 };
1225 if extent_key.start > offset {
1226 let split = std::cmp::min((extent_key.start - offset) as usize, buf.len());
1228 let (mut to_zero, remaining) = buf.split_at_mut(split);
1229 to_zero.fill(0);
1230 buf = remaining;
1231 if buf.is_empty() {
1232 break;
1233 }
1234 offset = extent_key.start;
1235 }
1236
1237 let mut bitmap_offset = 0;
1238 if extent_key.start < offset {
1239 let diff = offset - extent_key.start;
1240 extent_key.start = offset;
1241 device_offset += diff;
1242 bitmap_offset = diff;
1243 }
1244 if (extent_key.end - extent_key.start) > buf.len() as u64 {
1245 extent_key.end = extent_key.start + buf.len() as u64;
1246 }
1247 let (mut to_read, remaining) =
1248 buf.split_at_mut((extent_key.end - extent_key.start) as usize);
1249 buf = remaining;
1250 let maybe_bitmap = match mode {
1251 ExtentMode::OverwritePartial(bitmap) => {
1252 let mut read_bitmap =
1253 bitmap.clone().split_off((bitmap_offset / block_size) as usize);
1254 read_bitmap.truncate(((to_read.len() as u64) / block_size) as usize);
1255 Some(read_bitmap)
1256 }
1257 _ => None,
1258 };
1259 reads.push(async move {
1260 if decrypt {
1261 self.read_and_decrypt(
1262 attribute_id,
1263 device_offset,
1264 extent_key.start,
1265 to_read.reborrow(),
1266 key_id,
1267 )
1268 .await?;
1269 } else {
1270 let store = self.store();
1271 store.device_read_ops.fetch_add(1, Ordering::Relaxed);
1272 let _watchdog = Watchdog::io("Read");
1273 store.device.read(device_offset, to_read.reborrow()).await?;
1274 }
1275 if let Some(bitmap) = maybe_bitmap {
1276 apply_bitmap_zeroing(block_size, &bitmap, to_read);
1277 }
1278 Ok::<(), Error>(())
1279 });
1280 if buf.is_empty() {
1281 break;
1282 }
1283 offset = extent_key.end;
1284 iter.advance().await?;
1285 }
1286 match reads.len() {
1287 0 => {}
1288 1 => reads.pop().unwrap().await?,
1289 _ => {
1290 try_join_all(reads).await?;
1291 }
1292 }
1293 buf.fill(0);
1294 Ok(())
1295 }
1296
1297 pub async fn write_at(
1305 &self,
1306 attribute_id: AttributeId,
1307 offset: u64,
1308 buf: MutableBufferRef<'_>,
1309 key_id: Option<u64>,
1310 device_offset: u64,
1311 ) -> Result<MaybeChecksums, Error> {
1312 self.write_at_with_flags(
1313 attribute_id,
1314 offset,
1315 buf,
1316 key_id,
1317 device_offset,
1318 WriteFlags::empty(),
1319 )
1320 .await
1321 }
1322
1323 pub async fn write_at_with_flags(
1326 &self,
1327 attribute_id: AttributeId,
1328 offset: u64,
1329 buf: MutableBufferRef<'_>,
1330 key_id: Option<u64>,
1331 mut device_offset: u64,
1332 flags: WriteFlags,
1333 ) -> Result<MaybeChecksums, Error> {
1334 let mut transfer_buf;
1335 let block_size = self.block_size();
1336 let (range, mut transfer_buf_ref) =
1337 if offset % block_size == 0 && buf.len() as u64 % block_size == 0 {
1338 (offset..offset + buf.len() as u64, buf)
1339 } else {
1340 let (range, buf) = self.align_buffer(attribute_id, offset, buf.as_ref()).await?;
1341 transfer_buf = buf;
1342 device_offset -= offset - range.start;
1343 (range, transfer_buf.as_mut())
1344 };
1345
1346 let mut crypt_ctx = None;
1347 if let (_, Some(key)) = self.get_key(key_id).await? {
1348 if let Some(ctx) = key.crypt_ctx(self.object_id, attribute_id.raw(), range.start) {
1349 crypt_ctx = Some(ctx);
1350 } else {
1351 key.encrypt(
1352 self.object_id,
1353 attribute_id.raw(),
1354 device_offset,
1355 range.start,
1356 transfer_buf_ref.as_mut_ptr_slice(),
1357 )?;
1358 }
1359 }
1360 self.write_aligned(transfer_buf_ref.as_ref(), device_offset, crypt_ctx, flags).await
1361 }
1362
1363 #[cfg(feature = "migration")]
1368 pub async fn raw_multi_write(
1369 &self,
1370 transaction: &mut Transaction<'_>,
1371 attribute_id: AttributeId,
1372 key_id: Option<u64>,
1373 encrypt: bool,
1374 ranges: &[Range<u64>],
1375 buf: MutableBufferRef<'_>,
1376 ) -> Result<(), Error> {
1377 self.multi_write_internal(transaction, attribute_id, key_id, encrypt, ranges, buf).await?;
1378 Ok(())
1379 }
1380
1381 async fn multi_write_internal(
1387 &self,
1388 transaction: &mut Transaction<'_>,
1389 attribute_id: AttributeId,
1390 key_id: Option<u64>,
1391 encrypt: bool,
1392 ranges: &[Range<u64>],
1393 mut buf: MutableBufferRef<'_>,
1394 ) -> Result<(u64, u64), Error> {
1395 if buf.is_empty() {
1396 return Ok((0, 0));
1397 }
1398 let block_size = self.block_size();
1399 debug_assert!(
1400 transaction.skip_journal_checks
1401 || (buf.len() / block_size.get() as usize) * JOURNAL_CHECKSUM_BYTES_PER_BLOCK
1402 + ranges.len() * MAX_JOURNAL_BYTES_PER_RANGE
1403 <= TRANSACTION_MAX_JOURNAL_USAGE as usize,
1404 "Write is too large for a single transaction; callers must break up writes"
1405 );
1406 let store = self.store();
1407 let store_id = store.store_object_id();
1408
1409 let (key_id, key) = if !encrypt {
1412 (key_id.unwrap_or(VOLUME_DATA_KEY_ID), None)
1413 } else if key_id == Some(VOLUME_DATA_KEY_ID)
1414 && matches!(self.encryption, Encryption::CachedKeys)
1415 {
1416 (
1417 VOLUME_DATA_KEY_ID,
1418 Some(
1419 self.get_or_create_key(transaction)
1420 .await
1421 .context("get_or_create_key failed")?,
1422 ),
1423 )
1424 } else {
1425 self.get_key(key_id).await?
1426 };
1427 if let Some(key) = &key {
1428 if !key.supports_inline_encryption() {
1429 let mut slice = buf.as_mut_ptr_slice();
1430 for r in ranges {
1431 let l = r.end - r.start;
1432 let (head, tail) = slice.split_at_mut(l as usize);
1433 key.encrypt(
1434 self.object_id,
1435 attribute_id.raw(),
1436 0, r.start,
1438 MutPtrByteSlice::from(head),
1439 )?;
1440 slice = tail;
1441 }
1442 }
1443 }
1444
1445 let mut allocated = 0;
1446 let allocator = store.allocator();
1447 let trace = self.trace();
1448 let mut writes = FuturesOrdered::new();
1449
1450 let mut logical_ranges = ranges.iter();
1451 let mut current_range = logical_ranges.next().unwrap().clone();
1452
1453 while !buf.is_empty() {
1454 let mut device_range = allocator
1455 .allocate(transaction, store_id, buf.len() as u64)
1456 .await
1457 .context("allocation failed")?;
1458 if trace {
1459 info!(
1460 store_id,
1461 oid = self.object_id(),
1462 device_range:?,
1463 len = device_range.end - device_range.start;
1464 "A",
1465 );
1466 }
1467 let mut device_range_len = device_range.end - device_range.start;
1468 allocated += device_range_len;
1469 while device_range_len > 0 {
1471 if current_range.end <= current_range.start {
1472 current_range = logical_ranges.next().unwrap().clone();
1473 }
1474 let (crypt_ctx, split) = if let Some(key) = &key {
1475 if key.supports_inline_encryption() {
1476 let split = std::cmp::min(
1477 current_range.end - current_range.start,
1478 device_range_len,
1479 );
1480 let crypt_ctx =
1481 key.crypt_ctx(self.object_id, attribute_id.raw(), current_range.start);
1482 current_range.start += split;
1483 (crypt_ctx, split)
1484 } else {
1485 (None, device_range_len)
1486 }
1487 } else {
1488 (None, device_range_len)
1489 };
1490
1491 let (head, tail) = buf.split_at_mut(split as usize);
1492 buf = tail;
1493
1494 writes.push_back(async move {
1495 let len = head.len() as u64;
1496 Result::<_, Error>::Ok((
1497 device_range.start,
1498 len,
1499 self.write_aligned(
1500 head.as_ref(),
1501 device_range.start,
1502 crypt_ctx,
1503 WriteFlags::empty(),
1504 )
1505 .await?,
1506 ))
1507 });
1508 device_range.start += split;
1509 device_range_len = device_range.end - device_range.start;
1510 }
1511 }
1512
1513 self.store().logical_write_ops.fetch_add(1, Ordering::Relaxed);
1514 let ((mutations, checksums), deallocated) = try_join!(
1515 async {
1516 let mut current_range = 0..0;
1517 let mut mutations = Vec::new();
1518 let mut out_checksums = Vec::new();
1519 let mut ranges = ranges.iter();
1520 while let Some((mut device_offset, mut len, mut checksums)) =
1521 writes.try_next().await?
1522 {
1523 while len > 0 {
1524 if current_range.end <= current_range.start {
1525 current_range = ranges.next().unwrap().clone();
1526 }
1527 let chunk_len = std::cmp::min(len, current_range.end - current_range.start);
1528 let tail = checksums.split_off((chunk_len / block_size) as usize);
1529 if let Some(checksums) = checksums.maybe_as_ref() {
1530 out_checksums.push((
1531 device_offset..device_offset + chunk_len,
1532 checksums.to_owned(),
1533 ));
1534 }
1535 mutations.push(Mutation::merge_object(
1536 ObjectKey::extent(
1537 self.object_id(),
1538 attribute_id,
1539 current_range.start..current_range.start + chunk_len,
1540 ),
1541 ObjectValue::Extent(ExtentValue::new(
1542 device_offset,
1543 checksums.to_mode(),
1544 key_id,
1545 )),
1546 ));
1547 checksums = tail;
1548 device_offset += chunk_len;
1549 len -= chunk_len;
1550 current_range.start += chunk_len;
1551 }
1552 }
1553 Result::<_, Error>::Ok((mutations, out_checksums))
1554 },
1555 async {
1556 let mut deallocated = 0;
1557 for r in ranges {
1558 deallocated +=
1559 self.deallocate_old_extents(transaction, attribute_id, r.clone()).await?;
1560 }
1561 Result::<_, Error>::Ok(deallocated)
1562 }
1563 )?;
1564
1565 for m in mutations {
1566 transaction.add(store_id, m);
1567 }
1568
1569 if !store.filesystem().options().barriers_enabled {
1571 for (r, c) in checksums {
1572 transaction.add_checksum(store_id, r, c, true);
1573 }
1574 }
1575 Ok((allocated, deallocated))
1576 }
1577
1578 pub async fn multi_write(
1584 &self,
1585 transaction: &mut Transaction<'_>,
1586 attribute_id: AttributeId,
1587 key_id: Option<u64>,
1588 ranges: &[Range<u64>],
1589 buf: MutableBufferRef<'_>,
1590 ) -> Result<(), Error> {
1591 let (allocated, deallocated) = self
1592 .multi_write_internal(
1593 transaction,
1594 attribute_id,
1595 key_id,
1596 true,
1597 ranges,
1598 buf,
1599 )
1600 .await?;
1601 if allocated == 0 && deallocated == 0 {
1602 return Ok(());
1603 }
1604 self.update_allocated_size(transaction, allocated, deallocated).await
1605 }
1606
1607 pub async fn multi_overwrite<'a>(
1612 &'a self,
1613 transaction: &mut Transaction<'a>,
1614 attr_id: AttributeId,
1615 ranges: &[Range<u64>],
1616 mut buf: MutableBufferRef<'_>,
1617 ) -> Result<(), Error> {
1618 if buf.is_empty() {
1619 return Ok(());
1620 }
1621 let block_size = self.block_size();
1622 let store = self.store();
1623 let tree = store.tree();
1624 let store_id = store.store_object_id();
1625
1626 let (key_id, key) = self.get_key(None).await?;
1627 if let Some(key) = &key {
1628 if !key.supports_inline_encryption() {
1629 let mut slice = buf.as_mut_ptr_slice();
1630 for r in ranges {
1631 let l = r.end - r.start;
1632 let (head, tail) = slice.split_at_mut(l as usize);
1633 key.encrypt(
1634 self.object_id,
1635 attr_id.raw(),
1636 0, r.start,
1638 MutPtrByteSlice::from(head),
1639 )?;
1640 slice = tail;
1641 }
1642 }
1643 }
1644
1645 let mut range_iter = ranges.iter();
1646 let mut target_range = range_iter.next().unwrap().clone();
1648 let mut mutations = Vec::new();
1649 let writes = FuturesUnordered::new();
1650
1651 let layer_set = tree.layer_set();
1652 let mut merger = layer_set.merger();
1653 let mut iter = merger
1654 .query(Query::LimitedRange(&ObjectKey::extent(
1655 self.object_id(),
1656 attr_id,
1657 target_range.start..ranges.last().unwrap().end,
1658 )))
1659 .await?;
1660
1661 loop {
1662 match iter.get() {
1663 Some(ItemRef {
1664 key:
1665 ObjectKey {
1666 object_id,
1667 data:
1668 ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
1669 },
1670 value: ObjectValue::Extent(extent_value),
1671 ..
1672 }) if *object_id == self.object_id() && *attribute_id == attr_id => {
1673 if extent.end <= target_range.start {
1677 iter.advance().await?;
1678 continue;
1679 }
1680 let (device_offset, mode) = match extent_value {
1681 ExtentValue::None => {
1682 return Err(anyhow!(FxfsError::Inconsistent)).with_context(|| {
1683 format!(
1684 "multi_overwrite failed: target_range ({}, {}) overlaps with \
1685 deleted extent found at ({}, {})",
1686 target_range.start, target_range.end, extent.start, extent.end,
1687 )
1688 });
1689 }
1690 ExtentValue::Some { device_offset, mode, .. } => (device_offset, mode),
1691 };
1692 if extent.start > target_range.start {
1695 return Err(anyhow!(FxfsError::Inconsistent)).with_context(|| {
1696 format!(
1697 "multi_overwrite failed: target range ({}, {}) starts before first \
1698 extent found at ({}, {})",
1699 target_range.start, target_range.end, extent.start, extent.end,
1700 )
1701 });
1702 }
1703 let mut bitmap = match mode {
1704 ExtentMode::Raw | ExtentMode::Cow(_) => {
1705 return Err(anyhow!(FxfsError::Inconsistent)).with_context(|| {
1706 format!(
1707 "multi_overwrite failed: \
1708 extent from ({}, {}) which overlaps target range ({}, {}) had the \
1709 wrong extent mode",
1710 extent.start, extent.end, target_range.start, target_range.end,
1711 )
1712 });
1713 }
1714 ExtentMode::OverwritePartial(bitmap) => {
1715 OverwriteBitmaps::new(bitmap.clone())
1716 }
1717 ExtentMode::Overwrite => OverwriteBitmaps::None,
1718 };
1719 loop {
1720 let offset_within_extent = target_range.start - extent.start;
1721 let bitmap_offset = offset_within_extent / block_size;
1722 let write_device_offset = *device_offset + offset_within_extent;
1723 let write_end = min(extent.end, target_range.end);
1724 let write_len = write_end - target_range.start;
1725 let write_device_range =
1726 write_device_offset..write_device_offset + write_len;
1727 let (current_buf, remaining_buf) = buf.split_at_mut(write_len as usize);
1728
1729 bitmap.set_offset(bitmap_offset as usize);
1730 let checksum_ranges = ChecksumRangeChunk::group_first_write_ranges(
1731 &mut bitmap,
1732 block_size,
1733 write_device_range,
1734 );
1735
1736 let crypt_ctx = if let Some(key) = &key {
1737 key.crypt_ctx(self.object_id, attr_id.raw(), target_range.start)
1738 } else {
1739 None
1740 };
1741
1742 writes.push(async move {
1743 let maybe_checksums = self
1744 .write_aligned(
1745 current_buf.as_ref(),
1746 write_device_offset,
1747 crypt_ctx,
1748 WriteFlags::empty(),
1749 )
1750 .await?;
1751 Ok::<_, Error>(match maybe_checksums {
1752 MaybeChecksums::None => Vec::new(),
1753 MaybeChecksums::Fletcher(checksums) => checksum_ranges
1754 .into_iter()
1755 .map(
1756 |ChecksumRangeChunk {
1757 checksum_range,
1758 device_range,
1759 is_first_write,
1760 }| {
1761 (
1762 device_range,
1763 checksums[checksum_range].to_vec(),
1764 is_first_write,
1765 )
1766 },
1767 )
1768 .collect(),
1769 })
1770 });
1771 buf = remaining_buf;
1772 target_range.start += write_len;
1773 if target_range.start == target_range.end {
1774 match range_iter.next() {
1775 None => break,
1776 Some(next_range) => target_range = next_range.clone(),
1777 }
1778 }
1779 if extent.end <= target_range.start {
1780 break;
1781 }
1782 }
1783 if let Some((mut bitmap, write_bitmap)) = bitmap.take_bitmaps() {
1784 if bitmap.or(&write_bitmap) {
1785 let mode = if bitmap.all() {
1786 ExtentMode::Overwrite
1787 } else {
1788 ExtentMode::OverwritePartial(bitmap)
1789 };
1790 mutations.push(Mutation::merge_object(
1791 ObjectKey::extent(self.object_id(), attr_id, extent.clone().into()),
1792 ObjectValue::Extent(ExtentValue::new(*device_offset, mode, key_id)),
1793 ))
1794 }
1795 }
1796 if target_range.start == target_range.end {
1797 break;
1798 }
1799 iter.advance().await?;
1800 }
1801 _ => bail!(anyhow!(FxfsError::Internal).context(
1805 "found a non-extent object record while there were still ranges to process"
1806 )),
1807 }
1808 }
1809
1810 let checksums = writes.try_collect::<Vec<_>>().await?;
1811 if !store.filesystem().options().barriers_enabled {
1813 for (r, c, first_write) in checksums.into_iter().flatten() {
1814 transaction.add_checksum(store_id, r, c, first_write);
1815 }
1816 }
1817
1818 for m in mutations {
1819 transaction.add(store_id, m);
1820 }
1821
1822 Ok(())
1823 }
1824
1825 #[trace]
1829 pub async fn write_new_attr(
1830 &self,
1831 transaction: &mut Transaction<'_>,
1832 attribute_id: AttributeId,
1833 data: &[u8],
1834 ) -> Result<(), Error> {
1835 self.write_new_attr_impl(
1836 transaction,
1837 attribute_id,
1838 VOLUME_DATA_KEY_ID,
1839 true,
1840 data,
1841 )
1842 .await
1843 }
1844
1845 pub async fn write_new_attr_pre_encrypted(
1848 &self,
1849 transaction: &mut Transaction<'_>,
1850 attribute_id: AttributeId,
1851 key_id: u64,
1852 data: &[u8],
1853 ) -> Result<(), Error> {
1854 self.write_new_attr_impl(transaction, attribute_id, key_id, false, data)
1855 .await
1856 }
1857
1858 async fn write_new_attr_impl(
1859 &self,
1860 transaction: &mut Transaction<'_>,
1861 attribute_id: AttributeId,
1862 key_id: u64,
1863 encrypt: bool,
1864 data: &[u8],
1865 ) -> Result<(), Error> {
1866 transaction.add(
1867 self.store().store_object_id,
1868 Mutation::replace_or_insert_object(
1869 ObjectKey::attribute(self.object_id(), attribute_id, AttributeKey::Attribute),
1870 ObjectValue::attribute(data.len() as u64, false),
1871 ),
1872 );
1873 let chunks = data.chunks(WRITE_ATTR_BATCH_SIZE);
1874 let num_chunks = chunks.len();
1875 if num_chunks > 1 {
1876 transaction.add(
1877 self.store().store_object_id,
1878 Mutation::replace_or_insert_object(
1879 ObjectKey::graveyard_attribute_entry(
1880 self.store().graveyard_directory_object_id(),
1881 self.object_id(),
1882 attribute_id,
1883 ),
1884 ObjectValue::Some,
1885 ),
1886 );
1887 }
1888 let mut start_offset = 0;
1889 for (i, chunk) in chunks.enumerate() {
1890 let rounded_len = self.block_size().align_up(chunk.len() as u64).unwrap();
1891 let mut buffer = self.store().device.allocate_buffer(rounded_len as usize).await;
1892 let mut slice = buffer.as_mut_ptr_slice();
1893 slice.subslice_mut(0..chunk.len()).copy_from_slice(chunk);
1894 slice.subslice_mut(chunk.len()..slice.len()).fill(0);
1895 let (allocated, deallocated) = self
1896 .multi_write_internal(
1897 transaction,
1898 attribute_id,
1899 Some(key_id),
1900 encrypt,
1901 &[start_offset..start_offset + rounded_len],
1902 buffer.as_mut(),
1903 )
1904 .await?;
1905 if allocated != 0 || deallocated != 0 {
1906 self.update_allocated_size(transaction, allocated, deallocated).await?;
1907 }
1908 start_offset += rounded_len;
1909 if i < num_chunks - 1 {
1911 transaction.commit_and_continue().await?;
1912 }
1913 }
1914 if num_chunks > 1 {
1915 self.store().remove_attribute_from_graveyard(
1916 transaction,
1917 self.object_id(),
1918 attribute_id,
1919 );
1920 }
1921 Ok(())
1922 }
1923
1924 pub async fn write_attr(
1931 &self,
1932 transaction: &mut Transaction<'_>,
1933 attribute_id: AttributeId,
1934 data: &[u8],
1935 ) -> Result<NeedsTrim, Error> {
1936 let rounded_len = self.block_size().align_up(data.len() as u64).unwrap();
1937 let store = self.store();
1938 let tree = store.tree();
1939 let should_trim = tree
1940 .find_map(
1941 &ObjectKey::attribute(self.object_id(), attribute_id, AttributeKey::Attribute),
1942 |item| match item.value {
1943 ObjectValue::Attribute { size: _, has_overwrite_extents: true } => {
1944 Err(anyhow!(FxfsError::Inconsistent)
1945 .context("write_attr on an attribute with overwrite extents"))
1946 }
1947 ObjectValue::Attribute { size, .. } => Ok((data.len() as u64) < *size),
1948 _ => Err(FxfsError::Inconsistent.into()),
1949 },
1950 )
1951 .await?
1952 .transpose()?
1953 .unwrap_or(false);
1954 let mut buffer = self.store().device.allocate_buffer(rounded_len as usize).await;
1955 let mut slice = buffer.as_mut_ptr_slice();
1956 slice.subslice_mut(0..data.len()).copy_from_slice(data);
1957 slice.subslice_mut(data.len()..slice.len()).fill(0);
1958 self.multi_write(
1959 transaction,
1960 attribute_id,
1961 Some(VOLUME_DATA_KEY_ID),
1962 &[0..rounded_len],
1963 buffer.as_mut(),
1964 )
1965 .await?;
1966 transaction.add(
1967 self.store().store_object_id,
1968 Mutation::replace_or_insert_object(
1969 ObjectKey::attribute(self.object_id(), attribute_id, AttributeKey::Attribute),
1970 ObjectValue::attribute(data.len() as u64, false),
1971 ),
1972 );
1973 if should_trim {
1974 self.shrink(transaction, attribute_id, data.len() as u64).await
1975 } else {
1976 Ok(NeedsTrim(false))
1977 }
1978 }
1979
1980 pub async fn list_extended_attributes(&self) -> Result<Vec<Vec<u8>>, Error> {
1981 let layer_set = self.store().tree().layer_set();
1982 let mut merger = layer_set.merger();
1983 let mut iter = merger
1985 .query(Query::FullRange(&ObjectKey::extended_attribute(self.object_id(), Vec::new())))
1986 .await?;
1987 let mut out = Vec::new();
1988 while let Some(item) = iter.get() {
1989 if item.value != &ObjectValue::None {
1991 match item.key {
1992 ObjectKey { object_id, data: ObjectKeyData::ExtendedAttribute { name } }
1993 if *object_id == self.object_id() =>
1994 {
1995 out.push(name.clone());
1996 }
1997 _ => break,
2002 }
2003 }
2004 iter.advance().await?;
2005 }
2006 Ok(out)
2007 }
2008
2009 pub async fn get_inline_selinux_context(&self) -> Result<Option<fio::SelinuxContext>, Error> {
2013 const_assert!(fio::MAX_SELINUX_CONTEXT_ATTRIBUTE_LEN as usize <= MAX_INLINE_XATTR_SIZE);
2016 self.store()
2017 .tree()
2018 .find_map(
2019 &ObjectKey::extended_attribute(self.object_id(), fio::SELINUX_CONTEXT_NAME.into()),
2020 |item| match item.value {
2021 ObjectValue::ExtendedAttribute(ExtendedAttributeValue::Inline(value)) => {
2022 Ok(fio::SelinuxContext::Data(value.clone()))
2023 }
2024 ObjectValue::ExtendedAttribute(ExtendedAttributeValue::AttributeId(_)) => {
2025 Ok(fio::SelinuxContext::UseExtendedAttributes(fio::EmptyStruct {}))
2026 }
2027 _ => Err(anyhow!(FxfsError::Inconsistent).context(
2028 "get_inline_extended_attribute: Expected ExtendedAttribute value",
2029 )),
2030 },
2031 )
2032 .await?
2033 .transpose()
2034 }
2035
2036 pub async fn get_extended_attribute(&self, name: Vec<u8>) -> Result<Vec<u8>, Error> {
2037 let value = self
2038 .store()
2039 .tree()
2040 .find_value(&ObjectKey::extended_attribute(self.object_id(), name))
2041 .await?
2042 .ok_or(FxfsError::NotFound)?;
2043 match value {
2044 ObjectValue::ExtendedAttribute(ExtendedAttributeValue::Inline(value)) => Ok(value),
2045 ObjectValue::ExtendedAttribute(ExtendedAttributeValue::AttributeId(id)) => {
2046 ensure!(id.is_xattr(), FxfsError::Inconsistent);
2047 Ok(self.read_attr(id).await?.ok_or(FxfsError::Inconsistent)?.into_vec())
2048 }
2049 _ => {
2050 bail!(
2051 anyhow!(FxfsError::Inconsistent)
2052 .context("get_extended_attribute: Expected ExtendedAttribute value")
2053 )
2054 }
2055 }
2056 }
2057
2058 pub async fn set_extended_attribute(
2059 &self,
2060 name: Vec<u8>,
2061 value: Vec<u8>,
2062 mode: SetExtendedAttributeMode,
2063 ) -> Result<(), Error> {
2064 let store = self.store();
2065 let keys = lock_keys![LockKey::object(store.store_object_id(), self.object_id())];
2068 let mut transaction = store.new_transaction(keys, Options::default()).await?;
2069 self.set_extended_attribute_impl(name, value, mode, &mut transaction).await?;
2070 transaction.commit().await?;
2071 Ok(())
2072 }
2073
2074 async fn set_extended_attribute_impl(
2075 &self,
2076 name: Vec<u8>,
2077 value: Vec<u8>,
2078 mode: SetExtendedAttributeMode,
2079 transaction: &mut Transaction<'_>,
2080 ) -> Result<(), Error> {
2081 ensure!(name.len() <= MAX_XATTR_NAME_SIZE, FxfsError::TooBig);
2082 ensure!(value.len() <= MAX_XATTR_VALUE_SIZE, FxfsError::TooBig);
2083 let tree = self.store().tree();
2084 let object_key = ObjectKey::extended_attribute(self.object_id(), name);
2085
2086 let existing_attribute_id = {
2087 let find_result = tree
2088 .find_map(&object_key, |item| match item.value {
2089 ObjectValue::ExtendedAttribute(ExtendedAttributeValue::Inline(..)) => Ok(None),
2090 ObjectValue::ExtendedAttribute(ExtendedAttributeValue::AttributeId(id)) => {
2091 ensure!(id.is_xattr(), FxfsError::Inconsistent);
2092 Ok(Some(*id))
2093 }
2094 _ => Err(anyhow!(FxfsError::Inconsistent)
2095 .context("expected extended attribute value")),
2096 })
2097 .await?;
2098 let (found, existing_attribute_id) = match find_result {
2099 Some(id) => (true, id?),
2100 None => (false, None),
2101 };
2102 match mode {
2103 SetExtendedAttributeMode::Create if found => {
2104 bail!(FxfsError::AlreadyExists)
2105 }
2106 SetExtendedAttributeMode::Replace if !found => {
2107 bail!(FxfsError::NotFound)
2108 }
2109 _ => (),
2110 }
2111 existing_attribute_id
2112 };
2113
2114 if let Some(attribute_id) = existing_attribute_id {
2115 let _ = self.write_attr(transaction, attribute_id, &value).await?;
2121 } else if value.len() <= MAX_INLINE_XATTR_SIZE {
2122 transaction.add(
2123 self.store().store_object_id(),
2124 Mutation::replace_or_insert_object(
2125 object_key,
2126 ObjectValue::inline_extended_attribute(value),
2127 ),
2128 );
2129 } else {
2130 let mut attribute_id = AttributeId::XATTR_RANGE_START;
2136 let layer_set = tree.layer_set();
2137 let mut merger = layer_set.merger();
2138 let key = ObjectKey::attribute(self.object_id(), attribute_id, AttributeKey::Attribute);
2139 let mut iter = merger.query(Query::FullRange(&key)).await?;
2140 loop {
2141 match iter.get() {
2142 None => break,
2145 Some(ItemRef {
2146 key: ObjectKey { object_id, data: ObjectKeyData::Attribute(attr_id, _) },
2147 value,
2148 ..
2149 }) if *object_id == self.object_id() => {
2150 if matches!(value, ObjectValue::None) {
2151 break;
2154 }
2155 if attribute_id < *attr_id {
2156 break;
2158 } else if attribute_id == *attr_id {
2159 attribute_id = attribute_id.next();
2161 if attribute_id == AttributeId::XATTR_RANGE_END {
2162 bail!(FxfsError::NoSpace);
2163 }
2164 }
2165 }
2169 _ => break,
2173 }
2174 iter.advance().await?;
2175 }
2176
2177 let _ = self.write_attr(transaction, attribute_id, &value).await?;
2179 transaction.add(
2180 self.store().store_object_id(),
2181 Mutation::replace_or_insert_object(
2182 object_key,
2183 ObjectValue::extended_attribute(attribute_id),
2184 ),
2185 );
2186 }
2187
2188 Ok(())
2189 }
2190
2191 pub async fn remove_extended_attribute(&self, name: Vec<u8>) -> Result<(), Error> {
2192 let store = self.store();
2193 let tree = store.tree();
2194 let object_key = ObjectKey::extended_attribute(self.object_id(), name);
2195
2196 let keys = lock_keys![LockKey::object(store.store_object_id(), self.object_id())];
2201 let mut transaction = store.new_transaction(keys, Options::default()).await?;
2202
2203 let attribute_to_delete = tree
2204 .find_map(&object_key, |item| match item.value {
2205 ObjectValue::ExtendedAttribute(ExtendedAttributeValue::AttributeId(id)) => {
2206 ensure!(id.is_xattr(), FxfsError::Inconsistent);
2207 Ok(Some(*id))
2208 }
2209 ObjectValue::ExtendedAttribute(ExtendedAttributeValue::Inline(..)) => Ok(None),
2210 _ => Err(anyhow!(FxfsError::Inconsistent)
2211 .context("remove_extended_attribute: Expected ExtendedAttribute value")),
2212 })
2213 .await?
2214 .ok_or(FxfsError::NotFound)??;
2215
2216 transaction.add(
2217 store.store_object_id(),
2218 Mutation::replace_or_insert_object(object_key, ObjectValue::None),
2219 );
2220
2221 if let Some(attribute_id) = attribute_to_delete {
2228 let trim_result = store
2229 .trim_some(
2230 &mut transaction,
2231 self.object_id(),
2232 attribute_id,
2233 TrimMode::FromOffset(0),
2234 )
2235 .await?;
2236 assert_matches!(trim_result, TrimResult::Done(_));
2239 transaction.add(
2240 store.store_object_id(),
2241 Mutation::replace_or_insert_object(
2242 ObjectKey::attribute(self.object_id, attribute_id, AttributeKey::Attribute),
2243 ObjectValue::None,
2244 ),
2245 );
2246 }
2247
2248 transaction.commit().await?;
2249 Ok(())
2250 }
2251
2252 pub fn pre_fetch_keys(&self) -> Option<impl Future<Output = ()> + use<S>> {
2255 if let Encryption::CachedKeys = self.encryption {
2256 let owner = self.owner.clone();
2257 let object_id = self.object_id;
2258 Some(async move {
2259 let store = owner.as_ref().as_ref();
2260 if let Some(crypt) = store.crypt() {
2261 let _ = store
2262 .key_manager
2263 .get_keys(
2264 object_id,
2265 crypt.as_ref(),
2266 &mut Some(async || store.get_keys(object_id).await),
2267 false,
2268 false,
2269 )
2270 .await;
2271 }
2272 })
2273 } else {
2274 None
2275 }
2276 }
2277
2278 pub async fn read_encrypted_symlink(&self, link: Vec<u8>) -> Result<Vec<u8>, Error> {
2283 self.store().read_encrypted_symlink(self.object_id, link).await
2284 }
2285
2286 pub async fn read_symlink(&self) -> Result<Vec<u8>, Error> {
2288 let store = self.store();
2289 match store.tree.find(&ObjectKey::object(self.object_id)).await? {
2290 None | Some(ObjectItem { value: ObjectValue::None, .. }) => bail!(FxfsError::NotFound),
2291 Some(ObjectItem {
2292 value: ObjectValue::Object { kind: ObjectKind::EncryptedSymlink { link, .. }, .. },
2293 ..
2294 }) => store.read_encrypted_symlink(self.object_id, link.into_vec()).await,
2295 Some(ObjectItem {
2296 value: ObjectValue::Object { kind: ObjectKind::Symlink { link, .. }, .. },
2297 ..
2298 }) => Ok(link.into_vec()),
2299 Some(ObjectItem {
2300 value: ObjectValue::Object { kind: ObjectKind::NonInlineSymlink { .. }, .. },
2301 ..
2302 }) => self.read_non_inline_symlink().await,
2303 Some(item) => Err(anyhow!(FxfsError::Inconsistent)
2304 .context(format!("Unexpected item in symlink lookup: {item:?}"))),
2305 }
2306 }
2307
2308 pub(crate) async fn read_non_inline_symlink(&self) -> Result<Vec<u8>, Error> {
2309 let tree = &self.store().tree;
2322 let layer_set = tree.layer_set();
2323 let mut merger = layer_set.merger();
2324 let mut iter = merger.query(Query::FullRange(&ObjectKey::keys(self.object_id))).await?;
2325 let mut is_fscrypt = false;
2326 loop {
2327 match iter.get() {
2328 Some(ItemRef {
2329 key: ObjectKey { object_id, data: ObjectKeyData::Keys },
2330 value: ObjectValue::Keys(keys),
2331 ..
2332 }) if *object_id == self.object_id => {
2333 is_fscrypt = keys.get(FSCRYPT_KEY_ID).is_some();
2334 }
2335 Some(ItemRef {
2336 key:
2337 ObjectKey {
2338 object_id,
2339 data:
2340 ObjectKeyData::Attribute(AttributeId::DATA, AttributeKey::Attribute),
2341 },
2342 value: ObjectValue::Attribute { .. },
2343 ..
2344 }) if *object_id == self.object_id => break,
2345 _ => bail!(FxfsError::Inconsistent),
2346 }
2347 iter.advance().await?;
2348 }
2349 if is_fscrypt {
2350 let link = self.read_attr_from_iter_impl(iter, false).await?.into_vec();
2351 self.read_encrypted_symlink(link).await
2352 } else {
2353 Ok(self.read_attr_from_iter(iter).await?.into_vec())
2354 }
2355 }
2356}
2357
2358impl<S: HandleOwner> Drop for StoreObjectHandle<S> {
2359 fn drop(&mut self) {
2360 if self.is_encrypted() {
2361 let _ = self.store().key_manager.remove(self.object_id);
2362 }
2363 }
2364}
2365
2366#[must_use]
2370pub struct NeedsTrim(pub bool);
2371
2372#[cfg(test)]
2373mod tests {
2374 use super::{ChecksumRangeChunk, OverwriteBitmaps};
2375 use crate::errors::FxfsError;
2376 use crate::filesystem::{FxFilesystem, OpenFxFilesystem};
2377 use crate::object_handle::{ObjectHandle, WriteObjectHandle};
2378 use crate::object_store::data_object_handle::WRITE_ATTR_BATCH_SIZE;
2379 use crate::object_store::transaction::{Mutation, Options, lock_keys};
2380 use crate::object_store::{
2381 AttributeId, AttributeKey, DataObjectHandle, Directory, HandleOptions, LockKey, ObjectKey,
2382 ObjectStore, ObjectValue, SetExtendedAttributeMode, StoreObjectHandle,
2383 };
2384 use bit_vec::BitVec;
2385 use fuchsia_async as fasync;
2386 use futures::{TryStreamExt, join};
2387 use std::sync::Arc;
2388 use storage_device::DeviceHolder;
2389 use storage_device::fake_device::FakeDevice;
2390 use storage_units::BlockSize;
2391
2392 const TEST_DEVICE_BLOCK_SIZE: u32 = 512;
2393 const TEST_OBJECT_NAME: &str = "foo";
2394
2395 fn is_error(actual: anyhow::Error, expected: FxfsError) {
2396 assert_eq!(*actual.root_cause().downcast_ref::<FxfsError>().unwrap(), expected)
2397 }
2398
2399 async fn test_filesystem() -> OpenFxFilesystem {
2400 let device = DeviceHolder::new(FakeDevice::new(16384, TEST_DEVICE_BLOCK_SIZE));
2401 FxFilesystem::new_empty(device).await.expect("new_empty failed")
2402 }
2403
2404 async fn test_filesystem_and_empty_object() -> (OpenFxFilesystem, DataObjectHandle<ObjectStore>)
2405 {
2406 let fs = test_filesystem().await;
2407 let store = fs.root_store();
2408
2409 let mut transaction = fs
2410 .root_store()
2411 .new_transaction(
2412 lock_keys![LockKey::object(
2413 store.store_object_id(),
2414 store.root_directory_object_id()
2415 )],
2416 Options::default(),
2417 )
2418 .await
2419 .expect("new_transaction failed");
2420
2421 let object =
2422 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
2423 .await
2424 .expect("create_object failed");
2425
2426 let root_directory =
2427 Directory::open(&store, store.root_directory_object_id()).await.expect("open failed");
2428 root_directory
2429 .add_child_file(&mut transaction, TEST_OBJECT_NAME, &object)
2430 .await
2431 .expect("add_child_file failed");
2432
2433 transaction.commit().await.expect("commit failed");
2434
2435 (fs, object)
2436 }
2437
2438 #[fuchsia::test]
2439 async fn test_extent_stream() {
2440 let (fs, object) = test_filesystem_and_empty_object().await;
2441
2442 let mut buf = object.allocate_buffer(8192).await;
2444 buf.as_mut_ptr_slice().fill(0xaa);
2445 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
2446 object.write_or_append(Some(16384), buf.as_ref()).await.expect("write failed");
2447
2448 let basic = StoreObjectHandle::new(
2449 object.owner().clone(),
2450 object.object_id(),
2451 false,
2452 HandleOptions::default(),
2453 false,
2454 );
2455
2456 let store = fs.root_store();
2457 let layer_set = store.tree.layer_set();
2458 let mut merger = layer_set.merger();
2459
2460 let stream = basic
2461 .extent_stream(&mut merger, AttributeId::DATA)
2462 .await
2463 .expect("extent_stream failed");
2464
2465 let result: Vec<_> = stream.try_collect().await.expect("stream item error");
2466
2467 assert_eq!(result.len(), 2);
2469 assert_eq!(result[0].logical_offset(), 0);
2470 assert_eq!(result[0].length(), 8192);
2471 assert_eq!(result[1].logical_offset(), 16384);
2472 assert_eq!(result[1].length(), 8192);
2473 }
2474
2475 #[fuchsia::test(threads = 3)]
2476 async fn extended_attribute_double_remove() {
2477 let (fs, object) = test_filesystem_and_empty_object().await;
2482 let basic = Arc::new(StoreObjectHandle::new(
2483 object.owner().clone(),
2484 object.object_id(),
2485 false,
2486 HandleOptions::default(),
2487 false,
2488 ));
2489 let basic_a = basic.clone();
2490 let basic_b = basic.clone();
2491
2492 basic
2493 .set_extended_attribute(
2494 b"security.selinux".to_vec(),
2495 b"bar".to_vec(),
2496 SetExtendedAttributeMode::Set,
2497 )
2498 .await
2499 .expect("failed to set attribute");
2500
2501 let a_task = fasync::Task::spawn(async move {
2504 basic_a.remove_extended_attribute(b"security.selinux".to_vec()).await
2505 });
2506 let b_task = fasync::Task::spawn(async move {
2507 basic_b.remove_extended_attribute(b"security.selinux".to_vec()).await
2508 });
2509 match join!(a_task, b_task) {
2510 (Ok(()), Ok(())) => panic!("both remove calls succeeded"),
2511 (Err(_), Err(_)) => panic!("both remove calls failed"),
2512
2513 (Ok(()), Err(e)) => is_error(e, FxfsError::NotFound),
2514 (Err(e), Ok(())) => is_error(e, FxfsError::NotFound),
2515 }
2516
2517 fs.close().await.expect("Close failed");
2518 }
2519
2520 #[fuchsia::test(threads = 3)]
2521 async fn extended_attribute_double_create() {
2522 let (fs, object) = test_filesystem_and_empty_object().await;
2527 let basic = Arc::new(StoreObjectHandle::new(
2528 object.owner().clone(),
2529 object.object_id(),
2530 false,
2531 HandleOptions::default(),
2532 false,
2533 ));
2534 let basic_a = basic.clone();
2535 let basic_b = basic.clone();
2536
2537 let a_task = fasync::Task::spawn(async move {
2540 basic_a
2541 .set_extended_attribute(
2542 b"security.selinux".to_vec(),
2543 b"one".to_vec(),
2544 SetExtendedAttributeMode::Create,
2545 )
2546 .await
2547 });
2548 let b_task = fasync::Task::spawn(async move {
2549 basic_b
2550 .set_extended_attribute(
2551 b"security.selinux".to_vec(),
2552 b"two".to_vec(),
2553 SetExtendedAttributeMode::Create,
2554 )
2555 .await
2556 });
2557 match join!(a_task, b_task) {
2558 (Ok(()), Ok(())) => panic!("both set calls succeeded"),
2559 (Err(_), Err(_)) => panic!("both set calls failed"),
2560
2561 (Ok(()), Err(e)) => {
2562 assert_eq!(
2563 basic
2564 .get_extended_attribute(b"security.selinux".to_vec())
2565 .await
2566 .expect("failed to get xattr"),
2567 b"one"
2568 );
2569 is_error(e, FxfsError::AlreadyExists);
2570 }
2571 (Err(e), Ok(())) => {
2572 assert_eq!(
2573 basic
2574 .get_extended_attribute(b"security.selinux".to_vec())
2575 .await
2576 .expect("failed to get xattr"),
2577 b"two"
2578 );
2579 is_error(e, FxfsError::AlreadyExists);
2580 }
2581 }
2582
2583 fs.close().await.expect("Close failed");
2584 }
2585
2586 struct TestAttr {
2587 name: Vec<u8>,
2588 value: Vec<u8>,
2589 }
2590
2591 impl TestAttr {
2592 fn new(name: impl AsRef<[u8]>, value: impl AsRef<[u8]>) -> Self {
2593 Self { name: name.as_ref().to_vec(), value: value.as_ref().to_vec() }
2594 }
2595 fn name(&self) -> Vec<u8> {
2596 self.name.clone()
2597 }
2598 fn value(&self) -> Vec<u8> {
2599 self.value.clone()
2600 }
2601 }
2602
2603 #[fuchsia::test]
2604 async fn extended_attributes() {
2605 let (fs, object) = test_filesystem_and_empty_object().await;
2606
2607 let test_attr = TestAttr::new(b"security.selinux", b"foo");
2608
2609 assert_eq!(object.list_extended_attributes().await.unwrap(), Vec::<Vec<u8>>::new());
2610 is_error(
2611 object.get_extended_attribute(test_attr.name()).await.unwrap_err(),
2612 FxfsError::NotFound,
2613 );
2614
2615 object
2616 .set_extended_attribute(
2617 test_attr.name(),
2618 test_attr.value(),
2619 SetExtendedAttributeMode::Set,
2620 )
2621 .await
2622 .unwrap();
2623 assert_eq!(object.list_extended_attributes().await.unwrap(), vec![test_attr.name()]);
2624 assert_eq!(
2625 object.get_extended_attribute(test_attr.name()).await.unwrap(),
2626 test_attr.value()
2627 );
2628
2629 object.remove_extended_attribute(test_attr.name()).await.unwrap();
2630 assert_eq!(object.list_extended_attributes().await.unwrap(), Vec::<Vec<u8>>::new());
2631 is_error(
2632 object.get_extended_attribute(test_attr.name()).await.unwrap_err(),
2633 FxfsError::NotFound,
2634 );
2635
2636 object
2638 .set_extended_attribute(
2639 test_attr.name(),
2640 test_attr.value(),
2641 SetExtendedAttributeMode::Set,
2642 )
2643 .await
2644 .unwrap();
2645 assert_eq!(object.list_extended_attributes().await.unwrap(), vec![test_attr.name()]);
2646 assert_eq!(
2647 object.get_extended_attribute(test_attr.name()).await.unwrap(),
2648 test_attr.value()
2649 );
2650
2651 object.remove_extended_attribute(test_attr.name()).await.unwrap();
2652 assert_eq!(object.list_extended_attributes().await.unwrap(), Vec::<Vec<u8>>::new());
2653 is_error(
2654 object.get_extended_attribute(test_attr.name()).await.unwrap_err(),
2655 FxfsError::NotFound,
2656 );
2657
2658 fs.close().await.expect("close failed");
2659 }
2660
2661 #[fuchsia::test]
2662 async fn extended_attribute_invalid_id_range() {
2663 let (fs, object) = test_filesystem_and_empty_object().await;
2664
2665 let store = object.owner();
2666 let mut transaction = store
2667 .new_transaction(
2668 lock_keys![LockKey::object(store.store_object_id(), object.object_id())],
2669 Options::default(),
2670 )
2671 .await
2672 .unwrap();
2673 transaction.add(
2674 store.store_object_id(),
2675 Mutation::replace_or_insert_object(
2676 ObjectKey::extended_attribute(object.object_id(), b"bad_attr".to_vec()),
2677 ObjectValue::extended_attribute(AttributeId::DATA),
2678 ),
2679 );
2680 transaction.commit().await.unwrap();
2681
2682 is_error(
2683 object.get_extended_attribute(b"bad_attr".to_vec()).await.unwrap_err(),
2684 FxfsError::Inconsistent,
2685 );
2686 is_error(
2687 object
2688 .set_extended_attribute(
2689 b"bad_attr".to_vec(),
2690 b"new_val".to_vec(),
2691 SetExtendedAttributeMode::Set,
2692 )
2693 .await
2694 .unwrap_err(),
2695 FxfsError::Inconsistent,
2696 );
2697 is_error(
2698 object.remove_extended_attribute(b"bad_attr".to_vec()).await.unwrap_err(),
2699 FxfsError::Inconsistent,
2700 );
2701
2702 fs.close().await.expect("close failed");
2703 }
2704
2705 #[fuchsia::test]
2706 async fn large_extended_attribute() {
2707 let (fs, object) = test_filesystem_and_empty_object().await;
2708
2709 let test_attr = TestAttr::new(b"security.selinux", vec![3u8; 300]);
2710
2711 object
2712 .set_extended_attribute(
2713 test_attr.name(),
2714 test_attr.value(),
2715 SetExtendedAttributeMode::Set,
2716 )
2717 .await
2718 .unwrap();
2719 assert_eq!(
2720 object.get_extended_attribute(test_attr.name()).await.unwrap(),
2721 test_attr.value()
2722 );
2723
2724 assert_eq!(
2727 object
2728 .read_attr(AttributeId::XATTR_RANGE_START)
2729 .await
2730 .expect("read_attr failed")
2731 .expect("read_attr returned none")
2732 .into_vec(),
2733 test_attr.value()
2734 );
2735
2736 object.remove_extended_attribute(test_attr.name()).await.unwrap();
2737 is_error(
2738 object.get_extended_attribute(test_attr.name()).await.unwrap_err(),
2739 FxfsError::NotFound,
2740 );
2741
2742 object
2744 .set_extended_attribute(
2745 test_attr.name(),
2746 test_attr.value(),
2747 SetExtendedAttributeMode::Set,
2748 )
2749 .await
2750 .unwrap();
2751 assert_eq!(
2752 object.get_extended_attribute(test_attr.name()).await.unwrap(),
2753 test_attr.value()
2754 );
2755 object.remove_extended_attribute(test_attr.name()).await.unwrap();
2756 is_error(
2757 object.get_extended_attribute(test_attr.name()).await.unwrap_err(),
2758 FxfsError::NotFound,
2759 );
2760
2761 fs.close().await.expect("close failed");
2762 }
2763
2764 #[fuchsia::test]
2765 async fn multiple_extended_attributes() {
2766 let (fs, object) = test_filesystem_and_empty_object().await;
2767
2768 let attrs = [
2769 TestAttr::new(b"security.selinux", b"foo"),
2770 TestAttr::new(b"large.attribute", vec![3u8; 300]),
2771 TestAttr::new(b"an.attribute", b"asdf"),
2772 TestAttr::new(b"user.big", vec![5u8; 288]),
2773 TestAttr::new(b"user.tiny", b"smol"),
2774 TestAttr::new(b"this string doesn't matter", b"the quick brown fox etc"),
2775 TestAttr::new(b"also big", vec![7u8; 500]),
2776 TestAttr::new(b"all.ones", vec![1u8; 11111]),
2777 ];
2778
2779 for i in 0..attrs.len() {
2780 object
2781 .set_extended_attribute(
2782 attrs[i].name(),
2783 attrs[i].value(),
2784 SetExtendedAttributeMode::Set,
2785 )
2786 .await
2787 .unwrap();
2788 assert_eq!(
2789 object.get_extended_attribute(attrs[i].name()).await.unwrap(),
2790 attrs[i].value()
2791 );
2792 }
2793
2794 for i in 0..attrs.len() {
2795 let mut found_attrs = object.list_extended_attributes().await.unwrap();
2797 let mut expected_attrs: Vec<Vec<u8>> = attrs.iter().skip(i).map(|a| a.name()).collect();
2798 found_attrs.sort();
2799 expected_attrs.sort();
2800 assert_eq!(found_attrs, expected_attrs);
2801 for j in i..attrs.len() {
2802 assert_eq!(
2803 object.get_extended_attribute(attrs[j].name()).await.unwrap(),
2804 attrs[j].value()
2805 );
2806 }
2807
2808 object.remove_extended_attribute(attrs[i].name()).await.expect("failed to remove");
2809 is_error(
2810 object.get_extended_attribute(attrs[i].name()).await.unwrap_err(),
2811 FxfsError::NotFound,
2812 );
2813 }
2814
2815 fs.close().await.expect("close failed");
2816 }
2817
2818 #[fuchsia::test]
2819 async fn multiple_extended_attributes_delete() {
2820 let (fs, object) = test_filesystem_and_empty_object().await;
2821 let store = object.owner().clone();
2822
2823 let attrs = [
2824 TestAttr::new(b"security.selinux", b"foo"),
2825 TestAttr::new(b"large.attribute", vec![3u8; 300]),
2826 TestAttr::new(b"an.attribute", b"asdf"),
2827 TestAttr::new(b"user.big", vec![5u8; 288]),
2828 TestAttr::new(b"user.tiny", b"smol"),
2829 TestAttr::new(b"this string doesn't matter", b"the quick brown fox etc"),
2830 TestAttr::new(b"also big", vec![7u8; 500]),
2831 TestAttr::new(b"all.ones", vec![1u8; 11111]),
2832 ];
2833
2834 for i in 0..attrs.len() {
2835 object
2836 .set_extended_attribute(
2837 attrs[i].name(),
2838 attrs[i].value(),
2839 SetExtendedAttributeMode::Set,
2840 )
2841 .await
2842 .unwrap();
2843 assert_eq!(
2844 object.get_extended_attribute(attrs[i].name()).await.unwrap(),
2845 attrs[i].value()
2846 );
2847 }
2848
2849 let root_directory =
2851 Directory::open(object.owner(), object.store().root_directory_object_id())
2852 .await
2853 .expect("open failed");
2854 let mut transaction = fs
2855 .root_store()
2856 .new_transaction(
2857 lock_keys![
2858 LockKey::object(store.store_object_id(), store.root_directory_object_id()),
2859 LockKey::object(store.store_object_id(), object.object_id()),
2860 ],
2861 Options::default(),
2862 )
2863 .await
2864 .expect("new_transaction failed");
2865 crate::object_store::directory::replace_child(
2866 &mut transaction,
2867 None,
2868 (&root_directory, TEST_OBJECT_NAME),
2869 )
2870 .await
2871 .expect("replace_child failed");
2872 transaction.commit().await.unwrap();
2873 store.tombstone_object(object.object_id(), Options::default(), None).await.unwrap();
2874
2875 crate::fsck::fsck(fs.clone()).await.unwrap();
2876
2877 fs.close().await.expect("close failed");
2878 }
2879
2880 #[fuchsia::test]
2881 async fn extended_attribute_changing_sizes() {
2882 let (fs, object) = test_filesystem_and_empty_object().await;
2883
2884 let test_name = b"security.selinux";
2885 let test_small_attr = TestAttr::new(test_name, b"smol");
2886 let test_large_attr = TestAttr::new(test_name, vec![3u8; 300]);
2887
2888 object
2889 .set_extended_attribute(
2890 test_small_attr.name(),
2891 test_small_attr.value(),
2892 SetExtendedAttributeMode::Set,
2893 )
2894 .await
2895 .unwrap();
2896 assert_eq!(
2897 object.get_extended_attribute(test_small_attr.name()).await.unwrap(),
2898 test_small_attr.value()
2899 );
2900
2901 assert!(
2903 object
2904 .read_attr(AttributeId::XATTR_RANGE_START)
2905 .await
2906 .expect("read_attr failed")
2907 .is_none()
2908 );
2909
2910 crate::fsck::fsck(fs.clone()).await.unwrap();
2911
2912 object
2913 .set_extended_attribute(
2914 test_large_attr.name(),
2915 test_large_attr.value(),
2916 SetExtendedAttributeMode::Set,
2917 )
2918 .await
2919 .unwrap();
2920 assert_eq!(
2921 object.get_extended_attribute(test_large_attr.name()).await.unwrap(),
2922 test_large_attr.value()
2923 );
2924
2925 assert_eq!(
2928 object
2929 .read_attr(AttributeId::XATTR_RANGE_START)
2930 .await
2931 .expect("read_attr failed")
2932 .expect("read_attr returned none")
2933 .into_vec(),
2934 test_large_attr.value()
2935 );
2936
2937 crate::fsck::fsck(fs.clone()).await.unwrap();
2938
2939 object
2940 .set_extended_attribute(
2941 test_small_attr.name(),
2942 test_small_attr.value(),
2943 SetExtendedAttributeMode::Set,
2944 )
2945 .await
2946 .unwrap();
2947 assert_eq!(
2948 object.get_extended_attribute(test_small_attr.name()).await.unwrap(),
2949 test_small_attr.value()
2950 );
2951
2952 assert_eq!(
2955 object
2956 .read_attr(AttributeId::XATTR_RANGE_START)
2957 .await
2958 .expect("read_attr failed")
2959 .expect("read_attr returned none")
2960 .into_vec(),
2961 test_small_attr.value()
2962 );
2963
2964 crate::fsck::fsck(fs.clone()).await.unwrap();
2965
2966 object.remove_extended_attribute(test_small_attr.name()).await.expect("failed to remove");
2967
2968 crate::fsck::fsck(fs.clone()).await.unwrap();
2969
2970 fs.close().await.expect("close failed");
2971 }
2972
2973 #[fuchsia::test]
2974 async fn extended_attribute_max_size() {
2975 let (fs, object) = test_filesystem_and_empty_object().await;
2976
2977 let test_attr = TestAttr::new(
2978 vec![3u8; super::MAX_XATTR_NAME_SIZE],
2979 vec![1u8; super::MAX_XATTR_VALUE_SIZE],
2980 );
2981
2982 object
2983 .set_extended_attribute(
2984 test_attr.name(),
2985 test_attr.value(),
2986 SetExtendedAttributeMode::Set,
2987 )
2988 .await
2989 .unwrap();
2990 assert_eq!(
2991 object.get_extended_attribute(test_attr.name()).await.unwrap(),
2992 test_attr.value()
2993 );
2994 assert_eq!(object.list_extended_attributes().await.unwrap(), vec![test_attr.name()]);
2995 object.remove_extended_attribute(test_attr.name()).await.unwrap();
2996
2997 fs.close().await.expect("close failed");
2998 }
2999
3000 #[fuchsia::test]
3001 async fn extended_attribute_remove_then_create() {
3002 let (fs, object) = test_filesystem_and_empty_object().await;
3003
3004 let test_attr = TestAttr::new(
3005 vec![3u8; super::MAX_XATTR_NAME_SIZE],
3006 vec![1u8; super::MAX_XATTR_VALUE_SIZE],
3007 );
3008
3009 object
3010 .set_extended_attribute(
3011 test_attr.name(),
3012 test_attr.value(),
3013 SetExtendedAttributeMode::Create,
3014 )
3015 .await
3016 .unwrap();
3017 fs.journal().force_compact().await.unwrap();
3018 object.remove_extended_attribute(test_attr.name()).await.unwrap();
3019 object
3020 .set_extended_attribute(
3021 test_attr.name(),
3022 test_attr.value(),
3023 SetExtendedAttributeMode::Create,
3024 )
3025 .await
3026 .unwrap();
3027
3028 assert_eq!(
3029 object.get_extended_attribute(test_attr.name()).await.unwrap(),
3030 test_attr.value()
3031 );
3032
3033 fs.close().await.expect("close failed");
3034 }
3035
3036 #[fuchsia::test]
3037 async fn large_extended_attribute_max_number() {
3038 let (fs, object) = test_filesystem_and_empty_object().await;
3039
3040 let max_xattrs = AttributeId::XATTR_RANGE_END.raw() - AttributeId::XATTR_RANGE_START.raw();
3041 for i in 0..max_xattrs {
3042 let test_attr = TestAttr::new(format!("{}", i).as_bytes(), vec![0x3; 300]);
3043 object
3044 .set_extended_attribute(
3045 test_attr.name(),
3046 test_attr.value(),
3047 SetExtendedAttributeMode::Set,
3048 )
3049 .await
3050 .unwrap_or_else(|_| panic!("failed to set xattr number {}", i));
3051 }
3052
3053 match object
3056 .set_extended_attribute(
3057 b"one.too.many".to_vec(),
3058 vec![0x3; 300],
3059 SetExtendedAttributeMode::Set,
3060 )
3061 .await
3062 {
3063 Ok(()) => panic!("set should not succeed"),
3064 Err(e) => is_error(e, FxfsError::NoSpace),
3065 }
3066
3067 object
3069 .set_extended_attribute(
3070 b"this.is.okay".to_vec(),
3071 b"small value".to_vec(),
3072 SetExtendedAttributeMode::Set,
3073 )
3074 .await
3075 .unwrap();
3076
3077 object
3079 .set_extended_attribute(b"11".to_vec(), vec![0x4; 300], SetExtendedAttributeMode::Set)
3080 .await
3081 .unwrap();
3082 object
3083 .set_extended_attribute(
3084 b"12".to_vec(),
3085 vec![0x1; 300],
3086 SetExtendedAttributeMode::Replace,
3087 )
3088 .await
3089 .unwrap();
3090
3091 object.remove_extended_attribute(b"5".to_vec()).await.unwrap();
3093 object
3094 .set_extended_attribute(
3095 b"new attr".to_vec(),
3096 vec![0x3; 300],
3097 SetExtendedAttributeMode::Set,
3098 )
3099 .await
3100 .unwrap();
3101
3102 fs.close().await.expect("close failed");
3103 }
3104
3105 #[fuchsia::test]
3106 async fn write_attr_trims_beyond_new_end() {
3107 let (fs, object) = test_filesystem_and_empty_object().await;
3112
3113 let block_size = fs.block_size();
3114 let buf_size = block_size * 2;
3115 let attribute_id = AttributeId::TEST_ID;
3116
3117 let mut transaction = (*object).new_transaction(attribute_id).await.unwrap();
3118 let mut buffer = object.allocate_buffer(buf_size as usize).await;
3119 buffer.fill(3);
3120 object
3123 .multi_write(
3124 &mut transaction,
3125 attribute_id,
3126 &[0..block_size.get(), block_size.get()..block_size * 2],
3127 buffer.as_mut(),
3128 )
3129 .await
3130 .unwrap();
3131 transaction.add(
3132 object.store().store_object_id,
3133 Mutation::replace_or_insert_object(
3134 ObjectKey::attribute(object.object_id(), attribute_id, AttributeKey::Attribute),
3135 ObjectValue::attribute(block_size * 2, false),
3136 ),
3137 );
3138 transaction.commit().await.unwrap();
3139
3140 crate::fsck::fsck(fs.clone()).await.unwrap();
3141
3142 let mut transaction = (*object).new_transaction(attribute_id).await.unwrap();
3143 let needs_trim = (*object)
3144 .write_attr(&mut transaction, attribute_id, &vec![3u8; block_size.get() as usize])
3145 .await
3146 .unwrap();
3147 assert!(!needs_trim.0);
3148 transaction.commit().await.unwrap();
3149
3150 crate::fsck::fsck(fs.clone()).await.unwrap();
3151
3152 fs.close().await.expect("close failed");
3153 }
3154
3155 #[fuchsia::test]
3156 async fn write_new_attr_multiple_txns() {
3157 let (fs, object) = test_filesystem_and_empty_object().await;
3158 let merkle_tree = vec![1; 3 * WRITE_ATTR_BATCH_SIZE];
3159 let mut transaction = (*object).new_transaction(AttributeId::TEST_ID).await.unwrap();
3160 object
3161 .write_new_attr(&mut transaction, AttributeId::TEST_ID, &merkle_tree)
3162 .await
3163 .expect("failed to write merkle attribute");
3164 transaction.commit().await.unwrap();
3165 assert_eq!(
3166 object.read_attr(AttributeId::TEST_ID).await.expect("read_attr failed"),
3167 Some(merkle_tree.into())
3168 );
3169
3170 fs.close().await.expect("close failed");
3171 }
3172
3173 #[cfg(target_os = "fuchsia")]
3175 #[fuchsia::test(allow_stalls = false)]
3176 async fn test_watchdog() {
3177 use super::Watchdog;
3178 use fuchsia_async::{MonotonicDuration, MonotonicInstant, TestExecutor};
3179 use std::sync::mpsc::channel;
3180
3181 TestExecutor::advance_to(make_time(0)).await;
3182 let (sender, receiver) = channel();
3183
3184 fn make_time(time_secs: i64) -> MonotonicInstant {
3185 MonotonicInstant::from_nanos(0) + MonotonicDuration::from_seconds(time_secs)
3186 }
3187
3188 {
3189 let _watchdog = Watchdog::new(10, move |count| {
3190 sender.send(count).expect("Sending value");
3191 });
3192
3193 TestExecutor::advance_to(make_time(5)).await;
3195 receiver.try_recv().expect_err("Should not have message");
3196
3197 TestExecutor::advance_to(make_time(10)).await;
3199 assert_eq!(1, receiver.recv().expect("Receiving"));
3200
3201 TestExecutor::advance_to(make_time(15)).await;
3203 receiver.try_recv().expect_err("Should not have message");
3204
3205 TestExecutor::advance_to(make_time(30)).await;
3207 assert_eq!(2, receiver.recv().expect("Receiving"));
3208 assert_eq!(3, receiver.recv().expect("Receiving"));
3209 }
3210
3211 TestExecutor::advance_to(make_time(100)).await;
3213 receiver.recv().expect_err("Watchdog should be gone");
3214 }
3215
3216 #[fuchsia::test]
3217 fn test_checksum_range_chunk() {
3218 let block_size = BlockSize::SIZE_4KIB;
3219
3220 assert_eq!(
3222 ChecksumRangeChunk::group_first_write_ranges(
3223 &mut OverwriteBitmaps::None,
3224 block_size,
3225 block_size * 2..block_size * 5,
3226 ),
3227 vec![ChecksumRangeChunk {
3228 checksum_range: 0..3,
3229 device_range: block_size * 2..block_size * 5,
3230 is_first_write: false,
3231 }],
3232 );
3233
3234 let mut bitmaps = OverwriteBitmaps::new(BitVec::from_bytes(&[0b11110000]));
3235 assert_eq!(
3236 ChecksumRangeChunk::group_first_write_ranges(
3237 &mut bitmaps,
3238 block_size,
3239 block_size * 2..block_size * 5,
3240 ),
3241 vec![ChecksumRangeChunk {
3242 checksum_range: 0..3,
3243 device_range: block_size * 2..block_size * 5,
3244 is_first_write: false,
3245 }],
3246 );
3247 assert_eq!(
3248 bitmaps.take_bitmaps(),
3249 Some((BitVec::from_bytes(&[0b11110000]), BitVec::from_bytes(&[0b11100000])))
3250 );
3251
3252 let mut bitmaps = OverwriteBitmaps::new(BitVec::from_bytes(&[0b11110000]));
3253 bitmaps.set_offset(2);
3254 assert_eq!(
3255 ChecksumRangeChunk::group_first_write_ranges(
3256 &mut bitmaps,
3257 block_size,
3258 block_size * 2..block_size * 5,
3259 ),
3260 vec![
3261 ChecksumRangeChunk {
3262 checksum_range: 0..2,
3263 device_range: block_size * 2..block_size * 4,
3264 is_first_write: false,
3265 },
3266 ChecksumRangeChunk {
3267 checksum_range: 2..3,
3268 device_range: block_size * 4..block_size * 5,
3269 is_first_write: true,
3270 },
3271 ],
3272 );
3273 assert_eq!(
3274 bitmaps.take_bitmaps(),
3275 Some((BitVec::from_bytes(&[0b11110000]), BitVec::from_bytes(&[0b00111000])))
3276 );
3277
3278 let mut bitmaps = OverwriteBitmaps::new(BitVec::from_bytes(&[0b11110000]));
3279 bitmaps.set_offset(4);
3280 assert_eq!(
3281 ChecksumRangeChunk::group_first_write_ranges(
3282 &mut bitmaps,
3283 block_size,
3284 block_size * 2..block_size * 5,
3285 ),
3286 vec![ChecksumRangeChunk {
3287 checksum_range: 0..3,
3288 device_range: block_size * 2..block_size * 5,
3289 is_first_write: true,
3290 }],
3291 );
3292 assert_eq!(
3293 bitmaps.take_bitmaps(),
3294 Some((BitVec::from_bytes(&[0b11110000]), BitVec::from_bytes(&[0b00001110])))
3295 );
3296
3297 let mut bitmaps = OverwriteBitmaps::new(BitVec::from_bytes(&[0b01010101]));
3298 assert_eq!(
3299 ChecksumRangeChunk::group_first_write_ranges(
3300 &mut bitmaps,
3301 block_size,
3302 block_size * 2..block_size * 10,
3303 ),
3304 vec![
3305 ChecksumRangeChunk {
3306 checksum_range: 0..1,
3307 device_range: block_size * 2..block_size * 3,
3308 is_first_write: true,
3309 },
3310 ChecksumRangeChunk {
3311 checksum_range: 1..2,
3312 device_range: block_size * 3..block_size * 4,
3313 is_first_write: false,
3314 },
3315 ChecksumRangeChunk {
3316 checksum_range: 2..3,
3317 device_range: block_size * 4..block_size * 5,
3318 is_first_write: true,
3319 },
3320 ChecksumRangeChunk {
3321 checksum_range: 3..4,
3322 device_range: block_size * 5..block_size * 6,
3323 is_first_write: false,
3324 },
3325 ChecksumRangeChunk {
3326 checksum_range: 4..5,
3327 device_range: block_size * 6..block_size * 7,
3328 is_first_write: true,
3329 },
3330 ChecksumRangeChunk {
3331 checksum_range: 5..6,
3332 device_range: block_size * 7..block_size * 8,
3333 is_first_write: false,
3334 },
3335 ChecksumRangeChunk {
3336 checksum_range: 6..7,
3337 device_range: block_size * 8..block_size * 9,
3338 is_first_write: true,
3339 },
3340 ChecksumRangeChunk {
3341 checksum_range: 7..8,
3342 device_range: block_size * 9..block_size * 10,
3343 is_first_write: false,
3344 },
3345 ],
3346 );
3347 assert_eq!(
3348 bitmaps.take_bitmaps(),
3349 Some((BitVec::from_bytes(&[0b01010101]), BitVec::from_bytes(&[0b11111111])))
3350 );
3351 }
3352
3353 #[fuchsia::test]
3354 async fn test_read_large_buffer_excessive_partitions() {
3355 let (_fs, object) = test_filesystem_and_empty_object().await;
3356
3357 let size = 5 * 1024 * 1024;
3359 let mut buf = object.allocate_buffer(size).await;
3360 buf.as_mut_ptr_slice().fill(0xab);
3361 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3362
3363 object.owner().flush().await.expect("flush failed");
3365
3366 let mut read_buf = object.allocate_buffer(size).await;
3368 assert_eq!(object.read_aligned(0, read_buf.as_mut()).await.expect("read failed"), size);
3369 assert_eq!(&read_buf.as_ptr_slice().to_vec()[..], &buf.as_ptr_slice().to_vec()[..]);
3370 }
3371
3372 #[fuchsia::test]
3373 #[should_panic(expected = "Write is too large for a single transaction")]
3374 #[cfg(debug_assertions)]
3375 async fn test_multi_write_single_transaction_too_large_panics() {
3376 use super::JOURNAL_CHECKSUM_BYTES_PER_BLOCK;
3377 use crate::object_store::transaction::TRANSACTION_MAX_JOURNAL_USAGE;
3378
3379 let device = DeviceHolder::new(FakeDevice::new(32768, TEST_DEVICE_BLOCK_SIZE));
3380 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
3381 let store = fs.root_store();
3382 let mut transaction = store
3383 .new_transaction(
3384 lock_keys![LockKey::object(
3385 store.store_object_id(),
3386 store.root_directory_object_id()
3387 )],
3388 Options::default(),
3389 )
3390 .await
3391 .expect("new_txn");
3392 let object =
3393 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3394 .await
3395 .expect("create_object failed");
3396 transaction.commit().await.expect("commit");
3397
3398 let num_blocks = TRANSACTION_MAX_JOURNAL_USAGE as usize / JOURNAL_CHECKSUM_BYTES_PER_BLOCK;
3402 let write_len = num_blocks * fs.block_size().get() as usize;
3403 let mut buf = object.allocate_buffer(write_len).await;
3404 buf.fill(0x11);
3405 let mut transaction = object.new_transaction().await.expect("new_txn");
3406 object
3407 .multi_write(&mut transaction, AttributeId::DATA, &[0..write_len as u64], buf.as_mut())
3408 .await
3409 .expect("multi_write");
3410 }
3411}