xref: /openbmc/u-boot/fs/ext4/ext4_journal.c (revision 2290fe06)
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  * SPDX-License-Identifier:	GPL-2.0+
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 		if (dirty_block_ptr[i]->buf)
111 			free(dirty_block_ptr[i]->buf);
112 	}
113 
114 	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
115 		if (journal_ptr[i]->blknr == -1)
116 			break;
117 		if (journal_ptr[i]->buf)
118 			free(journal_ptr[i]->buf);
119 	}
120 
121 	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
122 		if (journal_ptr[i])
123 			free(journal_ptr[i]);
124 		if (dirty_block_ptr[i])
125 			free(dirty_block_ptr[i]);
126 	}
127 	gindex = 0;
128 	gd_index = 0;
129 	jrnl_blk_idx = 1;
130 }
131 
132 int ext4fs_log_gdt(char *gd_table)
133 {
134 	struct ext_filesystem *fs = get_fs();
135 	short i;
136 	long int var = fs->gdtable_blkno;
137 	for (i = 0; i < fs->no_blk_pergdt; i++) {
138 		journal_ptr[gindex]->buf = zalloc(fs->blksz);
139 		if (!journal_ptr[gindex]->buf)
140 			return -ENOMEM;
141 		memcpy(journal_ptr[gindex]->buf, gd_table, fs->blksz);
142 		gd_table += fs->blksz;
143 		journal_ptr[gindex++]->blknr = var++;
144 	}
145 
146 	return 0;
147 }
148 
149 /*
150  * This function stores the backup copy of meta data in RAM
151  * journal_buffer -- Buffer containing meta data
152  * blknr -- Block number on disk of the meta data buffer
153  */
154 int ext4fs_log_journal(char *journal_buffer, long int blknr)
155 {
156 	struct ext_filesystem *fs = get_fs();
157 	short i;
158 
159 	if (!journal_buffer) {
160 		printf("Invalid input arguments %s\n", __func__);
161 		return -EINVAL;
162 	}
163 
164 	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
165 		if (journal_ptr[i]->blknr == -1)
166 			break;
167 		if (journal_ptr[i]->blknr == blknr)
168 			return 0;
169 	}
170 
171 	journal_ptr[gindex]->buf = zalloc(fs->blksz);
172 	if (!journal_ptr[gindex]->buf)
173 		return -ENOMEM;
174 
175 	memcpy(journal_ptr[gindex]->buf, journal_buffer, fs->blksz);
176 	journal_ptr[gindex++]->blknr = blknr;
177 
178 	return 0;
179 }
180 
181 /*
182  * This function stores the modified meta data in RAM
183  * metadata_buffer -- Buffer containing meta data
184  * blknr -- Block number on disk of the meta data buffer
185  */
186 int ext4fs_put_metadata(char *metadata_buffer, long int blknr)
187 {
188 	struct ext_filesystem *fs = get_fs();
189 	if (!metadata_buffer) {
190 		printf("Invalid input arguments %s\n", __func__);
191 		return -EINVAL;
192 	}
193 	dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz);
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(*((long int *)(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 		if (tmp_node->content)
272 			free(tmp_node->content);
273 		tmp_node = tmp_node->next;
274 	}
275 
276 	tmp_node = revk_blk_list;
277 	while (tmp_node != NULL) {
278 		next_node = tmp_node->next;
279 		free(tmp_node);
280 		tmp_node = next_node;
281 	}
282 
283 	revk_blk_list = NULL;
284 	prev_node = NULL;
285 	first_node = true;
286 }
287 
288 int check_blknr_for_revoke(long int blknr, int sequence_no)
289 {
290 	struct journal_revoke_header_t *header;
291 	int offset;
292 	int max;
293 	long int blocknr;
294 	char *revk_blk;
295 	struct revoke_blk_list *tmp_revk_node = revk_blk_list;
296 	while (tmp_revk_node != NULL) {
297 		revk_blk = tmp_revk_node->content;
298 
299 		header = (struct journal_revoke_header_t *) revk_blk;
300 		if (sequence_no < be32_to_cpu(header->r_header.h_sequence)) {
301 			offset = sizeof(struct journal_revoke_header_t);
302 			max = be32_to_cpu(header->r_count);
303 
304 			while (offset < max) {
305 				blocknr = be32_to_cpu(*((long int *)
306 						  (revk_blk + offset)));
307 				if (blocknr == blknr)
308 					goto found;
309 				offset += 4;
310 			}
311 		}
312 		tmp_revk_node = tmp_revk_node->next;
313 	}
314 
315 	return -1;
316 
317 found:
318 	return 0;
319 }
320 
321 /*
322  * This function parses the journal blocks and replays the
323  * suceessful transactions. A transaction is successfull
324  * if commit block is found for a descriptor block
325  * The tags in descriptor block contain the disk block
326  * numbers of the metadata  to be replayed
327  */
328 void recover_transaction(int prev_desc_logical_no)
329 {
330 	struct ext2_inode inode_journal;
331 	struct ext_filesystem *fs = get_fs();
332 	struct journal_header_t *jdb;
333 	long int blknr;
334 	char *p_jdb;
335 	int ofs, flags;
336 	int i;
337 	struct ext3_journal_block_tag *tag;
338 	char *temp_buff = zalloc(fs->blksz);
339 	char *metadata_buff = zalloc(fs->blksz);
340 	if (!temp_buff || !metadata_buff)
341 		goto fail;
342 	i = prev_desc_logical_no;
343 	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
344 			  (struct ext2_inode *)&inode_journal);
345 	blknr = read_allocated_block((struct ext2_inode *)
346 				     &inode_journal, i);
347 	ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
348 		       temp_buff);
349 	p_jdb = (char *)temp_buff;
350 	jdb = (struct journal_header_t *) temp_buff;
351 	ofs = sizeof(struct journal_header_t);
352 
353 	do {
354 		tag = (struct ext3_journal_block_tag *)&p_jdb[ofs];
355 		ofs += sizeof(struct ext3_journal_block_tag);
356 
357 		if (ofs > fs->blksz)
358 			break;
359 
360 		flags = be32_to_cpu(tag->flags);
361 		if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
362 			ofs += 16;
363 
364 		i++;
365 		debug("\t\ttag %u\n", be32_to_cpu(tag->block));
366 		if (revk_blk_list != NULL) {
367 			if (check_blknr_for_revoke(be32_to_cpu(tag->block),
368 				be32_to_cpu(jdb->h_sequence)) == 0)
369 				continue;
370 		}
371 		blknr = read_allocated_block(&inode_journal, i);
372 		ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
373 			       fs->blksz, metadata_buff);
374 		put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz),
375 			 metadata_buff, (uint32_t) fs->blksz);
376 	} while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
377 fail:
378 	free(temp_buff);
379 	free(metadata_buff);
380 }
381 
382 void print_jrnl_status(int recovery_flag)
383 {
384 	if (recovery_flag == RECOVER)
385 		printf("Journal Recovery Completed\n");
386 	else
387 		printf("Journal Scan Completed\n");
388 }
389 
390 int ext4fs_check_journal_state(int recovery_flag)
391 {
392 	int i;
393 	int DB_FOUND = NO;
394 	long int blknr;
395 	int transaction_state = TRANSACTION_COMPLETE;
396 	int prev_desc_logical_no = 0;
397 	int curr_desc_logical_no = 0;
398 	int ofs, flags;
399 	struct ext2_inode inode_journal;
400 	struct journal_superblock_t *jsb = NULL;
401 	struct journal_header_t *jdb = NULL;
402 	char *p_jdb = NULL;
403 	struct ext3_journal_block_tag *tag = NULL;
404 	char *temp_buff = NULL;
405 	char *temp_buff1 = NULL;
406 	struct ext_filesystem *fs = get_fs();
407 
408 	temp_buff = zalloc(fs->blksz);
409 	if (!temp_buff)
410 		return -ENOMEM;
411 	temp_buff1 = zalloc(fs->blksz);
412 	if (!temp_buff1) {
413 		free(temp_buff);
414 		return -ENOMEM;
415 	}
416 
417 	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
418 	blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK);
419 	ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
420 		       temp_buff);
421 	jsb = (struct journal_superblock_t *) temp_buff;
422 
423 	if (fs->sb->feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
424 		if (recovery_flag == RECOVER)
425 			printf("Recovery required\n");
426 	} else {
427 		if (recovery_flag == RECOVER)
428 			printf("File System is consistent\n");
429 		goto end;
430 	}
431 
432 	if (be32_to_cpu(jsb->s_start) == 0)
433 		goto end;
434 
435 	if (!(jsb->s_feature_compat &
436 				cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM)))
437 		jsb->s_feature_compat |=
438 				cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
439 
440 	i = be32_to_cpu(jsb->s_first);
441 	while (1) {
442 		blknr = read_allocated_block(&inode_journal, i);
443 		memset(temp_buff1, '\0', fs->blksz);
444 		ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
445 			       0, fs->blksz, temp_buff1);
446 		jdb = (struct journal_header_t *) temp_buff1;
447 
448 		if (be32_to_cpu(jdb->h_blocktype) ==
449 		    EXT3_JOURNAL_DESCRIPTOR_BLOCK) {
450 			if (be32_to_cpu(jdb->h_sequence) !=
451 			    be32_to_cpu(jsb->s_sequence)) {
452 				print_jrnl_status(recovery_flag);
453 				break;
454 			}
455 
456 			curr_desc_logical_no = i;
457 			if (transaction_state == TRANSACTION_COMPLETE)
458 				transaction_state = TRANSACTION_RUNNING;
459 			else
460 				return -1;
461 			p_jdb = (char *)temp_buff1;
462 			ofs = sizeof(struct journal_header_t);
463 			do {
464 				tag = (struct ext3_journal_block_tag *)
465 				    &p_jdb[ofs];
466 				ofs += sizeof(struct ext3_journal_block_tag);
467 				if (ofs > fs->blksz)
468 					break;
469 				flags = be32_to_cpu(tag->flags);
470 				if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
471 					ofs += 16;
472 				i++;
473 				debug("\t\ttag %u\n", be32_to_cpu(tag->block));
474 			} while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
475 			i++;
476 			DB_FOUND = YES;
477 		} else if (be32_to_cpu(jdb->h_blocktype) ==
478 				EXT3_JOURNAL_COMMIT_BLOCK) {
479 			if (be32_to_cpu(jdb->h_sequence) !=
480 			     be32_to_cpu(jsb->s_sequence)) {
481 				print_jrnl_status(recovery_flag);
482 				break;
483 			}
484 
485 			if (transaction_state == TRANSACTION_RUNNING ||
486 					(DB_FOUND == NO)) {
487 				transaction_state = TRANSACTION_COMPLETE;
488 				i++;
489 				jsb->s_sequence =
490 					cpu_to_be32(be32_to_cpu(
491 						jsb->s_sequence) + 1);
492 			}
493 			prev_desc_logical_no = curr_desc_logical_no;
494 			if ((recovery_flag == RECOVER) && (DB_FOUND == YES))
495 				recover_transaction(prev_desc_logical_no);
496 
497 			DB_FOUND = NO;
498 		} else if (be32_to_cpu(jdb->h_blocktype) ==
499 				EXT3_JOURNAL_REVOKE_BLOCK) {
500 			if (be32_to_cpu(jdb->h_sequence) !=
501 			    be32_to_cpu(jsb->s_sequence)) {
502 				print_jrnl_status(recovery_flag);
503 				break;
504 			}
505 			if (recovery_flag == SCAN)
506 				ext4fs_push_revoke_blk((char *)jdb);
507 			i++;
508 		} else {
509 			debug("Else Case\n");
510 			if (be32_to_cpu(jdb->h_sequence) !=
511 			    be32_to_cpu(jsb->s_sequence)) {
512 				print_jrnl_status(recovery_flag);
513 				break;
514 			}
515 		}
516 	}
517 
518 end:
519 	if (recovery_flag == RECOVER) {
520 		jsb->s_start = cpu_to_be32(1);
521 		jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1);
522 		/* get the superblock */
523 		ext4_read_superblock((char *)fs->sb);
524 		fs->sb->feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
525 
526 		/* Update the super block */
527 		put_ext4((uint64_t) (SUPERBLOCK_SIZE),
528 			 (struct ext2_sblock *)fs->sb,
529 			 (uint32_t) SUPERBLOCK_SIZE);
530 		ext4_read_superblock((char *)fs->sb);
531 
532 		blknr = read_allocated_block(&inode_journal,
533 					 EXT2_JOURNAL_SUPERBLOCK);
534 		put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
535 			 (struct journal_superblock_t *)temp_buff,
536 			 (uint32_t) fs->blksz);
537 		ext4fs_free_revoke_blks();
538 	}
539 	free(temp_buff);
540 	free(temp_buff1);
541 
542 	return 0;
543 }
544 
545 static void update_descriptor_block(long int blknr)
546 {
547 	int i;
548 	long int jsb_blknr;
549 	struct journal_header_t jdb;
550 	struct ext3_journal_block_tag tag;
551 	struct ext2_inode inode_journal;
552 	struct journal_superblock_t *jsb = NULL;
553 	char *buf = NULL;
554 	char *temp = NULL;
555 	struct ext_filesystem *fs = get_fs();
556 	char *temp_buff = zalloc(fs->blksz);
557 	if (!temp_buff)
558 		return;
559 
560 	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
561 	jsb_blknr = read_allocated_block(&inode_journal,
562 					 EXT2_JOURNAL_SUPERBLOCK);
563 	ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
564 		       temp_buff);
565 	jsb = (struct journal_superblock_t *) temp_buff;
566 
567 	jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_DESCRIPTOR_BLOCK);
568 	jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
569 	jdb.h_sequence = jsb->s_sequence;
570 	buf = zalloc(fs->blksz);
571 	if (!buf) {
572 		free(temp_buff);
573 		return;
574 	}
575 	temp = buf;
576 	memcpy(buf, &jdb, sizeof(struct journal_header_t));
577 	temp += sizeof(struct journal_header_t);
578 
579 	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
580 		if (journal_ptr[i]->blknr == -1)
581 			break;
582 
583 		tag.block = cpu_to_be32(journal_ptr[i]->blknr);
584 		tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_SAME_UUID);
585 		memcpy(temp, &tag, sizeof(struct ext3_journal_block_tag));
586 		temp = temp + sizeof(struct ext3_journal_block_tag);
587 	}
588 
589 	tag.block = cpu_to_be32(journal_ptr[--i]->blknr);
590 	tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_LAST_TAG);
591 	memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag,
592 	       sizeof(struct ext3_journal_block_tag));
593 	put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
594 
595 	free(temp_buff);
596 	free(buf);
597 }
598 
599 static void update_commit_block(long int blknr)
600 {
601 	struct journal_header_t jdb;
602 	struct ext_filesystem *fs = get_fs();
603 	char *buf = NULL;
604 	struct ext2_inode inode_journal;
605 	struct journal_superblock_t *jsb;
606 	long int jsb_blknr;
607 	char *temp_buff = zalloc(fs->blksz);
608 	if (!temp_buff)
609 		return;
610 
611 	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
612 			  &inode_journal);
613 	jsb_blknr = read_allocated_block(&inode_journal,
614 					 EXT2_JOURNAL_SUPERBLOCK);
615 	ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
616 		       temp_buff);
617 	jsb = (struct journal_superblock_t *) temp_buff;
618 
619 	jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_COMMIT_BLOCK);
620 	jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
621 	jdb.h_sequence = jsb->s_sequence;
622 	buf = zalloc(fs->blksz);
623 	if (!buf) {
624 		free(temp_buff);
625 		return;
626 	}
627 	memcpy(buf, &jdb, sizeof(struct journal_header_t));
628 	put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
629 
630 	free(temp_buff);
631 	free(buf);
632 }
633 
634 void ext4fs_update_journal(void)
635 {
636 	struct ext2_inode inode_journal;
637 	struct ext_filesystem *fs = get_fs();
638 	long int blknr;
639 	int i;
640 	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
641 	blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
642 	update_descriptor_block(blknr);
643 	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
644 		if (journal_ptr[i]->blknr == -1)
645 			break;
646 		blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
647 		put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
648 			 journal_ptr[i]->buf, fs->blksz);
649 	}
650 	blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
651 	update_commit_block(blknr);
652 	printf("update journal finished\n");
653 }
654