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