1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2011 - 2012 Samsung Electronics
4 * EXT4 filesystem implementation in Uboot by
5 * Uma Shankar <uma.shankar@samsung.com>
6 * Manjunatha C Achar <a.manjunatha@samsung.com>
7 *
8 * Journal data structures and headers for Journaling feature of ext4
9 * have been referred from JBD2 (Journaling Block device 2)
10 * implementation in Linux Kernel.
11 * Written by Stephen C. Tweedie <sct@redhat.com>
12 *
13 * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved
14 */
15
16 #include <common.h>
17 #include <blk.h>
18 #include <ext4fs.h>
19 #include <log.h>
20 #include <malloc.h>
21 #include <ext_common.h>
22 #include "ext4_common.h"
23
24 static struct revoke_blk_list *revk_blk_list;
25 static struct revoke_blk_list *prev_node;
26 static int first_node = true;
27
28 int gindex;
29 int gd_index;
30 int jrnl_blk_idx;
31 struct journal_log *journal_ptr[MAX_JOURNAL_ENTRIES];
32 struct dirty_blocks *dirty_block_ptr[MAX_JOURNAL_ENTRIES];
33
ext4fs_init_journal(void)34 int ext4fs_init_journal(void)
35 {
36 int i;
37 char *temp = NULL;
38 struct ext_filesystem *fs = get_fs();
39
40 /* init globals */
41 revk_blk_list = NULL;
42 prev_node = NULL;
43 gindex = 0;
44 gd_index = 0;
45 jrnl_blk_idx = 1;
46
47 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
48 journal_ptr[i] = zalloc(sizeof(struct journal_log));
49 if (!journal_ptr[i])
50 goto fail;
51 dirty_block_ptr[i] = zalloc(sizeof(struct dirty_blocks));
52 if (!dirty_block_ptr[i])
53 goto fail;
54 journal_ptr[i]->buf = NULL;
55 journal_ptr[i]->blknr = -1;
56
57 dirty_block_ptr[i]->buf = NULL;
58 dirty_block_ptr[i]->blknr = -1;
59 }
60
61 if (fs->blksz == 4096) {
62 temp = zalloc(fs->blksz);
63 if (!temp)
64 goto fail;
65 journal_ptr[gindex]->buf = zalloc(fs->blksz);
66 if (!journal_ptr[gindex]->buf)
67 goto fail;
68 ext4fs_devread(0, 0, fs->blksz, temp);
69 memcpy(temp + SUPERBLOCK_SIZE, fs->sb, SUPERBLOCK_SIZE);
70 memcpy(journal_ptr[gindex]->buf, temp, fs->blksz);
71 journal_ptr[gindex++]->blknr = 0;
72 free(temp);
73 } else {
74 journal_ptr[gindex]->buf = zalloc(fs->blksz);
75 if (!journal_ptr[gindex]->buf)
76 goto fail;
77 memcpy(journal_ptr[gindex]->buf, fs->sb, SUPERBLOCK_SIZE);
78 journal_ptr[gindex++]->blknr = 1;
79 }
80
81 /* Check the file system state using journal super block */
82 if (ext4fs_check_journal_state(SCAN))
83 goto fail;
84 /* Check the file system state using journal super block */
85 if (ext4fs_check_journal_state(RECOVER))
86 goto fail;
87
88 return 0;
89 fail:
90 return -1;
91 }
92
ext4fs_dump_metadata(void)93 void ext4fs_dump_metadata(void)
94 {
95 struct ext_filesystem *fs = get_fs();
96 int i;
97 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
98 if (dirty_block_ptr[i]->blknr == -1)
99 break;
100 put_ext4((uint64_t) ((uint64_t)dirty_block_ptr[i]->blknr *
101 (uint64_t)fs->blksz), dirty_block_ptr[i]->buf,
102 fs->blksz);
103 }
104 }
105
ext4fs_free_journal(void)106 void ext4fs_free_journal(void)
107 {
108 int i;
109 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
110 if (dirty_block_ptr[i]->blknr == -1)
111 break;
112 free(dirty_block_ptr[i]->buf);
113 }
114
115 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
116 if (journal_ptr[i]->blknr == -1)
117 break;
118 free(journal_ptr[i]->buf);
119 }
120
121 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
122 free(journal_ptr[i]);
123 free(dirty_block_ptr[i]);
124 }
125 gindex = 0;
126 gd_index = 0;
127 jrnl_blk_idx = 1;
128 }
129
ext4fs_log_gdt(char * gd_table)130 int ext4fs_log_gdt(char *gd_table)
131 {
132 struct ext_filesystem *fs = get_fs();
133 short i;
134 long int var = fs->gdtable_blkno;
135 for (i = 0; i < fs->no_blk_pergdt; i++) {
136 journal_ptr[gindex]->buf = zalloc(fs->blksz);
137 if (!journal_ptr[gindex]->buf)
138 return -ENOMEM;
139 memcpy(journal_ptr[gindex]->buf, gd_table, fs->blksz);
140 gd_table += fs->blksz;
141 journal_ptr[gindex++]->blknr = var++;
142 }
143
144 return 0;
145 }
146
147 /*
148 * This function stores the backup copy of meta data in RAM
149 * journal_buffer -- Buffer containing meta data
150 * blknr -- Block number on disk of the meta data buffer
151 */
ext4fs_log_journal(char * journal_buffer,uint32_t blknr)152 int ext4fs_log_journal(char *journal_buffer, uint32_t blknr)
153 {
154 struct ext_filesystem *fs = get_fs();
155 short i;
156
157 if (!journal_buffer) {
158 printf("Invalid input arguments %s\n", __func__);
159 return -EINVAL;
160 }
161
162 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
163 if (journal_ptr[i]->blknr == -1)
164 break;
165 if (journal_ptr[i]->blknr == blknr)
166 return 0;
167 }
168
169 journal_ptr[gindex]->buf = zalloc(fs->blksz);
170 if (!journal_ptr[gindex]->buf)
171 return -ENOMEM;
172
173 memcpy(journal_ptr[gindex]->buf, journal_buffer, fs->blksz);
174 journal_ptr[gindex++]->blknr = blknr;
175
176 return 0;
177 }
178
179 /*
180 * This function stores the modified meta data in RAM
181 * metadata_buffer -- Buffer containing meta data
182 * blknr -- Block number on disk of the meta data buffer
183 */
ext4fs_put_metadata(char * metadata_buffer,uint32_t blknr)184 int ext4fs_put_metadata(char *metadata_buffer, uint32_t blknr)
185 {
186 struct ext_filesystem *fs = get_fs();
187 if (!metadata_buffer) {
188 printf("Invalid input arguments %s\n", __func__);
189 return -EINVAL;
190 }
191 if (dirty_block_ptr[gd_index]->buf)
192 assert(dirty_block_ptr[gd_index]->blknr == blknr);
193 else
194 dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz);
195
196 if (!dirty_block_ptr[gd_index]->buf)
197 return -ENOMEM;
198 memcpy(dirty_block_ptr[gd_index]->buf, metadata_buffer, fs->blksz);
199 dirty_block_ptr[gd_index++]->blknr = blknr;
200
201 return 0;
202 }
203
print_revoke_blks(char * revk_blk)204 void print_revoke_blks(char *revk_blk)
205 {
206 int offset;
207 int max;
208 long int blocknr;
209 struct journal_revoke_header_t *header;
210
211 if (revk_blk == NULL)
212 return;
213
214 header = (struct journal_revoke_header_t *) revk_blk;
215 offset = sizeof(struct journal_revoke_header_t);
216 max = be32_to_cpu(header->r_count);
217 printf("total bytes %d\n", max);
218
219 while (offset < max) {
220 blocknr = be32_to_cpu(*((__be32 *)(revk_blk + offset)));
221 printf("revoke blknr is %ld\n", blocknr);
222 offset += 4;
223 }
224 }
225
_get_node(void)226 static struct revoke_blk_list *_get_node(void)
227 {
228 struct revoke_blk_list *tmp_node;
229 tmp_node = zalloc(sizeof(struct revoke_blk_list));
230 if (tmp_node == NULL)
231 return NULL;
232 tmp_node->content = NULL;
233 tmp_node->next = NULL;
234
235 return tmp_node;
236 }
237
ext4fs_push_revoke_blk(char * buffer)238 void ext4fs_push_revoke_blk(char *buffer)
239 {
240 struct revoke_blk_list *node = NULL;
241 struct ext_filesystem *fs = get_fs();
242 if (buffer == NULL) {
243 printf("buffer ptr is NULL\n");
244 return;
245 }
246 node = _get_node();
247 if (!node) {
248 printf("_get_node: malloc failed\n");
249 return;
250 }
251
252 node->content = zalloc(fs->blksz);
253 if (node->content == NULL)
254 return;
255 memcpy(node->content, buffer, fs->blksz);
256
257 if (first_node == true) {
258 revk_blk_list = node;
259 prev_node = node;
260 first_node = false;
261 } else {
262 prev_node->next = node;
263 prev_node = node;
264 }
265 }
266
ext4fs_free_revoke_blks(void)267 void ext4fs_free_revoke_blks(void)
268 {
269 struct revoke_blk_list *tmp_node = revk_blk_list;
270 struct revoke_blk_list *next_node = NULL;
271
272 while (tmp_node != NULL) {
273 free(tmp_node->content);
274 tmp_node = tmp_node->next;
275 }
276
277 tmp_node = revk_blk_list;
278 while (tmp_node != NULL) {
279 next_node = tmp_node->next;
280 free(tmp_node);
281 tmp_node = next_node;
282 }
283
284 revk_blk_list = NULL;
285 prev_node = NULL;
286 first_node = true;
287 }
288
check_blknr_for_revoke(long int blknr,int sequence_no)289 int check_blknr_for_revoke(long int blknr, int sequence_no)
290 {
291 struct journal_revoke_header_t *header;
292 int offset;
293 int max;
294 long int blocknr;
295 char *revk_blk;
296 struct revoke_blk_list *tmp_revk_node = revk_blk_list;
297 while (tmp_revk_node != NULL) {
298 revk_blk = tmp_revk_node->content;
299
300 header = (struct journal_revoke_header_t *) revk_blk;
301 if (sequence_no < be32_to_cpu(header->r_header.h_sequence)) {
302 offset = sizeof(struct journal_revoke_header_t);
303 max = be32_to_cpu(header->r_count);
304
305 while (offset < max) {
306 blocknr = be32_to_cpu(*((__be32 *)
307 (revk_blk + offset)));
308 if (blocknr == blknr)
309 goto found;
310 offset += 4;
311 }
312 }
313 tmp_revk_node = tmp_revk_node->next;
314 }
315
316 return -1;
317
318 found:
319 return 0;
320 }
321
322 /*
323 * This function parses the journal blocks and replays the
324 * suceessful transactions. A transaction is successfull
325 * if commit block is found for a descriptor block
326 * The tags in descriptor block contain the disk block
327 * numbers of the metadata to be replayed
328 */
recover_transaction(int prev_desc_logical_no)329 void recover_transaction(int prev_desc_logical_no)
330 {
331 struct ext2_inode inode_journal;
332 struct ext_filesystem *fs = get_fs();
333 struct journal_header_t *jdb;
334 long int blknr;
335 char *p_jdb;
336 int ofs, flags;
337 int i;
338 struct ext3_journal_block_tag *tag;
339 char *temp_buff = zalloc(fs->blksz);
340 char *metadata_buff = zalloc(fs->blksz);
341 if (!temp_buff || !metadata_buff)
342 goto fail;
343 i = prev_desc_logical_no;
344 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
345 (struct ext2_inode *)&inode_journal);
346 blknr = read_allocated_block((struct ext2_inode *)
347 &inode_journal, i, NULL);
348 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
349 temp_buff);
350 p_jdb = (char *)temp_buff;
351 jdb = (struct journal_header_t *) temp_buff;
352 ofs = sizeof(struct journal_header_t);
353
354 do {
355 tag = (struct ext3_journal_block_tag *)(p_jdb + ofs);
356 ofs += sizeof(struct ext3_journal_block_tag);
357
358 if (ofs > fs->blksz)
359 break;
360
361 flags = be32_to_cpu(tag->flags);
362 if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
363 ofs += 16;
364
365 i++;
366 debug("\t\ttag %u\n", be32_to_cpu(tag->block));
367 if (revk_blk_list != NULL) {
368 if (check_blknr_for_revoke(be32_to_cpu(tag->block),
369 be32_to_cpu(jdb->h_sequence)) == 0)
370 continue;
371 }
372 blknr = read_allocated_block(&inode_journal, i, NULL);
373 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
374 fs->blksz, metadata_buff);
375 put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz),
376 metadata_buff, (uint32_t) fs->blksz);
377 } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
378 fail:
379 free(temp_buff);
380 free(metadata_buff);
381 }
382
print_jrnl_status(int recovery_flag)383 void print_jrnl_status(int recovery_flag)
384 {
385 if (recovery_flag == RECOVER)
386 printf("Journal Recovery Completed\n");
387 else
388 printf("Journal Scan Completed\n");
389 }
390
ext4fs_check_journal_state(int recovery_flag)391 int ext4fs_check_journal_state(int recovery_flag)
392 {
393 int i;
394 int DB_FOUND = NO;
395 long int blknr;
396 int transaction_state = TRANSACTION_COMPLETE;
397 int prev_desc_logical_no = 0;
398 int curr_desc_logical_no = 0;
399 int ofs, flags;
400 struct ext2_inode inode_journal;
401 struct journal_superblock_t *jsb = NULL;
402 struct journal_header_t *jdb = NULL;
403 char *p_jdb = NULL;
404 struct ext3_journal_block_tag *tag = NULL;
405 char *temp_buff = NULL;
406 char *temp_buff1 = NULL;
407 struct ext_filesystem *fs = get_fs();
408
409 if (le32_to_cpu(fs->sb->feature_ro_compat) & EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)
410 return 0;
411
412 temp_buff = zalloc(fs->blksz);
413 if (!temp_buff)
414 return -ENOMEM;
415 temp_buff1 = zalloc(fs->blksz);
416 if (!temp_buff1) {
417 free(temp_buff);
418 return -ENOMEM;
419 }
420
421 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
422 blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK,
423 NULL);
424 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
425 temp_buff);
426 jsb = (struct journal_superblock_t *) temp_buff;
427
428 if (le32_to_cpu(fs->sb->feature_incompat) & EXT3_FEATURE_INCOMPAT_RECOVER) {
429 if (recovery_flag == RECOVER)
430 printf("Recovery required\n");
431 } else {
432 if (recovery_flag == RECOVER)
433 printf("File System is consistent\n");
434 goto end;
435 }
436
437 if (be32_to_cpu(jsb->s_start) == 0)
438 goto end;
439
440 if (!(jsb->s_feature_compat &
441 cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM)))
442 jsb->s_feature_compat |=
443 cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
444
445 i = be32_to_cpu(jsb->s_first);
446 while (1) {
447 blknr = read_allocated_block(&inode_journal, i, NULL);
448 memset(temp_buff1, '\0', fs->blksz);
449 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
450 0, fs->blksz, temp_buff1);
451 jdb = (struct journal_header_t *) temp_buff1;
452
453 if (be32_to_cpu(jdb->h_blocktype) ==
454 EXT3_JOURNAL_DESCRIPTOR_BLOCK) {
455 if (be32_to_cpu(jdb->h_sequence) !=
456 be32_to_cpu(jsb->s_sequence)) {
457 print_jrnl_status(recovery_flag);
458 break;
459 }
460
461 curr_desc_logical_no = i;
462 if (transaction_state == TRANSACTION_COMPLETE)
463 transaction_state = TRANSACTION_RUNNING;
464 else
465 return -1;
466 p_jdb = (char *)temp_buff1;
467 ofs = sizeof(struct journal_header_t);
468 do {
469 tag = (struct ext3_journal_block_tag *)
470 (p_jdb + ofs);
471 ofs += sizeof(struct ext3_journal_block_tag);
472 if (ofs > fs->blksz)
473 break;
474 flags = be32_to_cpu(tag->flags);
475 if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
476 ofs += 16;
477 i++;
478 debug("\t\ttag %u\n", be32_to_cpu(tag->block));
479 } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
480 i++;
481 DB_FOUND = YES;
482 } else if (be32_to_cpu(jdb->h_blocktype) ==
483 EXT3_JOURNAL_COMMIT_BLOCK) {
484 if (be32_to_cpu(jdb->h_sequence) !=
485 be32_to_cpu(jsb->s_sequence)) {
486 print_jrnl_status(recovery_flag);
487 break;
488 }
489
490 if (transaction_state == TRANSACTION_RUNNING ||
491 (DB_FOUND == NO)) {
492 transaction_state = TRANSACTION_COMPLETE;
493 i++;
494 jsb->s_sequence =
495 cpu_to_be32(be32_to_cpu(
496 jsb->s_sequence) + 1);
497 }
498 prev_desc_logical_no = curr_desc_logical_no;
499 if ((recovery_flag == RECOVER) && (DB_FOUND == YES))
500 recover_transaction(prev_desc_logical_no);
501
502 DB_FOUND = NO;
503 } else if (be32_to_cpu(jdb->h_blocktype) ==
504 EXT3_JOURNAL_REVOKE_BLOCK) {
505 if (be32_to_cpu(jdb->h_sequence) !=
506 be32_to_cpu(jsb->s_sequence)) {
507 print_jrnl_status(recovery_flag);
508 break;
509 }
510 if (recovery_flag == SCAN)
511 ext4fs_push_revoke_blk((char *)jdb);
512 i++;
513 } else {
514 debug("Else Case\n");
515 if (be32_to_cpu(jdb->h_sequence) !=
516 be32_to_cpu(jsb->s_sequence)) {
517 print_jrnl_status(recovery_flag);
518 break;
519 }
520 }
521 }
522
523 end:
524 if (recovery_flag == RECOVER) {
525 uint32_t new_feature_incompat;
526 jsb->s_start = cpu_to_be32(1);
527 jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1);
528 /* get the superblock */
529 ext4_read_superblock((char *)fs->sb);
530 new_feature_incompat = le32_to_cpu(fs->sb->feature_incompat);
531 new_feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
532 fs->sb->feature_incompat = cpu_to_le32(new_feature_incompat);
533
534 /* Update the super block */
535 put_ext4((uint64_t) (SUPERBLOCK_SIZE),
536 (struct ext2_sblock *)fs->sb,
537 (uint32_t) SUPERBLOCK_SIZE);
538 ext4_read_superblock((char *)fs->sb);
539
540 blknr = read_allocated_block(&inode_journal,
541 EXT2_JOURNAL_SUPERBLOCK, NULL);
542 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
543 (struct journal_superblock_t *)temp_buff,
544 (uint32_t) fs->blksz);
545 ext4fs_free_revoke_blks();
546 }
547 free(temp_buff);
548 free(temp_buff1);
549
550 return 0;
551 }
552
update_descriptor_block(long int blknr)553 static void update_descriptor_block(long int blknr)
554 {
555 int i;
556 long int jsb_blknr;
557 struct journal_header_t jdb;
558 struct ext3_journal_block_tag tag;
559 struct ext2_inode inode_journal;
560 struct journal_superblock_t *jsb = NULL;
561 char *buf = NULL;
562 char *temp = NULL;
563 struct ext_filesystem *fs = get_fs();
564 char *temp_buff = zalloc(fs->blksz);
565 if (!temp_buff)
566 return;
567
568 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
569 jsb_blknr = read_allocated_block(&inode_journal,
570 EXT2_JOURNAL_SUPERBLOCK, NULL);
571 ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
572 temp_buff);
573 jsb = (struct journal_superblock_t *) temp_buff;
574
575 jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_DESCRIPTOR_BLOCK);
576 jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
577 jdb.h_sequence = jsb->s_sequence;
578 buf = zalloc(fs->blksz);
579 if (!buf) {
580 free(temp_buff);
581 return;
582 }
583 temp = buf;
584 memcpy(buf, &jdb, sizeof(struct journal_header_t));
585 temp += sizeof(struct journal_header_t);
586
587 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
588 if (journal_ptr[i]->blknr == -1)
589 break;
590
591 tag.block = cpu_to_be32(journal_ptr[i]->blknr);
592 tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_SAME_UUID);
593 memcpy(temp, &tag, sizeof(struct ext3_journal_block_tag));
594 temp = temp + sizeof(struct ext3_journal_block_tag);
595 }
596
597 tag.block = cpu_to_be32(journal_ptr[--i]->blknr);
598 tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_LAST_TAG);
599 memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag,
600 sizeof(struct ext3_journal_block_tag));
601 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
602
603 free(temp_buff);
604 free(buf);
605 }
606
update_commit_block(long int blknr)607 static void update_commit_block(long int blknr)
608 {
609 struct journal_header_t jdb;
610 struct ext_filesystem *fs = get_fs();
611 char *buf = NULL;
612 struct ext2_inode inode_journal;
613 struct journal_superblock_t *jsb;
614 long int jsb_blknr;
615 char *temp_buff = zalloc(fs->blksz);
616 if (!temp_buff)
617 return;
618
619 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
620 &inode_journal);
621 jsb_blknr = read_allocated_block(&inode_journal,
622 EXT2_JOURNAL_SUPERBLOCK, NULL);
623 ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
624 temp_buff);
625 jsb = (struct journal_superblock_t *) temp_buff;
626
627 jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_COMMIT_BLOCK);
628 jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
629 jdb.h_sequence = jsb->s_sequence;
630 buf = zalloc(fs->blksz);
631 if (!buf) {
632 free(temp_buff);
633 return;
634 }
635 memcpy(buf, &jdb, sizeof(struct journal_header_t));
636 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
637
638 free(temp_buff);
639 free(buf);
640 }
641
ext4fs_update_journal(void)642 void ext4fs_update_journal(void)
643 {
644 struct ext2_inode inode_journal;
645 struct ext_filesystem *fs = get_fs();
646 long int blknr;
647 int i;
648
649 if (!(fs->sb->feature_compatibility & EXT4_FEATURE_COMPAT_HAS_JOURNAL))
650 return;
651
652 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
653 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++, NULL);
654 update_descriptor_block(blknr);
655 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
656 if (journal_ptr[i]->blknr == -1)
657 break;
658 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++,
659 NULL);
660 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
661 journal_ptr[i]->buf, fs->blksz);
662 }
663 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++, NULL);
664 update_commit_block(blknr);
665 printf("update journal finished\n");
666 }
667