Skip to main content

fxfs/serialized_types/
types.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::blob_metadata::{BlobMetadata, BlobMetadataV53};
6use crate::lsm_tree::{
7    PersistentLayerHeader, PersistentLayerHeaderV39, PersistentLayerInfo, PersistentLayerInfoV39,
8};
9use crate::object_store::allocator::{
10    AllocatorInfo, AllocatorInfoV32, AllocatorKey, AllocatorKeyV32, AllocatorValue,
11    AllocatorValueV32,
12};
13use crate::object_store::journal::super_block::{
14    SuperBlockHeader, SuperBlockHeaderV32, SuperBlockRecord, SuperBlockRecordV56,
15};
16use crate::object_store::journal::{JournalRecord, JournalRecordV56, JournalRecordV57};
17use crate::object_store::object_record::{
18    FsverityMetadata, FsverityMetadataV50, ObjectKey, ObjectKeyV54, ObjectValue, ObjectValueV56,
19};
20use crate::object_store::transaction::{Mutation, MutationV56, MutationV57};
21use crate::object_store::{
22    EncryptedMutations, EncryptedMutationsV49, EncryptedTransaction, EncryptedTransactionV57,
23    StoreInfo, StoreInfoV52,
24};
25use crate::serialized_types::{Version, Versioned, VersionedLatest, versioned_type};
26use std::collections::BTreeMap;
27
28/// The latest version of on-disk filesystem format.
29///
30/// If all layer files are compacted the the journal flushed, and super-block
31/// both rewritten, all versions should match this value.
32///
33/// If making a breaking change, please see EARLIEST_SUPPORTED_VERSION (below).
34///
35/// IMPORTANT: When changing this (major or minor), update the list of possible versions at
36/// https://cs.opensource.google/fuchsia/fuchsia/+/main:third_party/cobalt_config/fuchsia/local_storage/versions.txt.
37pub const LATEST_VERSION: Version = Version { major: 58, minor: 0 };
38
39/// The last version of the filesystem where keys in layer files used the old serialization format
40/// (prior to SerializeKey and delta encoding).
41pub const OLD_KEY_SERIALIZATION_VERSION: Version = Version { major: 57, minor: 0 };
42
43/// The earliest supported version of the on-disk filesystem format.
44///
45/// When a breaking change is made:
46/// 1) LATEST_VERSION should have it's major component increased (see above).
47/// 2) EARLIEST_SUPPORTED_VERSION should be set to the new LATEST_VERSION.
48/// 3) The SuperBlockHeader version (below) should also be set to the new LATEST_VERSION.
49///
50/// Also check the constant version numbers above for any code cleanup that can happen.
51pub const EARLIEST_SUPPORTED_VERSION: Version = Version { major: 56, minor: 0 };
52
53// From this version forward, the journal encryption uses AES-256-XTS instead of Chacha20, as well
54// as chunking the mutations together for a transaction.
55pub const AES_JOURNAL_ENCRYPTION_VERSION: Version = Version { major: 57, minor: 0 };
56
57/// This trait prevents types from showing up in `versioned_types` multiple times. `versioned_types`
58/// implements this trait for every type passed to it. If a type is listed multiple times then this
59/// trait will be implemented for the type multiple times which will fail to compile.
60#[allow(dead_code)]
61trait UniqueVersionForType {}
62
63trait HasVersion {
64    const VERSION: u32;
65}
66
67macro_rules! versioned_types {
68    ( $( $name:ident { $latest:literal.. => $latest_type:ty $(, $major:literal.. => $type:ty )* $(,)? } )+ ) => {
69        $(
70            static_assertions::assert_type_eq_all!($name, $latest_type);
71
72            versioned_type! {
73                $latest.. => $latest_type,
74                $( $major.. => $type ),*
75            }
76
77            impl UniqueVersionForType for $latest_type {}
78            $( impl UniqueVersionForType for $type {} )*
79
80            impl HasVersion for $latest_type {
81                const VERSION: u32 = $latest;
82            }
83
84        )+
85
86        pub fn get_type_fingerprints(version: Version) -> BTreeMap<String, String> {
87            let mut map = BTreeMap::new();
88            $(
89                let fingerprint = {
90                    let mut fp = None;
91                    const FINGERPRINTS: &[(u32, fn() -> String)] = &[
92                        ($latest, <$latest_type as fprint::TypeFingerprint>::fingerprint),
93                        $( ($major, <$type as fprint::TypeFingerprint>::fingerprint) ),*
94                    ];
95                    for (major, type_fp) in FINGERPRINTS {
96                        if version.major >= *major {
97                            fp = Some(type_fp());
98                            break;
99                        }
100                    }
101                    fp
102                };
103                if let Some(fp) = fingerprint {
104                    map.insert(stringify!($name).to_string(), fp.to_string());
105                }
106            )+
107            map
108        }
109    };
110}
111
112versioned_types! {
113    AllocatorInfo {
114        32.. => AllocatorInfoV32,
115    }
116    AllocatorKey {
117        32.. => AllocatorKeyV32,
118    }
119    AllocatorValue {
120        32.. => AllocatorValueV32,
121    }
122    EncryptedMutations {
123        49.. => EncryptedMutationsV49,
124    }
125    EncryptedTransaction {
126        57.. => EncryptedTransactionV57,
127    }
128    FsverityMetadata {
129        50.. => FsverityMetadataV50,
130    }
131    JournalRecord {
132        57.. => JournalRecordV57,
133        56.. => JournalRecordV56,
134    }
135    Mutation {
136        57.. => MutationV57,
137        56.. => MutationV56,
138    }
139    ObjectKey {
140        54.. => ObjectKeyV54,
141    }
142    ObjectValue {
143        56.. => ObjectValueV56,
144    }
145    PersistentLayerHeader {
146        39.. => PersistentLayerHeaderV39,
147    }
148    PersistentLayerInfo {
149        39.. => PersistentLayerInfoV39,
150    }
151    StoreInfo {
152        52.. => StoreInfoV52,
153    }
154    SuperBlockHeader {
155        32.. => SuperBlockHeaderV32,
156    }
157    SuperBlockRecord {
158        56.. => SuperBlockRecordV56,
159    }
160    BlobMetadata {
161        53.. => BlobMetadataV53,
162    }
163}
164
165// EncryptedTransaction is actually inside the Mutation type, but obscured by a layer of
166// encryption. This ensures that when the EncryptedTransaction type is incremented, so is the
167// Mutation and thus any types above that.
168static_assertions::const_assert!(
169    <EncryptedTransaction as HasVersion>::VERSION <= <Mutation as HasVersion>::VERSION
170);