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