1use crate::checksum::Checksum;
6use crate::filesystem::FxFilesystem;
7use crate::log::*;
8use crate::lsm_tree::types::Item;
9use crate::object_handle::INVALID_OBJECT_ID;
10use crate::object_store::allocator::{AllocatorItem, Reservation};
11use crate::object_store::object_manager::{ObjectManager, reserved_space_from_journal_usage};
12use crate::object_store::object_record::{
13 FxfsKey, FxfsKeyV49, ObjectItem, ObjectItemV56, ObjectKey, ObjectKeyData, ObjectValue,
14 ProjectProperty,
15};
16use crate::object_store::{AttributeId, AttributeKey, ProjectId};
17use crate::serialized_types::{Migrate, Versioned, migrate_to_version};
18use anyhow::Error;
19use either::{Either, Left, Right};
20use fprint::TypeFingerprint;
21use fuchsia_sync::Mutex;
22use futures::future::poll_fn;
23use futures::pin_mut;
24use rustc_hash::FxHashMap as HashMap;
25use scopeguard::ScopeGuard;
26use serde::{Deserialize, Serialize};
27use std::cell::UnsafeCell;
28use std::cmp::Ordering;
29use std::collections::hash_map::Entry;
30use std::collections::{BTreeSet, btree_set};
31use std::iter::Peekable;
32use std::marker::PhantomPinned;
33use std::ops::{Deref, DerefMut, Range};
34use std::sync::Arc;
35use std::task::{Poll, Waker};
36use std::{fmt, mem};
37
38#[derive(Clone, Copy, Default)]
42pub struct Options<'a> {
43 pub skip_journal_checks: bool,
46
47 pub borrow_metadata_space: bool,
52
53 pub allocator_reservation: Option<&'a Reservation>,
58}
59
60pub const TRANSACTION_MAX_JOURNAL_USAGE: u64 = 24_576;
67pub const TRANSACTION_METADATA_MAX_AMOUNT: u64 =
68 reserved_space_from_journal_usage(TRANSACTION_MAX_JOURNAL_USAGE);
69
70#[must_use]
71pub struct TransactionLocks<'a>(pub WriteGuard<'a>);
72
73pub type Mutation = MutationV57;
78
79#[derive(
80 Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize, TypeFingerprint, Versioned,
81)]
82#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
83pub enum MutationV57 {
84 ObjectStore(ObjectStoreMutationV56),
85 EncryptedObjectStore(#[serde(with = "crate::zerocopy_serialization")] Box<[u8]>),
86 Allocator(AllocatorMutationV32),
87 BeginFlush,
89 EndFlush,
92 DeleteVolume,
94 UpdateBorrowed(u64),
95 UpdateMutationsKey(UpdateMutationsKey),
96 CreateInternalDir(u64),
97}
98
99#[derive(Migrate, Clone, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint, Versioned)]
100#[migrate_to_version(MutationV57)]
101pub enum MutationV56 {
102 ObjectStore(ObjectStoreMutationV56),
103 EncryptedObjectStore(#[serde(with = "crate::zerocopy_serialization")] Box<[u8]>),
104 Allocator(AllocatorMutationV32),
105 BeginFlush,
106 EndFlush,
107 DeleteVolume,
108 UpdateBorrowed(u64),
109 UpdateMutationsKey(UpdateMutationsKey),
110 CreateInternalDir(u64),
111}
112
113impl Mutation {
114 pub fn insert_object(key: ObjectKey, value: ObjectValue) -> Self {
115 Mutation::ObjectStore(ObjectStoreMutation {
116 item: Item::new(key, value),
117 op: Operation::Insert,
118 })
119 }
120
121 pub fn replace_or_insert_object(key: ObjectKey, value: ObjectValue) -> Self {
122 Mutation::ObjectStore(ObjectStoreMutation {
123 item: Item::new(key, value),
124 op: Operation::ReplaceOrInsert,
125 })
126 }
127
128 pub fn merge_object(key: ObjectKey, value: ObjectValue) -> Self {
129 Mutation::ObjectStore(ObjectStoreMutation {
130 item: Item::new(key, value),
131 op: Operation::Merge,
132 })
133 }
134
135 pub fn update_mutations_key(key: FxfsKey) -> Self {
136 Mutation::UpdateMutationsKey(key.into())
137 }
138}
139
140pub type ObjectStoreMutation = ObjectStoreMutationV56;
144
145#[derive(Clone, Debug, Serialize, Deserialize, TypeFingerprint)]
146#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
147pub struct ObjectStoreMutationV56 {
148 pub item: ObjectItemV56,
149 pub op: Operation,
150}
151
152pub type Operation = OperationV32;
154
155#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TypeFingerprint)]
156#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
157pub enum OperationV32 {
158 Insert,
159 ReplaceOrInsert,
160 Merge,
161}
162
163impl Ord for ObjectStoreMutation {
164 fn cmp(&self, other: &Self) -> Ordering {
165 self.item.key.cmp(&other.item.key)
166 }
167}
168
169impl PartialOrd for ObjectStoreMutation {
170 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
171 Some(self.cmp(other))
172 }
173}
174
175impl PartialEq for ObjectStoreMutation {
176 fn eq(&self, other: &Self) -> bool {
177 self.item.key.eq(&other.item.key)
178 }
179}
180
181impl Eq for ObjectStoreMutation {}
182
183impl Ord for AllocatorItem {
184 fn cmp(&self, other: &Self) -> Ordering {
185 self.key.cmp(&other.key)
186 }
187}
188
189impl PartialOrd for AllocatorItem {
190 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
191 Some(self.cmp(other))
192 }
193}
194
195pub type DeviceRange = DeviceRangeV32;
198
199#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, TypeFingerprint)]
200#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
201pub struct DeviceRangeV32(pub Range<u64>);
202
203impl Deref for DeviceRange {
204 type Target = Range<u64>;
205
206 fn deref(&self) -> &Self::Target {
207 &self.0
208 }
209}
210
211impl DerefMut for DeviceRange {
212 fn deref_mut(&mut self) -> &mut Self::Target {
213 &mut self.0
214 }
215}
216
217impl From<Range<u64>> for DeviceRange {
218 fn from(range: Range<u64>) -> Self {
219 Self(range)
220 }
221}
222
223impl Into<Range<u64>> for DeviceRange {
224 fn into(self) -> Range<u64> {
225 self.0
226 }
227}
228
229impl Ord for DeviceRange {
230 fn cmp(&self, other: &Self) -> Ordering {
231 self.start.cmp(&other.start).then(self.end.cmp(&other.end))
232 }
233}
234
235impl PartialOrd for DeviceRange {
236 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
237 Some(self.cmp(other))
238 }
239}
240
241pub type AllocatorMutation = AllocatorMutationV32;
242
243#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize, TypeFingerprint)]
244#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
245pub enum AllocatorMutationV32 {
246 Allocate {
247 device_range: DeviceRangeV32,
248 owner_object_id: u64,
249 },
250 Deallocate {
251 device_range: DeviceRangeV32,
252 owner_object_id: u64,
253 },
254 SetLimit {
255 owner_object_id: u64,
256 bytes: u64,
257 },
258 MarkForDeletion(u64),
264}
265
266pub type UpdateMutationsKey = UpdateMutationsKeyV49;
267
268#[derive(Clone, Debug, Serialize, Deserialize, TypeFingerprint)]
269pub struct UpdateMutationsKeyV49(pub FxfsKeyV49);
270
271impl From<UpdateMutationsKey> for FxfsKey {
272 fn from(outer: UpdateMutationsKey) -> Self {
273 outer.0
274 }
275}
276
277impl From<FxfsKey> for UpdateMutationsKey {
278 fn from(inner: FxfsKey) -> Self {
279 Self(inner)
280 }
281}
282
283#[cfg(fuzz)]
284impl<'a> arbitrary::Arbitrary<'a> for UpdateMutationsKey {
285 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
286 Ok(UpdateMutationsKey::from(FxfsKey::arbitrary(u).unwrap()))
287 }
288}
289
290impl Ord for UpdateMutationsKey {
291 fn cmp(&self, other: &Self) -> Ordering {
292 (self as *const UpdateMutationsKey).cmp(&(other as *const _))
293 }
294}
295
296impl PartialOrd for UpdateMutationsKey {
297 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
298 Some(self.cmp(other))
299 }
300}
301
302impl Eq for UpdateMutationsKey {}
303
304impl PartialEq for UpdateMutationsKey {
305 fn eq(&self, other: &Self) -> bool {
306 std::ptr::eq(self, other)
307 }
308}
309
310#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Copy)]
318pub enum LockKey {
319 Flush {
321 object_id: u64,
322 },
323
324 ObjectAttribute {
326 store_object_id: u64,
327 object_id: u64,
328 attribute_id: AttributeId,
329 },
330
331 Object {
333 store_object_id: u64,
334 object_id: u64,
335 },
336
337 ProjectId {
338 store_object_id: u64,
339 project_id: ProjectId,
340 },
341
342 Truncate {
344 store_object_id: u64,
345 object_id: u64,
346 },
347
348 InternalDirectory {
350 store_object_id: u64,
351 },
352
353 PreCacheKeys {
357 store_object_id: u64,
358 },
359}
360
361impl LockKey {
362 pub const fn object_attribute(
363 store_object_id: u64,
364 object_id: u64,
365 attribute_id: AttributeId,
366 ) -> Self {
367 LockKey::ObjectAttribute { store_object_id, object_id, attribute_id }
368 }
369
370 pub const fn object(store_object_id: u64, object_id: u64) -> Self {
371 LockKey::Object { store_object_id, object_id }
372 }
373
374 pub const fn flush(object_id: u64) -> Self {
375 LockKey::Flush { object_id }
376 }
377
378 pub const fn truncate(store_object_id: u64, object_id: u64) -> Self {
379 LockKey::Truncate { store_object_id, object_id }
380 }
381
382 pub const fn pre_cache_keys(store_object_id: u64) -> Self {
383 LockKey::PreCacheKeys { store_object_id }
384 }
385}
386
387#[derive(Clone, Debug)]
389pub enum LockKeys {
390 None,
391 Inline(LockKey),
392 Vec(Vec<LockKey>),
393}
394
395impl LockKeys {
396 pub fn with_capacity(capacity: usize) -> Self {
397 if capacity > 1 { LockKeys::Vec(Vec::with_capacity(capacity)) } else { LockKeys::None }
398 }
399
400 pub fn push(&mut self, key: LockKey) {
401 match self {
402 Self::None => *self = LockKeys::Inline(key),
403 Self::Inline(inline) => {
404 *self = LockKeys::Vec(vec![*inline, key]);
405 }
406 Self::Vec(vec) => vec.push(key),
407 }
408 }
409
410 pub fn truncate(&mut self, len: usize) {
411 match self {
412 Self::None => {}
413 Self::Inline(_) => {
414 if len == 0 {
415 *self = Self::None;
416 }
417 }
418 Self::Vec(vec) => vec.truncate(len),
419 }
420 }
421
422 fn len(&self) -> usize {
423 match self {
424 Self::None => 0,
425 Self::Inline(_) => 1,
426 Self::Vec(vec) => vec.len(),
427 }
428 }
429
430 fn contains(&self, key: &LockKey) -> bool {
431 match self {
432 Self::None => false,
433 Self::Inline(single) => single == key,
434 Self::Vec(vec) => vec.contains(key),
435 }
436 }
437
438 fn sort_unstable(&mut self) {
439 match self {
440 Self::Vec(vec) => vec.sort_unstable(),
441 _ => {}
442 }
443 }
444
445 fn dedup(&mut self) {
446 match self {
447 Self::Vec(vec) => vec.dedup(),
448 _ => {}
449 }
450 }
451
452 fn iter(&self) -> LockKeysIter<'_> {
453 match self {
454 LockKeys::None => LockKeysIter::None,
455 LockKeys::Inline(key) => LockKeysIter::Inline(key),
456 LockKeys::Vec(keys) => LockKeysIter::Vec(keys.iter()),
457 }
458 }
459}
460
461enum LockKeysIter<'a> {
462 None,
463 Inline(&'a LockKey),
464 Vec(std::slice::Iter<'a, LockKey>),
465}
466
467impl<'a> Iterator for LockKeysIter<'a> {
468 type Item = &'a LockKey;
469 fn next(&mut self) -> Option<Self::Item> {
470 match self {
471 Self::None => None,
472 Self::Inline(inline) => {
473 let next = *inline;
474 *self = Self::None;
475 Some(next)
476 }
477 Self::Vec(vec) => vec.next(),
478 }
479 }
480}
481
482impl Default for LockKeys {
483 fn default() -> Self {
484 LockKeys::None
485 }
486}
487
488#[macro_export]
489macro_rules! lock_keys {
490 () => {
491 $crate::object_store::transaction::LockKeys::None
492 };
493 ($lock_key:expr $(,)?) => {
494 $crate::object_store::transaction::LockKeys::Inline($lock_key)
495 };
496 ($($lock_keys:expr),+ $(,)?) => {
497 $crate::object_store::transaction::LockKeys::Vec(vec![$($lock_keys),+])
498 };
499}
500pub use lock_keys;
501
502pub trait AssociatedObject: Send + Sync {
506 fn will_apply_mutation(&self, _mutation: &Mutation, _object_id: u64, _manager: &ObjectManager) {
507 }
508}
509
510pub enum AssocObj<'a> {
511 None,
512 Borrowed(&'a dyn AssociatedObject),
513 Owned(Box<dyn AssociatedObject>),
514}
515
516impl AssocObj<'_> {
517 pub fn map<R, F: FnOnce(&dyn AssociatedObject) -> R>(&self, f: F) -> Option<R> {
518 match self {
519 AssocObj::None => None,
520 AssocObj::Borrowed(b) => Some(f(*b)),
521 AssocObj::Owned(o) => Some(f(o.as_ref())),
522 }
523 }
524}
525
526pub struct TxnMutation<'a> {
527 pub object_id: u64,
531
532 pub mutation: Mutation,
534
535 pub associated_object: AssocObj<'a>,
538}
539
540impl Ord for TxnMutation<'_> {
548 fn cmp(&self, other: &Self) -> Ordering {
549 self.object_id.cmp(&other.object_id).then_with(|| self.mutation.cmp(&other.mutation))
550 }
551}
552
553impl PartialOrd for TxnMutation<'_> {
554 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
555 Some(self.cmp(other))
556 }
557}
558
559impl PartialEq for TxnMutation<'_> {
560 fn eq(&self, other: &Self) -> bool {
561 self.object_id.eq(&other.object_id) && self.mutation.eq(&other.mutation)
562 }
563}
564
565impl Eq for TxnMutation<'_> {}
566
567impl std::fmt::Debug for TxnMutation<'_> {
568 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
569 f.debug_struct("TxnMutation")
570 .field("object_id", &self.object_id)
571 .field("mutation", &self.mutation)
572 .finish()
573 }
574}
575
576pub struct ObjectMutationIterator<'a, 'b> {
580 iter: &'a mut Peekable<btree_set::Iter<'b, TxnMutation<'b>>>,
581 object_id: u64,
582}
583
584impl<'a, 'b> ObjectMutationIterator<'a, 'b> {
585 pub fn new(iter: &'a mut Peekable<btree_set::Iter<'b, TxnMutation<'b>>>) -> Option<Self> {
586 let object_id = iter.peek()?.object_id;
587 Some(Self { iter, object_id })
588 }
589
590 pub fn object_id(&self) -> u64 {
591 self.object_id
592 }
593}
594
595impl<'b> Iterator for ObjectMutationIterator<'_, 'b> {
596 type Item = &'b Mutation;
597
598 fn next(&mut self) -> Option<Self::Item> {
599 if self.iter.peek().is_some_and(|m| m.object_id == self.object_id) {
600 Some(&self.iter.next().unwrap().mutation)
601 } else {
602 None
603 }
604 }
605}
606
607impl Drop for ObjectMutationIterator<'_, '_> {
608 fn drop(&mut self) {
611 for _ in self.by_ref() {}
612 }
613}
614
615pub enum MetadataReservation {
616 None,
618
619 Borrowed,
622
623 Reservation(Reservation),
625
626 Hold(u64),
628}
629
630pub struct Transaction<'a> {
632 fs: Arc<FxFilesystem>,
633
634 mutations: BTreeSet<TxnMutation<'a>>,
636
637 txn_locks: LockKeys,
639
640 pub allocator_reservation: Option<&'a Reservation>,
642
643 pub metadata_reservation: MetadataReservation,
645
646 new_objects: BTreeSet<(u64, u64)>,
649
650 checksums: Vec<(Range<u64>, Vec<Checksum>, bool)>,
652
653 includes_write: bool,
655}
656
657impl<'a> Transaction<'a> {
658 pub async fn new(
661 fs: Arc<FxFilesystem>,
662 options: Options<'a>,
663 txn_locks: LockKeys,
664 ) -> Result<Transaction<'a>, Error> {
665 fs.add_transaction(options.skip_journal_checks).await;
666 let fs_clone = fs.clone();
667 let guard = scopeguard::guard((), |_| fs_clone.sub_transaction());
668 let (metadata_reservation, allocator_reservation, hold) =
669 fs.reservation_for_transaction(options).await?;
670
671 let txn_locks = {
672 let lock_manager = fs.lock_manager();
673 let mut write_guard = lock_manager.txn_lock(txn_locks).await;
674 std::mem::take(&mut write_guard.0.lock_keys)
675 };
676 let mut transaction = Transaction {
677 fs,
678 mutations: BTreeSet::new(),
679 txn_locks,
680 allocator_reservation: None,
681 metadata_reservation,
682 new_objects: BTreeSet::new(),
683 checksums: Vec::new(),
684 includes_write: false,
685 };
686
687 ScopeGuard::into_inner(guard);
688 hold.map(|h| h.forget()); transaction.allocator_reservation = allocator_reservation;
690 Ok(transaction)
691 }
692
693 pub fn mutations(&self) -> &BTreeSet<TxnMutation<'a>> {
694 &self.mutations
695 }
696
697 pub fn take_mutations(&mut self) -> BTreeSet<TxnMutation<'a>> {
698 self.new_objects.clear();
699 mem::take(&mut self.mutations)
700 }
701
702 pub fn add(&mut self, object_id: u64, mutation: Mutation) -> Option<Mutation> {
705 self.add_with_object(object_id, mutation, AssocObj::None)
706 }
707
708 pub fn remove(&mut self, object_id: u64, mutation: Mutation) {
710 let txn_mutation = TxnMutation { object_id, mutation, associated_object: AssocObj::None };
711 if self.mutations.remove(&txn_mutation) {
712 if let Mutation::ObjectStore(ObjectStoreMutation {
713 item:
714 ObjectItem {
715 key: ObjectKey { object_id: new_object_id, data: ObjectKeyData::Object },
716 ..
717 },
718 op: Operation::Insert,
719 }) = txn_mutation.mutation
720 {
721 self.new_objects.remove(&(object_id, new_object_id));
722 }
723 }
724 }
725
726 pub fn add_with_object(
729 &mut self,
730 object_id: u64,
731 mutation: Mutation,
732 associated_object: AssocObj<'a>,
733 ) -> Option<Mutation> {
734 assert!(object_id != INVALID_OBJECT_ID);
735 if let Mutation::ObjectStore(ObjectStoreMutation {
736 item:
737 Item {
738 key:
739 ObjectKey { data: ObjectKeyData::Attribute(_, AttributeKey::Extent(_)), .. },
740 ..
741 },
742 ..
743 }) = &mutation
744 {
745 self.includes_write = true;
746 }
747 let txn_mutation = TxnMutation { object_id, mutation, associated_object };
748 self.verify_locks(&txn_mutation);
749 self.mutations.replace(txn_mutation).map(|m| m.mutation)
750 }
751
752 pub fn add_checksum(&mut self, range: Range<u64>, checksums: Vec<Checksum>, first_write: bool) {
753 self.checksums.push((range, checksums, first_write));
754 }
755
756 pub fn includes_write(&self) -> bool {
757 self.includes_write
758 }
759
760 pub fn checksums(&self) -> &[(Range<u64>, Vec<Checksum>, bool)] {
761 &self.checksums
762 }
763
764 pub fn take_checksums(&mut self) -> Vec<(Range<u64>, Vec<Checksum>, bool)> {
765 std::mem::replace(&mut self.checksums, Vec::new())
766 }
767
768 fn verify_locks(&mut self, mutation: &TxnMutation<'_>) {
769 match mutation {
773 TxnMutation {
774 mutation:
775 Mutation::ObjectStore {
776 0: ObjectStoreMutation { item: ObjectItem { key, .. }, op },
777 },
778 object_id: store_object_id,
779 ..
780 } => {
781 match &key.data {
782 ObjectKeyData::Attribute(..) => {
783 }
785 ObjectKeyData::Child { .. }
786 | ObjectKeyData::EncryptedChild(_)
787 | ObjectKeyData::EncryptedCasefoldChild(_)
788 | ObjectKeyData::CasefoldChild { .. }
789 | ObjectKeyData::LegacyCasefoldChild(_) => {
790 let id = key.object_id;
791 if !self.txn_locks.contains(&LockKey::object(*store_object_id, id))
792 && !self.new_objects.contains(&(*store_object_id, id))
793 {
794 debug_assert!(
795 false,
796 "Not holding required lock for object {id} \
797 in store {store_object_id}"
798 );
799 error!(
800 "Not holding required lock for object {id} in store \
801 {store_object_id}"
802 )
803 }
804 }
805 ObjectKeyData::GraveyardEntry { .. } => {
806 }
808 ObjectKeyData::GraveyardAttributeEntry { .. } => {
809 }
811 ObjectKeyData::Keys => {
812 let id = key.object_id;
813 if !self.txn_locks.contains(&LockKey::object(*store_object_id, id))
814 && !self.new_objects.contains(&(*store_object_id, id))
815 {
816 debug_assert!(
817 false,
818 "Not holding required lock for object {id} \
819 in store {store_object_id}"
820 );
821 error!(
822 "Not holding required lock for object {id} in store \
823 {store_object_id}"
824 )
825 }
826 }
827 ObjectKeyData::Object => match op {
828 Operation::Insert => {
830 self.new_objects.insert((*store_object_id, key.object_id));
831 }
832 Operation::Merge | Operation::ReplaceOrInsert => {
833 let id = key.object_id;
834 if !self.txn_locks.contains(&LockKey::object(*store_object_id, id))
835 && !self.new_objects.contains(&(*store_object_id, id))
836 {
837 debug_assert!(
838 false,
839 "Not holding required lock for object {id} \
840 in store {store_object_id}"
841 );
842 error!(
843 "Not holding required lock for object {id} in store \
844 {store_object_id}"
845 )
846 }
847 }
848 },
849 ObjectKeyData::Project { project_id, property: ProjectProperty::Limit } => {
850 if !self.txn_locks.contains(&LockKey::ProjectId {
851 store_object_id: *store_object_id,
852 project_id: *project_id,
853 }) {
854 debug_assert!(
855 false,
856 "Not holding required lock for project limit id {project_id} \
857 in store {store_object_id}"
858 );
859 error!(
860 "Not holding required lock for project limit id {project_id} in \
861 store {store_object_id}"
862 )
863 }
864 }
865 ObjectKeyData::Project { property: ProjectProperty::Usage, .. } => match op {
866 Operation::Insert | Operation::ReplaceOrInsert => {
867 panic!(
868 "Project usage is all handled by merging deltas, no inserts or \
869 replacements should be used"
870 );
871 }
872 Operation::Merge => {}
874 },
875 ObjectKeyData::ExtendedAttribute { .. } => {
876 let id = key.object_id;
877 if !self.txn_locks.contains(&LockKey::object(*store_object_id, id))
878 && !self.new_objects.contains(&(*store_object_id, id))
879 {
880 debug_assert!(
881 false,
882 "Not holding required lock for object {id} \
883 in store {store_object_id} while mutating extended attribute"
884 );
885 error!(
886 "Not holding required lock for object {id} in store \
887 {store_object_id} while mutating extended attribute"
888 )
889 }
890 }
891 }
892 }
893 TxnMutation { mutation: Mutation::DeleteVolume, object_id, .. } => {
894 if !self.txn_locks.contains(&LockKey::flush(*object_id)) {
895 debug_assert!(false, "Not holding required lock for DeleteVolume");
896 error!("Not holding required lock for DeleteVolume");
897 }
898 }
899 _ => {}
900 }
901 }
902
903 pub fn is_empty(&self) -> bool {
905 self.mutations.is_empty()
906 }
907
908 pub fn get_object_mutation(
911 &self,
912 store_object_id: u64,
913 key: ObjectKey,
914 ) -> Option<&ObjectStoreMutation> {
915 if let Some(TxnMutation { mutation: Mutation::ObjectStore(mutation), .. }) =
916 self.mutations.get(&TxnMutation {
917 object_id: store_object_id,
918 mutation: Mutation::insert_object(key, ObjectValue::None),
919 associated_object: AssocObj::None,
920 })
921 {
922 Some(mutation)
923 } else {
924 None
925 }
926 }
927
928 pub async fn commit(mut self) -> Result<u64, Error> {
930 debug!(txn:? = &self; "Commit");
931 self.fs.clone().commit_transaction(&mut self, |x| x).await
932 }
933
934 pub async fn commit_with_callback<R: Send>(
937 mut self,
938 f: impl FnOnce(u64) -> R + Send,
939 ) -> Result<R, Error> {
940 debug!(txn:? = &self; "Commit");
941 self.fs.clone().commit_transaction(&mut self, f).await
942 }
943
944 pub async fn commit_and_continue(&mut self) -> Result<(), Error> {
947 debug!(txn:? = self; "Commit");
948 self.fs.clone().commit_transaction(self, |_| {}).await?;
949 assert!(self.mutations.is_empty());
950 self.fs.lock_manager().downgrade_locks(&self.txn_locks);
951 Ok(())
952 }
953
954 pub async fn commit_prepare(&self) {
957 self.fs.lock_manager().commit_prepare(self).await;
958 }
959}
960
961impl Drop for Transaction<'_> {
962 fn drop(&mut self) {
963 debug!(txn:? = &self; "Drop");
966 self.fs.clone().drop_transaction(self);
967 }
968}
969
970impl std::fmt::Debug for Transaction<'_> {
971 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
972 f.debug_struct("Transaction")
973 .field("mutations", &self.mutations)
974 .field("txn_locks", &self.txn_locks)
975 .field("reservation", &self.allocator_reservation)
976 .finish()
977 }
978}
979
980pub enum BorrowedOrOwned<'a, T> {
981 Borrowed(&'a T),
982 Owned(T),
983}
984
985impl<T> Deref for BorrowedOrOwned<'_, T> {
986 type Target = T;
987
988 fn deref(&self) -> &Self::Target {
989 match self {
990 BorrowedOrOwned::Borrowed(b) => b,
991 BorrowedOrOwned::Owned(o) => &o,
992 }
993 }
994}
995
996impl<'a, T> From<&'a T> for BorrowedOrOwned<'a, T> {
997 fn from(value: &'a T) -> Self {
998 BorrowedOrOwned::Borrowed(value)
999 }
1000}
1001
1002impl<T> From<T> for BorrowedOrOwned<'_, T> {
1003 fn from(value: T) -> Self {
1004 BorrowedOrOwned::Owned(value)
1005 }
1006}
1007
1008pub struct LockManager {
1037 locks: Mutex<Locks>,
1038}
1039
1040struct Locks {
1041 keys: HashMap<LockKey, LockEntry>,
1042}
1043
1044impl Locks {
1045 fn drop_lock(&mut self, key: LockKey, state: LockState) {
1046 if let Entry::Occupied(mut occupied) = self.keys.entry(key) {
1047 let entry = occupied.get_mut();
1048 let wake = match state {
1049 LockState::ReadLock => {
1050 entry.read_count -= 1;
1051 entry.read_count == 0
1052 }
1053 LockState::Locked | LockState::WriteLock => {
1055 entry.state = LockState::ReadLock;
1056 true
1057 }
1058 };
1059 if wake {
1060 unsafe {
1062 entry.wake();
1063 }
1064 if entry.can_remove() {
1065 occupied.remove_entry();
1066 }
1067 }
1068 } else {
1069 unreachable!();
1070 }
1071 }
1072
1073 fn drop_read_locks(&mut self, lock_keys: LockKeys) {
1074 for lock in lock_keys.iter() {
1075 self.drop_lock(*lock, LockState::ReadLock);
1076 }
1077 }
1078
1079 fn drop_write_locks(&mut self, lock_keys: LockKeys) {
1080 for lock in lock_keys.iter() {
1081 self.drop_lock(*lock, LockState::WriteLock);
1084 }
1085 }
1086
1087 fn downgrade_locks(&mut self, lock_keys: &LockKeys) {
1089 for lock in lock_keys.iter() {
1090 unsafe {
1092 self.keys.get_mut(lock).unwrap().downgrade_lock();
1093 }
1094 }
1095 }
1096}
1097
1098#[derive(Debug)]
1099struct LockEntry {
1100 read_count: u64,
1103
1104 state: LockState,
1106
1107 head: *const LockWaker,
1112 tail: *const LockWaker,
1113}
1114
1115unsafe impl Send for LockEntry {}
1116
1117struct LockWaker {
1120 next: UnsafeCell<*const LockWaker>,
1122 prev: UnsafeCell<*const LockWaker>,
1123
1124 key: LockKey,
1127
1128 waker: UnsafeCell<WakerState>,
1130
1131 target_state: LockState,
1133
1134 is_upgrade: bool,
1136
1137 _pin: PhantomPinned,
1139}
1140
1141enum WakerState {
1142 Pending,
1144
1145 Registered(Waker),
1147
1148 Woken,
1150}
1151
1152impl WakerState {
1153 fn is_woken(&self) -> bool {
1154 matches!(self, WakerState::Woken)
1155 }
1156}
1157
1158unsafe impl Send for LockWaker {}
1159unsafe impl Sync for LockWaker {}
1160
1161impl LockWaker {
1162 async fn wait(&self, manager: &LockManager) {
1164 let waker_guard = scopeguard::guard((), |_| {
1166 let mut locks = manager.locks.lock();
1167 unsafe {
1169 if (*self.waker.get()).is_woken() {
1170 if self.is_upgrade {
1172 locks.keys.get_mut(&self.key).unwrap().downgrade_lock();
1173 } else {
1174 locks.drop_lock(self.key, self.target_state);
1175 }
1176 } else {
1177 locks.keys.get_mut(&self.key).unwrap().remove_waker(self);
1180 }
1181 }
1182 });
1183
1184 poll_fn(|cx| {
1185 let _locks = manager.locks.lock();
1186 unsafe {
1188 if (*self.waker.get()).is_woken() {
1189 Poll::Ready(())
1190 } else {
1191 *self.waker.get() = WakerState::Registered(cx.waker().clone());
1192 Poll::Pending
1193 }
1194 }
1195 })
1196 .await;
1197
1198 ScopeGuard::into_inner(waker_guard);
1199 }
1200}
1201
1202#[derive(Copy, Clone, Debug, PartialEq)]
1203enum LockState {
1204 ReadLock,
1206
1207 Locked,
1210
1211 WriteLock,
1213}
1214
1215impl LockManager {
1216 pub fn new() -> Self {
1217 LockManager { locks: Mutex::new(Locks { keys: HashMap::default() }) }
1218 }
1219
1220 pub async fn txn_lock<'a>(&'a self, lock_keys: LockKeys) -> TransactionLocks<'a> {
1224 TransactionLocks(
1225 debug_assert_not_too_long!(self.lock(lock_keys, LockState::Locked)).right().unwrap(),
1226 )
1227 }
1228
1229 async fn lock<'a>(
1232 &'a self,
1233 mut lock_keys: LockKeys,
1234 target_state: LockState,
1235 ) -> Either<ReadGuard<'a>, WriteGuard<'a>> {
1236 let mut guard = match &target_state {
1237 LockState::ReadLock => Left(ReadGuard {
1238 manager: self.into(),
1239 lock_keys: LockKeys::with_capacity(lock_keys.len()),
1240 }),
1241 LockState::Locked | LockState::WriteLock => Right(WriteGuard {
1242 manager: self.into(),
1243 lock_keys: LockKeys::with_capacity(lock_keys.len()),
1244 }),
1245 };
1246 let guard_keys = match &mut guard {
1247 Left(g) => &mut g.lock_keys,
1248 Right(g) => &mut g.lock_keys,
1249 };
1250 lock_keys.sort_unstable();
1251 lock_keys.dedup();
1252 for lock in lock_keys.iter() {
1253 let lock_waker = None;
1254 pin_mut!(lock_waker);
1255 {
1256 let mut locks = self.locks.lock();
1257 match locks.keys.entry(*lock) {
1258 Entry::Vacant(vacant) => {
1259 vacant.insert(LockEntry {
1260 read_count: if let LockState::ReadLock = target_state {
1261 guard_keys.push(*lock);
1262 1
1263 } else {
1264 guard_keys.push(*lock);
1265 0
1266 },
1267 state: target_state,
1268 head: std::ptr::null(),
1269 tail: std::ptr::null(),
1270 });
1271 }
1272 Entry::Occupied(mut occupied) => {
1273 let entry = occupied.get_mut();
1274 if unsafe { entry.is_allowed(target_state, entry.head.is_null()) } {
1276 if let LockState::ReadLock = target_state {
1277 entry.read_count += 1;
1278 guard_keys.push(*lock);
1279 } else {
1280 entry.state = target_state;
1281 guard_keys.push(*lock);
1282 }
1283 } else {
1284 unsafe {
1287 *lock_waker.as_mut().get_unchecked_mut() = Some(LockWaker {
1288 next: UnsafeCell::new(std::ptr::null()),
1289 prev: UnsafeCell::new(entry.tail),
1290 key: *lock,
1291 waker: UnsafeCell::new(WakerState::Pending),
1292 target_state: target_state,
1293 is_upgrade: false,
1294 _pin: PhantomPinned,
1295 });
1296 }
1297 let waker = (*lock_waker).as_ref().unwrap();
1298 if entry.tail.is_null() {
1299 entry.head = waker;
1300 } else {
1301 unsafe {
1303 *(*entry.tail).next.get() = waker;
1304 }
1305 }
1306 entry.tail = waker;
1307 }
1308 }
1309 }
1310 }
1311 if let Some(waker) = &*lock_waker {
1312 waker.wait(self).await;
1313 guard_keys.push(*lock);
1314 }
1315 }
1316 guard
1317 }
1318
1319 pub fn drop_transaction(&self, transaction: &mut Transaction<'_>) {
1321 let mut locks = self.locks.lock();
1322 locks.drop_write_locks(std::mem::take(&mut transaction.txn_locks));
1323 }
1324
1325 pub async fn commit_prepare(&self, transaction: &Transaction<'_>) {
1327 self.commit_prepare_keys(&transaction.txn_locks).await;
1328 }
1329
1330 async fn commit_prepare_keys(&self, lock_keys: &LockKeys) {
1331 for lock in lock_keys.iter() {
1332 let lock_waker = None;
1333 pin_mut!(lock_waker);
1334 {
1335 let mut locks = self.locks.lock();
1336 let entry = locks.keys.get_mut(lock).unwrap();
1337 if entry.state == LockState::WriteLock {
1342 continue;
1343 }
1344 assert_eq!(entry.state, LockState::Locked);
1345
1346 if entry.read_count == 0 {
1347 entry.state = LockState::WriteLock;
1348 } else {
1349 unsafe {
1352 *lock_waker.as_mut().get_unchecked_mut() = Some(LockWaker {
1353 next: UnsafeCell::new(entry.head),
1354 prev: UnsafeCell::new(std::ptr::null()),
1355 key: *lock,
1356 waker: UnsafeCell::new(WakerState::Pending),
1357 target_state: LockState::WriteLock,
1358 is_upgrade: true,
1359 _pin: PhantomPinned,
1360 });
1361 }
1362 let waker = (*lock_waker).as_ref().unwrap();
1363 if entry.head.is_null() {
1364 entry.tail = (*lock_waker).as_ref().unwrap();
1365 } else {
1366 unsafe {
1368 *(*entry.head).prev.get() = waker;
1369 }
1370 }
1371 entry.head = waker;
1372 }
1373 }
1374
1375 if let Some(waker) = &*lock_waker {
1376 waker.wait(self).await;
1377 }
1378 }
1379 }
1380
1381 pub async fn read_lock<'a>(&'a self, lock_keys: LockKeys) -> ReadGuard<'a> {
1387 debug_assert_not_too_long!(self.lock(lock_keys, LockState::ReadLock)).left().unwrap()
1388 }
1389
1390 pub async fn write_lock<'a>(&'a self, lock_keys: LockKeys) -> WriteGuard<'a> {
1393 debug_assert_not_too_long!(self.lock(lock_keys, LockState::WriteLock)).right().unwrap()
1394 }
1395
1396 pub fn downgrade_locks(&self, lock_keys: &LockKeys) {
1399 self.locks.lock().downgrade_locks(lock_keys);
1400 }
1401}
1402
1403impl LockEntry {
1405 unsafe fn wake(&mut self) {
1406 if self.head.is_null() || self.state == LockState::WriteLock {
1408 return;
1409 }
1410
1411 let waker = unsafe { &*self.head };
1412
1413 if waker.is_upgrade {
1414 if self.read_count > 0 {
1415 return;
1416 }
1417 } else if !unsafe { self.is_allowed(waker.target_state, true) } {
1418 return;
1419 }
1420
1421 unsafe { self.pop_and_wake() };
1422
1423 if waker.target_state == LockState::WriteLock {
1426 return;
1427 }
1428
1429 while !self.head.is_null() && unsafe { (*self.head).target_state } == LockState::ReadLock {
1430 unsafe { self.pop_and_wake() };
1431 }
1432 }
1433
1434 unsafe fn pop_and_wake(&mut self) {
1435 let waker = unsafe { &*self.head };
1436
1437 self.head = unsafe { *waker.next.get() };
1439 if self.head.is_null() {
1440 self.tail = std::ptr::null()
1441 } else {
1442 unsafe { *(*self.head).prev.get() = std::ptr::null() };
1443 }
1444
1445 if waker.target_state == LockState::ReadLock {
1447 self.read_count += 1;
1448 } else {
1449 self.state = waker.target_state;
1450 }
1451
1452 if let WakerState::Registered(waker) =
1454 std::mem::replace(unsafe { &mut *waker.waker.get() }, WakerState::Woken)
1455 {
1456 waker.wake();
1457 }
1458 }
1459
1460 fn can_remove(&self) -> bool {
1461 self.state == LockState::ReadLock && self.read_count == 0
1462 }
1463
1464 unsafe fn remove_waker(&mut self, waker: &LockWaker) {
1465 unsafe {
1466 let is_first = (*waker.prev.get()).is_null();
1467 if is_first {
1468 self.head = *waker.next.get();
1469 } else {
1470 *(**waker.prev.get()).next.get() = *waker.next.get();
1471 }
1472 if (*waker.next.get()).is_null() {
1473 self.tail = *waker.prev.get();
1474 } else {
1475 *(**waker.next.get()).prev.get() = *waker.prev.get();
1476 }
1477 if is_first {
1478 self.wake();
1481 }
1482 }
1483 }
1484
1485 unsafe fn is_allowed(&self, target_state: LockState, is_head: bool) -> bool {
1489 match self.state {
1490 LockState::ReadLock => {
1491 (self.read_count == 0
1493 || target_state == LockState::Locked
1494 || target_state == LockState::ReadLock)
1495 && is_head
1496 }
1497 LockState::Locked => {
1498 target_state == LockState::ReadLock
1502 && (is_head || unsafe { !(*self.head).is_upgrade })
1503 }
1504 LockState::WriteLock => false,
1505 }
1506 }
1507
1508 unsafe fn downgrade_lock(&mut self) {
1509 assert_eq!(std::mem::replace(&mut self.state, LockState::Locked), LockState::WriteLock);
1510 unsafe { self.wake() };
1511 }
1512}
1513
1514#[must_use]
1515pub struct ReadGuard<'a> {
1516 manager: LockManagerRef<'a>,
1517 lock_keys: LockKeys,
1518}
1519
1520impl ReadGuard<'_> {
1521 pub fn fs(&self) -> Option<&Arc<FxFilesystem>> {
1522 if let LockManagerRef::Owned(fs) = &self.manager { Some(fs) } else { None }
1523 }
1524
1525 pub fn into_owned(mut self, fs: Arc<FxFilesystem>) -> ReadGuard<'static> {
1526 ReadGuard {
1527 manager: LockManagerRef::Owned(fs),
1528 lock_keys: std::mem::replace(&mut self.lock_keys, LockKeys::None),
1529 }
1530 }
1531}
1532
1533impl Drop for ReadGuard<'_> {
1534 fn drop(&mut self) {
1535 let mut locks = self.manager.locks.lock();
1536 locks.drop_read_locks(std::mem::take(&mut self.lock_keys));
1537 }
1538}
1539
1540impl fmt::Debug for ReadGuard<'_> {
1541 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1542 f.debug_struct("ReadGuard")
1543 .field("manager", &(&self.manager as *const _))
1544 .field("lock_keys", &self.lock_keys)
1545 .finish()
1546 }
1547}
1548
1549#[must_use]
1550pub struct WriteGuard<'a> {
1551 manager: LockManagerRef<'a>,
1552 lock_keys: LockKeys,
1553}
1554
1555impl WriteGuard<'_> {
1556 pub fn into_owned(mut self, fs: Arc<FxFilesystem>) -> WriteGuard<'static> {
1557 WriteGuard {
1558 manager: LockManagerRef::Owned(fs),
1559 lock_keys: std::mem::replace(&mut self.lock_keys, LockKeys::None),
1560 }
1561 }
1562}
1563
1564impl Drop for WriteGuard<'_> {
1565 fn drop(&mut self) {
1566 let mut locks = self.manager.locks.lock();
1567 locks.drop_write_locks(std::mem::take(&mut self.lock_keys));
1568 }
1569}
1570
1571impl fmt::Debug for WriteGuard<'_> {
1572 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1573 f.debug_struct("WriteGuard")
1574 .field("manager", &(&self.manager as *const _))
1575 .field("lock_keys", &self.lock_keys)
1576 .finish()
1577 }
1578}
1579
1580enum LockManagerRef<'a> {
1581 Borrowed(&'a LockManager),
1582 Owned(Arc<FxFilesystem>),
1583}
1584
1585impl Deref for LockManagerRef<'_> {
1586 type Target = LockManager;
1587
1588 fn deref(&self) -> &Self::Target {
1589 match self {
1590 LockManagerRef::Borrowed(m) => m,
1591 LockManagerRef::Owned(f) => f.lock_manager(),
1592 }
1593 }
1594}
1595
1596impl<'a> From<&'a LockManager> for LockManagerRef<'a> {
1597 fn from(value: &'a LockManager) -> Self {
1598 LockManagerRef::Borrowed(value)
1599 }
1600}
1601
1602#[cfg(test)]
1603mod tests {
1604 use super::{
1605 AssocObj, AttributeId, LockKey, LockKeys, LockManager, LockState, Mutation,
1606 ObjectMutationIterator, Options, TxnMutation,
1607 };
1608 use crate::filesystem::FxFilesystem;
1609 use fuchsia_async as fasync;
1610 use fuchsia_sync::Mutex;
1611 use futures::channel::oneshot::channel;
1612 use futures::future::FutureExt;
1613 use futures::stream::FuturesUnordered;
1614 use futures::{StreamExt, join, pin_mut};
1615 use std::collections::BTreeSet;
1616 use std::task::Poll;
1617 use std::time::Duration;
1618 use storage_device::DeviceHolder;
1619 use storage_device::fake_device::FakeDevice;
1620
1621 #[fuchsia::test]
1622 async fn test_simple() {
1623 let device = DeviceHolder::new(FakeDevice::new(4096, 1024));
1624 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
1625 let mut t = fs
1626 .root_store()
1627 .new_transaction(lock_keys![], Options::default())
1628 .await
1629 .expect("new_transaction failed");
1630 t.add(1, Mutation::BeginFlush);
1631 assert!(!t.is_empty());
1632 }
1633
1634 #[fuchsia::test]
1635 async fn test_locks() {
1636 let device = DeviceHolder::new(FakeDevice::new(4096, 1024));
1637 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
1638 let (send1, recv1) = channel();
1639 let (send2, recv2) = channel();
1640 let (send3, recv3) = channel();
1641 let done = Mutex::new(false);
1642 let mut futures = FuturesUnordered::new();
1643 futures.push(
1644 async {
1645 let _t = fs
1646 .root_store()
1647 .new_transaction(
1648 lock_keys![LockKey::object_attribute(1, 2, AttributeId::TEST_ID)],
1649 Options::default(),
1650 )
1651 .await
1652 .expect("new_transaction failed");
1653 send1.send(()).unwrap(); send3.send(()).unwrap(); recv2.await.unwrap();
1656 fasync::Timer::new(Duration::from_millis(100)).await;
1658 assert!(!*done.lock());
1659 }
1660 .boxed(),
1661 );
1662 futures.push(
1663 async {
1664 recv1.await.unwrap();
1665 let _t = fs
1667 .root_store()
1668 .new_transaction(
1669 lock_keys![LockKey::object_attribute(2, 2, AttributeId::TEST_ID)],
1670 Options::default(),
1671 )
1672 .await
1673 .expect("new_transaction failed");
1674 send2.send(()).unwrap();
1676 }
1677 .boxed(),
1678 );
1679 futures.push(
1680 async {
1681 recv3.await.unwrap();
1683 let _t = fs
1684 .root_store()
1685 .new_transaction(
1686 lock_keys![LockKey::object_attribute(1, 2, AttributeId::TEST_ID)],
1687 Options::default(),
1688 )
1689 .await;
1690 *done.lock() = true;
1691 }
1692 .boxed(),
1693 );
1694 while let Some(()) = futures.next().await {}
1695 }
1696
1697 #[fuchsia::test]
1698 async fn test_read_lock_after_write_lock() {
1699 let device = DeviceHolder::new(FakeDevice::new(4096, 1024));
1700 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
1701 let (send1, recv1) = channel();
1702 let (send2, recv2) = channel();
1703 let done = Mutex::new(false);
1704 join!(
1705 async {
1706 let t = fs
1707 .root_store()
1708 .new_transaction(
1709 lock_keys![LockKey::object_attribute(1, 2, AttributeId::TEST_ID)],
1710 Options::default(),
1711 )
1712 .await
1713 .expect("new_transaction failed");
1714 send1.send(()).unwrap(); recv2.await.unwrap();
1716 t.commit().await.expect("commit failed");
1717 *done.lock() = true;
1718 },
1719 async {
1720 recv1.await.unwrap();
1721 let _guard = fs
1723 .lock_manager()
1724 .read_lock(lock_keys![LockKey::object_attribute(1, 2, AttributeId::TEST_ID)])
1725 .await;
1726 send2.send(()).unwrap();
1728 fasync::Timer::new(Duration::from_millis(100)).await;
1731 assert!(!*done.lock());
1732 },
1733 );
1734 }
1735
1736 #[fuchsia::test]
1737 async fn test_write_lock_after_read_lock() {
1738 let device = DeviceHolder::new(FakeDevice::new(4096, 1024));
1739 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
1740 let (send1, recv1) = channel();
1741 let (send2, recv2) = channel();
1742 let done = Mutex::new(false);
1743 join!(
1744 async {
1745 let _guard = fs
1747 .lock_manager()
1748 .read_lock(lock_keys![LockKey::object_attribute(1, 2, AttributeId::TEST_ID)])
1749 .await;
1750 send1.send(()).unwrap();
1752 recv2.await.unwrap();
1753 fasync::Timer::new(Duration::from_millis(100)).await;
1756 assert!(!*done.lock());
1757 },
1758 async {
1759 recv1.await.unwrap();
1760 let t = fs
1761 .root_store()
1762 .new_transaction(
1763 lock_keys![LockKey::object_attribute(1, 2, AttributeId::TEST_ID)],
1764 Options::default(),
1765 )
1766 .await
1767 .expect("new_transaction failed");
1768 send2.send(()).unwrap(); t.commit().await.expect("commit failed");
1770 *done.lock() = true;
1771 },
1772 );
1773 }
1774
1775 #[fuchsia::test]
1776 async fn test_drop_uncommitted_transaction() {
1777 let device = DeviceHolder::new(FakeDevice::new(4096, 1024));
1778 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
1779 let key = lock_keys![LockKey::object(1, 1)];
1780
1781 {
1783 let _write_lock = fs
1784 .root_store()
1785 .new_transaction(key.clone(), Options::default())
1786 .await
1787 .expect("new_transaction failed");
1788 let _read_lock = fs.lock_manager().read_lock(key.clone()).await;
1789 }
1790 {
1792 let _write_lock = fs
1793 .root_store()
1794 .new_transaction(key.clone(), Options::default())
1795 .await
1796 .expect("new_transaction failed");
1797 }
1798 fs.root_store()
1800 .new_transaction(key.clone(), Options::default())
1801 .await
1802 .expect("new_transaction failed");
1803 }
1804
1805 #[fuchsia::test]
1806 async fn test_drop_waiting_write_lock() {
1807 let manager = LockManager::new();
1808 let keys = lock_keys![LockKey::object(1, 1)];
1809 {
1810 let _guard = manager.lock(keys.clone(), LockState::ReadLock).await;
1811 if let Poll::Ready(_) =
1812 futures::poll!(manager.lock(keys.clone(), LockState::WriteLock).boxed())
1813 {
1814 assert!(false);
1815 }
1816 }
1817 let _ = manager.lock(keys, LockState::WriteLock).await;
1818 }
1819
1820 #[fuchsia::test]
1821 async fn test_write_lock_blocks_everything() {
1822 let manager = LockManager::new();
1823 let keys = lock_keys![LockKey::object(1, 1)];
1824 {
1825 let _guard = manager.lock(keys.clone(), LockState::WriteLock).await;
1826 if let Poll::Ready(_) =
1827 futures::poll!(manager.lock(keys.clone(), LockState::WriteLock).boxed())
1828 {
1829 assert!(false);
1830 }
1831 if let Poll::Ready(_) =
1832 futures::poll!(manager.lock(keys.clone(), LockState::ReadLock).boxed())
1833 {
1834 assert!(false);
1835 }
1836 }
1837 {
1838 let _guard = manager.lock(keys.clone(), LockState::WriteLock).await;
1839 }
1840 {
1841 let _guard = manager.lock(keys, LockState::ReadLock).await;
1842 }
1843 }
1844
1845 #[fuchsia::test]
1846 async fn test_downgrade_locks() {
1847 let manager = LockManager::new();
1848 let keys = lock_keys![LockKey::object(1, 1)];
1849 let _guard = manager.txn_lock(keys.clone()).await;
1850 manager.commit_prepare_keys(&keys).await;
1851
1852 let mut read_lock: FuturesUnordered<_> =
1854 std::iter::once(manager.read_lock(keys.clone())).collect();
1855
1856 assert!(futures::poll!(read_lock.next()).is_pending());
1858
1859 manager.downgrade_locks(&keys);
1860
1861 assert!(futures::poll!(read_lock.next()).is_ready());
1863 }
1864
1865 #[fuchsia::test]
1866 async fn test_dropped_write_lock_wakes() {
1867 let manager = LockManager::new();
1868 let keys = lock_keys![LockKey::object(1, 1)];
1869 let _guard = manager.lock(keys.clone(), LockState::ReadLock).await;
1870 let mut read_lock = FuturesUnordered::new();
1871 read_lock.push(manager.lock(keys.clone(), LockState::ReadLock));
1872
1873 {
1874 let write_lock = manager.lock(keys, LockState::WriteLock);
1875 pin_mut!(write_lock);
1876
1877 assert!(futures::poll!(write_lock).is_pending());
1879
1880 assert!(futures::poll!(read_lock.next()).is_pending());
1882 }
1883
1884 assert!(futures::poll!(read_lock.next()).is_ready());
1886 }
1887
1888 #[fuchsia::test]
1889 async fn test_drop_upgrade() {
1890 let manager = LockManager::new();
1891 let keys = lock_keys![LockKey::object(1, 1)];
1892 let _guard = manager.lock(keys.clone(), LockState::Locked).await;
1893
1894 {
1895 let commit_prepare = manager.commit_prepare_keys(&keys);
1896 pin_mut!(commit_prepare);
1897 let _read_guard = manager.lock(keys.clone(), LockState::ReadLock).await;
1898 assert!(futures::poll!(commit_prepare).is_pending());
1899
1900 }
1903
1904 manager.commit_prepare_keys(&keys).await;
1906 }
1907
1908 #[fuchsia::test]
1909 async fn test_woken_upgrade_blocks_reads() {
1910 let manager = LockManager::new();
1911 let keys = lock_keys![LockKey::object(1, 1)];
1912 let guard = manager.lock(keys.clone(), LockState::Locked).await;
1914
1915 let read1 = manager.lock(keys.clone(), LockState::ReadLock).await;
1917
1918 let commit_prepare = manager.commit_prepare_keys(&keys);
1920 pin_mut!(commit_prepare);
1921 assert!(futures::poll!(commit_prepare.as_mut()).is_pending());
1922
1923 let read2 = manager.lock(keys.clone(), LockState::ReadLock);
1925 pin_mut!(read2);
1926 assert!(futures::poll!(read2.as_mut()).is_pending());
1927
1928 std::mem::drop(read1);
1930 assert!(futures::poll!(commit_prepare).is_ready());
1931
1932 assert!(futures::poll!(read2.as_mut()).is_pending());
1934
1935 std::mem::drop(guard);
1937 assert!(futures::poll!(read2).is_ready());
1938 }
1939
1940 static LOCK_KEY_1: LockKey = LockKey::flush(1);
1941 static LOCK_KEY_2: LockKey = LockKey::flush(2);
1942 static LOCK_KEY_3: LockKey = LockKey::flush(3);
1943
1944 fn assert_lock_keys_equal(value: &LockKeys, expected: &LockKeys) {
1946 match (value, expected) {
1947 (LockKeys::None, LockKeys::None) => {}
1948 (LockKeys::Inline(key1), LockKeys::Inline(key2)) => {
1949 if key1 != key2 {
1950 panic!("{key1:?} != {key2:?}");
1951 }
1952 }
1953 (LockKeys::Vec(vec1), LockKeys::Vec(vec2)) => {
1954 if vec1 != vec2 {
1955 panic!("{vec1:?} != {vec2:?}");
1956 }
1957 if vec1.capacity() != vec2.capacity() {
1958 panic!(
1959 "LockKeys have different capacity: {} != {}",
1960 vec1.capacity(),
1961 vec2.capacity()
1962 );
1963 }
1964 }
1965 (_, _) => panic!("{value:?} != {expected:?}"),
1966 }
1967 }
1968
1969 fn assert_lock_keys_equivalent(value: &LockKeys, expected: &LockKeys) {
1971 let value: Vec<_> = value.iter().collect();
1972 let expected: Vec<_> = expected.iter().collect();
1973 assert_eq!(value, expected);
1974 }
1975
1976 #[test]
1977 fn test_lock_keys_macro() {
1978 assert_lock_keys_equal(&lock_keys![], &LockKeys::None);
1979 assert_lock_keys_equal(&lock_keys![LOCK_KEY_1], &LockKeys::Inline(LOCK_KEY_1));
1980 assert_lock_keys_equal(
1981 &lock_keys![LOCK_KEY_1, LOCK_KEY_2],
1982 &LockKeys::Vec(vec![LOCK_KEY_1, LOCK_KEY_2]),
1983 );
1984 }
1985
1986 #[test]
1987 fn test_lock_keys_with_capacity() {
1988 assert_lock_keys_equal(&LockKeys::with_capacity(0), &LockKeys::None);
1989 assert_lock_keys_equal(&LockKeys::with_capacity(1), &LockKeys::None);
1990 assert_lock_keys_equal(&LockKeys::with_capacity(2), &LockKeys::Vec(Vec::with_capacity(2)));
1991 }
1992
1993 #[test]
1994 fn test_lock_keys_len() {
1995 assert_eq!(lock_keys![].len(), 0);
1996 assert_eq!(lock_keys![LOCK_KEY_1].len(), 1);
1997 assert_eq!(lock_keys![LOCK_KEY_1, LOCK_KEY_2].len(), 2);
1998 }
1999
2000 #[test]
2001 fn test_lock_keys_contains() {
2002 assert_eq!(lock_keys![].contains(&LOCK_KEY_1), false);
2003 assert_eq!(lock_keys![LOCK_KEY_1].contains(&LOCK_KEY_1), true);
2004 assert_eq!(lock_keys![LOCK_KEY_1].contains(&LOCK_KEY_2), false);
2005 assert_eq!(lock_keys![LOCK_KEY_1, LOCK_KEY_2].contains(&LOCK_KEY_1), true);
2006 assert_eq!(lock_keys![LOCK_KEY_1, LOCK_KEY_2].contains(&LOCK_KEY_2), true);
2007 assert_eq!(lock_keys![LOCK_KEY_1, LOCK_KEY_2].contains(&LOCK_KEY_3), false);
2008 }
2009
2010 #[test]
2011 fn test_lock_keys_push() {
2012 let mut keys = lock_keys![];
2013 keys.push(LOCK_KEY_1);
2014 assert_lock_keys_equal(&keys, &LockKeys::Inline(LOCK_KEY_1));
2015 keys.push(LOCK_KEY_2);
2016 assert_lock_keys_equal(&keys, &LockKeys::Vec(vec![LOCK_KEY_1, LOCK_KEY_2]));
2017 keys.push(LOCK_KEY_3);
2018 assert_lock_keys_equivalent(
2019 &keys,
2020 &LockKeys::Vec(vec![LOCK_KEY_1, LOCK_KEY_2, LOCK_KEY_3]),
2021 );
2022 }
2023
2024 #[test]
2025 fn test_lock_keys_sort_unstable() {
2026 let mut keys = lock_keys![];
2027 keys.sort_unstable();
2028 assert_lock_keys_equal(&keys, &lock_keys![]);
2029
2030 let mut keys = lock_keys![LOCK_KEY_1];
2031 keys.sort_unstable();
2032 assert_lock_keys_equal(&keys, &lock_keys![LOCK_KEY_1]);
2033
2034 let mut keys = lock_keys![LOCK_KEY_2, LOCK_KEY_1];
2035 keys.sort_unstable();
2036 assert_lock_keys_equal(&keys, &lock_keys![LOCK_KEY_1, LOCK_KEY_2]);
2037 }
2038
2039 #[test]
2040 fn test_lock_keys_dedup() {
2041 let mut keys = lock_keys![];
2042 keys.dedup();
2043 assert_lock_keys_equal(&keys, &lock_keys![]);
2044
2045 let mut keys = lock_keys![LOCK_KEY_1];
2046 keys.dedup();
2047 assert_lock_keys_equal(&keys, &lock_keys![LOCK_KEY_1]);
2048
2049 let mut keys = lock_keys![LOCK_KEY_1, LOCK_KEY_1];
2050 keys.dedup();
2051 assert_lock_keys_equivalent(&keys, &lock_keys![LOCK_KEY_1]);
2052 }
2053
2054 #[test]
2055 fn test_lock_keys_truncate() {
2056 let mut keys = lock_keys![];
2057 keys.truncate(5);
2058 assert_lock_keys_equal(&keys, &lock_keys![]);
2059 keys.truncate(0);
2060 assert_lock_keys_equal(&keys, &lock_keys![]);
2061
2062 let mut keys = lock_keys![LOCK_KEY_1];
2063 keys.truncate(5);
2064 assert_lock_keys_equal(&keys, &lock_keys![LOCK_KEY_1]);
2065 keys.truncate(0);
2066 assert_lock_keys_equal(&keys, &lock_keys![]);
2067
2068 let mut keys = lock_keys![LOCK_KEY_1, LOCK_KEY_2];
2069 keys.truncate(5);
2070 assert_lock_keys_equal(&keys, &lock_keys![LOCK_KEY_1, LOCK_KEY_2]);
2071 keys.truncate(1);
2072 assert_lock_keys_equivalent(&keys, &lock_keys![LOCK_KEY_1]);
2074 }
2075
2076 #[test]
2077 fn test_lock_keys_iter() {
2078 assert_eq!(lock_keys![].iter().collect::<Vec<_>>(), Vec::<&LockKey>::new());
2079
2080 assert_eq!(lock_keys![LOCK_KEY_1].iter().collect::<Vec<_>>(), vec![&LOCK_KEY_1]);
2081
2082 assert_eq!(
2083 lock_keys![LOCK_KEY_1, LOCK_KEY_2].iter().collect::<Vec<_>>(),
2084 vec![&LOCK_KEY_1, &LOCK_KEY_2]
2085 );
2086 }
2087
2088 #[test]
2089 fn test_object_mutation_iterator() {
2090 let mut mutations = BTreeSet::new();
2091 mutations.insert(TxnMutation {
2092 object_id: 1,
2093 mutation: Mutation::BeginFlush,
2094 associated_object: AssocObj::None,
2095 });
2096 mutations.insert(TxnMutation {
2097 object_id: 1,
2098 mutation: Mutation::EndFlush,
2099 associated_object: AssocObj::None,
2100 });
2101 mutations.insert(TxnMutation {
2102 object_id: 2,
2103 mutation: Mutation::DeleteVolume,
2104 associated_object: AssocObj::None,
2105 });
2106
2107 let mut iter = mutations.iter().peekable();
2108
2109 {
2110 let mut obj_iter = ObjectMutationIterator::new(&mut iter).expect("expected object 1");
2111 assert_eq!(obj_iter.object_id(), 1);
2112 assert_eq!(obj_iter.next(), Some(&Mutation::BeginFlush));
2113 assert_eq!(obj_iter.next(), Some(&Mutation::EndFlush));
2114 assert_eq!(obj_iter.next(), None);
2115 }
2116
2117 {
2118 let mut obj_iter = ObjectMutationIterator::new(&mut iter).expect("expected object 2");
2119 assert_eq!(obj_iter.object_id(), 2);
2120 assert_eq!(obj_iter.next(), Some(&Mutation::DeleteVolume));
2121 assert_eq!(obj_iter.next(), None);
2122 }
2123
2124 assert!(ObjectMutationIterator::new(&mut iter).is_none());
2126 }
2127
2128 #[test]
2129 fn test_object_mutation_iterator_drop_drains_remaining() {
2130 let mut mutations = BTreeSet::new();
2131 mutations.insert(TxnMutation {
2133 object_id: 1,
2134 mutation: Mutation::BeginFlush,
2135 associated_object: AssocObj::None,
2136 });
2137 mutations.insert(TxnMutation {
2138 object_id: 1,
2139 mutation: Mutation::EndFlush,
2140 associated_object: AssocObj::None,
2141 });
2142 mutations.insert(TxnMutation {
2143 object_id: 1,
2144 mutation: Mutation::DeleteVolume,
2145 associated_object: AssocObj::None,
2146 });
2147 mutations.insert(TxnMutation {
2149 object_id: 2,
2150 mutation: Mutation::BeginFlush,
2151 associated_object: AssocObj::None,
2152 });
2153 mutations.insert(TxnMutation {
2154 object_id: 2,
2155 mutation: Mutation::EndFlush,
2156 associated_object: AssocObj::None,
2157 });
2158
2159 let mut iter = mutations.iter().peekable();
2160
2161 {
2162 let mut obj_iter = ObjectMutationIterator::new(&mut iter).expect("expected object 1");
2163 assert_eq!(obj_iter.object_id(), 1);
2164 assert_eq!(obj_iter.next(), Some(&Mutation::BeginFlush));
2165 }
2167
2168 {
2169 let obj_iter = ObjectMutationIterator::new(&mut iter).expect("expected object 2");
2170 assert_eq!(obj_iter.object_id(), 2);
2171 }
2173
2174 assert!(ObjectMutationIterator::new(&mut iter).is_none());
2176 }
2177}