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