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