1mod legacy;
6pub use legacy::{
7 EncryptionKeyV56, EncryptionKeysV56, ObjectItemV56, ObjectItemV59, ObjectKindV59,
8 ObjectValueV56, ObjectValueV59,
9};
10
11use crate::checksum::Checksums;
13use crate::log::error;
14use crate::lsm_tree::types::{
15 FuzzyHash, Item, ItemRef, LayerKey, MergeType, OrdLowerBound, OrdUpperBound, SortByU64, Value,
16};
17use crate::object_store::ProjectId;
18use crate::object_store::extent::{Extent, ExtentPartitionIterator};
19use crate::object_store::extent_record::{ExtentValue, ExtentValueV38};
20use crate::serialized_types::Versioned;
21use fprint::TypeFingerprint;
22use fxfs_crypto::{WrappedKey, WrappingKeyId};
23use fxfs_macros::SerializeKey;
24use fxfs_unicode::CasefoldString;
25use serde::{Deserialize, Serialize};
26use static_assertions::const_assert_eq;
27use std::collections::BTreeMap;
28use std::default::Default;
29use std::hash::Hash;
30use std::time::{Duration, SystemTime, UNIX_EPOCH};
31
32pub type ObjectDescriptor = ObjectDescriptorV32;
34
35#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
36#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
37pub enum ObjectDescriptorV32 {
38 File,
40 Directory,
42 Volume,
44 Symlink,
46}
47
48pub type ProjectProperty = ProjectPropertyV32;
50
51#[derive(
52 Clone,
53 Debug,
54 Eq,
55 Hash,
56 Ord,
57 PartialEq,
58 PartialOrd,
59 Serialize,
60 Deserialize,
61 TypeFingerprint,
62 SerializeKey,
63)]
64#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
65pub enum ProjectPropertyV32 {
66 Limit,
68 Usage,
70}
71
72pub type ObjectKeyData = ObjectKeyDataV54;
73
74#[derive(
75 Clone,
76 Debug,
77 Eq,
78 Hash,
79 PartialEq,
80 PartialOrd,
81 Ord,
82 Serialize,
83 Deserialize,
84 TypeFingerprint,
85 SerializeKey,
86)]
87#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
88pub enum ObjectKeyDataV54 {
89 Object,
92 Keys,
94 Attribute(AttributeId, AttributeKeyV32),
96 Child { name: String },
98 GraveyardEntry { object_id: u64 },
100 Project { project_id: ProjectId, property: ProjectPropertyV32 },
104 ExtendedAttribute {
107 #[serde(with = "crate::zerocopy_serialization")]
108 name: Vec<u8>,
109 },
110 GraveyardAttributeEntry { object_id: u64, attribute_id: AttributeId },
112 EncryptedCasefoldChild(EncryptedCasefoldChild),
117 LegacyCasefoldChild(CasefoldString),
119 EncryptedChild(EncryptedChild),
121 CasefoldChild { hash_code: u32, name: String },
124}
125
126#[derive(
127 Clone,
128 Debug,
129 Eq,
130 Hash,
131 PartialEq,
132 PartialOrd,
133 Ord,
134 Serialize,
135 Deserialize,
136 TypeFingerprint,
137 SerializeKey,
138)]
139#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
140pub struct EncryptedCasefoldChild {
141 pub hash_code: u32,
142 #[serde(with = "crate::zerocopy_serialization")]
143 pub name: Vec<u8>,
144}
145
146#[derive(
147 Clone,
148 Debug,
149 Eq,
150 Hash,
151 PartialEq,
152 PartialOrd,
153 Ord,
154 Serialize,
155 Deserialize,
156 TypeFingerprint,
157 SerializeKey,
158)]
159#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
160pub struct EncryptedChild(#[serde(with = "crate::zerocopy_serialization")] pub Vec<u8>);
161
162pub type AttributeKey = AttributeKeyV32;
163
164#[derive(
166 Clone,
167 Debug,
168 Eq,
169 Hash,
170 Ord,
171 PartialEq,
172 PartialOrd,
173 Serialize,
174 Deserialize,
175 TypeFingerprint,
176 SerializeKey,
177)]
178#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
179pub enum AttributeKeyV32 {
180 Attribute,
182 Extent(Extent),
183}
184
185pub type ObjectKey = ObjectKeyV54;
187
188#[derive(
189 Clone,
190 Debug,
191 Eq,
192 Ord,
193 Hash,
194 PartialEq,
195 PartialOrd,
196 Serialize,
197 Deserialize,
198 SerializeKey,
199 TypeFingerprint,
200 Versioned,
201)]
202#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
203pub struct ObjectKeyV54 {
204 pub object_id: u64,
206 pub data: ObjectKeyDataV54,
208}
209impl SortByU64 for ObjectKey {
212 fn get_leading_u64(&self) -> u64 {
213 self.object_id
214 }
215}
216
217impl ObjectKey {
218 pub fn object(object_id: u64) -> Self {
220 Self { object_id: object_id, data: ObjectKeyData::Object }
221 }
222
223 pub fn keys(object_id: u64) -> Self {
225 Self { object_id, data: ObjectKeyData::Keys }
226 }
227
228 pub fn attribute(object_id: u64, attribute_id: AttributeId, key: AttributeKey) -> Self {
230 Self { object_id, data: ObjectKeyData::Attribute(attribute_id, key) }
231 }
232
233 pub fn extent(object_id: u64, attribute_id: AttributeId, range: std::ops::Range<u64>) -> Self {
235 Self {
236 object_id,
237 data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(Extent(range))),
238 }
239 }
240
241 pub fn from_extent(object_id: u64, attribute_id: AttributeId, extent: Extent) -> Self {
243 Self {
244 object_id,
245 data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
246 }
247 }
248
249 pub fn child(object_id: u64, name: &str, dir_type: DirType) -> Self {
251 match dir_type {
252 DirType::Casefold => {
253 let cf = fxfs_unicode::CasefoldStr::new(name);
254 let casefolded = cf.casefold_normalized_chars().flat_map(fxfs_unicode::utf8_bytes);
255 let hash_code = fscrypt::direntry::tea_hash_filename(casefolded);
256 Self {
257 object_id,
258 data: ObjectKeyData::CasefoldChild { hash_code, name: name.into() },
259 }
260 }
261 DirType::LegacyCasefold => Self {
262 object_id,
263 data: ObjectKeyData::LegacyCasefoldChild(CasefoldString::new(name.into())),
264 },
265 DirType::Normal => Self { object_id, data: ObjectKeyData::Child { name: name.into() } },
266 DirType::Encrypted(_) | DirType::EncryptedCasefold(_) => {
267 panic!("Encrypted modes require an encrypted name");
269 }
270 }
271 }
272
273 pub fn encrypted_child(object_id: u64, name: Vec<u8>, hash_code: Option<u32>) -> Self {
283 if let Some(hash_code) = hash_code {
284 Self {
285 object_id,
286 data: ObjectKeyData::EncryptedCasefoldChild(EncryptedCasefoldChild {
287 hash_code,
288 name,
289 }),
290 }
291 } else {
292 Self { object_id, data: ObjectKeyData::EncryptedChild(EncryptedChild(name)) }
293 }
294 }
295
296 pub fn graveyard_entry(graveyard_object_id: u64, object_id: u64) -> Self {
298 Self { object_id: graveyard_object_id, data: ObjectKeyData::GraveyardEntry { object_id } }
299 }
300
301 pub fn graveyard_attribute_entry(
303 graveyard_object_id: u64,
304 object_id: u64,
305 attribute_id: AttributeId,
306 ) -> Self {
307 Self {
308 object_id: graveyard_object_id,
309 data: ObjectKeyData::GraveyardAttributeEntry { object_id, attribute_id },
310 }
311 }
312
313 pub fn project_limit(object_id: u64, project_id: ProjectId) -> Self {
315 Self {
316 object_id,
317 data: ObjectKeyData::Project { project_id, property: ProjectProperty::Limit },
318 }
319 }
320
321 pub fn project_usage(object_id: u64, project_id: ProjectId) -> Self {
323 Self {
324 object_id,
325 data: ObjectKeyData::Project { project_id, property: ProjectProperty::Usage },
326 }
327 }
328
329 pub fn extended_attribute(object_id: u64, name: Vec<u8>) -> Self {
330 Self { object_id, data: ObjectKeyData::ExtendedAttribute { name } }
331 }
332
333 pub fn key_for_merge_into(&self) -> Self {
336 if let Self {
337 object_id,
338 data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(e)),
339 } = self
340 {
341 Self::attribute(*object_id, *attribute_id, AttributeKey::Extent(e.key_for_merge_into()))
342 } else {
343 self.clone()
344 }
345 }
346}
347
348impl OrdUpperBound for ObjectKey {
349 fn cmp_upper_bound(&self, other: &ObjectKey) -> std::cmp::Ordering {
350 self.object_id.cmp(&other.object_id).then_with(|| match (&self.data, &other.data) {
351 (
352 ObjectKeyData::Attribute(left_attr_id, AttributeKey::Extent(left_extent)),
353 ObjectKeyData::Attribute(right_attr_id, AttributeKey::Extent(right_extent)),
354 ) => left_attr_id.cmp(right_attr_id).then(left_extent.cmp_upper_bound(right_extent)),
355 _ => self.data.cmp(&other.data),
356 })
357 }
358}
359
360impl OrdLowerBound for ObjectKey {
361 fn cmp_lower_bound(&self, other: &ObjectKey) -> std::cmp::Ordering {
362 self.object_id.cmp(&other.object_id).then_with(|| match (&self.data, &other.data) {
363 (
364 ObjectKeyData::Attribute(left_attr_id, AttributeKey::Extent(left_extent)),
365 ObjectKeyData::Attribute(right_attr_id, AttributeKey::Extent(right_extent)),
366 ) => left_attr_id.cmp(right_attr_id).then(left_extent.cmp_lower_bound(right_extent)),
367 _ => self.data.cmp(&other.data),
368 })
369 }
370}
371
372impl LayerKey for ObjectKey {
373 fn merge_type(&self) -> MergeType {
374 match self.data {
377 ObjectKeyData::Object
378 | ObjectKeyData::Keys
379 | ObjectKeyData::Attribute(..)
380 | ObjectKeyData::Child { .. }
381 | ObjectKeyData::EncryptedChild(_)
382 | ObjectKeyData::EncryptedCasefoldChild(_)
383 | ObjectKeyData::CasefoldChild { .. }
384 | ObjectKeyData::LegacyCasefoldChild(_)
385 | ObjectKeyData::GraveyardEntry { .. }
386 | ObjectKeyData::GraveyardAttributeEntry { .. }
387 | ObjectKeyData::Project { property: ProjectProperty::Limit, .. }
388 | ObjectKeyData::ExtendedAttribute { .. } => MergeType::OptimizedMerge,
389 ObjectKeyData::Project { property: ProjectProperty::Usage, .. } => MergeType::FullMerge,
390 }
391 }
392
393 fn next_key(&self) -> Option<Self> {
394 match &self.data {
395 ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent)) => {
396 Some(ObjectKey {
400 object_id: self.object_id,
401 data: ObjectKeyData::Attribute(
402 *attr_id,
403 AttributeKey::Extent(Extent::search_key_from_offset(extent.end)),
404 ),
405 })
406 }
407 _ => None,
408 }
409 }
410
411 fn search_key(&self) -> Option<Self> {
412 if let Self {
413 object_id,
414 data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(e)),
415 } = self
416 {
417 Some(Self::attribute(*object_id, *attribute_id, AttributeKey::Extent(e.search_key())))
418 } else {
419 None
420 }
421 }
422
423 fn is_search_key(&self) -> bool {
424 match self {
425 Self { data: ObjectKeyData::Attribute(_, AttributeKey::Extent(e)), .. } => {
426 e.is_search_key()
427 }
428 _ => true,
429 }
430 }
431
432 fn overlaps(&self, other: &Self) -> bool {
433 if self.object_id != other.object_id {
434 return false;
435 }
436 match (&self.data, &other.data) {
437 (
438 ObjectKeyData::Attribute(left_attr_id, AttributeKey::Extent(left_key)),
439 ObjectKeyData::Attribute(right_attr_id, AttributeKey::Extent(right_key)),
440 ) if *left_attr_id == *right_attr_id => left_key.overlaps(right_key),
441 (a, b) => a == b,
442 }
443 }
444}
445
446pub enum ObjectKeyFuzzyHashIterator {
447 Extent(u64, AttributeId, ExtentPartitionIterator),
448 NotExtent(Option<u64>),
449}
450
451impl Iterator for ObjectKeyFuzzyHashIterator {
452 type Item = u64;
453
454 fn next(&mut self) -> Option<Self::Item> {
455 match self {
456 Self::Extent(oid, attr_id, extent_keys) => extent_keys.next().map(|range| {
457 let key = ObjectKey::extent(*oid, *attr_id, range);
458 crate::stable_hash::stable_hash(key)
459 }),
460 Self::NotExtent(hash) => hash.take(),
461 }
462 }
463
464 fn size_hint(&self) -> (usize, Option<usize>) {
465 match self {
466 Self::Extent(_, _, extent_keys) => extent_keys.size_hint(),
467 Self::NotExtent(hash) => {
468 let len = if hash.is_some() { 1 } else { 0 };
469 (len, Some(len))
470 }
471 }
472 }
473}
474
475impl ExactSizeIterator for ObjectKeyFuzzyHashIterator {}
476
477impl FuzzyHash for ObjectKey {
478 fn fuzzy_hash(&self) -> impl ExactSizeIterator<Item = u64> {
479 match &self.data {
480 ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent)) => {
481 ObjectKeyFuzzyHashIterator::Extent(
482 self.object_id,
483 *attr_id,
484 extent.fuzzy_hash_partition(),
485 )
486 }
487 _ => {
488 let hash = crate::stable_hash::stable_hash(self);
489 ObjectKeyFuzzyHashIterator::NotExtent(Some(hash))
490 }
491 }
492 }
493
494 fn is_range_key(&self) -> bool {
495 match &self.data {
496 ObjectKeyData::Attribute(_, AttributeKey::Extent(_)) => true,
497 _ => false,
498 }
499 }
500}
501
502pub type Timestamp = TimestampV49;
504
505#[derive(
506 Copy,
507 Clone,
508 Debug,
509 Default,
510 Eq,
511 PartialEq,
512 Ord,
513 PartialOrd,
514 Serialize,
515 Deserialize,
516 TypeFingerprint,
517)]
518#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
519pub struct TimestampV49 {
520 nanos: u64,
521}
522
523impl Timestamp {
524 const NSEC_PER_SEC: u64 = 1_000_000_000;
525
526 pub fn now() -> Self {
527 SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or(Duration::ZERO).into()
528 }
529
530 pub const fn zero() -> Self {
531 Self { nanos: 0 }
532 }
533
534 pub const fn from_nanos(nanos: u64) -> Self {
535 Self { nanos }
536 }
537
538 pub fn from_secs_and_nanos(secs: u64, nanos: u32) -> Self {
539 let Some(secs_in_nanos) = secs.checked_mul(Self::NSEC_PER_SEC) else {
540 error!("Fxfs doesn't support dates past 2554-07-21");
541 return Self { nanos: u64::MAX };
542 };
543 let Some(nanos) = secs_in_nanos.checked_add(nanos as u64) else {
544 error!("Fxfs doesn't support dates past 2554-07-21");
545 return Self { nanos: u64::MAX };
546 };
547 Self { nanos }
548 }
549
550 pub fn as_nanos(&self) -> u64 {
553 self.nanos
554 }
555
556 pub fn subsec_nanos(&self) -> u32 {
558 (self.nanos % Self::NSEC_PER_SEC) as u32
559 }
560
561 pub fn as_secs(&self) -> u64 {
564 self.nanos / Self::NSEC_PER_SEC
565 }
566}
567
568impl From<std::time::Duration> for Timestamp {
569 fn from(duration: std::time::Duration) -> Self {
570 Self::from_secs_and_nanos(duration.as_secs(), duration.subsec_nanos())
571 }
572}
573
574impl From<Timestamp> for std::time::Duration {
575 fn from(timestamp: Timestamp) -> std::time::Duration {
576 Duration::from_nanos(timestamp.nanos)
577 }
578}
579
580pub type ObjectKind = ObjectKindV62;
581pub type DirType = DirTypeV59;
582
583pub const LEGACY_FSCRYPT_FLAGS: fidl_fuchsia_io::FscryptPolicyFlags =
593 fidl_fuchsia_io::FscryptPolicyFlags::PAD_16;
594
595#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
597#[repr(transparent)]
598pub struct FscryptPolicyFlags(u8);
599
600impl FscryptPolicyFlags {
601 pub const PAD_8: Self = Self(0x01);
602 pub const PAD_16: Self = Self(0x02);
603 pub const DIRECT_KEY: Self = Self(0x04);
604 pub const IV_INO_LBLK_64: Self = Self(0x08);
605 pub const IV_INO_LBLK_32: Self = Self(0x10);
606 pub const ALL: Self = Self(
607 Self::PAD_8.0
608 | Self::PAD_16.0
609 | Self::DIRECT_KEY.0
610 | Self::IV_INO_LBLK_64.0
611 | Self::IV_INO_LBLK_32.0,
612 );
613
614 pub const fn empty() -> Self {
615 Self(0)
616 }
617
618 pub const fn from_bits(bits: u8) -> Option<Self> {
619 if (bits & !Self::ALL.0) == 0 { Some(Self(bits)) } else { None }
620 }
621
622 pub const fn from_bits_retain(bits: u8) -> Self {
623 Self(bits)
624 }
625
626 pub const fn bits(&self) -> u8 {
627 self.0
628 }
629
630 pub const fn contains(&self, other: Self) -> bool {
631 (self.0 & other.0) == other.0
632 }
633
634 pub const fn intersects(&self, other: Self) -> bool {
635 (self.0 & other.0) != 0
636 }
637}
638
639#[cfg(fuzz)]
640impl<'a> arbitrary::Arbitrary<'a> for FscryptPolicyFlags {
641 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
642 Ok(Self(u.arbitrary::<u8>()? & Self::ALL.bits()))
643 }
644}
645
646const_assert_eq!(
647 FscryptPolicyFlags::PAD_8.bits(),
648 fidl_fuchsia_io::FscryptPolicyFlags::PAD_8.bits()
649);
650const_assert_eq!(
651 FscryptPolicyFlags::PAD_16.bits(),
652 fidl_fuchsia_io::FscryptPolicyFlags::PAD_16.bits()
653);
654const_assert_eq!(
655 FscryptPolicyFlags::DIRECT_KEY.bits(),
656 fidl_fuchsia_io::FscryptPolicyFlags::DIRECT_KEY.bits()
657);
658const_assert_eq!(
659 FscryptPolicyFlags::IV_INO_LBLK_64.bits(),
660 fidl_fuchsia_io::FscryptPolicyFlags::IV_INO_LBLK_64.bits()
661);
662const_assert_eq!(
663 FscryptPolicyFlags::IV_INO_LBLK_32.bits(),
664 fidl_fuchsia_io::FscryptPolicyFlags::IV_INO_LBLK_32.bits()
665);
666
667impl core::ops::BitOr for FscryptPolicyFlags {
668 type Output = Self;
669
670 fn bitor(self, rhs: Self) -> Self::Output {
671 Self(self.0 | rhs.0)
672 }
673}
674
675impl core::ops::BitOrAssign for FscryptPolicyFlags {
676 fn bitor_assign(&mut self, rhs: Self) {
677 self.0 |= rhs.0;
678 }
679}
680
681impl core::ops::BitAnd for FscryptPolicyFlags {
682 type Output = Self;
683
684 fn bitand(self, rhs: Self) -> Self::Output {
685 Self(self.0 & rhs.0)
686 }
687}
688
689impl core::ops::Not for FscryptPolicyFlags {
690 type Output = Self;
691
692 fn not(self) -> Self::Output {
693 Self(!self.0)
694 }
695}
696
697impl From<fidl_fuchsia_io::FscryptPolicyFlags> for FscryptPolicyFlags {
698 fn from(flags: fidl_fuchsia_io::FscryptPolicyFlags) -> Self {
699 Self(flags.bits())
700 }
701}
702
703impl From<FscryptPolicyFlags> for fidl_fuchsia_io::FscryptPolicyFlags {
704 fn from(flags: FscryptPolicyFlags) -> Self {
705 Self::from_bits_retain(flags.bits())
706 }
707}
708
709impl TryFrom<u8> for FscryptPolicyFlags {
710 type Error = anyhow::Error;
711
712 fn try_from(bits: u8) -> Result<Self, Self::Error> {
713 Self::from_bits(bits)
714 .ok_or_else(|| anyhow::anyhow!("Unrecognized fscrypt policy flags: {bits:#x}"))
715 }
716}
717
718impl From<FscryptPolicyFlags> for u8 {
719 fn from(flags: FscryptPolicyFlags) -> Self {
720 flags.bits()
721 }
722}
723
724impl TypeFingerprint for FscryptPolicyFlags {
725 fn fingerprint() -> String {
726 "u8".to_owned()
727 }
728}
729
730#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq, TypeFingerprint)]
732#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
733pub struct FscryptDirInfo {
734 pub wrapping_key_id: WrappingKeyId,
735 pub flags: FscryptPolicyFlags,
736}
737
738impl FscryptDirInfo {
739 pub fn new(wrapping_key_id: WrappingKeyId, flags: impl Into<FscryptPolicyFlags>) -> Self {
740 Self { wrapping_key_id, flags: flags.into() }
741 }
742}
743
744impl From<WrappingKeyId> for FscryptDirInfo {
749 fn from(wrapping_key_id: WrappingKeyId) -> Self {
750 Self { wrapping_key_id, flags: FscryptPolicyFlags::PAD_16 }
751 }
752}
753
754impl From<fidl_fuchsia_io::FscryptPolicy> for FscryptDirInfo {
755 fn from(policy: fidl_fuchsia_io::FscryptPolicy) -> Self {
756 Self {
757 wrapping_key_id: policy.key_identifier,
758 flags: FscryptPolicyFlags::from(policy.flags),
759 }
760 }
761}
762
763impl From<FscryptDirInfo> for fidl_fuchsia_io::FscryptPolicy {
764 fn from(info: FscryptDirInfo) -> Self {
765 fidl_fuchsia_io::FscryptPolicy {
766 key_identifier: info.wrapping_key_id,
767 flags: info.flags.into(),
768 }
769 }
770}
771
772#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, TypeFingerprint)]
773#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
774pub enum DirTypeV59 {
775 Normal,
776 Encrypted(FscryptDirInfo),
777 LegacyCasefold,
778 Casefold,
779 EncryptedCasefold(FscryptDirInfo),
780}
781
782impl DirType {
783 pub fn is_casefold(&self) -> bool {
784 matches!(self, DirType::LegacyCasefold | DirType::Casefold | DirType::EncryptedCasefold(_))
785 }
786
787 pub fn is_encrypted(&self) -> bool {
788 matches!(self, DirType::Encrypted(_) | DirType::EncryptedCasefold(_))
789 }
790
791 pub fn with_encryption(self, info: FscryptDirInfo) -> Self {
792 match self {
793 DirType::Normal => DirType::Encrypted(info),
794 DirType::Casefold => DirType::EncryptedCasefold(info),
795 _ => self,
796 }
797 }
798
799 pub fn with_casefold(self, val: bool) -> Self {
800 match (val, self) {
801 (true, DirType::Encrypted(info) | DirType::EncryptedCasefold(info)) => {
802 DirType::EncryptedCasefold(info)
803 }
804 (true, _) => DirType::Casefold,
805 (false, DirType::Encrypted(info) | DirType::EncryptedCasefold(info)) => {
806 DirType::Encrypted(info)
807 }
808 (false, _) => DirType::Normal,
809 }
810 }
811
812 pub fn wrapping_key_id(&self) -> Option<WrappingKeyId> {
813 match self {
814 DirType::Encrypted(info) | DirType::EncryptedCasefold(info) => {
815 Some(info.wrapping_key_id)
816 }
817 _ => None,
818 }
819 }
820
821 pub fn fscrypt_info(&self) -> Option<FscryptDirInfo> {
822 match self {
823 DirType::Encrypted(info) | DirType::EncryptedCasefold(info) => Some(*info),
824 _ => None,
825 }
826 }
827
828 pub fn fscrypt_policy(&self) -> Option<fidl_fuchsia_io::FscryptPolicy> {
829 self.fscrypt_info().map(Into::into)
830 }
831}
832
833impl Default for DirType {
834 fn default() -> Self {
835 DirType::Normal
836 }
837}
838
839#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
840#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
841pub enum ObjectKindV62 {
842 File {
843 refs: u64,
845 },
846 Directory {
847 sub_dirs: u64,
849 dir_type: DirType,
851 },
852 Graveyard,
853 Symlink {
854 refs: u64,
856 #[serde(with = "crate::zerocopy_serialization")]
859 link: Box<[u8]>,
860 },
861 EncryptedSymlink {
862 refs: u64,
864 #[serde(with = "crate::zerocopy_serialization")]
869 link: Box<[u8]>,
870 },
871 NonInlineSymlink {
872 refs: u64,
874 },
875}
876
877#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint, Versioned)]
878#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
879pub enum ObjectKindV49 {
880 File {
881 refs: u64,
883 },
884 Directory {
885 sub_dirs: u64,
887 wrapping_key_id: Option<WrappingKeyId>,
890 casefold: bool,
893 },
894 Graveyard,
895 Symlink {
896 refs: u64,
898 #[serde(with = "crate::zerocopy_serialization")]
901 link: Box<[u8]>,
902 },
903 EncryptedSymlink {
904 refs: u64,
906 #[serde(with = "crate::zerocopy_serialization")]
911 link: Box<[u8]>,
912 },
913}
914
915pub type PosixAttributes = PosixAttributesV32;
918
919#[derive(Clone, Debug, Copy, Default, Serialize, Deserialize, PartialEq, TypeFingerprint)]
920#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
921pub struct PosixAttributesV32 {
922 pub mode: u32,
924 pub uid: u32,
926 pub gid: u32,
928 pub rdev: u64,
930}
931
932pub type ObjectAttributes = ObjectAttributesV49;
936
937#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, TypeFingerprint)]
938#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
939pub struct ObjectAttributesV49 {
940 pub creation_time: TimestampV49,
942 pub modification_time: TimestampV49,
944 #[serde(with = "crate::object_store::project_id::optional_project_id")]
946 pub project_id: Option<ProjectId>,
947 pub posix_attributes: Option<PosixAttributesV32>,
949 pub allocated_size: u64,
951 pub access_time: TimestampV49,
953 pub change_time: TimestampV49,
955}
956
957pub type ExtendedAttributeValue = ExtendedAttributeValueV32;
958
959#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
960#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
961pub enum ExtendedAttributeValueV32 {
962 Inline(#[serde(with = "crate::zerocopy_serialization")] Vec<u8>),
965 AttributeId(AttributeId),
968}
969
970pub type ChildValue = ChildValueV32;
972
973#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint, Versioned)]
974#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
975pub struct ChildValueV32 {
976 pub object_id: u64,
978 pub object_descriptor: ObjectDescriptorV32,
980}
981
982pub type RootDigest = RootDigestV33;
983
984#[derive(
985 Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize, TypeFingerprint,
986)]
987#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
988pub enum RootDigestV33 {
989 Sha256([u8; 32]),
990 Sha512(#[serde(with = "crate::zerocopy_serialization")] Vec<u8>),
991}
992
993pub type FsverityMetadata = FsverityMetadataV50;
994
995#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TypeFingerprint, Versioned)]
996#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
997pub enum FsverityMetadataV50 {
998 Internal(RootDigestV33, #[serde(with = "crate::zerocopy_serialization")] Vec<u8>),
1000 F2fs(std::ops::Range<u64>),
1002}
1003
1004pub type EncryptionKey = EncryptionKeyV59;
1005pub type EncryptionKeyV59 = fxfs_crypto::EncryptionKey;
1006
1007pub type EncryptionKeys = EncryptionKeysV59;
1008
1009#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint)]
1010#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
1011pub struct EncryptionKeysV59(pub(super) Vec<(u64, EncryptionKeyV59)>);
1012
1013impl EncryptionKeys {
1014 pub fn get(&self, id: u64) -> Option<&EncryptionKey> {
1015 self.0.iter().find_map(|(i, key)| (*i == id).then_some(key))
1016 }
1017
1018 pub fn insert(&mut self, id: u64, key: EncryptionKey) {
1019 self.0.push((id, key))
1020 }
1021
1022 pub fn remove(&mut self, id: u64) -> Option<EncryptionKey> {
1023 if let Some(ix) = self.0.iter().position(|(k, _)| *k == id) {
1024 Some(self.0.remove(ix).1)
1025 } else {
1026 None
1027 }
1028 }
1029}
1030
1031impl From<EncryptionKeys> for BTreeMap<u64, WrappedKey> {
1032 fn from(keys: EncryptionKeys) -> Self {
1033 keys.0.into_iter().map(|(id, key)| (id, key.into())).collect()
1034 }
1035}
1036
1037impl From<Vec<(u64, EncryptionKey)>> for EncryptionKeys {
1038 fn from(value: Vec<(u64, EncryptionKey)>) -> Self {
1039 Self(value)
1040 }
1041}
1042
1043impl std::ops::Deref for EncryptionKeys {
1044 type Target = Vec<(u64, EncryptionKey)>;
1045 fn deref(&self) -> &Self::Target {
1046 &self.0
1047 }
1048}
1049
1050pub type ObjectValue = ObjectValueV62;
1054impl Value for ObjectValue {
1055 const DELETED_MARKER: Self = Self::None;
1056}
1057
1058#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint, Versioned)]
1059#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
1060pub enum ObjectValueV62 {
1061 None,
1065 Some,
1068 Object { kind: ObjectKindV62, attributes: ObjectAttributesV49 },
1070 Keys(EncryptionKeysV59),
1072 Attribute { size: u64, has_overwrite_extents: bool },
1074 Extent(ExtentValueV38),
1076 Child(ChildValue),
1078 Trim,
1082 BytesAndNodes { bytes: i64, nodes: i64 },
1084 ExtendedAttribute(ExtendedAttributeValueV32),
1087 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV50 },
1090}
1091
1092#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
1094pub struct BytesAndNodes {
1095 pub bytes: i64,
1096 pub nodes: i64,
1097}
1098
1099impl BytesAndNodes {
1100 pub fn is_zero(&self) -> bool {
1101 self.bytes == 0 && self.nodes == 0
1102 }
1103}
1104
1105impl std::ops::Add for BytesAndNodes {
1106 type Output = Self;
1107 fn add(self, rhs: Self) -> Self {
1108 Self { bytes: self.bytes + rhs.bytes, nodes: self.nodes + rhs.nodes }
1109 }
1110}
1111
1112impl std::ops::AddAssign for BytesAndNodes {
1113 fn add_assign(&mut self, rhs: Self) {
1114 self.bytes += rhs.bytes;
1115 self.nodes += rhs.nodes;
1116 }
1117}
1118
1119impl From<BytesAndNodes> for ObjectValue {
1120 fn from(value: BytesAndNodes) -> Self {
1121 ObjectValue::BytesAndNodes { bytes: value.bytes, nodes: value.nodes }
1122 }
1123}
1124
1125impl From<(i64, i64)> for BytesAndNodes {
1126 fn from((bytes, nodes): (i64, i64)) -> Self {
1127 Self { bytes, nodes }
1128 }
1129}
1130
1131impl From<BytesAndNodes> for (i64, i64) {
1132 fn from(value: BytesAndNodes) -> Self {
1133 (value.bytes, value.nodes)
1134 }
1135}
1136
1137impl ObjectValue {
1138 pub fn file(
1140 refs: u64,
1141 allocated_size: u64,
1142 creation_time: Timestamp,
1143 modification_time: Timestamp,
1144 access_time: Timestamp,
1145 change_time: Timestamp,
1146 project_id: Option<ProjectId>,
1147 posix_attributes: Option<PosixAttributes>,
1148 ) -> ObjectValue {
1149 ObjectValue::Object {
1150 kind: ObjectKind::File { refs },
1151 attributes: ObjectAttributes {
1152 creation_time,
1153 modification_time,
1154 project_id,
1155 posix_attributes,
1156 allocated_size,
1157 access_time,
1158 change_time,
1159 },
1160 }
1161 }
1162 pub fn keys(encryption_keys: EncryptionKeys) -> ObjectValue {
1163 ObjectValue::Keys(encryption_keys)
1164 }
1165 pub fn attribute(size: u64, has_overwrite_extents: bool) -> ObjectValue {
1167 ObjectValue::Attribute { size, has_overwrite_extents }
1168 }
1169 pub fn verified_attribute(size: u64, fsverity_metadata: FsverityMetadata) -> ObjectValue {
1171 ObjectValue::VerifiedAttribute { size, fsverity_metadata }
1172 }
1173 pub fn extent(device_offset: u64, key_id: u64) -> ObjectValue {
1175 ObjectValue::Extent(ExtentValue::new_raw(device_offset, key_id))
1176 }
1177 pub fn extent_with_checksum(
1179 device_offset: u64,
1180 checksum: Checksums,
1181 key_id: u64,
1182 ) -> ObjectValue {
1183 ObjectValue::Extent(ExtentValue::with_checksum(device_offset, checksum, key_id))
1184 }
1185 pub fn deleted_extent() -> ObjectValue {
1187 ObjectValue::Extent(ExtentValue::deleted_extent())
1188 }
1189 pub fn child(object_id: u64, object_descriptor: ObjectDescriptor) -> ObjectValue {
1191 ObjectValue::Child(ChildValue { object_id, object_descriptor })
1192 }
1193 pub fn symlink(
1195 link: impl Into<Box<[u8]>>,
1196 creation_time: Timestamp,
1197 modification_time: Timestamp,
1198 project_id: Option<ProjectId>,
1199 ) -> ObjectValue {
1200 ObjectValue::Object {
1201 kind: ObjectKind::Symlink { refs: 1, link: link.into() },
1202 attributes: ObjectAttributes {
1203 creation_time,
1204 modification_time,
1205 project_id,
1206 ..Default::default()
1207 },
1208 }
1209 }
1210 pub fn encrypted_symlink(
1212 link: impl Into<Box<[u8]>>,
1213 creation_time: Timestamp,
1214 modification_time: Timestamp,
1215 project_id: Option<ProjectId>,
1216 ) -> ObjectValue {
1217 ObjectValue::Object {
1218 kind: ObjectKind::EncryptedSymlink { refs: 1, link: link.into() },
1219 attributes: ObjectAttributes {
1220 creation_time,
1221 modification_time,
1222 project_id,
1223 ..Default::default()
1224 },
1225 }
1226 }
1227 pub fn non_inline_symlink(
1230 creation_time: Timestamp,
1231 modification_time: Timestamp,
1232 project_id: Option<ProjectId>,
1233 ) -> ObjectValue {
1234 ObjectValue::Object {
1235 kind: ObjectKind::NonInlineSymlink { refs: 1 },
1236 attributes: ObjectAttributes {
1237 creation_time,
1238 modification_time,
1239 project_id,
1240 ..Default::default()
1241 },
1242 }
1243 }
1244 pub fn inline_extended_attribute(value: impl Into<Vec<u8>>) -> ObjectValue {
1245 ObjectValue::ExtendedAttribute(ExtendedAttributeValue::Inline(value.into()))
1246 }
1247 pub fn extended_attribute(attribute_id: AttributeId) -> ObjectValue {
1248 ObjectValue::ExtendedAttribute(ExtendedAttributeValue::AttributeId(attribute_id))
1249 }
1250}
1251
1252pub type ObjectItem = ObjectItemV62;
1253
1254pub type ObjectItemV62 = Item<ObjectKeyV54, ObjectValueV62>;
1255
1256impl ObjectItem {
1257 pub fn is_tombstone(&self) -> bool {
1258 matches!(
1259 self,
1260 Item {
1261 key: ObjectKey { data: ObjectKeyData::Object, .. },
1262 value: ObjectValue::None,
1263 ..
1264 }
1265 )
1266 }
1267}
1268
1269impl<'a> From<ItemRef<'a, ObjectKey, ObjectValue>>
1271 for Option<(u64, AttributeId, &'a Extent, &'a ExtentValue)>
1272{
1273 fn from(item: ItemRef<'a, ObjectKey, ObjectValue>) -> Self {
1274 match item {
1275 ItemRef {
1276 key:
1277 ObjectKey {
1278 object_id,
1279 data:
1280 ObjectKeyData::Attribute(
1281 attribute_id, AttributeKey::Extent(extent_key),
1283 ),
1284 },
1285 value: ObjectValue::Extent(extent_value),
1286 ..
1287 } => Some((*object_id, *attribute_id, extent_key, extent_value)),
1288 _ => None,
1289 }
1290 }
1291}
1292
1293pub type FxfsKey = FxfsKeyV49;
1294pub type FxfsKeyV49 = fxfs_crypto::FxfsKey;
1295
1296#[derive(
1297 Clone,
1298 Copy,
1299 PartialEq,
1300 Eq,
1301 PartialOrd,
1302 Ord,
1303 Debug,
1304 Serialize,
1305 Deserialize,
1306 Hash,
1307 SerializeKey,
1308 TypeFingerprint,
1309)]
1310#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
1311#[repr(transparent)]
1312pub struct AttributeId(pub u64);
1313
1314impl AttributeId {
1315 pub const DATA: Self = Self(0);
1317
1318 pub const BLOB_METADATA: Self = Self(3);
1321
1322 pub const BLOB_MERKLE: Self = Self(1);
1325
1326 pub const FSVERITY_MERKLE: Self = Self(2);
1329
1330 pub const PROFILE_RECORDING: Self = Self(4);
1332
1333 pub const XATTR_RANGE_START: Self = Self(64);
1340 pub const XATTR_RANGE_END: Self = Self(512);
1341
1342 pub const SORTED_START: Self = Self(0);
1346
1347 #[cfg(test)]
1349 pub const TEST_ID: Self = Self(u64::MAX - 1000);
1350
1351 pub const fn raw(self) -> u64 {
1352 self.0
1353 }
1354
1355 pub const fn next(self) -> Self {
1357 Self(self.0 + 1)
1358 }
1359
1360 pub const fn is_xattr(self) -> bool {
1362 self.0 >= Self::XATTR_RANGE_START.0 && self.0 < Self::XATTR_RANGE_END.0
1363 }
1364}
1365
1366impl log::kv::ToValue for AttributeId {
1367 fn to_value(&self) -> log::kv::Value<'_> {
1368 log::kv::Value::from(self.0)
1369 }
1370}
1371
1372impl std::fmt::Display for AttributeId {
1373 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1374 std::fmt::Display::fmt(&self.0, f)
1375 }
1376}
1377
1378#[cfg(test)]
1379mod tests {
1380 use super::{AttributeId, ObjectKey, ObjectKeyV54, TimestampV49};
1381 use crate::lsm_tree::types::{FuzzyHash as _, LayerKey};
1382 use crate::object_store::extent::MIN_BLOCK_SIZE;
1383 use std::ops::Add;
1384 use std::time::{Duration, SystemTime, UNIX_EPOCH};
1385
1386 #[test]
1391 fn test_hash_stability() {
1392 assert_eq!(
1396 &ObjectKeyV54::object(100).fuzzy_hash().collect::<Vec<_>>()[..],
1397 &[11885326717398844384]
1398 );
1399 assert_eq!(
1400 &ObjectKeyV54::extent(1, AttributeId::DATA, 0..2 * 1024 * 1024)
1401 .fuzzy_hash()
1402 .collect::<Vec<_>>()[..],
1403 &[11090579907097549012, 2814892992701560424]
1404 );
1405 }
1406
1407 #[test]
1408 fn test_fuzzy_hash_len() {
1409 let key = ObjectKey::object(100);
1410 let mut iter = key.fuzzy_hash();
1411 assert_eq!(iter.len(), 1);
1412 assert_eq!(iter.size_hint(), (1, Some(1)));
1413 assert!(iter.next().is_some());
1414 assert_eq!(iter.len(), 0);
1415 assert_eq!(iter.size_hint(), (0, Some(0)));
1416 assert_eq!(iter.next(), None);
1417
1418 let key = ObjectKey::extent(1, AttributeId::DATA, 0..2 * 1024 * 1024);
1419 let mut iter = key.fuzzy_hash();
1420 assert_eq!(iter.len(), 2);
1421 assert_eq!(iter.size_hint(), (2, Some(2)));
1422 assert!(iter.next().is_some());
1423 assert_eq!(iter.len(), 1);
1424 assert_eq!(iter.size_hint(), (1, Some(1)));
1425 assert!(iter.next().is_some());
1426 assert_eq!(iter.len(), 0);
1427 assert_eq!(iter.size_hint(), (0, Some(0)));
1428 assert_eq!(iter.next(), None);
1429 }
1430
1431 #[test]
1432 fn test_next_key() {
1433 assert_eq!(
1434 ObjectKey::extent(1, AttributeId::TEST_ID, 25 * MIN_BLOCK_SIZE..100 * MIN_BLOCK_SIZE)
1435 .next_key()
1436 .unwrap(),
1437 ObjectKey::extent(1, AttributeId::TEST_ID, 100 * MIN_BLOCK_SIZE..101 * MIN_BLOCK_SIZE)
1438 );
1439 assert_eq!(ObjectKey::object(100).next_key(), None);
1440 }
1441
1442 #[test]
1443 fn test_range_key() {
1444 const ATTR_ID: AttributeId = AttributeId::TEST_ID;
1445 assert!(ObjectKey::extent(1, ATTR_ID, 0..2 * 1024 * 1024).is_range_key());
1448 assert!(!ObjectKey::object(100).is_range_key());
1449
1450 assert_eq!(ObjectKey::object(1).overlaps(&ObjectKey::object(1)), true);
1451 assert_eq!(ObjectKey::object(1).overlaps(&ObjectKey::object(2)), false);
1452 assert_eq!(ObjectKey::extent(1, ATTR_ID, 0..100).overlaps(&ObjectKey::object(1)), false);
1453 assert_eq!(ObjectKey::object(1).overlaps(&ObjectKey::extent(1, ATTR_ID, 0..100)), false);
1454 assert_eq!(
1455 ObjectKey::extent(1, ATTR_ID, 0..100).overlaps(&ObjectKey::extent(2, ATTR_ID, 0..100)),
1456 false
1457 );
1458 assert_eq!(
1459 ObjectKey::extent(1, ATTR_ID, 0..100).overlaps(&ObjectKey::extent(
1460 1,
1461 ATTR_ID.next(),
1462 0..100
1463 )),
1464 false
1465 );
1466 assert_eq!(
1467 ObjectKey::extent(1, ATTR_ID, 0..100).overlaps(&ObjectKey::extent(1, ATTR_ID, 0..100)),
1468 true
1469 );
1470
1471 assert_eq!(
1472 ObjectKey::extent(1, ATTR_ID, 0..50).overlaps(&ObjectKey::extent(1, ATTR_ID, 49..100)),
1473 true
1474 );
1475 assert_eq!(
1476 ObjectKey::extent(1, ATTR_ID, 49..100).overlaps(&ObjectKey::extent(1, ATTR_ID, 0..50)),
1477 true
1478 );
1479
1480 assert_eq!(
1481 ObjectKey::extent(1, ATTR_ID, 0..50).overlaps(&ObjectKey::extent(1, ATTR_ID, 50..100)),
1482 false
1483 );
1484 assert_eq!(
1485 ObjectKey::extent(1, ATTR_ID, 50..100).overlaps(&ObjectKey::extent(1, ATTR_ID, 0..50)),
1486 false
1487 );
1488 }
1489
1490 #[test]
1491 fn test_timestamp() {
1492 fn compare_time(std_time: Duration) {
1493 let ts_time: TimestampV49 = std_time.into();
1494 assert_eq!(<TimestampV49 as Into<Duration>>::into(ts_time), std_time);
1495 assert_eq!(ts_time.subsec_nanos(), std_time.subsec_nanos());
1496 assert_eq!(ts_time.as_secs(), std_time.as_secs());
1497 assert_eq!(ts_time.as_nanos() as u128, std_time.as_nanos());
1498 }
1499 compare_time(Duration::from_nanos(0));
1500 compare_time(Duration::from_nanos(u64::MAX));
1501 compare_time(SystemTime::now().duration_since(UNIX_EPOCH).unwrap());
1502
1503 let ts: TimestampV49 = Duration::from_secs(u64::MAX - 1).into();
1504 assert_eq!(ts.nanos, u64::MAX);
1505
1506 let ts: TimestampV49 = (Duration::from_nanos(u64::MAX).add(Duration::from_nanos(1))).into();
1507 assert_eq!(ts.nanos, u64::MAX);
1508 }
1509
1510 #[test]
1511 fn test_legacy_fxfs_key_decoding_fails() {
1512 use fxfs_crypto::{EncryptionKey, FXFS_WRAPPED_KEY_SIZE, FxfsKey, WrappedKeyBytes};
1513
1514 let key = EncryptionKey::LegacyFxfs(FxfsKey {
1515 wrapping_key_id: [1; 16],
1516 key: WrappedKeyBytes([2; FXFS_WRAPPED_KEY_SIZE]),
1517 });
1518 let mut buf = Vec::new();
1519 bincode::serialize_into(&mut buf, &key).expect("serialize succeeds");
1520 assert!(bincode::deserialize::<EncryptionKey>(&buf).is_err());
1521 }
1522}