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