1use super::*;
8use fxfs_crypto::WrappedKeyBytes;
9
10impl From<ObjectKeyDataV40> for ObjectKeyDataV43 {
11 fn from(item: ObjectKeyDataV40) -> Self {
12 match item {
13 ObjectKeyDataV40::Object => Self::Object,
14 ObjectKeyDataV40::Keys => Self::Keys,
15 ObjectKeyDataV40::Attribute(a, b) => Self::Attribute(a, b),
16 ObjectKeyDataV40::Child { name } => Self::Child { name },
17 ObjectKeyDataV40::GraveyardEntry { object_id } => Self::GraveyardEntry { object_id },
18 ObjectKeyDataV40::Project { project_id, property } => {
19 Self::Project { project_id, property }
20 }
21 ObjectKeyDataV40::ExtendedAttribute { name } => Self::ExtendedAttribute { name },
22 ObjectKeyDataV40::GraveyardAttributeEntry { object_id, attribute_id } => {
23 Self::GraveyardAttributeEntry { object_id, attribute_id }
24 }
25 ObjectKeyDataV40::EncryptedChild { name } => {
26 Self::EncryptedChild { hash_code: 0, name }
27 }
28 ObjectKeyDataV40::CasefoldChild { name } => Self::CasefoldChild { name },
29 }
30 }
31}
32
33#[derive(Serialize, Deserialize, TypeFingerprint)]
34#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
35pub enum ObjectKeyDataV40 {
36 Object,
37 Keys,
38 Attribute(u64, AttributeKeyV32),
39 Child { name: String },
40 GraveyardEntry { object_id: u64 },
41 Project { project_id: u64, property: ProjectPropertyV32 },
42 ExtendedAttribute { name: Vec<u8> },
43 GraveyardAttributeEntry { object_id: u64, attribute_id: u64 },
44 EncryptedChild { name: Vec<u8> },
45 CasefoldChild { name: CasefoldString },
46}
47
48#[derive(Migrate, Serialize, Deserialize, TypeFingerprint, Versioned)]
49#[migrate_to_version(ObjectKeyV43)]
50#[migrate_nodefault]
51pub struct ObjectKeyV40 {
52 pub object_id: u64,
53 pub data: ObjectKeyDataV40,
54}
55
56impl From<ObjectKindV46> for ObjectKindV49 {
57 fn from(value: ObjectKindV46) -> Self {
58 match value {
59 ObjectKindV46::File { refs } => Self::File { refs },
60 ObjectKindV46::Directory { sub_dirs, wrapping_key_id, casefold } => Self::Directory {
61 sub_dirs,
62 wrapping_key_id: wrapping_key_id.map(u128::to_le_bytes),
63 casefold,
64 },
65 ObjectKindV46::Graveyard => Self::Graveyard,
66 ObjectKindV46::Symlink { refs, link } => Self::Symlink { refs, link: link.into() },
67 ObjectKindV46::EncryptedSymlink { refs, link } => {
68 Self::EncryptedSymlink { refs, link: link.into() }
69 }
70 }
71 }
72}
73
74#[derive(Serialize, Deserialize, TypeFingerprint)]
75pub enum ObjectKindV46 {
76 File { refs: u64 },
77 Directory { sub_dirs: u64, wrapping_key_id: Option<u128>, casefold: bool },
78 Graveyard,
79 Symlink { refs: u64, link: Vec<u8> },
80 EncryptedSymlink { refs: u64, link: Vec<u8> },
81}
82
83#[derive(Migrate, Serialize, Deserialize, TypeFingerprint)]
84#[migrate_to_version(ObjectKindV46)]
85pub enum ObjectKindV41 {
86 File { refs: u64 },
87 Directory { sub_dirs: u64, wrapping_key_id: Option<u128>, casefold: bool },
88 Graveyard,
89 Symlink { refs: u64, link: Vec<u8> },
90}
91
92#[derive(Serialize, Deserialize, TypeFingerprint)]
93pub enum ObjectKindV40 {
94 File { refs: u64, has_overwrite_extents: bool },
95 Directory { sub_dirs: u64, wrapping_key_id: Option<u128>, casefold: bool },
96 Graveyard,
97 Symlink { refs: u64, link: Vec<u8> },
98}
99
100impl From<ObjectKindV40> for ObjectKindV41 {
101 fn from(value: ObjectKindV40) -> Self {
102 match value {
103 ObjectKindV40::File { refs, .. } => ObjectKindV41::File { refs },
105 ObjectKindV40::Directory { sub_dirs, wrapping_key_id, casefold } => {
106 ObjectKindV41::Directory { sub_dirs, wrapping_key_id, casefold }
107 }
108 ObjectKindV40::Graveyard => ObjectKindV41::Graveyard,
109 ObjectKindV40::Symlink { refs, link } => ObjectKindV41::Symlink { refs, link },
110 }
111 }
112}
113
114#[derive(Serialize, Deserialize, TypeFingerprint)]
115pub struct FxfsKeyV40 {
116 pub wrapping_key_id: u128,
117 pub key: WrappedKeyBytes,
118}
119
120impl From<FxfsKeyV40> for FxfsKeyV49 {
121 fn from(value: FxfsKeyV40) -> Self {
122 Self { wrapping_key_id: value.wrapping_key_id.to_le_bytes(), key: value.key }
123 }
124}
125
126#[derive(Migrate, Serialize, Deserialize, TypeFingerprint)]
127#[migrate_to_version(EncryptionKeyV49)]
128pub enum EncryptionKeyV47 {
129 Fxfs(FxfsKeyV40),
130 FscryptInoLblk32File { key_identifier: [u8; 16] },
131 FscryptInoLblk32Dir { key_identifier: [u8; 16], nonce: [u8; 16] },
132}
133
134#[derive(Serialize, Deserialize, TypeFingerprint)]
135pub struct EncryptionKeysV47(Vec<(u64, EncryptionKeyV47)>);
136
137impl From<EncryptionKeysV47> for EncryptionKeysV49 {
138 fn from(value: EncryptionKeysV47) -> Self {
139 Self(value.0.into_iter().map(|(id, key)| (id, key.into())).collect())
140 }
141}
142
143#[derive(Serialize, Deserialize, TypeFingerprint)]
144pub enum EncryptionKeysV40 {
145 AES256XTS(WrappedKeysV40),
146}
147
148impl From<EncryptionKeysV40> for EncryptionKeysV47 {
149 fn from(EncryptionKeysV40::AES256XTS(WrappedKeysV40(keys)): EncryptionKeysV40) -> Self {
150 EncryptionKeysV47(
151 keys.into_iter().map(|(id, key)| (id, EncryptionKeyV47::Fxfs(key))).collect(),
152 )
153 }
154}
155
156#[derive(Serialize, Deserialize, TypeFingerprint)]
157pub struct WrappedKeysV40(pub Vec<(u64, FxfsKeyV40)>);
158
159#[derive(Migrate, Serialize, Deserialize, TypeFingerprint, Versioned)]
160#[migrate_to_version(ObjectValueV49)]
161pub enum ObjectValueV47 {
162 None,
163 Some,
164 Object { kind: ObjectKindV46, attributes: ObjectAttributesV32 },
165 Keys(EncryptionKeysV47),
166 Attribute { size: u64, has_overwrite_extents: bool },
167 Extent(ExtentValueV38),
168 Child(ChildValueV32),
169 Trim,
170 BytesAndNodes { bytes: i64, nodes: i64 },
171 ExtendedAttribute(ExtendedAttributeValueV32),
172 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV33 },
173}
174
175#[derive(Migrate, Serialize, Deserialize, TypeFingerprint, Versioned)]
176#[migrate_to_version(ObjectValueV47)]
177pub enum ObjectValueV46 {
178 None,
179 Some,
180 Object { kind: ObjectKindV46, attributes: ObjectAttributesV32 },
181 Keys(EncryptionKeysV40),
182 Attribute { size: u64, has_overwrite_extents: bool },
183 Extent(ExtentValueV38),
184 Child(ChildValueV32),
185 Trim,
186 BytesAndNodes { bytes: i64, nodes: i64 },
187 ExtendedAttribute(ExtendedAttributeValueV32),
188 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV33 },
189}
190
191#[derive(Migrate, Serialize, Deserialize, TypeFingerprint, Versioned)]
192#[migrate_to_version(ObjectValueV46)]
193pub enum ObjectValueV41 {
194 None,
195 Some,
196 Object { kind: ObjectKindV41, attributes: ObjectAttributesV32 },
197 Keys(EncryptionKeysV40),
198 Attribute { size: u64, has_overwrite_extents: bool },
199 Extent(ExtentValueV38),
200 Child(ChildValueV32),
201 Trim,
202 BytesAndNodes { bytes: i64, nodes: i64 },
203 ExtendedAttribute(ExtendedAttributeValueV32),
204 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV33 },
205}
206
207impl From<ObjectValueV40> for ObjectValueV41 {
208 fn from(value: ObjectValueV40) -> Self {
209 match value {
210 ObjectValueV40::None => ObjectValueV41::None,
211 ObjectValueV40::Some => ObjectValueV41::Some,
212 ObjectValueV40::Object { kind, attributes } => {
213 ObjectValueV41::Object { kind: kind.into(), attributes }
214 }
215 ObjectValueV40::Keys(keys) => ObjectValueV41::Keys(keys),
216 ObjectValueV40::Attribute { size } => {
217 ObjectValueV41::Attribute { size, has_overwrite_extents: false }
218 }
219 ObjectValueV40::Extent(extent_value) => ObjectValueV41::Extent(extent_value),
220 ObjectValueV40::Child(child) => ObjectValueV41::Child(child),
221 ObjectValueV40::Trim => ObjectValueV41::Trim,
222 ObjectValueV40::BytesAndNodes { bytes, nodes } => {
223 ObjectValueV41::BytesAndNodes { bytes, nodes }
224 }
225 ObjectValueV40::ExtendedAttribute(xattr) => ObjectValueV41::ExtendedAttribute(xattr),
226 ObjectValueV40::VerifiedAttribute { size, fsverity_metadata } => {
227 ObjectValueV41::VerifiedAttribute { size, fsverity_metadata }
228 }
229 }
230 }
231}
232
233#[derive(Serialize, Deserialize, TypeFingerprint, Versioned)]
234pub enum ObjectValueV40 {
235 None,
236 Some,
237 Object { kind: ObjectKindV40, attributes: ObjectAttributesV32 },
238 Keys(EncryptionKeysV40),
239 Attribute { size: u64 },
240 Extent(ExtentValueV38),
241 Child(ChildValueV32),
242 Trim,
243 BytesAndNodes { bytes: i64, nodes: i64 },
244 ExtendedAttribute(ExtendedAttributeValueV32),
245 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV33 },
246}
247
248#[derive(Migrate, Serialize, Deserialize, TypeFingerprint)]
249#[migrate_to_version(ObjectAttributesV49)]
250pub struct ObjectAttributesV32 {
251 pub creation_time: TimestampV32,
252 pub modification_time: TimestampV32,
253 pub project_id: u64,
254 pub posix_attributes: Option<PosixAttributesV32>,
255 pub allocated_size: u64,
256 pub access_time: TimestampV32,
257 pub change_time: TimestampV32,
258}
259
260impl From<TimestampV32> for TimestampV49 {
261 fn from(timestamp: TimestampV32) -> Self {
262 Self::from_secs_and_nanos(timestamp.secs, timestamp.nanos)
263 }
264}
265
266#[derive(Copy, Clone, Serialize, Deserialize, TypeFingerprint)]
267pub struct TimestampV32 {
268 pub secs: u64,
269 pub nanos: u32,
270}
271
272pub type ObjectItemV47 = Item<ObjectKeyV43, ObjectValueV47>;
273pub type ObjectItemV46 = Item<ObjectKeyV43, ObjectValueV46>;
274pub type ObjectItemV43 = Item<ObjectKeyV43, ObjectValueV41>;
275pub type ObjectItemV41 = Item<ObjectKeyV40, ObjectValueV41>;
276pub type ObjectItemV40 = Item<ObjectKeyV40, ObjectValueV40>;
277
278impl From<ObjectItemV47> for ObjectItemV49 {
279 fn from(item: ObjectItemV47) -> Self {
280 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
281 }
282}
283impl From<ObjectItemV46> for ObjectItemV47 {
284 fn from(item: ObjectItemV46) -> Self {
285 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
286 }
287}
288impl From<ObjectItemV43> for ObjectItemV46 {
289 fn from(item: ObjectItemV43) -> Self {
290 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
291 }
292}
293impl From<ObjectItemV41> for ObjectItemV43 {
294 fn from(item: ObjectItemV41) -> Self {
295 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
296 }
297}
298impl From<ObjectItemV40> for ObjectItemV41 {
299 fn from(item: ObjectItemV40) -> Self {
300 Self { key: item.key.into(), value: item.value.into(), sequence: item.sequence }
301 }
302}
303
304#[cfg(test)]
305mod tests {
306 use super::*;
307
308 #[test]
309 fn test_timestamp_v32_to_v49() {
310 let v32 = TimestampV32 { secs: 100, nanos: 200 };
311 let v49: TimestampV49 = v32.into();
312 assert_eq!(v32.secs * 1_000_000_000 + v32.nanos as u64, v49.nanos);
313 }
314}