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