1use crate::checksum::Checksum;
6use crate::errors::FxfsError;
7use crate::filesystem::Filesystem;
8use crate::log::*;
9use crate::lsm_tree::types::Item;
10use crate::object_handle::INVALID_OBJECT_ID;
11use crate::object_store::allocator::{AllocatorItem, Hold, Reservation};
12use crate::object_store::object_manager::{ObjectManager, reserved_space_from_journal_usage};
13use crate::object_store::object_record::{
14 BytesAndNodes, FxfsKey, FxfsKeyV49, ObjectItem, ObjectItemV56, ObjectItemV59, ObjectItemV62,
15 ObjectKey, ObjectKeyData, ObjectValue, ProjectProperty,
16};
17use crate::object_store::{AttributeId, AttributeKey, ProjectId};
18use crate::serialized_types::{Migrate, Versioned, migrate_nodefault, migrate_to_version};
19use anyhow::Error;
20use async_trait::async_trait;
21use either::{Either, Left, Right};
22use event_listener::Event;
23use fprint::TypeFingerprint;
24use fuchsia_sync::Mutex;
25use futures::future::poll_fn;
26use futures::pin_mut;
27use rustc_hash::FxHashMap as HashMap;
28use scopeguard::ScopeGuard;
29use serde::{Deserialize, Serialize};
30use std::cell::UnsafeCell;
31use std::cmp::Ordering;
32use std::collections::hash_map::Entry;
33use std::collections::{BTreeSet, btree_set};
34use std::iter::Peekable;
35use std::marker::PhantomPinned;
36use std::ops::{Deref, DerefMut, Range};
37use std::sync::Arc;
38use std::sync::atomic::{AtomicU64, Ordering as AtomicOrdering};
39use std::task::{Poll, Waker};
40use std::{fmt, mem};
41
42#[derive(Clone, Copy, Default)]
62pub enum ReservationOptions<'a> {
63 #[default]
71 New,
72
73 Borrowed,
88
89 Hold(&'a Reservation),
92}
93
94#[derive(Clone, Copy, Default)]
98pub struct Options<'a> {
99 pub skip_journal_checks: bool,
102
103 pub reservation: ReservationOptions<'a>,
105
106 pub parent_transaction: Option<&'a Transaction<'a>>,
114}
115
116pub const TRANSACTION_MAX_JOURNAL_USAGE: u64 = 24_576;
123pub const TRANSACTION_METADATA_MAX_AMOUNT: u64 =
124 reserved_space_from_journal_usage(TRANSACTION_MAX_JOURNAL_USAGE);
125
126#[must_use]
127pub struct TransactionLocks<'a>(pub WriteGuard<'a>);
128
129pub struct TransactionConcurrencyLimiter {
131 limit: u64,
132 in_flight_transactions: AtomicU64,
134 transaction_limit_event: Event,
137}
138
139impl TransactionConcurrencyLimiter {
140 pub fn new(limit: u64) -> Self {
141 Self {
142 limit,
143 in_flight_transactions: AtomicU64::new(0),
144 transaction_limit_event: Event::new(),
145 }
146 }
147
148 pub async fn add(&self, skip_journal_checks: bool) {
149 if skip_journal_checks {
150 self.in_flight_transactions.fetch_add(1, AtomicOrdering::Relaxed);
151 } else {
152 let inc = || {
153 let mut in_flights = self.in_flight_transactions.load(AtomicOrdering::Relaxed);
154 while in_flights < self.limit {
155 match self.in_flight_transactions.compare_exchange_weak(
156 in_flights,
157 in_flights + 1,
158 AtomicOrdering::Relaxed,
159 AtomicOrdering::Relaxed,
160 ) {
161 Ok(_) => return true,
162 Err(x) => in_flights = x,
163 }
164 }
165 false
166 };
167 while !inc() {
168 let listener = self.transaction_limit_event.listen();
169 if inc() {
170 break;
171 }
172 debug_assert_not_too_long!(listener);
173 }
174 }
175 }
176
177 pub fn sub(&self) {
178 let old = self.in_flight_transactions.fetch_sub(1, AtomicOrdering::Relaxed);
179 assert!(old != 0);
180 if old <= self.limit {
181 self.transaction_limit_event.notify(usize::MAX);
182 }
183 }
184}
185
186#[async_trait]
191pub trait TransactionSink: Send + Sync + 'static {
192 async fn new_transaction<'a>(
194 self: Arc<Self>,
195 txn_locks: LockKeys,
196 options: Options<'a>,
197 ) -> Result<Transaction<'a>, Error>;
198 async fn check_space(&self) -> Result<(), Error>;
201 fn reserve(&self, owner_object_id: Option<u64>, amount: u64) -> Option<Reservation>;
203 fn image_builder_mode(&self) -> bool {
205 false
206 }
207 async fn commit(&self, transaction: &mut Transaction<'_>) -> Result<u64, Error>;
210 async fn commit_with_callback<'a>(
212 &self,
213 transaction: &mut Transaction<'_>,
214 callback: Box<dyn FnOnce(u64) + Send + 'a>,
215 ) -> Result<u64, Error>;
216 fn downgrade_locks(&self, lock_keys: &LockKeys);
219 fn drop_transaction(&self, transaction: &mut Transaction<'_>);
222 fn lock_manager(&self) -> &LockManager;
224 fn transaction_limiter(&self) -> &TransactionConcurrencyLimiter;
226 fn metadata_reservation(&self) -> Option<&Reservation> {
228 None
229 }
230 fn is_system_store(&self, _store_id: u64) -> bool {
232 false
233 }
234}
235
236pub type Mutation = MutationV62;
241
242#[derive(
243 Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize, TypeFingerprint, Versioned,
244)]
245#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
246pub enum MutationV62 {
247 ObjectStore(ObjectStoreMutationV62),
248 EncryptedObjectStore(#[serde(with = "crate::zerocopy_serialization")] Box<[u8]>),
249 Allocator(AllocatorMutationV32),
250
251 BeginFlush,
253
254 EndFlush(u64),
258
259 DeleteVolume,
261 UpdateMutationsKey(UpdateMutationsKey),
262 CreateInternalDir(u64),
263
264 #[serde(skip)]
270 #[cfg_attr(fuzz, arbitrary(skip))]
271 UpdateBorrowed(u64),
272}
273
274#[derive(Migrate, Clone, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint, Versioned)]
275#[migrate_to_version(MutationV62)]
276pub enum MutationV61 {
277 ObjectStore(ObjectStoreMutationV59),
278 EncryptedObjectStore(#[serde(with = "crate::zerocopy_serialization")] Box<[u8]>),
279 Allocator(AllocatorMutationV32),
280 BeginFlush,
281 EndFlush(u64),
282 DeleteVolume,
283 UpdateMutationsKey(UpdateMutationsKey),
284 CreateInternalDir(u64),
285 #[serde(skip)]
286 UpdateBorrowed(u64),
287}
288
289#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint, Versioned)]
290pub enum MutationV59 {
291 ObjectStore(ObjectStoreMutationV59),
292 EncryptedObjectStore(#[serde(with = "crate::zerocopy_serialization")] Box<[u8]>),
293 Allocator(AllocatorMutationV32),
294 BeginFlush,
295 EndFlush,
296 DeleteVolume,
297 UpdateBorrowed(u64),
298 UpdateMutationsKey(UpdateMutationsKey),
299 CreateInternalDir(u64),
300}
301
302impl From<MutationV59> for MutationV61 {
303 fn from(mutation: MutationV59) -> Self {
304 match mutation {
305 MutationV59::ObjectStore(m) => Self::ObjectStore(m),
306 MutationV59::EncryptedObjectStore(m) => Self::EncryptedObjectStore(m),
307 MutationV59::Allocator(m) => Self::Allocator(m),
308 MutationV59::BeginFlush => Self::BeginFlush,
309 MutationV59::EndFlush => Self::EndFlush(0),
310 MutationV59::DeleteVolume => Self::DeleteVolume,
311 MutationV59::UpdateBorrowed(b) => Self::UpdateBorrowed(b),
312 MutationV59::UpdateMutationsKey(k) => Self::UpdateMutationsKey(k),
313 MutationV59::CreateInternalDir(id) => Self::CreateInternalDir(id),
314 }
315 }
316}
317
318#[derive(Migrate, Clone, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint, Versioned)]
319#[migrate_to_version(MutationV59)]
320pub enum MutationV57 {
321 ObjectStore(ObjectStoreMutationV56),
322 EncryptedObjectStore(#[serde(with = "crate::zerocopy_serialization")] Box<[u8]>),
323 Allocator(AllocatorMutationV32),
324 BeginFlush,
325 EndFlush,
326 DeleteVolume,
327 UpdateBorrowed(u64),
328 UpdateMutationsKey(UpdateMutationsKey),
329 CreateInternalDir(u64),
330}
331
332#[derive(Migrate, Clone, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint, Versioned)]
333#[migrate_to_version(MutationV57)]
334pub enum MutationV56 {
335 ObjectStore(ObjectStoreMutationV56),
336 EncryptedObjectStore(#[serde(with = "crate::zerocopy_serialization")] Box<[u8]>),
337 Allocator(AllocatorMutationV32),
338 BeginFlush,
339 EndFlush,
340 DeleteVolume,
341 UpdateBorrowed(u64),
342 UpdateMutationsKey(UpdateMutationsKey),
343 CreateInternalDir(u64),
344}
345
346impl Mutation {
347 pub fn insert_object(key: ObjectKey, value: ObjectValue) -> Self {
348 Mutation::ObjectStore(ObjectStoreMutation {
349 item: Item::new(key, value),
350 op: Operation::Insert,
351 })
352 }
353
354 pub fn replace_or_insert_object(key: ObjectKey, value: ObjectValue) -> Self {
355 Mutation::ObjectStore(ObjectStoreMutation {
356 item: Item::new(key, value),
357 op: Operation::ReplaceOrInsert,
358 })
359 }
360
361 pub fn merge_object(key: ObjectKey, value: ObjectValue) -> Self {
362 Mutation::ObjectStore(ObjectStoreMutation {
363 item: Item::new(key, value),
364 op: Operation::Merge,
365 })
366 }
367
368 pub fn update_mutations_key(key: FxfsKey) -> Self {
369 Mutation::UpdateMutationsKey(key.into())
370 }
371
372 pub fn counts_towards_object_journal_usage(&self) -> bool {
382 !matches!(self, Mutation::BeginFlush | Mutation::EndFlush(_) | Mutation::DeleteVolume)
383 }
384}
385
386pub type ObjectStoreMutation = ObjectStoreMutationV62;
390
391#[derive(Clone, Debug, Serialize, Deserialize, TypeFingerprint)]
392#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
393pub struct ObjectStoreMutationV62 {
394 pub item: ObjectItemV62,
395 pub op: Operation,
396}
397
398#[derive(Migrate, Clone, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint, Versioned)]
399#[migrate_to_version(ObjectStoreMutationV62)]
400#[migrate_nodefault]
401pub struct ObjectStoreMutationV59 {
402 pub item: ObjectItemV59,
403 pub op: Operation,
404}
405
406#[derive(Migrate, Clone, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint, Versioned)]
407#[migrate_to_version(ObjectStoreMutationV59)]
408#[migrate_nodefault]
409pub struct ObjectStoreMutationV56 {
410 pub item: ObjectItemV56,
411 pub op: Operation,
412}
413
414pub type Operation = OperationV32;
416
417#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TypeFingerprint)]
418#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
419pub enum OperationV32 {
420 Insert,
421 ReplaceOrInsert,
422 Merge,
423}
424
425impl Ord for ObjectStoreMutation {
426 fn cmp(&self, other: &Self) -> Ordering {
427 self.item.key.cmp(&other.item.key)
428 }
429}
430
431impl PartialOrd for ObjectStoreMutation {
432 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
433 Some(self.cmp(other))
434 }
435}
436
437impl PartialEq for ObjectStoreMutation {
438 fn eq(&self, other: &Self) -> bool {
439 self.item.key.eq(&other.item.key)
440 }
441}
442
443impl Eq for ObjectStoreMutation {}
444
445impl Ord for AllocatorItem {
446 fn cmp(&self, other: &Self) -> Ordering {
447 self.key.cmp(&other.key)
448 }
449}
450
451impl PartialOrd for AllocatorItem {
452 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
453 Some(self.cmp(other))
454 }
455}
456
457pub type DeviceRange = DeviceRangeV32;
460
461#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, TypeFingerprint)]
462#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
463pub struct DeviceRangeV32(pub Range<u64>);
464
465impl Deref for DeviceRange {
466 type Target = Range<u64>;
467
468 fn deref(&self) -> &Self::Target {
469 &self.0
470 }
471}
472
473impl DerefMut for DeviceRange {
474 fn deref_mut(&mut self) -> &mut Self::Target {
475 &mut self.0
476 }
477}
478
479impl From<Range<u64>> for DeviceRange {
480 fn from(range: Range<u64>) -> Self {
481 Self(range)
482 }
483}
484
485impl Into<Range<u64>> for DeviceRange {
486 fn into(self) -> Range<u64> {
487 self.0
488 }
489}
490
491impl Ord for DeviceRange {
492 fn cmp(&self, other: &Self) -> Ordering {
493 self.start.cmp(&other.start).then(self.end.cmp(&other.end))
494 }
495}
496
497impl PartialOrd for DeviceRange {
498 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
499 Some(self.cmp(other))
500 }
501}
502
503pub type AllocatorMutation = AllocatorMutationV32;
504
505#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize, TypeFingerprint)]
507#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
508pub enum AllocatorMutationV32 {
509 Allocate {
510 device_range: DeviceRangeV32,
511 owner_object_id: u64,
512 },
513 Deallocate {
514 device_range: DeviceRangeV32,
515 owner_object_id: u64,
516 },
517 SetLimit {
518 owner_object_id: u64,
519 bytes: u64,
520 },
521 MarkForDeletion(u64),
527}
528pub type UpdateMutationsKey = UpdateMutationsKeyV49;
531
532#[derive(Clone, Debug, Serialize, Deserialize, TypeFingerprint)]
533pub struct UpdateMutationsKeyV49(pub FxfsKeyV49);
534
535impl From<UpdateMutationsKey> for FxfsKey {
536 fn from(outer: UpdateMutationsKey) -> Self {
537 outer.0
538 }
539}
540
541impl From<FxfsKey> for UpdateMutationsKey {
542 fn from(inner: FxfsKey) -> Self {
543 Self(inner)
544 }
545}
546
547#[cfg(fuzz)]
548impl<'a> arbitrary::Arbitrary<'a> for UpdateMutationsKey {
549 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
550 Ok(UpdateMutationsKey::from(FxfsKey::arbitrary(u).unwrap()))
551 }
552}
553
554impl Ord for UpdateMutationsKey {
555 fn cmp(&self, other: &Self) -> Ordering {
556 (self as *const UpdateMutationsKey).cmp(&(other as *const _))
557 }
558}
559
560impl PartialOrd for UpdateMutationsKey {
561 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
562 Some(self.cmp(other))
563 }
564}
565
566impl Eq for UpdateMutationsKey {}
567
568impl PartialEq for UpdateMutationsKey {
569 fn eq(&self, other: &Self) -> bool {
570 std::ptr::eq(self, other)
571 }
572}
573
574#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Copy)]
582pub enum LockKey {
583 Flush {
585 object_id: u64,
586 },
587
588 ObjectAttribute {
590 store_object_id: u64,
591 object_id: u64,
592 attribute_id: AttributeId,
593 },
594
595 Object {
597 store_object_id: u64,
598 object_id: u64,
599 },
600
601 ProjectId {
602 store_object_id: u64,
603 project_id: ProjectId,
604 },
605
606 Truncate {
608 store_object_id: u64,
609 object_id: u64,
610 },
611
612 InternalDirectory {
614 store_object_id: u64,
615 },
616
617 PreCacheKeys {
621 store_object_id: u64,
622 },
623}
624
625impl LockKey {
626 pub const fn object_attribute(
627 store_object_id: u64,
628 object_id: u64,
629 attribute_id: AttributeId,
630 ) -> Self {
631 LockKey::ObjectAttribute { store_object_id, object_id, attribute_id }
632 }
633
634 pub const fn object(store_object_id: u64, object_id: u64) -> Self {
635 LockKey::Object { store_object_id, object_id }
636 }
637
638 pub const fn flush(object_id: u64) -> Self {
639 LockKey::Flush { object_id }
640 }
641
642 pub const fn truncate(store_object_id: u64, object_id: u64) -> Self {
643 LockKey::Truncate { store_object_id, object_id }
644 }
645
646 pub const fn pre_cache_keys(store_object_id: u64) -> Self {
647 LockKey::PreCacheKeys { store_object_id }
648 }
649}
650
651#[derive(Clone, Debug)]
653pub enum LockKeys {
654 None,
655 Inline(LockKey),
656 Vec(Vec<LockKey>),
657}
658
659impl LockKeys {
660 pub fn with_capacity(capacity: usize) -> Self {
661 if capacity > 1 { LockKeys::Vec(Vec::with_capacity(capacity)) } else { LockKeys::None }
662 }
663
664 pub fn push(&mut self, key: LockKey) {
665 match self {
666 Self::None => *self = LockKeys::Inline(key),
667 Self::Inline(inline) => {
668 *self = LockKeys::Vec(vec![*inline, key]);
669 }
670 Self::Vec(vec) => vec.push(key),
671 }
672 }
673
674 pub fn truncate(&mut self, len: usize) {
675 match self {
676 Self::None => {}
677 Self::Inline(_) => {
678 if len == 0 {
679 *self = Self::None;
680 }
681 }
682 Self::Vec(vec) => vec.truncate(len),
683 }
684 }
685
686 fn len(&self) -> usize {
687 match self {
688 Self::None => 0,
689 Self::Inline(_) => 1,
690 Self::Vec(vec) => vec.len(),
691 }
692 }
693
694 fn contains(&self, key: &LockKey) -> bool {
695 match self {
696 Self::None => false,
697 Self::Inline(single) => single == key,
698 Self::Vec(vec) => vec.contains(key),
699 }
700 }
701
702 fn sort_unstable(&mut self) {
703 match self {
704 Self::Vec(vec) => vec.sort_unstable(),
705 _ => {}
706 }
707 }
708
709 fn dedup(&mut self) {
710 match self {
711 Self::Vec(vec) => vec.dedup(),
712 _ => {}
713 }
714 }
715
716 fn iter(&self) -> LockKeysIter<'_> {
717 match self {
718 LockKeys::None => LockKeysIter::None,
719 LockKeys::Inline(key) => LockKeysIter::Inline(key),
720 LockKeys::Vec(keys) => LockKeysIter::Vec(keys.iter()),
721 }
722 }
723}
724
725enum LockKeysIter<'a> {
726 None,
727 Inline(&'a LockKey),
728 Vec(std::slice::Iter<'a, LockKey>),
729}
730
731impl<'a> Iterator for LockKeysIter<'a> {
732 type Item = &'a LockKey;
733 fn next(&mut self) -> Option<Self::Item> {
734 match self {
735 Self::None => None,
736 Self::Inline(inline) => {
737 let next = *inline;
738 *self = Self::None;
739 Some(next)
740 }
741 Self::Vec(vec) => vec.next(),
742 }
743 }
744}
745
746impl Default for LockKeys {
747 fn default() -> Self {
748 LockKeys::None
749 }
750}
751
752#[macro_export]
753macro_rules! lock_keys {
754 () => {
755 $crate::object_store::transaction::LockKeys::None
756 };
757 ($lock_key:expr $(,)?) => {
758 $crate::object_store::transaction::LockKeys::Inline($lock_key)
759 };
760 ($($lock_keys:expr),+ $(,)?) => {
761 $crate::object_store::transaction::LockKeys::Vec(vec![$($lock_keys),+])
762 };
763}
764pub use lock_keys;
765
766pub trait AssociatedObject: Send + Sync {
770 fn will_apply_mutation(&self, _mutation: &Mutation, _object_id: u64, _manager: &ObjectManager) {
771 }
772}
773
774pub enum AssocObj<'a> {
775 None,
776 Borrowed(&'a dyn AssociatedObject),
777 Owned(Box<dyn AssociatedObject>),
778}
779
780impl AssocObj<'_> {
781 pub fn map<R, F: FnOnce(&dyn AssociatedObject) -> R>(&self, f: F) -> Option<R> {
782 match self {
783 AssocObj::None => None,
784 AssocObj::Borrowed(b) => Some(f(*b)),
785 AssocObj::Owned(o) => Some(f(o.as_ref())),
786 }
787 }
788}
789
790pub struct TxnMutation<'a> {
791 pub object_id: u64,
795
796 pub mutation: Mutation,
798
799 pub associated_object: AssocObj<'a>,
802}
803
804impl Ord for TxnMutation<'_> {
812 fn cmp(&self, other: &Self) -> Ordering {
813 self.object_id.cmp(&other.object_id).then_with(|| self.mutation.cmp(&other.mutation))
814 }
815}
816
817impl PartialOrd for TxnMutation<'_> {
818 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
819 Some(self.cmp(other))
820 }
821}
822
823impl PartialEq for TxnMutation<'_> {
824 fn eq(&self, other: &Self) -> bool {
825 self.object_id.eq(&other.object_id) && self.mutation.eq(&other.mutation)
826 }
827}
828
829impl Eq for TxnMutation<'_> {}
830
831impl std::fmt::Debug for TxnMutation<'_> {
832 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
833 f.debug_struct("TxnMutation")
834 .field("object_id", &self.object_id)
835 .field("mutation", &self.mutation)
836 .finish()
837 }
838}
839
840pub struct ObjectMutationIterator<'a, 'b> {
844 iter: &'a mut Peekable<btree_set::Iter<'b, TxnMutation<'b>>>,
845 object_id: u64,
846}
847
848impl<'a, 'b> ObjectMutationIterator<'a, 'b> {
849 pub fn new(iter: &'a mut Peekable<btree_set::Iter<'b, TxnMutation<'b>>>) -> Option<Self> {
850 let object_id = iter.peek()?.object_id;
851 Some(Self { iter, object_id })
852 }
853
854 pub fn object_id(&self) -> u64 {
855 self.object_id
856 }
857}
858
859impl<'b> Iterator for ObjectMutationIterator<'_, 'b> {
860 type Item = &'b Mutation;
861
862 fn next(&mut self) -> Option<Self::Item> {
863 if self.iter.peek().is_some_and(|m| m.object_id == self.object_id) {
864 Some(&self.iter.next().unwrap().mutation)
865 } else {
866 None
867 }
868 }
869}
870
871impl Drop for ObjectMutationIterator<'_, '_> {
872 fn drop(&mut self) {
875 for _ in self.by_ref() {}
876 }
877}
878
879#[derive(Debug)]
880pub enum MetadataReservation<'a> {
881 Borrowed,
884
885 Reservation(Reservation),
887
888 Hold(Hold<'a>),
890}
891
892impl MetadataReservation<'_> {
893 pub fn is_borrowed(&self) -> bool {
896 matches!(self, Self::Borrowed)
897 }
898}
899
900pub struct Transaction<'a> {
902 sink: Arc<dyn TransactionSink>,
903
904 mutations: BTreeSet<TxnMutation<'a>>,
906
907 txn_locks: LockKeys,
909
910 pub metadata_reservation: MetadataReservation<'a>,
912
913 new_objects: BTreeSet<(u64, u64)>,
916
917 checksums: Vec<(u64, Range<u64>, Vec<Checksum>, bool)>,
919
920 includes_write: bool,
922
923 pub skip_journal_checks: bool,
925
926 pub(crate) parent_transaction: Option<&'a Transaction<'a>>,
929}
930
931impl<'a> Transaction<'a> {
932 pub async fn new(
935 sink: Arc<dyn TransactionSink>,
936 options: Options<'a>,
937 txn_locks: LockKeys,
938 ) -> Result<Transaction<'a>, Error> {
939 if options.parent_transaction.is_none() {
940 sink.transaction_limiter().add(options.skip_journal_checks).await;
941 }
942 let metadata_reservation = if sink.image_builder_mode() {
956 MetadataReservation::Borrowed
957 } else {
958 match options.reservation {
959 ReservationOptions::New => {
960 MetadataReservation::Reservation(sink.reserve(None, 0).unwrap())
961 }
962 ReservationOptions::Borrowed => MetadataReservation::Borrowed,
963 ReservationOptions::Hold(reservation) => {
964 MetadataReservation::Hold(reservation.reserve(0).unwrap())
965 }
966 }
967 };
968 let mut transaction = Transaction {
969 sink: sink.clone(),
970 mutations: BTreeSet::new(),
971 txn_locks: LockKeys::default(),
972 metadata_reservation,
973 new_objects: BTreeSet::new(),
974 checksums: Vec::new(),
975 includes_write: false,
976 skip_journal_checks: options.skip_journal_checks,
977 parent_transaction: options.parent_transaction,
978 };
979 transaction.add_transaction_reservation().await?;
980
981 transaction.txn_locks = {
982 let lock_manager = sink.lock_manager();
983 let mut write_guard = lock_manager.txn_lock(txn_locks).await;
984 std::mem::take(&mut write_guard.0.lock_keys)
985 };
986 Ok(transaction)
987 }
988
989 async fn add_transaction_reservation(&mut self) -> Result<(), Error> {
996 if self.sink.image_builder_mode() {
997 return Ok(());
1000 }
1001 if !self.skip_journal_checks {
1002 self.sink.check_space().await?;
1003 }
1004
1005 match &mut self.metadata_reservation {
1006 MetadataReservation::Borrowed => {}
1007 MetadataReservation::Hold(hold) => {
1008 let amount = TRANSACTION_METADATA_MAX_AMOUNT.saturating_sub(hold.amount());
1009 hold.add(hold.owner().reserve(amount).ok_or(FxfsError::NoSpace)?.forget());
1010 }
1011 MetadataReservation::Reservation(txn_reservation) => {
1012 txn_reservation.add(
1013 self.sink
1014 .reserve(
1015 txn_reservation.owner_object_id(),
1016 TRANSACTION_METADATA_MAX_AMOUNT
1017 .saturating_sub(txn_reservation.amount()),
1018 )
1019 .ok_or(FxfsError::NoSpace)?
1020 .forget(),
1021 );
1022 }
1023 }
1024 Ok(())
1025 }
1026
1027 pub fn allocator_reservation(&self, owner_object_id: u64) -> Option<&Reservation> {
1030 match &self.metadata_reservation {
1031 MetadataReservation::Borrowed => (!self.sink.image_builder_mode()
1032 && self.sink.is_system_store(owner_object_id))
1033 .then(|| self.sink.metadata_reservation())
1034 .flatten(),
1035 MetadataReservation::Hold(hold) => Some(hold.owner()),
1036 MetadataReservation::Reservation(_) => None,
1037 }
1038 }
1039
1040 pub fn mutations(&self) -> &BTreeSet<TxnMutation<'a>> {
1041 &self.mutations
1042 }
1043
1044 pub fn take_mutations(&mut self) -> BTreeSet<TxnMutation<'a>> {
1045 self.new_objects.clear();
1046 mem::take(&mut self.mutations)
1047 }
1048
1049 pub fn add(&mut self, object_id: u64, mutation: Mutation) -> Option<Mutation> {
1052 self.add_with_object(object_id, mutation, AssocObj::None)
1053 }
1054
1055 pub fn merge_bytes_and_nodes(
1059 &mut self,
1060 store_object_id: u64,
1061 key: ObjectKey,
1062 delta: BytesAndNodes,
1063 ) {
1064 let delta = match self.get_object_mutation(store_object_id, key.clone()) {
1065 Some(ObjectStoreMutation {
1066 item: Item { value: ObjectValue::BytesAndNodes { bytes, nodes }, .. },
1067 ..
1068 }) => delta + BytesAndNodes { bytes: *bytes, nodes: *nodes },
1069 _ => delta,
1070 };
1071 if delta.is_zero() {
1072 self.remove(store_object_id, Mutation::merge_object(key, ObjectValue::None));
1073 } else {
1074 self.add_with_object_internal(
1075 store_object_id,
1076 Mutation::merge_object(key, delta.into()),
1077 AssocObj::None,
1078 );
1079 }
1080 }
1081
1082 pub fn remove(&mut self, object_id: u64, mutation: Mutation) {
1084 let txn_mutation = TxnMutation { object_id, mutation, associated_object: AssocObj::None };
1085 if self.mutations.remove(&txn_mutation) {
1086 if let Mutation::ObjectStore(ObjectStoreMutation {
1087 item:
1088 ObjectItem {
1089 key: ObjectKey { object_id: new_object_id, data: ObjectKeyData::Object },
1090 ..
1091 },
1092 op: Operation::Insert,
1093 }) = txn_mutation.mutation
1094 {
1095 self.new_objects.remove(&(object_id, new_object_id));
1096 }
1097 }
1098 }
1099
1100 pub fn add_with_object(
1103 &mut self,
1104 object_id: u64,
1105 mutation: Mutation,
1106 associated_object: AssocObj<'a>,
1107 ) -> Option<Mutation> {
1108 debug_assert!(
1109 !matches!(
1110 mutation,
1111 Mutation::ObjectStore(ObjectStoreMutation {
1112 item: ObjectItem {
1113 key: ObjectKey {
1114 data: ObjectKeyData::Project { property: ProjectProperty::Usage, .. },
1115 ..
1116 },
1117 ..
1118 },
1119 ..
1120 })
1121 ),
1122 "Use merge_bytes_and_nodes"
1123 );
1124 self.add_with_object_internal(object_id, mutation, associated_object)
1125 }
1126
1127 fn add_with_object_internal(
1130 &mut self,
1131 object_id: u64,
1132 mutation: Mutation,
1133 associated_object: AssocObj<'a>,
1134 ) -> Option<Mutation> {
1135 assert!(object_id != INVALID_OBJECT_ID);
1136 match &mutation {
1137 Mutation::ObjectStore(ObjectStoreMutation {
1138 item:
1139 Item {
1140 key:
1141 ObjectKey {
1142 data: ObjectKeyData::Attribute(_, AttributeKey::Extent(_)), ..
1143 },
1144 ..
1145 },
1146 ..
1147 }) => {
1148 self.includes_write = true;
1149 }
1150 Mutation::Allocator(AllocatorMutation::Allocate { owner_object_id, .. }) => {
1151 assert!(
1152 !self.metadata_reservation.is_borrowed()
1153 || self.sink.image_builder_mode()
1154 || self.sink.is_system_store(*owner_object_id),
1155 "Allocations for non-system stores are not allowed in Borrowed transactions"
1156 );
1157 }
1158 _ => {}
1159 }
1160 let txn_mutation = TxnMutation { object_id, mutation, associated_object };
1161 self.verify_locks(&txn_mutation);
1162 self.mutations.replace(txn_mutation).map(|m| m.mutation)
1163 }
1164
1165 pub fn add_checksum(
1166 &mut self,
1167 owner_object_id: u64,
1168 range: Range<u64>,
1169 checksums: Vec<Checksum>,
1170 first_write: bool,
1171 ) {
1172 self.checksums.push((owner_object_id, range, checksums, first_write));
1173 }
1174
1175 pub fn includes_write(&self) -> bool {
1176 self.includes_write
1177 }
1178
1179 pub fn checksums(&self) -> &[(u64, Range<u64>, Vec<Checksum>, bool)] {
1180 &self.checksums
1181 }
1182
1183 pub fn take_checksums(&mut self) -> Vec<(u64, Range<u64>, Vec<Checksum>, bool)> {
1184 std::mem::replace(&mut self.checksums, Vec::new())
1185 }
1186
1187 fn verify_locks(&mut self, mutation: &TxnMutation<'_>) {
1188 match mutation {
1192 TxnMutation {
1193 mutation:
1194 Mutation::ObjectStore {
1195 0: ObjectStoreMutation { item: ObjectItem { key, .. }, op },
1196 },
1197 object_id: store_object_id,
1198 ..
1199 } => {
1200 match &key.data {
1201 ObjectKeyData::Attribute(..) => {
1202 }
1204 ObjectKeyData::Child { .. }
1205 | ObjectKeyData::EncryptedChild(_)
1206 | ObjectKeyData::EncryptedCasefoldChild(_)
1207 | ObjectKeyData::CasefoldChild { .. }
1208 | ObjectKeyData::LegacyCasefoldChild(_) => {
1209 let id = key.object_id;
1210 if !self.txn_locks.contains(&LockKey::object(*store_object_id, id))
1211 && !self.new_objects.contains(&(*store_object_id, id))
1212 {
1213 debug_assert!(
1214 false,
1215 "Not holding required lock for object {id} \
1216 in store {store_object_id}"
1217 );
1218 error!(
1219 "Not holding required lock for object {id} in store \
1220 {store_object_id}"
1221 )
1222 }
1223 }
1224 ObjectKeyData::GraveyardEntry { .. } => {
1225 }
1227 ObjectKeyData::GraveyardAttributeEntry { .. } => {
1228 }
1230 ObjectKeyData::Keys => {
1231 let id = key.object_id;
1232 if !self.txn_locks.contains(&LockKey::object(*store_object_id, id))
1233 && !self.new_objects.contains(&(*store_object_id, id))
1234 {
1235 debug_assert!(
1236 false,
1237 "Not holding required lock for object {id} \
1238 in store {store_object_id}"
1239 );
1240 error!(
1241 "Not holding required lock for object {id} in store \
1242 {store_object_id}"
1243 )
1244 }
1245 }
1246 ObjectKeyData::Object => match op {
1247 Operation::Insert => {
1249 self.new_objects.insert((*store_object_id, key.object_id));
1250 }
1251 Operation::Merge | Operation::ReplaceOrInsert => {
1252 let id = key.object_id;
1253 if !self.txn_locks.contains(&LockKey::object(*store_object_id, id))
1254 && !self.new_objects.contains(&(*store_object_id, id))
1255 {
1256 debug_assert!(
1257 false,
1258 "Not holding required lock for object {id} \
1259 in store {store_object_id}"
1260 );
1261 error!(
1262 "Not holding required lock for object {id} in store \
1263 {store_object_id}"
1264 )
1265 }
1266 }
1267 },
1268 ObjectKeyData::Project { project_id, property: ProjectProperty::Limit } => {
1269 if !self.txn_locks.contains(&LockKey::ProjectId {
1270 store_object_id: *store_object_id,
1271 project_id: *project_id,
1272 }) {
1273 debug_assert!(
1274 false,
1275 "Not holding required lock for project limit id {project_id} \
1276 in store {store_object_id}"
1277 );
1278 error!(
1279 "Not holding required lock for project limit id {project_id} in \
1280 store {store_object_id}"
1281 )
1282 }
1283 }
1284 ObjectKeyData::Project { property: ProjectProperty::Usage, .. } => match op {
1285 Operation::Insert | Operation::ReplaceOrInsert => {
1286 panic!(
1287 "Project usage is all handled by merging deltas, no inserts or \
1288 replacements should be used"
1289 );
1290 }
1291 Operation::Merge => {}
1293 },
1294 ObjectKeyData::ExtendedAttribute { .. } => {
1295 let id = key.object_id;
1296 if !self.txn_locks.contains(&LockKey::object(*store_object_id, id))
1297 && !self.new_objects.contains(&(*store_object_id, id))
1298 {
1299 debug_assert!(
1300 false,
1301 "Not holding required lock for object {id} \
1302 in store {store_object_id} while mutating extended attribute"
1303 );
1304 error!(
1305 "Not holding required lock for object {id} in store \
1306 {store_object_id} while mutating extended attribute"
1307 )
1308 }
1309 }
1310 }
1311 }
1312 TxnMutation { mutation: Mutation::DeleteVolume, object_id, .. } => {
1313 if !self.txn_locks.contains(&LockKey::flush(*object_id)) {
1314 debug_assert!(false, "Not holding required lock for DeleteVolume");
1315 error!("Not holding required lock for DeleteVolume");
1316 }
1317 }
1318 _ => {}
1319 }
1320 }
1321
1322 pub fn is_empty(&self) -> bool {
1324 self.mutations.is_empty()
1325 }
1326
1327 pub fn get_object_mutation(
1330 &self,
1331 store_object_id: u64,
1332 key: ObjectKey,
1333 ) -> Option<&ObjectStoreMutation> {
1334 if let Some(TxnMutation { mutation: Mutation::ObjectStore(mutation), .. }) =
1335 self.mutations.get(&TxnMutation {
1336 object_id: store_object_id,
1337 mutation: Mutation::insert_object(key, ObjectValue::None),
1338 associated_object: AssocObj::None,
1339 })
1340 {
1341 Some(mutation)
1342 } else {
1343 None
1344 }
1345 }
1346
1347 pub async fn commit(mut self) -> Result<u64, Error> {
1349 debug!(txn:? = &self; "Commit");
1350 let sink = self.sink.clone();
1351 sink.commit(&mut self).await
1352 }
1353
1354 pub async fn commit_with_callback<R: Send>(
1357 mut self,
1358 f: impl FnOnce(u64) -> R + Send,
1359 ) -> Result<R, Error> {
1360 debug!(txn:? = &self; "Commit");
1361 let mut res = None;
1362 let sink = self.sink.clone();
1363 sink.commit_with_callback(
1364 &mut self,
1365 Box::new(|offset| {
1366 res = Some(f(offset));
1367 }),
1368 )
1369 .await?;
1370 Ok(res.expect("callback should have been called"))
1371 }
1372
1373 pub async fn commit_and_continue(&mut self) -> Result<(), Error> {
1376 debug!(txn:? = self; "Commit");
1377 let sink = self.sink.clone();
1378 sink.commit(self).await?;
1379 assert!(self.mutations.is_empty());
1380 assert!(self.new_objects.is_empty());
1381 assert!(self.checksums.is_empty());
1382 self.includes_write = false;
1383 sink.downgrade_locks(&self.txn_locks);
1384 self.add_transaction_reservation().await
1385 }
1386
1387 pub async fn commit_prepare(&self) {
1390 self.sink.lock_manager().commit_prepare(self).await;
1391 }
1392}
1393
1394impl Drop for Transaction<'_> {
1395 fn drop(&mut self) {
1396 debug!(txn:? = &self; "Drop");
1399 let sink = self.sink.clone();
1400 if self.parent_transaction.is_none() {
1401 sink.transaction_limiter().sub();
1402 }
1403 sink.drop_transaction(self);
1404 }
1405}
1406
1407impl std::fmt::Debug for Transaction<'_> {
1408 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1409 f.debug_struct("Transaction")
1410 .field("mutations", &self.mutations)
1411 .field("txn_locks", &self.txn_locks)
1412 .field("reservation", &self.metadata_reservation)
1413 .finish()
1414 }
1415}
1416
1417pub enum BorrowedOrOwned<'a, T> {
1418 Borrowed(&'a T),
1419 Owned(T),
1420}
1421
1422impl<T> Deref for BorrowedOrOwned<'_, T> {
1423 type Target = T;
1424
1425 fn deref(&self) -> &Self::Target {
1426 match self {
1427 BorrowedOrOwned::Borrowed(b) => b,
1428 BorrowedOrOwned::Owned(o) => &o,
1429 }
1430 }
1431}
1432
1433impl<'a, T> From<&'a T> for BorrowedOrOwned<'a, T> {
1434 fn from(value: &'a T) -> Self {
1435 BorrowedOrOwned::Borrowed(value)
1436 }
1437}
1438
1439impl<T> From<T> for BorrowedOrOwned<'_, T> {
1440 fn from(value: T) -> Self {
1441 BorrowedOrOwned::Owned(value)
1442 }
1443}
1444
1445#[derive(Default)]
1474pub struct LockManager {
1475 locks: Mutex<Locks>,
1476}
1477
1478#[derive(Default)]
1479struct Locks {
1480 keys: HashMap<LockKey, LockEntry>,
1481}
1482
1483impl Locks {
1484 fn drop_lock(&mut self, key: LockKey, state: LockState) {
1485 if let Entry::Occupied(mut occupied) = self.keys.entry(key) {
1486 let entry = occupied.get_mut();
1487 let wake = match state {
1488 LockState::ReadLock => {
1489 entry.read_count -= 1;
1490 entry.read_count == 0
1491 }
1492 LockState::Locked | LockState::WriteLock => {
1494 entry.state = LockState::ReadLock;
1495 true
1496 }
1497 };
1498 if wake {
1499 unsafe {
1501 entry.wake();
1502 }
1503 if entry.can_remove() {
1504 occupied.remove_entry();
1505 }
1506 }
1507 } else {
1508 unreachable!();
1509 }
1510 }
1511
1512 fn drop_read_locks(&mut self, lock_keys: LockKeys) {
1513 for lock in lock_keys.iter() {
1514 self.drop_lock(*lock, LockState::ReadLock);
1515 }
1516 }
1517
1518 fn drop_write_locks(&mut self, lock_keys: LockKeys) {
1519 for lock in lock_keys.iter() {
1520 self.drop_lock(*lock, LockState::WriteLock);
1523 }
1524 }
1525
1526 fn downgrade_locks(&mut self, lock_keys: &LockKeys) {
1528 for lock in lock_keys.iter() {
1529 unsafe {
1531 self.keys.get_mut(lock).unwrap().downgrade_lock();
1532 }
1533 }
1534 }
1535}
1536
1537#[derive(Debug)]
1538struct LockEntry {
1539 read_count: u64,
1542
1543 state: LockState,
1545
1546 head: *const LockWaker,
1551 tail: *const LockWaker,
1552}
1553
1554unsafe impl Send for LockEntry {}
1555
1556struct LockWaker {
1559 next: UnsafeCell<*const LockWaker>,
1561 prev: UnsafeCell<*const LockWaker>,
1562
1563 key: LockKey,
1566
1567 waker: UnsafeCell<WakerState>,
1569
1570 target_state: LockState,
1572
1573 is_upgrade: bool,
1575
1576 _pin: PhantomPinned,
1578}
1579
1580enum WakerState {
1581 Pending,
1583
1584 Registered(Waker),
1586
1587 Woken,
1589}
1590
1591impl WakerState {
1592 fn is_woken(&self) -> bool {
1593 matches!(self, WakerState::Woken)
1594 }
1595}
1596
1597unsafe impl Send for LockWaker {}
1598unsafe impl Sync for LockWaker {}
1599
1600impl LockWaker {
1601 async fn wait(&self, manager: &LockManager) {
1603 let waker_guard = scopeguard::guard((), |_| {
1605 let mut locks = manager.locks.lock();
1606 unsafe {
1608 if (*self.waker.get()).is_woken() {
1609 if self.is_upgrade {
1611 locks.keys.get_mut(&self.key).unwrap().downgrade_lock();
1612 } else {
1613 locks.drop_lock(self.key, self.target_state);
1614 }
1615 } else {
1616 locks.keys.get_mut(&self.key).unwrap().remove_waker(self);
1619 }
1620 }
1621 });
1622
1623 poll_fn(|cx| {
1624 let _locks = manager.locks.lock();
1625 unsafe {
1627 if (*self.waker.get()).is_woken() {
1628 Poll::Ready(())
1629 } else {
1630 *self.waker.get() = WakerState::Registered(cx.waker().clone());
1631 Poll::Pending
1632 }
1633 }
1634 })
1635 .await;
1636
1637 ScopeGuard::into_inner(waker_guard);
1638 }
1639}
1640
1641#[derive(Copy, Clone, Debug, PartialEq)]
1642enum LockState {
1643 ReadLock,
1645
1646 Locked,
1649
1650 WriteLock,
1652}
1653
1654impl LockManager {
1655 pub async fn txn_lock<'a>(&'a self, lock_keys: LockKeys) -> TransactionLocks<'a> {
1659 TransactionLocks(
1660 debug_assert_not_too_long!(self.lock(lock_keys, LockState::Locked)).right().unwrap(),
1661 )
1662 }
1663
1664 async fn lock<'a>(
1667 &'a self,
1668 mut lock_keys: LockKeys,
1669 target_state: LockState,
1670 ) -> Either<ReadGuard<'a>, WriteGuard<'a>> {
1671 let mut guard = match &target_state {
1672 LockState::ReadLock => Left(ReadGuard {
1673 manager: self.into(),
1674 lock_keys: LockKeys::with_capacity(lock_keys.len()),
1675 }),
1676 LockState::Locked | LockState::WriteLock => Right(WriteGuard {
1677 manager: self.into(),
1678 lock_keys: LockKeys::with_capacity(lock_keys.len()),
1679 }),
1680 };
1681 let guard_keys = match &mut guard {
1682 Left(g) => &mut g.lock_keys,
1683 Right(g) => &mut g.lock_keys,
1684 };
1685 lock_keys.sort_unstable();
1686 lock_keys.dedup();
1687 for lock in lock_keys.iter() {
1688 let lock_waker = None;
1689 pin_mut!(lock_waker);
1690 {
1691 let mut locks = self.locks.lock();
1692 match locks.keys.entry(*lock) {
1693 Entry::Vacant(vacant) => {
1694 vacant.insert(LockEntry {
1695 read_count: if let LockState::ReadLock = target_state {
1696 guard_keys.push(*lock);
1697 1
1698 } else {
1699 guard_keys.push(*lock);
1700 0
1701 },
1702 state: target_state,
1703 head: std::ptr::null(),
1704 tail: std::ptr::null(),
1705 });
1706 }
1707 Entry::Occupied(mut occupied) => {
1708 let entry = occupied.get_mut();
1709 if unsafe { entry.is_allowed(target_state, entry.head.is_null()) } {
1711 if let LockState::ReadLock = target_state {
1712 entry.read_count += 1;
1713 guard_keys.push(*lock);
1714 } else {
1715 entry.state = target_state;
1716 guard_keys.push(*lock);
1717 }
1718 } else {
1719 unsafe {
1722 *lock_waker.as_mut().get_unchecked_mut() = Some(LockWaker {
1723 next: UnsafeCell::new(std::ptr::null()),
1724 prev: UnsafeCell::new(entry.tail),
1725 key: *lock,
1726 waker: UnsafeCell::new(WakerState::Pending),
1727 target_state: target_state,
1728 is_upgrade: false,
1729 _pin: PhantomPinned,
1730 });
1731 }
1732 let waker = (*lock_waker).as_ref().unwrap();
1733 if entry.tail.is_null() {
1734 entry.head = waker;
1735 } else {
1736 unsafe {
1738 *(*entry.tail).next.get() = waker;
1739 }
1740 }
1741 entry.tail = waker;
1742 }
1743 }
1744 }
1745 }
1746 if let Some(waker) = &*lock_waker {
1747 waker.wait(self).await;
1748 guard_keys.push(*lock);
1749 }
1750 }
1751 guard
1752 }
1753
1754 pub fn drop_transaction(&self, transaction: &mut Transaction<'_>) {
1756 let mut locks = self.locks.lock();
1757 locks.drop_write_locks(std::mem::take(&mut transaction.txn_locks));
1758 }
1759
1760 pub async fn commit_prepare(&self, transaction: &Transaction<'_>) {
1762 self.commit_prepare_keys(&transaction.txn_locks).await;
1763 }
1764
1765 async fn commit_prepare_keys(&self, lock_keys: &LockKeys) {
1766 for lock in lock_keys.iter() {
1767 let lock_waker = None;
1768 pin_mut!(lock_waker);
1769 {
1770 let mut locks = self.locks.lock();
1771 let entry = locks.keys.get_mut(lock).unwrap();
1772 if entry.state == LockState::WriteLock {
1777 continue;
1778 }
1779 assert_eq!(entry.state, LockState::Locked);
1780
1781 if entry.read_count == 0 {
1782 entry.state = LockState::WriteLock;
1783 } else {
1784 unsafe {
1787 *lock_waker.as_mut().get_unchecked_mut() = Some(LockWaker {
1788 next: UnsafeCell::new(entry.head),
1789 prev: UnsafeCell::new(std::ptr::null()),
1790 key: *lock,
1791 waker: UnsafeCell::new(WakerState::Pending),
1792 target_state: LockState::WriteLock,
1793 is_upgrade: true,
1794 _pin: PhantomPinned,
1795 });
1796 }
1797 let waker = (*lock_waker).as_ref().unwrap();
1798 if entry.head.is_null() {
1799 entry.tail = (*lock_waker).as_ref().unwrap();
1800 } else {
1801 unsafe {
1803 *(*entry.head).prev.get() = waker;
1804 }
1805 }
1806 entry.head = waker;
1807 }
1808 }
1809
1810 if let Some(waker) = &*lock_waker {
1811 waker.wait(self).await;
1812 }
1813 }
1814 }
1815
1816 pub async fn read_lock<'a>(&'a self, lock_keys: LockKeys) -> ReadGuard<'a> {
1822 debug_assert_not_too_long!(self.lock(lock_keys, LockState::ReadLock)).left().unwrap()
1823 }
1824
1825 pub async fn write_lock<'a>(&'a self, lock_keys: LockKeys) -> WriteGuard<'a> {
1828 debug_assert_not_too_long!(self.lock(lock_keys, LockState::WriteLock)).right().unwrap()
1829 }
1830
1831 pub fn downgrade_locks(&self, lock_keys: &LockKeys) {
1834 self.locks.lock().downgrade_locks(lock_keys);
1835 }
1836}
1837
1838impl LockEntry {
1840 unsafe fn wake(&mut self) {
1841 if self.head.is_null() || self.state == LockState::WriteLock {
1843 return;
1844 }
1845
1846 let waker = unsafe { &*self.head };
1847
1848 if waker.is_upgrade {
1849 if self.read_count > 0 {
1850 return;
1851 }
1852 } else if !unsafe { self.is_allowed(waker.target_state, true) } {
1853 return;
1854 }
1855
1856 unsafe { self.pop_and_wake() };
1857
1858 if waker.target_state == LockState::WriteLock {
1861 return;
1862 }
1863
1864 while !self.head.is_null() && unsafe { (*self.head).target_state } == LockState::ReadLock {
1865 unsafe { self.pop_and_wake() };
1866 }
1867 }
1868
1869 unsafe fn pop_and_wake(&mut self) {
1870 let waker = unsafe { &*self.head };
1871
1872 self.head = unsafe { *waker.next.get() };
1874 if self.head.is_null() {
1875 self.tail = std::ptr::null()
1876 } else {
1877 unsafe { *(*self.head).prev.get() = std::ptr::null() };
1878 }
1879
1880 if waker.target_state == LockState::ReadLock {
1882 self.read_count += 1;
1883 } else {
1884 self.state = waker.target_state;
1885 }
1886
1887 if let WakerState::Registered(waker) =
1889 std::mem::replace(unsafe { &mut *waker.waker.get() }, WakerState::Woken)
1890 {
1891 waker.wake();
1892 }
1893 }
1894
1895 fn can_remove(&self) -> bool {
1896 self.state == LockState::ReadLock && self.read_count == 0
1897 }
1898
1899 unsafe fn remove_waker(&mut self, waker: &LockWaker) {
1900 unsafe {
1901 let is_first = (*waker.prev.get()).is_null();
1902 if is_first {
1903 self.head = *waker.next.get();
1904 } else {
1905 *(**waker.prev.get()).next.get() = *waker.next.get();
1906 }
1907 if (*waker.next.get()).is_null() {
1908 self.tail = *waker.prev.get();
1909 } else {
1910 *(**waker.next.get()).prev.get() = *waker.prev.get();
1911 }
1912 if is_first {
1913 self.wake();
1916 }
1917 }
1918 }
1919
1920 unsafe fn is_allowed(&self, target_state: LockState, is_head: bool) -> bool {
1924 match self.state {
1925 LockState::ReadLock => {
1926 (self.read_count == 0
1928 || target_state == LockState::Locked
1929 || target_state == LockState::ReadLock)
1930 && is_head
1931 }
1932 LockState::Locked => {
1933 target_state == LockState::ReadLock
1937 && (is_head || unsafe { !(*self.head).is_upgrade })
1938 }
1939 LockState::WriteLock => false,
1940 }
1941 }
1942
1943 unsafe fn downgrade_lock(&mut self) {
1944 assert_eq!(std::mem::replace(&mut self.state, LockState::Locked), LockState::WriteLock);
1945 unsafe { self.wake() };
1946 }
1947}
1948
1949#[must_use]
1950pub struct ReadGuard<'a> {
1951 manager: LockManagerRef<'a>,
1952 lock_keys: LockKeys,
1953}
1954
1955impl ReadGuard<'_> {
1956 pub fn fs(&self) -> Option<&Arc<dyn Filesystem>> {
1957 if let LockManagerRef::Owned(fs) = &self.manager { Some(fs) } else { None }
1958 }
1959
1960 pub fn into_owned(mut self, fs: Arc<dyn Filesystem>) -> ReadGuard<'static> {
1961 ReadGuard {
1962 manager: LockManagerRef::Owned(fs),
1963 lock_keys: std::mem::replace(&mut self.lock_keys, LockKeys::None),
1964 }
1965 }
1966}
1967
1968impl Drop for ReadGuard<'_> {
1969 fn drop(&mut self) {
1970 let mut locks = self.manager.locks.lock();
1971 locks.drop_read_locks(std::mem::take(&mut self.lock_keys));
1972 }
1973}
1974
1975impl fmt::Debug for ReadGuard<'_> {
1976 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1977 f.debug_struct("ReadGuard")
1978 .field("manager", &(&self.manager as *const _))
1979 .field("lock_keys", &self.lock_keys)
1980 .finish()
1981 }
1982}
1983
1984#[must_use]
1985pub struct WriteGuard<'a> {
1986 manager: LockManagerRef<'a>,
1987 lock_keys: LockKeys,
1988}
1989
1990impl WriteGuard<'_> {
1991 pub fn into_owned(mut self, fs: Arc<dyn Filesystem>) -> WriteGuard<'static> {
1992 WriteGuard {
1993 manager: LockManagerRef::Owned(fs),
1994 lock_keys: std::mem::replace(&mut self.lock_keys, LockKeys::None),
1995 }
1996 }
1997}
1998
1999impl Drop for WriteGuard<'_> {
2000 fn drop(&mut self) {
2001 let mut locks = self.manager.locks.lock();
2002 locks.drop_write_locks(std::mem::take(&mut self.lock_keys));
2003 }
2004}
2005
2006impl fmt::Debug for WriteGuard<'_> {
2007 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2008 f.debug_struct("WriteGuard")
2009 .field("manager", &(&self.manager as *const _))
2010 .field("lock_keys", &self.lock_keys)
2011 .finish()
2012 }
2013}
2014
2015enum LockManagerRef<'a> {
2016 Borrowed(&'a LockManager),
2017 Owned(Arc<dyn Filesystem>),
2018}
2019
2020impl Deref for LockManagerRef<'_> {
2021 type Target = LockManager;
2022
2023 fn deref(&self) -> &Self::Target {
2024 match self {
2025 LockManagerRef::Borrowed(m) => m,
2026 LockManagerRef::Owned(f) => f.lock_manager(),
2027 }
2028 }
2029}
2030
2031impl<'a> From<&'a LockManager> for LockManagerRef<'a> {
2032 fn from(value: &'a LockManager) -> Self {
2033 LockManagerRef::Borrowed(value)
2034 }
2035}
2036
2037#[cfg(test)]
2038mod tests {
2039 use super::{
2040 AssocObj, AttributeId, LockKey, LockKeys, LockManager, LockState, Mutation,
2041 ObjectMutationIterator, Options, ReservationOptions, Transaction,
2042 TransactionConcurrencyLimiter, TransactionSink, TxnMutation,
2043 };
2044 use crate::filesystem::FxFilesystem;
2045 use crate::object_store::allocator::{Reservation, ReservationOwner};
2046 use crate::object_store::{BytesAndNodes, ObjectKey};
2047 use anyhow::Error;
2048 use async_trait::async_trait;
2049 use fuchsia_async as fasync;
2050 use fuchsia_sync::Mutex;
2051 use futures::channel::oneshot::channel;
2052 use futures::future::FutureExt;
2053 use futures::stream::FuturesUnordered;
2054 use futures::{StreamExt, join, pin_mut};
2055 use std::collections::BTreeSet;
2056 use std::sync::Arc;
2057 use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
2058 use std::task::Poll;
2059 use std::time::Duration;
2060 use storage_device::DeviceHolder;
2061 use storage_device::fake_device::FakeDevice;
2062
2063 #[fuchsia::test]
2064 async fn test_simple() {
2065 let device = DeviceHolder::new(FakeDevice::new(4096, 1024));
2066 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
2067 let mut t = fs
2068 .root_store()
2069 .new_transaction(lock_keys![], Options::default())
2070 .await
2071 .expect("new_transaction failed");
2072 t.add(1, Mutation::BeginFlush);
2073 assert!(!t.is_empty());
2074 }
2075
2076 #[fuchsia::test]
2077 async fn test_locks() {
2078 let device = DeviceHolder::new(FakeDevice::new(4096, 1024));
2079 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
2080 let (send1, recv1) = channel();
2081 let (send2, recv2) = channel();
2082 let (send3, recv3) = channel();
2083 let done = Mutex::new(false);
2084 let mut futures = FuturesUnordered::new();
2085 futures.push(
2086 async {
2087 let _t = fs
2088 .root_store()
2089 .new_transaction(
2090 lock_keys![LockKey::object_attribute(1, 2, AttributeId::TEST_ID)],
2091 Options::default(),
2092 )
2093 .await
2094 .expect("new_transaction failed");
2095 send1.send(()).unwrap(); send3.send(()).unwrap(); recv2.await.unwrap();
2098 fasync::Timer::new(Duration::from_millis(100)).await;
2100 assert!(!*done.lock());
2101 }
2102 .boxed(),
2103 );
2104 futures.push(
2105 async {
2106 recv1.await.unwrap();
2107 let _t = fs
2109 .root_store()
2110 .new_transaction(
2111 lock_keys![LockKey::object_attribute(2, 2, AttributeId::TEST_ID)],
2112 Options::default(),
2113 )
2114 .await
2115 .expect("new_transaction failed");
2116 send2.send(()).unwrap();
2118 }
2119 .boxed(),
2120 );
2121 futures.push(
2122 async {
2123 recv3.await.unwrap();
2125 let _t = fs
2126 .root_store()
2127 .new_transaction(
2128 lock_keys![LockKey::object_attribute(1, 2, AttributeId::TEST_ID)],
2129 Options::default(),
2130 )
2131 .await;
2132 *done.lock() = true;
2133 }
2134 .boxed(),
2135 );
2136 while let Some(()) = futures.next().await {}
2137 }
2138
2139 #[fuchsia::test]
2140 async fn test_read_lock_after_write_lock() {
2141 let device = DeviceHolder::new(FakeDevice::new(4096, 1024));
2142 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
2143 let (send1, recv1) = channel();
2144 let (send2, recv2) = channel();
2145 let done = Mutex::new(false);
2146 join!(
2147 async {
2148 let t = fs
2149 .root_store()
2150 .new_transaction(
2151 lock_keys![LockKey::object_attribute(1, 2, AttributeId::TEST_ID)],
2152 Options::default(),
2153 )
2154 .await
2155 .expect("new_transaction failed");
2156 send1.send(()).unwrap(); recv2.await.unwrap();
2158 t.commit().await.expect("commit failed");
2159 *done.lock() = true;
2160 },
2161 async {
2162 recv1.await.unwrap();
2163 let _guard = fs
2165 .lock_manager()
2166 .read_lock(lock_keys![LockKey::object_attribute(1, 2, AttributeId::TEST_ID)])
2167 .await;
2168 send2.send(()).unwrap();
2170 fasync::Timer::new(Duration::from_millis(100)).await;
2173 assert!(!*done.lock());
2174 },
2175 );
2176 }
2177
2178 #[fuchsia::test]
2179 async fn test_write_lock_after_read_lock() {
2180 let device = DeviceHolder::new(FakeDevice::new(4096, 1024));
2181 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
2182 let (send1, recv1) = channel();
2183 let (send2, recv2) = channel();
2184 let done = Mutex::new(false);
2185 join!(
2186 async {
2187 let _guard = fs
2189 .lock_manager()
2190 .read_lock(lock_keys![LockKey::object_attribute(1, 2, AttributeId::TEST_ID)])
2191 .await;
2192 send1.send(()).unwrap();
2194 recv2.await.unwrap();
2195 fasync::Timer::new(Duration::from_millis(100)).await;
2198 assert!(!*done.lock());
2199 },
2200 async {
2201 recv1.await.unwrap();
2202 let t = fs
2203 .root_store()
2204 .new_transaction(
2205 lock_keys![LockKey::object_attribute(1, 2, AttributeId::TEST_ID)],
2206 Options::default(),
2207 )
2208 .await
2209 .expect("new_transaction failed");
2210 send2.send(()).unwrap(); t.commit().await.expect("commit failed");
2212 *done.lock() = true;
2213 },
2214 );
2215 }
2216
2217 #[fuchsia::test]
2218 async fn test_drop_uncommitted_transaction() {
2219 let device = DeviceHolder::new(FakeDevice::new(4096, 1024));
2220 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
2221 let key = lock_keys![LockKey::object(1, 1)];
2222
2223 {
2225 let _write_lock = fs
2226 .root_store()
2227 .new_transaction(key.clone(), Options::default())
2228 .await
2229 .expect("new_transaction failed");
2230 let _read_lock = fs.lock_manager().read_lock(key.clone()).await;
2231 }
2232 {
2234 let _write_lock = fs
2235 .root_store()
2236 .new_transaction(key.clone(), Options::default())
2237 .await
2238 .expect("new_transaction failed");
2239 }
2240 fs.root_store()
2242 .new_transaction(key.clone(), Options::default())
2243 .await
2244 .expect("new_transaction failed");
2245 }
2246
2247 #[fuchsia::test]
2248 async fn test_drop_waiting_write_lock() {
2249 let manager = LockManager::default();
2250 let keys = lock_keys![LockKey::object(1, 1)];
2251 {
2252 let _guard = manager.lock(keys.clone(), LockState::ReadLock).await;
2253 if let Poll::Ready(_) =
2254 futures::poll!(manager.lock(keys.clone(), LockState::WriteLock).boxed())
2255 {
2256 assert!(false);
2257 }
2258 }
2259 let _ = manager.lock(keys, LockState::WriteLock).await;
2260 }
2261
2262 #[fuchsia::test]
2263 async fn test_write_lock_blocks_everything() {
2264 let manager = LockManager::default();
2265 let keys = lock_keys![LockKey::object(1, 1)];
2266 {
2267 let _guard = manager.lock(keys.clone(), LockState::WriteLock).await;
2268 if let Poll::Ready(_) =
2269 futures::poll!(manager.lock(keys.clone(), LockState::WriteLock).boxed())
2270 {
2271 assert!(false);
2272 }
2273 if let Poll::Ready(_) =
2274 futures::poll!(manager.lock(keys.clone(), LockState::ReadLock).boxed())
2275 {
2276 assert!(false);
2277 }
2278 }
2279 {
2280 let _guard = manager.lock(keys.clone(), LockState::WriteLock).await;
2281 }
2282 {
2283 let _guard = manager.lock(keys, LockState::ReadLock).await;
2284 }
2285 }
2286
2287 #[fuchsia::test]
2288 async fn test_downgrade_locks() {
2289 let manager = LockManager::default();
2290 let keys = lock_keys![LockKey::object(1, 1)];
2291 let _guard = manager.txn_lock(keys.clone()).await;
2292 manager.commit_prepare_keys(&keys).await;
2293
2294 let mut read_lock: FuturesUnordered<_> =
2296 std::iter::once(manager.read_lock(keys.clone())).collect();
2297
2298 assert!(futures::poll!(read_lock.next()).is_pending());
2300
2301 manager.downgrade_locks(&keys);
2302
2303 assert!(futures::poll!(read_lock.next()).is_ready());
2305 }
2306
2307 #[fuchsia::test]
2308 async fn test_dropped_write_lock_wakes() {
2309 let manager = LockManager::default();
2310 let keys = lock_keys![LockKey::object(1, 1)];
2311 let _guard = manager.lock(keys.clone(), LockState::ReadLock).await;
2312 let mut read_lock = FuturesUnordered::new();
2313 read_lock.push(manager.lock(keys.clone(), LockState::ReadLock));
2314
2315 {
2316 let write_lock = manager.lock(keys, LockState::WriteLock);
2317 pin_mut!(write_lock);
2318
2319 assert!(futures::poll!(write_lock).is_pending());
2321
2322 assert!(futures::poll!(read_lock.next()).is_pending());
2324 }
2325
2326 assert!(futures::poll!(read_lock.next()).is_ready());
2328 }
2329
2330 #[fuchsia::test]
2331 async fn test_drop_upgrade() {
2332 let manager = LockManager::default();
2333 let keys = lock_keys![LockKey::object(1, 1)];
2334 let _guard = manager.lock(keys.clone(), LockState::Locked).await;
2335
2336 {
2337 let commit_prepare = manager.commit_prepare_keys(&keys);
2338 pin_mut!(commit_prepare);
2339 let _read_guard = manager.lock(keys.clone(), LockState::ReadLock).await;
2340 assert!(futures::poll!(commit_prepare).is_pending());
2341
2342 }
2345
2346 manager.commit_prepare_keys(&keys).await;
2348 }
2349
2350 #[fuchsia::test]
2351 async fn test_woken_upgrade_blocks_reads() {
2352 let manager = LockManager::default();
2353 let keys = lock_keys![LockKey::object(1, 1)];
2354 let guard = manager.lock(keys.clone(), LockState::Locked).await;
2356
2357 let read1 = manager.lock(keys.clone(), LockState::ReadLock).await;
2359
2360 let commit_prepare = manager.commit_prepare_keys(&keys);
2362 pin_mut!(commit_prepare);
2363 assert!(futures::poll!(commit_prepare.as_mut()).is_pending());
2364
2365 let read2 = manager.lock(keys.clone(), LockState::ReadLock);
2367 pin_mut!(read2);
2368 assert!(futures::poll!(read2.as_mut()).is_pending());
2369
2370 std::mem::drop(read1);
2372 assert!(futures::poll!(commit_prepare).is_ready());
2373
2374 assert!(futures::poll!(read2.as_mut()).is_pending());
2376
2377 std::mem::drop(guard);
2379 assert!(futures::poll!(read2).is_ready());
2380 }
2381
2382 static LOCK_KEY_1: LockKey = LockKey::flush(1);
2383 static LOCK_KEY_2: LockKey = LockKey::flush(2);
2384 static LOCK_KEY_3: LockKey = LockKey::flush(3);
2385
2386 fn assert_lock_keys_equal(value: &LockKeys, expected: &LockKeys) {
2388 match (value, expected) {
2389 (LockKeys::None, LockKeys::None) => {}
2390 (LockKeys::Inline(key1), LockKeys::Inline(key2)) => {
2391 if key1 != key2 {
2392 panic!("{key1:?} != {key2:?}");
2393 }
2394 }
2395 (LockKeys::Vec(vec1), LockKeys::Vec(vec2)) => {
2396 if vec1 != vec2 {
2397 panic!("{vec1:?} != {vec2:?}");
2398 }
2399 if vec1.capacity() != vec2.capacity() {
2400 panic!(
2401 "LockKeys have different capacity: {} != {}",
2402 vec1.capacity(),
2403 vec2.capacity()
2404 );
2405 }
2406 }
2407 (_, _) => panic!("{value:?} != {expected:?}"),
2408 }
2409 }
2410
2411 fn assert_lock_keys_equivalent(value: &LockKeys, expected: &LockKeys) {
2413 let value: Vec<_> = value.iter().collect();
2414 let expected: Vec<_> = expected.iter().collect();
2415 assert_eq!(value, expected);
2416 }
2417
2418 #[test]
2419 fn test_lock_keys_macro() {
2420 assert_lock_keys_equal(&lock_keys![], &LockKeys::None);
2421 assert_lock_keys_equal(&lock_keys![LOCK_KEY_1], &LockKeys::Inline(LOCK_KEY_1));
2422 assert_lock_keys_equal(
2423 &lock_keys![LOCK_KEY_1, LOCK_KEY_2],
2424 &LockKeys::Vec(vec![LOCK_KEY_1, LOCK_KEY_2]),
2425 );
2426 }
2427
2428 #[test]
2429 fn test_lock_keys_with_capacity() {
2430 assert_lock_keys_equal(&LockKeys::with_capacity(0), &LockKeys::None);
2431 assert_lock_keys_equal(&LockKeys::with_capacity(1), &LockKeys::None);
2432 assert_lock_keys_equal(&LockKeys::with_capacity(2), &LockKeys::Vec(Vec::with_capacity(2)));
2433 }
2434
2435 #[test]
2436 fn test_lock_keys_len() {
2437 assert_eq!(lock_keys![].len(), 0);
2438 assert_eq!(lock_keys![LOCK_KEY_1].len(), 1);
2439 assert_eq!(lock_keys![LOCK_KEY_1, LOCK_KEY_2].len(), 2);
2440 }
2441
2442 #[test]
2443 fn test_lock_keys_contains() {
2444 assert_eq!(lock_keys![].contains(&LOCK_KEY_1), false);
2445 assert_eq!(lock_keys![LOCK_KEY_1].contains(&LOCK_KEY_1), true);
2446 assert_eq!(lock_keys![LOCK_KEY_1].contains(&LOCK_KEY_2), false);
2447 assert_eq!(lock_keys![LOCK_KEY_1, LOCK_KEY_2].contains(&LOCK_KEY_1), true);
2448 assert_eq!(lock_keys![LOCK_KEY_1, LOCK_KEY_2].contains(&LOCK_KEY_2), true);
2449 assert_eq!(lock_keys![LOCK_KEY_1, LOCK_KEY_2].contains(&LOCK_KEY_3), false);
2450 }
2451
2452 #[test]
2453 fn test_lock_keys_push() {
2454 let mut keys = lock_keys![];
2455 keys.push(LOCK_KEY_1);
2456 assert_lock_keys_equal(&keys, &LockKeys::Inline(LOCK_KEY_1));
2457 keys.push(LOCK_KEY_2);
2458 assert_lock_keys_equal(&keys, &LockKeys::Vec(vec![LOCK_KEY_1, LOCK_KEY_2]));
2459 keys.push(LOCK_KEY_3);
2460 assert_lock_keys_equivalent(
2461 &keys,
2462 &LockKeys::Vec(vec![LOCK_KEY_1, LOCK_KEY_2, LOCK_KEY_3]),
2463 );
2464 }
2465
2466 #[test]
2467 fn test_lock_keys_sort_unstable() {
2468 let mut keys = lock_keys![];
2469 keys.sort_unstable();
2470 assert_lock_keys_equal(&keys, &lock_keys![]);
2471
2472 let mut keys = lock_keys![LOCK_KEY_1];
2473 keys.sort_unstable();
2474 assert_lock_keys_equal(&keys, &lock_keys![LOCK_KEY_1]);
2475
2476 let mut keys = lock_keys![LOCK_KEY_2, LOCK_KEY_1];
2477 keys.sort_unstable();
2478 assert_lock_keys_equal(&keys, &lock_keys![LOCK_KEY_1, LOCK_KEY_2]);
2479 }
2480
2481 #[test]
2482 fn test_lock_keys_dedup() {
2483 let mut keys = lock_keys![];
2484 keys.dedup();
2485 assert_lock_keys_equal(&keys, &lock_keys![]);
2486
2487 let mut keys = lock_keys![LOCK_KEY_1];
2488 keys.dedup();
2489 assert_lock_keys_equal(&keys, &lock_keys![LOCK_KEY_1]);
2490
2491 let mut keys = lock_keys![LOCK_KEY_1, LOCK_KEY_1];
2492 keys.dedup();
2493 assert_lock_keys_equivalent(&keys, &lock_keys![LOCK_KEY_1]);
2494 }
2495
2496 #[test]
2497 fn test_lock_keys_truncate() {
2498 let mut keys = lock_keys![];
2499 keys.truncate(5);
2500 assert_lock_keys_equal(&keys, &lock_keys![]);
2501 keys.truncate(0);
2502 assert_lock_keys_equal(&keys, &lock_keys![]);
2503
2504 let mut keys = lock_keys![LOCK_KEY_1];
2505 keys.truncate(5);
2506 assert_lock_keys_equal(&keys, &lock_keys![LOCK_KEY_1]);
2507 keys.truncate(0);
2508 assert_lock_keys_equal(&keys, &lock_keys![]);
2509
2510 let mut keys = lock_keys![LOCK_KEY_1, LOCK_KEY_2];
2511 keys.truncate(5);
2512 assert_lock_keys_equal(&keys, &lock_keys![LOCK_KEY_1, LOCK_KEY_2]);
2513 keys.truncate(1);
2514 assert_lock_keys_equivalent(&keys, &lock_keys![LOCK_KEY_1]);
2516 }
2517
2518 #[test]
2519 fn test_lock_keys_iter() {
2520 assert_eq!(lock_keys![].iter().collect::<Vec<_>>(), Vec::<&LockKey>::new());
2521
2522 assert_eq!(lock_keys![LOCK_KEY_1].iter().collect::<Vec<_>>(), vec![&LOCK_KEY_1]);
2523
2524 assert_eq!(
2525 lock_keys![LOCK_KEY_1, LOCK_KEY_2].iter().collect::<Vec<_>>(),
2526 vec![&LOCK_KEY_1, &LOCK_KEY_2]
2527 );
2528 }
2529
2530 #[test]
2531 fn test_object_mutation_iterator() {
2532 let mut mutations = BTreeSet::new();
2533 mutations.insert(TxnMutation {
2534 object_id: 1,
2535 mutation: Mutation::BeginFlush,
2536 associated_object: AssocObj::None,
2537 });
2538 mutations.insert(TxnMutation {
2539 object_id: 1,
2540 mutation: Mutation::EndFlush(0),
2541 associated_object: AssocObj::None,
2542 });
2543 mutations.insert(TxnMutation {
2544 object_id: 2,
2545 mutation: Mutation::DeleteVolume,
2546 associated_object: AssocObj::None,
2547 });
2548
2549 let mut iter = mutations.iter().peekable();
2550
2551 {
2552 let mut obj_iter = ObjectMutationIterator::new(&mut iter).expect("expected object 1");
2553 assert_eq!(obj_iter.object_id(), 1);
2554 assert_eq!(obj_iter.next(), Some(&Mutation::BeginFlush));
2555 assert_eq!(obj_iter.next(), Some(&Mutation::EndFlush(0)));
2556 assert_eq!(obj_iter.next(), None);
2557 }
2558
2559 {
2560 let mut obj_iter = ObjectMutationIterator::new(&mut iter).expect("expected object 2");
2561 assert_eq!(obj_iter.object_id(), 2);
2562 assert_eq!(obj_iter.next(), Some(&Mutation::DeleteVolume));
2563 assert_eq!(obj_iter.next(), None);
2564 }
2565
2566 assert!(ObjectMutationIterator::new(&mut iter).is_none());
2568 }
2569
2570 #[test]
2571 fn test_object_mutation_iterator_drop_drains_remaining() {
2572 let mut mutations = BTreeSet::new();
2573 mutations.insert(TxnMutation {
2575 object_id: 1,
2576 mutation: Mutation::BeginFlush,
2577 associated_object: AssocObj::None,
2578 });
2579 mutations.insert(TxnMutation {
2580 object_id: 1,
2581 mutation: Mutation::EndFlush(0),
2582 associated_object: AssocObj::None,
2583 });
2584 mutations.insert(TxnMutation {
2585 object_id: 1,
2586 mutation: Mutation::DeleteVolume,
2587 associated_object: AssocObj::None,
2588 });
2589 mutations.insert(TxnMutation {
2591 object_id: 2,
2592 mutation: Mutation::BeginFlush,
2593 associated_object: AssocObj::None,
2594 });
2595 mutations.insert(TxnMutation {
2596 object_id: 2,
2597 mutation: Mutation::EndFlush(0),
2598 associated_object: AssocObj::None,
2599 });
2600
2601 let mut iter = mutations.iter().peekable();
2602
2603 {
2604 let mut obj_iter = ObjectMutationIterator::new(&mut iter).expect("expected object 1");
2605 assert_eq!(obj_iter.object_id(), 1);
2606 assert_eq!(obj_iter.next(), Some(&Mutation::BeginFlush));
2607 }
2609
2610 {
2611 let obj_iter = ObjectMutationIterator::new(&mut iter).expect("expected object 2");
2612 assert_eq!(obj_iter.object_id(), 2);
2613 }
2615
2616 assert!(ObjectMutationIterator::new(&mut iter).is_none());
2618 }
2619
2620 #[fuchsia::test]
2621 async fn test_merge_bytes_and_nodes() {
2622 let device = DeviceHolder::new(FakeDevice::new(4096, 1024));
2623 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
2624 let root_store = fs.root_store();
2625 let store_id = root_store.store_object_id();
2626 let mut t = root_store
2627 .new_transaction(lock_keys![], Options::default())
2628 .await
2629 .expect("new_transaction failed");
2630
2631 let key = ObjectKey::project_usage(
2632 root_store.root_directory_object_id(),
2633 crate::object_store::ProjectId::new(1).unwrap(),
2634 );
2635
2636 t.merge_bytes_and_nodes(store_id, key.clone(), BytesAndNodes { bytes: 100, nodes: 2 });
2638 let mutation = t.get_object_mutation(store_id, key.clone()).expect("mutation expected");
2639 assert_eq!(mutation.op, super::Operation::Merge);
2640 assert_eq!(
2641 mutation.item.value,
2642 crate::object_store::object_record::ObjectValue::BytesAndNodes { bytes: 100, nodes: 2 }
2643 );
2644
2645 t.merge_bytes_and_nodes(store_id, key.clone(), BytesAndNodes { bytes: 50, nodes: 1 });
2647 let mutation = t.get_object_mutation(store_id, key.clone()).expect("mutation expected");
2648 assert_eq!(mutation.op, super::Operation::Merge);
2649 assert_eq!(
2650 mutation.item.value,
2651 crate::object_store::object_record::ObjectValue::BytesAndNodes { bytes: 150, nodes: 3 }
2652 );
2653
2654 t.merge_bytes_and_nodes(store_id, key.clone(), BytesAndNodes { bytes: -50, nodes: -1 });
2656 let mutation = t.get_object_mutation(store_id, key.clone()).expect("mutation expected");
2657 assert_eq!(mutation.op, super::Operation::Merge);
2658 assert_eq!(
2659 mutation.item.value,
2660 crate::object_store::object_record::ObjectValue::BytesAndNodes { bytes: 100, nodes: 2 }
2661 );
2662
2663 t.merge_bytes_and_nodes(store_id, key.clone(), BytesAndNodes { bytes: -100, nodes: -2 });
2665 assert!(t.get_object_mutation(store_id, key.clone()).is_none());
2666
2667 t.merge_bytes_and_nodes(store_id, key.clone(), BytesAndNodes { bytes: 0, nodes: 0 });
2669 assert!(t.get_object_mutation(store_id, key.clone()).is_none());
2670 }
2671
2672 #[fuchsia::test]
2673 async fn test_commit_and_continue_checks_journal_space() {
2674 use crate::filesystem::FxFilesystemBuilder;
2675 use crate::hooks::Hooks;
2676 use crate::object_store::journal::JournalOptions;
2677 use crate::object_store::volume::root_volume;
2678 use crate::object_store::{NewChildStoreOptions, ObjectKey, ObjectValue};
2679 use storage_device::DeviceHolder;
2680 use storage_device::fake_device::FakeDevice;
2681
2682 let reclaim_size = 65536;
2683 let device = DeviceHolder::new(FakeDevice::new(8192, 4096));
2684 let (mut hooks, fs_hooks) = Hooks::new();
2685 let fs = FxFilesystemBuilder::new()
2686 .hooks(fs_hooks)
2687 .journal_options(JournalOptions { reclaim_size, ..Default::default() })
2688 .format(true)
2689 .open(device)
2690 .await
2691 .expect("open failed");
2692
2693 let root_volume = root_volume(fs.clone()).await.expect("root_volume failed");
2694 let store = root_volume
2695 .new_volume("test", NewChildStoreOptions::default())
2696 .await
2697 .expect("new_volume failed");
2698
2699 fs.journal().force_compact().await.expect("force_compact failed");
2700 fs.journal().pause_compactions().await;
2701
2702 let journal_clone = fs.journal().clone();
2703 hooks.set_waiting_for_journal_space(move || {
2704 journal_clone.resume_compactions();
2705 });
2706
2707 let _reservation = fs.allocator().reserve_with(None, |limit| limit);
2710
2711 let mut transaction = store
2712 .new_transaction(
2713 lock_keys![LockKey::object(store.store_object_id(), 1000)],
2714 Options { reservation: ReservationOptions::Borrowed, ..Default::default() },
2715 )
2716 .await
2717 .expect("new_transaction failed");
2718
2719 for _ in 0..64 {
2723 for i in 0..16 {
2724 transaction.add(
2725 store.store_object_id(),
2726 Mutation::replace_or_insert_object(
2727 ObjectKey::extended_attribute(1000, format!("attr_{i}").into_bytes()),
2728 ObjectValue::inline_extended_attribute(vec![0u8; 1024]),
2729 ),
2730 );
2731 }
2732 transaction.commit_and_continue().await.expect("commit_and_continue failed");
2733 }
2734 transaction.commit().await.expect("commit failed");
2735
2736 fs.close().await.expect("close failed");
2737 }
2738
2739 #[fuchsia::test]
2740 async fn test_commit_and_continue_resets_state() {
2741 use crate::object_store::volume::root_volume;
2742 use crate::object_store::{ExtentValue, NewChildStoreOptions, ObjectKey, ObjectValue};
2743 use storage_device::DeviceHolder;
2744 use storage_device::fake_device::FakeDevice;
2745
2746 let device = DeviceHolder::new(FakeDevice::new(8192, 4096));
2747 let fs = FxFilesystem::new_empty(device).await.expect("new_empty failed");
2748 let root_volume = root_volume(fs.clone()).await.expect("root_volume failed");
2749 let store = root_volume
2750 .new_volume("test", NewChildStoreOptions::default())
2751 .await
2752 .expect("new_volume failed");
2753
2754 let mut transaction = store
2755 .new_transaction(
2756 lock_keys![LockKey::object(store.store_object_id(), 1000)],
2757 Options::default(),
2758 )
2759 .await
2760 .expect("new_transaction failed");
2761
2762 assert!(!transaction.includes_write());
2763 transaction.add(
2764 store.store_object_id(),
2765 Mutation::merge_object(
2766 ObjectKey::extent(1000, AttributeId::DATA, 0..4096),
2767 ObjectValue::Extent(ExtentValue::deleted_extent()),
2768 ),
2769 );
2770 transaction.add_checksum(store.store_object_id(), 0..4096, vec![0], true);
2771 assert!(transaction.includes_write());
2772 assert!(!transaction.checksums().is_empty());
2773
2774 transaction.commit_and_continue().await.expect("commit_and_continue failed");
2775
2776 assert!(!transaction.includes_write());
2777 assert!(transaction.checksums().is_empty());
2778
2779 transaction.commit().await.expect("commit failed");
2780 fs.close().await.expect("close failed");
2781 }
2782
2783 struct MockSink {
2784 commits: AtomicU64,
2785 callbacks: AtomicU64,
2786 drops: AtomicU64,
2787 downgrades: AtomicU64,
2788 should_fail: AtomicBool,
2789 lock_manager: LockManager,
2790 transaction_limiter: TransactionConcurrencyLimiter,
2791 }
2792
2793 impl Default for MockSink {
2794 fn default() -> Self {
2795 Self {
2796 commits: Default::default(),
2797 callbacks: Default::default(),
2798 drops: Default::default(),
2799 downgrades: Default::default(),
2800 should_fail: Default::default(),
2801 lock_manager: LockManager::default(),
2802 transaction_limiter: TransactionConcurrencyLimiter::new(u64::MAX),
2803 }
2804 }
2805 }
2806
2807 struct MockReservationOwner;
2808
2809 impl ReservationOwner for MockReservationOwner {
2810 fn release_reservation(&self, _owner_object_id: Option<u64>, _amount: u64) {}
2811 }
2812
2813 #[async_trait]
2814 impl TransactionSink for MockSink {
2815 async fn new_transaction<'a>(
2816 self: Arc<Self>,
2817 txn_locks: LockKeys,
2818 options: Options<'a>,
2819 ) -> Result<Transaction<'a>, Error> {
2820 Transaction::new(self, options, txn_locks).await
2821 }
2822
2823 async fn check_space(&self) -> Result<(), Error> {
2824 Ok(())
2825 }
2826
2827 fn reserve(&self, owner_object_id: Option<u64>, amount: u64) -> Option<Reservation> {
2828 Some(Reservation::new(Arc::new(MockReservationOwner), owner_object_id, amount))
2829 }
2830
2831 async fn commit(&self, _transaction: &mut Transaction<'_>) -> Result<u64, Error> {
2832 if self.should_fail.load(Ordering::Relaxed) {
2833 anyhow::bail!("mock commit failed");
2834 }
2835 let count = self.commits.fetch_add(1, Ordering::Relaxed);
2836 Ok(count + 1)
2837 }
2838
2839 async fn commit_with_callback<'a>(
2840 &self,
2841 _transaction: &mut Transaction<'_>,
2842 callback: Box<dyn FnOnce(u64) + Send + 'a>,
2843 ) -> Result<u64, Error> {
2844 if self.should_fail.load(Ordering::Relaxed) {
2845 anyhow::bail!("mock commit_with_callback failed");
2846 }
2847 let count = self.commits.fetch_add(1, Ordering::Relaxed);
2848 let offset = count + 1;
2849 callback(offset);
2850 self.callbacks.fetch_add(1, Ordering::Relaxed);
2851 Ok(offset)
2852 }
2853
2854 fn downgrade_locks(&self, _lock_keys: &LockKeys) {
2855 self.downgrades.fetch_add(1, Ordering::Relaxed);
2856 }
2857
2858 fn drop_transaction(&self, transaction: &mut Transaction<'_>) {
2859 self.lock_manager.drop_transaction(transaction);
2860 self.drops.fetch_add(1, Ordering::Relaxed);
2861 }
2862
2863 fn lock_manager(&self) -> &LockManager {
2864 &self.lock_manager
2865 }
2866
2867 fn transaction_limiter(&self) -> &TransactionConcurrencyLimiter {
2868 &self.transaction_limiter
2869 }
2870 }
2871
2872 #[fuchsia::test]
2873 async fn test_mock_transaction_sink_lifecycle_and_stress() {
2874 let sink = Arc::new(MockSink::default());
2875
2876 {
2878 let txn = sink
2879 .clone()
2880 .new_transaction(lock_keys![LOCK_KEY_1], Options::default())
2881 .await
2882 .unwrap();
2883 let offset = txn.commit().await.expect("commit should succeed");
2884 assert_eq!(offset, 1);
2885 assert_eq!(sink.commits.load(Ordering::Relaxed), 1);
2886 assert_eq!(sink.drops.load(Ordering::Relaxed), 1);
2887 }
2888
2889 {
2891 let txn = sink
2892 .clone()
2893 .new_transaction(lock_keys![LOCK_KEY_1], Options::default())
2894 .await
2895 .unwrap();
2896 let res = txn
2897 .commit_with_callback(|offset| {
2898 assert_eq!(offset, 2);
2899 "callback_executed"
2900 })
2901 .await
2902 .expect("commit_with_callback should succeed");
2903 assert_eq!(res, "callback_executed");
2904 assert_eq!(sink.commits.load(Ordering::Relaxed), 2);
2905 assert_eq!(sink.callbacks.load(Ordering::Relaxed), 1);
2906 assert_eq!(sink.drops.load(Ordering::Relaxed), 2);
2907 }
2908
2909 {
2911 let mut txn = sink
2912 .clone()
2913 .new_transaction(lock_keys![LOCK_KEY_1], Options::default())
2914 .await
2915 .unwrap();
2916 for i in 0..100 {
2917 txn.commit_and_continue().await.expect("commit_and_continue should succeed");
2918 assert_eq!(sink.commits.load(Ordering::Relaxed), 3 + i);
2919 assert_eq!(sink.downgrades.load(Ordering::Relaxed), 1 + i);
2920 }
2921 std::mem::drop(txn);
2922 assert_eq!(sink.drops.load(Ordering::Relaxed), 3);
2923 }
2924
2925 {
2927 let txn = sink
2928 .clone()
2929 .new_transaction(lock_keys![LOCK_KEY_1], Options::default())
2930 .await
2931 .unwrap();
2932 std::mem::drop(txn);
2933 assert_eq!(sink.drops.load(Ordering::Relaxed), 4);
2934 }
2935
2936 {
2938 sink.should_fail.store(true, Ordering::Relaxed);
2939 let txn = sink
2940 .clone()
2941 .new_transaction(lock_keys![LOCK_KEY_1], Options::default())
2942 .await
2943 .unwrap();
2944 assert!(txn.commit().await.is_err());
2945 assert_eq!(sink.drops.load(Ordering::Relaxed), 5);
2946 }
2947 }
2948}