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 ReadGuard, ReservationOptions, 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 let read = self
313 .handle
314 .read_aligned(AttributeId::FSVERITY_MERKLE, verity_range.start, buffer.as_mut())
315 .await?;
316 ensure!(expected_length == read, FxfsError::Inconsistent);
317 let data = buffer.as_ptr_slice().subslice(0..expected_length);
318 FsverityStateInner::from_ptr_slice(data, self.block_size())?
319 }
320 };
321 ensure!(metadata.merkle_tree.len() % hasher.hash_size() == 0, FxfsError::Inconsistent);
323 let leaf_chunks = metadata.merkle_tree.chunks_exact(hasher.hash_size());
324
325 let root_hash = match &metadata.root_digest {
326 RootDigest::Sha256(root_hash) => root_hash.as_slice(),
327 RootDigest::Sha512(root_hash) => root_hash.as_slice(),
328 };
329
330 let tree = match hasher {
331 FsVerityHasher::Sha256(_) => {
332 let mut builder = MerkleTreeBuilder::<Sha256Hash>::new(hasher);
333 for leaf in leaf_chunks {
334 let hash = Sha256Hash::read_from_bytes(leaf).unwrap();
335 builder.push_data_hash(hash);
336 }
337 builder.finish()
338 }
339 FsVerityHasher::Sha512(_) => {
340 let mut builder = MerkleTreeBuilder::<Sha512Hash>::new(hasher);
341 for leaf in leaf_chunks {
342 let hash = Sha512Hash::read_from_bytes(leaf).unwrap();
343 builder.push_data_hash(hash);
344 }
345 builder.finish()
346 }
347 };
348
349 ensure!(root_hash == tree.root(), FxfsError::IntegrityError);
350
351 let mut state = self.state.lock();
352 assert!(matches!(*state, DataObjectState::Standard(_)));
353 *state = DataObjectState::Verity(metadata);
354
355 Ok(())
356 }
357
358 fn verify_data(&self, mut offset: usize, buffer: PtrByteSlice<'_>) -> Result<(), Error> {
366 let block_size = self.block_size();
367 assert!(block_size.is_aligned(offset as u64));
368 let state = self.state.lock();
369 match &*state {
370 DataObjectState::Standard(_) => {
371 Err(anyhow!("Tried to verify read on a non verity-enabled file"))
372 }
373 DataObjectState::VerityStarted | DataObjectState::VerityPending(_) => {
374 Err(anyhow!("Enable verity has not yet completed, state: {state:?}"))
375 }
376 DataObjectState::Verity(metadata) => {
377 let hasher = metadata.get_hasher_for_block_size(block_size);
378 let leaf_nodes: Vec<&[u8]> =
379 metadata.merkle_tree.chunks(hasher.hash_size()).collect();
380 fxfs_trace::duration!("fsverity-verify", "len" => buffer.len());
381 for chunk in buffer.chunks(block_size.get() as usize) {
383 let b = unsafe { &*chunk.as_raw_slice_ptr() };
387
388 ensure!(
389 hasher.hash_block(b) == leaf_nodes[((offset as u64) / block_size) as usize],
390 anyhow!(FxfsError::Inconsistent).context("Hash mismatch")
391 );
392 offset += block_size.get() as usize;
393 }
394 Ok(())
395 }
396 }
397 }
398
399 pub async fn extend<'a>(
402 &'a self,
403 transaction: &mut Transaction<'a>,
404 device_range: Range<u64>,
405 ) -> Result<(), Error> {
406 let old_end =
407 self.block_size().align_up(self.txn_get_size(transaction)).ok_or(FxfsError::TooBig)?;
408 let new_size = old_end + device_range.end - device_range.start;
409 self.store().allocator().mark_allocated(
410 transaction,
411 self.store().store_object_id(),
412 device_range.clone(),
413 )?;
414 self.txn_update_size(transaction, new_size, None).await?;
415 let key_id = self.get_key(None).await?.0;
416 transaction.add(
417 self.store().store_object_id,
418 Mutation::merge_object(
419 ObjectKey::extent(self.object_id(), self.attribute_id(), old_end..new_size),
420 ObjectValue::Extent(ExtentValue::new_raw(device_range.start, key_id)),
421 ),
422 );
423 self.update_allocated_size(transaction, device_range.end - device_range.start, 0).await
424 }
425
426 async fn align_buffer(
429 &self,
430 offset: u64,
431 buf: BufferRef<'_>,
432 ) -> Result<(std::ops::Range<u64>, Buffer<'_>), Error> {
433 self.handle.align_buffer(self.attribute_id(), offset, buf).await
434 }
435
436 async fn write_at(
442 &self,
443 offset: u64,
444 buf: MutableBufferRef<'_>,
445 device_offset: u64,
446 flags: WriteFlags,
447 ) -> Result<MaybeChecksums, Error> {
448 self.handle
449 .write_at_with_flags(self.attribute_id(), offset, buf, None, device_offset, flags)
450 .await
451 }
452
453 pub async fn check_unwritten_zero(&self, range: Range<u64>) -> Result<bool, Error> {
457 if range.is_empty() {
458 return Ok(true);
459 }
460 let tree = &self.store().tree();
461 let layer_set = tree.layer_set();
462 let key = Extent(range);
463 let query_key = ObjectKey::attribute(
464 self.object_id(),
465 self.attribute_id,
466 AttributeKey::Extent(key.clone()),
467 );
468 let mut merger = layer_set.merger();
469 let mut iter = merger.query(Query::LimitedRange(&query_key)).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 let Some(overlap) = key.overlap(extent_key) else {
483 break;
484 };
485 if let ExtentValue::Some { mode, .. } = value {
486 if let ExtentMode::OverwritePartial(bits) = mode {
487 let starting_index = (overlap.start - extent_key.start) / self.block_size();
488 for initialized in bits
489 .iter()
490 .skip(starting_index as usize)
491 .take((overlap.length().unwrap() / self.block_size()) as usize)
492 {
493 if initialized {
494 return Ok(false);
495 }
496 }
497 } else {
498 return Ok(false);
499 }
500 }
501 iter.advance().await?;
502 }
503 Ok(true)
504 }
505
506 pub async fn zero(
508 &self,
509 transaction: &mut Transaction<'_>,
510 range: Range<u64>,
511 ) -> Result<(), Error> {
512 self.handle.zero(transaction, self.attribute_id(), range).await
513 }
514
515 pub fn get_descriptor(&self) -> Option<(fio::VerificationOptions, Vec<u8>)> {
519 let state = self.state.lock();
520 match &*state {
521 DataObjectState::Verity(metadata) => {
522 let (options, root_hash) = match &metadata.root_digest {
523 RootDigest::Sha256(root_hash) => (
524 fio::VerificationOptions {
525 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
526 salt: Some(metadata.salt.clone()),
527 ..Default::default()
528 },
529 root_hash.to_vec(),
530 ),
531 RootDigest::Sha512(root_hash) => (
532 fio::VerificationOptions {
533 hash_algorithm: Some(fio::HashAlgorithm::Sha512),
534 salt: Some(metadata.salt.clone()),
535 ..Default::default()
536 },
537 root_hash.clone(),
538 ),
539 };
540 Some((options, root_hash))
541 }
542 _ => None,
543 }
544 }
545
546 async fn build_verity_tree(
547 &self,
548 hasher: FsVerityHasher,
549 hash_alg: fio::HashAlgorithm,
550 salt: &[u8],
551 ) -> Result<(MerkleTree, Vec<u8>), Error> {
552 match hasher {
553 FsVerityHasher::Sha256(_) => {
554 self.build_verity_tree_impl::<Sha256Hash>(hasher, hash_alg, salt).await
555 }
556 FsVerityHasher::Sha512(_) => {
557 self.build_verity_tree_impl::<Sha512Hash>(hasher, hash_alg, salt).await
558 }
559 }
560 }
561
562 async fn build_verity_tree_impl<D: FsVerityHash>(
563 &self,
564 hasher: FsVerityHasher,
565 hash_alg: fio::HashAlgorithm,
566 salt: &[u8],
567 ) -> Result<(MerkleTree, Vec<u8>), Error> {
568 let hash_len = hasher.hash_size();
569 let mut builder = MerkleTreeBuilder::<D>::new(hasher);
570 let mut offset = 0;
571 let size = self.get_size();
572 let mut buf = self.allocate_buffer(64 * self.block_size().get() as usize).await;
575 while offset < size {
576 let read = self.read_aligned(offset, buf.as_mut()).await? as u64;
578 assert!(offset + read <= size);
579 let slice = buf.as_ptr_slice().subslice(0..read as usize);
580
581 let chunk = unsafe { &*slice.as_raw_slice_ptr() };
585
586 builder.write(chunk);
587 offset += read;
588 }
589 let tree = builder.finish();
590 let tree_data_len = tree
592 .levels()
593 .iter()
594 .map(|layer| self.block_size().align_up(layer.len() as u64).unwrap() as usize)
595 .sum();
596 let mut merkle_tree_data = Vec::<u8>::with_capacity(tree_data_len);
597 for layer in tree.levels().iter().rev() {
599 if layer.len() <= hash_len {
601 continue;
602 }
603 merkle_tree_data.extend_from_slice(layer);
604 let padded_size =
606 self.block_size().align_up(merkle_tree_data.len() as u64).unwrap() as usize;
607 merkle_tree_data.resize(padded_size, 0);
608 }
609
610 let descriptor_offset = merkle_tree_data.len();
612 merkle_tree_data.resize(descriptor_offset + self.block_size().get() as usize, 0);
613 let descriptor = FsVerityDescriptorRaw::new(
614 hash_alg,
615 self.block_size().get(),
616 self.get_size(),
617 tree.root(),
618 salt,
619 )?;
620 descriptor.write_to_slice(&mut merkle_tree_data[descriptor_offset..])?;
621
622 Ok((tree, merkle_tree_data))
623 }
624
625 #[trace]
632 pub async fn enable_verity(&self, options: fio::VerificationOptions) -> Result<(), Error> {
633 self.set_fsverity_state_started()?;
634 if self
637 .store()
638 .tree()
639 .exists(&ObjectKey::graveyard_attribute_entry(
640 self.store().graveyard_directory_object_id(),
641 self.object_id(),
642 AttributeId::FSVERITY_MERKLE,
643 ))
644 .await?
645 {
646 self.store().filesystem().ensure_local().graveyard().flush().await;
647 }
648 let mut transaction = self.new_transaction().await?;
649 let hash_alg =
650 options.hash_algorithm.ok_or_else(|| anyhow!("No hash algorithm provided"))?;
651 let salt = options.salt.ok_or_else(|| anyhow!("No salt provided"))?;
652 let (root_digest, merkle_tree) = match hash_alg {
653 fio::HashAlgorithm::Sha256 => {
654 let hasher = FsVerityHasher::Sha256(FsVerityHasherOptions::new(
655 salt.clone(),
656 self.block_size().get() as usize,
657 ));
658 let (tree, merkle_tree_data) =
659 self.build_verity_tree(hasher, hash_alg, &salt).await?;
660 let root: [u8; 32] = tree.root().try_into().unwrap();
661 (RootDigest::Sha256(root), merkle_tree_data)
662 }
663 fio::HashAlgorithm::Sha512 => {
664 let hasher = FsVerityHasher::Sha512(FsVerityHasherOptions::new(
665 salt.clone(),
666 self.block_size().get() as usize,
667 ));
668 let (tree, merkle_tree_data) =
669 self.build_verity_tree(hasher, hash_alg, &salt).await?;
670 (RootDigest::Sha512(tree.root().to_vec()), merkle_tree_data)
671 }
672 _ => {
673 bail!(
674 anyhow!(FxfsError::NotSupported)
675 .context(format!("hash algorithm not supported"))
676 );
677 }
678 };
679 self.handle
683 .write_new_attr(&mut transaction, AttributeId::FSVERITY_MERKLE, &merkle_tree)
684 .await?;
685 let descriptor_decoded =
686 FsVerityDescriptor::new(&merkle_tree[..], self.block_size().get() as usize)?;
687 let descriptor = FsverityStateInner {
688 root_digest,
689 salt,
690 merkle_tree: descriptor_decoded.leaf_digests()?.into(),
691 };
692 self.set_fsverity_state_pending(descriptor);
693 transaction.add_with_object(
694 self.store().store_object_id(),
695 Mutation::replace_or_insert_object(
696 ObjectKey::attribute(self.object_id(), AttributeId::DATA, AttributeKey::Attribute),
697 ObjectValue::verified_attribute(
698 self.get_size(),
699 FsverityMetadata::F2fs(0..merkle_tree.len() as u64),
700 ),
701 ),
702 AssocObj::Borrowed(self),
703 );
704 transaction.commit().await?;
705 Ok(())
706 }
707
708 pub async fn allocate(&self, range: Range<u64>) -> Result<(), Error> {
711 debug_assert!(range.start < range.end);
712
713 let mut new_range =
719 self.block_size().align_range_outwards(&range).ok_or(FxfsError::TooBig)?;
720
721 let mut transaction = self.new_transaction().await?;
722 {
729 let state = self.state.lock();
730 match &*state {
731 DataObjectState::Standard(_) => {}
732 _ => bail!(
733 anyhow!(FxfsError::AccessDenied).context("Cannot allocate on verity file")
734 ),
735 }
736 }
737 let mut to_allocate = Vec::new();
738 let mut to_switch = Vec::new();
739 let key_id = self.get_key(None).await?.0;
740
741 {
742 let tree = &self.store().tree;
743 let layer_set = tree.layer_set();
744 let offset_key =
745 ObjectKey::extent(self.object_id(), self.attribute_id(), new_range.clone());
746 let mut merger = layer_set.merger();
747 let mut iter = merger.query(Query::LimitedRange(&offset_key)).await?;
748
749 loop {
750 match iter.get() {
751 Some(ItemRef {
752 key:
753 ObjectKey {
754 object_id,
755 data:
756 ObjectKeyData::Attribute(
757 attribute_id,
758 AttributeKey::Extent(extent_key),
759 ),
760 },
761 value: ObjectValue::Extent(extent_value),
762 ..
763 }) if *object_id == self.object_id()
764 && *attribute_id == self.attribute_id() =>
765 {
766 if new_range.end <= extent_key.start {
769 break;
770 }
771 if new_range.start < extent_key.start {
773 to_allocate.push(new_range.start..extent_key.start);
774 new_range.start = extent_key.start;
775 }
776 let device_offset = match extent_value {
777 ExtentValue::None => {
778 iter.advance().await?;
783 continue;
784 }
785 ExtentValue::Some { mode: ExtentMode::OverwritePartial(_), .. }
786 | ExtentValue::Some { mode: ExtentMode::Overwrite, .. } => {
787 if extent_key.end < new_range.end {
789 new_range.start = extent_key.end;
790 iter.advance().await?;
791 continue;
792 } else {
793 new_range.start = new_range.end;
794 break;
795 }
796 }
797 ExtentValue::Some { device_offset, .. } => *device_offset,
798 };
799
800 let device_offset = device_offset + (new_range.start - extent_key.start);
802 if extent_key.end < new_range.end {
803 to_switch.push((new_range.start..extent_key.end, device_offset));
804 new_range.start = extent_key.end;
805 } else {
806 to_switch.push((new_range.start..new_range.end, device_offset));
807 new_range.start = new_range.end;
808 break;
809 }
810 }
811 _ => break,
815 }
816 iter.advance().await?;
817 }
818 }
819
820 if new_range.start < new_range.end {
821 to_allocate.push(new_range.clone());
822 }
823
824 let new_size = std::cmp::max(range.end, self.get_size());
833 transaction.add_with_object(
838 self.store().store_object_id(),
839 Mutation::replace_or_insert_object(
840 ObjectKey::attribute(
841 self.object_id(),
842 self.attribute_id(),
843 AttributeKey::Attribute,
844 ),
845 ObjectValue::Attribute { size: new_size, has_overwrite_extents: true },
846 ),
847 AssocObj::Borrowed(self),
848 );
849
850 const MAX_TRANSACTION_SIZE: usize = 256;
854 for (switch_range, device_offset) in to_switch {
855 transaction.add_with_object(
856 self.store().store_object_id(),
857 Mutation::merge_object(
858 ObjectKey::extent(self.object_id(), self.attribute_id(), switch_range),
859 ObjectValue::Extent(ExtentValue::initialized_overwrite_extent(
860 device_offset,
861 key_id,
862 )),
863 ),
864 AssocObj::Borrowed(self),
865 );
866 if transaction.mutations().len() >= MAX_TRANSACTION_SIZE {
867 transaction.commit_and_continue().await?;
868 }
869 }
870
871 let mut allocated = 0;
872 let allocator = self.store().allocator();
873 for mut allocate_range in to_allocate {
874 while allocate_range.start < allocate_range.end {
875 let device_range = allocator
876 .allocate(
877 &mut transaction,
878 self.store().store_object_id(),
879 allocate_range.end - allocate_range.start,
880 )
881 .await
882 .context("allocation failed")?;
883 let device_range_len = device_range.end - device_range.start;
884
885 transaction.add_with_object(
886 self.store().store_object_id(),
887 Mutation::merge_object(
888 ObjectKey::extent(
889 self.object_id(),
890 self.attribute_id(),
891 allocate_range.start..allocate_range.start + device_range_len,
892 ),
893 ObjectValue::Extent(ExtentValue::blank_overwrite_extent(
894 device_range.start,
895 (device_range_len / self.block_size()) as usize,
896 key_id,
897 )),
898 ),
899 AssocObj::Borrowed(self),
900 );
901
902 allocate_range.start += device_range_len;
903 allocated += device_range_len;
904
905 if transaction.mutations().len() >= MAX_TRANSACTION_SIZE {
906 self.update_allocated_size(&mut transaction, allocated, 0).await?;
907 transaction.commit_and_continue().await?;
908 allocated = 0;
909 }
910 }
911 }
912
913 self.update_allocated_size(&mut transaction, allocated, 0).await?;
914 transaction.commit().await?;
915
916 Ok(())
917 }
918
919 pub async fn is_allocated(&self, start_offset: u64) -> Result<(bool, u64), Error> {
925 let block_size = self.block_size();
926 assert_eq!(start_offset % block_size, 0);
927
928 if start_offset > self.get_size() {
929 bail!(FxfsError::OutOfRange)
930 }
931
932 if start_offset == self.get_size() {
933 return Ok((false, 0));
934 }
935
936 let tree = &self.store().tree;
937 let layer_set = tree.layer_set();
938 let offset_key = ObjectKey::attribute(
939 self.object_id(),
940 self.attribute_id(),
941 AttributeKey::Extent(Extent::search_key_from_offset(start_offset)),
942 );
943 let mut merger = layer_set.merger();
944 let mut iter = merger.query(Query::FullRange(&offset_key)).await?;
945
946 let mut allocated = None;
947 let mut end = start_offset;
948
949 loop {
950 match iter.get() {
953 Some(ItemRef {
954 key:
955 ObjectKey {
956 object_id,
957 data:
958 ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent_key)),
959 },
960 value: ObjectValue::Extent(extent_value),
961 ..
962 }) => {
963 if *object_id != self.object_id() || *attribute_id != self.attribute_id() {
965 if allocated == Some(false) || allocated.is_none() {
966 end = self.get_size();
967 allocated = Some(false);
968 }
969 break;
970 }
971 ensure!(block_size.is_aligned(extent_key), FxfsError::Inconsistent);
972 if extent_key.start > end {
973 if allocated == Some(true) {
977 break;
978 } else {
979 end = extent_key.start;
981 allocated = Some(false);
982 }
986 }
987
988 match extent_value {
991 ExtentValue::Some { .. } => {
993 if allocated == Some(false) {
995 break;
996 }
997 allocated = Some(true);
998 }
999 ExtentValue::None => {
1001 if allocated == Some(true) {
1003 break;
1004 }
1005 allocated = Some(false);
1006 }
1007 }
1008 end = extent_key.end;
1009 }
1010 None => {
1012 if allocated == Some(false) || allocated.is_none() {
1013 end = self.get_size();
1014 allocated = Some(false);
1015 }
1016 break;
1018 }
1019 Some(_) => {}
1021 }
1022 iter.advance().await?;
1023 }
1024
1025 Ok((allocated.unwrap(), end - start_offset))
1026 }
1027
1028 pub async fn txn_write<'a>(
1029 &'a self,
1030 transaction: &mut Transaction<'a>,
1031 offset: u64,
1032 buf: BufferRef<'_>,
1033 ) -> Result<(), Error> {
1034 if buf.is_empty() {
1035 return Ok(());
1036 }
1037 let (aligned, mut transfer_buf) = self.align_buffer(offset, buf).await?;
1038 self.multi_write(
1039 transaction,
1040 self.attribute_id(),
1041 std::slice::from_ref(&aligned),
1042 transfer_buf.as_mut(),
1043 )
1044 .await?;
1045 if offset + buf.len() as u64 > self.txn_get_size(transaction) {
1046 self.txn_update_size(transaction, offset + buf.len() as u64, None).await?;
1047 }
1048 Ok(())
1049 }
1050
1051 pub async fn multi_write<'a>(
1055 &'a self,
1056 transaction: &mut Transaction<'a>,
1057 attribute_id: AttributeId,
1058 ranges: &[Range<u64>],
1059 buf: MutableBufferRef<'_>,
1060 ) -> Result<(), Error> {
1061 self.handle.multi_write(transaction, attribute_id, None, ranges, buf).await
1062 }
1063
1064 pub async fn overwrite(
1072 &self,
1073 mut offset: u64,
1074 mut buf: MutableBufferRef<'_>,
1075 options: OverwriteOptions,
1076 ) -> Result<(), Error> {
1077 if buf.is_empty() {
1078 return Ok(());
1079 }
1080 ensure!((buf.len() as u32) % self.store().device.block_size() == 0, FxfsError::InvalidArgs);
1081 let end = offset + buf.len() as u64;
1082
1083 let key_id = self.get_key(None).await?.0;
1084
1085 let mut transaction =
1087 if options.allow_allocations { Some(self.new_transaction().await?) } else { None };
1088
1089 let mut writes = FuturesOrdered::new();
1091 let mut first_write = options.barrier_on_first_write;
1092
1093 {
1096 let store = self.store();
1097 let store_object_id = store.store_object_id;
1098 let allocator = store.allocator();
1099 let tree = &store.tree;
1100 let layer_set = tree.layer_set();
1101 let mut merger = layer_set.merger();
1102 let mut iter = merger
1103 .query(Query::LimitedRange(&ObjectKey::extent(
1104 self.object_id(),
1105 self.attribute_id(),
1106 offset..end,
1107 )))
1108 .await?;
1109 let block_size = self.block_size();
1110
1111 loop {
1112 let (device_offset, bytes_to_write, should_advance) = match iter.get() {
1113 Some(ItemRef {
1114 key:
1115 ObjectKey {
1116 object_id,
1117 data:
1118 ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
1119 },
1120 value: ObjectValue::Extent(ExtentValue::Some { .. }),
1121 ..
1122 }) if *object_id == self.object_id()
1123 && *attribute_id == self.attribute_id()
1124 && extent.end == offset =>
1125 {
1126 iter.advance().await?;
1127 continue;
1128 }
1129 Some(ItemRef {
1130 key:
1131 ObjectKey {
1132 object_id,
1133 data:
1134 ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
1135 },
1136 value,
1137 ..
1138 }) if *object_id == self.object_id()
1139 && *attribute_id == self.attribute_id()
1140 && extent.start <= offset =>
1141 {
1142 match value {
1143 ObjectValue::Extent(ExtentValue::Some {
1144 device_offset,
1145 mode: ExtentMode::Raw,
1146 ..
1147 }) => {
1148 ensure!(
1149 block_size.is_aligned(extent)
1150 && block_size.is_aligned(device_offset),
1151 FxfsError::Inconsistent
1152 );
1153 let offset_within_extent = offset - extent.start;
1154 let remaining_length_of_extent = (extent
1155 .end
1156 .checked_sub(offset)
1157 .ok_or(FxfsError::Inconsistent)?)
1158 as usize;
1159 (
1161 device_offset + offset_within_extent,
1162 min(buf.len(), remaining_length_of_extent),
1163 true,
1164 )
1165 }
1166 ObjectValue::Extent(ExtentValue::Some { .. }) => {
1167 bail!(
1170 "extent from ({},{}) which overlaps offset \
1171 {} has the wrong extent mode",
1172 extent.start,
1173 extent.end,
1174 offset
1175 )
1176 }
1177 _ => {
1178 bail!(
1179 "overwrite failed: extent overlapping offset {} has \
1180 unexpected ObjectValue",
1181 offset
1182 )
1183 }
1184 }
1185 }
1186 maybe_item_ref => {
1187 if let Some(transaction) = transaction.as_mut() {
1188 assert_eq!(options.allow_allocations, true);
1189 assert_eq!(offset % self.block_size(), 0);
1190
1191 let mut bytes_to_allocate = self
1195 .block_size()
1196 .align_up(buf.len() as u64)
1197 .ok_or(FxfsError::TooBig)?;
1198 if let Some(ItemRef {
1199 key:
1200 ObjectKey {
1201 object_id,
1202 data:
1203 ObjectKeyData::Attribute(
1204 attribute_id,
1205 AttributeKey::Extent(extent),
1206 ),
1207 },
1208 ..
1209 }) = maybe_item_ref
1210 {
1211 if *object_id == self.object_id()
1212 && *attribute_id == self.attribute_id()
1213 && offset < extent.start
1214 {
1215 let bytes_until_next_extent = extent.start - offset;
1216 bytes_to_allocate =
1217 min(bytes_to_allocate, bytes_until_next_extent);
1218 }
1219 }
1220
1221 let device_range = allocator
1222 .allocate(transaction, store_object_id, bytes_to_allocate)
1223 .await?;
1224 let device_range_len = device_range.end - device_range.start;
1225 transaction.add(
1226 store_object_id,
1227 Mutation::insert_object(
1228 ObjectKey::extent(
1229 self.object_id(),
1230 self.attribute_id(),
1231 offset..offset + device_range_len,
1232 ),
1233 ObjectValue::Extent(ExtentValue::new_raw(
1234 device_range.start,
1235 key_id,
1236 )),
1237 ),
1238 );
1239
1240 self.update_allocated_size(transaction, device_range_len, 0).await?;
1241
1242 (device_range.start, min(buf.len(), device_range_len as usize), false)
1244 } else {
1245 bail!(
1246 "no extent overlapping offset {}, \
1247 and new allocations are not allowed",
1248 offset
1249 )
1250 }
1251 }
1252 };
1253 let (current_buf, remaining_buf) = buf.split_at_mut(bytes_to_write);
1254 let flags = if first_write {
1255 first_write = false;
1256 WriteFlags::PRE_BARRIER
1257 } else {
1258 WriteFlags::empty()
1259 };
1260 writes.push_back(self.write_at(offset, current_buf, device_offset, flags));
1261 if remaining_buf.len() == 0 {
1262 break;
1263 } else {
1264 buf = remaining_buf;
1265 offset += bytes_to_write as u64;
1266 if should_advance {
1267 iter.advance().await?;
1268 }
1269 }
1270 }
1271 }
1272
1273 self.store().logical_write_ops.fetch_add(1, Ordering::Relaxed);
1274 writes.try_collect::<Vec<MaybeChecksums>>().await?;
1276
1277 if let Some(mut transaction) = transaction {
1278 assert_eq!(options.allow_allocations, true);
1279 if !transaction.is_empty() {
1280 if end > self.get_size() {
1281 self.grow(&mut transaction, self.get_size(), end).await?;
1282 }
1283 transaction.commit().await?;
1284 }
1285 }
1286
1287 Ok(())
1288 }
1289
1290 fn txn_get_size(&self, transaction: &Transaction<'_>) -> u64 {
1293 transaction
1294 .get_object_mutation(
1295 self.store().store_object_id,
1296 ObjectKey::attribute(
1297 self.object_id(),
1298 self.attribute_id(),
1299 AttributeKey::Attribute,
1300 ),
1301 )
1302 .and_then(|m| {
1303 if let ObjectItem { value: ObjectValue::Attribute { size, .. }, .. } = m.item {
1304 Some(size)
1305 } else {
1306 None
1307 }
1308 })
1309 .unwrap_or_else(|| self.get_size())
1310 }
1311
1312 pub async fn txn_update_size<'a>(
1313 &'a self,
1314 transaction: &mut Transaction<'a>,
1315 new_size: u64,
1316 update_has_overwrite_extents: Option<bool>,
1319 ) -> Result<(), Error> {
1320 let key =
1321 ObjectKey::attribute(self.object_id(), self.attribute_id(), AttributeKey::Attribute);
1322 let mut mutation = if let Some(mutation) =
1323 transaction.get_object_mutation(self.store().store_object_id(), key.clone())
1324 {
1325 mutation.clone()
1326 } else {
1327 ObjectStoreMutation {
1328 item: self.store().tree().find(&key).await?.ok_or(FxfsError::NotFound)?,
1329 op: Operation::ReplaceOrInsert,
1330 }
1331 };
1332 if let ObjectValue::Attribute { size, has_overwrite_extents } = &mut mutation.item.value {
1333 *size = new_size;
1334 if let Some(update_has_overwrite_extents) = update_has_overwrite_extents {
1335 *has_overwrite_extents = update_has_overwrite_extents;
1336 }
1337 } else {
1338 bail!(anyhow!(FxfsError::Inconsistent).context("Unexpected object value"));
1339 }
1340 transaction.add_with_object(
1341 self.store().store_object_id(),
1342 Mutation::ObjectStore(mutation),
1343 AssocObj::Borrowed(self),
1344 );
1345 Ok(())
1346 }
1347
1348 async fn update_allocated_size(
1349 &self,
1350 transaction: &mut Transaction<'_>,
1351 allocated: u64,
1352 deallocated: u64,
1353 ) -> Result<(), Error> {
1354 self.handle.update_allocated_size(transaction, allocated, deallocated).await
1355 }
1356
1357 pub fn truncate_overwrite_ranges(&self, size: u64) -> Result<Option<bool>, Error> {
1358 let cutoff = self.block_size().align_up(size).ok_or(FxfsError::TooBig)?;
1359 if self.with_overwrite_ranges_mut(|ranges| ranges.map_or(false, |r| r.truncate(cutoff))) {
1360 Ok(Some(false))
1363 } else {
1364 Ok(None)
1365 }
1366 }
1367
1368 pub async fn shrink<'a>(
1369 &'a self,
1370 transaction: &mut Transaction<'a>,
1371 size: u64,
1372 update_has_overwrite_extents: Option<bool>,
1373 ) -> Result<NeedsTrim, Error> {
1374 let needs_trim = self.handle.shrink(transaction, self.attribute_id(), size).await?;
1375 self.txn_update_size(transaction, size, update_has_overwrite_extents).await?;
1376 Ok(needs_trim)
1377 }
1378
1379 pub async fn grow<'a>(
1380 &'a self,
1381 transaction: &mut Transaction<'a>,
1382 old_size: u64,
1383 size: u64,
1384 ) -> Result<(), Error> {
1385 let store = self.store();
1387 while matches!(
1388 store
1389 .trim_some(
1390 transaction,
1391 self.object_id(),
1392 self.attribute_id(),
1393 TrimMode::FromOffset(old_size)
1394 )
1395 .await?,
1396 TrimResult::Incomplete
1397 ) {
1398 transaction.commit_and_continue().await?;
1399 }
1400 let block_size = self.block_size();
1402 if !block_size.is_aligned(old_size) {
1403 let layer_set = store.tree.layer_set();
1404 let mut merger = layer_set.merger();
1405 let aligned_old_size = block_size.align_down(old_size);
1406 let iter = merger
1407 .query(Query::LimitedRange(&ObjectKey::extent(
1408 self.object_id(),
1409 self.attribute_id(),
1410 aligned_old_size..aligned_old_size + block_size,
1411 )))
1412 .await?;
1413 if let Some(ItemRef {
1414 key:
1415 ObjectKey {
1416 object_id,
1417 data:
1418 ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent_key)),
1419 },
1420 value: ObjectValue::Extent(ExtentValue::Some { device_offset, key_id, .. }),
1421 ..
1422 }) = iter.get()
1423 {
1424 if *object_id == self.object_id()
1425 && *attribute_id == self.attribute_id()
1426 && extent_key.start <= aligned_old_size
1427 {
1428 let device_offset = device_offset
1429 .checked_add(aligned_old_size - extent_key.start)
1430 .ok_or(FxfsError::Inconsistent)?;
1431 ensure!(block_size.is_aligned(device_offset), FxfsError::Inconsistent);
1432 let mut buf = self.allocate_buffer(block_size.get() as usize).await;
1433 self.read_and_decrypt(device_offset, aligned_old_size, buf.as_mut(), *key_id)
1439 .await?;
1440 buf.subslice_mut((old_size % block_size) as usize..buf.len()).fill(0);
1441 self.multi_write(
1442 transaction,
1443 *attribute_id,
1444 &[aligned_old_size..aligned_old_size + block_size],
1445 buf.as_mut(),
1446 )
1447 .await?;
1448 }
1449 }
1450 }
1451 self.txn_update_size(transaction, size, None).await?;
1452 Ok(())
1453 }
1454
1455 pub async fn preallocate_range<'a>(
1468 &'a self,
1469 transaction: &mut Transaction<'a>,
1470 file_range: &mut Range<u64>,
1471 ) -> Result<Vec<Range<u64>>, Error> {
1472 let block_size = self.block_size();
1473 ensure!(block_size.is_aligned(&*file_range), FxfsError::InvalidArgs);
1474 ensure!(!self.handle.is_encrypted(), FxfsError::NotSupported);
1475 if file_range.is_empty() {
1476 return Ok(Vec::new());
1477 }
1478 let mut ranges = Vec::new();
1479 let tree = &self.store().tree;
1480 let layer_set = tree.layer_set();
1481 let mut merger = layer_set.merger();
1482 let mut iter = merger
1483 .query(Query::LimitedRange(&ObjectKey::extent(
1484 self.object_id(),
1485 self.attribute_id(),
1486 file_range.clone(),
1487 )))
1488 .await?;
1489 let mut allocated = 0;
1490 let key_id = self.get_key(None).await?.0;
1491 'outer: while file_range.start < file_range.end {
1492 let allocate_end = loop {
1493 match iter.get() {
1494 Some(ItemRef {
1496 key:
1497 ObjectKey {
1498 object_id,
1499 data:
1500 ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
1501 },
1502 value: ObjectValue::Extent(ExtentValue::Some { device_offset, .. }),
1503 ..
1504 }) if *object_id == self.object_id()
1505 && *attribute_id == self.attribute_id()
1506 && extent.start < file_range.end =>
1507 {
1508 ensure!(
1509 extent.is_valid()
1510 && block_size.is_aligned(extent)
1511 && block_size.is_aligned(device_offset),
1512 FxfsError::Inconsistent
1513 );
1514 if extent.start <= file_range.start {
1516 let device_range = device_offset
1518 .checked_add(file_range.start - extent.start)
1519 .ok_or(FxfsError::Inconsistent)?
1520 ..device_offset
1521 .checked_add(min(extent.end, file_range.end) - extent.start)
1522 .ok_or(FxfsError::Inconsistent)?;
1523 file_range.start += device_range.end - device_range.start;
1524 ranges.push(device_range);
1525 if file_range.start >= file_range.end {
1526 break 'outer;
1527 }
1528 iter.advance().await?;
1529 continue;
1530 } else {
1531 break extent.start;
1534 }
1535 }
1536 Some(ItemRef {
1538 key:
1539 ObjectKey {
1540 object_id,
1541 data:
1542 ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
1543 },
1544 value: ObjectValue::Extent(ExtentValue::None),
1545 ..
1546 }) if *object_id == self.object_id()
1547 && *attribute_id == self.attribute_id()
1548 && extent.end < file_range.end =>
1549 {
1550 iter.advance().await?;
1551 }
1552 _ => {
1553 break file_range.end;
1555 }
1556 }
1557 };
1558 let device_range = self
1559 .store()
1560 .allocator()
1561 .allocate(
1562 transaction,
1563 self.store().store_object_id(),
1564 allocate_end - file_range.start,
1565 )
1566 .await
1567 .context("Allocation failed")?;
1568 allocated += device_range.end - device_range.start;
1569 let this_file_range =
1570 file_range.start..file_range.start + device_range.end - device_range.start;
1571 file_range.start = this_file_range.end;
1572 transaction.add(
1573 self.store().store_object_id,
1574 Mutation::merge_object(
1575 ObjectKey::extent(self.object_id(), self.attribute_id(), this_file_range),
1576 ObjectValue::Extent(ExtentValue::new_raw(device_range.start, key_id)),
1577 ),
1578 );
1579 ranges.push(device_range);
1580 if transaction.mutations().len() > TRANSACTION_MUTATION_THRESHOLD {
1583 break;
1584 }
1585 }
1586 if file_range.start > block_size.align_up(self.txn_get_size(transaction)).unwrap() {
1588 self.txn_update_size(transaction, file_range.start, None).await?;
1589 }
1590 self.update_allocated_size(transaction, allocated, 0).await?;
1591 Ok(ranges)
1592 }
1593
1594 pub async fn update_attributes<'a>(
1595 &self,
1596 transaction: &mut Transaction<'a>,
1597 node_attributes: Option<&fio::MutableNodeAttributes>,
1598 change_time: Option<Timestamp>,
1599 ) -> Result<(), Error> {
1600 ensure!(
1603 !matches!(
1604 node_attributes,
1605 Some(fio::MutableNodeAttributes { encryption_policy: Some(_), .. })
1606 ),
1607 FxfsError::BadPath
1608 );
1609 self.handle.update_attributes(transaction, node_attributes, change_time).await
1610 }
1611
1612 pub fn default_transaction_options<'b>(&self) -> Options<'b> {
1615 self.handle.default_transaction_options()
1616 }
1617
1618 pub async fn new_transaction<'b>(&self) -> Result<Transaction<'b>, Error> {
1619 self.new_transaction_with_options(self.default_transaction_options()).await
1620 }
1621
1622 pub async fn new_transaction_with_options<'b>(
1623 &self,
1624 options: Options<'b>,
1625 ) -> Result<Transaction<'b>, Error> {
1626 self.handle.new_transaction_with_options(self.attribute_id(), options).await
1627 }
1628
1629 pub async fn flush_device(&self) -> Result<(), Error> {
1631 self.handle.flush_device().await
1632 }
1633
1634 pub async fn read_attr(&self, attribute_id: AttributeId) -> Result<Option<Box<[u8]>>, Error> {
1636 self.handle.read_attr(attribute_id).await
1637 }
1638
1639 pub async fn write_attr(&self, attribute_id: AttributeId, data: &[u8]) -> Result<(), Error> {
1641 assert_ne!(attribute_id, self.attribute_id());
1643 let store = self.store();
1644 let mut transaction = self.new_transaction().await?;
1645 if self.handle.write_attr(&mut transaction, attribute_id, data).await?.0 {
1646 transaction.commit_and_continue().await?;
1647 while matches!(
1648 store
1649 .trim_some(
1650 &mut transaction,
1651 self.object_id(),
1652 attribute_id,
1653 TrimMode::FromOffset(data.len() as u64),
1654 )
1655 .await?,
1656 TrimResult::Incomplete
1657 ) {
1658 transaction.commit_and_continue().await?;
1659 }
1660 }
1661 transaction.commit().await?;
1662 Ok(())
1663 }
1664
1665 async fn read_and_decrypt(
1666 &self,
1667 device_offset: u64,
1668 file_offset: u64,
1669 buffer: MutableBufferRef<'_>,
1670 key_id: u64,
1671 ) -> Result<(), Error> {
1672 self.handle
1673 .read_and_decrypt(self.attribute_id, device_offset, file_offset, buffer, key_id)
1674 .await
1675 }
1676
1677 pub async fn truncate_with_options(
1682 &self,
1683 mut options: Options<'_>,
1684 size: u64,
1685 ) -> Result<(), Error> {
1686 let borrowed_for_shrink =
1687 size < self.get_size() && matches!(options.reservation, ReservationOptions::New);
1688 if borrowed_for_shrink {
1689 options.reservation = ReservationOptions::Borrowed;
1690 }
1691 let mut transaction = self.new_transaction_with_options(options).await?;
1692 let mut old_size = self.get_size();
1693 if size > old_size && borrowed_for_shrink {
1694 drop(transaction);
1697 options.reservation = ReservationOptions::New;
1698 transaction = self.new_transaction_with_options(options).await?;
1699 old_size = self.get_size();
1700 }
1701 {
1702 let state = self.state.lock();
1703 match &*state {
1704 DataObjectState::Standard(_) => {}
1705 _ => bail!(anyhow!(FxfsError::AccessDenied).context("Cannot truncate verity file")),
1706 }
1707 }
1708 if size == old_size {
1709 return Ok(());
1710 }
1711 if size < old_size {
1712 let update_has_overwrite_ranges = self.truncate_overwrite_ranges(size)?;
1713 if self.shrink(&mut transaction, size, update_has_overwrite_ranges).await?.0 {
1714 transaction.commit_and_continue().await?;
1716 let store = self.store();
1717 while matches!(
1718 store
1719 .trim_some(
1720 &mut transaction,
1721 self.object_id(),
1722 self.attribute_id(),
1723 TrimMode::FromOffset(size)
1724 )
1725 .await?,
1726 TrimResult::Incomplete
1727 ) {
1728 if let Err(error) = transaction.commit_and_continue().await {
1729 warn!(error:?; "Failed to trim after truncate");
1730 return Ok(());
1731 }
1732 }
1733 if let Err(error) = transaction.commit().await {
1734 warn!(error:?; "Failed to trim after truncate");
1735 }
1736 return Ok(());
1737 }
1738 } else {
1739 self.grow(&mut transaction, old_size, size).await?;
1740 }
1741 transaction.commit().await?;
1742 Ok(())
1743 }
1744
1745 pub async fn get_properties(&self) -> Result<ObjectProperties, Error> {
1746 let value = self
1750 .store()
1751 .tree
1752 .find_value(&ObjectKey::object(self.object_id()))
1753 .await?
1754 .expect("Unable to find object record");
1755 match value {
1756 ObjectValue::Object {
1757 kind: ObjectKind::File { refs, .. },
1758 attributes:
1759 ObjectAttributes {
1760 creation_time,
1761 modification_time,
1762 posix_attributes,
1763 allocated_size,
1764 access_time,
1765 change_time,
1766 ..
1767 },
1768 } => Ok(ObjectProperties {
1769 refs,
1770 allocated_size,
1771 data_attribute_size: self.get_size(),
1772 creation_time,
1773 modification_time,
1774 access_time,
1775 change_time,
1776 sub_dirs: 0,
1777 posix_attributes,
1778 dir_type: DirType::Normal,
1779 }),
1780 _ => bail!(FxfsError::NotFile),
1781 }
1782 }
1783
1784 pub async fn device_extents(&self) -> Result<Vec<FileExtent>, Error> {
1789 let tree = &self.store().tree;
1790 let layer_set = tree.layer_set();
1791 let mut merger = layer_set.merger();
1792 let stream = self.handle.extent_stream(&mut merger, self.attribute_id()).await?;
1793 let extents: Vec<FileExtent> = stream.try_collect().await?;
1794 Ok(extents)
1795 }
1796
1797 pub async fn contents(&self, limit: usize) -> Result<Box<[u8]>, Error> {
1799 let size = self.get_size();
1800 if size > limit as u64 {
1801 bail!("Object too big ({} > {})", size, limit);
1802 }
1803 self.read_bytes(0..size).await
1804 }
1805
1806 pub async fn read_bytes(&self, range: Range<u64>) -> Result<Box<[u8]>, Error> {
1810 const MAX_READ_BYTES_CHUNK_SIZE: usize = 2 * 1024 * 1024; ensure!(range.start <= range.end, FxfsError::InvalidArgs);
1813 if range.is_empty() {
1814 return Ok(Box::default());
1815 }
1816 let fs = self.store().filesystem();
1817 let guard = fs
1818 .lock_manager()
1819 .read_lock(lock_keys![LockKey::object_attribute(
1820 self.store().store_object_id,
1821 self.object_id(),
1822 self.attribute_id(),
1823 )])
1824 .await;
1825
1826 let size = self.get_size();
1827 if range.start >= size {
1828 return Ok(Box::default());
1829 }
1830 let end = std::cmp::min(range.end, size);
1831 let total_to_read = (end - range.start) as usize;
1832 let block_size = self.block_size();
1833 let aligned_start = block_size.align_down(range.start);
1834 let aligned_end = block_size.align_up(end).ok_or(FxfsError::TooBig)?;
1835 let total_aligned_len = aligned_end - aligned_start;
1836
1837 let buf_size = std::cmp::min(total_aligned_len, MAX_READ_BYTES_CHUNK_SIZE as u64) as usize;
1838 let mut buf = self.allocate_buffer(buf_size).await;
1839 let mut out = Vec::with_capacity(total_to_read);
1840 let mut current_block_offset = aligned_start;
1841
1842 while current_block_offset < end {
1843 let bytes_read =
1844 self.read_aligned_locked(current_block_offset, buf.as_mut(), &guard).await?;
1845 let chunk_start = current_block_offset;
1846 let chunk_end = current_block_offset + bytes_read as u64;
1847 let slice_start = std::cmp::max(range.start, chunk_start);
1848 let slice_end = std::cmp::min(end, chunk_end);
1849 let buf_offset = (slice_start - chunk_start) as usize;
1850 let to_copy = (slice_end - slice_start) as usize;
1851 buf.subslice(buf_offset..buf_offset + to_copy).append_to(&mut out);
1852 current_block_offset = current_block_offset.saturating_add(buf_size as u64);
1853 }
1854 Ok(out.into_boxed_slice())
1855 }
1856
1857 async fn read_aligned_locked(
1868 &self,
1869 offset: u64,
1870 mut buf: MutableBufferRef<'_>,
1871 guard: &ReadGuard<'_>,
1872 ) -> Result<usize, Error> {
1873 let block_size = self.block_size();
1874 debug_assert!(block_size.is_aligned(offset));
1875 debug_assert!(block_size.is_aligned(buf.len() as u64));
1876
1877 let size = self.get_size();
1878 if offset >= size {
1879 return Ok(0);
1880 }
1881 let length = min(buf.len() as u64, size - offset) as usize;
1882 let aligned_length =
1883 block_size.align_up(length as u64).ok_or(FxfsError::Inconsistent)? as usize;
1884 buf = buf.subslice_mut(0..aligned_length);
1885
1886 self.handle
1887 .read_aligned_unchecked(self.attribute_id(), offset, buf.reborrow(), guard)
1888 .await?;
1889 if self.is_verified_file() {
1890 self.verify_data(offset as usize, buf.subslice(0..length).as_ptr_slice())?;
1891 }
1892 Ok(length)
1893 }
1894
1895 pub async fn read_aligned(
1909 &self,
1910 offset: u64,
1911 buf: MutableBufferRef<'_>,
1912 ) -> Result<usize, Error> {
1913 let block_size = self.block_size();
1914 ensure!(block_size.is_aligned(offset), FxfsError::InvalidArgs);
1915 ensure!(block_size.is_aligned(buf.len() as u64), FxfsError::InvalidArgs);
1916 let fs = self.store().filesystem();
1917 let guard = fs
1918 .lock_manager()
1919 .read_lock(lock_keys![LockKey::object_attribute(
1920 self.store().store_object_id,
1921 self.object_id(),
1922 self.attribute_id(),
1923 )])
1924 .await;
1925 self.read_aligned_locked(offset, buf, &guard).await
1926 }
1927}
1928
1929impl<S: HandleOwner> AssociatedObject for DataObjectHandle<S> {
1930 fn will_apply_mutation(&self, mutation: &Mutation, _object_id: u64, _manager: &ObjectManager) {
1931 match mutation {
1932 Mutation::ObjectStore(ObjectStoreMutation {
1933 item: ObjectItem { value: ObjectValue::Attribute { size, .. }, .. },
1934 ..
1935 }) => self.content_size.store(*size, atomic::Ordering::Relaxed),
1936 Mutation::ObjectStore(ObjectStoreMutation {
1937 item: ObjectItem { value: ObjectValue::VerifiedAttribute { size, .. }, .. },
1938 ..
1939 }) => {
1940 debug_assert_eq!(
1941 self.get_size(),
1942 *size,
1943 "size should be set when verity is enabled and must not change"
1944 );
1945 self.finalize_fsverity_state()
1946 }
1947 Mutation::ObjectStore(ObjectStoreMutation {
1948 item:
1949 ObjectItem {
1950 key:
1951 ObjectKey {
1952 object_id,
1953 data:
1954 ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent)),
1955 },
1956 value: ObjectValue::Extent(ExtentValue::Some { mode, .. }),
1957 ..
1958 },
1959 ..
1960 }) if self.object_id() == *object_id && self.attribute_id() == *attr_id => match mode {
1961 ExtentMode::Overwrite | ExtentMode::OverwritePartial(_) => {
1962 self.with_overwrite_ranges_mut(|ranges| {
1967 if let Some(ranges) = ranges {
1968 ranges.apply_range(extent.clone().into());
1969 }
1970 });
1971 }
1972 ExtentMode::Raw | ExtentMode::Cow(_) => (),
1973 },
1974 _ => {}
1975 }
1976 }
1977}
1978
1979impl<S: HandleOwner> ObjectHandle for DataObjectHandle<S> {
1980 fn set_trace(&self, v: bool) {
1981 self.handle.set_trace(v)
1982 }
1983
1984 fn object_id(&self) -> u64 {
1985 self.handle.object_id()
1986 }
1987
1988 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
1989 self.handle.allocate_buffer(size)
1990 }
1991
1992 fn block_size(&self) -> BlockSize {
1993 self.handle.block_size()
1994 }
1995}
1996
1997impl<S: HandleOwner> ReadObjectHandle for DataObjectHandle<S> {
1998 fn read_aligned<'a, 'b, 'c>(
1999 &'a self,
2000 offset: u64,
2001 buf: MutableBufferRef<'b>,
2002 ) -> Pin<Box<dyn Future<Output = Result<usize, Error>> + Send + 'c>>
2003 where
2004 'a: 'c,
2005 'b: 'c,
2006 Self: 'c,
2007 {
2008 Box::pin(DataObjectHandle::read_aligned(self, offset, buf))
2009 }
2010
2011 fn get_size(&self) -> u64 {
2012 self.content_size.load(atomic::Ordering::Relaxed)
2013 }
2014}
2015
2016impl<S: HandleOwner> LayerObject for DataObjectHandle<S> {}
2017
2018impl<S: HandleOwner> WriteObjectHandle for DataObjectHandle<S> {
2019 async fn write_or_append(&self, offset: Option<u64>, buf: BufferRef<'_>) -> Result<u64, Error> {
2020 let offset = offset.unwrap_or_else(|| self.get_size());
2021 let mut transaction = self.new_transaction().await?;
2022 self.txn_write(&mut transaction, offset, buf).await?;
2023 let new_size = self.txn_get_size(&transaction);
2024 transaction.commit().await?;
2025 Ok(new_size)
2026 }
2027
2028 async fn truncate(&self, size: u64) -> Result<(), Error> {
2029 self.truncate_with_options(self.default_transaction_options(), size).await
2030 }
2031
2032 async fn flush(&self) -> Result<(), Error> {
2033 Ok(())
2034 }
2035}
2036
2037pub struct DirectWriter<'a, S: HandleOwner> {
2040 handle: &'a DataObjectHandle<S>,
2041 options: transaction::Options<'a>,
2042 buffer: Buffer<'a>,
2043 offset: u64,
2044 buf_offset: usize,
2045}
2046
2047const BUFFER_SIZE: usize = 1_048_576;
2048
2049impl<S: HandleOwner> Drop for DirectWriter<'_, S> {
2050 fn drop(&mut self) {
2051 if self.buf_offset != 0 {
2052 warn!("DirectWriter: dropping data, did you forget to call complete?");
2053 }
2054 }
2055}
2056
2057impl<'a, S: HandleOwner> DirectWriter<'a, S> {
2058 pub async fn new(
2059 handle: &'a DataObjectHandle<S>,
2060 options: transaction::Options<'a>,
2061 ) -> DirectWriter<'a, S> {
2062 Self {
2063 handle,
2064 options,
2065 buffer: handle.allocate_buffer(BUFFER_SIZE).await,
2066 offset: 0,
2067 buf_offset: 0,
2068 }
2069 }
2070
2071 async fn flush(&mut self) -> Result<(), Error> {
2072 let mut transaction = self.handle.new_transaction_with_options(self.options).await?;
2073 self.handle
2074 .txn_write(&mut transaction, self.offset, self.buffer.subslice(0..self.buf_offset))
2075 .await?;
2076 transaction.commit().await?;
2077 self.offset += self.buf_offset as u64;
2078 self.buf_offset = 0;
2079 Ok(())
2080 }
2081}
2082
2083impl<'a, S: HandleOwner> WriteBytes for DirectWriter<'a, S> {
2084 fn block_size(&self) -> BlockSize {
2085 self.handle.block_size()
2086 }
2087
2088 async fn write_bytes(&mut self, mut buf: &[u8]) -> Result<(), Error> {
2089 while buf.len() > 0 {
2090 let to_do = std::cmp::min(buf.len(), BUFFER_SIZE - self.buf_offset);
2091 self.buffer
2092 .subslice_mut(self.buf_offset..self.buf_offset + to_do)
2093 .copy_from_slice(&buf[..to_do]);
2094 self.buf_offset += to_do;
2095 if self.buf_offset == BUFFER_SIZE {
2096 self.flush().await?;
2097 }
2098 buf = &buf[to_do..];
2099 }
2100 Ok(())
2101 }
2102
2103 async fn complete(mut self) -> Result<u64, Error> {
2104 self.flush().await?;
2105 Ok(self.offset + self.buf_offset as u64)
2106 }
2107
2108 async fn skip(&mut self, amount: u64) -> Result<(), Error> {
2109 if (BUFFER_SIZE - self.buf_offset) as u64 > amount {
2110 self.buffer.subslice_mut(self.buf_offset..self.buf_offset + amount as usize).fill(0);
2111 self.buf_offset += amount as usize;
2112 } else {
2113 self.flush().await?;
2114 self.offset += amount;
2115 }
2116 Ok(())
2117 }
2118}
2119
2120#[cfg(test)]
2121mod tests {
2122 use crate::errors::FxfsError;
2123 use crate::filesystem::{FxFilesystem, FxFilesystemBuilder, OpenFxFilesystem, SyncOptions};
2124 use crate::fsck::{
2125 FsckOptions, fsck, fsck_volume, fsck_volume_with_options, fsck_with_options,
2126 };
2127 use crate::lsm_tree::Query;
2128 use crate::lsm_tree::types::{ItemRef, LayerIterator};
2129 use crate::object_handle::{
2130 ObjectHandle, ObjectProperties, ReadObjectHandle, WriteObjectHandle,
2131 };
2132 use crate::object_store::data_object_handle::{OverwriteOptions, WRITE_ATTR_BATCH_SIZE};
2133 use crate::object_store::directory::replace_child;
2134 use crate::object_store::object_record::{FsverityMetadata, ObjectKey, ObjectValue, Timestamp};
2135 use crate::object_store::transaction::{Mutation, Options, ReservationOptions, lock_keys};
2136 use crate::object_store::volume::root_volume;
2137 use crate::object_store::{
2138 AttributeId, AttributeKey, DataObjectHandle, DirType, Directory, Extent, ExtentMode,
2139 ExtentValue, HandleOptions, LockKey, NewChildStoreOptions, ObjectKeyData, ObjectStore,
2140 PosixAttributes, StoreOptions, TRANSACTION_MUTATION_THRESHOLD,
2141 };
2142 use crate::range::RangeExt;
2143 use crate::round::{round_down, round_up};
2144 use assert_matches::assert_matches;
2145 use bit_vec::BitVec;
2146 use fidl_fuchsia_io as fio;
2147 use fsverity_merkle::{FsVerityDescriptor, FsVerityDescriptorRaw};
2148 use fuchsia_async as fasync;
2149 use fuchsia_sync::Mutex;
2150 use futures::FutureExt;
2151 use futures::channel::oneshot::channel;
2152 use futures::stream::{FuturesUnordered, StreamExt};
2153 use fxfs_crypto::{Crypt, EncryptionKey, KeyPurpose};
2154 use fxfs_insecure_crypto::new_insecure_crypt;
2155 use std::ops::Range;
2156 use std::sync::{Arc, Weak};
2157 use std::time::Duration;
2158 use storage_device::DeviceHolder;
2159 use storage_device::fake_device::FakeDevice;
2160
2161 const TEST_DEVICE_BLOCK_SIZE: u32 = 512;
2162
2163 const TEST_DATA_OFFSET: u64 = 5000;
2166 const TEST_DATA: &[u8] = b"hello";
2167 const TEST_OBJECT_SIZE: u64 = 5678;
2168 const TEST_OBJECT_ALLOCATED_SIZE: u64 = 4096;
2169 const TEST_OBJECT_NAME: &str = "foo";
2170
2171 async fn test_filesystem() -> OpenFxFilesystem {
2172 let device = DeviceHolder::new(FakeDevice::new(8192, TEST_DEVICE_BLOCK_SIZE));
2173 FxFilesystem::new_empty(device).await.expect("new_empty failed")
2174 }
2175
2176 async fn create_object_with_key(
2177 fs: Arc<FxFilesystem>,
2178 crypt: Option<&dyn Crypt>,
2179 write_object_test_data: bool,
2180 ) -> DataObjectHandle<ObjectStore> {
2181 let store = fs.root_store();
2182 let object;
2183
2184 let mut transaction = fs
2185 .root_store()
2186 .new_transaction(
2187 lock_keys![LockKey::object(
2188 store.store_object_id(),
2189 store.root_directory_object_id()
2190 )],
2191 Options::default(),
2192 )
2193 .await
2194 .expect("new_transaction failed");
2195
2196 object = if let Some(crypt) = crypt {
2197 let object_id = store.get_next_object_id(&transaction).await.unwrap();
2198 let (key, unwrapped_key) =
2199 crypt.create_key(object_id.get(), KeyPurpose::Data).await.unwrap();
2200 ObjectStore::create_object_with_key(
2201 &store,
2202 &mut transaction,
2203 object_id,
2204 HandleOptions::default(),
2205 EncryptionKey::Fxfs(key),
2206 unwrapped_key,
2207 )
2208 .await
2209 .expect("create_object failed")
2210 } else {
2211 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
2212 .await
2213 .expect("create_object failed")
2214 };
2215
2216 let root_directory =
2217 Directory::open(&store, store.root_directory_object_id()).await.expect("open failed");
2218 root_directory
2219 .add_child_file(&mut transaction, TEST_OBJECT_NAME, &object)
2220 .await
2221 .expect("add_child_file failed");
2222
2223 if write_object_test_data {
2224 let align = TEST_DATA_OFFSET as usize % TEST_DEVICE_BLOCK_SIZE as usize;
2225 let mut buf = object.allocate_buffer(align + TEST_DATA.len()).await;
2226 buf.subslice_mut(align..buf.len()).copy_from_slice(TEST_DATA);
2227 object
2228 .txn_write(&mut transaction, TEST_DATA_OFFSET, buf.subslice(align..buf.len()))
2229 .await
2230 .expect("write failed");
2231 }
2232 transaction.commit().await.expect("commit failed");
2233 object.truncate(TEST_OBJECT_SIZE).await.expect("truncate failed");
2234 object
2235 }
2236
2237 async fn test_filesystem_and_object_with_key(
2238 crypt: Option<&dyn Crypt>,
2239 write_object_test_data: bool,
2240 ) -> (OpenFxFilesystem, DataObjectHandle<ObjectStore>) {
2241 let fs = test_filesystem().await;
2242 let object = create_object_with_key(fs.clone(), crypt, write_object_test_data).await;
2243 (fs, object)
2244 }
2245
2246 async fn test_filesystem_and_object() -> (OpenFxFilesystem, DataObjectHandle<ObjectStore>) {
2247 test_filesystem_and_object_with_key(Some(&new_insecure_crypt()), true).await
2248 }
2249
2250 async fn test_filesystem_and_empty_object() -> (OpenFxFilesystem, DataObjectHandle<ObjectStore>)
2251 {
2252 test_filesystem_and_object_with_key(Some(&new_insecure_crypt()), false).await
2253 }
2254
2255 #[fuchsia::test]
2256 async fn test_zero_buf_len_read() {
2257 let (fs, object) = test_filesystem_and_object().await;
2258 let mut buf = object.allocate_buffer(0).await;
2259 assert_eq!(object.read_aligned(0u64, buf.as_mut()).await.expect("read failed"), 0);
2260 fs.close().await.expect("Close failed");
2261 }
2262
2263 #[fuchsia::test]
2264 async fn test_beyond_eof_read() {
2265 let (fs, object) = test_filesystem_and_object().await;
2266 let offset = TEST_OBJECT_SIZE as usize - 2;
2267 let align = (offset as u64 % fs.block_size()) as usize;
2268 let len: usize = 2;
2269 let block_size = fs.block_size().get() as usize;
2270
2271 let mut unaligned_buf = object.allocate_buffer(align + len + 1).await;
2273 assert_matches!(
2274 object.read_aligned((offset - align) as u64, unaligned_buf.as_mut()).await,
2275 Err(e) if FxfsError::InvalidArgs.matches(&e)
2276 );
2277
2278 let mut buf = object.allocate_buffer(block_size).await;
2279 buf.fill(123u8);
2280 assert_eq!(
2281 object.read_aligned((offset - align) as u64, buf.as_mut()).await.expect("read failed"),
2282 align + len
2283 );
2284 assert_eq!(&buf.as_ptr_slice().subslice(align..align + len).to_vec()[..], &vec![0u8; len]);
2285
2286 assert_matches!(
2288 object.read_aligned((offset - align + 1) as u64, buf.as_mut()).await,
2289 Err(e) if FxfsError::InvalidArgs.matches(&e)
2290 );
2291
2292 let aligned_eof = fs.block_size().align_up(TEST_OBJECT_SIZE).unwrap();
2294 assert_eq!(object.read_aligned(aligned_eof, buf.as_mut()).await.expect("read failed"), 0);
2295
2296 let data = object
2298 .read_bytes(offset as u64..offset as u64 + len as u64 + 1)
2299 .await
2300 .expect("read_bytes failed");
2301 assert_eq!(&data[..], &vec![0u8; len]);
2302
2303 fs.close().await.expect("Close failed");
2304 }
2305
2306 #[fuchsia::test]
2307 async fn test_beyond_eof_read_from() {
2308 let (fs, object) = test_filesystem_and_object().await;
2309 let handle = &*object;
2310 let offset = TEST_OBJECT_SIZE as usize - 2;
2311 let align = (offset as u64 % fs.block_size()) as usize;
2312 let len: usize = 2;
2313 let block_size = fs.block_size().get() as usize;
2314
2315 let mut unaligned_buf = object.allocate_buffer(align + len + 1).await;
2317 assert_matches!(
2318 handle
2319 .read_aligned(AttributeId::DATA, (offset - align) as u64, unaligned_buf.as_mut())
2320 .await,
2321 Err(e) if FxfsError::InvalidArgs.matches(&e)
2322 );
2323
2324 let mut buf = object.allocate_buffer(block_size).await;
2325 buf.fill(123u8);
2326 assert_eq!(
2327 handle
2328 .read_aligned(AttributeId::DATA, (offset - align) as u64, buf.as_mut())
2329 .await
2330 .expect("read failed"),
2331 align + len
2332 );
2333 assert_eq!(&buf.as_ptr_slice().subslice(align..align + len).to_vec()[..], &vec![0u8; len]);
2334
2335 assert_matches!(
2337 handle
2338 .read_aligned(AttributeId::DATA, (offset - align + 1) as u64, buf.as_mut())
2339 .await,
2340 Err(e) if FxfsError::InvalidArgs.matches(&e)
2341 );
2342
2343 let aligned_eof = fs.block_size().align_up(TEST_OBJECT_SIZE).unwrap();
2345 assert_eq!(
2346 handle
2347 .read_aligned(AttributeId::DATA, aligned_eof, buf.as_mut())
2348 .await
2349 .expect("read failed"),
2350 0
2351 );
2352
2353 fs.close().await.expect("Close failed");
2354 }
2355
2356 #[fuchsia::test]
2357 async fn test_beyond_eof_read_aligned_unchecked() {
2358 let (fs, object) = test_filesystem_and_object().await;
2359 let offset = TEST_OBJECT_SIZE as usize - 2;
2360 let align = (offset as u64 % fs.block_size()) as usize;
2361 let block_size = fs.block_size().get() as usize;
2362 let mut buf = object.allocate_buffer(block_size).await;
2363 buf.fill(123u8);
2364 let guard = fs
2365 .lock_manager()
2366 .read_lock(lock_keys![LockKey::object_attribute(
2367 object.store().store_object_id,
2368 object.object_id(),
2369 AttributeId::DATA,
2370 )])
2371 .await;
2372 object
2373 .read_aligned_unchecked(
2374 AttributeId::DATA,
2375 (offset - align) as u64,
2376 buf.as_mut(),
2377 &guard,
2378 )
2379 .await
2380 .expect("read failed");
2381 assert_eq!(
2382 &buf.as_ptr_slice().subslice(align..block_size).to_vec()[..],
2383 &vec![0u8; block_size - align]
2384 );
2385
2386 let aligned_eof = fs.block_size().align_up(TEST_OBJECT_SIZE).unwrap();
2388 buf.fill(123u8);
2389 object
2390 .read_aligned_unchecked(AttributeId::DATA, aligned_eof, buf.as_mut(), &guard)
2391 .await
2392 .expect("read failed");
2393 assert_eq!(buf.to_vec(), vec![0u8; block_size]);
2394 fs.close().await.expect("Close failed");
2395 }
2396
2397 #[fuchsia::test]
2398 async fn test_read_sparse() {
2399 let (fs, object) = test_filesystem_and_object().await;
2400 let len = TEST_OBJECT_SIZE as usize - 1;
2402 let data = object.read_bytes(0..len as u64).await.expect("read failed");
2403 let mut expected = vec![0; len];
2404 let offset = TEST_DATA_OFFSET as usize;
2405 expected[offset..offset + TEST_DATA.len()].copy_from_slice(TEST_DATA);
2406 assert_eq!(&data[..], &expected[..]);
2407
2408 let aligned_len = fs.block_size().align_up(TEST_OBJECT_SIZE).unwrap() as usize;
2409 let mut buf = object.allocate_buffer(aligned_len).await;
2410 buf.fill(123u8);
2411 assert_eq!(
2412 object.read_aligned(0, buf.as_mut()).await.expect("read failed"),
2413 TEST_OBJECT_SIZE as usize
2414 );
2415 let mut expected_aligned = vec![0; TEST_OBJECT_SIZE as usize];
2416 expected_aligned[offset..offset + TEST_DATA.len()].copy_from_slice(TEST_DATA);
2417 assert_eq!(
2418 &buf.as_ptr_slice().subslice(0..TEST_OBJECT_SIZE as usize).to_vec()[..],
2419 &expected_aligned[..]
2420 );
2421 fs.close().await.expect("Close failed");
2422 }
2423
2424 #[fuchsia::test]
2425 async fn test_read_after_writes_interspersed_with_flush() {
2426 let (fs, object) = test_filesystem_and_object().await;
2427
2428 object.owner().flush().await.expect("flush failed");
2429
2430 let mut buf = object.allocate_buffer(TEST_DATA.len()).await;
2432 buf.copy_from_slice(TEST_DATA);
2433 object.write_or_append(Some(0u64), buf.as_ref()).await.expect("write failed");
2434
2435 let len = TEST_OBJECT_SIZE as usize - 1;
2436 let data = object.read_bytes(0..len as u64).await.expect("read failed");
2437
2438 let mut expected = vec![0u8; len];
2439 let offset = TEST_DATA_OFFSET as usize;
2440 expected[offset..offset + TEST_DATA.len()].copy_from_slice(TEST_DATA);
2441 expected[..TEST_DATA.len()].copy_from_slice(TEST_DATA);
2442 assert_eq!(&data[..], &expected);
2443 fs.close().await.expect("Close failed");
2444 }
2445
2446 #[fuchsia::test]
2447 async fn test_read_after_truncate_and_extend() {
2448 let (fs, object) = test_filesystem_and_object().await;
2449
2450 let mut buf = object.allocate_buffer(TEST_DATA.len()).await;
2452 buf.copy_from_slice(TEST_DATA);
2453 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
2455 object.truncate(3).await.expect("truncate failed");
2457 let data = b"foo";
2458 let offset = 1500u64;
2459 let align = (offset % fs.block_size()) as usize;
2460 let mut buf = object.allocate_buffer(align + data.len()).await;
2461 buf.subslice_mut(align..buf.len()).copy_from_slice(data);
2462 object
2464 .write_or_append(Some(1500), buf.subslice(align..buf.len()))
2465 .await
2466 .expect("write failed");
2467
2468 const LEN1: usize = 1503;
2469 let data1 = object.read_bytes(0..LEN1 as u64).await.expect("read failed");
2470 let mut expected = [0; LEN1];
2471 expected[..3].copy_from_slice(&TEST_DATA[..3]);
2472 expected[1500..].copy_from_slice(b"foo");
2473 assert_eq!(&data1[..], &expected);
2474
2475 const LEN2: usize = 601;
2477 let data2 = object.read_bytes(0..LEN2 as u64).await.expect("read failed");
2478 assert_eq!(&data2[..], &expected[..LEN2]);
2479 fs.close().await.expect("Close failed");
2480 }
2481
2482 #[fuchsia::test]
2483 async fn test_read_whole_blocks_with_multiple_objects() {
2484 let (fs, object) = test_filesystem_and_object().await;
2485 let block_size = object.block_size().get() as usize;
2486 let mut buffer = object.allocate_buffer(block_size).await;
2487 buffer.fill(0xaf);
2488 object.write_or_append(Some(0), buffer.as_ref()).await.expect("write failed");
2489
2490 let store = object.owner();
2491 let mut transaction = fs
2492 .root_store()
2493 .new_transaction(lock_keys![], Options::default())
2494 .await
2495 .expect("new_transaction failed");
2496 let object2 =
2497 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
2498 .await
2499 .expect("create_object failed");
2500 transaction.commit().await.expect("commit failed");
2501 let mut ef_buffer = object.allocate_buffer(block_size).await;
2502 ef_buffer.fill(0xef);
2503 object2.write_or_append(Some(0), ef_buffer.as_ref()).await.expect("write failed");
2504
2505 let mut buffer = object.allocate_buffer(block_size).await;
2506 buffer.fill(0xaf);
2507 object
2508 .write_or_append(Some(block_size as u64), buffer.as_ref())
2509 .await
2510 .expect("write failed");
2511 object.truncate(3 * block_size as u64).await.expect("truncate failed");
2512 object2
2513 .write_or_append(Some(block_size as u64), ef_buffer.as_ref())
2514 .await
2515 .expect("write failed");
2516
2517 let mut buffer = object.allocate_buffer(4 * block_size).await;
2518 buffer.fill(123);
2519 assert_eq!(
2520 object.read_aligned(0, buffer.as_mut()).await.expect("read failed"),
2521 3 * block_size
2522 );
2523 assert_eq!(
2524 &buffer.as_ptr_slice().subslice(0..2 * block_size).to_vec()[..],
2525 &vec![0xaf; 2 * block_size]
2526 );
2527 assert_eq!(
2528 &buffer.as_ptr_slice().subslice(2 * block_size..3 * block_size).to_vec()[..],
2529 &vec![0; block_size]
2530 );
2531 assert_eq!(
2532 object2.read_aligned(0, buffer.as_mut()).await.expect("read failed"),
2533 2 * block_size
2534 );
2535 assert_eq!(
2536 &buffer.as_ptr_slice().subslice(0..2 * block_size).to_vec()[..],
2537 &vec![0xef; 2 * block_size]
2538 );
2539 fs.close().await.expect("Close failed");
2540 }
2541
2542 #[fuchsia::test]
2543 async fn test_alignment() {
2544 let (fs, object) = test_filesystem_and_object().await;
2545
2546 struct AlignTest {
2547 fill: u8,
2548 object: DataObjectHandle<ObjectStore>,
2549 mirror: Vec<u8>,
2550 }
2551
2552 impl AlignTest {
2553 async fn new(object: DataObjectHandle<ObjectStore>) -> Self {
2554 let mirror =
2555 object.read_bytes(0..object.get_size()).await.expect("read failed").into_vec();
2556 Self { fill: 0, object, mirror }
2557 }
2558
2559 async fn test(&mut self, range: Range<u64>) {
2564 let mut buf = self.object.allocate_buffer((range.end - range.start) as usize).await;
2565 self.fill += 1;
2566 buf.fill(self.fill);
2567 self.object
2568 .write_or_append(Some(range.start), buf.as_ref())
2569 .await
2570 .expect("write_or_append failed");
2571 if range.end > self.mirror.len() as u64 {
2572 self.mirror.resize(range.end as usize, 0);
2573 }
2574 self.mirror[range.start as usize..range.end as usize].fill(self.fill);
2575 let data = self
2576 .object
2577 .read_bytes(0..self.mirror.len() as u64 + 1)
2578 .await
2579 .expect("read failed");
2580 assert_eq!(&data[..], self.mirror.as_slice());
2581 }
2582 }
2583
2584 let block_size = object.block_size().get();
2585 let mut align = AlignTest::new(object).await;
2586
2587 align.test(0..2 * block_size + 1).await;
2589
2590 align.test(1..block_size).await;
2592 align.test(1..2 * block_size).await;
2593
2594 align.test(0..block_size - 1).await;
2596 align.test(0..2 * block_size - 1).await;
2597
2598 align.test(1..block_size - 1).await;
2600 align.test(1..2 * block_size - 1).await;
2601
2602 fs.close().await.expect("Close failed");
2603 }
2604
2605 #[fuchsia::test]
2606 async fn test_read_bytes_chunked() {
2607 let device = DeviceHolder::new(FakeDevice::new(32768, TEST_DEVICE_BLOCK_SIZE));
2609 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
2610 let object = create_object_with_key(fs.clone(), Some(&new_insecure_crypt()), false).await;
2611
2612 const FILE_SIZE: usize = 5 * 1024 * 1024;
2613 let mut data = vec![0u8; FILE_SIZE];
2614 for (i, byte) in data.iter_mut().enumerate() {
2615 *byte = (i % 251) as u8;
2616 }
2617
2618 const WRITE_CHUNK_SIZE: usize = 1024 * 1024;
2619 let mut buf = object.allocate_buffer(WRITE_CHUNK_SIZE).await;
2620 for chunk in (0..FILE_SIZE).step_by(WRITE_CHUNK_SIZE) {
2621 let end = std::cmp::min(chunk + WRITE_CHUNK_SIZE, FILE_SIZE);
2622 buf.subslice_mut(..end - chunk).copy_from_slice(&data[chunk..end]);
2623 object
2624 .write_or_append(Some(chunk as u64), buf.subslice(..end - chunk))
2625 .await
2626 .expect("write failed");
2627 }
2628
2629 let read_data = object.read_bytes(0..FILE_SIZE as u64).await.expect("read_bytes failed");
2631 assert_eq!(&read_data[..], &data[..]);
2632
2633 let range = 123_456..4_718_592;
2635 let read_data = object.read_bytes(range.clone()).await.expect("read_bytes failed");
2636 assert_eq!(&read_data[..], &data[range.start as usize..range.end as usize]);
2637
2638 let range = (2 * 1024 * 1024 - 500)..(2 * 1024 * 1024 + 500);
2640 let read_data = object.read_bytes(range.clone()).await.expect("read_bytes failed");
2641 assert_eq!(&read_data[..], &data[range.start as usize..range.end as usize]);
2642
2643 let range = (FILE_SIZE as u64 - 100)..(FILE_SIZE as u64 + 1000);
2645 let read_data = object.read_bytes(range).await.expect("read_bytes failed");
2646 assert_eq!(&read_data[..], &data[(FILE_SIZE - 100)..]);
2647
2648 let range = (FILE_SIZE as u64 + 10)..(FILE_SIZE as u64 + 100);
2650 let read_data = object.read_bytes(range).await.expect("read_bytes failed");
2651 assert!(read_data.is_empty());
2652
2653 assert!(object.contents(FILE_SIZE - 1).await.is_err());
2655 let contents = object.contents(usize::MAX).await.expect("contents failed");
2656 assert_eq!(&contents[..], &data[..]);
2657
2658 let empty = object.read_bytes(0..0).await.expect("read_bytes failed");
2660 assert!(empty.is_empty());
2661 let empty = object.read_bytes(100..100).await.expect("read_bytes failed");
2662 assert!(empty.is_empty());
2663
2664 fs.close().await.expect("Close failed");
2665 }
2666
2667 async fn test_preallocate_common(fs: &FxFilesystem, object: DataObjectHandle<ObjectStore>) {
2668 let allocator = fs.allocator();
2669 let allocated_before = allocator.get_allocated_bytes();
2670 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2671 object
2672 .preallocate_range(&mut transaction, &mut (0..fs.block_size().get()))
2673 .await
2674 .expect("preallocate_range failed");
2675 transaction.commit().await.expect("commit failed");
2676 assert!(object.get_size() < 1048576);
2677 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2678 object
2679 .preallocate_range(&mut transaction, &mut (0..1048576))
2680 .await
2681 .expect("preallocate_range failed");
2682 transaction.commit().await.expect("commit failed");
2683 assert_eq!(object.get_size(), 1048576);
2684 let allocated_after = allocator.get_allocated_bytes();
2686 assert_eq!(allocated_after - allocated_before, 1048576 - fs.block_size());
2687
2688 let mut buf = object
2689 .allocate_buffer(fs.block_size().align_up(TEST_DATA_OFFSET).unwrap() as usize)
2690 .await;
2691 buf.fill(47);
2692 object
2693 .write_or_append(Some(0), buf.subslice(0..TEST_DATA_OFFSET as usize))
2694 .await
2695 .expect("write failed");
2696 buf.fill(95);
2697 let offset = fs.block_size().align_up(TEST_OBJECT_SIZE).unwrap();
2698 object
2699 .overwrite(offset, buf.as_mut(), OverwriteOptions::default())
2700 .await
2701 .expect("write failed");
2702
2703 assert_eq!(allocator.get_allocated_bytes(), allocated_after);
2705
2706 let mut buf = object.allocate_buffer(1048576).await;
2708 assert_eq!(object.read_aligned(0, buf.as_mut()).await.expect("read failed"), buf.len());
2709 assert_eq!(
2710 &buf.as_ptr_slice().subslice(0..TEST_DATA_OFFSET as usize).to_vec()[..],
2711 &[47; TEST_DATA_OFFSET as usize]
2712 );
2713 assert_eq!(
2714 &buf.as_ptr_slice()
2715 .subslice(TEST_DATA_OFFSET as usize..TEST_DATA_OFFSET as usize + TEST_DATA.len())
2716 .to_vec()[..],
2717 TEST_DATA
2718 );
2719 assert_eq!(
2720 &buf.as_ptr_slice().subslice(offset as usize..offset as usize + 2048).to_vec()[..],
2721 &[95; 2048]
2722 );
2723 }
2724
2725 #[fuchsia::test]
2726 async fn test_unaligned_overwrite_returns_error() {
2727 let (fs, object) = test_filesystem_and_object().await;
2728 let mut buf = object.allocate_buffer(100).await;
2729 let res = object.overwrite(0, buf.as_mut(), OverwriteOptions::default()).await;
2730 assert!(matches!(res, Err(e) if FxfsError::InvalidArgs.matches(&e)));
2731 fs.close().await.expect("Close failed");
2732 }
2733
2734 #[fuchsia::test]
2735 async fn test_unaligned_preallocate_returns_error() {
2736 let (fs, object) = test_filesystem_and_object().await;
2737 let mut transaction = fs
2738 .root_store()
2739 .new_transaction(lock_keys![], Options::default())
2740 .await
2741 .expect("new failed");
2742 let res = object.preallocate_range(&mut transaction, &mut (0..100)).await;
2743 assert!(matches!(res, Err(e) if FxfsError::InvalidArgs.matches(&e)));
2744 fs.close().await.expect("Close failed");
2745 }
2746
2747 #[fuchsia::test]
2748 async fn test_encrypted_preallocate_returns_error() {
2749 let (fs, object) = test_filesystem_and_object().await;
2750 let mut transaction = fs
2751 .root_store()
2752 .new_transaction(lock_keys![], Options::default())
2753 .await
2754 .expect("new failed");
2755 let bs = fs.block_size();
2756 let res = object.preallocate_range(&mut transaction, &mut (0..bs.get())).await;
2757 assert!(matches!(res, Err(e) if FxfsError::NotSupported.matches(&e)));
2758 fs.close().await.expect("Close failed");
2759 }
2760
2761 #[fuchsia::test]
2762 async fn test_preallocate_range() {
2763 let (fs, object) = test_filesystem_and_object_with_key(None, true).await;
2764 test_preallocate_common(&fs, object).await;
2765 fs.close().await.expect("Close failed");
2766 }
2767
2768 #[fuchsia::test]
2771 async fn test_preallocate_succeeds_when_extents_are_in_different_layers() {
2772 let (fs, object) = test_filesystem_and_object_with_key(None, true).await;
2773 object.owner().flush().await.expect("flush failed");
2774 test_preallocate_common(&fs, object).await;
2775 fs.close().await.expect("Close failed");
2776 }
2777
2778 #[fuchsia::test]
2779 async fn test_already_preallocated() {
2780 let (fs, object) = test_filesystem_and_object_with_key(None, true).await;
2781 let allocator = fs.allocator();
2782 let allocated_before = allocator.get_allocated_bytes();
2783 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2784 let offset = fs.block_size().align_down(TEST_DATA_OFFSET);
2785 object
2786 .preallocate_range(&mut transaction, &mut (offset..offset + fs.block_size()))
2787 .await
2788 .expect("preallocate_range failed");
2789 transaction.commit().await.expect("commit failed");
2790 assert_eq!(allocator.get_allocated_bytes(), allocated_before);
2792 fs.close().await.expect("Close failed");
2793 }
2794
2795 #[fuchsia::test]
2796 async fn test_overwrite_when_preallocated_at_start_of_file() {
2797 let (fs, object) = test_filesystem_and_empty_object().await;
2800
2801 let object = ObjectStore::open_object(
2802 object.owner(),
2803 object.object_id(),
2804 HandleOptions::default(),
2805 None,
2806 )
2807 .await
2808 .expect("open_object failed");
2809
2810 assert_eq!(fs.block_size(), 4096);
2811
2812 let mut write_buf = object.allocate_buffer(4096).await;
2813 write_buf.fill(95);
2814
2815 object
2818 .overwrite(0, write_buf.as_mut(), OverwriteOptions::default())
2819 .await
2820 .expect_err("overwrite succeeded");
2821
2822 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2824 object
2825 .preallocate_range(&mut transaction, &mut (0..4096 as u64))
2826 .await
2827 .expect("preallocate_range failed");
2828 transaction.commit().await.expect("commit failed");
2829
2830 {
2833 let mut read_buf = object.allocate_buffer(4096).await;
2834 object.read_aligned(0, read_buf.as_mut()).await.expect("read failed");
2835 assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2836 }
2837 object
2838 .overwrite(0, write_buf.as_mut(), OverwriteOptions::default())
2839 .await
2840 .expect("overwrite failed");
2841 {
2842 let mut read_buf = object.allocate_buffer(4096).await;
2843 object.read_aligned(0, read_buf.as_mut()).await.expect("read failed");
2844 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2845 }
2846
2847 object
2850 .overwrite(4096, write_buf.as_mut(), OverwriteOptions::default())
2851 .await
2852 .expect_err("overwrite succeeded");
2853
2854 object
2857 .overwrite(
2858 4096,
2859 write_buf.as_mut(),
2860 OverwriteOptions { allow_allocations: true, ..Default::default() },
2861 )
2862 .await
2863 .expect("overwrite failed");
2864 {
2865 let mut read_buf = object.allocate_buffer(4096).await;
2866 object.read_aligned(4096, read_buf.as_mut()).await.expect("read failed");
2867 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2868 }
2869
2870 let fsck_options = FsckOptions {
2872 fail_on_warning: true,
2873 no_lock: true,
2874 on_error: Box::new(|err| println!("fsck error: {:?}", err)),
2875 ..Default::default()
2876 };
2877 fsck_with_options(fs.clone(), &fsck_options).await.expect("fsck failed");
2878
2879 fs.close().await.expect("Close failed");
2880 }
2881
2882 #[fuchsia::test]
2883 async fn test_overwrite_large_buffer_and_file_with_many_holes() {
2884 let (fs, object) = test_filesystem_and_empty_object().await;
2887
2888 let object = ObjectStore::open_object(
2889 object.owner(),
2890 object.object_id(),
2891 HandleOptions::default(),
2892 None,
2893 )
2894 .await
2895 .expect("open_object failed");
2896
2897 assert_eq!(fs.block_size(), 4096);
2898 assert_eq!(object.get_size(), TEST_OBJECT_SIZE);
2899
2900 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
2902 object
2903 .preallocate_range(&mut transaction, &mut (4096..8192 as u64))
2904 .await
2905 .expect("preallocate_range failed");
2906 object
2907 .preallocate_range(&mut transaction, &mut (16384..32768 as u64))
2908 .await
2909 .expect("preallocate_range failed");
2910 object
2911 .preallocate_range(&mut transaction, &mut (65536..131072 as u64))
2912 .await
2913 .expect("preallocate_range failed");
2914 object
2915 .preallocate_range(&mut transaction, &mut (262144..524288 as u64))
2916 .await
2917 .expect("preallocate_range failed");
2918 transaction.commit().await.expect("commit failed");
2919
2920 assert_eq!(object.get_size(), 524288);
2921
2922 let mut write_buf = object.allocate_buffer(4096).await;
2923 write_buf.fill(95);
2924
2925 object
2927 .overwrite(0, write_buf.as_mut(), OverwriteOptions::default())
2928 .await
2929 .expect_err("overwrite succeeded");
2930 object
2931 .overwrite(8192, write_buf.as_mut(), OverwriteOptions::default())
2932 .await
2933 .expect_err("overwrite succeeded");
2934 object
2935 .overwrite(32768, write_buf.as_mut(), OverwriteOptions::default())
2936 .await
2937 .expect_err("overwrite succeeded");
2938 object
2939 .overwrite(131072, write_buf.as_mut(), OverwriteOptions::default())
2940 .await
2941 .expect_err("overwrite succeeded");
2942
2943 {
2945 let mut read_buf = object.allocate_buffer(4096).await;
2946 object.read_aligned(4096, read_buf.as_mut()).await.expect("read failed");
2947 assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2948 }
2949 object
2950 .overwrite(4096, write_buf.as_mut(), OverwriteOptions::default())
2951 .await
2952 .expect("overwrite failed");
2953 {
2954 let mut read_buf = object.allocate_buffer(4096).await;
2955 object.read_aligned(4096, read_buf.as_mut()).await.expect("read failed");
2956 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2957 }
2958 {
2959 let mut read_buf = object.allocate_buffer(4096).await;
2960 object.read_aligned(16384, read_buf.as_mut()).await.expect("read failed");
2961 assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2962 }
2963 object
2964 .overwrite(16384, write_buf.as_mut(), OverwriteOptions::default())
2965 .await
2966 .expect("overwrite failed");
2967 {
2968 let mut read_buf = object.allocate_buffer(4096).await;
2969 object.read_aligned(16384, read_buf.as_mut()).await.expect("read failed");
2970 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2971 }
2972 {
2973 let mut read_buf = object.allocate_buffer(4096).await;
2974 object.read_aligned(65536, read_buf.as_mut()).await.expect("read failed");
2975 assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2976 }
2977 object
2978 .overwrite(65536, write_buf.as_mut(), OverwriteOptions::default())
2979 .await
2980 .expect("overwrite failed");
2981 {
2982 let mut read_buf = object.allocate_buffer(4096).await;
2983 object.read_aligned(65536, read_buf.as_mut()).await.expect("read failed");
2984 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2985 }
2986 {
2987 let mut read_buf = object.allocate_buffer(4096).await;
2988 object.read_aligned(262144, read_buf.as_mut()).await.expect("read failed");
2989 assert_eq!(&read_buf.to_vec()[..], &[0; 4096]);
2990 }
2991 object
2992 .overwrite(262144, write_buf.as_mut(), OverwriteOptions::default())
2993 .await
2994 .expect("overwrite failed");
2995 {
2996 let mut read_buf = object.allocate_buffer(4096).await;
2997 object.read_aligned(262144, read_buf.as_mut()).await.expect("read failed");
2998 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
2999 }
3000
3001 let mut huge_write_buf = object.allocate_buffer(524288).await;
3003 huge_write_buf.fill(96);
3004
3005 object
3007 .overwrite(0, huge_write_buf.as_mut(), OverwriteOptions::default())
3008 .await
3009 .expect_err("overwrite succeeded");
3010 object
3012 .overwrite(
3013 0,
3014 huge_write_buf.as_mut(),
3015 OverwriteOptions { allow_allocations: true, ..Default::default() },
3016 )
3017 .await
3018 .expect("overwrite failed");
3019 {
3020 let mut read_buf = object.allocate_buffer(524288).await;
3021 object.read_aligned(0, read_buf.as_mut()).await.expect("read failed");
3022 assert_eq!(&read_buf.to_vec()[..], &[96; 524288]);
3023 }
3024
3025 let fsck_options = FsckOptions {
3027 fail_on_warning: true,
3028 no_lock: true,
3029 on_error: Box::new(|err| println!("fsck error: {:?}", err)),
3030 ..Default::default()
3031 };
3032 fsck_with_options(fs.clone(), &fsck_options).await.expect("fsck failed");
3033
3034 fs.close().await.expect("Close failed");
3035 }
3036
3037 #[fuchsia::test]
3038 async fn test_overwrite_when_unallocated_at_start_of_file() {
3039 let (fs, object) = test_filesystem_and_empty_object().await;
3042
3043 let object = ObjectStore::open_object(
3044 object.owner(),
3045 object.object_id(),
3046 HandleOptions::default(),
3047 None,
3048 )
3049 .await
3050 .expect("open_object failed");
3051
3052 assert_eq!(fs.block_size(), 4096);
3053
3054 let mut write_buf = object.allocate_buffer(4096).await;
3055 write_buf.fill(95);
3056
3057 object
3060 .overwrite(0, write_buf.as_mut(), OverwriteOptions::default())
3061 .await
3062 .expect_err("overwrite succeeded");
3063
3064 object
3066 .overwrite(
3067 0,
3068 write_buf.as_mut(),
3069 OverwriteOptions { allow_allocations: true, ..Default::default() },
3070 )
3071 .await
3072 .expect("overwrite failed");
3073 {
3074 let mut read_buf = object.allocate_buffer(4096).await;
3075 object.read_aligned(0, read_buf.as_mut()).await.expect("read failed");
3076 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
3077 }
3078
3079 object
3081 .overwrite(4096, write_buf.as_mut(), OverwriteOptions::default())
3082 .await
3083 .expect_err("overwrite succeeded");
3084
3085 object
3087 .overwrite(
3088 4096,
3089 write_buf.as_mut(),
3090 OverwriteOptions { allow_allocations: true, ..Default::default() },
3091 )
3092 .await
3093 .expect("overwrite failed");
3094 {
3095 let mut read_buf = object.allocate_buffer(4096).await;
3096 object.read_aligned(4096, read_buf.as_mut()).await.expect("read failed");
3097 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
3098 }
3099
3100 let fsck_options = FsckOptions {
3102 fail_on_warning: true,
3103 no_lock: true,
3104 on_error: Box::new(|err| println!("fsck error: {:?}", err)),
3105 ..Default::default()
3106 };
3107 fsck_with_options(fs.clone(), &fsck_options).await.expect("fsck failed");
3108
3109 fs.close().await.expect("Close failed");
3110 }
3111
3112 #[fuchsia::test]
3113 async fn test_overwrite_can_extend_a_file() {
3114 let (fs, object) = test_filesystem_and_empty_object().await;
3117
3118 let object = ObjectStore::open_object(
3119 object.owner(),
3120 object.object_id(),
3121 HandleOptions::default(),
3122 None,
3123 )
3124 .await
3125 .expect("open_object failed");
3126
3127 assert_eq!(fs.block_size(), 4096);
3128 assert_eq!(object.get_size(), TEST_OBJECT_SIZE);
3129
3130 let mut write_buf = object.allocate_buffer(4096).await;
3131 write_buf.fill(95);
3132
3133 let last_block_offset = round_down(TEST_OBJECT_SIZE, 4096 as u32);
3135
3136 object
3138 .overwrite(last_block_offset, write_buf.as_mut(), OverwriteOptions::default())
3139 .await
3140 .expect_err("overwrite succeeded");
3141 object
3143 .overwrite(
3144 last_block_offset,
3145 write_buf.as_mut(),
3146 OverwriteOptions { allow_allocations: true, ..Default::default() },
3147 )
3148 .await
3149 .expect("overwrite failed");
3150 {
3151 let mut read_buf = object.allocate_buffer(4096).await;
3152 object.read_aligned(last_block_offset, read_buf.as_mut()).await.expect("read failed");
3153 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
3154 }
3155
3156 assert_eq!(object.get_size(), 8192);
3157
3158 let next_block_offset = round_up(TEST_OBJECT_SIZE, 4096 as u32).unwrap();
3160
3161 object
3163 .overwrite(next_block_offset, write_buf.as_mut(), OverwriteOptions::default())
3164 .await
3165 .expect_err("overwrite succeeded");
3166 object
3168 .overwrite(
3169 next_block_offset,
3170 write_buf.as_mut(),
3171 OverwriteOptions { allow_allocations: true, ..Default::default() },
3172 )
3173 .await
3174 .expect("overwrite failed");
3175 {
3176 let mut read_buf = object.allocate_buffer(4096).await;
3177 object.read_aligned(next_block_offset, read_buf.as_mut()).await.expect("read failed");
3178 assert_eq!(&read_buf.to_vec()[..], &[95; 4096]);
3179 }
3180
3181 assert_eq!(object.get_size(), 12288);
3182
3183 let fsck_options = FsckOptions {
3185 fail_on_warning: true,
3186 no_lock: true,
3187 on_error: Box::new(|err| println!("fsck error: {:?}", err)),
3188 ..Default::default()
3189 };
3190 fsck_with_options(fs.clone(), &fsck_options).await.expect("fsck failed");
3191
3192 fs.close().await.expect("Close failed");
3193 }
3194
3195 #[fuchsia::test]
3196 async fn test_enable_verity() {
3197 let fs: OpenFxFilesystem = test_filesystem().await;
3198 let mut transaction = fs
3199 .root_store()
3200 .new_transaction(lock_keys![], Options::default())
3201 .await
3202 .expect("new_transaction failed");
3203 let store = fs.root_store();
3204 let object = Arc::new(
3205 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3206 .await
3207 .expect("create_object failed"),
3208 );
3209
3210 transaction.commit().await.unwrap();
3211
3212 object
3213 .enable_verity(fio::VerificationOptions {
3214 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3215 salt: Some(vec![]),
3216 ..Default::default()
3217 })
3218 .await
3219 .expect("set verified file metadata failed");
3220
3221 let handle =
3222 ObjectStore::open_object(&store, object.object_id(), HandleOptions::default(), None)
3223 .await
3224 .expect("open_object failed");
3225
3226 assert!(handle.is_verified_file());
3227
3228 fs.close().await.expect("Close failed");
3229 }
3230
3231 #[fuchsia::test]
3232 async fn test_enable_verity_large_file() {
3233 let device = DeviceHolder::new(FakeDevice::new(262144, TEST_DEVICE_BLOCK_SIZE));
3235 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
3236 let root_store = fs.root_store();
3237 let mut transaction = fs
3238 .root_store()
3239 .new_transaction(lock_keys![], Options::default())
3240 .await
3241 .expect("new_transaction failed");
3242
3243 let handle = ObjectStore::create_object(
3244 &root_store,
3245 &mut transaction,
3246 HandleOptions::default(),
3247 None,
3248 )
3249 .await
3250 .expect("failed to create object");
3251 transaction.commit().await.expect("commit failed");
3252 let mut offset = 0;
3253
3254 let mut buf = handle.allocate_buffer(WRITE_ATTR_BATCH_SIZE).await;
3256 buf.fill(1);
3257 for _ in 0..130 {
3258 handle.write_or_append(Some(offset), buf.as_ref()).await.expect("write failed");
3259 offset += WRITE_ATTR_BATCH_SIZE as u64;
3260 }
3261
3262 handle
3263 .enable_verity(fio::VerificationOptions {
3264 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3265 salt: Some(vec![]),
3266 ..Default::default()
3267 })
3268 .await
3269 .expect("set verified file metadata failed");
3270
3271 let mut buf = handle.allocate_buffer(WRITE_ATTR_BATCH_SIZE).await;
3272 offset = 0;
3273 for _ in 0..130 {
3274 handle
3275 .read_aligned(offset, buf.as_mut())
3276 .await
3277 .expect("verification during read should fail");
3278 assert_eq!(buf.to_vec(), &[1; WRITE_ATTR_BATCH_SIZE]);
3279 offset += WRITE_ATTR_BATCH_SIZE as u64;
3280 }
3281
3282 fsck(fs.clone()).await.expect("fsck failed");
3283 fs.close().await.expect("Close failed");
3284 }
3285
3286 #[fuchsia::test]
3287 async fn test_retry_enable_verity_on_reboot() {
3288 let device = DeviceHolder::new(FakeDevice::new(8192, TEST_DEVICE_BLOCK_SIZE));
3289 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
3290 let root_store = fs.root_store();
3291 let mut transaction = fs
3292 .root_store()
3293 .new_transaction(lock_keys![], Options::default())
3294 .await
3295 .expect("new_transaction failed");
3296
3297 let handle = ObjectStore::create_object(
3298 &root_store,
3299 &mut transaction,
3300 HandleOptions::default(),
3301 None,
3302 )
3303 .await
3304 .expect("failed to create object");
3305 transaction.commit().await.expect("commit failed");
3306
3307 let object_id = {
3308 let mut transaction = handle.new_transaction().await.expect("new_transaction failed");
3309 transaction.add(
3310 root_store.store_object_id(),
3311 Mutation::replace_or_insert_object(
3312 ObjectKey::graveyard_attribute_entry(
3313 root_store.graveyard_directory_object_id(),
3314 handle.object_id(),
3315 AttributeId::FSVERITY_MERKLE,
3316 ),
3317 ObjectValue::Some,
3318 ),
3319 );
3320
3321 handle
3324 .write_new_attr(
3325 &mut transaction,
3326 AttributeId::FSVERITY_MERKLE,
3327 &vec![0; 2 * WRITE_ATTR_BATCH_SIZE],
3328 )
3329 .await
3330 .expect("failed to write merkle attribute");
3331
3332 handle.object_id()
3333 };
3336
3337 fs.close().await.expect("failed to close filesystem");
3338 let device = fs.take_device().await;
3339 device.reopen(false);
3340
3341 let fs =
3342 FxFilesystemBuilder::new().read_only(true).open(device).await.expect("open failed");
3343 fsck(fs.clone()).await.expect("fsck failed");
3344 fs.close().await.expect("failed to close filesystem");
3345 let device = fs.take_device().await;
3346 device.reopen(false);
3347
3348 let fs = FxFilesystem::open(device).await.expect("open failed");
3350 let root_store = fs.root_store();
3351 let handle =
3352 ObjectStore::open_object(&root_store, object_id, HandleOptions::default(), None)
3353 .await
3354 .expect("open_object failed");
3355 handle
3356 .enable_verity(fio::VerificationOptions {
3357 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3358 salt: Some(vec![]),
3359 ..Default::default()
3360 })
3361 .await
3362 .expect("set verified file metadata failed");
3363
3364 fs.graveyard().flush().await;
3369 let merkle_data = handle
3370 .read_attr(AttributeId::FSVERITY_MERKLE)
3371 .await
3372 .expect("read_attr failed")
3373 .expect("No attr found");
3374 assert!(
3375 FsVerityDescriptor::new(&merkle_data[..], handle.block_size().get() as usize).is_ok()
3376 );
3377 fsck(fs.clone()).await.expect("fsck failed");
3378 fs.close().await.expect("Close failed");
3379 }
3380
3381 #[fuchsia::test]
3382 async fn test_verify_data_corrupt_file() {
3383 let fs: OpenFxFilesystem = test_filesystem().await;
3384 let mut transaction = fs
3385 .root_store()
3386 .new_transaction(lock_keys![], Options::default())
3387 .await
3388 .expect("new_transaction failed");
3389 let store = fs.root_store();
3390 let object = Arc::new(
3391 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3392 .await
3393 .expect("create_object failed"),
3394 );
3395
3396 transaction.commit().await.unwrap();
3397
3398 let mut buf = object.allocate_buffer(5 * fs.block_size().get() as usize).await;
3399 buf.fill(123);
3400 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3401
3402 object
3403 .enable_verity(fio::VerificationOptions {
3404 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3405 salt: Some(vec![]),
3406 ..Default::default()
3407 })
3408 .await
3409 .expect("set verified file metadata failed");
3410
3411 buf.fill(234);
3413 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3414 object
3415 .read_aligned(0, buf.as_mut())
3416 .await
3417 .expect_err("verification during read should fail");
3418 object
3419 .read_bytes(0..buf.len() as u64)
3420 .await
3421 .expect_err("verification during read_bytes should fail");
3422
3423 fs.close().await.expect("Close failed");
3424 }
3425
3426 #[fuchsia::test]
3430 async fn test_parse_f2fs_verity() {
3431 let fs: OpenFxFilesystem = test_filesystem().await;
3432 let mut transaction = fs
3433 .root_store()
3434 .new_transaction(lock_keys![], Options::default())
3435 .await
3436 .expect("new_transaction failed");
3437 let store = fs.root_store();
3438 let object = Arc::new(
3439 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3440 .await
3441 .expect("create_object failed"),
3442 );
3443
3444 transaction.commit().await.unwrap();
3445 let file_size = fs.block_size() * 2;
3446 {
3448 let mut buf = object.allocate_buffer(file_size as usize).await;
3449 buf.fill(64);
3450 assert_eq!(
3451 object.write_or_append(None, buf.as_ref()).await.expect("Writing to file."),
3452 file_size
3453 );
3454 }
3455
3456 object
3458 .enable_verity(fio::VerificationOptions {
3459 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3460 salt: Some(vec![]),
3461 ..Default::default()
3462 })
3463 .await
3464 .expect("set verified file metadata failed");
3465 let (verity_info, root_hash) = object.get_descriptor().unwrap();
3466
3467 let mut transaction = fs
3468 .root_store()
3469 .new_transaction(
3470 lock_keys![LockKey::Object {
3471 store_object_id: store.store_object_id(),
3472 object_id: object.object_id()
3473 }],
3474 Options::default(),
3475 )
3476 .await
3477 .expect("new_transaction failed");
3478 transaction.add(
3479 store.store_object_id(),
3480 Mutation::replace_or_insert_object(
3481 ObjectKey::attribute(
3482 object.object_id(),
3483 AttributeId::DATA,
3484 AttributeKey::Attribute,
3485 ),
3486 ObjectValue::verified_attribute(
3487 file_size,
3488 FsverityMetadata::F2fs(0..(fs.block_size() * 2)),
3489 ),
3490 ),
3491 );
3492 transaction.add(
3493 store.store_object_id(),
3494 Mutation::replace_or_insert_object(
3495 ObjectKey::attribute(
3496 object.object_id(),
3497 AttributeId::FSVERITY_MERKLE,
3498 AttributeKey::Attribute,
3499 ),
3500 ObjectValue::attribute(fs.block_size() * 2, false),
3501 ),
3502 );
3503 {
3504 let descriptor = FsVerityDescriptorRaw::new(
3505 fio::HashAlgorithm::Sha256,
3506 fs.block_size().get(),
3507 file_size,
3508 root_hash.as_slice(),
3509 match &verity_info.salt {
3510 Some(salt) => salt.as_slice(),
3511 None => [0u8; 0].as_slice(),
3512 },
3513 )
3514 .expect("Creating descriptor");
3515 let mut buf = object.allocate_buffer(fs.block_size().get() as usize).await;
3516 let mut temp = vec![0u8; fs.block_size().get() as usize];
3517 descriptor.write_to_slice(&mut temp).expect("Writing descriptor to buf");
3518 buf.copy_from_slice(&temp);
3519 object
3520 .multi_write(
3521 &mut transaction,
3522 AttributeId::FSVERITY_MERKLE,
3523 &[fs.block_size().get()..(fs.block_size() * 2)],
3524 buf.as_mut(),
3525 )
3526 .await
3527 .expect("Writing descriptor");
3528 }
3529 transaction.commit().await.unwrap();
3530
3531 let handle =
3532 ObjectStore::open_object(&store, object.object_id(), HandleOptions::default(), None)
3533 .await
3534 .expect("open_object failed");
3535
3536 assert!(handle.is_verified_file());
3537
3538 let mut buf = object.allocate_buffer(file_size as usize).await;
3539 assert_eq!(
3540 handle.read_aligned(0, buf.as_mut()).await.expect("Read whole file."),
3541 file_size as usize
3542 );
3543
3544 fs.close().await.expect("Close failed");
3545 }
3546
3547 #[fuchsia::test]
3548 async fn test_verify_data_corrupt_tree() {
3549 let fs: OpenFxFilesystem = test_filesystem().await;
3550 let object_id = {
3551 let store = fs.root_store();
3552 let mut transaction = fs
3553 .root_store()
3554 .new_transaction(lock_keys![], Options::default())
3555 .await
3556 .expect("new_transaction failed");
3557 let object = Arc::new(
3558 ObjectStore::create_object(
3559 &store,
3560 &mut transaction,
3561 HandleOptions::default(),
3562 None,
3563 )
3564 .await
3565 .expect("create_object failed"),
3566 );
3567 let object_id = object.object_id();
3568
3569 transaction.commit().await.unwrap();
3570
3571 let mut buf = object.allocate_buffer(5 * fs.block_size().get() as usize).await;
3572 buf.fill(123);
3573 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3574
3575 object
3576 .enable_verity(fio::VerificationOptions {
3577 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3578 salt: Some(vec![]),
3579 ..Default::default()
3580 })
3581 .await
3582 .expect("set verified file metadata failed");
3583 object.read_aligned(0, buf.as_mut()).await.expect("verified read");
3584
3585 let mut merkle = object
3587 .read_attr(AttributeId::FSVERITY_MERKLE)
3588 .await
3589 .unwrap()
3590 .expect("Reading merkle tree");
3591 merkle[0] = merkle[0].wrapping_add(1);
3592 object
3593 .write_attr(AttributeId::FSVERITY_MERKLE, &*merkle)
3594 .await
3595 .expect("Overwriting merkle");
3596
3597 object_id
3598 }; assert!(
3602 ObjectStore::open_object(&fs.root_store(), object_id, HandleOptions::default(), None)
3603 .await
3604 .is_err()
3605 );
3606 fs.close().await.expect("Close failed");
3607 }
3608
3609 #[fuchsia::test]
3610 async fn test_allocate_verity_file() {
3611 let fs: OpenFxFilesystem = test_filesystem().await;
3612 let mut transaction = fs
3613 .root_store()
3614 .new_transaction(lock_keys![], Options::default())
3615 .await
3616 .expect("new_transaction failed");
3617 let store = fs.root_store();
3618 let object = Arc::new(
3619 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3620 .await
3621 .expect("create_object failed"),
3622 );
3623 transaction.commit().await.unwrap();
3624
3625 let mut buf = object.allocate_buffer(8192).await;
3626 buf.fill(0xAA);
3627 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3628
3629 object
3630 .enable_verity(fio::VerificationOptions {
3631 hash_algorithm: Some(fio::HashAlgorithm::Sha256),
3632 salt: Some(vec![]),
3633 ..Default::default()
3634 })
3635 .await
3636 .expect("enable_verity failed");
3637
3638 assert!(object.is_verified_file());
3639
3640 assert!(object.allocate(0..8192).await.is_err());
3642
3643 let reopened =
3645 ObjectStore::open_object(&store, object.object_id(), HandleOptions::default(), None)
3646 .await
3647 .expect("open_object failed");
3648 assert!(reopened.is_verified_file());
3649
3650 fs.close().await.expect("Close failed");
3651 }
3652
3653 #[fuchsia::test]
3654 async fn test_extend() {
3655 let fs = test_filesystem().await;
3656 let handle;
3657 let mut transaction = fs
3658 .root_store()
3659 .new_transaction(lock_keys![], Options::default())
3660 .await
3661 .expect("new_transaction failed");
3662 let store = fs.root_store();
3663 handle =
3664 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
3665 .await
3666 .expect("create_object failed");
3667
3668 const START_OFFSET: u64 = 2048 * 1024;
3672 handle
3673 .extend(&mut transaction, START_OFFSET..START_OFFSET + 5 * fs.block_size())
3674 .await
3675 .expect("extend failed");
3676 transaction.commit().await.expect("commit failed");
3677 let mut buf = handle.allocate_buffer(5 * fs.block_size().get() as usize).await;
3678 buf.fill(123);
3679 handle.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3680 buf.fill(67);
3681 handle.read_aligned(0, buf.as_mut()).await.expect("read failed");
3682 assert_eq!(buf.to_vec(), vec![123; 5 * fs.block_size().get() as usize]);
3683 fs.close().await.expect("Close failed");
3684 }
3685
3686 #[fuchsia::test]
3687 async fn test_truncate_deallocates_old_extents() {
3688 let (fs, object) = test_filesystem_and_object().await;
3689 let mut buf = object.allocate_buffer(5 * fs.block_size().get() as usize).await;
3690 buf.fill(0xaa);
3691 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
3692
3693 let allocator = fs.allocator();
3694 let allocated_before = allocator.get_allocated_bytes();
3695 object.truncate(fs.block_size().get()).await.expect("truncate failed");
3696 let allocated_after = allocator.get_allocated_bytes();
3697 assert!(
3698 allocated_after < allocated_before,
3699 "before = {} after = {}",
3700 allocated_before,
3701 allocated_after
3702 );
3703 fs.close().await.expect("Close failed");
3704 }
3705
3706 #[fuchsia::test]
3707 async fn test_truncate_zeroes_tail_block() {
3708 let (fs, object) = test_filesystem_and_object().await;
3709
3710 WriteObjectHandle::truncate(&object, TEST_DATA_OFFSET + 3).await.expect("truncate failed");
3711 WriteObjectHandle::truncate(&object, TEST_DATA_OFFSET + TEST_DATA.len() as u64)
3712 .await
3713 .expect("truncate failed");
3714
3715 let mut buf = object.allocate_buffer(fs.block_size().get() as usize).await;
3716 let offset = (TEST_DATA_OFFSET % fs.block_size()) as usize;
3717 object
3718 .read_aligned(TEST_DATA_OFFSET - offset as u64, buf.as_mut())
3719 .await
3720 .expect("read failed");
3721
3722 let mut expected = TEST_DATA.to_vec();
3723 expected[3..].fill(0);
3724 assert_eq!(
3725 &buf.as_ptr_slice().subslice(offset..offset + expected.len()).to_vec()[..],
3726 &expected
3727 );
3728 }
3729
3730 #[fuchsia::test]
3731 async fn test_trim() {
3732 let device = DeviceHolder::new(FakeDevice::new(8192, TEST_DEVICE_BLOCK_SIZE));
3734 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
3735 let block_size = fs.block_size();
3736 root_volume(fs.clone())
3737 .await
3738 .expect("root_volume failed")
3739 .new_volume("test", NewChildStoreOptions::default())
3740 .await
3741 .expect("volume failed");
3742 fs.close().await.expect("close failed");
3743 let device = fs.take_device().await;
3744 device.reopen(false);
3745
3746 #[derive(Default)]
3751 struct Context {
3752 fs: Option<Weak<FxFilesystem>>,
3753 store: Option<Arc<ObjectStore>>,
3754 object_id: Option<u64>,
3755 }
3756 let shared_context = Arc::new(Mutex::new(Context::default()));
3757
3758 let object_size = (TRANSACTION_MUTATION_THRESHOLD as u64 + 10) * 2 * block_size;
3759
3760 async fn expect_tombstoned(store: &Arc<ObjectStore>, object_id: u64) {
3762 loop {
3763 if let Err(e) =
3764 ObjectStore::open_object(store, object_id, HandleOptions::default(), None).await
3765 {
3766 assert!(
3767 FxfsError::NotFound.matches(&e),
3768 "open_object didn't fail with NotFound: {:?}",
3769 e
3770 );
3771 break;
3772 }
3773 fasync::Timer::new(std::time::Duration::from_millis(100)).await;
3775 }
3776 }
3777
3778 async fn needs_trim(store: &Arc<ObjectStore>) -> Option<DataObjectHandle<ObjectStore>> {
3780 let root_directory = Directory::open(store, store.root_directory_object_id())
3781 .await
3782 .expect("open failed");
3783 let oid = root_directory.lookup("foo").await.expect("lookup failed");
3784 if let Some((oid, _, _)) = oid {
3785 let object = ObjectStore::open_object(store, oid, HandleOptions::default(), None)
3786 .await
3787 .expect("open_object failed");
3788 let props = object.get_properties().await.expect("get_properties failed");
3789 if props.allocated_size > 0 && props.data_attribute_size == 0 {
3790 Some(object)
3791 } else {
3792 None
3793 }
3794 } else {
3795 None
3796 }
3797 }
3798
3799 let shared_context_clone = shared_context.clone();
3800 let post_commit = move || {
3801 let (fs, store) = {
3802 let context = shared_context_clone.lock();
3803 (
3804 context.fs.as_ref().unwrap().upgrade().unwrap(),
3805 context.store.as_ref().cloned().unwrap(),
3806 )
3807 };
3808 let shared_context = shared_context_clone.clone();
3809 async move {
3810 let options = FsckOptions {
3812 fail_on_warning: true,
3813 no_lock: true,
3814 on_error: Box::new(|err| println!("fsck error: {:?}", err)),
3815 ..Default::default()
3816 };
3817
3818 fsck_with_options(fs.clone(), &options).await.expect("fsck_with_options failed");
3819 fsck_volume_with_options(fs.as_ref(), &options, store.store_object_id(), None)
3820 .await
3821 .expect("fsck_volume_with_options failed");
3822
3823 fs.sync(SyncOptions { flush_device: true, ..Default::default() })
3825 .await
3826 .expect("sync failed");
3827 let device = fs.device().snapshot().expect("snapshot failed");
3828
3829 let object_id = shared_context.lock().object_id.clone();
3830
3831 let fs2 = FxFilesystemBuilder::new()
3832 .skip_initial_reap(object_id.is_none())
3833 .open(device)
3834 .await
3835 .expect("open failed");
3836
3837 let root_vol = root_volume(fs2.clone()).await.expect("root_volume failed");
3839 let store =
3840 root_vol.volume("test", StoreOptions::default()).await.expect("volume failed");
3841
3842 if let Some(oid) = object_id {
3843 expect_tombstoned(&store, oid).await;
3845 } else if let Some(object) = needs_trim(&store).await {
3846 object.truncate(object_size).await.expect("truncate failed");
3848 let mut buf = object.allocate_buffer(block_size.get() as usize).await;
3849 object
3850 .read_aligned(object_size - block_size * 2, buf.as_mut())
3851 .await
3852 .expect("read failed");
3853 assert_eq!(buf.to_vec(), vec![0; block_size.get() as usize]);
3854
3855 let fs = FxFilesystem::open(fs.device().snapshot().expect("snapshot failed"))
3858 .await
3859 .expect("open failed");
3860 let root_vol = root_volume(fs.clone()).await.expect("root_volume failed");
3861 let store = root_vol
3862 .volume("test", StoreOptions::default())
3863 .await
3864 .expect("volume failed");
3865 while needs_trim(&store).await.is_some() {
3866 fasync::Timer::new(std::time::Duration::from_millis(100)).await;
3869 }
3870
3871 fsck_with_options(fs.clone(), &options)
3873 .await
3874 .expect("fsck_with_options failed");
3875 fsck_volume_with_options(fs.as_ref(), &options, store.store_object_id(), None)
3876 .await
3877 .expect("fsck_volume_with_options failed");
3878 fs.close().await.expect("close failed");
3879 }
3880
3881 fsck_with_options(fs2.clone(), &options).await.expect("fsck_with_options failed");
3883 fsck_volume_with_options(fs2.as_ref(), &options, store.store_object_id(), None)
3884 .await
3885 .expect("fsck_volume_with_options failed");
3886 fs2.close().await.expect("close failed");
3887 }
3888 .boxed()
3889 };
3890
3891 let fs = FxFilesystemBuilder::new()
3892 .post_commit_hook(post_commit)
3893 .open(device)
3894 .await
3895 .expect("open failed");
3896
3897 let root_vol = root_volume(fs.clone()).await.expect("root_volume failed");
3898 let store = root_vol.volume("test", StoreOptions::default()).await.expect("volume failed");
3899
3900 {
3901 let mut context = shared_context.lock();
3902 context.fs = Some(Arc::downgrade(&fs));
3903 context.store = Some(store.clone());
3904 }
3905
3906 let root_directory =
3907 Directory::open(&store, store.root_directory_object_id()).await.expect("open failed");
3908
3909 let object;
3910 let mut transaction = fs
3911 .root_store()
3912 .new_transaction(
3913 lock_keys![LockKey::object(
3914 store.store_object_id(),
3915 store.root_directory_object_id()
3916 )],
3917 Options::default(),
3918 )
3919 .await
3920 .expect("new_transaction failed");
3921 object = root_directory
3922 .create_child_file(&mut transaction, "foo")
3923 .await
3924 .expect("create_object failed");
3925 transaction.commit().await.expect("commit failed");
3926
3927 let mut transaction = fs
3928 .root_store()
3929 .new_transaction(
3930 lock_keys![LockKey::object(store.store_object_id(), object.object_id())],
3931 Options::default(),
3932 )
3933 .await
3934 .expect("new_transaction failed");
3935
3936 let mut pass = 0;
3939 loop {
3940 let mut buf = object.allocate_buffer(5).await;
3943 buf.fill(1);
3944 for offset in (0..object_size).into_iter().step_by((2 * block_size) as usize) {
3946 object
3947 .txn_write(&mut transaction, offset, buf.as_ref())
3948 .await
3949 .expect("write failed");
3950 }
3951 transaction.commit().await.expect("commit failed");
3952 WriteObjectHandle::truncate(&object, 0).await.expect("truncate failed");
3954
3955 if pass == 1 {
3956 break;
3957 }
3958
3959 shared_context.lock().object_id = Some(object.object_id());
3962
3963 transaction = fs
3964 .root_store()
3965 .new_transaction(
3966 lock_keys![
3967 LockKey::object(store.store_object_id(), store.root_directory_object_id()),
3968 LockKey::object(store.store_object_id(), object.object_id()),
3969 ],
3970 Options::default(),
3971 )
3972 .await
3973 .expect("new_transaction failed");
3974
3975 replace_child(&mut transaction, None, (&root_directory, "foo"))
3977 .await
3978 .expect("replace_child failed");
3979 store.add_to_graveyard(&mut transaction, object.object_id());
3980
3981 pass += 1;
3982 }
3983
3984 fs.close().await.expect("Close failed");
3985 }
3986
3987 #[fuchsia::test]
3988 async fn test_adjust_refs() {
3989 let (fs, object) = test_filesystem_and_object().await;
3990 let store = object.owner();
3991 let mut transaction = fs
3992 .root_store()
3993 .new_transaction(
3994 lock_keys![LockKey::object(store.store_object_id(), object.object_id())],
3995 Options::default(),
3996 )
3997 .await
3998 .expect("new_transaction failed");
3999 assert_eq!(
4000 store
4001 .adjust_refs(&mut transaction, object.object_id(), 1)
4002 .await
4003 .expect("adjust_refs failed"),
4004 false
4005 );
4006 transaction.commit().await.expect("commit failed");
4007
4008 let allocator = fs.allocator();
4009 let allocated_before = allocator.get_allocated_bytes();
4010 let mut transaction = fs
4011 .root_store()
4012 .new_transaction(
4013 lock_keys![LockKey::object(store.store_object_id(), object.object_id())],
4014 Options::default(),
4015 )
4016 .await
4017 .expect("new_transaction failed");
4018 assert_eq!(
4019 store
4020 .adjust_refs(&mut transaction, object.object_id(), -2)
4021 .await
4022 .expect("adjust_refs failed"),
4023 true
4024 );
4025 transaction.commit().await.expect("commit failed");
4026
4027 assert_eq!(allocator.get_allocated_bytes(), allocated_before);
4028
4029 store
4030 .tombstone_object(object.object_id(), Options::default(), None)
4031 .await
4032 .expect("purge failed");
4033
4034 assert_eq!(allocated_before - allocator.get_allocated_bytes(), fs.block_size());
4035
4036 {
4038 let mut transaction = fs
4039 .root_store()
4040 .new_transaction(
4041 lock_keys![LockKey::object(
4042 store.store_object_id(),
4043 store.root_directory_object_id()
4044 )],
4045 Options::default(),
4046 )
4047 .await
4048 .expect("new_transaction failed");
4049 let root_directory = Directory::open(&store, store.root_directory_object_id())
4050 .await
4051 .expect("open failed");
4052 transaction.add(
4053 store.store_object_id(),
4054 Mutation::replace_or_insert_object(
4055 ObjectKey::child(root_directory.object_id(), TEST_OBJECT_NAME, DirType::Normal),
4056 ObjectValue::None,
4057 ),
4058 );
4059 transaction.commit().await.expect("commit failed");
4060 }
4061
4062 fsck_with_options(
4063 fs.clone(),
4064 &FsckOptions {
4065 fail_on_warning: true,
4066 on_error: Box::new(|err| println!("fsck error: {:?}", err)),
4067 ..Default::default()
4068 },
4069 )
4070 .await
4071 .expect("fsck_with_options failed");
4072
4073 fs.close().await.expect("Close failed");
4074 }
4075
4076 #[fuchsia::test]
4077 async fn test_locks() {
4078 let (fs, object) = test_filesystem_and_object().await;
4079 let (send1, recv1) = channel();
4080 let (send2, recv2) = channel();
4081 let (send3, recv3) = channel();
4082 let done = Mutex::new(false);
4083 let mut futures = FuturesUnordered::new();
4084 futures.push(
4085 async {
4086 let mut t = object.new_transaction().await.expect("new_transaction failed");
4087 send1.send(()).unwrap(); send3.send(()).unwrap(); recv2.await.unwrap();
4090 let mut buf = object.allocate_buffer(5).await;
4091 buf.copy_from_slice(b"hello");
4092 object.txn_write(&mut t, 0, buf.as_ref()).await.expect("write failed");
4093 fasync::Timer::new(Duration::from_millis(100)).await;
4095 assert!(!*done.lock());
4096 t.commit().await.expect("commit failed");
4097 }
4098 .boxed(),
4099 );
4100 futures.push(
4101 async {
4102 recv1.await.unwrap();
4103 let data = object
4105 .read_bytes(TEST_DATA_OFFSET..(TEST_DATA_OFFSET + TEST_DATA.len() as u64))
4106 .await
4107 .expect("read failed");
4108 assert_eq!(&*data, TEST_DATA);
4109 send2.send(()).unwrap();
4111 }
4112 .boxed(),
4113 );
4114 futures.push(
4115 async {
4116 recv3.await.unwrap();
4118 let _t = object.new_transaction().await.expect("new_transaction failed");
4119 let data = object.read_bytes(0..5).await.expect("read failed");
4120 assert_eq!(&*data, b"hello");
4121 }
4122 .boxed(),
4123 );
4124 while let Some(()) = futures.next().await {}
4125 fs.close().await.expect("Close failed");
4126 }
4127
4128 #[fuchsia::test(threads = 10)]
4129 async fn test_racy_reads() {
4130 let fs = test_filesystem().await;
4131 let object;
4132 let mut transaction = fs
4133 .root_store()
4134 .new_transaction(lock_keys![], Options::default())
4135 .await
4136 .expect("new_transaction failed");
4137 let store = fs.root_store();
4138 object = Arc::new(
4139 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
4140 .await
4141 .expect("create_object failed"),
4142 );
4143 transaction.commit().await.expect("commit failed");
4144 for _ in 0..100 {
4145 let cloned_object = object.clone();
4146 let writer = fasync::Task::spawn(async move {
4147 let mut buf = cloned_object.allocate_buffer(10).await;
4148 buf.fill(123);
4149 cloned_object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
4150 });
4151 let cloned_object = object.clone();
4152 let reader = fasync::Task::spawn(async move {
4153 let wait_time = rand::random_range(0..5);
4154 fasync::Timer::new(Duration::from_millis(wait_time)).await;
4155 let mut buf =
4156 cloned_object.allocate_buffer(cloned_object.block_size().get() as usize).await;
4157 buf.fill(23);
4158 let amount =
4159 cloned_object.read_aligned(0, buf.as_mut()).await.expect("read failed");
4160 if amount != 0 {
4165 assert_eq!(amount, 10);
4166 assert_eq!(&buf.as_ptr_slice().subslice(0..10).to_vec()[..], &[123; 10]);
4167 }
4168 });
4169 writer.await;
4170 reader.await;
4171 object.truncate(0).await.expect("truncate failed");
4172 }
4173 fs.close().await.expect("Close failed");
4174 }
4175
4176 #[fuchsia::test]
4177 async fn test_allocated_size() {
4178 let (fs, object) = test_filesystem_and_object_with_key(None, true).await;
4179
4180 let before = object.get_properties().await.expect("get_properties failed").allocated_size;
4181 let mut buf = object.allocate_buffer(5).await;
4182 buf.copy_from_slice(b"hello");
4183 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
4184 let after = object.get_properties().await.expect("get_properties failed").allocated_size;
4185 assert_eq!(after, before + fs.block_size());
4186
4187 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
4189 assert_eq!(
4190 object.get_properties().await.expect("get_properties failed").allocated_size,
4191 after
4192 );
4193
4194 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
4196 let offset = 1000 * fs.block_size();
4197 let before = after;
4198 object
4199 .extend(&mut transaction, offset..offset + fs.block_size())
4200 .await
4201 .expect("extend failed");
4202 transaction.commit().await.expect("commit failed");
4203 let after = object.get_properties().await.expect("get_properties failed").allocated_size;
4204 assert_eq!(after, before + fs.block_size());
4205
4206 let before = after;
4208 let size = object.get_size();
4209 object.truncate(size - fs.block_size()).await.expect("extend failed");
4210 let after = object.get_properties().await.expect("get_properties failed").allocated_size;
4211 assert_eq!(after, before - fs.block_size());
4212
4213 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
4215 let before = after;
4216 let mut file_range = offset..offset + fs.block_size();
4217 object.preallocate_range(&mut transaction, &mut file_range).await.expect("extend failed");
4218 transaction.commit().await.expect("commit failed");
4219 let after = object.get_properties().await.expect("get_properties failed").allocated_size;
4220 assert_eq!(after, before + fs.block_size());
4221 fs.close().await.expect("Close failed");
4222 }
4223
4224 #[fuchsia::test(threads = 10)]
4225 async fn test_zero() {
4226 let (fs, object) = test_filesystem_and_object().await;
4227 let expected_size = object.get_size();
4228 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
4229 object.zero(&mut transaction, 0..fs.block_size() * 10).await.expect("zero failed");
4230 transaction.commit().await.expect("commit failed");
4231 assert_eq!(object.get_size(), expected_size);
4232 let mut buf = object.allocate_buffer((fs.block_size() * 10) as usize).await;
4233 assert_eq!(
4234 object.read_aligned(0, buf.as_mut()).await.expect("read failed") as u64,
4235 expected_size
4236 );
4237 assert_eq!(
4238 &buf.as_ptr_slice().subslice(0..expected_size as usize).to_vec()[..],
4239 vec![0u8; expected_size as usize].as_slice()
4240 );
4241 fs.close().await.expect("Close failed");
4242 }
4243
4244 #[fuchsia::test]
4245 async fn test_properties() {
4246 let (fs, object) = test_filesystem_and_object().await;
4247 const CRTIME: Timestamp = Timestamp::from_nanos(1234);
4248 const MTIME: Timestamp = Timestamp::from_nanos(5678);
4249 const CTIME: Timestamp = Timestamp::from_nanos(8765);
4250
4251 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
4254 object
4255 .update_attributes(
4256 &mut transaction,
4257 Some(&fio::MutableNodeAttributes {
4258 creation_time: Some(CRTIME.as_nanos()),
4259 modification_time: Some(MTIME.as_nanos()),
4260 mode: Some(111),
4261 gid: Some(222),
4262 ..Default::default()
4263 }),
4264 None,
4265 )
4266 .await
4267 .expect("update_attributes failed");
4268 const MTIME_NEW: Timestamp = Timestamp::from_nanos(12345678);
4269 object
4270 .update_attributes(
4271 &mut transaction,
4272 Some(&fio::MutableNodeAttributes {
4273 modification_time: Some(MTIME_NEW.as_nanos()),
4274 gid: Some(333),
4275 rdev: Some(444),
4276 ..Default::default()
4277 }),
4278 Some(CTIME),
4279 )
4280 .await
4281 .expect("update_timestamps failed");
4282 transaction.commit().await.expect("commit failed");
4283
4284 let properties = object.get_properties().await.expect("get_properties failed");
4285 assert_matches!(
4286 properties,
4287 ObjectProperties {
4288 refs: 1u64,
4289 allocated_size: TEST_OBJECT_ALLOCATED_SIZE,
4290 data_attribute_size: TEST_OBJECT_SIZE,
4291 creation_time: CRTIME,
4292 modification_time: MTIME_NEW,
4293 posix_attributes: Some(PosixAttributes { mode: 111, gid: 333, rdev: 444, .. }),
4294 change_time: CTIME,
4295 ..
4296 }
4297 );
4298 fs.close().await.expect("Close failed");
4299 }
4300
4301 #[fuchsia::test]
4302 async fn test_is_allocated() {
4303 let (fs, object) = test_filesystem_and_object().await;
4304
4305 let aligned_offset = fs.block_size().align_down(TEST_DATA_OFFSET);
4308 let aligned_length = fs.block_size().align_up(TEST_DATA.len() as u64).unwrap();
4309
4310 let (allocated, count) = object.is_allocated(0).await.expect("is_allocated failed");
4314 assert_eq!(count, aligned_offset);
4315 assert_eq!(allocated, false);
4316
4317 let (allocated, count) =
4318 object.is_allocated(aligned_offset).await.expect("is_allocated failed");
4319 assert_eq!(count, aligned_length);
4320 assert_eq!(allocated, true);
4321
4322 let end = aligned_offset + aligned_length;
4324 object
4325 .is_allocated(end)
4326 .await
4327 .expect_err("is_allocated should have returned ERR_OUT_OF_RANGE");
4328
4329 let size = 50 * fs.block_size();
4332 object.truncate(size).await.expect("extend failed");
4333
4334 let (allocated, count) = object.is_allocated(end).await.expect("is_allocated failed");
4335 assert_eq!(count, size - end);
4336 assert_eq!(allocated, false);
4337
4338 let buf_length = 5 * fs.block_size();
4341 let mut buf = object.allocate_buffer(buf_length as usize).await;
4342 buf.fill(123);
4343 let new_offset = end + 20 * fs.block_size();
4344 object.write_or_append(Some(new_offset), buf.as_ref()).await.expect("write failed");
4345 object
4346 .write_or_append(Some(new_offset + buf_length), buf.as_ref())
4347 .await
4348 .expect("write failed");
4349
4350 let (allocated, count) = object.is_allocated(end).await.expect("is_allocated failed");
4351 assert_eq!(count, new_offset - end);
4352 assert_eq!(allocated, false);
4353
4354 let (allocated, count) =
4355 object.is_allocated(new_offset).await.expect("is_allocated failed");
4356 assert_eq!(count, 2 * buf_length);
4357 assert_eq!(allocated, true);
4358
4359 let (allocated, count) = object
4361 .is_allocated(new_offset + 4 * fs.block_size())
4362 .await
4363 .expect("is_allocated failed");
4364 assert_eq!(count, 2 * buf_length - 4 * fs.block_size());
4365 assert_eq!(allocated, true);
4366
4367 let other_buf_length = 3 * fs.block_size();
4371 let mut other_buf = object.allocate_buffer(other_buf_length as usize).await;
4372 other_buf.fill(231);
4373 object.write_or_append(Some(new_offset), other_buf.as_ref()).await.expect("write failed");
4374
4375 let (allocated, count) =
4378 object.is_allocated(new_offset).await.expect("is_allocated failed");
4379 assert_eq!(count, 2 * buf_length);
4380 assert_eq!(allocated, true);
4381
4382 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
4386 object
4387 .zero(&mut transaction, aligned_offset..aligned_offset + aligned_length)
4388 .await
4389 .expect("zero failed");
4390 object
4392 .zero(&mut transaction, new_offset..new_offset + buf_length)
4393 .await
4394 .expect("zero failed");
4395 transaction.commit().await.expect("commit transaction failed");
4396
4397 let (allocated, count) = object.is_allocated(0).await.expect("is_allocated failed");
4398 assert_eq!(count, new_offset + buf_length);
4399 assert_eq!(allocated, false);
4400
4401 let (allocated, count) =
4402 object.is_allocated(new_offset + buf_length).await.expect("is_allocated failed");
4403 assert_eq!(count, buf_length);
4404 assert_eq!(allocated, true);
4405
4406 let new_end = new_offset + buf_length + count;
4407
4408 let store = object.owner();
4412 let mut transaction = fs
4413 .root_store()
4414 .new_transaction(lock_keys![], Options::default())
4415 .await
4416 .expect("new_transaction failed");
4417 let object2 =
4418 ObjectStore::create_object(&store, &mut transaction, HandleOptions::default(), None)
4419 .await
4420 .expect("create_object failed");
4421 transaction.commit().await.expect("commit failed");
4422
4423 object2
4424 .write_or_append(Some(new_end + fs.block_size()), buf.as_ref())
4425 .await
4426 .expect("write failed");
4427
4428 let (allocated, count) = object.is_allocated(new_end).await.expect("is_allocated failed");
4430 assert_eq!(count, size - new_end);
4431 assert_eq!(allocated, false);
4432
4433 fs.close().await.expect("close failed");
4434 }
4435
4436 #[fuchsia::test(threads = 10)]
4437 async fn test_read_write_attr() {
4438 let (_fs, object) = test_filesystem_and_object().await;
4439 let data = [0xffu8; 16_384];
4440 object.write_attr(AttributeId(20), &data).await.expect("write_attr failed");
4441 let rdata = object
4442 .read_attr(AttributeId(20))
4443 .await
4444 .expect("read_attr failed")
4445 .expect("no attribute data found");
4446 assert_eq!(&data[..], &rdata[..]);
4447
4448 assert_eq!(object.read_attr(AttributeId(21)).await.expect("read_attr failed"), None);
4449 }
4450
4451 #[fuchsia::test(threads = 10)]
4452 async fn test_read_write_attr_unaligned() {
4453 let (_fs, object) = test_filesystem_and_object().await;
4454 let data_unaligned = [0x55u8; 5000];
4455 object.write_attr(AttributeId(22), &data_unaligned).await.expect("write_attr failed");
4456 let rdata = object
4457 .read_attr(AttributeId(22))
4458 .await
4459 .expect("read_attr failed")
4460 .expect("no attribute data found");
4461 assert_eq!(&data_unaligned[..], &rdata[..]);
4462 }
4463
4464 #[fuchsia::test(threads = 10)]
4465 async fn test_read_write_attr_empty() {
4466 let (_fs, object) = test_filesystem_and_object().await;
4467 object.write_attr(AttributeId(23), &[]).await.expect("write_attr failed");
4468 let rdata = object
4469 .read_attr(AttributeId(23))
4470 .await
4471 .expect("read_attr failed")
4472 .expect("no attribute data found");
4473 assert!(rdata.is_empty());
4474 }
4475
4476 #[fuchsia::test(threads = 10)]
4477 async fn test_allocate_basic() {
4478 let (fs, object) = test_filesystem_and_empty_object().await;
4479 let block_size = fs.block_size();
4480 let file_size = block_size * 10;
4481 object.truncate(file_size).await.unwrap();
4482
4483 let small_buf_size = block_size.get() as usize;
4484 let medium_buf_size = (block_size * 2) as usize;
4485 let large_buf_size = (block_size * 3) as usize;
4486
4487 let mut small_buf = object.allocate_buffer(small_buf_size).await;
4488 let mut medium_buf = object.allocate_buffer(medium_buf_size).await;
4489 let mut large_buf = object.allocate_buffer(large_buf_size).await;
4490
4491 assert_eq!(object.read_aligned(0, small_buf.as_mut()).await.unwrap(), small_buf_size);
4492 assert_eq!(small_buf.to_vec(), vec![0; small_buf_size]);
4493 assert_eq!(object.read_aligned(0, large_buf.as_mut()).await.unwrap(), large_buf_size);
4494 assert_eq!(large_buf.to_vec(), vec![0; large_buf_size]);
4495 assert_eq!(object.read_aligned(0, medium_buf.as_mut()).await.unwrap(), medium_buf_size);
4496 assert_eq!(medium_buf.to_vec(), vec![0; medium_buf_size]);
4497
4498 object.allocate(block_size.get()..block_size * 3).await.unwrap();
4500
4501 for (buf_index, buf) in [small_buf, large_buf, medium_buf].iter_mut().enumerate() {
4503 for offset in 0..4 {
4504 assert_eq!(
4505 object.read_aligned(block_size * offset, buf.as_mut()).await.unwrap(),
4506 buf.len(),
4507 "buf_index: {}, read offset: {}",
4508 buf_index,
4509 offset,
4510 );
4511 assert_eq!(
4512 &buf.to_vec(),
4513 &vec![0; buf.len()],
4514 "buf_index: {}, read offset: {}",
4515 buf_index,
4516 offset,
4517 );
4518 }
4519 }
4520
4521 fs.close().await.expect("close failed");
4522 }
4523
4524 #[fuchsia::test(threads = 10)]
4525 async fn test_allocate_extends_file() {
4526 let (fs, object) = test_filesystem_and_empty_object().await;
4527 let block_size = fs.block_size();
4528 let buf_size = block_size.get() as usize;
4529 let mut buf = object.allocate_buffer(buf_size).await;
4530
4531 assert_eq!(object.read_aligned(0, buf.as_mut()).await.unwrap(), buf.len());
4532 assert_eq!(buf.to_vec(), vec![0; buf_size]);
4533
4534 assert!(TEST_OBJECT_SIZE < block_size * 4);
4535 object.allocate(0..block_size * 4).await.unwrap();
4537 assert_eq!(object.read_aligned(0, buf.as_mut()).await.unwrap(), buf.len());
4538 assert_eq!(buf.to_vec(), vec![0; buf_size]);
4539 assert_eq!(object.read_aligned(block_size.get(), buf.as_mut()).await.unwrap(), buf.len());
4540 assert_eq!(buf.to_vec(), vec![0; buf_size]);
4541 assert_eq!(object.read_aligned(block_size * 3, buf.as_mut()).await.unwrap(), buf.len());
4542 assert_eq!(buf.to_vec(), vec![0; buf_size]);
4543
4544 fs.close().await.expect("close failed");
4545 }
4546
4547 #[fuchsia::test(threads = 10)]
4548 async fn test_allocate_past_end() {
4549 let (fs, object) = test_filesystem_and_empty_object().await;
4550 let block_size = fs.block_size();
4551 let buf_size = block_size.get() as usize;
4552 let mut buf = object.allocate_buffer(buf_size).await;
4553
4554 assert_eq!(object.read_aligned(0, buf.as_mut()).await.unwrap(), buf.len());
4555 assert_eq!(buf.to_vec(), vec![0; buf_size]);
4556
4557 assert!(TEST_OBJECT_SIZE < block_size * 4);
4558 object.allocate(block_size * 4..block_size * 6).await.unwrap();
4560 assert_eq!(object.read_aligned(0, buf.as_mut()).await.unwrap(), buf.len());
4561 assert_eq!(buf.to_vec(), vec![0; buf_size]);
4562 assert_eq!(object.read_aligned(block_size * 4, buf.as_mut()).await.unwrap(), buf.len());
4563 assert_eq!(buf.to_vec(), vec![0; buf_size]);
4564 assert_eq!(object.read_aligned(block_size * 5, buf.as_mut()).await.unwrap(), buf.len());
4565 assert_eq!(buf.to_vec(), vec![0; buf_size]);
4566
4567 fs.close().await.expect("close failed");
4568 }
4569
4570 #[fuchsia::test(threads = 10)]
4571 async fn test_allocate_read_attr() {
4572 let (fs, object) = test_filesystem_and_empty_object().await;
4573 let block_size = fs.block_size();
4574 let file_size = block_size * 4;
4575 object.truncate(file_size).await.unwrap();
4576
4577 let content = object
4578 .read_attr(object.attribute_id())
4579 .await
4580 .expect("failed to read attr")
4581 .expect("attr returned none");
4582 assert_eq!(content.as_ref(), &vec![0; file_size as usize]);
4583
4584 object.allocate(block_size.get()..block_size * 3).await.unwrap();
4585
4586 let content = object
4587 .read_attr(object.attribute_id())
4588 .await
4589 .expect("failed to read attr")
4590 .expect("attr returned none");
4591 assert_eq!(content.as_ref(), &vec![0; file_size as usize]);
4592
4593 fs.close().await.expect("close failed");
4594 }
4595
4596 #[fuchsia::test(threads = 10)]
4597 async fn test_allocate_existing_data() {
4598 struct Case {
4599 written_ranges: Vec<Range<usize>>,
4600 allocate_range: Range<u64>,
4601 }
4602 let cases = [
4603 Case { written_ranges: vec![4..7], allocate_range: 4..7 },
4604 Case { written_ranges: vec![4..7], allocate_range: 3..8 },
4605 Case { written_ranges: vec![4..7], allocate_range: 5..6 },
4606 Case { written_ranges: vec![4..7], allocate_range: 5..8 },
4607 Case { written_ranges: vec![4..7], allocate_range: 3..5 },
4608 Case { written_ranges: vec![0..1, 2..3, 4..5, 6..7, 8..9], allocate_range: 0..10 },
4609 Case { written_ranges: vec![0..2, 4..6, 7..10], allocate_range: 1..8 },
4610 ];
4611
4612 for case in cases {
4613 let (fs, object) = test_filesystem_and_empty_object().await;
4614 let block_size = fs.block_size();
4615 let file_size = block_size * 10;
4616 object.truncate(file_size).await.unwrap();
4617
4618 for write in &case.written_ranges {
4619 let write_len = (write.end - write.start) * block_size.get() as usize;
4620 let mut write_buf = object.allocate_buffer(write_len).await;
4621 write_buf.fill(0xff);
4622 assert_eq!(
4623 object
4624 .write_or_append(Some(block_size * write.start as u64), write_buf.as_ref())
4625 .await
4626 .unwrap(),
4627 file_size
4628 );
4629 }
4630
4631 let mut expected_buf = object.allocate_buffer(file_size as usize).await;
4632 assert_eq!(
4633 object.read_aligned(0, expected_buf.as_mut()).await.unwrap(),
4634 expected_buf.len()
4635 );
4636
4637 object
4638 .allocate(
4639 case.allocate_range.start * block_size..case.allocate_range.end * block_size,
4640 )
4641 .await
4642 .unwrap();
4643
4644 let mut read_buf = object.allocate_buffer(file_size as usize).await;
4645 assert_eq!(object.read_aligned(0, read_buf.as_mut()).await.unwrap(), read_buf.len());
4646 assert_eq!(read_buf.to_vec(), expected_buf.to_vec());
4647
4648 fs.close().await.expect("close failed");
4649 }
4650 }
4651
4652 async fn get_modes(
4653 obj: &DataObjectHandle<ObjectStore>,
4654 mut search_range: Range<u64>,
4655 ) -> Vec<(Range<u64>, ExtentMode)> {
4656 let mut modes = Vec::new();
4657 let store = obj.store();
4658 let tree = store.tree();
4659 let layer_set = tree.layer_set();
4660 let mut merger = layer_set.merger();
4661 let mut iter = merger
4662 .query(Query::FullRange(&ObjectKey::attribute(
4663 obj.object_id(),
4664 AttributeId::DATA,
4665 AttributeKey::Extent(Extent::search_key_from_offset(search_range.start)),
4666 )))
4667 .await
4668 .unwrap();
4669 loop {
4670 match iter.get() {
4671 Some(ItemRef {
4672 key:
4673 ObjectKey {
4674 object_id,
4675 data:
4676 ObjectKeyData::Attribute(
4677 AttributeId::DATA,
4678 AttributeKey::Extent(extent),
4679 ),
4680 },
4681 value: ObjectValue::Extent(ExtentValue::Some { mode, .. }),
4682 ..
4683 }) if *object_id == obj.object_id() => {
4684 if search_range.end <= extent.start {
4685 break;
4686 }
4687 let found_range = std::cmp::max(search_range.start, extent.start)
4688 ..std::cmp::min(search_range.end, extent.end);
4689 search_range.start = found_range.end;
4690 modes.push((found_range, mode.clone()));
4691 if search_range.start == search_range.end {
4692 break;
4693 }
4694 iter.advance().await.unwrap();
4695 }
4696 x => panic!("looking for extent record, found this {:?}", x),
4697 }
4698 }
4699 modes
4700 }
4701
4702 async fn assert_all_overwrite(
4703 obj: &DataObjectHandle<ObjectStore>,
4704 mut search_range: Range<u64>,
4705 ) {
4706 let modes = get_modes(obj, search_range.clone()).await;
4707 for mode in modes {
4708 assert_eq!(
4709 mode.0.start, search_range.start,
4710 "missing mode in range {}..{}",
4711 search_range.start, mode.0.start
4712 );
4713 match mode.1 {
4714 ExtentMode::Overwrite | ExtentMode::OverwritePartial(_) => (),
4715 m => panic!("mode at range {:?} was not overwrite, instead found {:?}", mode.0, m),
4716 }
4717 assert!(
4718 mode.0.end <= search_range.end,
4719 "mode ends beyond search range (bug in test) - search_range: {:?}, mode: {:?}",
4720 search_range,
4721 mode,
4722 );
4723 search_range.start = mode.0.end;
4724 }
4725 assert_eq!(
4726 search_range.start, search_range.end,
4727 "missing mode in range {:?}",
4728 search_range
4729 );
4730 }
4731
4732 #[fuchsia::test(threads = 10)]
4733 async fn test_multi_overwrite() {
4734 #[derive(Debug)]
4735 struct Case {
4736 pre_writes: Vec<Range<usize>>,
4737 allocate_ranges: Vec<Range<u64>>,
4738 overwrites: Vec<Vec<Range<u64>>>,
4739 }
4740 let cases = [
4741 Case {
4742 pre_writes: Vec::new(),
4743 allocate_ranges: vec![1..3],
4744 overwrites: vec![vec![1..3]],
4745 },
4746 Case {
4747 pre_writes: Vec::new(),
4748 allocate_ranges: vec![0..1, 1..2, 2..3, 3..4],
4749 overwrites: vec![vec![0..4]],
4750 },
4751 Case {
4752 pre_writes: Vec::new(),
4753 allocate_ranges: vec![0..4],
4754 overwrites: vec![vec![0..1], vec![1..2], vec![3..4]],
4755 },
4756 Case {
4757 pre_writes: Vec::new(),
4758 allocate_ranges: vec![0..4],
4759 overwrites: vec![vec![3..4]],
4760 },
4761 Case {
4762 pre_writes: Vec::new(),
4763 allocate_ranges: vec![0..4],
4764 overwrites: vec![vec![3..4], vec![2..3], vec![1..2]],
4765 },
4766 Case {
4767 pre_writes: Vec::new(),
4768 allocate_ranges: vec![1..2, 5..6, 7..8],
4769 overwrites: vec![vec![5..6]],
4770 },
4771 Case {
4772 pre_writes: Vec::new(),
4773 allocate_ranges: vec![1..3],
4774 overwrites: vec![
4775 vec![1..3],
4776 vec![1..3],
4777 vec![1..3],
4778 vec![1..3],
4779 vec![1..3],
4780 vec![1..3],
4781 vec![1..3],
4782 vec![1..3],
4783 ],
4784 },
4785 Case {
4786 pre_writes: Vec::new(),
4787 allocate_ranges: vec![0..5],
4788 overwrites: vec![
4789 vec![1..3],
4790 vec![1..3],
4791 vec![1..3],
4792 vec![1..3],
4793 vec![1..3],
4794 vec![1..3],
4795 vec![1..3],
4796 vec![1..3],
4797 ],
4798 },
4799 Case {
4800 pre_writes: Vec::new(),
4801 allocate_ranges: vec![0..5],
4802 overwrites: vec![vec![0..2, 2..4, 4..5]],
4803 },
4804 Case {
4805 pre_writes: Vec::new(),
4806 allocate_ranges: vec![0..5, 5..10],
4807 overwrites: vec![vec![1..2, 2..3, 4..7, 7..8]],
4808 },
4809 Case {
4810 pre_writes: Vec::new(),
4811 allocate_ranges: vec![0..4, 6..10],
4812 overwrites: vec![vec![2..3, 7..9]],
4813 },
4814 Case {
4815 pre_writes: Vec::new(),
4816 allocate_ranges: vec![0..10],
4817 overwrites: vec![vec![1..2, 5..10], vec![0..1, 5..10], vec![0..5, 5..10]],
4818 },
4819 Case {
4820 pre_writes: Vec::new(),
4821 allocate_ranges: vec![0..10],
4822 overwrites: vec![vec![0..2, 2..4, 4..6, 6..8, 8..10], vec![0..5, 5..10]],
4823 },
4824 Case {
4825 pre_writes: vec![1..3],
4826 allocate_ranges: vec![1..3],
4827 overwrites: vec![vec![1..3]],
4828 },
4829 Case {
4830 pre_writes: vec![1..3],
4831 allocate_ranges: vec![4..6],
4832 overwrites: vec![vec![5..6]],
4833 },
4834 Case {
4835 pre_writes: vec![1..3],
4836 allocate_ranges: vec![0..4],
4837 overwrites: vec![vec![0..4]],
4838 },
4839 Case {
4840 pre_writes: vec![1..3],
4841 allocate_ranges: vec![2..4],
4842 overwrites: vec![vec![2..4]],
4843 },
4844 Case {
4845 pre_writes: vec![3..5],
4846 allocate_ranges: vec![1..3, 6..7],
4847 overwrites: vec![vec![1..3, 6..7]],
4848 },
4849 Case {
4850 pre_writes: vec![1..3, 5..7, 8..9],
4851 allocate_ranges: vec![0..5],
4852 overwrites: vec![vec![0..2, 2..5], vec![0..5]],
4853 },
4854 Case {
4855 pre_writes: Vec::new(),
4856 allocate_ranges: vec![0..10, 4..6],
4857 overwrites: Vec::new(),
4858 },
4859 Case {
4860 pre_writes: Vec::new(),
4861 allocate_ranges: vec![3..8, 5..10],
4862 overwrites: Vec::new(),
4863 },
4864 Case {
4865 pre_writes: Vec::new(),
4866 allocate_ranges: vec![5..10, 3..8],
4867 overwrites: Vec::new(),
4868 },
4869 ];
4870
4871 for (i, case) in cases.into_iter().enumerate() {
4872 log::info!("running case {} - {:?}", i, case);
4873 let (fs, object) = test_filesystem_and_empty_object().await;
4874 let block_size = fs.block_size();
4875 let file_size = block_size * 10;
4876 object.truncate(file_size).await.unwrap();
4877
4878 for write in case.pre_writes {
4879 let write_len = (write.end - write.start) * block_size.get() as usize;
4880 let mut write_buf = object.allocate_buffer(write_len).await;
4881 write_buf.fill(0xff);
4882 assert_eq!(
4883 object
4884 .write_or_append(Some(block_size * write.start as u64), write_buf.as_ref())
4885 .await
4886 .unwrap(),
4887 file_size
4888 );
4889 }
4890
4891 for allocate_range in &case.allocate_ranges {
4892 object
4893 .allocate(allocate_range.start * block_size..allocate_range.end * block_size)
4894 .await
4895 .unwrap();
4896 }
4897
4898 for allocate_range in case.allocate_ranges {
4899 assert_all_overwrite(
4900 &object,
4901 allocate_range.start * block_size..allocate_range.end * block_size,
4902 )
4903 .await;
4904 }
4905
4906 for overwrite in case.overwrites {
4907 let mut write_len = 0;
4908 let overwrite = overwrite
4909 .into_iter()
4910 .map(|r| {
4911 write_len += (r.end - r.start) * block_size;
4912 r.start * block_size..r.end * block_size
4913 })
4914 .collect::<Vec<_>>();
4915 let mut write_buf = object.allocate_buffer(write_len as usize).await;
4916 let data = (0..20).cycle().take(write_len as usize).collect::<Vec<_>>();
4917 write_buf.copy_from_slice(&data);
4918
4919 let mut expected_buf = object.allocate_buffer(file_size as usize).await;
4920 assert_eq!(
4921 object.read_aligned(0, expected_buf.as_mut()).await.unwrap(),
4922 expected_buf.len()
4923 );
4924 let mut expected_buf_slice = expected_buf.as_mut_ptr_slice();
4925 let mut data_slice = data.as_slice();
4926 for r in &overwrite {
4927 let len = r.length().unwrap() as usize;
4928 let (copy_from, rest) = data_slice.split_at(len);
4929 expected_buf_slice
4930 .subslice_mut(r.start as usize..r.end as usize)
4931 .copy_from_slice(©_from);
4932 data_slice = rest;
4933 }
4934
4935 let mut transaction = object.new_transaction().await.unwrap();
4936 object
4937 .multi_overwrite(
4938 &mut transaction,
4939 AttributeId::DATA,
4940 &overwrite,
4941 write_buf.as_mut(),
4942 )
4943 .await
4944 .unwrap_or_else(|_| panic!("multi_overwrite error on case {}", i));
4945 let mut checksummed_range_length = 0;
4948 let mut num_checksums = 0;
4949 for (_, device_range, checksums, _) in transaction.checksums() {
4950 let range_len = device_range.end - device_range.start;
4951 let checksums_len = checksums.len() as u64;
4952 assert_eq!(range_len / checksums_len, block_size);
4953 checksummed_range_length += range_len;
4954 num_checksums += checksums_len;
4955 }
4956 assert_eq!(checksummed_range_length, write_len);
4957 assert_eq!(num_checksums, write_len / block_size);
4958 transaction.commit().await.unwrap();
4959
4960 let mut buf = object.allocate_buffer(file_size as usize).await;
4961 assert_eq!(
4962 object.read_aligned(0, buf.as_mut()).await.unwrap(),
4963 buf.len(),
4964 "failed length check on case {}",
4965 i,
4966 );
4967 assert_eq!(buf.to_vec(), expected_buf.to_vec(), "failed on case {}", i);
4968 }
4969
4970 fsck_volume(&fs, object.store().store_object_id(), None).await.expect("fsck failed");
4971 fs.close().await.expect("close failed");
4972 }
4973 }
4974
4975 #[fuchsia::test(threads = 10)]
4976 async fn test_multi_overwrite_mode_updates() {
4977 let (fs, object) = test_filesystem_and_empty_object().await;
4978 let block_size = fs.block_size();
4979 let file_size = block_size * 10;
4980 object.truncate(file_size).await.unwrap();
4981
4982 let mut expected_bitmap = BitVec::from_elem(10, false);
4983
4984 object.allocate(0..10 * block_size).await.unwrap();
4985 assert_eq!(
4986 get_modes(&object, 0..10 * block_size).await,
4987 vec![(0..10 * block_size, ExtentMode::OverwritePartial(expected_bitmap.clone()))]
4988 );
4989
4990 let mut write_buf = object.allocate_buffer((2 * block_size) as usize).await;
4991 let data = (0..20).cycle().take(write_buf.len()).collect::<Vec<_>>();
4992 write_buf.copy_from_slice(&data);
4993 let mut transaction = object.new_transaction().await.unwrap();
4994 object
4995 .multi_overwrite(
4996 &mut transaction,
4997 AttributeId::DATA,
4998 &[2 * block_size..4 * block_size],
4999 write_buf.as_mut(),
5000 )
5001 .await
5002 .unwrap();
5003 transaction.commit().await.unwrap();
5004
5005 expected_bitmap.set(2, true);
5006 expected_bitmap.set(3, true);
5007 assert_eq!(
5008 get_modes(&object, 0..10 * block_size).await,
5009 vec![(0..10 * block_size, ExtentMode::OverwritePartial(expected_bitmap.clone()))]
5010 );
5011
5012 let mut write_buf = object.allocate_buffer((3 * block_size) as usize).await;
5013 let data = (0..20).cycle().take(write_buf.len()).collect::<Vec<_>>();
5014 write_buf.copy_from_slice(&data);
5015 let mut transaction = object.new_transaction().await.unwrap();
5016 object
5017 .multi_overwrite(
5018 &mut transaction,
5019 AttributeId::DATA,
5020 &[3 * block_size..5 * block_size, 6 * block_size..7 * block_size],
5021 write_buf.as_mut(),
5022 )
5023 .await
5024 .unwrap();
5025 transaction.commit().await.unwrap();
5026
5027 expected_bitmap.set(4, true);
5028 expected_bitmap.set(6, true);
5029 assert_eq!(
5030 get_modes(&object, 0..10 * block_size).await,
5031 vec![(0..10 * block_size, ExtentMode::OverwritePartial(expected_bitmap.clone()))]
5032 );
5033
5034 let mut write_buf = object.allocate_buffer((6 * block_size) as usize).await;
5035 let data = (0..20).cycle().take(write_buf.len()).collect::<Vec<_>>();
5036 write_buf.copy_from_slice(&data);
5037 let mut transaction = object.new_transaction().await.unwrap();
5038 object
5039 .multi_overwrite(
5040 &mut transaction,
5041 AttributeId::DATA,
5042 &[
5043 0..2 * block_size,
5044 5 * block_size..6 * block_size,
5045 7 * block_size..10 * block_size,
5046 ],
5047 write_buf.as_mut(),
5048 )
5049 .await
5050 .unwrap();
5051 transaction.commit().await.unwrap();
5052
5053 assert_eq!(
5054 get_modes(&object, 0..10 * block_size).await,
5055 vec![(0..10 * block_size, ExtentMode::Overwrite)]
5056 );
5057
5058 fs.close().await.expect("close failed");
5059 }
5060
5061 #[fuchsia::test(threads = 10)]
5062 async fn test_check_unwritten_zero() {
5063 let device = DeviceHolder::new(FakeDevice::new(256 * 1024, TEST_DEVICE_BLOCK_SIZE));
5064 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
5065 let object = create_object_with_key(fs.clone(), Some(&new_insecure_crypt()), false).await;
5066 let block_size = fs.block_size();
5067
5068 let file_size = block_size * 7;
5071 object.truncate(file_size).await.unwrap();
5072 assert!(object.check_unwritten_zero(0..file_size).await.unwrap());
5073
5074 let mut buffer = object.allocate_buffer(block_size.get() as usize).await;
5075 buffer.fill(1);
5076 object
5077 .write_or_append(Some(block_size.get()), buffer.as_ref())
5078 .await
5079 .expect("write failed");
5080 object.write_or_append(Some(block_size * 2), buffer.as_ref()).await.expect("write failed");
5081
5082 object.allocate((block_size * 4)..(block_size * 6)).await.expect("Allocate failed");
5083 let mut transaction = fs
5084 .root_store()
5085 .new_transaction(
5086 lock_keys![LockKey::object(object.store().store_object_id(), object.object_id(),)],
5087 Options::default(),
5088 )
5089 .await
5090 .expect("new_transaction failed");
5091 object
5092 .multi_overwrite(
5093 &mut transaction,
5094 AttributeId::DATA,
5095 &vec![(block_size * 5)..(block_size * 6)],
5096 buffer.as_mut(),
5097 )
5098 .await
5099 .expect("Multi overwrite");
5100 transaction.commit().await.expect("Committing overwrite");
5101
5102 assert!(!object.check_unwritten_zero(0..(block_size * 2)).await.unwrap());
5104 assert!(!object.check_unwritten_zero(block_size.get()..(block_size * 3)).await.unwrap());
5105 assert!(!object.check_unwritten_zero((block_size * 2)..(block_size * 4)).await.unwrap());
5106
5107 assert!(object.check_unwritten_zero((block_size * 3)..(block_size * 5)).await.unwrap());
5109
5110 assert!(!object.check_unwritten_zero((block_size * 4)..(block_size * 6)).await.unwrap());
5112 assert!(!object.check_unwritten_zero((block_size * 5)..(block_size * 7)).await.unwrap());
5113
5114 fs.close().await.expect("close failed");
5115 }
5116
5117 #[fuchsia::test]
5118 async fn test_allocate_large_file() {
5119 let device = DeviceHolder::new(FakeDevice::new(8192, 4096));
5120 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
5121 let object = create_object_with_key(fs.clone(), Some(&new_insecure_crypt()), false).await;
5122 let block_size = fs.block_size().get();
5123
5124 for i in (0..1600).step_by(2) {
5125 object.allocate(i * block_size..(i + 1) * block_size).await.expect("allocate failed");
5126 }
5127 object.allocate(0..1600 * block_size).await.expect("allocate failed");
5128
5129 fs.close().await.expect("close failed");
5130 }
5131
5132 #[fuchsia::test]
5133 async fn test_bounded_extent_queries_skip_layers() {
5134 let device = DeviceHolder::new(FakeDevice::new(8192, TEST_DEVICE_BLOCK_SIZE));
5135 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
5136 let store = fs.root_store();
5137 let block_size = fs.block_size().get();
5138
5139 for _ in 0..200 {
5141 let _ = create_object_with_key(fs.clone(), Some(&new_insecure_crypt()), false).await;
5142 }
5143 store.flush().await.expect("flush failed");
5144
5145 let object = create_object_with_key(fs.clone(), Some(&new_insecure_crypt()), true).await;
5146 let mut buf = object.allocate_buffer(block_size as usize).await;
5147 buf.fill(0xab);
5148
5149 let skipped = || {
5150 store.tree().counters().layer_files_skipped.load(std::sync::atomic::Ordering::Relaxed)
5151 };
5152
5153 let before = skipped();
5155 object.write_or_append(Some(0), buf.as_ref()).await.expect("write failed");
5156 assert!(skipped() > before);
5157
5158 object.write_or_append(Some(block_size * 2), buf.as_ref()).await.expect("write failed");
5160 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
5164 transaction.add(
5165 store.store_object_id(),
5166 Mutation::merge_object(
5167 ObjectKey::extent(
5168 object.object_id(),
5169 AttributeId::DATA,
5170 block_size..block_size * 2,
5171 ),
5172 ObjectValue::deleted_extent(),
5173 ),
5174 );
5175 transaction.commit().await.expect("commit failed");
5176
5177 let before = skipped();
5178 assert!(!object.check_unwritten_zero(0..block_size).await.expect("check failed"));
5179 assert!(
5180 object.check_unwritten_zero(block_size..block_size * 2).await.expect("check failed")
5181 );
5182 assert!(skipped() >= before + 2);
5183
5184 let before = skipped();
5186 object.allocate(0..block_size * 2).await.expect("allocate failed");
5187 assert!(skipped() > before);
5188
5189 let mut transaction = object.new_transaction().await.expect("new_transaction failed");
5190 let before = skipped();
5191 object
5192 .multi_overwrite(&mut transaction, AttributeId::DATA, &[0..block_size], buf.as_mut())
5193 .await
5194 .expect("multi_overwrite failed");
5195 transaction.commit().await.expect("commit failed");
5196 assert!(skipped() > before);
5197
5198 object.truncate(block_size / 2).await.expect("truncate failed");
5200 let before = skipped();
5201 object.truncate(block_size * 2).await.expect("grow failed");
5202 assert!(skipped() > before);
5203
5204 fs.close().await.expect("close failed");
5205 }
5206
5207 #[fuchsia::test]
5208 async fn test_truncate_shrink_when_disk_full() {
5209 let device = DeviceHolder::new(FakeDevice::new(16384, TEST_DEVICE_BLOCK_SIZE));
5210 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
5211 let root_volume = root_volume(fs.clone()).await.expect("root_volume failed");
5212 let store = root_volume
5213 .new_volume("test", NewChildStoreOptions::default())
5214 .await
5215 .expect("new_volume failed");
5216 let root_dir =
5217 Directory::open(&store, store.root_directory_object_id()).await.expect("open failed");
5218
5219 let (victim, filler) = {
5220 let mut transaction = store
5221 .new_transaction(
5222 lock_keys![LockKey::object(store.store_object_id(), root_dir.object_id())],
5223 Options::default(),
5224 )
5225 .await
5226 .expect("new_txn");
5227 let v = root_dir.create_child_file(&mut transaction, "victim").await.expect("create");
5228 let f = root_dir.create_child_file(&mut transaction, "filler").await.expect("create");
5229 transaction.commit().await.expect("commit");
5230 (v, f)
5231 };
5232 {
5233 let mut buf = victim.allocate_buffer(1_048_576).await;
5234 buf.fill(0x55);
5235 victim.write_or_append(Some(0), buf.as_ref()).await.expect("write victim");
5236 }
5237
5238 fs.journal().force_compact().await.expect("compact");
5239
5240 let mut offset = 0;
5241 for chunk_size in [65536usize, 4096, 512] {
5242 let mut buf = filler.allocate_buffer(chunk_size).await;
5243 buf.fill(0xAA);
5244 while filler.write_or_append(Some(offset), buf.as_ref()).await.is_ok() {
5245 offset += chunk_size as u64;
5246 }
5247 }
5248 while let Ok(mut transaction) = store
5249 .new_transaction(
5250 lock_keys![LockKey::object(store.store_object_id(), root_dir.object_id())],
5251 Options::default(),
5252 )
5253 .await
5254 {
5255 root_dir
5256 .create_child_file(&mut transaction, &format!("pad_{offset}"))
5257 .await
5258 .expect("pad");
5259 transaction.commit().await.expect("commit pad");
5260 offset += 1;
5261 }
5262
5263 let free_when_full = fs.allocator().get_disk_bytes() - fs.allocator().get_used_bytes().0;
5264 assert!(
5265 free_when_full < crate::object_store::transaction::TRANSACTION_METADATA_MAX_AMOUNT,
5266 "Remaining unallocated space ({free_when_full}) is less than \
5267 TRANSACTION_METADATA_MAX_AMOUNT"
5268 );
5269
5270 let sys_object = {
5271 let root_store = fs.root_store();
5272 let mut transaction = root_store
5273 .new_transaction(
5274 lock_keys![],
5275 Options { reservation: ReservationOptions::Borrowed, ..Default::default() },
5276 )
5277 .await
5278 .expect("new_txn borrowed");
5279 let obj = ObjectStore::create_object(
5280 &root_store,
5281 &mut transaction,
5282 HandleOptions::default(),
5283 None,
5284 )
5285 .await
5286 .expect("create system store object");
5287 root_store.add_to_graveyard(&mut transaction, obj.object_id());
5288 transaction.commit().await.expect("commit system store object");
5289 obj
5290 };
5291 sys_object
5294 .truncate_with_options(
5295 Options { reservation: ReservationOptions::Borrowed, ..Default::default() },
5296 4096,
5297 )
5298 .await
5299 .expect("Growing a system store object with Borrowed reservation should succeed");
5300 assert_eq!(sys_object.get_size(), 4096);
5301
5302 victim.truncate(0).await.expect("DataObjectHandle::truncate(0) should succeed when full");
5305 assert_eq!(victim.get_size(), 0);
5306 let free_after_truncate =
5307 fs.allocator().get_disk_bytes() - fs.allocator().get_used_bytes().0;
5308 assert!(free_after_truncate >= free_when_full + 1_048_576);
5309
5310 fs.close().await.expect("close failed");
5311 }
5312}