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