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