hc
2023-12-06 08f87f769b595151be1afeff53e144f543faa614
kernel/fs/incfs/format.c
....@@ -42,7 +42,7 @@
4242 kfree(bfc);
4343 }
4444
45
-loff_t incfs_get_end_offset(struct file *f)
45
+static loff_t incfs_get_end_offset(struct file *f)
4646 {
4747 /*
4848 * This function assumes that file size and the end-offset
....@@ -91,11 +91,42 @@
9191 return result;
9292 }
9393
94
+static int write_to_bf(struct backing_file_context *bfc, const void *buf,
95
+ size_t count, loff_t pos)
96
+{
97
+ ssize_t res = incfs_kwrite(bfc, buf, count, pos);
98
+
99
+ if (res < 0)
100
+ return res;
101
+ if (res != count)
102
+ return -EIO;
103
+ return 0;
104
+}
105
+
106
+static int append_zeros_no_fallocate(struct backing_file_context *bfc,
107
+ size_t file_size, size_t len)
108
+{
109
+ u8 buffer[256] = {};
110
+ size_t i;
111
+
112
+ for (i = 0; i < len; i += sizeof(buffer)) {
113
+ int to_write = len - i > sizeof(buffer)
114
+ ? sizeof(buffer) : len - i;
115
+ int err = write_to_bf(bfc, buffer, to_write, file_size + i);
116
+
117
+ if (err)
118
+ return err;
119
+ }
120
+
121
+ return 0;
122
+}
123
+
94124 /* Append a given number of zero bytes to the end of the backing file. */
95125 static int append_zeros(struct backing_file_context *bfc, size_t len)
96126 {
97127 loff_t file_size = 0;
98128 loff_t new_last_byte_offset = 0;
129
+ int result;
99130
100131 if (!bfc)
101132 return -EFAULT;
....@@ -112,39 +143,11 @@
112143 */
113144 file_size = incfs_get_end_offset(bfc->bc_file);
114145 new_last_byte_offset = file_size + len - 1;
115
- return vfs_fallocate(bfc->bc_file, 0, new_last_byte_offset, 1);
116
-}
146
+ result = vfs_fallocate(bfc->bc_file, 0, new_last_byte_offset, 1);
147
+ if (result != -EOPNOTSUPP)
148
+ return result;
117149
118
-static int write_to_bf(struct backing_file_context *bfc, const void *buf,
119
- size_t count, loff_t pos)
120
-{
121
- ssize_t res = incfs_kwrite(bfc, buf, count, pos);
122
-
123
- if (res < 0)
124
- return res;
125
- if (res != count)
126
- return -EIO;
127
- return 0;
128
-}
129
-
130
-static u32 calc_md_crc(struct incfs_md_header *record)
131
-{
132
- u32 result = 0;
133
- __le32 saved_crc = record->h_record_crc;
134
- __le64 saved_md_offset = record->h_next_md_offset;
135
- size_t record_size = min_t(size_t, le16_to_cpu(record->h_record_size),
136
- INCFS_MAX_METADATA_RECORD_SIZE);
137
-
138
- /* Zero fields which needs to be excluded from CRC calculation. */
139
- record->h_record_crc = 0;
140
- record->h_next_md_offset = 0;
141
- result = crc32(0, record, record_size);
142
-
143
- /* Restore excluded fields. */
144
- record->h_record_crc = saved_crc;
145
- record->h_next_md_offset = saved_md_offset;
146
-
147
- return result;
150
+ return append_zeros_no_fallocate(bfc, file_size, len);
148151 }
149152
150153 /*
....@@ -170,9 +173,7 @@
170173
171174 record_size = le16_to_cpu(record->h_record_size);
172175 file_pos = incfs_get_end_offset(bfc->bc_file);
173
- record->h_prev_md_offset = cpu_to_le64(bfc->bc_last_md_record_offset);
174176 record->h_next_md_offset = 0;
175
- record->h_record_crc = cpu_to_le32(calc_md_crc(record));
176177
177178 /* Write the metadata record to the end of the backing file */
178179 record_offset = file_pos;
....@@ -204,16 +205,6 @@
204205
205206 bfc->bc_last_md_record_offset = record_offset;
206207 return result;
207
-}
208
-
209
-int incfs_write_file_header_flags(struct backing_file_context *bfc, u32 flags)
210
-{
211
- if (!bfc)
212
- return -EFAULT;
213
-
214
- return write_to_bf(bfc, &flags, sizeof(flags),
215
- offsetof(struct incfs_file_header,
216
- fh_file_header_flags));
217208 }
218209
219210 /*
....@@ -254,51 +245,9 @@
254245 return result;
255246 }
256247
257
-/*
258
- * Write file attribute data and metadata record to the backing file.
259
- */
260
-int incfs_write_file_attr_to_backing_file(struct backing_file_context *bfc,
261
- struct mem_range value, struct incfs_file_attr *attr)
262
-{
263
- struct incfs_file_attr file_attr = {};
264
- int result = 0;
265
- u32 crc = 0;
266
- loff_t value_offset = 0;
267
-
268
- if (!bfc)
269
- return -EFAULT;
270
-
271
- if (value.len > INCFS_MAX_FILE_ATTR_SIZE)
272
- return -ENOSPC;
273
-
274
- LOCK_REQUIRED(bfc->bc_mutex);
275
-
276
- crc = crc32(0, value.data, value.len);
277
- value_offset = incfs_get_end_offset(bfc->bc_file);
278
- file_attr.fa_header.h_md_entry_type = INCFS_MD_FILE_ATTR;
279
- file_attr.fa_header.h_record_size = cpu_to_le16(sizeof(file_attr));
280
- file_attr.fa_header.h_next_md_offset = cpu_to_le64(0);
281
- file_attr.fa_size = cpu_to_le16((u16)value.len);
282
- file_attr.fa_offset = cpu_to_le64(value_offset);
283
- file_attr.fa_crc = cpu_to_le32(crc);
284
-
285
- result = write_to_bf(bfc, value.data, value.len, value_offset);
286
- if (result)
287
- return result;
288
-
289
- result = append_md_to_backing_file(bfc, &file_attr.fa_header);
290
- if (result) {
291
- /* Error, rollback file changes */
292
- truncate_backing_file(bfc, value_offset);
293
- } else if (attr) {
294
- *attr = file_attr;
295
- }
296
-
297
- return result;
298
-}
299
-
300248 int incfs_write_signature_to_backing_file(struct backing_file_context *bfc,
301
- struct mem_range sig, u32 tree_size)
249
+ struct mem_range sig, u32 tree_size,
250
+ loff_t *tree_offset, loff_t *sig_offset)
302251 {
303252 struct incfs_file_signature sg = {};
304253 int result = 0;
....@@ -317,12 +266,10 @@
317266 sg.sg_header.h_record_size = cpu_to_le16(sizeof(sg));
318267 sg.sg_header.h_next_md_offset = cpu_to_le64(0);
319268 if (sig.data != NULL && sig.len > 0) {
320
- loff_t pos = incfs_get_end_offset(bfc->bc_file);
321
-
322269 sg.sg_sig_size = cpu_to_le32(sig.len);
323
- sg.sg_sig_offset = cpu_to_le64(pos);
270
+ sg.sg_sig_offset = cpu_to_le64(rollback_pos);
324271
325
- result = write_to_bf(bfc, sig.data, sig.len, pos);
272
+ result = write_to_bf(bfc, sig.data, sig.len, rollback_pos);
326273 if (result)
327274 goto err;
328275 }
....@@ -358,13 +305,112 @@
358305 if (result)
359306 /* Error, rollback file changes */
360307 truncate_backing_file(bfc, rollback_pos);
308
+ else {
309
+ if (tree_offset)
310
+ *tree_offset = tree_area_pos;
311
+ if (sig_offset)
312
+ *sig_offset = rollback_pos;
313
+ }
314
+
315
+ return result;
316
+}
317
+
318
+static int write_new_status_to_backing_file(struct backing_file_context *bfc,
319
+ u32 data_blocks_written,
320
+ u32 hash_blocks_written)
321
+{
322
+ int result;
323
+ loff_t rollback_pos;
324
+ struct incfs_status is = {
325
+ .is_header = {
326
+ .h_md_entry_type = INCFS_MD_STATUS,
327
+ .h_record_size = cpu_to_le16(sizeof(is)),
328
+ },
329
+ .is_data_blocks_written = cpu_to_le32(data_blocks_written),
330
+ .is_hash_blocks_written = cpu_to_le32(hash_blocks_written),
331
+ };
332
+
333
+ LOCK_REQUIRED(bfc->bc_mutex);
334
+ rollback_pos = incfs_get_end_offset(bfc->bc_file);
335
+ result = append_md_to_backing_file(bfc, &is.is_header);
336
+ if (result)
337
+ truncate_backing_file(bfc, rollback_pos);
338
+
339
+ return result;
340
+}
341
+
342
+int incfs_write_status_to_backing_file(struct backing_file_context *bfc,
343
+ loff_t status_offset,
344
+ u32 data_blocks_written,
345
+ u32 hash_blocks_written)
346
+{
347
+ struct incfs_status is;
348
+ int result;
349
+
350
+ if (!bfc)
351
+ return -EFAULT;
352
+
353
+ if (status_offset == 0)
354
+ return write_new_status_to_backing_file(bfc,
355
+ data_blocks_written, hash_blocks_written);
356
+
357
+ result = incfs_kread(bfc, &is, sizeof(is), status_offset);
358
+ if (result != sizeof(is))
359
+ return -EIO;
360
+
361
+ is.is_data_blocks_written = cpu_to_le32(data_blocks_written);
362
+ is.is_hash_blocks_written = cpu_to_le32(hash_blocks_written);
363
+ result = incfs_kwrite(bfc, &is, sizeof(is), status_offset);
364
+ if (result != sizeof(is))
365
+ return -EIO;
366
+
367
+ return 0;
368
+}
369
+
370
+int incfs_write_verity_signature_to_backing_file(
371
+ struct backing_file_context *bfc, struct mem_range signature,
372
+ loff_t *offset)
373
+{
374
+ struct incfs_file_verity_signature vs = {};
375
+ int result;
376
+ loff_t pos;
377
+
378
+ /* No verity signature section is equivalent to an empty section */
379
+ if (signature.data == NULL || signature.len == 0)
380
+ return 0;
381
+
382
+ pos = incfs_get_end_offset(bfc->bc_file);
383
+
384
+ vs = (struct incfs_file_verity_signature) {
385
+ .vs_header = (struct incfs_md_header) {
386
+ .h_md_entry_type = INCFS_MD_VERITY_SIGNATURE,
387
+ .h_record_size = cpu_to_le16(sizeof(vs)),
388
+ .h_next_md_offset = cpu_to_le64(0),
389
+ },
390
+ .vs_size = cpu_to_le32(signature.len),
391
+ .vs_offset = cpu_to_le64(pos),
392
+ };
393
+
394
+ result = write_to_bf(bfc, signature.data, signature.len, pos);
395
+ if (result)
396
+ goto err;
397
+
398
+ result = append_md_to_backing_file(bfc, &vs.vs_header);
399
+ if (result)
400
+ goto err;
401
+
402
+ *offset = pos;
403
+err:
404
+ if (result)
405
+ /* Error, rollback file changes */
406
+ truncate_backing_file(bfc, pos);
361407 return result;
362408 }
363409
364410 /*
365411 * Write a backing file header
366412 * It should always be called only on empty file.
367
- * incfs_super_block.s_first_md_offset is 0 for now, but will be updated
413
+ * fh.fh_first_md_offset is 0 for now, but will be updated
368414 * once first metadata record is added.
369415 */
370416 int incfs_write_fh_to_backing_file(struct backing_file_context *bfc,
....@@ -384,6 +430,38 @@
384430
385431 fh.fh_file_size = cpu_to_le64(file_size);
386432 fh.fh_uuid = *uuid;
433
+
434
+ LOCK_REQUIRED(bfc->bc_mutex);
435
+
436
+ file_pos = incfs_get_end_offset(bfc->bc_file);
437
+ if (file_pos != 0)
438
+ return -EEXIST;
439
+
440
+ return write_to_bf(bfc, &fh, sizeof(fh), file_pos);
441
+}
442
+
443
+/*
444
+ * Write a backing file header for a mapping file
445
+ * It should always be called only on empty file.
446
+ */
447
+int incfs_write_mapping_fh_to_backing_file(struct backing_file_context *bfc,
448
+ incfs_uuid_t *uuid, u64 file_size, u64 offset)
449
+{
450
+ struct incfs_file_header fh = {};
451
+ loff_t file_pos = 0;
452
+
453
+ if (!bfc)
454
+ return -EFAULT;
455
+
456
+ fh.fh_magic = cpu_to_le64(INCFS_MAGIC_NUMBER);
457
+ fh.fh_version = cpu_to_le64(INCFS_FORMAT_CURRENT_VER);
458
+ fh.fh_header_size = cpu_to_le16(sizeof(fh));
459
+ fh.fh_original_offset = cpu_to_le64(offset);
460
+ fh.fh_data_block_size = cpu_to_le16(INCFS_DATA_FILE_BLOCK_SIZE);
461
+
462
+ fh.fh_mapped_file_size = cpu_to_le64(file_size);
463
+ fh.fh_original_uuid = *uuid;
464
+ fh.fh_flags = cpu_to_le32(INCFS_FILE_MAPPED);
387465
388466 LOCK_REQUIRED(bfc->bc_mutex);
389467
....@@ -469,32 +547,8 @@
469547 bm_entry.me_data_offset_lo = cpu_to_le32((u32)data_offset);
470548 bm_entry.me_data_offset_hi = cpu_to_le16((u16)(data_offset >> 32));
471549 bm_entry.me_data_size = cpu_to_le16(INCFS_DATA_FILE_BLOCK_SIZE);
472
- bm_entry.me_flags = cpu_to_le16(INCFS_BLOCK_HASH);
473550
474551 return write_to_bf(bfc, &bm_entry, sizeof(bm_entry), bm_entry_off);
475
-}
476
-
477
-/* Initialize a new image in a given backing file. */
478
-int incfs_make_empty_backing_file(struct backing_file_context *bfc,
479
- incfs_uuid_t *uuid, u64 file_size)
480
-{
481
- int result = 0;
482
-
483
- if (!bfc || !bfc->bc_file)
484
- return -EFAULT;
485
-
486
- result = mutex_lock_interruptible(&bfc->bc_mutex);
487
- if (result)
488
- goto out;
489
-
490
- result = truncate_backing_file(bfc, 0);
491
- if (result)
492
- goto out;
493
-
494
- result = incfs_write_fh_to_backing_file(bfc, uuid, file_size);
495
-out:
496
- mutex_unlock(&bfc->bc_mutex);
497
- return result;
498552 }
499553
500554 int incfs_read_blockmap_entry(struct backing_file_context *bfc, int block_index,
....@@ -575,7 +629,7 @@
575629 if (file_size)
576630 *file_size = le64_to_cpu(fh.fh_file_size);
577631 if (flags)
578
- *flags = le32_to_cpu(fh.fh_file_header_flags);
632
+ *flags = le32_to_cpu(fh.fh_flags);
579633 return 0;
580634 }
581635
....@@ -590,14 +644,11 @@
590644 ssize_t bytes_read = 0;
591645 size_t md_record_size = 0;
592646 loff_t next_record = 0;
593
- loff_t prev_record = 0;
594647 int res = 0;
595648 struct incfs_md_header *md_hdr = NULL;
596649
597650 if (!bfc || !handler)
598651 return -EFAULT;
599
-
600
- LOCK_REQUIRED(bfc->bc_mutex);
601652
602653 if (handler->md_record_offset == 0)
603654 return -EPERM;
....@@ -612,7 +663,6 @@
612663
613664 md_hdr = &handler->md_buffer.md_header;
614665 next_record = le64_to_cpu(md_hdr->h_next_md_offset);
615
- prev_record = le64_to_cpu(md_hdr->h_prev_md_offset);
616666 md_record_size = le16_to_cpu(md_hdr->h_record_size);
617667
618668 if (md_record_size > max_md_size) {
....@@ -632,16 +682,6 @@
632682 return -EBADMSG;
633683 }
634684
635
- if (prev_record != handler->md_prev_record_offset) {
636
- pr_warn("incfs: Metadata chain has been corrupted.");
637
- return -EBADMSG;
638
- }
639
-
640
- if (le32_to_cpu(md_hdr->h_record_crc) != calc_md_crc(md_hdr)) {
641
- pr_warn("incfs: Metadata CRC mismatch.");
642
- return -EBADMSG;
643
- }
644
-
645685 switch (md_hdr->h_md_entry_type) {
646686 case INCFS_MD_NONE:
647687 break;
....@@ -651,15 +691,26 @@
651691 &handler->md_buffer.blockmap, handler);
652692 break;
653693 case INCFS_MD_FILE_ATTR:
654
- if (handler->handle_file_attr)
655
- res = handler->handle_file_attr(
656
- &handler->md_buffer.file_attr, handler);
694
+ /*
695
+ * File attrs no longer supported, ignore section for
696
+ * compatibility
697
+ */
657698 break;
658699 case INCFS_MD_SIGNATURE:
659700 if (handler->handle_signature)
660701 res = handler->handle_signature(
661702 &handler->md_buffer.signature, handler);
662703 break;
704
+ case INCFS_MD_STATUS:
705
+ if (handler->handle_status)
706
+ res = handler->handle_status(
707
+ &handler->md_buffer.status, handler);
708
+ break;
709
+ case INCFS_MD_VERITY_SIGNATURE:
710
+ if (handler->handle_verity_signature)
711
+ res = handler->handle_verity_signature(
712
+ &handler->md_buffer.verity_signature, handler);
713
+ break;
663714 default:
664715 res = -ENOTSUPP;
665716 break;