1use super::*;
8use fxfs_crypto::WrappedKeyBytes;
9
10impl From<ObjectKeyDataV43> for ObjectKeyDataV54 {
11 fn from(item: ObjectKeyDataV43) -> Self {
12 match item {
13 ObjectKeyDataV43::Object => Self::Object,
14 ObjectKeyDataV43::Keys => Self::Keys,
15 ObjectKeyDataV43::Attribute(a, b) => Self::Attribute(a, b),
16 ObjectKeyDataV43::Child { name } => Self::Child { name },
17 ObjectKeyDataV43::GraveyardEntry { object_id } => Self::GraveyardEntry { object_id },
18 ObjectKeyDataV43::Project { project_id, property } => {
19 Self::Project { project_id, property }
20 }
21 ObjectKeyDataV43::ExtendedAttribute { name } => Self::ExtendedAttribute { name },
22 ObjectKeyDataV43::GraveyardAttributeEntry { object_id, attribute_id } => {
23 Self::GraveyardAttributeEntry { object_id, attribute_id }
24 }
25 ObjectKeyDataV43::EncryptedCasefoldChild(c) => Self::EncryptedCasefoldChild(c),
26 ObjectKeyDataV43::CasefoldChild { name } => Self::LegacyCasefoldChild(name),
27 ObjectKeyDataV43::EncryptedChild(c) => Self::EncryptedChild(c),
28 }
29 }
30}
31
32#[derive(Serialize, Deserialize, TypeFingerprint)]
33pub enum ObjectKeyDataV43 {
34 Object,
35 Keys,
36 Attribute(AttributeId, AttributeKeyV32),
37 Child {
38 name: String,
39 },
40 GraveyardEntry {
41 object_id: u64,
42 },
43 Project {
44 project_id: ProjectId,
45 property: ProjectPropertyV32,
46 },
47 ExtendedAttribute {
48 #[serde(with = "crate::zerocopy_serialization")]
49 name: Vec<u8>,
50 },
51 GraveyardAttributeEntry {
52 object_id: u64,
53 attribute_id: AttributeId,
54 },
55 EncryptedCasefoldChild(EncryptedCasefoldChild),
56 CasefoldChild {
57 name: CasefoldString,
58 },
59 EncryptedChild(EncryptedChild),
60}
61
62#[derive(Migrate, Serialize, Deserialize, TypeFingerprint, Versioned)]
63#[migrate_to_version(ObjectKeyV54)]
64#[migrate_nodefault]
65pub struct ObjectKeyV43 {
66 pub object_id: u64,
67 pub data: ObjectKeyDataV43,
68}
69
70impl From<ObjectKeyDataV40> for ObjectKeyDataV43 {
71 fn from(item: ObjectKeyDataV40) -> Self {
72 match item {
73 ObjectKeyDataV40::Object => Self::Object,
74 ObjectKeyDataV40::Keys => Self::Keys,
75 ObjectKeyDataV40::Attribute(a, b) => Self::Attribute(a, b),
76 ObjectKeyDataV40::Child { name } => Self::Child { name },
77 ObjectKeyDataV40::GraveyardEntry { object_id } => Self::GraveyardEntry { object_id },
78 ObjectKeyDataV40::Project { project_id, property } => {
79 Self::Project { project_id, property }
80 }
81 ObjectKeyDataV40::ExtendedAttribute { name } => Self::ExtendedAttribute { name },
82 ObjectKeyDataV40::GraveyardAttributeEntry { object_id, attribute_id } => {
83 Self::GraveyardAttributeEntry { object_id, attribute_id }
84 }
85 ObjectKeyDataV40::EncryptedChild { name } => {
86 Self::EncryptedCasefoldChild(EncryptedCasefoldChild { hash_code: 0, name })
87 }
88 ObjectKeyDataV40::CasefoldChild { name } => Self::CasefoldChild { name },
89 }
90 }
91}
92
93#[derive(Serialize, Deserialize, TypeFingerprint)]
94pub enum ObjectKeyDataV40 {
95 Object,
96 Keys,
97 Attribute(AttributeId, AttributeKeyV32),
98 Child { name: String },
99 GraveyardEntry { object_id: u64 },
100 Project { project_id: ProjectId, property: ProjectPropertyV32 },
101 ExtendedAttribute { name: Vec<u8> },
102 GraveyardAttributeEntry { object_id: u64, attribute_id: AttributeId },
103 EncryptedChild { name: Vec<u8> },
104 CasefoldChild { name: CasefoldString },
105}
106
107#[derive(Migrate, Serialize, Deserialize, TypeFingerprint, Versioned)]
108#[migrate_to_version(ObjectKeyV43)]
109#[migrate_nodefault]
110pub struct ObjectKeyV40 {
111 pub object_id: u64,
112 pub data: ObjectKeyDataV40,
113}
114
115impl From<ObjectKindV49> for ObjectKindV54 {
116 fn from(kind: ObjectKindV49) -> Self {
117 match kind {
118 ObjectKindV49::File { refs } => ObjectKindV54::File { refs },
119 ObjectKindV49::Directory { sub_dirs, wrapping_key_id, casefold } => {
120 let dir_type = match (casefold, wrapping_key_id) {
121 (true, Some(id)) => DirType::EncryptedCasefold(id),
122 (true, None) => DirType::LegacyCasefold, (false, Some(id)) => DirType::Encrypted(id),
124 (false, None) => DirType::Normal,
125 };
126 ObjectKindV54::Directory { sub_dirs, dir_type }
127 }
128 ObjectKindV49::Graveyard => ObjectKindV54::Graveyard,
129 ObjectKindV49::Symlink { refs, link } => ObjectKindV54::Symlink { refs, link },
130 ObjectKindV49::EncryptedSymlink { refs, link } => {
131 ObjectKindV54::EncryptedSymlink { refs, link }
132 }
133 }
134 }
135}
136
137impl From<ObjectKindV46> for ObjectKindV49 {
138 fn from(value: ObjectKindV46) -> Self {
139 match value {
140 ObjectKindV46::File { refs } => Self::File { refs },
141 ObjectKindV46::Directory { sub_dirs, wrapping_key_id, casefold } => Self::Directory {
142 sub_dirs,
143 wrapping_key_id: wrapping_key_id.map(u128::to_le_bytes),
144 casefold,
145 },
146 ObjectKindV46::Graveyard => Self::Graveyard,
147 ObjectKindV46::Symlink { refs, link } => Self::Symlink { refs, link: link.into() },
148 ObjectKindV46::EncryptedSymlink { refs, link } => {
149 Self::EncryptedSymlink { refs, link: link.into() }
150 }
151 }
152 }
153}
154
155#[derive(Serialize, Deserialize, TypeFingerprint)]
156pub enum ObjectKindV46 {
157 File { refs: u64 },
158 Directory { sub_dirs: u64, wrapping_key_id: Option<u128>, casefold: bool },
159 Graveyard,
160 Symlink { refs: u64, link: Vec<u8> },
161 EncryptedSymlink { refs: u64, link: Vec<u8> },
162}
163
164#[derive(Migrate, Serialize, Deserialize, TypeFingerprint)]
165#[migrate_to_version(ObjectKindV46)]
166pub enum ObjectKindV41 {
167 File { refs: u64 },
168 Directory { sub_dirs: u64, wrapping_key_id: Option<u128>, casefold: bool },
169 Graveyard,
170 Symlink { refs: u64, link: Vec<u8> },
171}
172
173#[derive(Serialize, Deserialize, TypeFingerprint)]
174pub enum ObjectKindV40 {
175 File { refs: u64, has_overwrite_extents: bool },
176 Directory { sub_dirs: u64, wrapping_key_id: Option<u128>, casefold: bool },
177 Graveyard,
178 Symlink { refs: u64, link: Vec<u8> },
179}
180
181impl From<ObjectKindV40> for ObjectKindV41 {
182 fn from(value: ObjectKindV40) -> Self {
183 match value {
184 ObjectKindV40::File { refs, .. } => ObjectKindV41::File { refs },
186 ObjectKindV40::Directory { sub_dirs, wrapping_key_id, casefold } => {
187 ObjectKindV41::Directory { sub_dirs, wrapping_key_id, casefold }
188 }
189 ObjectKindV40::Graveyard => ObjectKindV41::Graveyard,
190 ObjectKindV40::Symlink { refs, link } => ObjectKindV41::Symlink { refs, link },
191 }
192 }
193}
194
195#[derive(Serialize, Deserialize, TypeFingerprint, Versioned)]
196pub struct FsverityMetadataV33 {
197 pub root_digest: RootDigestV33,
198 pub salt: Vec<u8>,
199}
200
201impl From<FsverityMetadataV33> for FsverityMetadataV50 {
202 fn from(value: FsverityMetadataV33) -> Self {
203 Self::Internal(value.root_digest, value.salt)
204 }
205}
206
207#[derive(Serialize, Deserialize, TypeFingerprint)]
208pub struct FxfsKeyV40 {
209 pub wrapping_key_id: u128,
210 pub key: WrappedKeyBytes,
211}
212
213impl From<FxfsKeyV40> for FxfsKeyV49 {
214 fn from(value: FxfsKeyV40) -> Self {
215 Self { wrapping_key_id: value.wrapping_key_id.to_le_bytes(), key: value.key }
216 }
217}
218
219#[derive(Migrate, Serialize, Deserialize, TypeFingerprint)]
220#[migrate_to_version(EncryptionKeyV49)]
221pub enum EncryptionKeyV47 {
222 Fxfs(FxfsKeyV40),
223 FscryptInoLblk32File { key_identifier: [u8; 16] },
224 FscryptInoLblk32Dir { key_identifier: [u8; 16], nonce: [u8; 16] },
225}
226
227#[derive(Serialize, Deserialize, TypeFingerprint)]
228pub struct EncryptionKeysV47(Vec<(u64, EncryptionKeyV47)>);
229
230impl From<EncryptionKeysV47> for EncryptionKeysV49 {
231 fn from(value: EncryptionKeysV47) -> Self {
232 Self(value.0.into_iter().map(|(id, key)| (id, key.into())).collect())
233 }
234}
235
236#[derive(Serialize, Deserialize, TypeFingerprint)]
237pub enum EncryptionKeysV40 {
238 AES256XTS(WrappedKeysV40),
239}
240
241impl From<EncryptionKeysV40> for EncryptionKeysV47 {
242 fn from(EncryptionKeysV40::AES256XTS(WrappedKeysV40(keys)): EncryptionKeysV40) -> Self {
243 EncryptionKeysV47(
244 keys.into_iter().map(|(id, key)| (id, EncryptionKeyV47::Fxfs(key))).collect(),
245 )
246 }
247}
248
249#[derive(Serialize, Deserialize, TypeFingerprint)]
250pub struct WrappedKeysV40(pub Vec<(u64, FxfsKeyV40)>);
251
252#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint)]
253#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
254pub enum EncryptionKeyV49 {
255 Fxfs(fxfs_crypto::FxfsKey),
256 FscryptInoLblk32File { key_identifier: [u8; 16] },
257 FscryptInoLblk32Dir { key_identifier: [u8; 16], nonce: [u8; 16] },
258}
259
260impl From<EncryptionKeyV49> for EncryptionKeyV56 {
261 fn from(old: EncryptionKeyV49) -> Self {
262 match old {
263 EncryptionKeyV49::Fxfs(key) => EncryptionKeyV56::LegacyFxfs(key),
264 EncryptionKeyV49::FscryptInoLblk32File { key_identifier } => {
265 EncryptionKeyV56::FscryptInoLblk32File { key_identifier }
266 }
267 EncryptionKeyV49::FscryptInoLblk32Dir { key_identifier, nonce } => {
268 EncryptionKeyV56::FscryptInoLblk32Dir { key_identifier, nonce }
269 }
270 }
271 }
272}
273
274#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint)]
275#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
276pub struct EncryptionKeysV49(Vec<(u64, EncryptionKeyV49)>);
277
278impl From<EncryptionKeysV49> for EncryptionKeysV56 {
279 fn from(old: EncryptionKeysV49) -> Self {
280 Self(old.0.into_iter().map(|(id, key)| (id, key.into())).collect())
281 }
282}
283
284#[derive(Migrate, Clone, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint, Versioned)]
285#[migrate_to_version(ObjectValueV56)]
286#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
287pub enum ObjectValueV54 {
288 None,
289 Some,
290 Object { kind: ObjectKindV54, attributes: ObjectAttributesV49 },
291 Keys(EncryptionKeysV49),
292 Attribute { size: u64, has_overwrite_extents: bool },
293 Extent(ExtentValueV38),
294 Child(ChildValue),
295 Trim,
296 BytesAndNodes { bytes: i64, nodes: i64 },
297 ExtendedAttribute(ExtendedAttributeValueV32),
298 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV50 },
299}
300
301#[derive(Migrate, Serialize, Deserialize, TypeFingerprint, Versioned)]
302#[migrate_to_version(ObjectValueV50)]
303pub enum ObjectValueV49 {
304 None,
305 Some,
306 Object { kind: ObjectKindV49, attributes: ObjectAttributesV49 },
307 Keys(EncryptionKeysV49),
308 Attribute { size: u64, has_overwrite_extents: bool },
309 Extent(ExtentValueV38),
310 Child(ChildValueV32),
311 Trim,
312 BytesAndNodes { bytes: i64, nodes: i64 },
313 ExtendedAttribute(ExtendedAttributeValueV32),
314 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV33 },
315}
316
317#[derive(Migrate, Serialize, Deserialize, TypeFingerprint, Versioned)]
318#[migrate_to_version(ObjectValueV49)]
319pub enum ObjectValueV47 {
320 None,
321 Some,
322 Object { kind: ObjectKindV46, attributes: ObjectAttributesV32 },
323 Keys(EncryptionKeysV47),
324 Attribute { size: u64, has_overwrite_extents: bool },
325 Extent(ExtentValueV38),
326 Child(ChildValueV32),
327 Trim,
328 BytesAndNodes { bytes: i64, nodes: i64 },
329 ExtendedAttribute(ExtendedAttributeValueV32),
330 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV33 },
331}
332
333#[derive(Migrate, Serialize, Deserialize, TypeFingerprint, Versioned)]
334#[migrate_to_version(ObjectValueV47)]
335pub enum ObjectValueV46 {
336 None,
337 Some,
338 Object { kind: ObjectKindV46, attributes: ObjectAttributesV32 },
339 Keys(EncryptionKeysV40),
340 Attribute { size: u64, has_overwrite_extents: bool },
341 Extent(ExtentValueV38),
342 Child(ChildValueV32),
343 Trim,
344 BytesAndNodes { bytes: i64, nodes: i64 },
345 ExtendedAttribute(ExtendedAttributeValueV32),
346 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV33 },
347}
348
349#[derive(Migrate, Serialize, Deserialize, TypeFingerprint, Versioned)]
350#[migrate_to_version(ObjectValueV46)]
351pub enum ObjectValueV41 {
352 None,
353 Some,
354 Object { kind: ObjectKindV41, attributes: ObjectAttributesV32 },
355 Keys(EncryptionKeysV40),
356 Attribute { size: u64, has_overwrite_extents: bool },
357 Extent(ExtentValueV38),
358 Child(ChildValueV32),
359 Trim,
360 BytesAndNodes { bytes: i64, nodes: i64 },
361 ExtendedAttribute(ExtendedAttributeValueV32),
362 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV33 },
363}
364
365impl From<ObjectValueV40> for ObjectValueV41 {
366 fn from(value: ObjectValueV40) -> Self {
367 match value {
368 ObjectValueV40::None => ObjectValueV41::None,
369 ObjectValueV40::Some => ObjectValueV41::Some,
370 ObjectValueV40::Object { kind, attributes } => {
371 ObjectValueV41::Object { kind: kind.into(), attributes }
372 }
373 ObjectValueV40::Keys(keys) => ObjectValueV41::Keys(keys),
374 ObjectValueV40::Attribute { size } => {
375 ObjectValueV41::Attribute { size, has_overwrite_extents: false }
376 }
377 ObjectValueV40::Extent(extent_value) => ObjectValueV41::Extent(extent_value),
378 ObjectValueV40::Child(child) => ObjectValueV41::Child(child),
379 ObjectValueV40::Trim => ObjectValueV41::Trim,
380 ObjectValueV40::BytesAndNodes { bytes, nodes } => {
381 ObjectValueV41::BytesAndNodes { bytes, nodes }
382 }
383 ObjectValueV40::ExtendedAttribute(xattr) => ObjectValueV41::ExtendedAttribute(xattr),
384 ObjectValueV40::VerifiedAttribute { size, fsverity_metadata } => {
385 ObjectValueV41::VerifiedAttribute { size, fsverity_metadata }
386 }
387 }
388 }
389}
390
391#[derive(Serialize, Deserialize, TypeFingerprint, Versioned)]
392pub enum ObjectValueV40 {
393 None,
394 Some,
395 Object { kind: ObjectKindV40, attributes: ObjectAttributesV32 },
396 Keys(EncryptionKeysV40),
397 Attribute { size: u64 },
398 Extent(ExtentValueV38),
399 Child(ChildValueV32),
400 Trim,
401 BytesAndNodes { bytes: i64, nodes: i64 },
402 ExtendedAttribute(ExtendedAttributeValueV32),
403 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV33 },
404}
405
406#[derive(Migrate, Serialize, Deserialize, TypeFingerprint)]
407#[migrate_to_version(ObjectAttributesV49)]
408pub struct ObjectAttributesV32 {
409 pub creation_time: TimestampV32,
410 pub modification_time: TimestampV32,
411 #[serde(with = "crate::object_store::project_id::optional_project_id")]
412 pub project_id: Option<ProjectId>,
413 pub posix_attributes: Option<PosixAttributesV32>,
414 pub allocated_size: u64,
415 pub access_time: TimestampV32,
416 pub change_time: TimestampV32,
417}
418
419impl From<TimestampV32> for TimestampV49 {
420 fn from(timestamp: TimestampV32) -> Self {
421 Self::from_secs_and_nanos(timestamp.secs, timestamp.nanos)
422 }
423}
424
425#[derive(Copy, Clone, Serialize, Deserialize, TypeFingerprint)]
426pub struct TimestampV32 {
427 pub secs: u64,
428 pub nanos: u32,
429}
430
431pub type ObjectItemV54 = LegacyItem<ObjectKeyV54, ObjectValueV54>;
432pub type ObjectItemV55 = Item<ObjectKeyV54, ObjectValueV54>;
433
434impl From<ObjectItemV54> for ObjectItemV55 {
435 fn from(item: ObjectItemV54) -> Self {
436 Self { key: item.key, value: item.value }
437 }
438}
439
440impl From<ObjectItemV55> for ObjectItemV56 {
441 fn from(item: ObjectItemV55) -> Self {
442 Self { key: item.key, value: item.value.into() }
443 }
444}
445
446pub type ObjectItemV49 = LegacyItem<ObjectKeyV43, ObjectValueV49>;
447pub type ObjectItemV47 = LegacyItem<ObjectKeyV43, ObjectValueV47>;
448pub type ObjectItemV46 = LegacyItem<ObjectKeyV43, ObjectValueV46>;
449pub type ObjectItemV43 = LegacyItem<ObjectKeyV43, ObjectValueV41>;
450pub type ObjectItemV41 = LegacyItem<ObjectKeyV40, ObjectValueV41>;
451pub type ObjectItemV40 = LegacyItem<ObjectKeyV40, ObjectValueV40>;
452
453impl From<ObjectItemV50> for ObjectItemV54 {
454 fn from(item: ObjectItemV50) -> Self {
455 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
456 }
457}
458
459impl From<ObjectItemV49> for ObjectItemV50 {
460 fn from(item: ObjectItemV49) -> Self {
461 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
462 }
463}
464impl From<ObjectItemV47> for ObjectItemV49 {
465 fn from(item: ObjectItemV47) -> Self {
466 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
467 }
468}
469impl From<ObjectItemV46> for ObjectItemV47 {
470 fn from(item: ObjectItemV46) -> Self {
471 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
472 }
473}
474impl From<ObjectItemV43> for ObjectItemV46 {
475 fn from(item: ObjectItemV43) -> Self {
476 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
477 }
478}
479impl From<ObjectItemV41> for ObjectItemV43 {
480 fn from(item: ObjectItemV41) -> Self {
481 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
482 }
483}
484impl From<ObjectItemV40> for ObjectItemV41 {
485 fn from(item: ObjectItemV40) -> Self {
486 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
487 }
488}
489
490#[cfg(test)]
491mod tests {
492 use super::*;
493
494 #[test]
495 fn test_timestamp_v32_to_v49() {
496 let v32 = TimestampV32 { secs: 100, nanos: 200 };
497 let v49: TimestampV49 = v32.into();
498 assert_eq!(v32.secs * 1_000_000_000 + v32.nanos as u64, v49.nanos);
499 }
500}