ARM: rmobile: Merge prior-stage firmware DT fragment into U-Boot DT on Gen3
[oweals/u-boot.git] / fs / ext4 / ext4_journal.c
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
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
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
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
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  */
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  */
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
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
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
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
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
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  */
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
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
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
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
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
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 }