1use crate::errors::FxfsError;
6use crate::log::*;
7use crate::lsm_tree::Query;
8use crate::lsm_tree::types::{ItemRef, LayerIterator};
9use crate::object_handle::{
10 LayerObject, ObjectHandle, ObjectProperties, ReadObjectHandle, WriteBytes, WriteObjectHandle,
11};
12use crate::object_store::extent_record::{ExtentMode, ExtentValue};
13use crate::object_store::object_manager::ObjectManager;
14use crate::object_store::object_record::{
15 AttributeKey, DirType, FsverityMetadata, ObjectAttributes, ObjectItem, ObjectKey,
16 ObjectKeyData, ObjectKind, ObjectValue, Timestamp,
17};
18use crate::object_store::store_object_handle::{MaybeChecksums, NeedsTrim};
19use crate::object_store::transaction::{
20 self, AssocObj, AssociatedObject, LockKey, Mutation, ObjectStoreMutation, Operation, Options,
21 Transaction, lock_keys,
22};
23use crate::object_store::{
24 AttributeId, Extent, HandleOptions, HandleOwner, RootDigest, StoreObjectHandle,
25 TRANSACTION_MUTATION_THRESHOLD, TrimMode, TrimResult,
26};
27use crate::range::RangeExt;
28use anyhow::{Context, Error, anyhow, bail, ensure};
29use fidl_fuchsia_io as fio;
30use fsverity_merkle::{
31 FsVerityDescriptor, FsVerityDescriptorRaw, FsVerityHash, FsVerityHasher, FsVerityHasherOptions,
32 MerkleTree, MerkleTreeBuilder, Sha256Hash, Sha512Hash,
33};
34use fuchsia_sync::Mutex;
35use futures::TryStreamExt;
36use futures::stream::FuturesOrdered;
37use fxfs_trace::trace;
38use std::cmp::min;
39use std::future::Future;
40use std::ops::{Deref, Range};
41use std::pin::Pin;
42use std::sync::Arc;
43use std::sync::atomic::{self, AtomicU64, Ordering};
44use storage_device::WriteFlags;
45use storage_device::buffer::{Buffer, BufferFuture, BufferRef, MutableBufferRef};
46use storage_ptr_slice::PtrByteSlice;
47use storage_units::BlockSize;
48use zerocopy::FromBytes;
49
50mod allocated_ranges;
51pub use allocated_ranges::{AllocatedRanges, RangeType};
52
53pub const WRITE_ATTR_BATCH_SIZE: usize = 524_288;
56
57pub struct DataObjectHandle<S: HandleOwner> {
65 handle: StoreObjectHandle<S>,
66 attribute_id: AttributeId,
67 content_size: AtomicU64,
68 state: Mutex<DataObjectState>,
69}
70
71#[derive(Debug, Clone)]
73pub struct FileExtent {
74 logical_offset: u64,
75 device_range: Range<u64>,
76}
77
78impl FileExtent {
79 pub fn new(logical_offset: u64, device_range: Range<u64>) -> Result<Self, Error> {
80 let length = device_range.length()?;
82 let _ = logical_offset.checked_add(length).ok_or(FxfsError::OutOfRange)?;
84 Ok(Self { logical_offset, device_range })
85 }
86}
87
88impl FileExtent {
89 pub fn length(&self) -> u64 {
90 unsafe { self.device_range.unchecked_length() }
92 }
93
94 pub fn logical_offset(&self) -> u64 {
95 self.logical_offset
96 }
97
98 pub fn logical_range(&self) -> Range<u64> {
99 unsafe { self.logical_offset..self.logical_offset.unchecked_add(self.length()) }
101 }
102
103 pub fn device_range(&self) -> &Range<u64> {
104 &self.device_range
105 }
106}
107
108#[derive(Debug)]
109pub enum DataObjectState {
110 Standard(AllocatedRanges),
111 VerityStarted,
112 VerityPending(FsverityStateInner),
113 Verity(FsverityStateInner),
114}
115
116#[derive(Debug)]
117pub struct FsverityStateInner {
118 root_digest: RootDigest,
119 salt: Vec<u8>,
120 merkle_tree: Box<[u8]>,
123}
124
125#[derive(Debug, Default)]
126pub struct OverwriteOptions {
127 pub allow_allocations: bool,
130 pub barrier_on_first_write: bool,
131}
132
133impl FsverityStateInner {
134 pub fn new(root_digest: RootDigest, salt: Vec<u8>, merkle_tree: Box<[u8]>) -> Self {
135 FsverityStateInner { root_digest, salt, merkle_tree }
136 }
137
138 fn get_hasher_for_block_size(&self, block_size: BlockSize) -> FsVerityHasher {
139 match self.root_digest {
140 RootDigest::Sha256(_) => FsVerityHasher::Sha256(FsVerityHasherOptions::new(
141 self.salt.clone(),
142 block_size.get() as usize,
143 )),
144 RootDigest::Sha512(_) => FsVerityHasher::Sha512(FsVerityHasherOptions::new(
145 self.salt.clone(),
146 block_size.get() as usize,
147 )),
148 }
149 }
150
151 fn from_ptr_slice(
152 data: PtrByteSlice<'_>,
153 block_size: BlockSize,
154 ) -> Result<(Self, FsVerityHasher), Error> {
155 let descriptor = FsVerityDescriptor::new(data, block_size.get() as usize)
156 .map_err(|e| anyhow!(FxfsError::IntegrityError).context(e))?;
157
158 let root_digest = match descriptor.digest_algorithm() {
159 fio::HashAlgorithm::Sha256 => {
160 RootDigest::Sha256(descriptor.root_digest().try_into().unwrap())
161 }
162 fio::HashAlgorithm::Sha512 => RootDigest::Sha512(descriptor.root_digest().to_vec()),
163 _ => return Err(anyhow!(FxfsError::NotSupported).context("Unsupported hash algorithm")),
164 };
165 let hasher = descriptor.hasher();
166 let leaves =
167 descriptor.leaf_digests().map_err(|e| anyhow!(FxfsError::IntegrityError).context(e))?;
168
169 Ok((Self::new(root_digest, descriptor.salt().to_vec(), leaves.into_boxed_slice()), hasher))
170 }
171}
172
173impl<S: HandleOwner> Deref for DataObjectHandle<S> {
174 type Target = StoreObjectHandle<S>;
175 fn deref(&self) -> &Self::Target {
176 &self.handle
177 }
178}
179
180impl<S: HandleOwner> DataObjectHandle<S> {
181 pub fn new(
182 owner: Arc<S>,
183 object_id: u64,
184 permanent_keys: bool,
185 attribute_id: AttributeId,
186 size: u64,
187 options: HandleOptions,
188 trace: bool,
189 overwrite_ranges: &[Range<u64>],
190 ) -> Self {
191 Self {
192 handle: StoreObjectHandle::new(owner, object_id, permanent_keys, options, trace),
193 attribute_id,
194 content_size: AtomicU64::new(size),
195 state: Mutex::new(DataObjectState::Standard(AllocatedRanges::new(overwrite_ranges))),
196 }
197 }
198
199 pub fn attribute_id(&self) -> AttributeId {
200 self.attribute_id
201 }
202
203 pub fn into_store_object_handle(self) -> StoreObjectHandle<S> {
205 self.handle
206 }
207
208 pub fn overwrite_ranges_is_empty(&self) -> bool {
209 match &*self.state.lock() {
210 DataObjectState::Standard(ranges) => ranges.is_empty(),
211 _ => true,
212 }
213 }
214
215 pub fn with_overwrite_ranges<R>(&self, f: impl FnOnce(Option<&AllocatedRanges>) -> R) -> R {
216 let state = self.state.lock();
217 match &*state {
218 DataObjectState::Standard(ranges) => f(Some(ranges)),
219 _ => f(None),
220 }
221 }
222
223 pub fn with_overwrite_ranges_mut<R>(
224 &self,
225 f: impl FnOnce(Option<&mut AllocatedRanges>) -> R,
226 ) -> R {
227 let mut state = self.state.lock();
228 match &mut *state {
229 DataObjectState::Standard(ranges) => f(Some(ranges)),
230 _ => f(None),
231 }
232 }
233
234 pub fn is_verified_file(&self) -> bool {
235 matches!(*self.state.lock(), DataObjectState::Verity(_))
236 }
237
238 pub fn set_fsverity_state_started(&self) -> Result<(), Error> {
248 let mut state = self.state.lock();
249 match *state {
250 DataObjectState::Standard(_) => {
251 *state = DataObjectState::VerityStarted;
252 Ok(())
253 }
254 DataObjectState::VerityStarted | DataObjectState::VerityPending(_) => {
255 Err(anyhow!(FxfsError::Unavailable))
256 }
257 DataObjectState::Verity(_) => Err(anyhow!(FxfsError::AlreadyExists)),
258 }
259 }
260
261 pub fn set_fsverity_state_pending(&self, descriptor: FsverityStateInner) {
267 let mut state = self.state.lock();
268 assert!(matches!(*state, DataObjectState::VerityStarted));
269 *state = DataObjectState::VerityPending(descriptor);
270 }
271
272 pub fn finalize_fsverity_state(&self) {
278 let mut state = self.state.lock();
279 let old_state =
280 std::mem::replace(&mut *state, DataObjectState::Standard(AllocatedRanges::empty()));
281 match old_state {
282 DataObjectState::VerityPending(inner) => *state = DataObjectState::Verity(inner),
283 _ => panic!("Cannot finalize verity state from {old_state:?}"),
284 }
285 }
286
287 pub async fn set_fsverity_state_some(&self, descriptor: FsverityMetadata) -> Result<(), Error> {
295 let (metadata, hasher) = match descriptor {
296 FsverityMetadata::Internal(root_digest, salt) => {
297 let merkle_tree = self
298 .read_attr(AttributeId::FSVERITY_MERKLE)
299 .await?
300 .ok_or_else(|| anyhow!(FxfsError::Inconsistent))?;
301 let metadata = FsverityStateInner { root_digest, salt, merkle_tree };
302 let hasher = metadata.get_hasher_for_block_size(self.block_size());
303 (metadata, hasher)
304 }
305 FsverityMetadata::F2fs(verity_range) => {
306 let expected_length = verity_range.length()? as usize;
307 let mut buffer = self
308 .allocate_buffer(
309 self.block_size().align_up(expected_length as u64).unwrap() as usize
310 )
311 .await;
312 ensure!(
313 expected_length
314 == self
315 .handle
316 .read(AttributeId::FSVERITY_MERKLE, verity_range.start, buffer.as_mut())
317 .await?,
318 FxfsError::Inconsistent
319 );
320 let data = buffer.as_ptr_slice().subslice(0..expected_length);
321 FsverityStateInner::from_ptr_slice(data, self.block_size())?
322 }
323 };
324 ensure!(metadata.merkle_tree.len() % hasher.hash_size() == 0, FxfsError::Inconsistent);
326 let leaf_chunks = metadata.merkle_tree.chunks_exact(hasher.hash_size());
327
328 let root_hash = match &metadata.root_digest {
329 RootDigest::Sha256(root_hash) => root_hash.as_slice(),
330 RootDigest::Sha512(root_hash) => root_hash.as_slice(),
331 };
332
333 let tree = match hasher {
334 FsVerityHasher::Sha256(_) => {
335 let mut builder = MerkleTreeBuilder::<Sha256Hash>::new(hasher);
336 for leaf in leaf_chunks {
337 let hash = Sha256Hash::read_from_bytes(leaf).unwrap();
338 builder.push_data_hash(hash);
339 }
340 builder.finish()
341 }
342 FsVerityHasher::Sha512(_) => {
343 let mut builder = MerkleTreeBuilder::<Sha512Hash>::new(hasher);
344 for leaf in leaf_chunks {
345 let hash = Sha512Hash::read_from_bytes(leaf).unwrap();
346 builder.push_data_hash(hash);
347 }
348 builder.finish()
349 }
350 };
351
352 ensure!(root_hash == tree.root(), FxfsError::IntegrityError);
353
354 let mut state = self.state.lock();
355 assert!(matches!(*state, DataObjectState::Standard(_)));
356 *state = DataObjectState::Verity(metadata);
357
358 Ok(())
359 }
360
361 fn verify_data(&self, mut offset: usize, buffer: PtrByteSlice<'_>) -> Result<(), Error> {
369 let block_size = self.block_size();
370 assert!(block_size.is_aligned(offset as u64));
371 let state = self.state.lock();
372 match &*state {
373 DataObjectState::Standard(_) => {
374 Err(anyhow!("Tried to verify read on a non verity-enabled file"))
375 }
376 DataObjectState::VerityStarted | DataObjectState::VerityPending(_) => {
377 Err(anyhow!("Enable verity has not yet completed, state: {state:?}"))
378 }
379 DataObjectState::Verity(metadata) => {
380 let hasher = metadata.get_hasher_for_block_size(block_size);
381 let leaf_nodes: Vec<&[u8]> =
382 metadata.merkle_tree.chunks(hasher.hash_size()).collect();
383 fxfs_trace::duration!("fsverity-verify", "len" => buffer.len());
384 for chunk in buffer.chunks(block_size.get() as usize) {
386 let b = unsafe { &*chunk.as_raw_slice_ptr() };
390
391 ensure!(
392 hasher.hash_block(b) == leaf_nodes[((offset as u64) / block_size) as usize],
393 anyhow!(FxfsError::Inconsistent).context("Hash mismatch")
394 );
395 offset += block_size.get() as usize;
396 }
397 Ok(())
398 }
399 }
400 }
401
402 pub async fn extend<'a>(
405 &'a self,
406 transaction: &mut Transaction<'a>,
407 device_range: Range<u64>,
408 ) -> Result<(), Error> {
409 let old_end =
410 self.block_size().align_up(self.txn_get_size(transaction)).ok_or(FxfsError::TooBig)?;
411 let new_size = old_end + device_range.end - device_range.start;
412 self.store().allocator().mark_allocated(
413 transaction,
414 self.store().store_object_id(),
415 device_range.clone(),
416 )?;
417 self.txn_update_size(transaction, new_size, None).await?;
418 let key_id = self.get_key(None).await?.0;
419 transaction.add(
420 self.store().store_object_id,
421 Mutation::merge_object(
422 ObjectKey::extent(self.object_id(), self.attribute_id(), old_end..new_size),
423 ObjectValue::Extent(ExtentValue::new_raw(device_range.start, key_id)),
424 ),
425 );
426 self.update_allocated_size(transaction, device_range.end - device_range.start, 0).await
427 }
428
429 async fn align_buffer(
432 &self,
433 offset: u64,
434 buf: BufferRef<'_>,
435 ) -> Result<(std::ops::Range<u64>, Buffer<'_>), Error> {
436 self.handle.align_buffer(self.attribute_id(), offset, buf).await
437 }
438
439 async fn write_at(
445 &self,
446 offset: u64,
447 buf: MutableBufferRef<'_>,
448 device_offset: u64,
449 flags: WriteFlags,
450 ) -> Result<MaybeChecksums, Error> {
451 self.handle
452 .write_at_with_flags(self.attribute_id(), offset, buf, None, device_offset, flags)
453 .await
454 }
455
456 pub async fn check_unwritten_zero(&self, range: Range<u64>) -> Result<bool, Error> {
460 let tree = &self.store().tree();
461 let layer_set = tree.layer_set();
462 let key = Extent(range);
463 let lower_bound = ObjectKey::attribute(
464 self.object_id(),
465 self.attribute_id,
466 AttributeKey::Extent(key.search_key()),
467 );
468 let mut merger = layer_set.merger();
469 let mut iter = merger.query(Query::FullRange(&lower_bound)).await?;
470 while let Some(ItemRef {
471 key:
472 ObjectKey {
473 object_id,
474 data: ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent_key)),
475 },
476 value: ObjectValue::Extent(value),
477 ..
478 }) = iter.get()
479 && *object_id == self.object_id()
480 && *attr_id == self.attribute_id
481 {
482 if let ExtentValue::Some { mode, .. } = value {
483 if let Some(overlap) = key.overlap(extent_key) {
484 if let ExtentMode::OverwritePartial(bits) = mode {
485 let starting_index = (overlap.start - extent_key.start) / self.block_size();
486 for initialized in bits
487 .iter()
488 .skip(starting_index as usize)
489 .take((overlap.length().unwrap() / self.block_size()) as usize)
490 {
491 if initialized {
492 return Ok(false);
493 }
494 }
495 } else {
496 return Ok(false);
497 }
498 } else {
499 break;
500 }
501 }
502 iter.advance().await?;
503 }
504 Ok(true)
505 }
506
507 pub async fn zero(
509 &self,
510 transaction: &mut Transaction<'_>,
511 range: Range<u64>,
512 ) -> Result<(), Error> {
513 self.handle.zero(transaction, self.attribute_id(), range).await
514 }
515
516 pub fn get_descriptor(&self) -> Option<(fio::VerificationOptions, Vec<u8>)> {
520 let state = self.state.lock();
521 match &*state {
522 DataObjectState::Verity(metadata) => {
523 let (options, root_hash) = match &metadata.root_digest {
524 RootDigest::Sha256(root_hash) => (
525 fio::VerificationOptions {
526 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
527 salt: Some(metadata.salt.clone()),
528 ..Default::default()
529 },
530 root_hash.to_vec(),
531 ),
532 RootDigest::Sha512(root_hash) => (
533 fio::VerificationOptions {
534 hash_algorithm: Some(fio::HashAlgorithm::Sha512),
535 salt: Some(metadata.salt.clone()),
536 ..Default::default()
537 },
538 root_hash.clone(),
539 ),
540 };
541 Some((options, root_hash))
542 }
543 _ => None,
544 }
545 }
546
547 async fn build_verity_tree(
548 &self,
549 hasher: FsVerityHasher,
550 hash_alg: fio::HashAlgorithm,
551 salt: &[u8],
552 ) -> Result<(MerkleTree, Vec<u8>), Error> {
553 match hasher {
554 FsVerityHasher::Sha256(_) => {
555 self.build_verity_tree_impl::<Sha256Hash>(hasher, hash_alg, salt).await
556 }
557 FsVerityHasher::Sha512(_) => {
558 self.build_verity_tree_impl::<Sha512Hash>(hasher, hash_alg, salt).await
559 }
560 }
561 }
562
563 async fn build_verity_tree_impl<D: FsVerityHash>(
564 &self,
565 hasher: FsVerityHasher,
566 hash_alg: fio::HashAlgorithm,
567 salt: &[u8],
568 ) -> Result<(MerkleTree, Vec<u8>), Error> {
569 let hash_len = hasher.hash_size();
570 let mut builder = MerkleTreeBuilder::<D>::new(hasher);
571 let mut offset = 0;
572 let size = self.get_size();
573 let mut buf = self.allocate_buffer(64 * self.block_size().get() as usize).await;
576 while offset < size {
577 let read = self.read(offset, buf.as_mut()).await? as u64;
579 assert!(offset + read <= size);
580 let slice = buf.as_ptr_slice().subslice(0..read as usize);
581
582 let chunk = unsafe { &*slice.as_raw_slice_ptr() };
586
587 builder.write(chunk);
588 offset += read;
589 }
590 let tree = builder.finish();
591 let tree_data_len = tree
593 .levels()
594 .iter()
595 .map(|layer| self.block_size().align_up(layer.len() as u64).unwrap() as usize)
596 .sum();
597 let mut merkle_tree_data = Vec::<u8>::with_capacity(tree_data_len);
598 for layer in tree.levels().iter().rev() {
600 if layer.len() <= hash_len {
602 continue;
603 }
604 merkle_tree_data.extend_from_slice(layer);
605 let padded_size =
607 self.block_size().align_up(merkle_tree_data.len() as u64).unwrap() as usize;
608 merkle_tree_data.resize(padded_size, 0);
609 }
610
611 let descriptor_offset = merkle_tree_data.len();
613 merkle_tree_data.resize(descriptor_offset + self.block_size().get() as usize, 0);
614 let descriptor = FsVerityDescriptorRaw::new(
615 hash_alg,
616 self.block_size().get(),
617 self.get_size(),
618 tree.root(),
619 salt,
620 )?;
621 descriptor.write_to_slice(&mut merkle_tree_data[descriptor_offset..])?;
622
623 Ok((tree, merkle_tree_data))
624 }
625
626 #[trace]
633 pub async fn enable_verity(&self, options: fio::VerificationOptions) -> Result<(), Error> {
634 self.set_fsverity_state_started()?;
635 if self
638 .store()
639 .tree()
640 .exists(&ObjectKey::graveyard_attribute_entry(
641 self.store().graveyard_directory_object_id(),
642 self.object_id(),
643 AttributeId::FSVERITY_MERKLE,
644 ))
645 .await?
646 {
647 self.store().filesystem().graveyard().flush().await;
648 }
649 let mut transaction = self.new_transaction().await?;
650 let hash_alg =
651 options.hash_algorithm.ok_or_else(|| anyhow!("No hash algorithm provided"))?;
652 let salt = options.salt.ok_or_else(|| anyhow!("No salt provided"))?;
653 let (root_digest, merkle_tree) = match hash_alg {
654 fio::HashAlgorithm::Sha256 => {
655 let hasher = FsVerityHasher::Sha256(FsVerityHasherOptions::new(
656 salt.clone(),
657 self.block_size().get() as usize,
658 ));
659 let (tree, merkle_tree_data) =
660 self.build_verity_tree(hasher, hash_alg, &salt).await?;
661 let root: [u8; 32] = tree.root().try_into().unwrap();
662 (RootDigest::Sha256(root), merkle_tree_data)
663 }
664 fio::HashAlgorithm::Sha512 => {
665 let hasher = FsVerityHasher::Sha512(FsVerityHasherOptions::new(
666 salt.clone(),
667 self.block_size().get() as usize,
668 ));
669 let (tree, merkle_tree_data) =
670 self.build_verity_tree(hasher, hash_alg, &salt).await?;
671 (RootDigest::Sha512(tree.root().to_vec()), merkle_tree_data)
672 }
673 _ => {
674 bail!(
675 anyhow!(FxfsError::NotSupported)
676 .context(format!("hash algorithm not supported"))
677 );
678 }
679 };
680 self.handle
684 .write_new_attr_in_batches(
685 &mut transaction,
686 AttributeId::FSVERITY_MERKLE,
687 &merkle_tree,
688 WRITE_ATTR_BATCH_SIZE,
689 )
690 .await?;
691 if merkle_tree.len() > WRITE_ATTR_BATCH_SIZE {
692 self.store().remove_attribute_from_graveyard(
693 &mut transaction,
694 self.object_id(),
695 AttributeId::FSVERITY_MERKLE,
696 );
697 };
698 let descriptor_decoded =
699 FsVerityDescriptor::new(&merkle_tree[..], self.block_size().get() as usize)?;
700 let descriptor = FsverityStateInner {
701 root_digest,
702 salt,
703 merkle_tree: descriptor_decoded.leaf_digests()?.into(),
704 };
705 self.set_fsverity_state_pending(descriptor);
706 transaction.add_with_object(
707 self.store().store_object_id(),
708 Mutation::replace_or_insert_object(
709 ObjectKey::attribute(self.object_id(), AttributeId::DATA, AttributeKey::Attribute),
710 ObjectValue::verified_attribute(
711 self.get_size(),
712 FsverityMetadata::F2fs(0..merkle_tree.len() as u64),
713 ),
714 ),
715 AssocObj::Borrowed(self),
716 );
717 transaction.commit().await?;
718 Ok(())
719 }
720
721 pub async fn allocate(&self, range: Range<u64>) -> Result<(), Error> {
724 debug_assert!(range.start < range.end);
725
726 let mut new_range =
732 self.block_size().align_range_outwards(&range).ok_or(FxfsError::TooBig)?;
733
734 let mut transaction = self.new_transaction().await?;
735 {
742 let state = self.state.lock();
743 match &*state {
744 DataObjectState::Standard(_) => {}
745 _ => bail!(
746 anyhow!(FxfsError::AccessDenied).context("Cannot allocate on verity file")
747 ),
748 }
749 }
750 let mut to_allocate = Vec::new();
751 let mut to_switch = Vec::new();
752 let key_id = self.get_key(None).await?.0;
753
754 {
755 let tree = &self.store().tree;
756 let layer_set = tree.layer_set();
757 let offset_key = ObjectKey::attribute(
758 self.object_id(),
759 self.attribute_id(),
760 AttributeKey::Extent(Extent::search_key_from_offset(new_range.start)),
761 );
762 let mut merger = layer_set.merger();
763 let mut iter = merger.query(Query::FullRange(&offset_key)).await?;
764
765 loop {
766 match iter.get() {
767 Some(ItemRef {
768 key:
769 ObjectKey {
770 object_id,
771 data:
772 ObjectKeyData::Attribute(
773 attribute_id,
774 AttributeKey::Extent(extent_key),
775 ),
776 },
777 value: ObjectValue::Extent(extent_value),
778 ..
779 }) if *object_id == self.object_id()
780 && *attribute_id == self.attribute_id() =>
781 {
782 if new_range.end <= extent_key.start {
785 break;
786 }
787 if new_range.start < extent_key.start {
789 to_allocate.push(new_range.start..extent_key.start);
790 new_range.start = extent_key.start;
791 }
792 let device_offset = match extent_value {
793 ExtentValue::None => {
794 iter.advance().await?;
799 continue;
800 }
801 ExtentValue::Some { mode: ExtentMode::OverwritePartial(_), .. }
802 | ExtentValue::Some { mode: ExtentMode::Overwrite, .. } => {
803 if extent_key.end < new_range.end {
805 new_range.start = extent_key.end;
806 iter.advance().await?;
807 continue;
808 } else {
809 new_range.start = new_range.end;
810 break;
811 }
812 }
813 ExtentValue::Some { device_offset, .. } => *device_offset,
814 };
815
816 let device_offset = device_offset + (new_range.start - extent_key.start);
818 if extent_key.end < new_range.end {
819 to_switch.push((new_range.start..extent_key.end, device_offset));
820 new_range.start = extent_key.end;
821 } else {
822 to_switch.push((new_range.start..new_range.end, device_offset));
823 new_range.start = new_range.end;
824 break;
825 }
826 }
827 _ => break,
831 }
832 iter.advance().await?;
833 }
834 }
835
836 if new_range.start < new_range.end {
837 to_allocate.push(new_range.clone());
838 }
839
840 let new_size = std::cmp::max(range.end, self.get_size());
849 transaction.add_with_object(
854 self.store().store_object_id(),
855 Mutation::replace_or_insert_object(
856 ObjectKey::attribute(
857 self.object_id(),
858 self.attribute_id(),
859 AttributeKey::Attribute,
860 ),
861 ObjectValue::Attribute { size: new_size, has_overwrite_extents: true },
862 ),
863 AssocObj::Borrowed(self),
864 );
865
866 const MAX_TRANSACTION_SIZE: usize = 256;
870 for (switch_range, device_offset) in to_switch {
871 transaction.add_with_object(
872 self.store().store_object_id(),
873 Mutation::merge_object(
874 ObjectKey::extent(self.object_id(), self.attribute_id(), switch_range),
875 ObjectValue::Extent(ExtentValue::initialized_overwrite_extent(
876 device_offset,
877 key_id,
878 )),
879 ),
880 AssocObj::Borrowed(self),
881 );
882 if transaction.mutations().len() >= MAX_TRANSACTION_SIZE {
883 transaction.commit_and_continue().await?;
884 }
885 }
886
887 let mut allocated = 0;
888 let allocator = self.store().allocator();
889 for mut allocate_range in to_allocate {
890 while allocate_range.start < allocate_range.end {
891 let device_range = allocator
892 .allocate(
893 &mut transaction,
894 self.store().store_object_id(),
895 allocate_range.end - allocate_range.start,
896 )
897 .await
898 .context("allocation failed")?;
899 let device_range_len = device_range.end - device_range.start;
900
901 transaction.add_with_object(
902 self.store().store_object_id(),
903 Mutation::merge_object(
904 ObjectKey::extent(
905 self.object_id(),
906 self.attribute_id(),
907 allocate_range.start..allocate_range.start + device_range_len,
908 ),
909 ObjectValue::Extent(ExtentValue::blank_overwrite_extent(
910 device_range.start,
911 (device_range_len / self.block_size()) as usize,
912 key_id,
913 )),
914 ),
915 AssocObj::Borrowed(self),
916 );
917
918 allocate_range.start += device_range_len;
919 allocated += device_range_len;
920
921 if transaction.mutations().len() >= MAX_TRANSACTION_SIZE {
922 self.update_allocated_size(&mut transaction, allocated, 0).await?;
923 transaction.commit_and_continue().await?;
924 allocated = 0;
925 }
926 }
927 }
928
929 self.update_allocated_size(&mut transaction, allocated, 0).await?;
930 transaction.commit().await?;
931
932 Ok(())
933 }
934
935 pub async fn is_allocated(&self, start_offset: u64) -> Result<(bool, u64), Error> {
941 let block_size = self.block_size();
942 assert_eq!(start_offset % block_size, 0);
943
944 if start_offset > self.get_size() {
945 bail!(FxfsError::OutOfRange)
946 }
947
948 if start_offset == self.get_size() {
949 return Ok((false, 0));
950 }
951
952 let tree = &self.store().tree;
953 let layer_set = tree.layer_set();
954 let offset_key = ObjectKey::attribute(
955 self.object_id(),
956 self.attribute_id(),
957 AttributeKey::Extent(Extent::search_key_from_offset(start_offset)),
958 );
959 let mut merger = layer_set.merger();
960 let mut iter = merger.query(Query::FullRange(&offset_key)).await?;
961
962 let mut allocated = None;
963 let mut end = start_offset;
964
965 loop {
966 match iter.get() {
969 Some(ItemRef {
970 key:
971 ObjectKey {
972 object_id,
973 data:
974 ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent_key)),
975 },
976 value: ObjectValue::Extent(extent_value),
977 ..
978 }) => {
979 if *object_id != self.object_id() || *attribute_id != self.attribute_id() {
981 if allocated == Some(false) || allocated.is_none() {
982 end = self.get_size();
983 allocated = Some(false);
984 }
985 break;
986 }
987 ensure!(block_size.is_aligned(extent_key), FxfsError::Inconsistent);
988 if extent_key.start > end {
989 if allocated == Some(true) {
993 break;
994 } else {
995 end = extent_key.start;
997 allocated = Some(false);
998 }
1002 }
1003
1004 match extent_value {
1007 ExtentValue::Some { .. } => {
1009 if allocated == Some(false) {
1011 break;
1012 }
1013 allocated = Some(true);
1014 }
1015 ExtentValue::None => {
1017 if allocated == Some(true) {
1019 break;
1020 }
1021 allocated = Some(false);
1022 }
1023 }
1024 end = extent_key.end;
1025 }
1026 None => {
1028 if allocated == Some(false) || allocated.is_none() {
1029 end = self.get_size();
1030 allocated = Some(false);
1031 }
1032 break;
1034 }
1035 Some(_) => {}
1037 }
1038 iter.advance().await?;
1039 }
1040
1041 Ok((allocated.unwrap(), end - start_offset))
1042 }
1043
1044 pub async fn txn_write<'a>(
1045 &'a self,
1046 transaction: &mut Transaction<'a>,
1047 offset: u64,
1048 buf: BufferRef<'_>,
1049 ) -> Result<(), Error> {
1050 if buf.is_empty() {
1051 return Ok(());
1052 }
1053 let (aligned, mut transfer_buf) = self.align_buffer(offset, buf).await?;
1054 self.multi_write(
1055 transaction,
1056 self.attribute_id(),
1057 std::slice::from_ref(&aligned),
1058 transfer_buf.as_mut(),
1059 )
1060 .await?;
1061 if offset + buf.len() as u64 > self.txn_get_size(transaction) {
1062 self.txn_update_size(transaction, offset + buf.len() as u64, None).await?;
1063 }
1064 Ok(())
1065 }
1066
1067 pub async fn multi_write<'a>(
1071 &'a self,
1072 transaction: &mut Transaction<'a>,
1073 attribute_id: AttributeId,
1074 ranges: &[Range<u64>],
1075 buf: MutableBufferRef<'_>,
1076 ) -> Result<(), Error> {
1077 self.handle.multi_write(transaction, attribute_id, None, ranges, buf).await
1078 }
1079
1080 pub async fn overwrite(
1088 &self,
1089 mut offset: u64,
1090 mut buf: MutableBufferRef<'_>,
1091 options: OverwriteOptions,
1092 ) -> Result<(), Error> {
1093 ensure!((buf.len() as u32) % self.store().device.block_size() == 0, FxfsError::InvalidArgs);
1094 let end = offset + buf.len() as u64;
1095
1096 let key_id = self.get_key(None).await?.0;
1097
1098 let mut transaction =
1100 if options.allow_allocations { Some(self.new_transaction().await?) } else { None };
1101
1102 let mut writes = FuturesOrdered::new();
1104 let mut first_write = options.barrier_on_first_write;
1105
1106 {
1109 let store = self.store();
1110 let store_object_id = store.store_object_id;
1111 let allocator = store.allocator();
1112 let tree = &store.tree;
1113 let layer_set = tree.layer_set();
1114 let mut merger = layer_set.merger();
1115 let mut iter = merger
1116 .query(Query::FullRange(&ObjectKey::attribute(
1117 self.object_id(),
1118 self.attribute_id(),
1119 AttributeKey::Extent(Extent::search_key_from_offset(offset)),
1120 )))
1121 .await?;
1122 let block_size = self.block_size();
1123
1124 loop {
1125 let (device_offset, bytes_to_write, should_advance) = match iter.get() {
1126 Some(ItemRef {
1127 key:
1128 ObjectKey {
1129 object_id,
1130 data:
1131 ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
1132 },
1133 value: ObjectValue::Extent(ExtentValue::Some { .. }),
1134 ..
1135 }) if *object_id == self.object_id()
1136 && *attribute_id == self.attribute_id()
1137 && extent.end == offset =>
1138 {
1139 iter.advance().await?;
1140 continue;
1141 }
1142 Some(ItemRef {
1143 key:
1144 ObjectKey {
1145 object_id,
1146 data:
1147 ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
1148 },
1149 value,
1150 ..
1151 }) if *object_id == self.object_id()
1152 && *attribute_id == self.attribute_id()
1153 && extent.start <= offset =>
1154 {
1155 match value {
1156 ObjectValue::Extent(ExtentValue::Some {
1157 device_offset,
1158 mode: ExtentMode::Raw,
1159 ..
1160 }) => {
1161 ensure!(
1162 block_size.is_aligned(extent)
1163 && block_size.is_aligned(device_offset),
1164 FxfsError::Inconsistent
1165 );
1166 let offset_within_extent = offset - extent.start;
1167 let remaining_length_of_extent = (extent
1168 .end
1169 .checked_sub(offset)
1170 .ok_or(FxfsError::Inconsistent)?)
1171 as usize;
1172 (
1174 device_offset + offset_within_extent,
1175 min(buf.len(), remaining_length_of_extent),
1176 true,
1177 )
1178 }
1179 ObjectValue::Extent(ExtentValue::Some { .. }) => {
1180 bail!(
1183 "extent from ({},{}) which overlaps offset \
1184 {} has the wrong extent mode",
1185 extent.start,
1186 extent.end,
1187 offset
1188 )
1189 }
1190 _ => {
1191 bail!(
1192 "overwrite failed: extent overlapping offset {} has \
1193 unexpected ObjectValue",
1194 offset
1195 )
1196 }
1197 }
1198 }
1199 maybe_item_ref => {
1200 if let Some(transaction) = transaction.as_mut() {
1201 assert_eq!(options.allow_allocations, true);
1202 assert_eq!(offset % self.block_size(), 0);
1203
1204 let mut bytes_to_allocate = self
1208 .block_size()
1209 .align_up(buf.len() as u64)
1210 .ok_or(FxfsError::TooBig)?;
1211 if let Some(ItemRef {
1212 key:
1213 ObjectKey {
1214 object_id,
1215 data:
1216 ObjectKeyData::Attribute(
1217 attribute_id,
1218 AttributeKey::Extent(extent),
1219 ),
1220 },
1221 ..
1222 }) = maybe_item_ref
1223 {
1224 if *object_id == self.object_id()
1225 && *attribute_id == self.attribute_id()
1226 && offset < extent.start
1227 {
1228 let bytes_until_next_extent = extent.start - offset;
1229 bytes_to_allocate =
1230 min(bytes_to_allocate, bytes_until_next_extent);
1231 }
1232 }
1233
1234 let device_range = allocator
1235 .allocate(transaction, store_object_id, bytes_to_allocate)
1236 .await?;
1237 let device_range_len = device_range.end - device_range.start;
1238 transaction.add(
1239 store_object_id,
1240 Mutation::insert_object(
1241 ObjectKey::extent(
1242 self.object_id(),
1243 self.attribute_id(),
1244 offset..offset + device_range_len,
1245 ),
1246 ObjectValue::Extent(ExtentValue::new_raw(
1247 device_range.start,
1248 key_id,
1249 )),
1250 ),
1251 );
1252
1253 self.update_allocated_size(transaction, device_range_len, 0).await?;
1254
1255 (device_range.start, min(buf.len(), device_range_len as usize), false)
1257 } else {
1258 bail!(
1259 "no extent overlapping offset {}, \
1260 and new allocations are not allowed",
1261 offset
1262 )
1263 }
1264 }
1265 };
1266 let (current_buf, remaining_buf) = buf.split_at_mut(bytes_to_write);
1267 let flags = if first_write {
1268 first_write = false;
1269 WriteFlags::PRE_BARRIER
1270 } else {
1271 WriteFlags::empty()
1272 };
1273 writes.push_back(self.write_at(offset, current_buf, device_offset, flags));
1274 if remaining_buf.len() == 0 {
1275 break;
1276 } else {
1277 buf = remaining_buf;
1278 offset += bytes_to_write as u64;
1279 if should_advance {
1280 iter.advance().await?;
1281 }
1282 }
1283 }
1284 }
1285
1286 self.store().logical_write_ops.fetch_add(1, Ordering::Relaxed);
1287 writes.try_collect::<Vec<MaybeChecksums>>().await?;
1289
1290 if let Some(mut transaction) = transaction {
1291 assert_eq!(options.allow_allocations, true);
1292 if !transaction.is_empty() {
1293 if end > self.get_size() {
1294 self.grow(&mut transaction, self.get_size(), end).await?;
1295 }
1296 transaction.commit().await?;
1297 }
1298 }
1299
1300 Ok(())
1301 }
1302
1303 fn txn_get_size(&self, transaction: &Transaction<'_>) -> u64 {
1306 transaction
1307 .get_object_mutation(
1308 self.store().store_object_id,
1309 ObjectKey::attribute(
1310 self.object_id(),
1311 self.attribute_id(),
1312 AttributeKey::Attribute,
1313 ),
1314 )
1315 .and_then(|m| {
1316 if let ObjectItem { value: ObjectValue::Attribute { size, .. }, .. } = m.item {
1317 Some(size)
1318 } else {
1319 None
1320 }
1321 })
1322 .unwrap_or_else(|| self.get_size())
1323 }
1324
1325 pub async fn txn_update_size<'a>(
1326 &'a self,
1327 transaction: &mut Transaction<'a>,
1328 new_size: u64,
1329 update_has_overwrite_extents: Option<bool>,
1332 ) -> Result<(), Error> {
1333 let key =
1334 ObjectKey::attribute(self.object_id(), self.attribute_id(), AttributeKey::Attribute);
1335 let mut mutation = if let Some(mutation) =
1336 transaction.get_object_mutation(self.store().store_object_id(), key.clone())
1337 {
1338 mutation.clone()
1339 } else {
1340 ObjectStoreMutation {
1341 item: self.store().tree().find(&key).await?.ok_or(FxfsError::NotFound)?,
1342 op: Operation::ReplaceOrInsert,
1343 }
1344 };
1345 if let ObjectValue::Attribute { size, has_overwrite_extents } = &mut mutation.item.value {
1346 *size = new_size;
1347 if let Some(update_has_overwrite_extents) = update_has_overwrite_extents {
1348 *has_overwrite_extents = update_has_overwrite_extents;
1349 }
1350 } else {
1351 bail!(anyhow!(FxfsError::Inconsistent).context("Unexpected object value"));
1352 }
1353 transaction.add_with_object(
1354 self.store().store_object_id(),
1355 Mutation::ObjectStore(mutation),
1356 AssocObj::Borrowed(self),
1357 );
1358 Ok(())
1359 }
1360
1361 async fn update_allocated_size(
1362 &self,
1363 transaction: &mut Transaction<'_>,
1364 allocated: u64,
1365 deallocated: u64,
1366 ) -> Result<(), Error> {
1367 self.handle.update_allocated_size(transaction, allocated, deallocated).await
1368 }
1369
1370 pub fn truncate_overwrite_ranges(&self, size: u64) -> Result<Option<bool>, Error> {
1371 let cutoff = self.block_size().align_up(size).ok_or(FxfsError::TooBig)?;
1372 if self.with_overwrite_ranges_mut(|ranges| ranges.map_or(false, |r| r.truncate(cutoff))) {
1373 Ok(Some(false))
1376 } else {
1377 Ok(None)
1378 }
1379 }
1380
1381 pub async fn shrink<'a>(
1382 &'a self,
1383 transaction: &mut Transaction<'a>,
1384 size: u64,
1385 update_has_overwrite_extents: Option<bool>,
1386 ) -> Result<NeedsTrim, Error> {
1387 let needs_trim = self.handle.shrink(transaction, self.attribute_id(), size).await?;
1388 self.txn_update_size(transaction, size, update_has_overwrite_extents).await?;
1389 Ok(needs_trim)
1390 }
1391
1392 pub async fn grow<'a>(
1393 &'a self,
1394 transaction: &mut Transaction<'a>,
1395 old_size: u64,
1396 size: u64,
1397 ) -> Result<(), Error> {
1398 let store = self.store();
1400 while matches!(
1401 store
1402 .trim_some(
1403 transaction,
1404 self.object_id(),
1405 self.attribute_id(),
1406 TrimMode::FromOffset(old_size)
1407 )
1408 .await?,
1409 TrimResult::Incomplete
1410 ) {
1411 transaction.commit_and_continue().await?;
1412 }
1413 let block_size = self.block_size();
1415 if !block_size.is_aligned(old_size) {
1416 let layer_set = store.tree.layer_set();
1417 let mut merger = layer_set.merger();
1418 let aligned_old_size = block_size.align_down(old_size);
1419 let iter = merger
1420 .query(Query::FullRange(&ObjectKey::attribute(
1421 self.object_id(),
1422 self.attribute_id(),
1423 AttributeKey::Extent(Extent::search_key_from_offset(aligned_old_size)),
1424 )))
1425 .await?;
1426 if let Some(ItemRef {
1427 key:
1428 ObjectKey {
1429 object_id,
1430 data:
1431 ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent_key)),
1432 },
1433 value: ObjectValue::Extent(ExtentValue::Some { device_offset, key_id, .. }),
1434 ..
1435 }) = iter.get()
1436 {
1437 if *object_id == self.object_id() && *attribute_id == self.attribute_id() {
1438 let device_offset = device_offset
1439 .checked_add(aligned_old_size - extent_key.start)
1440 .ok_or(FxfsError::Inconsistent)?;
1441 ensure!(block_size.is_aligned(device_offset), FxfsError::Inconsistent);
1442 let mut buf = self.allocate_buffer(block_size.get() as usize).await;
1443 self.read_and_decrypt(device_offset, aligned_old_size, buf.as_mut(), *key_id)
1449 .await?;
1450 buf.subslice_mut((old_size % block_size) as usize..buf.len()).fill(0);
1451 self.multi_write(
1452 transaction,
1453 *attribute_id,
1454 &[aligned_old_size..aligned_old_size + block_size],
1455 buf.as_mut(),
1456 )
1457 .await?;
1458 }
1459 }
1460 }
1461 self.txn_update_size(transaction, size, None).await?;
1462 Ok(())
1463 }
1464
1465 pub async fn preallocate_range<'a>(
1478 &'a self,
1479 transaction: &mut Transaction<'a>,
1480 file_range: &mut Range<u64>,
1481 ) -> Result<Vec<Range<u64>>, Error> {
1482 let block_size = self.block_size();
1483 ensure!(block_size.is_aligned(&*file_range), FxfsError::InvalidArgs);
1484 ensure!(!self.handle.is_encrypted(), FxfsError::NotSupported);
1485 let mut ranges = Vec::new();
1486 let tree = &self.store().tree;
1487 let layer_set = tree.layer_set();
1488 let mut merger = layer_set.merger();
1489 let mut iter = merger
1490 .query(Query::FullRange(&ObjectKey::attribute(
1491 self.object_id(),
1492 self.attribute_id(),
1493 AttributeKey::Extent(Extent::search_key_from_offset(file_range.start)),
1494 )))
1495 .await?;
1496 let mut allocated = 0;
1497 let key_id = self.get_key(None).await?.0;
1498 'outer: while file_range.start < file_range.end {
1499 let allocate_end = loop {
1500 match iter.get() {
1501 Some(ItemRef {
1503 key:
1504 ObjectKey {
1505 object_id,
1506 data:
1507 ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
1508 },
1509 value: ObjectValue::Extent(ExtentValue::Some { device_offset, .. }),
1510 ..
1511 }) if *object_id == self.object_id()
1512 && *attribute_id == self.attribute_id()
1513 && extent.start < file_range.end =>
1514 {
1515 ensure!(
1516 extent.is_valid()
1517 && block_size.is_aligned(extent)
1518 && block_size.is_aligned(device_offset),
1519 FxfsError::Inconsistent
1520 );
1521 if extent.start <= file_range.start {
1523 let device_range = device_offset
1525 .checked_add(file_range.start - extent.start)
1526 .ok_or(FxfsError::Inconsistent)?
1527 ..device_offset
1528 .checked_add(min(extent.end, file_range.end) - extent.start)
1529 .ok_or(FxfsError::Inconsistent)?;
1530 file_range.start += device_range.end - device_range.start;
1531 ranges.push(device_range);
1532 if file_range.start >= file_range.end {
1533 break 'outer;
1534 }
1535 iter.advance().await?;
1536 continue;
1537 } else {
1538 break extent.start;
1541 }
1542 }
1543 Some(ItemRef {
1545 key:
1546 ObjectKey {
1547 object_id,
1548 data:
1549 ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
1550 },
1551 value: ObjectValue::Extent(ExtentValue::None),
1552 ..
1553 }) if *object_id == self.object_id()
1554 && *attribute_id == self.attribute_id()
1555 && extent.end < file_range.end =>
1556 {
1557 iter.advance().await?;
1558 }
1559 _ => {
1560 break file_range.end;
1562 }
1563 }
1564 };
1565 let device_range = self
1566 .store()
1567 .allocator()
1568 .allocate(
1569 transaction,
1570 self.store().store_object_id(),
1571 allocate_end - file_range.start,
1572 )
1573 .await
1574 .context("Allocation failed")?;
1575 allocated += device_range.end - device_range.start;
1576 let this_file_range =
1577 file_range.start..file_range.start + device_range.end - device_range.start;
1578 file_range.start = this_file_range.end;
1579 transaction.add(
1580 self.store().store_object_id,
1581 Mutation::merge_object(
1582 ObjectKey::extent(self.object_id(), self.attribute_id(), this_file_range),
1583 ObjectValue::Extent(ExtentValue::new_raw(device_range.start, key_id)),
1584 ),
1585 );
1586 ranges.push(device_range);
1587 if transaction.mutations().len() > TRANSACTION_MUTATION_THRESHOLD {
1590 break;
1591 }
1592 }
1593 if file_range.start > block_size.align_up(self.txn_get_size(transaction)).unwrap() {
1595 self.txn_update_size(transaction, file_range.start, None).await?;
1596 }
1597 self.update_allocated_size(transaction, allocated, 0).await?;
1598 Ok(ranges)
1599 }
1600
1601 pub async fn update_attributes<'a>(
1602 &self,
1603 transaction: &mut Transaction<'a>,
1604 node_attributes: Option<&fio::MutableNodeAttributes>,
1605 change_time: Option<Timestamp>,
1606 ) -> Result<(), Error> {
1607 ensure!(
1610 !matches!(
1611 node_attributes,
1612 Some(fio::MutableNodeAttributes { wrapping_key_id: Some(_), .. })
1613 ),
1614 FxfsError::BadPath
1615 );
1616 self.handle.update_attributes(transaction, node_attributes, change_time).await
1617 }
1618
1619 pub fn default_transaction_options<'b>(&self) -> Options<'b> {
1622 self.handle.default_transaction_options()
1623 }
1624
1625 pub async fn new_transaction<'b>(&self) -> Result<Transaction<'b>, Error> {
1626 self.new_transaction_with_options(self.default_transaction_options()).await
1627 }
1628
1629 pub async fn new_transaction_with_options<'b>(
1630 &self,
1631 options: Options<'b>,
1632 ) -> Result<Transaction<'b>, Error> {
1633 self.handle.new_transaction_with_options(self.attribute_id(), options).await
1634 }
1635
1636 pub async fn flush_device(&self) -> Result<(), Error> {
1638 self.handle.flush_device().await
1639 }
1640
1641 pub async fn read_attr(&self, attribute_id: AttributeId) -> Result<Option<Box<[u8]>>, Error> {
1643 self.handle.read_attr(attribute_id).await
1644 }
1645
1646 pub async fn write_attr(&self, attribute_id: AttributeId, data: &[u8]) -> Result<(), Error> {
1648 assert_ne!(attribute_id, self.attribute_id());
1650 let store = self.store();
1651 let mut transaction = self.new_transaction().await?;
1652 if self.handle.write_attr(&mut transaction, attribute_id, data).await?.0 {
1653 transaction.commit_and_continue().await?;
1654 while matches!(
1655 store
1656 .trim_some(
1657 &mut transaction,
1658 self.object_id(),
1659 attribute_id,
1660 TrimMode::FromOffset(data.len() as u64),
1661 )
1662 .await?,
1663 TrimResult::Incomplete
1664 ) {
1665 transaction.commit_and_continue().await?;
1666 }
1667 }
1668 transaction.commit().await?;
1669 Ok(())
1670 }
1671
1672 async fn read_and_decrypt(
1673 &self,
1674 device_offset: u64,
1675 file_offset: u64,
1676 buffer: MutableBufferRef<'_>,
1677 key_id: u64,
1678 ) -> Result<(), Error> {
1679 self.handle
1680 .read_and_decrypt(self.attribute_id, device_offset, file_offset, buffer, key_id)
1681 .await
1682 }
1683
1684 pub async fn truncate_with_options(
1689 &self,
1690 options: Options<'_>,
1691 size: u64,
1692 ) -> Result<(), Error> {
1693 let mut transaction = self.new_transaction_with_options(options).await?;
1694 {
1695 let state = self.state.lock();
1696 match &*state {
1697 DataObjectState::Standard(_) => {}
1698 _ => bail!(anyhow!(FxfsError::AccessDenied).context("Cannot truncate verity file")),
1699 }
1700 }
1701 let old_size = self.get_size();
1702 if size == old_size {
1703 return Ok(());
1704 }
1705 if size < old_size {
1706 let update_has_overwrite_ranges = self.truncate_overwrite_ranges(size)?;
1707 if self.shrink(&mut transaction, size, update_has_overwrite_ranges).await?.0 {
1708 transaction.commit_and_continue().await?;
1710 let store = self.store();
1711 while matches!(
1712 store
1713 .trim_some(
1714 &mut transaction,
1715 self.object_id(),
1716 self.attribute_id(),
1717 TrimMode::FromOffset(size)
1718 )
1719 .await?,
1720 TrimResult::Incomplete
1721 ) {
1722 if let Err(error) = transaction.commit_and_continue().await {
1723 warn!(error:?; "Failed to trim after truncate");
1724 return Ok(());
1725 }
1726 }
1727 if let Err(error) = transaction.commit().await {
1728 warn!(error:?; "Failed to trim after truncate");
1729 }
1730 return Ok(());
1731 }
1732 } else {
1733 self.grow(&mut transaction, old_size, size).await?;
1734 }
1735 transaction.commit().await?;
1736 Ok(())
1737 }
1738
1739 pub async fn get_properties(&self) -> Result<ObjectProperties, Error> {
1740 let value = self
1744 .store()
1745 .tree
1746 .find_value(&ObjectKey::object(self.object_id()))
1747 .await?
1748 .expect("Unable to find object record");
1749 match value {
1750 ObjectValue::Object {
1751 kind: ObjectKind::File { refs, .. },
1752 attributes:
1753 ObjectAttributes {
1754 creation_time,
1755 modification_time,
1756 posix_attributes,
1757 allocated_size,
1758 access_time,
1759 change_time,
1760 ..
1761 },
1762 } => Ok(ObjectProperties {
1763 refs,
1764 allocated_size,
1765 data_attribute_size: self.get_size(),
1766 creation_time,
1767 modification_time,
1768 access_time,
1769 change_time,
1770 sub_dirs: 0,
1771 posix_attributes,
1772 dir_type: DirType::Normal,
1773 }),
1774 _ => bail!(FxfsError::NotFile),
1775 }
1776 }
1777
1778 pub async fn contents(&self, limit: usize) -> Result<Box<[u8]>, Error> {
1780 let size = self.get_size();
1781 if size > limit as u64 {
1782 bail!("Object too big ({} > {})", size, limit);
1783 }
1784 let mut buf = self.allocate_buffer(size as usize).await;
1785 self.read(0u64, buf.as_mut()).await?;
1786 Ok(buf.to_vec().into_boxed_slice())
1787 }
1788
1789 pub async fn device_extents(&self) -> Result<Vec<FileExtent>, Error> {
1794 let tree = &self.store().tree;
1795 let layer_set = tree.layer_set();
1796 let mut merger = layer_set.merger();
1797 let stream = self.handle.extent_stream(&mut merger, self.attribute_id()).await?;
1798 let extents: Vec<FileExtent> = stream.try_collect().await?;
1799 Ok(extents)
1800 }
1801
1802 pub async fn read(&self, offset: u64, mut buf: MutableBufferRef<'_>) -> Result<usize, Error> {
1808 let fs = self.store().filesystem();
1809 let guard = fs
1810 .lock_manager()
1811 .read_lock(lock_keys![LockKey::object_attribute(
1812 self.store().store_object_id,
1813 self.object_id(),
1814 self.attribute_id(),
1815 )])
1816 .await;
1817
1818 let size = self.get_size();
1819 if offset >= size {
1820 return Ok(0);
1821 }
1822 let length = min(buf.len() as u64, size - offset) as usize;
1823 buf = buf.subslice_mut(0..length);
1824 self.handle.read_unchecked(self.attribute_id(), offset, buf.reborrow(), &guard).await?;
1825 if self.is_verified_file() {
1826 self.verify_data(offset as usize, buf.as_ptr_slice())?;
1827 }
1828 Ok(length)
1829 }
1830}
1831
1832impl<S: HandleOwner> AssociatedObject for DataObjectHandle<S> {
1833 fn will_apply_mutation(&self, mutation: &Mutation, _object_id: u64, _manager: &ObjectManager) {
1834 match mutation {
1835 Mutation::ObjectStore(ObjectStoreMutation {
1836 item: ObjectItem { value: ObjectValue::Attribute { size, .. }, .. },
1837 ..
1838 }) => self.content_size.store(*size, atomic::Ordering::Relaxed),
1839 Mutation::ObjectStore(ObjectStoreMutation {
1840 item: ObjectItem { value: ObjectValue::VerifiedAttribute { size, .. }, .. },
1841 ..
1842 }) => {
1843 debug_assert_eq!(
1844 self.get_size(),
1845 *size,
1846 "size should be set when verity is enabled and must not change"
1847 );
1848 self.finalize_fsverity_state()
1849 }
1850 Mutation::ObjectStore(ObjectStoreMutation {
1851 item:
1852 ObjectItem {
1853 key:
1854 ObjectKey {
1855 object_id,
1856 data:
1857 ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent)),
1858 },
1859 value: ObjectValue::Extent(ExtentValue::Some { mode, .. }),
1860 ..
1861 },
1862 ..
1863 }) if self.object_id() == *object_id && self.attribute_id() == *attr_id => match mode {
1864 ExtentMode::Overwrite | ExtentMode::OverwritePartial(_) => {
1865 self.with_overwrite_ranges_mut(|ranges| {
1870 if let Some(ranges) = ranges {
1871 ranges.apply_range(extent.clone().into());
1872 }
1873 });
1874 }
1875 ExtentMode::Raw | ExtentMode::Cow(_) => (),
1876 },
1877 _ => {}
1878 }
1879 }
1880}
1881
1882impl<S: HandleOwner> ObjectHandle for DataObjectHandle<S> {
1883 fn set_trace(&self, v: bool) {
1884 self.handle.set_trace(v)
1885 }
1886
1887 fn object_id(&self) -> u64 {
1888 self.handle.object_id()
1889 }
1890
1891 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
1892 self.handle.allocate_buffer(size)
1893 }
1894
1895 fn block_size(&self) -> BlockSize {
1896 self.handle.block_size()
1897 }
1898}
1899
1900impl<S: HandleOwner> ReadObjectHandle for DataObjectHandle<S> {
1901 fn read<'a, 'b, 'c>(
1902 &'a self,
1903 offset: u64,
1904 buf: MutableBufferRef<'b>,
1905 ) -> Pin<Box<dyn Future<Output = Result<usize, Error>> + Send + 'c>>
1906 where
1907 'a: 'c,
1908 'b: 'c,
1909 Self: 'c,
1910 {
1911 Box::pin(DataObjectHandle::read(self, offset, buf))
1912 }
1913
1914 fn get_size(&self) -> u64 {
1915 self.content_size.load(atomic::Ordering::Relaxed)
1916 }
1917}
1918
1919impl<S: HandleOwner> LayerObject for DataObjectHandle<S> {}
1920
1921impl<S: HandleOwner> WriteObjectHandle for DataObjectHandle<S> {
1922 async fn write_or_append(&self, offset: Option<u64>, buf: BufferRef<'_>) -> Result<u64, Error> {
1923 let offset = offset.unwrap_or_else(|| self.get_size());
1924 let mut transaction = self.new_transaction().await?;
1925 self.txn_write(&mut transaction, offset, buf).await?;
1926 let new_size = self.txn_get_size(&transaction);
1927 transaction.commit().await?;
1928 Ok(new_size)
1929 }
1930
1931 async fn truncate(&self, size: u64) -> Result<(), Error> {
1932 self.truncate_with_options(self.default_transaction_options(), size).await
1933 }
1934
1935 async fn flush(&self) -> Result<(), Error> {
1936 Ok(())
1937 }
1938}
1939
1940pub struct DirectWriter<'a, S: HandleOwner> {
1943 handle: &'a DataObjectHandle<S>,
1944 options: transaction::Options<'a>,
1945 buffer: Buffer<'a>,
1946 offset: u64,
1947 buf_offset: usize,
1948}
1949
1950const BUFFER_SIZE: usize = 1_048_576;
1951
1952impl<S: HandleOwner> Drop for DirectWriter<'_, S> {
1953 fn drop(&mut self) {
1954 if self.buf_offset != 0 {
1955 warn!("DirectWriter: dropping data, did you forget to call complete?");
1956 }
1957 }
1958}
1959
1960impl<'a, S: HandleOwner> DirectWriter<'a, S> {
1961 pub async fn new(
1962 handle: &'a DataObjectHandle<S>,
1963 options: transaction::Options<'a>,
1964 ) -> DirectWriter<'a, S> {
1965 Self {
1966 handle,
1967 options,
1968 buffer: handle.allocate_buffer(BUFFER_SIZE).await,
1969 offset: 0,
1970 buf_offset: 0,
1971 }
1972 }
1973
1974 async fn flush(&mut self) -> Result<(), Error> {
1975 let mut transaction = self.handle.new_transaction_with_options(self.options).await?;
1976 self.handle
1977 .txn_write(&mut transaction, self.offset, self.buffer.subslice(0..self.buf_offset))
1978 .await?;
1979 transaction.commit().await?;
1980 self.offset += self.buf_offset as u64;
1981 self.buf_offset = 0;
1982 Ok(())
1983 }
1984}
1985
1986impl<'a, S: HandleOwner> WriteBytes for DirectWriter<'a, S> {
1987 fn block_size(&self) -> BlockSize {
1988 self.handle.block_size()
1989 }
1990
1991 async fn write_bytes(&mut self, mut buf: &[u8]) -> Result<(), Error> {
1992 while buf.len() > 0 {
1993 let to_do = std::cmp::min(buf.len(), BUFFER_SIZE - self.buf_offset);
1994 self.buffer
1995 .subslice_mut(self.buf_offset..self.buf_offset + to_do)
1996 .copy_from_slice(&buf[..to_do]);
1997 self.buf_offset += to_do;
1998 if self.buf_offset == BUFFER_SIZE {
1999 self.flush().await?;
2000 }
2001 buf = &buf[to_do..];
2002 }
2003 Ok(())
2004 }
2005
2006 async fn complete(mut self) -> Result<u64, Error> {
2007 self.flush().await?;
2008 Ok(self.offset + self.buf_offset as u64)
2009 }
2010
2011 async fn skip(&mut self, amount: u64) -> Result<(), Error> {
2012 if (BUFFER_SIZE - self.buf_offset) as u64 > amount {
2013 self.buffer.subslice_mut(self.buf_offset..self.buf_offset + amount as usize).fill(0);
2014 self.buf_offset += amount as usize;
2015 } else {
2016 self.flush().await?;
2017 self.offset += amount;
2018 }
2019 Ok(())
2020 }
2021}
2022
2023#[cfg(test)]
2024mod tests {
2025 use crate::errors::FxfsError;
2026 use crate::filesystem::{FxFilesystem, FxFilesystemBuilder, OpenFxFilesystem, SyncOptions};
2027 use crate::fsck::{
2028 FsckOptions, fsck, fsck_volume, fsck_volume_with_options, fsck_with_options,
2029 };
2030 use crate::lsm_tree::Query;
2031 use crate::lsm_tree::types::{ItemRef, LayerIterator};
2032 use crate::object_handle::{
2033 ObjectHandle, ObjectProperties, ReadObjectHandle, WriteObjectHandle,
2034 };
2035 use crate::object_store::data_object_handle::{OverwriteOptions, WRITE_ATTR_BATCH_SIZE};
2036 use crate::object_store::directory::replace_child;
2037 use crate::object_store::object_record::{FsverityMetadata, ObjectKey, ObjectValue, Timestamp};
2038 use crate::object_store::transaction::{Mutation, Options, lock_keys};
2039 use crate::object_store::volume::root_volume;
2040 use crate::object_store::{
2041 AttributeId, AttributeKey, DataObjectHandle, DirType, Directory, Extent, ExtentMode,
2042 ExtentValue, HandleOptions, LockKey, NewChildStoreOptions, ObjectKeyData, ObjectStore,
2043 PosixAttributes, StoreOptions, TRANSACTION_MUTATION_THRESHOLD,
2044 };
2045 use crate::range::RangeExt;
2046 use crate::round::{round_down, round_up};
2047 use assert_matches::assert_matches;
2048 use bit_vec::BitVec;
2049 use fidl_fuchsia_io as fio;
2050 use fsverity_merkle::{FsVerityDescriptor, FsVerityDescriptorRaw};
2051 use fuchsia_async as fasync;
2052 use fuchsia_sync::Mutex;
2053 use futures::FutureExt;
2054 use futures::channel::oneshot::channel;
2055 use futures::stream::{FuturesUnordered, StreamExt};
2056 use fxfs_crypto::{Crypt, EncryptionKey, KeyPurpose};
2057 use fxfs_insecure_crypto::new_insecure_crypt;
2058 use std::ops::Range;
2059 use std::sync::Arc;
2060 use std::time::Duration;
2061 use storage_device::DeviceHolder;
2062 use storage_device::fake_device::FakeDevice;
2063
2064 const TEST_DEVICE_BLOCK_SIZE: u32 = 512;
2065
2066 const TEST_DATA_OFFSET: u64 = 5000;
2069 const TEST_DATA: &[u8] = b"hello";
2070 const TEST_OBJECT_SIZE: u64 = 5678;
2071 const TEST_OBJECT_ALLOCATED_SIZE: u64 = 4096;
2072 const TEST_OBJECT_NAME: &str = "foo";
2073
2074 async fn test_filesystem() -> OpenFxFilesystem {
2075 let device = DeviceHolder::new(FakeDevice::new(8192, TEST_DEVICE_BLOCK_SIZE));
2076 FxFilesystem::new_empty(device).await.expect("new_empty failed")
2077 }
2078
2079 async fn create_object_with_key(
2080 fs: Arc<FxFilesystem>,
2081 crypt: Option<&dyn Crypt>,
2082 write_object_test_data: bool,
2083 ) -> DataObjectHandle<ObjectStore> {
2084 let store = fs.root_store();
2085 let object;
2086
2087 let mut transaction = fs
2088 .root_store()
2089 .new_transaction(
2090 lock_keys![LockKey::object(
2091 store.store_object_id(),
2092 store.root_directory_object_id()
2093 )],
2094 Options::default(),
2095 )
2096 .await
2097 .expect("new_transaction failed");
2098
2099 object = if let Some(crypt) = crypt {
2100 let object_id = store.get_next_object_id().await.unwrap();
2101 let (key, unwrapped_key) =
2102 crypt.create_key(object_id.get(), KeyPurpose::Data).await.unwrap();
2103 ObjectStore::create_object_with_key(
2104 &store,
2105 &mut transaction,
2106 object_id,
2107 HandleOptions::default(),
2108 EncryptionKey::Fxfs(key),
2109 unwrapped_key,
2110 )
2111 .await
2112 .expect("create_object failed")
2113 } else {
2114 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
2115 .await
2116 .expect("create_object failed")
2117 };
2118
2119 let root_directory =
2120 Directory::open(&store, store.root_directory_object_id()).await.expect("open failed");
2121 root_directory
2122 .add_child_file(&mut transaction, TEST_OBJECT_NAME, &object)
2123 .await
2124 .expect("add_child_file failed");
2125
2126 if write_object_test_data {
2127 let align = TEST_DATA_OFFSET as usize % TEST_DEVICE_BLOCK_SIZE as usize;
2128 let mut buf = object.allocate_buffer(align + TEST_DATA.len()).await;
2129 buf.subslice_mut(align..buf.len()).copy_from_slice(TEST_DATA);
2130 object
2131 .txn_write(&mut transaction, TEST_DATA_OFFSET, buf.subslice(align..buf.len()))
2132 .await
2133 .expect("write failed");
2134 }
2135 transaction.commit().await.expect("commit failed");
2136 object.truncate(TEST_OBJECT_SIZE).await.expect("truncate failed");
2137 object
2138 }
2139
2140 async fn test_filesystem_and_object_with_key(
2141 crypt: Option<&dyn Crypt>,
2142 write_object_test_data: bool,
2143 ) -> (OpenFxFilesystem, DataObjectHandle<ObjectStore>) {
2144 let fs = test_filesystem().await;
2145 let object = create_object_with_key(fs.clone(), crypt, write_object_test_data).await;
2146 (fs, object)
2147 }
2148
2149 async fn test_filesystem_and_object() -> (OpenFxFilesystem, DataObjectHandle<ObjectStore>) {
2150 test_filesystem_and_object_with_key(Some(&new_insecure_crypt()), true).await
2151 }
2152
2153 async fn test_filesystem_and_empty_object() -> (OpenFxFilesystem, DataObjectHandle<ObjectStore>)
2154 {
2155 test_filesystem_and_object_with_key(Some(&new_insecure_crypt()), false).await
2156 }
2157
2158 #[fuchsia::test]
2159 async fn test_zero_buf_len_read() {
2160 let (fs, object) = test_filesystem_and_object().await;
2161 let mut buf = object.allocate_buffer(0).await;
2162 assert_eq!(object.read(0u64, buf.as_mut()).await.expect("read failed"), 0);
2163 fs.close().await.expect("Close failed");
2164 }
2165
2166 #[fuchsia::test]
2167 async fn test_beyond_eof_read() {
2168 let (fs, object) = test_filesystem_and_object().await;
2169 let offset = TEST_OBJECT_SIZE as usize - 2;
2170 let align = (offset as u64 % fs.block_size()) as usize;
2171 let len: usize = 2;
2172 let mut buf = object.allocate_buffer(align + len + 1).await;
2173 buf.fill(123u8);
2174 assert_eq!(
2175 object.read((offset - align) as u64, buf.as_mut()).await.expect("read failed"),
2176 align + len
2177 );
2178 assert_eq!(&buf.as_ptr_slice().subslice(align..align + len).to_vec()[..], &vec![0u8; len]);
2179 assert_eq!(
2180 &buf.as_ptr_slice().subslice(align + len..buf.len()).to_vec()[..],
2181 &vec![123u8; buf.len() - align - len]
2182 );
2183 fs.close().await.expect("Close failed");
2184 }
2185
2186 #[fuchsia::test]
2187 async fn test_beyond_eof_read_from() {
2188 let (fs, object) = test_filesystem_and_object().await;
2189 let handle = &*object;
2190 let offset = TEST_OBJECT_SIZE as usize - 2;
2191 let align = (offset as u64 % fs.block_size()) as usize;
2192 let len: usize = 2;
2193 let mut buf = object.allocate_buffer(align + len + 1).await;
2194 buf.fill(123u8);
2195 assert_eq!(
2196 handle
2197 .read(AttributeId::DATA, (offset - align) as u64, buf.as_mut())
2198 .await
2199 .expect("read failed"),
2200 align + len
2201 );
2202 assert_eq!(&buf.as_ptr_slice().subslice(align..align + len).to_vec()[..], &vec![0u8; len]);
2203 assert_eq!(
2204 &buf.as_ptr_slice().subslice(align + len..buf.len()).to_vec()[..],
2205 &vec![123u8; buf.len() - align - len]
2206 );
2207 fs.close().await.expect("Close failed");
2208 }
2209
2210 #[fuchsia::test]
2211 async fn test_beyond_eof_read_unchecked() {
2212 let (fs, object) = test_filesystem_and_object().await;
2213 let offset = TEST_OBJECT_SIZE as usize - 2;
2214 let align = (offset as u64 % fs.block_size()) as usize;
2215 let len: usize = 2;
2216 let mut buf = object.allocate_buffer(align + len + 1).await;
2217 buf.fill(123u8);
2218 let guard = fs
2219 .lock_manager()
2220 .read_lock(lock_keys![LockKey::object_attribute(
2221 object.store().store_object_id,
2222 object.object_id(),
2223 AttributeId::DATA,
2224 )])
2225 .await;
2226 object
2227 .read_unchecked(AttributeId::DATA, (offset - align) as u64, buf.as_mut(), &guard)
2228 .await
2229 .expect("read failed");
2230 assert_eq!(
2231 &buf.as_ptr_slice().subslice(align..buf.len()).to_vec()[..],
2232 &vec![0u8; len + 1]
2233 );
2234 fs.close().await.expect("Close failed");
2235 }
2236
2237 #[fuchsia::test]
2238 async fn test_read_sparse() {
2239 let (fs, object) = test_filesystem_and_object().await;
2240 let len = TEST_OBJECT_SIZE as usize - 1;
2242 let mut buf = object.allocate_buffer(len).await;
2243 buf.fill(123u8);
2244 assert_eq!(object.read(0, buf.as_mut()).await.expect("read failed"), len);
2245 let mut expected = vec![0; len];
2246 let offset = TEST_DATA_OFFSET as usize;
2247 expected[offset..offset + TEST_DATA.len()].copy_from_slice(TEST_DATA);
2248 assert_eq!(&buf.as_ptr_slice().subslice(0..len).to_vec()[..], &expected[..]);
2249 fs.close().await.expect("Close failed");
2250 }
2251
2252 #[fuchsia::test]
2253 async fn test_read_after_writes_interspersed_with_flush() {
2254 let (fs, object) = test_filesystem_and_object().await;
2255
2256 object.owner().flush().await.expect("flush failed");
2257
2258 let mut buf = object.allocate_buffer(TEST_DATA.len()).await;
2260 buf.copy_from_slice(TEST_DATA);
2261 object.write_or_append(Some(0u64), buf.as_ref()).await.expect("write failed");
2262
2263 let len = TEST_OBJECT_SIZE as usize - 1;
2264 let mut buf = object.allocate_buffer(len).await;
2265 buf.fill(123u8);
2266 assert_eq!(object.read(0, buf.as_mut()).await.expect("read failed"), len);
2267
2268 let mut expected = vec![0u8; len];
2269 let offset = TEST_DATA_OFFSET as usize;
2270 expected[offset..offset + TEST_DATA.len()].copy_from_slice(TEST_DATA);
2271 expected[..TEST_DATA.len()].copy_from_slice(TEST_DATA);
2272 assert_eq!(&buf.to_vec(), &expected);
2273 fs.close().await.expect("Close failed");
2274 }
2275
2276 #[fuchsia::test]
2277 async fn test_read_after_truncate_and_extend() {
2278 let (fs, object) = test_filesystem_and_object().await;
2279
2280 let mut buf = object.allocate_buffer(TEST_DATA.len()).await;
2282 buf.copy_from_slice(TEST_DATA);
2283 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
2285 object.truncate(3).await.expect("truncate failed");
2287 let data = b"foo";
2288 let offset = 1500u64;
2289 let align = (offset % fs.block_size()) as usize;
2290 let mut buf = object.allocate_buffer(align + data.len()).await;
2291 buf.subslice_mut(align..buf.len()).copy_from_slice(data);
2292 object
2294 .write_or_append(Some(1500), buf.subslice(align..buf.len()))
2295 .await
2296 .expect("write failed");
2297
2298 const LEN1: usize = 1503;
2299 let mut buf = object.allocate_buffer(LEN1).await;
2300 buf.fill(123u8);
2301 assert_eq!(object.read(0, buf.as_mut()).await.expect("read failed"), LEN1);
2302 let mut expected = [0; LEN1];
2303 expected[..3].copy_from_slice(&TEST_DATA[..3]);
2304 expected[1500..].copy_from_slice(b"foo");
2305 assert_eq!(&buf.to_vec(), &expected);
2306
2307 const LEN2: usize = 601;
2309 let mut buf = object.allocate_buffer(LEN2).await;
2310 buf.fill(123u8);
2311 assert_eq!(object.read(0, buf.as_mut()).await.expect("read failed"), LEN2);
2312 assert_eq!(buf.to_vec(), &expected[..LEN2]);
2313 fs.close().await.expect("Close failed");
2314 }
2315
2316 #[fuchsia::test]
2317 async fn test_read_whole_blocks_with_multiple_objects() {
2318 let (fs, object) = test_filesystem_and_object().await;
2319 let block_size = object.block_size().get() as usize;
2320 let mut buffer = object.allocate_buffer(block_size).await;
2321 buffer.fill(0xaf);
2322 object.write_or_append(Some(0), buffer.as_ref()).await.expect("write failed");
2323
2324 let store = object.owner();
2325 let mut transaction = fs
2326 .root_store()
2327 .new_transaction(lock_keys![], Options::default())
2328 .await
2329 .expect("new_transaction failed");
2330 let object2 =
2331 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
2332 .await
2333 .expect("create_object failed");
2334 transaction.commit().await.expect("commit failed");
2335 let mut ef_buffer = object.allocate_buffer(block_size).await;
2336 ef_buffer.fill(0xef);
2337 object2.write_or_append(Some(0), ef_buffer.as_ref()).await.expect("write failed");
2338
2339 let mut buffer = object.allocate_buffer(block_size).await;
2340 buffer.fill(0xaf);
2341 object
2342 .write_or_append(Some(block_size as u64), buffer.as_ref())
2343 .await
2344 .expect("write failed");
2345 object.truncate(3 * block_size as u64).await.expect("truncate failed");
2346 object2
2347 .write_or_append(Some(block_size as u64), ef_buffer.as_ref())
2348 .await
2349 .expect("write failed");
2350
2351 let mut buffer = object.allocate_buffer(4 * block_size).await;
2352 buffer.fill(123);
2353 assert_eq!(object.read(0, buffer.as_mut()).await.expect("read failed"), 3 * block_size);
2354 assert_eq!(
2355 &buffer.as_ptr_slice().subslice(0..2 * block_size).to_vec()[..],
2356 &vec![0xaf; 2 * block_size]
2357 );
2358 assert_eq!(
2359 &buffer.as_ptr_slice().subslice(2 * block_size..3 * block_size).to_vec()[..],
2360 &vec![0; block_size]
2361 );
2362 assert_eq!(object2.read(0, buffer.as_mut()).await.expect("read failed"), 2 * block_size);
2363 assert_eq!(
2364 &buffer.as_ptr_slice().subslice(0..2 * block_size).to_vec()[..],
2365 &vec![0xef; 2 * block_size]
2366 );
2367 fs.close().await.expect("Close failed");
2368 }
2369
2370 #[fuchsia::test]
2371 async fn test_alignment() {
2372 let (fs, object) = test_filesystem_and_object().await;
2373
2374 struct AlignTest {
2375 fill: u8,
2376 object: DataObjectHandle<ObjectStore>,
2377 mirror: Vec<u8>,
2378 }
2379
2380 impl AlignTest {
2381 async fn new(object: DataObjectHandle<ObjectStore>) -> Self {
2382 let mirror = {
2383 let mut buf = object.allocate_buffer(object.get_size() as usize).await;
2384 assert_eq!(object.read(0, buf.as_mut()).await.expect("read failed"), buf.len());
2385 buf.to_vec()
2386 };
2387 Self { fill: 0, object, mirror }
2388 }
2389
2390 async fn test(&mut self, range: Range<u64>) {
2395 let mut buf = self.object.allocate_buffer((range.end - range.start) as usize).await;
2396 self.fill += 1;
2397 buf.fill(self.fill);
2398 self.object
2399 .write_or_append(Some(range.start), buf.as_ref())
2400 .await
2401 .expect("write_or_append failed");
2402 if range.end > self.mirror.len() as u64 {
2403 self.mirror.resize(range.end as usize, 0);
2404 }
2405 self.mirror[range.start as usize..range.end as usize].fill(self.fill);
2406 let mut buf = self.object.allocate_buffer(self.mirror.len() + 1).await;
2407 assert_eq!(
2408 self.object.read(0, buf.as_mut()).await.expect("read failed"),
2409 self.mirror.len()
2410 );
2411 assert_eq!(
2412 &buf.as_ptr_slice().subslice(0..self.mirror.len()).to_vec()[..],
2413 self.mirror.as_slice()
2414 );
2415 }
2416 }
2417
2418 let block_size = object.block_size().get();
2419 let mut align = AlignTest::new(object).await;
2420
2421 align.test(0..2 * block_size + 1).await;
2423
2424 align.test(1..block_size).await;
2426 align.test(1..2 * block_size).await;
2427
2428 align.test(0..block_size - 1).await;
2430 align.test(0..2 * block_size - 1).await;
2431
2432 align.test(1..block_size - 1).await;
2434 align.test(1..2 * block_size - 1).await;
2435
2436 fs.close().await.expect("Close failed");
2437 }
2438
2439 async fn test_preallocate_common(fs: &FxFilesystem, object: DataObjectHandle<ObjectStore>) {
2440 let allocator = fs.allocator();
2441 let allocated_before = allocator.get_allocated_bytes();
2442 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2443 object
2444 .preallocate_range(&mut transaction, &mut (0..fs.block_size().get()))
2445 .await
2446 .expect("preallocate_range failed");
2447 transaction.commit().await.expect("commit failed");
2448 assert!(object.get_size() < 1048576);
2449 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2450 object
2451 .preallocate_range(&mut transaction, &mut (0..1048576))
2452 .await
2453 .expect("preallocate_range failed");
2454 transaction.commit().await.expect("commit failed");
2455 assert_eq!(object.get_size(), 1048576);
2456 let allocated_after = allocator.get_allocated_bytes();
2458 assert_eq!(allocated_after - allocated_before, 1048576 - fs.block_size());
2459
2460 let mut buf = object
2461 .allocate_buffer(fs.block_size().align_up(TEST_DATA_OFFSET).unwrap() as usize)
2462 .await;
2463 buf.fill(47);
2464 object
2465 .write_or_append(Some(0), buf.subslice(0..TEST_DATA_OFFSET as usize))
2466 .await
2467 .expect("write failed");
2468 buf.fill(95);
2469 let offset = fs.block_size().align_up(TEST_OBJECT_SIZE).unwrap();
2470 object
2471 .overwrite(offset, buf.as_mut(), OverwriteOptions::default())
2472 .await
2473 .expect("write failed");
2474
2475 assert_eq!(allocator.get_allocated_bytes(), allocated_after);
2477
2478 let mut buf = object.allocate_buffer(104876).await;
2480 assert_eq!(object.read(0, buf.as_mut()).await.expect("read failed"), buf.len());
2481 assert_eq!(
2482 &buf.as_ptr_slice().subslice(0..TEST_DATA_OFFSET as usize).to_vec()[..],
2483 &[47; TEST_DATA_OFFSET as usize]
2484 );
2485 assert_eq!(
2486 &buf.as_ptr_slice()
2487 .subslice(TEST_DATA_OFFSET as usize..TEST_DATA_OFFSET as usize + TEST_DATA.len())
2488 .to_vec()[..],
2489 TEST_DATA
2490 );
2491 assert_eq!(
2492 &buf.as_ptr_slice().subslice(offset as usize..offset as usize + 2048).to_vec()[..],
2493 &[95; 2048]
2494 );
2495 }
2496
2497 #[fuchsia::test]
2498 async fn test_unaligned_overwrite_returns_error() {
2499 let (fs, object) = test_filesystem_and_object().await;
2500 let mut buf = object.allocate_buffer(100).await;
2501 let res = object.overwrite(0, buf.as_mut(), OverwriteOptions::default()).await;
2502 assert!(matches!(res, Err(e) if FxfsError::InvalidArgs.matches(&e)));
2503 fs.close().await.expect("Close failed");
2504 }
2505
2506 #[fuchsia::test]
2507 async fn test_unaligned_preallocate_returns_error() {
2508 let (fs, object) = test_filesystem_and_object().await;
2509 let mut transaction = fs
2510 .root_store()
2511 .new_transaction(lock_keys![], Options::default())
2512 .await
2513 .expect("new failed");
2514 let res = object.preallocate_range(&mut transaction, &mut (0..100)).await;
2515 assert!(matches!(res, Err(e) if FxfsError::InvalidArgs.matches(&e)));
2516 fs.close().await.expect("Close failed");
2517 }
2518
2519 #[fuchsia::test]
2520 async fn test_encrypted_preallocate_returns_error() {
2521 let (fs, object) = test_filesystem_and_object().await;
2522 let mut transaction = fs
2523 .root_store()
2524 .new_transaction(lock_keys![], Options::default())
2525 .await
2526 .expect("new failed");
2527 let bs = fs.block_size();
2528 let res = object.preallocate_range(&mut transaction, &mut (0..bs.get())).await;
2529 assert!(matches!(res, Err(e) if FxfsError::NotSupported.matches(&e)));
2530 fs.close().await.expect("Close failed");
2531 }
2532
2533 #[fuchsia::test]
2534 async fn test_preallocate_range() {
2535 let (fs, object) = test_filesystem_and_object_with_key(None, true).await;
2536 test_preallocate_common(&fs, object).await;
2537 fs.close().await.expect("Close failed");
2538 }
2539
2540 #[fuchsia::test]
2543 async fn test_preallocate_succeeds_when_extents_are_in_different_layers() {
2544 let (fs, object) = test_filesystem_and_object_with_key(None, true).await;
2545 object.owner().flush().await.expect("flush failed");
2546 test_preallocate_common(&fs, object).await;
2547 fs.close().await.expect("Close failed");
2548 }
2549
2550 #[fuchsia::test]
2551 async fn test_already_preallocated() {
2552 let (fs, object) = test_filesystem_and_object_with_key(None, true).await;
2553 let allocator = fs.allocator();
2554 let allocated_before = allocator.get_allocated_bytes();
2555 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2556 let offset = fs.block_size().align_down(TEST_DATA_OFFSET);
2557 object
2558 .preallocate_range(&mut transaction, &mut (offset..offset + fs.block_size()))
2559 .await
2560 .expect("preallocate_range failed");
2561 transaction.commit().await.expect("commit failed");
2562 assert_eq!(allocator.get_allocated_bytes(), allocated_before);
2564 fs.close().await.expect("Close failed");
2565 }
2566
2567 #[fuchsia::test]
2568 async fn test_overwrite_when_preallocated_at_start_of_file() {
2569 let (fs, object) = test_filesystem_and_empty_object().await;
2572
2573 let object = ObjectStore::open_object(
2574 object.owner(),
2575 object.object_id(),
2576 HandleOptions::default(),
2577 None,
2578 )
2579 .await
2580 .expect("open_object failed");
2581
2582 assert_eq!(fs.block_size(), 4096);
2583
2584 let mut write_buf = object.allocate_buffer(4096).await;
2585 write_buf.fill(95);
2586
2587 object
2590 .overwrite(0, write_buf.as_mut(), OverwriteOptions::default())
2591 .await
2592 .expect_err("overwrite succeeded");
2593
2594 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2596 object
2597 .preallocate_range(&mut transaction, &mut (0..4096 as u64))
2598 .await
2599 .expect("preallocate_range failed");
2600 transaction.commit().await.expect("commit failed");
2601
2602 {
2605 let mut read_buf = object.allocate_buffer(4096).await;
2606 object.read(0, read_buf.as_mut()).await.expect("read failed");
2607 assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2608 }
2609 object
2610 .overwrite(0, write_buf.as_mut(), OverwriteOptions::default())
2611 .await
2612 .expect("overwrite failed");
2613 {
2614 let mut read_buf = object.allocate_buffer(4096).await;
2615 object.read(0, read_buf.as_mut()).await.expect("read failed");
2616 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2617 }
2618
2619 object
2622 .overwrite(4096, write_buf.as_mut(), OverwriteOptions::default())
2623 .await
2624 .expect_err("overwrite succeeded");
2625
2626 object
2629 .overwrite(
2630 4096,
2631 write_buf.as_mut(),
2632 OverwriteOptions { allow_allocations: true, ..Default::default() },
2633 )
2634 .await
2635 .expect("overwrite failed");
2636 {
2637 let mut read_buf = object.allocate_buffer(4096).await;
2638 object.read(4096, read_buf.as_mut()).await.expect("read failed");
2639 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2640 }
2641
2642 let fsck_options = FsckOptions {
2644 fail_on_warning: true,
2645 no_lock: true,
2646 on_error: Box::new(|err| println!("fsck error: {:?}", err)),
2647 ..Default::default()
2648 };
2649 fsck_with_options(fs.clone(), &fsck_options).await.expect("fsck failed");
2650
2651 fs.close().await.expect("Close failed");
2652 }
2653
2654 #[fuchsia::test]
2655 async fn test_overwrite_large_buffer_and_file_with_many_holes() {
2656 let (fs, object) = test_filesystem_and_empty_object().await;
2659
2660 let object = ObjectStore::open_object(
2661 object.owner(),
2662 object.object_id(),
2663 HandleOptions::default(),
2664 None,
2665 )
2666 .await
2667 .expect("open_object failed");
2668
2669 assert_eq!(fs.block_size(), 4096);
2670 assert_eq!(object.get_size(), TEST_OBJECT_SIZE);
2671
2672 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2674 object
2675 .preallocate_range(&mut transaction, &mut (4096..8192 as u64))
2676 .await
2677 .expect("preallocate_range failed");
2678 object
2679 .preallocate_range(&mut transaction, &mut (16384..32768 as u64))
2680 .await
2681 .expect("preallocate_range failed");
2682 object
2683 .preallocate_range(&mut transaction, &mut (65536..131072 as u64))
2684 .await
2685 .expect("preallocate_range failed");
2686 object
2687 .preallocate_range(&mut transaction, &mut (262144..524288 as u64))
2688 .await
2689 .expect("preallocate_range failed");
2690 transaction.commit().await.expect("commit failed");
2691
2692 assert_eq!(object.get_size(), 524288);
2693
2694 let mut write_buf = object.allocate_buffer(4096).await;
2695 write_buf.fill(95);
2696
2697 object
2699 .overwrite(0, write_buf.as_mut(), OverwriteOptions::default())
2700 .await
2701 .expect_err("overwrite succeeded");
2702 object
2703 .overwrite(8192, write_buf.as_mut(), OverwriteOptions::default())
2704 .await
2705 .expect_err("overwrite succeeded");
2706 object
2707 .overwrite(32768, write_buf.as_mut(), OverwriteOptions::default())
2708 .await
2709 .expect_err("overwrite succeeded");
2710 object
2711 .overwrite(131072, write_buf.as_mut(), OverwriteOptions::default())
2712 .await
2713 .expect_err("overwrite succeeded");
2714
2715 {
2717 let mut read_buf = object.allocate_buffer(4096).await;
2718 object.read(4096, read_buf.as_mut()).await.expect("read failed");
2719 assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2720 }
2721 object
2722 .overwrite(4096, write_buf.as_mut(), OverwriteOptions::default())
2723 .await
2724 .expect("overwrite failed");
2725 {
2726 let mut read_buf = object.allocate_buffer(4096).await;
2727 object.read(4096, read_buf.as_mut()).await.expect("read failed");
2728 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2729 }
2730 {
2731 let mut read_buf = object.allocate_buffer(4096).await;
2732 object.read(16384, read_buf.as_mut()).await.expect("read failed");
2733 assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2734 }
2735 object
2736 .overwrite(16384, write_buf.as_mut(), OverwriteOptions::default())
2737 .await
2738 .expect("overwrite failed");
2739 {
2740 let mut read_buf = object.allocate_buffer(4096).await;
2741 object.read(16384, read_buf.as_mut()).await.expect("read failed");
2742 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2743 }
2744 {
2745 let mut read_buf = object.allocate_buffer(4096).await;
2746 object.read(65536, read_buf.as_mut()).await.expect("read failed");
2747 assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2748 }
2749 object
2750 .overwrite(65536, write_buf.as_mut(), OverwriteOptions::default())
2751 .await
2752 .expect("overwrite failed");
2753 {
2754 let mut read_buf = object.allocate_buffer(4096).await;
2755 object.read(65536, read_buf.as_mut()).await.expect("read failed");
2756 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2757 }
2758 {
2759 let mut read_buf = object.allocate_buffer(4096).await;
2760 object.read(262144, read_buf.as_mut()).await.expect("read failed");
2761 assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2762 }
2763 object
2764 .overwrite(262144, write_buf.as_mut(), OverwriteOptions::default())
2765 .await
2766 .expect("overwrite failed");
2767 {
2768 let mut read_buf = object.allocate_buffer(4096).await;
2769 object.read(262144, read_buf.as_mut()).await.expect("read failed");
2770 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2771 }
2772
2773 let mut huge_write_buf = object.allocate_buffer(524288).await;
2775 huge_write_buf.fill(96);
2776
2777 object
2779 .overwrite(0, huge_write_buf.as_mut(), OverwriteOptions::default())
2780 .await
2781 .expect_err("overwrite succeeded");
2782 object
2784 .overwrite(
2785 0,
2786 huge_write_buf.as_mut(),
2787 OverwriteOptions { allow_allocations: true, ..Default::default() },
2788 )
2789 .await
2790 .expect("overwrite failed");
2791 {
2792 let mut read_buf = object.allocate_buffer(524288).await;
2793 object.read(0, read_buf.as_mut()).await.expect("read failed");
2794 assert_eq!(&read_buf.to_vec()[..], &[96; 524288]);
2795 }
2796
2797 let fsck_options = FsckOptions {
2799 fail_on_warning: true,
2800 no_lock: true,
2801 on_error: Box::new(|err| println!("fsck error: {:?}", err)),
2802 ..Default::default()
2803 };
2804 fsck_with_options(fs.clone(), &fsck_options).await.expect("fsck failed");
2805
2806 fs.close().await.expect("Close failed");
2807 }
2808
2809 #[fuchsia::test]
2810 async fn test_overwrite_when_unallocated_at_start_of_file() {
2811 let (fs, object) = test_filesystem_and_empty_object().await;
2814
2815 let object = ObjectStore::open_object(
2816 object.owner(),
2817 object.object_id(),
2818 HandleOptions::default(),
2819 None,
2820 )
2821 .await
2822 .expect("open_object failed");
2823
2824 assert_eq!(fs.block_size(), 4096);
2825
2826 let mut write_buf = object.allocate_buffer(4096).await;
2827 write_buf.fill(95);
2828
2829 object
2832 .overwrite(0, write_buf.as_mut(), OverwriteOptions::default())
2833 .await
2834 .expect_err("overwrite succeeded");
2835
2836 object
2838 .overwrite(
2839 0,
2840 write_buf.as_mut(),
2841 OverwriteOptions { allow_allocations: true, ..Default::default() },
2842 )
2843 .await
2844 .expect("overwrite failed");
2845 {
2846 let mut read_buf = object.allocate_buffer(4096).await;
2847 object.read(0, read_buf.as_mut()).await.expect("read failed");
2848 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2849 }
2850
2851 object
2853 .overwrite(4096, write_buf.as_mut(), OverwriteOptions::default())
2854 .await
2855 .expect_err("overwrite succeeded");
2856
2857 object
2859 .overwrite(
2860 4096,
2861 write_buf.as_mut(),
2862 OverwriteOptions { allow_allocations: true, ..Default::default() },
2863 )
2864 .await
2865 .expect("overwrite failed");
2866 {
2867 let mut read_buf = object.allocate_buffer(4096).await;
2868 object.read(4096, read_buf.as_mut()).await.expect("read failed");
2869 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2870 }
2871
2872 let fsck_options = FsckOptions {
2874 fail_on_warning: true,
2875 no_lock: true,
2876 on_error: Box::new(|err| println!("fsck error: {:?}", err)),
2877 ..Default::default()
2878 };
2879 fsck_with_options(fs.clone(), &fsck_options).await.expect("fsck failed");
2880
2881 fs.close().await.expect("Close failed");
2882 }
2883
2884 #[fuchsia::test]
2885 async fn test_overwrite_can_extend_a_file() {
2886 let (fs, object) = test_filesystem_and_empty_object().await;
2889
2890 let object = ObjectStore::open_object(
2891 object.owner(),
2892 object.object_id(),
2893 HandleOptions::default(),
2894 None,
2895 )
2896 .await
2897 .expect("open_object failed");
2898
2899 assert_eq!(fs.block_size(), 4096);
2900 assert_eq!(object.get_size(), TEST_OBJECT_SIZE);
2901
2902 let mut write_buf = object.allocate_buffer(4096).await;
2903 write_buf.fill(95);
2904
2905 let last_block_offset = round_down(TEST_OBJECT_SIZE, 4096 as u32);
2907
2908 object
2910 .overwrite(last_block_offset, write_buf.as_mut(), OverwriteOptions::default())
2911 .await
2912 .expect_err("overwrite succeeded");
2913 object
2915 .overwrite(
2916 last_block_offset,
2917 write_buf.as_mut(),
2918 OverwriteOptions { allow_allocations: true, ..Default::default() },
2919 )
2920 .await
2921 .expect("overwrite failed");
2922 {
2923 let mut read_buf = object.allocate_buffer(4096).await;
2924 object.read(last_block_offset, read_buf.as_mut()).await.expect("read failed");
2925 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2926 }
2927
2928 assert_eq!(object.get_size(), 8192);
2929
2930 let next_block_offset = round_up(TEST_OBJECT_SIZE, 4096 as u32).unwrap();
2932
2933 object
2935 .overwrite(next_block_offset, write_buf.as_mut(), OverwriteOptions::default())
2936 .await
2937 .expect_err("overwrite succeeded");
2938 object
2940 .overwrite(
2941 next_block_offset,
2942 write_buf.as_mut(),
2943 OverwriteOptions { allow_allocations: true, ..Default::default() },
2944 )
2945 .await
2946 .expect("overwrite failed");
2947 {
2948 let mut read_buf = object.allocate_buffer(4096).await;
2949 object.read(next_block_offset, read_buf.as_mut()).await.expect("read failed");
2950 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2951 }
2952
2953 assert_eq!(object.get_size(), 12288);
2954
2955 let fsck_options = FsckOptions {
2957 fail_on_warning: true,
2958 no_lock: true,
2959 on_error: Box::new(|err| println!("fsck error: {:?}", err)),
2960 ..Default::default()
2961 };
2962 fsck_with_options(fs.clone(), &fsck_options).await.expect("fsck failed");
2963
2964 fs.close().await.expect("Close failed");
2965 }
2966
2967 #[fuchsia::test]
2968 async fn test_enable_verity() {
2969 let fs: OpenFxFilesystem = test_filesystem().await;
2970 let mut transaction = fs
2971 .root_store()
2972 .new_transaction(lock_keys![], Options::default())
2973 .await
2974 .expect("new_transaction failed");
2975 let store = fs.root_store();
2976 let object = Arc::new(
2977 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
2978 .await
2979 .expect("create_object failed"),
2980 );
2981
2982 transaction.commit().await.unwrap();
2983
2984 object
2985 .enable_verity(fio::VerificationOptions {
2986 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
2987 salt: Some(vec![]),
2988 ..Default::default()
2989 })
2990 .await
2991 .expect("set verified file metadata failed");
2992
2993 let handle =
2994 ObjectStore::open_object(&store, object.object_id(), HandleOptions::default(), None)
2995 .await
2996 .expect("open_object failed");
2997
2998 assert!(handle.is_verified_file());
2999
3000 fs.close().await.expect("Close failed");
3001 }
3002
3003 #[fuchsia::test]
3004 async fn test_enable_verity_large_file() {
3005 let device = DeviceHolder::new(FakeDevice::new(262144, TEST_DEVICE_BLOCK_SIZE));
3007 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
3008 let root_store = fs.root_store();
3009 let mut transaction = fs
3010 .root_store()
3011 .new_transaction(lock_keys![], Options::default())
3012 .await
3013 .expect("new_transaction failed");
3014
3015 let handle = ObjectStore::create_object(
3016 &root_store,
3017 &mut transaction,
3018 HandleOptions::default(),
3019 None,
3020 )
3021 .await
3022 .expect("failed to create object");
3023 transaction.commit().await.expect("commit failed");
3024 let mut offset = 0;
3025
3026 let mut buf = handle.allocate_buffer(WRITE_ATTR_BATCH_SIZE).await;
3028 buf.fill(1);
3029 for _ in 0..130 {
3030 handle.write_or_append(Some(offset), buf.as_ref()).await.expect("write failed");
3031 offset += WRITE_ATTR_BATCH_SIZE as u64;
3032 }
3033
3034 handle
3035 .enable_verity(fio::VerificationOptions {
3036 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3037 salt: Some(vec![]),
3038 ..Default::default()
3039 })
3040 .await
3041 .expect("set verified file metadata failed");
3042
3043 let mut buf = handle.allocate_buffer(WRITE_ATTR_BATCH_SIZE).await;
3044 offset = 0;
3045 for _ in 0..130 {
3046 handle.read(offset, buf.as_mut()).await.expect("verification during read should fail");
3047 assert_eq!(buf.to_vec(), &[1; WRITE_ATTR_BATCH_SIZE]);
3048 offset += WRITE_ATTR_BATCH_SIZE as u64;
3049 }
3050
3051 fsck(fs.clone()).await.expect("fsck failed");
3052 fs.close().await.expect("Close failed");
3053 }
3054
3055 #[fuchsia::test]
3056 async fn test_retry_enable_verity_on_reboot() {
3057 let device = DeviceHolder::new(FakeDevice::new(8192, TEST_DEVICE_BLOCK_SIZE));
3058 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
3059 let root_store = fs.root_store();
3060 let mut transaction = fs
3061 .root_store()
3062 .new_transaction(lock_keys![], Options::default())
3063 .await
3064 .expect("new_transaction failed");
3065
3066 let handle = ObjectStore::create_object(
3067 &root_store,
3068 &mut transaction,
3069 HandleOptions::default(),
3070 None,
3071 )
3072 .await
3073 .expect("failed to create object");
3074 transaction.commit().await.expect("commit failed");
3075
3076 let object_id = {
3077 let mut transaction = handle.new_transaction().await.expect("new_transaction failed");
3078 transaction.add(
3079 root_store.store_object_id(),
3080 Mutation::replace_or_insert_object(
3081 ObjectKey::graveyard_attribute_entry(
3082 root_store.graveyard_directory_object_id(),
3083 handle.object_id(),
3084 AttributeId::FSVERITY_MERKLE,
3085 ),
3086 ObjectValue::Some,
3087 ),
3088 );
3089
3090 handle
3093 .write_new_attr_in_batches(
3094 &mut transaction,
3095 AttributeId::FSVERITY_MERKLE,
3096 &vec![0; 2 * WRITE_ATTR_BATCH_SIZE],
3097 WRITE_ATTR_BATCH_SIZE,
3098 )
3099 .await
3100 .expect("failed to write merkle attribute");
3101
3102 handle.object_id()
3103 };
3106
3107 fs.close().await.expect("failed to close filesystem");
3108 let device = fs.take_device().await;
3109 device.reopen(false);
3110
3111 let fs =
3112 FxFilesystemBuilder::new().read_only(true).open(device).await.expect("open failed");
3113 fsck(fs.clone()).await.expect("fsck failed");
3114 fs.close().await.expect("failed to close filesystem");
3115 let device = fs.take_device().await;
3116 device.reopen(false);
3117
3118 let fs = FxFilesystem::open(device).await.expect("open failed");
3120 let root_store = fs.root_store();
3121 let handle =
3122 ObjectStore::open_object(&root_store, object_id, HandleOptions::default(), None)
3123 .await
3124 .expect("open_object failed");
3125 handle
3126 .enable_verity(fio::VerificationOptions {
3127 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3128 salt: Some(vec![]),
3129 ..Default::default()
3130 })
3131 .await
3132 .expect("set verified file metadata failed");
3133
3134 fs.graveyard().flush().await;
3139 let merkle_data = handle
3140 .read_attr(AttributeId::FSVERITY_MERKLE)
3141 .await
3142 .expect("read_attr failed")
3143 .expect("No attr found");
3144 assert!(
3145 FsVerityDescriptor::new(&merkle_data[..], handle.block_size().get() as usize).is_ok()
3146 );
3147 fsck(fs.clone()).await.expect("fsck failed");
3148 fs.close().await.expect("Close failed");
3149 }
3150
3151 #[fuchsia::test]
3152 async fn test_verify_data_corrupt_file() {
3153 let fs: OpenFxFilesystem = test_filesystem().await;
3154 let mut transaction = fs
3155 .root_store()
3156 .new_transaction(lock_keys![], Options::default())
3157 .await
3158 .expect("new_transaction failed");
3159 let store = fs.root_store();
3160 let object = Arc::new(
3161 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3162 .await
3163 .expect("create_object failed"),
3164 );
3165
3166 transaction.commit().await.unwrap();
3167
3168 let mut buf = object.allocate_buffer(5 * fs.block_size().get() as usize).await;
3169 buf.fill(123);
3170 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3171
3172 object
3173 .enable_verity(fio::VerificationOptions {
3174 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3175 salt: Some(vec![]),
3176 ..Default::default()
3177 })
3178 .await
3179 .expect("set verified file metadata failed");
3180
3181 buf.fill(234);
3183 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3184 object.read(0, buf.as_mut()).await.expect_err("verification during read should fail");
3185
3186 fs.close().await.expect("Close failed");
3187 }
3188
3189 #[fuchsia::test]
3193 async fn test_parse_f2fs_verity() {
3194 let fs: OpenFxFilesystem = test_filesystem().await;
3195 let mut transaction = fs
3196 .root_store()
3197 .new_transaction(lock_keys![], Options::default())
3198 .await
3199 .expect("new_transaction failed");
3200 let store = fs.root_store();
3201 let object = Arc::new(
3202 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3203 .await
3204 .expect("create_object failed"),
3205 );
3206
3207 transaction.commit().await.unwrap();
3208 let file_size = fs.block_size() * 2;
3209 {
3211 let mut buf = object.allocate_buffer(file_size as usize).await;
3212 buf.fill(64);
3213 assert_eq!(
3214 object.write_or_append(None, buf.as_ref()).await.expect("Writing to file."),
3215 file_size
3216 );
3217 }
3218
3219 object
3221 .enable_verity(fio::VerificationOptions {
3222 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3223 salt: Some(vec![]),
3224 ..Default::default()
3225 })
3226 .await
3227 .expect("set verified file metadata failed");
3228 let (verity_info, root_hash) = object.get_descriptor().unwrap();
3229
3230 let mut transaction = fs
3231 .root_store()
3232 .new_transaction(
3233 lock_keys![LockKey::Object {
3234 store_object_id: store.store_object_id(),
3235 object_id: object.object_id()
3236 }],
3237 Options::default(),
3238 )
3239 .await
3240 .expect("new_transaction failed");
3241 transaction.add(
3242 store.store_object_id(),
3243 Mutation::replace_or_insert_object(
3244 ObjectKey::attribute(
3245 object.object_id(),
3246 AttributeId::DATA,
3247 AttributeKey::Attribute,
3248 ),
3249 ObjectValue::verified_attribute(
3250 file_size,
3251 FsverityMetadata::F2fs(0..(fs.block_size() * 2)),
3252 ),
3253 ),
3254 );
3255 transaction.add(
3256 store.store_object_id(),
3257 Mutation::replace_or_insert_object(
3258 ObjectKey::attribute(
3259 object.object_id(),
3260 AttributeId::FSVERITY_MERKLE,
3261 AttributeKey::Attribute,
3262 ),
3263 ObjectValue::attribute(fs.block_size() * 2, false),
3264 ),
3265 );
3266 {
3267 let descriptor = FsVerityDescriptorRaw::new(
3268 fio::HashAlgorithm::Sha256,
3269 fs.block_size().get(),
3270 file_size,
3271 root_hash.as_slice(),
3272 match &verity_info.salt {
3273 Some(salt) => salt.as_slice(),
3274 None => [0u8; 0].as_slice(),
3275 },
3276 )
3277 .expect("Creating descriptor");
3278 let mut buf = object.allocate_buffer(fs.block_size().get() as usize).await;
3279 let mut temp = vec![0u8; fs.block_size().get() as usize];
3280 descriptor.write_to_slice(&mut temp).expect("Writing descriptor to buf");
3281 buf.copy_from_slice(&temp);
3282 object
3283 .multi_write(
3284 &mut transaction,
3285 AttributeId::FSVERITY_MERKLE,
3286 &[fs.block_size().get()..(fs.block_size() * 2)],
3287 buf.as_mut(),
3288 )
3289 .await
3290 .expect("Writing descriptor");
3291 }
3292 transaction.commit().await.unwrap();
3293
3294 let handle =
3295 ObjectStore::open_object(&store, object.object_id(), HandleOptions::default(), None)
3296 .await
3297 .expect("open_object failed");
3298
3299 assert!(handle.is_verified_file());
3300
3301 let mut buf = object.allocate_buffer(file_size as usize).await;
3302 assert_eq!(
3303 handle.read(0, buf.as_mut()).await.expect("Read whole file."),
3304 file_size as usize
3305 );
3306
3307 fs.close().await.expect("Close failed");
3308 }
3309
3310 #[fuchsia::test]
3311 async fn test_verify_data_corrupt_tree() {
3312 let fs: OpenFxFilesystem = test_filesystem().await;
3313 let object_id = {
3314 let store = fs.root_store();
3315 let mut transaction = fs
3316 .root_store()
3317 .new_transaction(lock_keys![], Options::default())
3318 .await
3319 .expect("new_transaction failed");
3320 let object = Arc::new(
3321 ObjectStore::create_object(
3322 &store,
3323 &mut transaction,
3324 HandleOptions::default(),
3325 None,
3326 )
3327 .await
3328 .expect("create_object failed"),
3329 );
3330 let object_id = object.object_id();
3331
3332 transaction.commit().await.unwrap();
3333
3334 let mut buf = object.allocate_buffer(5 * fs.block_size().get() as usize).await;
3335 buf.fill(123);
3336 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3337
3338 object
3339 .enable_verity(fio::VerificationOptions {
3340 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3341 salt: Some(vec![]),
3342 ..Default::default()
3343 })
3344 .await
3345 .expect("set verified file metadata failed");
3346 object.read(0, buf.as_mut()).await.expect("verified read");
3347
3348 let mut merkle = object
3350 .read_attr(AttributeId::FSVERITY_MERKLE)
3351 .await
3352 .unwrap()
3353 .expect("Reading merkle tree");
3354 merkle[0] = merkle[0].wrapping_add(1);
3355 object
3356 .write_attr(AttributeId::FSVERITY_MERKLE, &*merkle)
3357 .await
3358 .expect("Overwriting merkle");
3359
3360 object_id
3361 }; assert!(
3365 ObjectStore::open_object(&fs.root_store(), object_id, HandleOptions::default(), None)
3366 .await
3367 .is_err()
3368 );
3369 fs.close().await.expect("Close failed");
3370 }
3371
3372 #[fuchsia::test]
3373 async fn test_allocate_verity_file() {
3374 let fs: OpenFxFilesystem = test_filesystem().await;
3375 let mut transaction = fs
3376 .root_store()
3377 .new_transaction(lock_keys![], Options::default())
3378 .await
3379 .expect("new_transaction failed");
3380 let store = fs.root_store();
3381 let object = Arc::new(
3382 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3383 .await
3384 .expect("create_object failed"),
3385 );
3386 transaction.commit().await.unwrap();
3387
3388 let mut buf = object.allocate_buffer(8192).await;
3389 buf.fill(0xAA);
3390 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3391
3392 object
3393 .enable_verity(fio::VerificationOptions {
3394 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3395 salt: Some(vec![]),
3396 ..Default::default()
3397 })
3398 .await
3399 .expect("enable_verity failed");
3400
3401 assert!(object.is_verified_file());
3402
3403 assert!(object.allocate(0..8192).await.is_err());
3405
3406 let reopened =
3408 ObjectStore::open_object(&store, object.object_id(), HandleOptions::default(), None)
3409 .await
3410 .expect("open_object failed");
3411 assert!(reopened.is_verified_file());
3412
3413 fs.close().await.expect("Close failed");
3414 }
3415
3416 #[fuchsia::test]
3417 async fn test_extend() {
3418 let fs = test_filesystem().await;
3419 let handle;
3420 let mut transaction = fs
3421 .root_store()
3422 .new_transaction(lock_keys![], Options::default())
3423 .await
3424 .expect("new_transaction failed");
3425 let store = fs.root_store();
3426 handle =
3427 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3428 .await
3429 .expect("create_object failed");
3430
3431 const START_OFFSET: u64 = 2048 * 1024;
3435 handle
3436 .extend(&mut transaction, START_OFFSET..START_OFFSET + 5 * fs.block_size())
3437 .await
3438 .expect("extend failed");
3439 transaction.commit().await.expect("commit failed");
3440 let mut buf = handle.allocate_buffer(5 * fs.block_size().get() as usize).await;
3441 buf.fill(123);
3442 handle.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3443 buf.fill(67);
3444 handle.read(0, buf.as_mut()).await.expect("read failed");
3445 assert_eq!(buf.to_vec(), vec![123; 5 * fs.block_size().get() as usize]);
3446 fs.close().await.expect("Close failed");
3447 }
3448
3449 #[fuchsia::test]
3450 async fn test_truncate_deallocates_old_extents() {
3451 let (fs, object) = test_filesystem_and_object().await;
3452 let mut buf = object.allocate_buffer(5 * fs.block_size().get() as usize).await;
3453 buf.fill(0xaa);
3454 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3455
3456 let allocator = fs.allocator();
3457 let allocated_before = allocator.get_allocated_bytes();
3458 object.truncate(fs.block_size().get()).await.expect("truncate failed");
3459 let allocated_after = allocator.get_allocated_bytes();
3460 assert!(
3461 allocated_after < allocated_before,
3462 "before = {} after = {}",
3463 allocated_before,
3464 allocated_after
3465 );
3466 fs.close().await.expect("Close failed");
3467 }
3468
3469 #[fuchsia::test]
3470 async fn test_truncate_zeroes_tail_block() {
3471 let (fs, object) = test_filesystem_and_object().await;
3472
3473 WriteObjectHandle::truncate(&object, TEST_DATA_OFFSET + 3).await.expect("truncate failed");
3474 WriteObjectHandle::truncate(&object, TEST_DATA_OFFSET + TEST_DATA.len() as u64)
3475 .await
3476 .expect("truncate failed");
3477
3478 let mut buf = object.allocate_buffer(fs.block_size().get() as usize).await;
3479 let offset = (TEST_DATA_OFFSET % fs.block_size()) as usize;
3480 object.read(TEST_DATA_OFFSET - offset as u64, buf.as_mut()).await.expect("read failed");
3481
3482 let mut expected = TEST_DATA.to_vec();
3483 expected[3..].fill(0);
3484 assert_eq!(
3485 &buf.as_ptr_slice().subslice(offset..offset + expected.len()).to_vec()[..],
3486 &expected
3487 );
3488 }
3489
3490 #[fuchsia::test]
3491 async fn test_trim() {
3492 let device = DeviceHolder::new(FakeDevice::new(8192, TEST_DEVICE_BLOCK_SIZE));
3494 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
3495 let block_size = fs.block_size();
3496 root_volume(fs.clone())
3497 .await
3498 .expect("root_volume failed")
3499 .new_volume("test", NewChildStoreOptions::default())
3500 .await
3501 .expect("volume failed");
3502 fs.close().await.expect("close failed");
3503 let device = fs.take_device().await;
3504 device.reopen(false);
3505
3506 #[derive(Default)]
3511 struct Context {
3512 store: Option<Arc<ObjectStore>>,
3513 object_id: Option<u64>,
3514 }
3515 let shared_context = Arc::new(Mutex::new(Context::default()));
3516
3517 let object_size = (TRANSACTION_MUTATION_THRESHOLD as u64 + 10) * 2 * block_size;
3518
3519 async fn expect_tombstoned(store: &Arc<ObjectStore>, object_id: u64) {
3521 loop {
3522 if let Err(e) =
3523 ObjectStore::open_object(store, object_id, HandleOptions::default(), None).await
3524 {
3525 assert!(
3526 FxfsError::NotFound.matches(&e),
3527 "open_object didn't fail with NotFound: {:?}",
3528 e
3529 );
3530 break;
3531 }
3532 fasync::Timer::new(std::time::Duration::from_millis(100)).await;
3534 }
3535 }
3536
3537 async fn needs_trim(store: &Arc<ObjectStore>) -> Option<DataObjectHandle<ObjectStore>> {
3539 let root_directory = Directory::open(store, store.root_directory_object_id())
3540 .await
3541 .expect("open failed");
3542 let oid = root_directory.lookup("foo").await.expect("lookup failed");
3543 if let Some((oid, _, _)) = oid {
3544 let object = ObjectStore::open_object(store, oid, HandleOptions::default(), None)
3545 .await
3546 .expect("open_object failed");
3547 let props = object.get_properties().await.expect("get_properties failed");
3548 if props.allocated_size > 0 && props.data_attribute_size == 0 {
3549 Some(object)
3550 } else {
3551 None
3552 }
3553 } else {
3554 None
3555 }
3556 }
3557
3558 let shared_context_clone = shared_context.clone();
3559 let post_commit = move || {
3560 let store = shared_context_clone.lock().store.as_ref().cloned().unwrap();
3561 let shared_context = shared_context_clone.clone();
3562 async move {
3563 let options = FsckOptions {
3565 fail_on_warning: true,
3566 no_lock: true,
3567 on_error: Box::new(|err| println!("fsck error: {:?}", err)),
3568 ..Default::default()
3569 };
3570 let fs = store.filesystem();
3571
3572 fsck_with_options(fs.clone(), &options).await.expect("fsck_with_options failed");
3573 fsck_volume_with_options(fs.as_ref(), &options, store.store_object_id(), None)
3574 .await
3575 .expect("fsck_volume_with_options failed");
3576
3577 fs.sync(SyncOptions { flush_device: true, ..Default::default() })
3579 .await
3580 .expect("sync failed");
3581 let device = fs.device().snapshot().expect("snapshot failed");
3582
3583 let object_id = shared_context.lock().object_id.clone();
3584
3585 let fs2 = FxFilesystemBuilder::new()
3586 .skip_initial_reap(object_id.is_none())
3587 .open(device)
3588 .await
3589 .expect("open failed");
3590
3591 let root_vol = root_volume(fs2.clone()).await.expect("root_volume failed");
3593 let store =
3594 root_vol.volume("test", StoreOptions::default()).await.expect("volume failed");
3595
3596 if let Some(oid) = object_id {
3597 expect_tombstoned(&store, oid).await;
3599 } else if let Some(object) = needs_trim(&store).await {
3600 object.truncate(object_size).await.expect("truncate failed");
3602 let mut buf = object.allocate_buffer(block_size.get() as usize).await;
3603 object
3604 .read(object_size - block_size * 2, buf.as_mut())
3605 .await
3606 .expect("read failed");
3607 assert_eq!(buf.to_vec(), vec![0; block_size.get() as usize]);
3608
3609 let fs = FxFilesystem::open(fs.device().snapshot().expect("snapshot failed"))
3612 .await
3613 .expect("open failed");
3614 let root_vol = root_volume(fs.clone()).await.expect("root_volume failed");
3615 let store = root_vol
3616 .volume("test", StoreOptions::default())
3617 .await
3618 .expect("volume failed");
3619 while needs_trim(&store).await.is_some() {
3620 fasync::Timer::new(std::time::Duration::from_millis(100)).await;
3623 }
3624
3625 fsck_with_options(fs.clone(), &options)
3627 .await
3628 .expect("fsck_with_options failed");
3629 fsck_volume_with_options(fs.as_ref(), &options, store.store_object_id(), None)
3630 .await
3631 .expect("fsck_volume_with_options failed");
3632 fs.close().await.expect("close failed");
3633 }
3634
3635 fsck_with_options(fs2.clone(), &options).await.expect("fsck_with_options failed");
3637 fsck_volume_with_options(fs2.as_ref(), &options, store.store_object_id(), None)
3638 .await
3639 .expect("fsck_volume_with_options failed");
3640 fs2.close().await.expect("close failed");
3641 }
3642 .boxed()
3643 };
3644
3645 let fs = FxFilesystemBuilder::new()
3646 .post_commit_hook(post_commit)
3647 .open(device)
3648 .await
3649 .expect("open failed");
3650
3651 let root_vol = root_volume(fs.clone()).await.expect("root_volume failed");
3652 let store = root_vol.volume("test", StoreOptions::default()).await.expect("volume failed");
3653
3654 shared_context.lock().store = Some(store.clone());
3655
3656 let root_directory =
3657 Directory::open(&store, store.root_directory_object_id()).await.expect("open failed");
3658
3659 let object;
3660 let mut transaction = fs
3661 .root_store()
3662 .new_transaction(
3663 lock_keys![LockKey::object(
3664 store.store_object_id(),
3665 store.root_directory_object_id()
3666 )],
3667 Options::default(),
3668 )
3669 .await
3670 .expect("new_transaction failed");
3671 object = root_directory
3672 .create_child_file(&mut transaction, "foo")
3673 .await
3674 .expect("create_object failed");
3675 transaction.commit().await.expect("commit failed");
3676
3677 let mut transaction = fs
3678 .root_store()
3679 .new_transaction(
3680 lock_keys![LockKey::object(store.store_object_id(), object.object_id())],
3681 Options::default(),
3682 )
3683 .await
3684 .expect("new_transaction failed");
3685
3686 let mut pass = 0;
3689 loop {
3690 let mut buf = object.allocate_buffer(5).await;
3693 buf.fill(1);
3694 for offset in (0..object_size).into_iter().step_by((2 * block_size) as usize) {
3696 object
3697 .txn_write(&mut transaction, offset, buf.as_ref())
3698 .await
3699 .expect("write failed");
3700 }
3701 transaction.commit().await.expect("commit failed");
3702 WriteObjectHandle::truncate(&object, 0).await.expect("truncate failed");
3704
3705 if pass == 1 {
3706 break;
3707 }
3708
3709 shared_context.lock().object_id = Some(object.object_id());
3712
3713 transaction = fs
3714 .root_store()
3715 .new_transaction(
3716 lock_keys![
3717 LockKey::object(store.store_object_id(), store.root_directory_object_id()),
3718 LockKey::object(store.store_object_id(), object.object_id()),
3719 ],
3720 Options::default(),
3721 )
3722 .await
3723 .expect("new_transaction failed");
3724
3725 replace_child(&mut transaction, None, (&root_directory, "foo"))
3727 .await
3728 .expect("replace_child failed");
3729 store.add_to_graveyard(&mut transaction, object.object_id());
3730
3731 pass += 1;
3732 }
3733
3734 fs.close().await.expect("Close failed");
3735 }
3736
3737 #[fuchsia::test]
3738 async fn test_adjust_refs() {
3739 let (fs, object) = test_filesystem_and_object().await;
3740 let store = object.owner();
3741 let mut transaction = fs
3742 .root_store()
3743 .new_transaction(
3744 lock_keys![LockKey::object(store.store_object_id(), object.object_id())],
3745 Options::default(),
3746 )
3747 .await
3748 .expect("new_transaction failed");
3749 assert_eq!(
3750 store
3751 .adjust_refs(&mut transaction, object.object_id(), 1)
3752 .await
3753 .expect("adjust_refs failed"),
3754 false
3755 );
3756 transaction.commit().await.expect("commit failed");
3757
3758 let allocator = fs.allocator();
3759 let allocated_before = allocator.get_allocated_bytes();
3760 let mut transaction = fs
3761 .root_store()
3762 .new_transaction(
3763 lock_keys![LockKey::object(store.store_object_id(), object.object_id())],
3764 Options::default(),
3765 )
3766 .await
3767 .expect("new_transaction failed");
3768 assert_eq!(
3769 store
3770 .adjust_refs(&mut transaction, object.object_id(), -2)
3771 .await
3772 .expect("adjust_refs failed"),
3773 true
3774 );
3775 transaction.commit().await.expect("commit failed");
3776
3777 assert_eq!(allocator.get_allocated_bytes(), allocated_before);
3778
3779 store
3780 .tombstone_object(
3781 object.object_id(),
3782 Options { borrow_metadata_space: true, ..Default::default() },
3783 None,
3784 )
3785 .await
3786 .expect("purge failed");
3787
3788 assert_eq!(allocated_before - allocator.get_allocated_bytes(), fs.block_size());
3789
3790 {
3792 let mut transaction = fs
3793 .root_store()
3794 .new_transaction(
3795 lock_keys![LockKey::object(
3796 store.store_object_id(),
3797 store.root_directory_object_id()
3798 )],
3799 Options::default(),
3800 )
3801 .await
3802 .expect("new_transaction failed");
3803 let root_directory = Directory::open(&store, store.root_directory_object_id())
3804 .await
3805 .expect("open failed");
3806 transaction.add(
3807 store.store_object_id(),
3808 Mutation::replace_or_insert_object(
3809 ObjectKey::child(root_directory.object_id(), TEST_OBJECT_NAME, DirType::Normal),
3810 ObjectValue::None,
3811 ),
3812 );
3813 transaction.commit().await.expect("commit failed");
3814 }
3815
3816 fsck_with_options(
3817 fs.clone(),
3818 &FsckOptions {
3819 fail_on_warning: true,
3820 on_error: Box::new(|err| println!("fsck error: {:?}", err)),
3821 ..Default::default()
3822 },
3823 )
3824 .await
3825 .expect("fsck_with_options failed");
3826
3827 fs.close().await.expect("Close failed");
3828 }
3829
3830 #[fuchsia::test]
3831 async fn test_locks() {
3832 let (fs, object) = test_filesystem_and_object().await;
3833 let (send1, recv1) = channel();
3834 let (send2, recv2) = channel();
3835 let (send3, recv3) = channel();
3836 let done = Mutex::new(false);
3837 let mut futures = FuturesUnordered::new();
3838 futures.push(
3839 async {
3840 let mut t = object.new_transaction().await.expect("new_transaction failed");
3841 send1.send(()).unwrap(); send3.send(()).unwrap(); recv2.await.unwrap();
3844 let mut buf = object.allocate_buffer(5).await;
3845 buf.copy_from_slice(b"hello");
3846 object.txn_write(&mut t, 0, buf.as_ref()).await.expect("write failed");
3847 fasync::Timer::new(Duration::from_millis(100)).await;
3849 assert!(!*done.lock());
3850 t.commit().await.expect("commit failed");
3851 }
3852 .boxed(),
3853 );
3854 futures.push(
3855 async {
3856 recv1.await.unwrap();
3857 let offset = TEST_DATA_OFFSET as usize;
3859 let align = (offset as u64 % fs.block_size()) as usize;
3860 let len = TEST_DATA.len();
3861 let mut buf = object.allocate_buffer(align + len).await;
3862 assert_eq!(
3863 object.read((offset - align) as u64, buf.as_mut()).await.expect("read failed"),
3864 align + TEST_DATA.len()
3865 );
3866 assert_eq!(&buf.as_ptr_slice().subslice(align..buf.len()).to_vec()[..], TEST_DATA);
3867 send2.send(()).unwrap();
3869 }
3870 .boxed(),
3871 );
3872 futures.push(
3873 async {
3874 recv3.await.unwrap();
3876 let _t = object.new_transaction().await.expect("new_transaction failed");
3877 let mut buf = object.allocate_buffer(5).await;
3878 assert_eq!(object.read(0, buf.as_mut()).await.expect("read failed"), 5);
3879 assert_eq!(buf.to_vec(), b"hello");
3880 }
3881 .boxed(),
3882 );
3883 while let Some(()) = futures.next().await {}
3884 fs.close().await.expect("Close failed");
3885 }
3886
3887 #[fuchsia::test(threads = 10)]
3888 async fn test_racy_reads() {
3889 let fs = test_filesystem().await;
3890 let object;
3891 let mut transaction = fs
3892 .root_store()
3893 .new_transaction(lock_keys![], Options::default())
3894 .await
3895 .expect("new_transaction failed");
3896 let store = fs.root_store();
3897 object = Arc::new(
3898 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3899 .await
3900 .expect("create_object failed"),
3901 );
3902 transaction.commit().await.expect("commit failed");
3903 for _ in 0..100 {
3904 let cloned_object = object.clone();
3905 let writer = fasync::Task::spawn(async move {
3906 let mut buf = cloned_object.allocate_buffer(10).await;
3907 buf.fill(123);
3908 cloned_object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3909 });
3910 let cloned_object = object.clone();
3911 let reader = fasync::Task::spawn(async move {
3912 let wait_time = rand::random_range(0..5);
3913 fasync::Timer::new(Duration::from_millis(wait_time)).await;
3914 let mut buf = cloned_object.allocate_buffer(10).await;
3915 buf.fill(23);
3916 let amount = cloned_object.read(0, buf.as_mut()).await.expect("write failed");
3917 if amount != 0 {
3922 assert_eq!(amount, 10);
3923 assert_eq!(buf.to_vec(), &[123; 10]);
3924 }
3925 });
3926 writer.await;
3927 reader.await;
3928 object.truncate(0).await.expect("truncate failed");
3929 }
3930 fs.close().await.expect("Close failed");
3931 }
3932
3933 #[fuchsia::test]
3934 async fn test_allocated_size() {
3935 let (fs, object) = test_filesystem_and_object_with_key(None, true).await;
3936
3937 let before = object.get_properties().await.expect("get_properties failed").allocated_size;
3938 let mut buf = object.allocate_buffer(5).await;
3939 buf.copy_from_slice(b"hello");
3940 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3941 let after = object.get_properties().await.expect("get_properties failed").allocated_size;
3942 assert_eq!(after, before + fs.block_size());
3943
3944 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3946 assert_eq!(
3947 object.get_properties().await.expect("get_properties failed").allocated_size,
3948 after
3949 );
3950
3951 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
3953 let offset = 1000 * fs.block_size();
3954 let before = after;
3955 object
3956 .extend(&mut transaction, offset..offset + fs.block_size())
3957 .await
3958 .expect("extend failed");
3959 transaction.commit().await.expect("commit failed");
3960 let after = object.get_properties().await.expect("get_properties failed").allocated_size;
3961 assert_eq!(after, before + fs.block_size());
3962
3963 let before = after;
3965 let size = object.get_size();
3966 object.truncate(size - fs.block_size()).await.expect("extend failed");
3967 let after = object.get_properties().await.expect("get_properties failed").allocated_size;
3968 assert_eq!(after, before - fs.block_size());
3969
3970 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
3972 let before = after;
3973 let mut file_range = offset..offset + fs.block_size();
3974 object.preallocate_range(&mut transaction, &mut file_range).await.expect("extend failed");
3975 transaction.commit().await.expect("commit failed");
3976 let after = object.get_properties().await.expect("get_properties failed").allocated_size;
3977 assert_eq!(after, before + fs.block_size());
3978 fs.close().await.expect("Close failed");
3979 }
3980
3981 #[fuchsia::test(threads = 10)]
3982 async fn test_zero() {
3983 let (fs, object) = test_filesystem_and_object().await;
3984 let expected_size = object.get_size();
3985 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
3986 object.zero(&mut transaction, 0..fs.block_size() * 10).await.expect("zero failed");
3987 transaction.commit().await.expect("commit failed");
3988 assert_eq!(object.get_size(), expected_size);
3989 let mut buf = object.allocate_buffer((fs.block_size() * 10) as usize).await;
3990 assert_eq!(object.read(0, buf.as_mut()).await.expect("read failed") as u64, expected_size);
3991 assert_eq!(
3992 &buf.as_ptr_slice().subslice(0..expected_size as usize).to_vec()[..],
3993 vec![0u8; expected_size as usize].as_slice()
3994 );
3995 fs.close().await.expect("Close failed");
3996 }
3997
3998 #[fuchsia::test]
3999 async fn test_properties() {
4000 let (fs, object) = test_filesystem_and_object().await;
4001 const CRTIME: Timestamp = Timestamp::from_nanos(1234);
4002 const MTIME: Timestamp = Timestamp::from_nanos(5678);
4003 const CTIME: Timestamp = Timestamp::from_nanos(8765);
4004
4005 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
4008 object
4009 .update_attributes(
4010 &mut transaction,
4011 Some(&fio::MutableNodeAttributes {
4012 creation_time: Some(CRTIME.as_nanos()),
4013 modification_time: Some(MTIME.as_nanos()),
4014 mode: Some(111),
4015 gid: Some(222),
4016 ..Default::default()
4017 }),
4018 None,
4019 )
4020 .await
4021 .expect("update_attributes failed");
4022 const MTIME_NEW: Timestamp = Timestamp::from_nanos(12345678);
4023 object
4024 .update_attributes(
4025 &mut transaction,
4026 Some(&fio::MutableNodeAttributes {
4027 modification_time: Some(MTIME_NEW.as_nanos()),
4028 gid: Some(333),
4029 rdev: Some(444),
4030 ..Default::default()
4031 }),
4032 Some(CTIME),
4033 )
4034 .await
4035 .expect("update_timestamps failed");
4036 transaction.commit().await.expect("commit failed");
4037
4038 let properties = object.get_properties().await.expect("get_properties failed");
4039 assert_matches!(
4040 properties,
4041 ObjectProperties {
4042 refs: 1u64,
4043 allocated_size: TEST_OBJECT_ALLOCATED_SIZE,
4044 data_attribute_size: TEST_OBJECT_SIZE,
4045 creation_time: CRTIME,
4046 modification_time: MTIME_NEW,
4047 posix_attributes: Some(PosixAttributes { mode: 111, gid: 333, rdev: 444, .. }),
4048 change_time: CTIME,
4049 ..
4050 }
4051 );
4052 fs.close().await.expect("Close failed");
4053 }
4054
4055 #[fuchsia::test]
4056 async fn test_is_allocated() {
4057 let (fs, object) = test_filesystem_and_object().await;
4058
4059 let aligned_offset = fs.block_size().align_down(TEST_DATA_OFFSET);
4062 let aligned_length = fs.block_size().align_up(TEST_DATA.len() as u64).unwrap();
4063
4064 let (allocated, count) = object.is_allocated(0).await.expect("is_allocated failed");
4068 assert_eq!(count, aligned_offset);
4069 assert_eq!(allocated, false);
4070
4071 let (allocated, count) =
4072 object.is_allocated(aligned_offset).await.expect("is_allocated failed");
4073 assert_eq!(count, aligned_length);
4074 assert_eq!(allocated, true);
4075
4076 let end = aligned_offset + aligned_length;
4078 object
4079 .is_allocated(end)
4080 .await
4081 .expect_err("is_allocated should have returned ERR_OUT_OF_RANGE");
4082
4083 let size = 50 * fs.block_size();
4086 object.truncate(size).await.expect("extend failed");
4087
4088 let (allocated, count) = object.is_allocated(end).await.expect("is_allocated failed");
4089 assert_eq!(count, size - end);
4090 assert_eq!(allocated, false);
4091
4092 let buf_length = 5 * fs.block_size();
4095 let mut buf = object.allocate_buffer(buf_length as usize).await;
4096 buf.fill(123);
4097 let new_offset = end + 20 * fs.block_size();
4098 object.write_or_append(Some(new_offset), buf.as_ref()).await.expect("write failed");
4099 object
4100 .write_or_append(Some(new_offset + buf_length), buf.as_ref())
4101 .await
4102 .expect("write failed");
4103
4104 let (allocated, count) = object.is_allocated(end).await.expect("is_allocated failed");
4105 assert_eq!(count, new_offset - end);
4106 assert_eq!(allocated, false);
4107
4108 let (allocated, count) =
4109 object.is_allocated(new_offset).await.expect("is_allocated failed");
4110 assert_eq!(count, 2 * buf_length);
4111 assert_eq!(allocated, true);
4112
4113 let (allocated, count) = object
4115 .is_allocated(new_offset + 4 * fs.block_size())
4116 .await
4117 .expect("is_allocated failed");
4118 assert_eq!(count, 2 * buf_length - 4 * fs.block_size());
4119 assert_eq!(allocated, true);
4120
4121 let other_buf_length = 3 * fs.block_size();
4125 let mut other_buf = object.allocate_buffer(other_buf_length as usize).await;
4126 other_buf.fill(231);
4127 object.write_or_append(Some(new_offset), other_buf.as_ref()).await.expect("write failed");
4128
4129 let (allocated, count) =
4132 object.is_allocated(new_offset).await.expect("is_allocated failed");
4133 assert_eq!(count, 2 * buf_length);
4134 assert_eq!(allocated, true);
4135
4136 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
4140 object
4141 .zero(&mut transaction, aligned_offset..aligned_offset + aligned_length)
4142 .await
4143 .expect("zero failed");
4144 object
4146 .zero(&mut transaction, new_offset..new_offset + buf_length)
4147 .await
4148 .expect("zero failed");
4149 transaction.commit().await.expect("commit transaction failed");
4150
4151 let (allocated, count) = object.is_allocated(0).await.expect("is_allocated failed");
4152 assert_eq!(count, new_offset + buf_length);
4153 assert_eq!(allocated, false);
4154
4155 let (allocated, count) =
4156 object.is_allocated(new_offset + buf_length).await.expect("is_allocated failed");
4157 assert_eq!(count, buf_length);
4158 assert_eq!(allocated, true);
4159
4160 let new_end = new_offset + buf_length + count;
4161
4162 let store = object.owner();
4166 let mut transaction = fs
4167 .root_store()
4168 .new_transaction(lock_keys![], Options::default())
4169 .await
4170 .expect("new_transaction failed");
4171 let object2 =
4172 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
4173 .await
4174 .expect("create_object failed");
4175 transaction.commit().await.expect("commit failed");
4176
4177 object2
4178 .write_or_append(Some(new_end + fs.block_size()), buf.as_ref())
4179 .await
4180 .expect("write failed");
4181
4182 let (allocated, count) = object.is_allocated(new_end).await.expect("is_allocated failed");
4184 assert_eq!(count, size - new_end);
4185 assert_eq!(allocated, false);
4186
4187 fs.close().await.expect("close failed");
4188 }
4189
4190 #[fuchsia::test(threads = 10)]
4191 async fn test_read_write_attr() {
4192 let (_fs, object) = test_filesystem_and_object().await;
4193 let data = [0xffu8; 16_384];
4194 object.write_attr(AttributeId(20), &data).await.expect("write_attr failed");
4195 let rdata = object
4196 .read_attr(AttributeId(20))
4197 .await
4198 .expect("read_attr failed")
4199 .expect("no attribute data found");
4200 assert_eq!(&data[..], &rdata[..]);
4201
4202 assert_eq!(object.read_attr(AttributeId(21)).await.expect("read_attr failed"), None);
4203 }
4204
4205 #[fuchsia::test(threads = 10)]
4206 async fn test_allocate_basic() {
4207 let (fs, object) = test_filesystem_and_empty_object().await;
4208 let block_size = fs.block_size();
4209 let file_size = block_size * 10;
4210 object.truncate(file_size).await.unwrap();
4211
4212 let small_buf_size = 1024;
4213 let large_buf_aligned_size = (block_size * 2) as usize;
4214 let large_buf_size = (block_size * 2 + 1024) as usize;
4215
4216 let mut small_buf = object.allocate_buffer(small_buf_size).await;
4217 let mut large_buf_aligned = object.allocate_buffer(large_buf_aligned_size).await;
4218 let mut large_buf = object.allocate_buffer(large_buf_size).await;
4219
4220 assert_eq!(object.read(0, small_buf.as_mut()).await.unwrap(), small_buf_size);
4221 assert_eq!(small_buf.to_vec(), vec![0; small_buf_size]);
4222 assert_eq!(object.read(0, large_buf.as_mut()).await.unwrap(), large_buf_size);
4223 assert_eq!(large_buf.to_vec(), vec![0; large_buf_size]);
4224 assert_eq!(
4225 object.read(0, large_buf_aligned.as_mut()).await.unwrap(),
4226 large_buf_aligned_size
4227 );
4228 assert_eq!(large_buf_aligned.to_vec(), vec![0; large_buf_aligned_size]);
4229
4230 object.allocate(block_size.get()..block_size * 3).await.unwrap();
4232
4233 for (buf_index, buf) in [small_buf, large_buf, large_buf_aligned].iter_mut().enumerate() {
4235 for offset in 0..4 {
4236 assert_eq!(
4237 object.read(block_size * offset, buf.as_mut()).await.unwrap(),
4238 buf.len(),
4239 "buf_index: {}, read offset: {}",
4240 buf_index,
4241 offset,
4242 );
4243 assert_eq!(
4244 &buf.to_vec(),
4245 &vec![0; buf.len()],
4246 "buf_index: {}, read offset: {}",
4247 buf_index,
4248 offset,
4249 );
4250 }
4251 }
4252
4253 fs.close().await.expect("close failed");
4254 }
4255
4256 #[fuchsia::test(threads = 10)]
4257 async fn test_allocate_extends_file() {
4258 const BUF_SIZE: usize = 1024;
4259 let (fs, object) = test_filesystem_and_empty_object().await;
4260 let mut buf = object.allocate_buffer(BUF_SIZE).await;
4261 let block_size = fs.block_size();
4262
4263 assert_eq!(object.read(0, buf.as_mut()).await.unwrap(), buf.len());
4264 assert_eq!(buf.to_vec(), &[0; BUF_SIZE]);
4265
4266 assert!(TEST_OBJECT_SIZE < block_size * 4);
4267 object.allocate(0..block_size * 4).await.unwrap();
4269 assert_eq!(object.read(0, buf.as_mut()).await.unwrap(), buf.len());
4270 assert_eq!(buf.to_vec(), &[0; BUF_SIZE]);
4271 assert_eq!(object.read(block_size.get(), buf.as_mut()).await.unwrap(), buf.len());
4272 assert_eq!(buf.to_vec(), &[0; BUF_SIZE]);
4273 assert_eq!(object.read(block_size * 3, buf.as_mut()).await.unwrap(), buf.len());
4274 assert_eq!(buf.to_vec(), &[0; BUF_SIZE]);
4275
4276 fs.close().await.expect("close failed");
4277 }
4278
4279 #[fuchsia::test(threads = 10)]
4280 async fn test_allocate_past_end() {
4281 const BUF_SIZE: usize = 1024;
4282 let (fs, object) = test_filesystem_and_empty_object().await;
4283 let mut buf = object.allocate_buffer(BUF_SIZE).await;
4284 let block_size = fs.block_size();
4285
4286 assert_eq!(object.read(0, buf.as_mut()).await.unwrap(), buf.len());
4287 assert_eq!(buf.to_vec(), &[0; BUF_SIZE]);
4288
4289 assert!(TEST_OBJECT_SIZE < block_size * 4);
4290 object.allocate(block_size * 4..block_size * 6).await.unwrap();
4292 assert_eq!(object.read(0, buf.as_mut()).await.unwrap(), buf.len());
4293 assert_eq!(buf.to_vec(), &[0; BUF_SIZE]);
4294 assert_eq!(object.read(block_size * 4, buf.as_mut()).await.unwrap(), buf.len());
4295 assert_eq!(buf.to_vec(), &[0; BUF_SIZE]);
4296 assert_eq!(object.read(block_size * 5, buf.as_mut()).await.unwrap(), buf.len());
4297 assert_eq!(buf.to_vec(), &[0; BUF_SIZE]);
4298
4299 fs.close().await.expect("close failed");
4300 }
4301
4302 #[fuchsia::test(threads = 10)]
4303 async fn test_allocate_read_attr() {
4304 let (fs, object) = test_filesystem_and_empty_object().await;
4305 let block_size = fs.block_size();
4306 let file_size = block_size * 4;
4307 object.truncate(file_size).await.unwrap();
4308
4309 let content = object
4310 .read_attr(object.attribute_id())
4311 .await
4312 .expect("failed to read attr")
4313 .expect("attr returned none");
4314 assert_eq!(content.as_ref(), &vec![0; file_size as usize]);
4315
4316 object.allocate(block_size.get()..block_size * 3).await.unwrap();
4317
4318 let content = object
4319 .read_attr(object.attribute_id())
4320 .await
4321 .expect("failed to read attr")
4322 .expect("attr returned none");
4323 assert_eq!(content.as_ref(), &vec![0; file_size as usize]);
4324
4325 fs.close().await.expect("close failed");
4326 }
4327
4328 #[fuchsia::test(threads = 10)]
4329 async fn test_allocate_existing_data() {
4330 struct Case {
4331 written_ranges: Vec<Range<usize>>,
4332 allocate_range: Range<u64>,
4333 }
4334 let cases = [
4335 Case { written_ranges: vec![4..7], allocate_range: 4..7 },
4336 Case { written_ranges: vec![4..7], allocate_range: 3..8 },
4337 Case { written_ranges: vec![4..7], allocate_range: 5..6 },
4338 Case { written_ranges: vec![4..7], allocate_range: 5..8 },
4339 Case { written_ranges: vec![4..7], allocate_range: 3..5 },
4340 Case { written_ranges: vec![0..1, 2..3, 4..5, 6..7, 8..9], allocate_range: 0..10 },
4341 Case { written_ranges: vec![0..2, 4..6, 7..10], allocate_range: 1..8 },
4342 ];
4343
4344 for case in cases {
4345 let (fs, object) = test_filesystem_and_empty_object().await;
4346 let block_size = fs.block_size();
4347 let file_size = block_size * 10;
4348 object.truncate(file_size).await.unwrap();
4349
4350 for write in &case.written_ranges {
4351 let write_len = (write.end - write.start) * block_size.get() as usize;
4352 let mut write_buf = object.allocate_buffer(write_len).await;
4353 write_buf.fill(0xff);
4354 assert_eq!(
4355 object
4356 .write_or_append(Some(block_size * write.start as u64), write_buf.as_ref())
4357 .await
4358 .unwrap(),
4359 file_size
4360 );
4361 }
4362
4363 let mut expected_buf = object.allocate_buffer(file_size as usize).await;
4364 assert_eq!(object.read(0, expected_buf.as_mut()).await.unwrap(), expected_buf.len());
4365
4366 object
4367 .allocate(
4368 case.allocate_range.start * block_size..case.allocate_range.end * block_size,
4369 )
4370 .await
4371 .unwrap();
4372
4373 let mut read_buf = object.allocate_buffer(file_size as usize).await;
4374 assert_eq!(object.read(0, read_buf.as_mut()).await.unwrap(), read_buf.len());
4375 assert_eq!(read_buf.to_vec(), expected_buf.to_vec());
4376
4377 fs.close().await.expect("close failed");
4378 }
4379 }
4380
4381 async fn get_modes(
4382 obj: &DataObjectHandle<ObjectStore>,
4383 mut search_range: Range<u64>,
4384 ) -> Vec<(Range<u64>, ExtentMode)> {
4385 let mut modes = Vec::new();
4386 let store = obj.store();
4387 let tree = store.tree();
4388 let layer_set = tree.layer_set();
4389 let mut merger = layer_set.merger();
4390 let mut iter = merger
4391 .query(Query::FullRange(&ObjectKey::attribute(
4392 obj.object_id(),
4393 AttributeId::DATA,
4394 AttributeKey::Extent(Extent::search_key_from_offset(search_range.start)),
4395 )))
4396 .await
4397 .unwrap();
4398 loop {
4399 match iter.get() {
4400 Some(ItemRef {
4401 key:
4402 ObjectKey {
4403 object_id,
4404 data:
4405 ObjectKeyData::Attribute(
4406 AttributeId::DATA,
4407 AttributeKey::Extent(extent),
4408 ),
4409 },
4410 value: ObjectValue::Extent(ExtentValue::Some { mode, .. }),
4411 ..
4412 }) if *object_id == obj.object_id() => {
4413 if search_range.end <= extent.start {
4414 break;
4415 }
4416 let found_range = std::cmp::max(search_range.start, extent.start)
4417 ..std::cmp::min(search_range.end, extent.end);
4418 search_range.start = found_range.end;
4419 modes.push((found_range, mode.clone()));
4420 if search_range.start == search_range.end {
4421 break;
4422 }
4423 iter.advance().await.unwrap();
4424 }
4425 x => panic!("looking for extent record, found this {:?}", x),
4426 }
4427 }
4428 modes
4429 }
4430
4431 async fn assert_all_overwrite(
4432 obj: &DataObjectHandle<ObjectStore>,
4433 mut search_range: Range<u64>,
4434 ) {
4435 let modes = get_modes(obj, search_range.clone()).await;
4436 for mode in modes {
4437 assert_eq!(
4438 mode.0.start, search_range.start,
4439 "missing mode in range {}..{}",
4440 search_range.start, mode.0.start
4441 );
4442 match mode.1 {
4443 ExtentMode::Overwrite | ExtentMode::OverwritePartial(_) => (),
4444 m => panic!("mode at range {:?} was not overwrite, instead found {:?}", mode.0, m),
4445 }
4446 assert!(
4447 mode.0.end <= search_range.end,
4448 "mode ends beyond search range (bug in test) - search_range: {:?}, mode: {:?}",
4449 search_range,
4450 mode,
4451 );
4452 search_range.start = mode.0.end;
4453 }
4454 assert_eq!(
4455 search_range.start, search_range.end,
4456 "missing mode in range {:?}",
4457 search_range
4458 );
4459 }
4460
4461 #[fuchsia::test(threads = 10)]
4462 async fn test_multi_overwrite() {
4463 #[derive(Debug)]
4464 struct Case {
4465 pre_writes: Vec<Range<usize>>,
4466 allocate_ranges: Vec<Range<u64>>,
4467 overwrites: Vec<Vec<Range<u64>>>,
4468 }
4469 let cases = [
4470 Case {
4471 pre_writes: Vec::new(),
4472 allocate_ranges: vec![1..3],
4473 overwrites: vec![vec![1..3]],
4474 },
4475 Case {
4476 pre_writes: Vec::new(),
4477 allocate_ranges: vec![0..1, 1..2, 2..3, 3..4],
4478 overwrites: vec![vec![0..4]],
4479 },
4480 Case {
4481 pre_writes: Vec::new(),
4482 allocate_ranges: vec![0..4],
4483 overwrites: vec![vec![0..1], vec![1..2], vec![3..4]],
4484 },
4485 Case {
4486 pre_writes: Vec::new(),
4487 allocate_ranges: vec![0..4],
4488 overwrites: vec![vec![3..4]],
4489 },
4490 Case {
4491 pre_writes: Vec::new(),
4492 allocate_ranges: vec![0..4],
4493 overwrites: vec![vec![3..4], vec![2..3], vec![1..2]],
4494 },
4495 Case {
4496 pre_writes: Vec::new(),
4497 allocate_ranges: vec![1..2, 5..6, 7..8],
4498 overwrites: vec![vec![5..6]],
4499 },
4500 Case {
4501 pre_writes: Vec::new(),
4502 allocate_ranges: vec![1..3],
4503 overwrites: vec![
4504 vec![1..3],
4505 vec![1..3],
4506 vec![1..3],
4507 vec![1..3],
4508 vec![1..3],
4509 vec![1..3],
4510 vec![1..3],
4511 vec![1..3],
4512 ],
4513 },
4514 Case {
4515 pre_writes: Vec::new(),
4516 allocate_ranges: vec![0..5],
4517 overwrites: vec![
4518 vec![1..3],
4519 vec![1..3],
4520 vec![1..3],
4521 vec![1..3],
4522 vec![1..3],
4523 vec![1..3],
4524 vec![1..3],
4525 vec![1..3],
4526 ],
4527 },
4528 Case {
4529 pre_writes: Vec::new(),
4530 allocate_ranges: vec![0..5],
4531 overwrites: vec![vec![0..2, 2..4, 4..5]],
4532 },
4533 Case {
4534 pre_writes: Vec::new(),
4535 allocate_ranges: vec![0..5, 5..10],
4536 overwrites: vec![vec![1..2, 2..3, 4..7, 7..8]],
4537 },
4538 Case {
4539 pre_writes: Vec::new(),
4540 allocate_ranges: vec![0..4, 6..10],
4541 overwrites: vec![vec![2..3, 7..9]],
4542 },
4543 Case {
4544 pre_writes: Vec::new(),
4545 allocate_ranges: vec![0..10],
4546 overwrites: vec![vec![1..2, 5..10], vec![0..1, 5..10], vec![0..5, 5..10]],
4547 },
4548 Case {
4549 pre_writes: Vec::new(),
4550 allocate_ranges: vec![0..10],
4551 overwrites: vec![vec![0..2, 2..4, 4..6, 6..8, 8..10], vec![0..5, 5..10]],
4552 },
4553 Case {
4554 pre_writes: vec![1..3],
4555 allocate_ranges: vec![1..3],
4556 overwrites: vec![vec![1..3]],
4557 },
4558 Case {
4559 pre_writes: vec![1..3],
4560 allocate_ranges: vec![4..6],
4561 overwrites: vec![vec![5..6]],
4562 },
4563 Case {
4564 pre_writes: vec![1..3],
4565 allocate_ranges: vec![0..4],
4566 overwrites: vec![vec![0..4]],
4567 },
4568 Case {
4569 pre_writes: vec![1..3],
4570 allocate_ranges: vec![2..4],
4571 overwrites: vec![vec![2..4]],
4572 },
4573 Case {
4574 pre_writes: vec![3..5],
4575 allocate_ranges: vec![1..3, 6..7],
4576 overwrites: vec![vec![1..3, 6..7]],
4577 },
4578 Case {
4579 pre_writes: vec![1..3, 5..7, 8..9],
4580 allocate_ranges: vec![0..5],
4581 overwrites: vec![vec![0..2, 2..5], vec![0..5]],
4582 },
4583 Case {
4584 pre_writes: Vec::new(),
4585 allocate_ranges: vec![0..10, 4..6],
4586 overwrites: Vec::new(),
4587 },
4588 Case {
4589 pre_writes: Vec::new(),
4590 allocate_ranges: vec![3..8, 5..10],
4591 overwrites: Vec::new(),
4592 },
4593 Case {
4594 pre_writes: Vec::new(),
4595 allocate_ranges: vec![5..10, 3..8],
4596 overwrites: Vec::new(),
4597 },
4598 ];
4599
4600 for (i, case) in cases.into_iter().enumerate() {
4601 log::info!("running case {} - {:?}", i, case);
4602 let (fs, object) = test_filesystem_and_empty_object().await;
4603 let block_size = fs.block_size();
4604 let file_size = block_size * 10;
4605 object.truncate(file_size).await.unwrap();
4606
4607 for write in case.pre_writes {
4608 let write_len = (write.end - write.start) * block_size.get() as usize;
4609 let mut write_buf = object.allocate_buffer(write_len).await;
4610 write_buf.fill(0xff);
4611 assert_eq!(
4612 object
4613 .write_or_append(Some(block_size * write.start as u64), write_buf.as_ref())
4614 .await
4615 .unwrap(),
4616 file_size
4617 );
4618 }
4619
4620 for allocate_range in &case.allocate_ranges {
4621 object
4622 .allocate(allocate_range.start * block_size..allocate_range.end * block_size)
4623 .await
4624 .unwrap();
4625 }
4626
4627 for allocate_range in case.allocate_ranges {
4628 assert_all_overwrite(
4629 &object,
4630 allocate_range.start * block_size..allocate_range.end * block_size,
4631 )
4632 .await;
4633 }
4634
4635 for overwrite in case.overwrites {
4636 let mut write_len = 0;
4637 let overwrite = overwrite
4638 .into_iter()
4639 .map(|r| {
4640 write_len += (r.end - r.start) * block_size;
4641 r.start * block_size..r.end * block_size
4642 })
4643 .collect::<Vec<_>>();
4644 let mut write_buf = object.allocate_buffer(write_len as usize).await;
4645 let data = (0..20).cycle().take(write_len as usize).collect::<Vec<_>>();
4646 write_buf.copy_from_slice(&data);
4647
4648 let mut expected_buf = object.allocate_buffer(file_size as usize).await;
4649 assert_eq!(
4650 object.read(0, expected_buf.as_mut()).await.unwrap(),
4651 expected_buf.len()
4652 );
4653 let mut expected_buf_slice = expected_buf.as_mut_ptr_slice();
4654 let mut data_slice = data.as_slice();
4655 for r in &overwrite {
4656 let len = r.length().unwrap() as usize;
4657 let (copy_from, rest) = data_slice.split_at(len);
4658 expected_buf_slice
4659 .subslice_mut(r.start as usize..r.end as usize)
4660 .copy_from_slice(©_from);
4661 data_slice = rest;
4662 }
4663
4664 let mut transaction = object.new_transaction().await.unwrap();
4665 object
4666 .multi_overwrite(
4667 &mut transaction,
4668 AttributeId::DATA,
4669 &overwrite,
4670 write_buf.as_mut(),
4671 )
4672 .await
4673 .unwrap_or_else(|_| panic!("multi_overwrite error on case {}", i));
4674 let mut checksummed_range_length = 0;
4677 let mut num_checksums = 0;
4678 for (device_range, checksums, _) in transaction.checksums() {
4679 let range_len = device_range.end - device_range.start;
4680 let checksums_len = checksums.len() as u64;
4681 assert_eq!(range_len / checksums_len, block_size);
4682 checksummed_range_length += range_len;
4683 num_checksums += checksums_len;
4684 }
4685 assert_eq!(checksummed_range_length, write_len);
4686 assert_eq!(num_checksums, write_len / block_size);
4687 transaction.commit().await.unwrap();
4688
4689 let mut buf = object.allocate_buffer(file_size as usize).await;
4690 assert_eq!(
4691 object.read(0, buf.as_mut()).await.unwrap(),
4692 buf.len(),
4693 "failed length check on case {}",
4694 i,
4695 );
4696 assert_eq!(buf.to_vec(), expected_buf.to_vec(), "failed on case {}", i);
4697 }
4698
4699 fsck_volume(&fs, object.store().store_object_id(), None).await.expect("fsck failed");
4700 fs.close().await.expect("close failed");
4701 }
4702 }
4703
4704 #[fuchsia::test(threads = 10)]
4705 async fn test_multi_overwrite_mode_updates() {
4706 let (fs, object) = test_filesystem_and_empty_object().await;
4707 let block_size = fs.block_size();
4708 let file_size = block_size * 10;
4709 object.truncate(file_size).await.unwrap();
4710
4711 let mut expected_bitmap = BitVec::from_elem(10, false);
4712
4713 object.allocate(0..10 * block_size).await.unwrap();
4714 assert_eq!(
4715 get_modes(&object, 0..10 * block_size).await,
4716 vec![(0..10 * block_size, ExtentMode::OverwritePartial(expected_bitmap.clone()))]
4717 );
4718
4719 let mut write_buf = object.allocate_buffer((2 * block_size) as usize).await;
4720 let data = (0..20).cycle().take(write_buf.len()).collect::<Vec<_>>();
4721 write_buf.copy_from_slice(&data);
4722 let mut transaction = object.new_transaction().await.unwrap();
4723 object
4724 .multi_overwrite(
4725 &mut transaction,
4726 AttributeId::DATA,
4727 &[2 * block_size..4 * block_size],
4728 write_buf.as_mut(),
4729 )
4730 .await
4731 .unwrap();
4732 transaction.commit().await.unwrap();
4733
4734 expected_bitmap.set(2, true);
4735 expected_bitmap.set(3, true);
4736 assert_eq!(
4737 get_modes(&object, 0..10 * block_size).await,
4738 vec![(0..10 * block_size, ExtentMode::OverwritePartial(expected_bitmap.clone()))]
4739 );
4740
4741 let mut write_buf = object.allocate_buffer((3 * block_size) as usize).await;
4742 let data = (0..20).cycle().take(write_buf.len()).collect::<Vec<_>>();
4743 write_buf.copy_from_slice(&data);
4744 let mut transaction = object.new_transaction().await.unwrap();
4745 object
4746 .multi_overwrite(
4747 &mut transaction,
4748 AttributeId::DATA,
4749 &[3 * block_size..5 * block_size, 6 * block_size..7 * block_size],
4750 write_buf.as_mut(),
4751 )
4752 .await
4753 .unwrap();
4754 transaction.commit().await.unwrap();
4755
4756 expected_bitmap.set(4, true);
4757 expected_bitmap.set(6, true);
4758 assert_eq!(
4759 get_modes(&object, 0..10 * block_size).await,
4760 vec![(0..10 * block_size, ExtentMode::OverwritePartial(expected_bitmap.clone()))]
4761 );
4762
4763 let mut write_buf = object.allocate_buffer((6 * block_size) as usize).await;
4764 let data = (0..20).cycle().take(write_buf.len()).collect::<Vec<_>>();
4765 write_buf.copy_from_slice(&data);
4766 let mut transaction = object.new_transaction().await.unwrap();
4767 object
4768 .multi_overwrite(
4769 &mut transaction,
4770 AttributeId::DATA,
4771 &[
4772 0..2 * block_size,
4773 5 * block_size..6 * block_size,
4774 7 * block_size..10 * block_size,
4775 ],
4776 write_buf.as_mut(),
4777 )
4778 .await
4779 .unwrap();
4780 transaction.commit().await.unwrap();
4781
4782 assert_eq!(
4783 get_modes(&object, 0..10 * block_size).await,
4784 vec![(0..10 * block_size, ExtentMode::Overwrite)]
4785 );
4786
4787 fs.close().await.expect("close failed");
4788 }
4789
4790 #[fuchsia::test(threads = 10)]
4791 async fn test_check_unwritten_zero() {
4792 let device = DeviceHolder::new(FakeDevice::new(256 * 1024, TEST_DEVICE_BLOCK_SIZE));
4793 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
4794 let object = create_object_with_key(fs.clone(), Some(&new_insecure_crypt()), false).await;
4795 let block_size = fs.block_size();
4796
4797 let file_size = block_size * 7;
4800 object.truncate(file_size).await.unwrap();
4801 assert!(object.check_unwritten_zero(0..file_size).await.unwrap());
4802
4803 let mut buffer = object.allocate_buffer(block_size.get() as usize).await;
4804 buffer.fill(1);
4805 object
4806 .write_or_append(Some(block_size.get()), buffer.as_ref())
4807 .await
4808 .expect("write failed");
4809 object.write_or_append(Some(block_size * 2), buffer.as_ref()).await.expect("write failed");
4810
4811 object.allocate((block_size * 4)..(block_size * 6)).await.expect("Allocate failed");
4812 let mut transaction = fs
4813 .root_store()
4814 .new_transaction(
4815 lock_keys![LockKey::object(object.store().store_object_id(), object.object_id(),)],
4816 Options::default(),
4817 )
4818 .await
4819 .expect("new_transaction failed");
4820 object
4821 .multi_overwrite(
4822 &mut transaction,
4823 AttributeId::DATA,
4824 &vec![(block_size * 5)..(block_size * 6)],
4825 buffer.as_mut(),
4826 )
4827 .await
4828 .expect("Multi overwrite");
4829 transaction.commit().await.expect("Committing overwrite");
4830
4831 assert!(!object.check_unwritten_zero(0..(block_size * 2)).await.unwrap());
4833 assert!(!object.check_unwritten_zero(block_size.get()..(block_size * 3)).await.unwrap());
4834 assert!(!object.check_unwritten_zero((block_size * 2)..(block_size * 4)).await.unwrap());
4835
4836 assert!(object.check_unwritten_zero((block_size * 3)..(block_size * 5)).await.unwrap());
4838
4839 assert!(!object.check_unwritten_zero((block_size * 4)..(block_size * 6)).await.unwrap());
4841 assert!(!object.check_unwritten_zero((block_size * 5)..(block_size * 7)).await.unwrap());
4842
4843 fs.close().await.expect("close failed");
4844 }
4845}