Skip to main content

fxfs/object_store/
object_record.rs

1// Copyright 2021 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
5mod legacy;
6
7pub use legacy::*;
8
9// TODO(https://fxbug.dev/42178223): need validation after deserialization.
10use crate::checksum::Checksums;
11use crate::log::error;
12use crate::lsm_tree::types::{
13    FuzzyHash, Item, ItemRef, LayerKey, MergeType, OrdLowerBound, OrdUpperBound, RangeKey,
14    SortByU64, Value,
15};
16use crate::object_store::extent_record::{
17    ExtentKey, ExtentKeyPartitionIterator, ExtentKeyV32, ExtentValue, ExtentValueV38,
18};
19use crate::serialized_types::{Migrate, Versioned, migrate_nodefault, migrate_to_version};
20use fprint::TypeFingerprint;
21use fxfs_crypto::{WrappedKey, WrappingKeyId};
22use fxfs_unicode::CasefoldString;
23use serde::{Deserialize, Serialize};
24use std::collections::BTreeMap;
25use std::default::Default;
26use std::hash::Hash;
27use std::time::{Duration, SystemTime, UNIX_EPOCH};
28
29/// ObjectDescriptor is the set of possible records in the object store.
30pub type ObjectDescriptor = ObjectDescriptorV32;
31
32#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
33#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
34pub enum ObjectDescriptorV32 {
35    /// A file (in the generic sense; i.e. an object with some attributes).
36    File,
37    /// A directory (in the generic sense; i.e. an object with children).
38    Directory,
39    /// A volume, which is the root of a distinct object store containing Files and Directories.
40    Volume,
41    /// A symbolic link.
42    Symlink,
43}
44
45/// For specifying what property of the project is being addressed.
46pub type ProjectProperty = ProjectPropertyV32;
47
48#[derive(
49    Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize, TypeFingerprint,
50)]
51#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
52pub enum ProjectPropertyV32 {
53    /// The configured limit for the project.
54    Limit,
55    /// The currently tracked usage for the project.
56    Usage,
57}
58
59pub type ObjectKeyData = ObjectKeyDataV43;
60
61#[derive(
62    Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize, TypeFingerprint,
63)]
64#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
65pub enum ObjectKeyDataV43 {
66    /// A generic, untyped object.  This must come first and sort before all other keys for a given
67    /// object because it's also used as a tombstone and it needs to merge with all following keys.
68    Object,
69    /// Encryption keys for an object.
70    Keys,
71    /// An attribute associated with an object.  It has a 64-bit ID.
72    Attribute(u64, AttributeKeyV32),
73    /// A child of a directory.
74    Child { name: String },
75    /// A graveyard entry for an entire object.
76    GraveyardEntry { object_id: u64 },
77    /// Project ID info. This should only be attached to the volume's root node. Used to address the
78    /// configured limit and the usage tracking which are ordered after the `project_id` to provide
79    /// locality of the two related values.
80    Project { project_id: u64, property: ProjectPropertyV32 },
81    /// An extended attribute associated with an object. It stores the name used for the extended
82    /// attribute, which has a maximum size of 255 bytes enforced by fuchsia.io.
83    ExtendedAttribute {
84        #[serde(with = "crate::zerocopy_serialization")]
85        name: Vec<u8>,
86    },
87    /// A graveyard entry for an attribute.
88    GraveyardAttributeEntry { object_id: u64, attribute_id: u64 },
89    /// A child of an encrypted directory.  We store the filename in its encrypted form.  hash_code
90    /// is the hash of the casefolded human-readable name if a directory is also casefolded.  In
91    /// some legacy cases, this is also used in non-casefolded cases, and in some of those cases the
92    /// hash code can be 0.  Going forward, these cases are covered by `EncryptedChild` below.
93    EncryptedCasefoldChild(EncryptedCasefoldChild),
94    /// A child of a directory that uses the casefold feature.
95    /// (i.e. case insensitive, case preserving names)
96    CasefoldChild { name: CasefoldString },
97    /// An encrypted child that does not use case folding.
98    EncryptedChild(EncryptedChild),
99}
100
101#[derive(
102    Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize, TypeFingerprint,
103)]
104#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
105pub struct EncryptedCasefoldChild {
106    pub hash_code: u32,
107    #[serde(with = "crate::zerocopy_serialization")]
108    pub name: Vec<u8>,
109}
110
111#[derive(
112    Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize, TypeFingerprint,
113)]
114#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
115pub struct EncryptedChild(#[serde(with = "crate::zerocopy_serialization")] pub Vec<u8>);
116
117pub type AttributeKey = AttributeKeyV32;
118
119#[derive(
120    Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize, TypeFingerprint,
121)]
122#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
123pub enum AttributeKeyV32 {
124    // Order here is important: code expects Attribute to precede Extent.
125    Attribute,
126    Extent(ExtentKeyV32),
127}
128
129/// ObjectKey is a key in the object store.
130pub type ObjectKey = ObjectKeyV43;
131
132#[derive(
133    Clone,
134    Debug,
135    Eq,
136    Ord,
137    Hash,
138    PartialEq,
139    PartialOrd,
140    Serialize,
141    Deserialize,
142    TypeFingerprint,
143    Versioned,
144)]
145#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
146pub struct ObjectKeyV43 {
147    /// The ID of the object referred to.
148    pub object_id: u64,
149    /// The type and data of the key.
150    pub data: ObjectKeyDataV43,
151}
152
153impl SortByU64 for ObjectKey {
154    fn get_leading_u64(&self) -> u64 {
155        self.object_id
156    }
157}
158
159impl ObjectKey {
160    /// Creates a generic ObjectKey.
161    pub fn object(object_id: u64) -> Self {
162        Self { object_id: object_id, data: ObjectKeyData::Object }
163    }
164
165    /// Creates an ObjectKey for encryption keys.
166    pub fn keys(object_id: u64) -> Self {
167        Self { object_id, data: ObjectKeyData::Keys }
168    }
169
170    /// Creates an ObjectKey for an attribute.
171    pub fn attribute(object_id: u64, attribute_id: u64, key: AttributeKey) -> Self {
172        Self { object_id, data: ObjectKeyData::Attribute(attribute_id, key) }
173    }
174
175    /// Creates an ObjectKey for an extent.
176    pub fn extent(object_id: u64, attribute_id: u64, range: std::ops::Range<u64>) -> Self {
177        Self {
178            object_id,
179            data: ObjectKeyData::Attribute(
180                attribute_id,
181                AttributeKey::Extent(ExtentKey::new(range)),
182            ),
183        }
184    }
185
186    /// Creates an ObjectKey from an extent.
187    pub fn from_extent(object_id: u64, attribute_id: u64, extent: ExtentKey) -> Self {
188        Self {
189            object_id,
190            data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
191        }
192    }
193
194    /// Creates an ObjectKey for a child.
195    pub fn child(object_id: u64, name: &str, casefold: bool) -> Self {
196        if casefold {
197            Self { object_id, data: ObjectKeyData::CasefoldChild { name: name.into() } }
198        } else {
199            Self { object_id, data: ObjectKeyData::Child { name: name.into() } }
200        }
201    }
202
203    /// Creates an ObjectKey for an encrypted child.
204    ///
205    /// The hash_code is important here -- especially for fscrypt as it affects the
206    /// name of locked files.
207    ///
208    /// For case-insensitive lookups in large encrypted directories, we lose the ability to binary
209    /// search for an entry of interest because encryption breaks our sort order. In these cases
210    /// we prefix records with a 32-bit hash based on the stable *casefolded* name. Hash collisions
211    /// aside, this lets us jump straight to the entry of interest, if it exists.
212    pub fn encrypted_child(object_id: u64, name: Vec<u8>, hash_code: Option<u32>) -> Self {
213        if let Some(hash_code) = hash_code {
214            Self {
215                object_id,
216                data: ObjectKeyData::EncryptedCasefoldChild(EncryptedCasefoldChild {
217                    hash_code,
218                    name,
219                }),
220            }
221        } else {
222            Self { object_id, data: ObjectKeyData::EncryptedChild(EncryptedChild(name)) }
223        }
224    }
225
226    /// Creates a graveyard entry for an object.
227    pub fn graveyard_entry(graveyard_object_id: u64, object_id: u64) -> Self {
228        Self { object_id: graveyard_object_id, data: ObjectKeyData::GraveyardEntry { object_id } }
229    }
230
231    /// Creates a graveyard entry for an attribute.
232    pub fn graveyard_attribute_entry(
233        graveyard_object_id: u64,
234        object_id: u64,
235        attribute_id: u64,
236    ) -> Self {
237        Self {
238            object_id: graveyard_object_id,
239            data: ObjectKeyData::GraveyardAttributeEntry { object_id, attribute_id },
240        }
241    }
242
243    /// Creates an ObjectKey for a ProjectLimit entry.
244    pub fn project_limit(object_id: u64, project_id: u64) -> Self {
245        Self {
246            object_id,
247            data: ObjectKeyData::Project { project_id, property: ProjectProperty::Limit },
248        }
249    }
250
251    /// Creates an ObjectKey for a ProjectUsage entry.
252    pub fn project_usage(object_id: u64, project_id: u64) -> Self {
253        Self {
254            object_id,
255            data: ObjectKeyData::Project { project_id, property: ProjectProperty::Usage },
256        }
257    }
258
259    pub fn extended_attribute(object_id: u64, name: Vec<u8>) -> Self {
260        Self { object_id, data: ObjectKeyData::ExtendedAttribute { name } }
261    }
262
263    /// Returns the merge key for this key; that is, a key which is <= this key and any
264    /// other possibly overlapping key, under Ord. This would be used for the hint in |merge_into|.
265    pub fn key_for_merge_into(&self) -> Self {
266        if let Self {
267            object_id,
268            data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(e)),
269        } = self
270        {
271            Self::attribute(*object_id, *attribute_id, AttributeKey::Extent(e.key_for_merge_into()))
272        } else {
273            self.clone()
274        }
275    }
276}
277
278impl OrdUpperBound for ObjectKey {
279    fn cmp_upper_bound(&self, other: &ObjectKey) -> std::cmp::Ordering {
280        self.object_id.cmp(&other.object_id).then_with(|| match (&self.data, &other.data) {
281            (
282                ObjectKeyData::Attribute(left_attr_id, AttributeKey::Extent(left_extent)),
283                ObjectKeyData::Attribute(right_attr_id, AttributeKey::Extent(right_extent)),
284            ) => left_attr_id.cmp(right_attr_id).then(left_extent.cmp_upper_bound(right_extent)),
285            _ => self.data.cmp(&other.data),
286        })
287    }
288}
289
290impl OrdLowerBound for ObjectKey {
291    fn cmp_lower_bound(&self, other: &ObjectKey) -> std::cmp::Ordering {
292        self.object_id.cmp(&other.object_id).then_with(|| match (&self.data, &other.data) {
293            (
294                ObjectKeyData::Attribute(left_attr_id, AttributeKey::Extent(left_extent)),
295                ObjectKeyData::Attribute(right_attr_id, AttributeKey::Extent(right_extent)),
296            ) => left_attr_id.cmp(right_attr_id).then(left_extent.cmp_lower_bound(right_extent)),
297            _ => self.data.cmp(&other.data),
298        })
299    }
300}
301
302impl LayerKey for ObjectKey {
303    fn merge_type(&self) -> MergeType {
304        // This listing is intentionally exhaustive to force folks to think about how certain
305        // subsets of the keyspace are merged.
306        match self.data {
307            ObjectKeyData::Object
308            | ObjectKeyData::Keys
309            | ObjectKeyData::Attribute(..)
310            | ObjectKeyData::Child { .. }
311            | ObjectKeyData::EncryptedChild(_)
312            | ObjectKeyData::EncryptedCasefoldChild(_)
313            | ObjectKeyData::CasefoldChild { .. }
314            | ObjectKeyData::GraveyardEntry { .. }
315            | ObjectKeyData::GraveyardAttributeEntry { .. }
316            | ObjectKeyData::Project { property: ProjectProperty::Limit, .. }
317            | ObjectKeyData::ExtendedAttribute { .. } => MergeType::OptimizedMerge,
318            ObjectKeyData::Project { property: ProjectProperty::Usage, .. } => MergeType::FullMerge,
319        }
320    }
321
322    fn next_key(&self) -> Option<Self> {
323        match self.data {
324            ObjectKeyData::Attribute(_, AttributeKey::Extent(_)) => {
325                let mut key = self.clone();
326                if let ObjectKey {
327                    data: ObjectKeyData::Attribute(_, AttributeKey::Extent(ExtentKey { range })),
328                    ..
329                } = &mut key
330                {
331                    // We want a key such that cmp_lower_bound returns Greater for any key which
332                    // starts after end, and a key such that if you search for it, you'll get an
333                    // extent whose end > range.end.
334                    *range = range.end..range.end + 1;
335                }
336                Some(key)
337            }
338            _ => None,
339        }
340    }
341
342    fn search_key(&self) -> Self {
343        if let Self {
344            object_id,
345            data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(e)),
346        } = self
347        {
348            Self::attribute(*object_id, *attribute_id, AttributeKey::Extent(e.search_key()))
349        } else {
350            self.clone()
351        }
352    }
353}
354
355impl RangeKey for ObjectKey {
356    fn overlaps(&self, other: &Self) -> bool {
357        if self.object_id != other.object_id {
358            return false;
359        }
360        match (&self.data, &other.data) {
361            (
362                ObjectKeyData::Attribute(left_attr_id, AttributeKey::Extent(left_key)),
363                ObjectKeyData::Attribute(right_attr_id, AttributeKey::Extent(right_key)),
364            ) if *left_attr_id == *right_attr_id => {
365                left_key.range.end > right_key.range.start
366                    && left_key.range.start < right_key.range.end
367            }
368            (a, b) => a == b,
369        }
370    }
371}
372
373pub enum ObjectKeyFuzzyHashIterator {
374    ExtentKey(/* object_id */ u64, /* attribute_id */ u64, ExtentKeyPartitionIterator),
375    NotExtentKey(/* hash */ Option<u64>),
376}
377
378impl Iterator for ObjectKeyFuzzyHashIterator {
379    type Item = u64;
380
381    fn next(&mut self) -> Option<Self::Item> {
382        match self {
383            Self::ExtentKey(oid, attr_id, extent_keys) => extent_keys.next().map(|range| {
384                let key = ObjectKey::extent(*oid, *attr_id, range);
385                crate::stable_hash::stable_hash(key)
386            }),
387            Self::NotExtentKey(hash) => hash.take(),
388        }
389    }
390}
391
392impl FuzzyHash for ObjectKey {
393    fn fuzzy_hash(&self) -> impl Iterator<Item = u64> {
394        match &self.data {
395            ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent)) => {
396                ObjectKeyFuzzyHashIterator::ExtentKey(
397                    self.object_id,
398                    *attr_id,
399                    extent.fuzzy_hash_partition(),
400                )
401            }
402            _ => {
403                let hash = crate::stable_hash::stable_hash(self);
404                ObjectKeyFuzzyHashIterator::NotExtentKey(Some(hash))
405            }
406        }
407    }
408
409    fn is_range_key(&self) -> bool {
410        match &self.data {
411            ObjectKeyData::Attribute(_, AttributeKey::Extent(_)) => true,
412            _ => false,
413        }
414    }
415}
416
417/// UNIX epoch based timestamp in the UTC timezone.
418pub type Timestamp = TimestampV49;
419
420#[derive(
421    Copy,
422    Clone,
423    Debug,
424    Default,
425    Eq,
426    PartialEq,
427    Ord,
428    PartialOrd,
429    Serialize,
430    Deserialize,
431    TypeFingerprint,
432)]
433#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
434pub struct TimestampV49 {
435    nanos: u64,
436}
437
438impl Timestamp {
439    const NSEC_PER_SEC: u64 = 1_000_000_000;
440
441    pub fn now() -> Self {
442        SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or(Duration::ZERO).into()
443    }
444
445    pub const fn zero() -> Self {
446        Self { nanos: 0 }
447    }
448
449    pub const fn from_nanos(nanos: u64) -> Self {
450        Self { nanos }
451    }
452
453    pub fn from_secs_and_nanos(secs: u64, nanos: u32) -> Self {
454        let Some(secs_in_nanos) = secs.checked_mul(Self::NSEC_PER_SEC) else {
455            error!("Fxfs doesn't support dates past 2554-07-21");
456            return Self { nanos: u64::MAX };
457        };
458        let Some(nanos) = secs_in_nanos.checked_add(nanos as u64) else {
459            error!("Fxfs doesn't support dates past 2554-07-21");
460            return Self { nanos: u64::MAX };
461        };
462        Self { nanos }
463    }
464
465    /// Returns the total number of nanoseconds represented by this `Timestamp` since the Unix
466    /// epoch.
467    pub fn as_nanos(&self) -> u64 {
468        self.nanos
469    }
470
471    /// Returns the fractional nanoseconds represented by this `Timestamp`.
472    pub fn subsec_nanos(&self) -> u32 {
473        (self.nanos % Self::NSEC_PER_SEC) as u32
474    }
475
476    /// Returns the total number of whole seconds represented by this `Timestamp` since the Unix
477    /// epoch.
478    pub fn as_secs(&self) -> u64 {
479        self.nanos / Self::NSEC_PER_SEC
480    }
481}
482
483impl From<std::time::Duration> for Timestamp {
484    fn from(duration: std::time::Duration) -> Self {
485        Self::from_secs_and_nanos(duration.as_secs(), duration.subsec_nanos())
486    }
487}
488
489impl From<Timestamp> for std::time::Duration {
490    fn from(timestamp: Timestamp) -> std::time::Duration {
491        Duration::from_nanos(timestamp.nanos)
492    }
493}
494
495pub type ObjectKind = ObjectKindV49;
496
497#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
498#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
499pub enum ObjectKindV49 {
500    File {
501        /// The number of references to this file.
502        refs: u64,
503    },
504    Directory {
505        /// The number of sub-directories in this directory.
506        sub_dirs: u64,
507        /// If set, contains the wrapping key id used to encrypt the file contents and filenames in
508        /// this directory.
509        wrapping_key_id: Option<WrappingKeyId>,
510        /// If true, all files and sub-directories created in this directory will support case
511        /// insensitive (but case-preserving) file naming.
512        casefold: bool,
513    },
514    Graveyard,
515    Symlink {
516        /// The number of references to this symbolic link.
517        refs: u64,
518        /// `link` is the target of the link and has no meaning within Fxfs; clients are free to
519        /// interpret it however they like.
520        #[serde(with = "crate::zerocopy_serialization")]
521        link: Box<[u8]>,
522    },
523    EncryptedSymlink {
524        /// The number of references to this symbolic link.
525        refs: u64,
526        /// `link` is the target of the link and has no meaning within Fxfs; clients are free to
527        /// interpret it however they like.
528        /// `link` is stored here in encrypted form, encrypted with the symlink's key using the
529        /// same encryption scheme as the one used to encrypt filenames.
530        #[serde(with = "crate::zerocopy_serialization")]
531        link: Box<[u8]>,
532    },
533}
534
535/// This consists of POSIX attributes that are not used in Fxfs but it may be meaningful to some
536/// clients to have the ability to to set and retrieve these values.
537pub type PosixAttributes = PosixAttributesV32;
538
539#[derive(Clone, Debug, Copy, Default, Serialize, Deserialize, PartialEq, TypeFingerprint)]
540#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
541pub struct PosixAttributesV32 {
542    /// The mode bits associated with this object
543    pub mode: u32,
544    /// User ID of owner
545    pub uid: u32,
546    /// Group ID of owner
547    pub gid: u32,
548    /// Device ID
549    pub rdev: u64,
550}
551
552/// Object-level attributes.  Note that these are not the same as "attributes" in the
553/// ObjectValue::Attribute sense, which refers to an arbitrary data payload associated with an
554/// object.  This naming collision is unfortunate.
555pub type ObjectAttributes = ObjectAttributesV49;
556
557#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, TypeFingerprint)]
558#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
559pub struct ObjectAttributesV49 {
560    /// The timestamp at which the object was created (i.e. crtime).
561    pub creation_time: TimestampV49,
562    /// The timestamp at which the object's data was last modified (i.e. mtime).
563    pub modification_time: TimestampV49,
564    /// The project id to associate this object's resource usage with. Zero means none.
565    pub project_id: u64,
566    /// Mode, uid, gid, and rdev
567    pub posix_attributes: Option<PosixAttributesV32>,
568    /// The number of bytes allocated to all extents across all attributes for this object.
569    pub allocated_size: u64,
570    /// The timestamp at which the object was last read (i.e. atime).
571    pub access_time: TimestampV49,
572    /// The timestamp at which the object's status was last modified (i.e. ctime).
573    pub change_time: TimestampV49,
574}
575
576pub type ExtendedAttributeValue = ExtendedAttributeValueV32;
577
578#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
579#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
580pub enum ExtendedAttributeValueV32 {
581    /// The extended attribute value is stored directly in this object. If the value is above a
582    /// certain size, it should be stored as an attribute with extents instead.
583    Inline(#[serde(with = "crate::zerocopy_serialization")] Vec<u8>),
584    /// The extended attribute value is stored as an attribute with extents. The attribute id
585    /// should be chosen to be within the range of 64-512.
586    AttributeId(u64),
587}
588
589/// Id and descriptor for a child entry.
590pub type ChildValue = ChildValueV32;
591
592#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
593#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
594pub struct ChildValueV32 {
595    /// The ID of the child object.
596    pub object_id: u64,
597    /// Describes the type of the child.
598    pub object_descriptor: ObjectDescriptorV32,
599}
600
601pub type RootDigest = RootDigestV33;
602
603#[derive(
604    Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize, TypeFingerprint,
605)]
606#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
607pub enum RootDigestV33 {
608    Sha256([u8; 32]),
609    Sha512(#[serde(with = "crate::zerocopy_serialization")] Vec<u8>),
610}
611
612pub type FsverityMetadata = FsverityMetadataV50;
613
614#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TypeFingerprint, Versioned)]
615#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
616pub enum FsverityMetadataV50 {
617    /// The root hash and salt.
618    Internal(RootDigestV33, #[serde(with = "crate::zerocopy_serialization")] Vec<u8>),
619    /// The root hash and salt are in a descriptor inside the merkle attribute.
620    F2fs(std::ops::Range<u64>),
621}
622
623pub type EncryptionKey = EncryptionKeyV49;
624pub type EncryptionKeyV49 = fxfs_crypto::EncryptionKey;
625
626pub type EncryptionKeys = EncryptionKeysV49;
627
628#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint)]
629#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
630pub struct EncryptionKeysV49(Vec<(u64, EncryptionKeyV49)>);
631
632impl EncryptionKeys {
633    pub fn get(&self, id: u64) -> Option<&EncryptionKey> {
634        self.0.iter().find_map(|(i, key)| (*i == id).then_some(key))
635    }
636
637    pub fn insert(&mut self, id: u64, key: EncryptionKey) {
638        self.0.push((id, key))
639    }
640
641    pub fn remove(&mut self, id: u64) -> Option<EncryptionKey> {
642        if let Some(ix) = self.0.iter().position(|(k, _)| *k == id) {
643            Some(self.0.remove(ix).1)
644        } else {
645            None
646        }
647    }
648}
649
650impl From<EncryptionKeys> for BTreeMap<u64, WrappedKey> {
651    fn from(keys: EncryptionKeys) -> Self {
652        keys.0.into_iter().map(|(id, key)| (id, key.into())).collect()
653    }
654}
655
656impl From<Vec<(u64, EncryptionKey)>> for EncryptionKeys {
657    fn from(value: Vec<(u64, EncryptionKey)>) -> Self {
658        Self(value)
659    }
660}
661
662impl std::ops::Deref for EncryptionKeys {
663    type Target = Vec<(u64, EncryptionKey)>;
664    fn deref(&self) -> &Self::Target {
665        &self.0
666    }
667}
668
669/// ObjectValue is the value of an item in the object store.
670/// Note that the tree stores deltas on objects, so these values describe deltas. Unless specified
671/// otherwise, a value indicates an insert/replace mutation.
672pub type ObjectValue = ObjectValueV50;
673impl Value for ObjectValue {
674    const DELETED_MARKER: Self = Self::None;
675}
676
677#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint, Versioned)]
678#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
679pub enum ObjectValueV50 {
680    /// Some keys have no value (this often indicates a tombstone of some sort).  Records with this
681    /// value are always filtered when a major compaction is performed, so the meaning must be the
682    /// same as if the item was not present.
683    None,
684    /// Some keys have no value but need to differentiate between a present value and no value
685    /// (None) i.e. their value is really a boolean: None => false, Some => true.
686    Some,
687    /// The value for an ObjectKey::Object record.
688    Object { kind: ObjectKindV49, attributes: ObjectAttributesV49 },
689    /// Specifies encryption keys to use for an object.
690    Keys(EncryptionKeysV49),
691    /// An attribute associated with a file object. |size| is the size of the attribute in bytes.
692    Attribute { size: u64, has_overwrite_extents: bool },
693    /// An extent associated with an object.
694    Extent(ExtentValueV38),
695    /// A child of an object.
696    Child(ChildValueV32),
697    /// Graveyard entries can contain these entries which will cause a file that has extents beyond
698    /// EOF to be trimmed at mount time.  This is used in cases where shrinking a file can exceed
699    /// the bounds of a single transaction.
700    Trim,
701    /// Added to support tracking Project ID usage and limits.
702    BytesAndNodes { bytes: i64, nodes: i64 },
703    /// A value for an extended attribute. Either inline or a redirection to an attribute with
704    /// extents.
705    ExtendedAttribute(ExtendedAttributeValueV32),
706    /// An attribute associated with a verified file object. |size| is the size of the attribute
707    /// in bytes.
708    VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV50 },
709}
710
711impl ObjectValue {
712    /// Creates an ObjectValue for a file object.
713    pub fn file(
714        refs: u64,
715        allocated_size: u64,
716        creation_time: Timestamp,
717        modification_time: Timestamp,
718        access_time: Timestamp,
719        change_time: Timestamp,
720        project_id: u64,
721        posix_attributes: Option<PosixAttributes>,
722    ) -> ObjectValue {
723        ObjectValue::Object {
724            kind: ObjectKind::File { refs },
725            attributes: ObjectAttributes {
726                creation_time,
727                modification_time,
728                project_id,
729                posix_attributes,
730                allocated_size,
731                access_time,
732                change_time,
733            },
734        }
735    }
736    pub fn keys(encryption_keys: EncryptionKeys) -> ObjectValue {
737        ObjectValue::Keys(encryption_keys)
738    }
739    /// Creates an ObjectValue for an object attribute.
740    pub fn attribute(size: u64, has_overwrite_extents: bool) -> ObjectValue {
741        ObjectValue::Attribute { size, has_overwrite_extents }
742    }
743    /// Creates an ObjectValue for an object attribute of a verified file.
744    pub fn verified_attribute(size: u64, fsverity_metadata: FsverityMetadata) -> ObjectValue {
745        ObjectValue::VerifiedAttribute { size, fsverity_metadata }
746    }
747    /// Creates an ObjectValue for an insertion/replacement of an object extent.
748    pub fn extent(device_offset: u64, key_id: u64) -> ObjectValue {
749        ObjectValue::Extent(ExtentValue::new_raw(device_offset, key_id))
750    }
751    /// Creates an ObjectValue for an insertion/replacement of an object extent.
752    pub fn extent_with_checksum(
753        device_offset: u64,
754        checksum: Checksums,
755        key_id: u64,
756    ) -> ObjectValue {
757        ObjectValue::Extent(ExtentValue::with_checksum(device_offset, checksum, key_id))
758    }
759    /// Creates an ObjectValue for a deletion of an object extent.
760    pub fn deleted_extent() -> ObjectValue {
761        ObjectValue::Extent(ExtentValue::deleted_extent())
762    }
763    /// Creates an ObjectValue for an object child.
764    pub fn child(object_id: u64, object_descriptor: ObjectDescriptor) -> ObjectValue {
765        ObjectValue::Child(ChildValue { object_id, object_descriptor })
766    }
767    /// Creates an ObjectValue for an object symlink.
768    pub fn symlink(
769        link: impl Into<Box<[u8]>>,
770        creation_time: Timestamp,
771        modification_time: Timestamp,
772        project_id: u64,
773    ) -> ObjectValue {
774        ObjectValue::Object {
775            kind: ObjectKind::Symlink { refs: 1, link: link.into() },
776            attributes: ObjectAttributes {
777                creation_time,
778                modification_time,
779                project_id,
780                ..Default::default()
781            },
782        }
783    }
784    /// Creates an ObjectValue for an encrypted symlink object.
785    pub fn encrypted_symlink(
786        link: impl Into<Box<[u8]>>,
787        creation_time: Timestamp,
788        modification_time: Timestamp,
789        project_id: u64,
790    ) -> ObjectValue {
791        ObjectValue::Object {
792            kind: ObjectKind::EncryptedSymlink { refs: 1, link: link.into() },
793            attributes: ObjectAttributes {
794                creation_time,
795                modification_time,
796                project_id,
797                ..Default::default()
798            },
799        }
800    }
801    pub fn inline_extended_attribute(value: impl Into<Vec<u8>>) -> ObjectValue {
802        ObjectValue::ExtendedAttribute(ExtendedAttributeValue::Inline(value.into()))
803    }
804    pub fn extended_attribute(attribute_id: u64) -> ObjectValue {
805        ObjectValue::ExtendedAttribute(ExtendedAttributeValue::AttributeId(attribute_id))
806    }
807}
808
809pub type ObjectItem = ObjectItemV50;
810pub type ObjectItemV50 = Item<ObjectKeyV43, ObjectValueV50>;
811
812impl ObjectItem {
813    pub fn is_tombstone(&self) -> bool {
814        matches!(
815            self,
816            Item {
817                key: ObjectKey { data: ObjectKeyData::Object, .. },
818                value: ObjectValue::None,
819                ..
820            }
821        )
822    }
823}
824
825// If the given item describes an extent, unwraps it and returns the extent key/value.
826impl<'a> From<ItemRef<'a, ObjectKey, ObjectValue>>
827    for Option<(/*object-id*/ u64, /*attribute-id*/ u64, &'a ExtentKey, &'a ExtentValue)>
828{
829    fn from(item: ItemRef<'a, ObjectKey, ObjectValue>) -> Self {
830        match item {
831            ItemRef {
832                key:
833                    ObjectKey {
834                        object_id,
835                        data:
836                            ObjectKeyData::Attribute(
837                                attribute_id, //
838                                AttributeKey::Extent(extent_key),
839                            ),
840                    },
841                value: ObjectValue::Extent(extent_value),
842                ..
843            } => Some((*object_id, *attribute_id, extent_key, extent_value)),
844            _ => None,
845        }
846    }
847}
848
849pub type FxfsKey = FxfsKeyV49;
850pub type FxfsKeyV49 = fxfs_crypto::FxfsKey;
851
852#[cfg(test)]
853mod tests {
854    use super::{ObjectKey, ObjectKeyV43, TimestampV49};
855    use crate::lsm_tree::types::{
856        FuzzyHash as _, LayerKey, OrdLowerBound, OrdUpperBound, RangeKey,
857    };
858    use std::cmp::Ordering;
859    use std::ops::Add;
860    use std::time::{Duration, SystemTime, UNIX_EPOCH};
861
862    // Smoke test to ensure hash stability for Fxfs objects.
863    // If this test fails, the hash algorithm changed, and that won't do -- Fxfs relies on stable
864    // hash values, and existing images will appear to be corrupt if they change (see
865    // https://fxbug.dev/419133532).
866    #[test]
867    fn test_hash_stability() {
868        // Target a specific version of ObjectKey.  If you want to delete ObjectKeyV43, simply
869        // update this test with a later key version, which will also require re-generating the
870        // hashes.
871        assert_eq!(
872            &ObjectKeyV43::object(100).fuzzy_hash().collect::<Vec<_>>()[..],
873            &[11885326717398844384]
874        );
875        assert_eq!(
876            &ObjectKeyV43::extent(1, 0, 0..2 * 1024 * 1024).fuzzy_hash().collect::<Vec<_>>()[..],
877            &[11090579907097549012, 2814892992701560424]
878        );
879    }
880
881    #[test]
882    fn test_next_key() {
883        let next_key = ObjectKey::extent(1, 0, 0..100).next_key().unwrap();
884        assert_eq!(ObjectKey::extent(1, 0, 101..200).cmp_lower_bound(&next_key), Ordering::Greater);
885        assert_eq!(ObjectKey::extent(1, 0, 100..200).cmp_lower_bound(&next_key), Ordering::Equal);
886        assert_eq!(ObjectKey::extent(1, 0, 100..101).cmp_lower_bound(&next_key), Ordering::Equal);
887        assert_eq!(ObjectKey::extent(1, 0, 99..100).cmp_lower_bound(&next_key), Ordering::Less);
888        assert_eq!(ObjectKey::extent(1, 0, 0..100).cmp_upper_bound(&next_key), Ordering::Less);
889        assert_eq!(ObjectKey::extent(1, 0, 99..100).cmp_upper_bound(&next_key), Ordering::Less);
890        assert_eq!(ObjectKey::extent(1, 0, 100..101).cmp_upper_bound(&next_key), Ordering::Equal);
891        assert_eq!(ObjectKey::extent(1, 0, 100..200).cmp_upper_bound(&next_key), Ordering::Greater);
892        assert_eq!(ObjectKey::extent(1, 0, 50..101).cmp_upper_bound(&next_key), Ordering::Equal);
893        assert_eq!(ObjectKey::extent(1, 0, 50..200).cmp_upper_bound(&next_key), Ordering::Greater);
894    }
895    #[test]
896    fn test_range_key() {
897        // Make sure we disallow using extent keys with point queries. Other object keys should
898        // still be allowed with point queries.
899        assert!(ObjectKeyV43::extent(1, 0, 0..2 * 1024 * 1024).is_range_key());
900        assert!(!ObjectKeyV43::object(100).is_range_key());
901
902        assert_eq!(ObjectKey::object(1).overlaps(&ObjectKey::object(1)), true);
903        assert_eq!(ObjectKey::object(1).overlaps(&ObjectKey::object(2)), false);
904        assert_eq!(ObjectKey::extent(1, 0, 0..100).overlaps(&ObjectKey::object(1)), false);
905        assert_eq!(ObjectKey::object(1).overlaps(&ObjectKey::extent(1, 0, 0..100)), false);
906        assert_eq!(
907            ObjectKey::extent(1, 0, 0..100).overlaps(&ObjectKey::extent(2, 0, 0..100)),
908            false
909        );
910        assert_eq!(
911            ObjectKey::extent(1, 0, 0..100).overlaps(&ObjectKey::extent(1, 1, 0..100)),
912            false
913        );
914        assert_eq!(
915            ObjectKey::extent(1, 0, 0..100).overlaps(&ObjectKey::extent(1, 0, 0..100)),
916            true
917        );
918
919        assert_eq!(
920            ObjectKey::extent(1, 0, 0..50).overlaps(&ObjectKey::extent(1, 0, 49..100)),
921            true
922        );
923        assert_eq!(
924            ObjectKey::extent(1, 0, 49..100).overlaps(&ObjectKey::extent(1, 0, 0..50)),
925            true
926        );
927
928        assert_eq!(
929            ObjectKey::extent(1, 0, 0..50).overlaps(&ObjectKey::extent(1, 0, 50..100)),
930            false
931        );
932        assert_eq!(
933            ObjectKey::extent(1, 0, 50..100).overlaps(&ObjectKey::extent(1, 0, 0..50)),
934            false
935        );
936    }
937
938    #[test]
939    fn test_timestamp() {
940        fn compare_time(std_time: Duration) {
941            let ts_time: TimestampV49 = std_time.into();
942            assert_eq!(<TimestampV49 as Into<Duration>>::into(ts_time), std_time);
943            assert_eq!(ts_time.subsec_nanos(), std_time.subsec_nanos());
944            assert_eq!(ts_time.as_secs(), std_time.as_secs());
945            assert_eq!(ts_time.as_nanos() as u128, std_time.as_nanos());
946        }
947        compare_time(Duration::from_nanos(0));
948        compare_time(Duration::from_nanos(u64::MAX));
949        compare_time(SystemTime::now().duration_since(UNIX_EPOCH).unwrap());
950
951        let ts: TimestampV49 = Duration::from_secs(u64::MAX - 1).into();
952        assert_eq!(ts.nanos, u64::MAX);
953
954        let ts: TimestampV49 = (Duration::from_nanos(u64::MAX).add(Duration::from_nanos(1))).into();
955        assert_eq!(ts.nanos, u64::MAX);
956    }
957}