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(Migrate, Serialize, Deserialize, TypeFingerprint, Versioned)]
253#[migrate_to_version(ObjectValueV50)]
254pub enum ObjectValueV49 {
255 None,
256 Some,
257 Object { kind: ObjectKindV49, attributes: ObjectAttributesV49 },
258 Keys(EncryptionKeysV49),
259 Attribute { size: u64, has_overwrite_extents: bool },
260 Extent(ExtentValueV38),
261 Child(ChildValueV32),
262 Trim,
263 BytesAndNodes { bytes: i64, nodes: i64 },
264 ExtendedAttribute(ExtendedAttributeValueV32),
265 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV33 },
266}
267
268#[derive(Migrate, Serialize, Deserialize, TypeFingerprint, Versioned)]
269#[migrate_to_version(ObjectValueV49)]
270pub enum ObjectValueV47 {
271 None,
272 Some,
273 Object { kind: ObjectKindV46, attributes: ObjectAttributesV32 },
274 Keys(EncryptionKeysV47),
275 Attribute { size: u64, has_overwrite_extents: bool },
276 Extent(ExtentValueV38),
277 Child(ChildValueV32),
278 Trim,
279 BytesAndNodes { bytes: i64, nodes: i64 },
280 ExtendedAttribute(ExtendedAttributeValueV32),
281 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV33 },
282}
283
284#[derive(Migrate, Serialize, Deserialize, TypeFingerprint, Versioned)]
285#[migrate_to_version(ObjectValueV47)]
286pub enum ObjectValueV46 {
287 None,
288 Some,
289 Object { kind: ObjectKindV46, attributes: ObjectAttributesV32 },
290 Keys(EncryptionKeysV40),
291 Attribute { size: u64, has_overwrite_extents: bool },
292 Extent(ExtentValueV38),
293 Child(ChildValueV32),
294 Trim,
295 BytesAndNodes { bytes: i64, nodes: i64 },
296 ExtendedAttribute(ExtendedAttributeValueV32),
297 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV33 },
298}
299
300#[derive(Migrate, Serialize, Deserialize, TypeFingerprint, Versioned)]
301#[migrate_to_version(ObjectValueV46)]
302pub enum ObjectValueV41 {
303 None,
304 Some,
305 Object { kind: ObjectKindV41, attributes: ObjectAttributesV32 },
306 Keys(EncryptionKeysV40),
307 Attribute { size: u64, has_overwrite_extents: bool },
308 Extent(ExtentValueV38),
309 Child(ChildValueV32),
310 Trim,
311 BytesAndNodes { bytes: i64, nodes: i64 },
312 ExtendedAttribute(ExtendedAttributeValueV32),
313 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV33 },
314}
315
316impl From<ObjectValueV40> for ObjectValueV41 {
317 fn from(value: ObjectValueV40) -> Self {
318 match value {
319 ObjectValueV40::None => ObjectValueV41::None,
320 ObjectValueV40::Some => ObjectValueV41::Some,
321 ObjectValueV40::Object { kind, attributes } => {
322 ObjectValueV41::Object { kind: kind.into(), attributes }
323 }
324 ObjectValueV40::Keys(keys) => ObjectValueV41::Keys(keys),
325 ObjectValueV40::Attribute { size } => {
326 ObjectValueV41::Attribute { size, has_overwrite_extents: false }
327 }
328 ObjectValueV40::Extent(extent_value) => ObjectValueV41::Extent(extent_value),
329 ObjectValueV40::Child(child) => ObjectValueV41::Child(child),
330 ObjectValueV40::Trim => ObjectValueV41::Trim,
331 ObjectValueV40::BytesAndNodes { bytes, nodes } => {
332 ObjectValueV41::BytesAndNodes { bytes, nodes }
333 }
334 ObjectValueV40::ExtendedAttribute(xattr) => ObjectValueV41::ExtendedAttribute(xattr),
335 ObjectValueV40::VerifiedAttribute { size, fsverity_metadata } => {
336 ObjectValueV41::VerifiedAttribute { size, fsverity_metadata }
337 }
338 }
339 }
340}
341
342#[derive(Serialize, Deserialize, TypeFingerprint, Versioned)]
343pub enum ObjectValueV40 {
344 None,
345 Some,
346 Object { kind: ObjectKindV40, attributes: ObjectAttributesV32 },
347 Keys(EncryptionKeysV40),
348 Attribute { size: u64 },
349 Extent(ExtentValueV38),
350 Child(ChildValueV32),
351 Trim,
352 BytesAndNodes { bytes: i64, nodes: i64 },
353 ExtendedAttribute(ExtendedAttributeValueV32),
354 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV33 },
355}
356
357#[derive(Migrate, Serialize, Deserialize, TypeFingerprint)]
358#[migrate_to_version(ObjectAttributesV49)]
359pub struct ObjectAttributesV32 {
360 pub creation_time: TimestampV32,
361 pub modification_time: TimestampV32,
362 #[serde(with = "crate::object_store::project_id::optional_project_id")]
363 pub project_id: Option<ProjectId>,
364 pub posix_attributes: Option<PosixAttributesV32>,
365 pub allocated_size: u64,
366 pub access_time: TimestampV32,
367 pub change_time: TimestampV32,
368}
369
370impl From<TimestampV32> for TimestampV49 {
371 fn from(timestamp: TimestampV32) -> Self {
372 Self::from_secs_and_nanos(timestamp.secs, timestamp.nanos)
373 }
374}
375
376#[derive(Copy, Clone, Serialize, Deserialize, TypeFingerprint)]
377pub struct TimestampV32 {
378 pub secs: u64,
379 pub nanos: u32,
380}
381
382pub type ObjectItemV49 = LegacyItem<ObjectKeyV43, ObjectValueV49>;
383pub type ObjectItemV47 = LegacyItem<ObjectKeyV43, ObjectValueV47>;
384pub type ObjectItemV46 = LegacyItem<ObjectKeyV43, ObjectValueV46>;
385pub type ObjectItemV43 = LegacyItem<ObjectKeyV43, ObjectValueV41>;
386pub type ObjectItemV41 = LegacyItem<ObjectKeyV40, ObjectValueV41>;
387pub type ObjectItemV40 = LegacyItem<ObjectKeyV40, ObjectValueV40>;
388
389impl From<ObjectItemV50> for ObjectItemV54 {
390 fn from(item: ObjectItemV50) -> Self {
391 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
392 }
393}
394
395impl From<ObjectItemV49> for ObjectItemV50 {
396 fn from(item: ObjectItemV49) -> Self {
397 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
398 }
399}
400impl From<ObjectItemV47> for ObjectItemV49 {
401 fn from(item: ObjectItemV47) -> Self {
402 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
403 }
404}
405impl From<ObjectItemV46> for ObjectItemV47 {
406 fn from(item: ObjectItemV46) -> Self {
407 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
408 }
409}
410impl From<ObjectItemV43> for ObjectItemV46 {
411 fn from(item: ObjectItemV43) -> Self {
412 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
413 }
414}
415impl From<ObjectItemV41> for ObjectItemV43 {
416 fn from(item: ObjectItemV41) -> Self {
417 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
418 }
419}
420impl From<ObjectItemV40> for ObjectItemV41 {
421 fn from(item: ObjectItemV40) -> Self {
422 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
423 }
424}
425
426#[cfg(test)]
427mod tests {
428 use super::*;
429
430 #[test]
431 fn test_timestamp_v32_to_v49() {
432 let v32 = TimestampV32 { secs: 100, nanos: 200 };
433 let v49: TimestampV49 = v32.into();
434 assert_eq!(v32.secs * 1_000_000_000 + v32.nanos as u64, v49.nanos);
435 }
436}