xref: /openbmc/u-boot/fs/ext4/ext4_journal.c (revision c9af6673)
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, uint32_t 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, uint32_t 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 	if (dirty_block_ptr[gd_index]->buf)
194 		assert(dirty_block_ptr[gd_index]->blknr == blknr);
195 	else
196 		dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz);
197 
198 	if (!dirty_block_ptr[gd_index]->buf)
199 		return -ENOMEM;
200 	memcpy(dirty_block_ptr[gd_index]->buf, metadata_buffer, fs->blksz);
201 	dirty_block_ptr[gd_index++]->blknr = blknr;
202 
203 	return 0;
204 }
205 
206 void print_revoke_blks(char *revk_blk)
207 {
208 	int offset;
209 	int max;
210 	long int blocknr;
211 	struct journal_revoke_header_t *header;
212 
213 	if (revk_blk == NULL)
214 		return;
215 
216 	header = (struct journal_revoke_header_t *) revk_blk;
217 	offset = sizeof(struct journal_revoke_header_t);
218 	max = be32_to_cpu(header->r_count);
219 	printf("total bytes %d\n", max);
220 
221 	while (offset < max) {
222 		blocknr = be32_to_cpu(*((__be32 *)(revk_blk + offset)));
223 		printf("revoke blknr is %ld\n", blocknr);
224 		offset += 4;
225 	}
226 }
227 
228 static struct revoke_blk_list *_get_node(void)
229 {
230 	struct revoke_blk_list *tmp_node;
231 	tmp_node = zalloc(sizeof(struct revoke_blk_list));
232 	if (tmp_node == NULL)
233 		return NULL;
234 	tmp_node->content = NULL;
235 	tmp_node->next = NULL;
236 
237 	return tmp_node;
238 }
239 
240 void ext4fs_push_revoke_blk(char *buffer)
241 {
242 	struct revoke_blk_list *node = NULL;
243 	struct ext_filesystem *fs = get_fs();
244 	if (buffer == NULL) {
245 		printf("buffer ptr is NULL\n");
246 		return;
247 	}
248 	node = _get_node();
249 	if (!node) {
250 		printf("_get_node: malloc failed\n");
251 		return;
252 	}
253 
254 	node->content = zalloc(fs->blksz);
255 	if (node->content == NULL)
256 		return;
257 	memcpy(node->content, buffer, fs->blksz);
258 
259 	if (first_node == true) {
260 		revk_blk_list = node;
261 		prev_node = node;
262 		 first_node = false;
263 	} else {
264 		prev_node->next = node;
265 		prev_node = node;
266 	}
267 }
268 
269 void ext4fs_free_revoke_blks(void)
270 {
271 	struct revoke_blk_list *tmp_node = revk_blk_list;
272 	struct revoke_blk_list *next_node = NULL;
273 
274 	while (tmp_node != NULL) {
275 		if (tmp_node->content)
276 			free(tmp_node->content);
277 		tmp_node = tmp_node->next;
278 	}
279 
280 	tmp_node = revk_blk_list;
281 	while (tmp_node != NULL) {
282 		next_node = tmp_node->next;
283 		free(tmp_node);
284 		tmp_node = next_node;
285 	}
286 
287 	revk_blk_list = NULL;
288 	prev_node = NULL;
289 	first_node = true;
290 }
291 
292 int check_blknr_for_revoke(long int blknr, int sequence_no)
293 {
294 	struct journal_revoke_header_t *header;
295 	int offset;
296 	int max;
297 	long int blocknr;
298 	char *revk_blk;
299 	struct revoke_blk_list *tmp_revk_node = revk_blk_list;
300 	while (tmp_revk_node != NULL) {
301 		revk_blk = tmp_revk_node->content;
302 
303 		header = (struct journal_revoke_header_t *) revk_blk;
304 		if (sequence_no < be32_to_cpu(header->r_header.h_sequence)) {
305 			offset = sizeof(struct journal_revoke_header_t);
306 			max = be32_to_cpu(header->r_count);
307 
308 			while (offset < max) {
309 				blocknr = be32_to_cpu(*((__be32 *)
310 						  (revk_blk + offset)));
311 				if (blocknr == blknr)
312 					goto found;
313 				offset += 4;
314 			}
315 		}
316 		tmp_revk_node = tmp_revk_node->next;
317 	}
318 
319 	return -1;
320 
321 found:
322 	return 0;
323 }
324 
325 /*
326  * This function parses the journal blocks and replays the
327  * suceessful transactions. A transaction is successfull
328  * if commit block is found for a descriptor block
329  * The tags in descriptor block contain the disk block
330  * numbers of the metadata  to be replayed
331  */
332 void recover_transaction(int prev_desc_logical_no)
333 {
334 	struct ext2_inode inode_journal;
335 	struct ext_filesystem *fs = get_fs();
336 	struct journal_header_t *jdb;
337 	long int blknr;
338 	char *p_jdb;
339 	int ofs, flags;
340 	int i;
341 	struct ext3_journal_block_tag *tag;
342 	char *temp_buff = zalloc(fs->blksz);
343 	char *metadata_buff = zalloc(fs->blksz);
344 	if (!temp_buff || !metadata_buff)
345 		goto fail;
346 	i = prev_desc_logical_no;
347 	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
348 			  (struct ext2_inode *)&inode_journal);
349 	blknr = read_allocated_block((struct ext2_inode *)
350 				     &inode_journal, i);
351 	ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
352 		       temp_buff);
353 	p_jdb = (char *)temp_buff;
354 	jdb = (struct journal_header_t *) temp_buff;
355 	ofs = sizeof(struct journal_header_t);
356 
357 	do {
358 		tag = (struct ext3_journal_block_tag *)&p_jdb[ofs];
359 		ofs += sizeof(struct ext3_journal_block_tag);
360 
361 		if (ofs > fs->blksz)
362 			break;
363 
364 		flags = be32_to_cpu(tag->flags);
365 		if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
366 			ofs += 16;
367 
368 		i++;
369 		debug("\t\ttag %u\n", be32_to_cpu(tag->block));
370 		if (revk_blk_list != NULL) {
371 			if (check_blknr_for_revoke(be32_to_cpu(tag->block),
372 				be32_to_cpu(jdb->h_sequence)) == 0)
373 				continue;
374 		}
375 		blknr = read_allocated_block(&inode_journal, i);
376 		ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
377 			       fs->blksz, metadata_buff);
378 		put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz),
379 			 metadata_buff, (uint32_t) fs->blksz);
380 	} while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
381 fail:
382 	free(temp_buff);
383 	free(metadata_buff);
384 }
385 
386 void print_jrnl_status(int recovery_flag)
387 {
388 	if (recovery_flag == RECOVER)
389 		printf("Journal Recovery Completed\n");
390 	else
391 		printf("Journal Scan Completed\n");
392 }
393 
394 int ext4fs_check_journal_state(int recovery_flag)
395 {
396 	int i;
397 	int DB_FOUND = NO;
398 	long int blknr;
399 	int transaction_state = TRANSACTION_COMPLETE;
400 	int prev_desc_logical_no = 0;
401 	int curr_desc_logical_no = 0;
402 	int ofs, flags;
403 	struct ext2_inode inode_journal;
404 	struct journal_superblock_t *jsb = NULL;
405 	struct journal_header_t *jdb = NULL;
406 	char *p_jdb = NULL;
407 	struct ext3_journal_block_tag *tag = NULL;
408 	char *temp_buff = NULL;
409 	char *temp_buff1 = NULL;
410 	struct ext_filesystem *fs = get_fs();
411 
412 	temp_buff = zalloc(fs->blksz);
413 	if (!temp_buff)
414 		return -ENOMEM;
415 	temp_buff1 = zalloc(fs->blksz);
416 	if (!temp_buff1) {
417 		free(temp_buff);
418 		return -ENOMEM;
419 	}
420 
421 	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
422 	blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK);
423 	ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
424 		       temp_buff);
425 	jsb = (struct journal_superblock_t *) temp_buff;
426 
427 	if (le32_to_cpu(fs->sb->feature_incompat) & EXT3_FEATURE_INCOMPAT_RECOVER) {
428 		if (recovery_flag == RECOVER)
429 			printf("Recovery required\n");
430 	} else {
431 		if (recovery_flag == RECOVER)
432 			printf("File System is consistent\n");
433 		goto end;
434 	}
435 
436 	if (be32_to_cpu(jsb->s_start) == 0)
437 		goto end;
438 
439 	if (!(jsb->s_feature_compat &
440 				cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM)))
441 		jsb->s_feature_compat |=
442 				cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
443 
444 	i = be32_to_cpu(jsb->s_first);
445 	while (1) {
446 		blknr = read_allocated_block(&inode_journal, i);
447 		memset(temp_buff1, '\0', fs->blksz);
448 		ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
449 			       0, fs->blksz, temp_buff1);
450 		jdb = (struct journal_header_t *) temp_buff1;
451 
452 		if (be32_to_cpu(jdb->h_blocktype) ==
453 		    EXT3_JOURNAL_DESCRIPTOR_BLOCK) {
454 			if (be32_to_cpu(jdb->h_sequence) !=
455 			    be32_to_cpu(jsb->s_sequence)) {
456 				print_jrnl_status(recovery_flag);
457 				break;
458 			}
459 
460 			curr_desc_logical_no = i;
461 			if (transaction_state == TRANSACTION_COMPLETE)
462 				transaction_state = TRANSACTION_RUNNING;
463 			else
464 				return -1;
465 			p_jdb = (char *)temp_buff1;
466 			ofs = sizeof(struct journal_header_t);
467 			do {
468 				tag = (struct ext3_journal_block_tag *)
469 				    &p_jdb[ofs];
470 				ofs += sizeof(struct ext3_journal_block_tag);
471 				if (ofs > fs->blksz)
472 					break;
473 				flags = be32_to_cpu(tag->flags);
474 				if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
475 					ofs += 16;
476 				i++;
477 				debug("\t\ttag %u\n", be32_to_cpu(tag->block));
478 			} while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
479 			i++;
480 			DB_FOUND = YES;
481 		} else if (be32_to_cpu(jdb->h_blocktype) ==
482 				EXT3_JOURNAL_COMMIT_BLOCK) {
483 			if (be32_to_cpu(jdb->h_sequence) !=
484 			     be32_to_cpu(jsb->s_sequence)) {
485 				print_jrnl_status(recovery_flag);
486 				break;
487 			}
488 
489 			if (transaction_state == TRANSACTION_RUNNING ||
490 					(DB_FOUND == NO)) {
491 				transaction_state = TRANSACTION_COMPLETE;
492 				i++;
493 				jsb->s_sequence =
494 					cpu_to_be32(be32_to_cpu(
495 						jsb->s_sequence) + 1);
496 			}
497 			prev_desc_logical_no = curr_desc_logical_no;
498 			if ((recovery_flag == RECOVER) && (DB_FOUND == YES))
499 				recover_transaction(prev_desc_logical_no);
500 
501 			DB_FOUND = NO;
502 		} else if (be32_to_cpu(jdb->h_blocktype) ==
503 				EXT3_JOURNAL_REVOKE_BLOCK) {
504 			if (be32_to_cpu(jdb->h_sequence) !=
505 			    be32_to_cpu(jsb->s_sequence)) {
506 				print_jrnl_status(recovery_flag);
507 				break;
508 			}
509 			if (recovery_flag == SCAN)
510 				ext4fs_push_revoke_blk((char *)jdb);
511 			i++;
512 		} else {
513 			debug("Else Case\n");
514 			if (be32_to_cpu(jdb->h_sequence) !=
515 			    be32_to_cpu(jsb->s_sequence)) {
516 				print_jrnl_status(recovery_flag);
517 				break;
518 			}
519 		}
520 	}
521 
522 end:
523 	if (recovery_flag == RECOVER) {
524 		uint32_t new_feature_incompat;
525 		jsb->s_start = cpu_to_be32(1);
526 		jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1);
527 		/* get the superblock */
528 		ext4_read_superblock((char *)fs->sb);
529 		new_feature_incompat = le32_to_cpu(fs->sb->feature_incompat);
530 		new_feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
531 		fs->sb->feature_incompat = cpu_to_le32(new_feature_incompat);
532 
533 		/* Update the super block */
534 		put_ext4((uint64_t) (SUPERBLOCK_SIZE),
535 			 (struct ext2_sblock *)fs->sb,
536 			 (uint32_t) SUPERBLOCK_SIZE);
537 		ext4_read_superblock((char *)fs->sb);
538 
539 		blknr = read_allocated_block(&inode_journal,
540 					 EXT2_JOURNAL_SUPERBLOCK);
541 		put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
542 			 (struct journal_superblock_t *)temp_buff,
543 			 (uint32_t) fs->blksz);
544 		ext4fs_free_revoke_blks();
545 	}
546 	free(temp_buff);
547 	free(temp_buff1);
548 
549 	return 0;
550 }
551 
552 static void update_descriptor_block(long int blknr)
553 {
554 	int i;
555 	long int jsb_blknr;
556 	struct journal_header_t jdb;
557 	struct ext3_journal_block_tag tag;
558 	struct ext2_inode inode_journal;
559 	struct journal_superblock_t *jsb = NULL;
560 	char *buf = NULL;
561 	char *temp = NULL;
562 	struct ext_filesystem *fs = get_fs();
563 	char *temp_buff = zalloc(fs->blksz);
564 	if (!temp_buff)
565 		return;
566 
567 	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
568 	jsb_blknr = read_allocated_block(&inode_journal,
569 					 EXT2_JOURNAL_SUPERBLOCK);
570 	ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
571 		       temp_buff);
572 	jsb = (struct journal_superblock_t *) temp_buff;
573 
574 	jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_DESCRIPTOR_BLOCK);
575 	jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
576 	jdb.h_sequence = jsb->s_sequence;
577 	buf = zalloc(fs->blksz);
578 	if (!buf) {
579 		free(temp_buff);
580 		return;
581 	}
582 	temp = buf;
583 	memcpy(buf, &jdb, sizeof(struct journal_header_t));
584 	temp += sizeof(struct journal_header_t);
585 
586 	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
587 		if (journal_ptr[i]->blknr == -1)
588 			break;
589 
590 		tag.block = cpu_to_be32(journal_ptr[i]->blknr);
591 		tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_SAME_UUID);
592 		memcpy(temp, &tag, sizeof(struct ext3_journal_block_tag));
593 		temp = temp + sizeof(struct ext3_journal_block_tag);
594 	}
595 
596 	tag.block = cpu_to_be32(journal_ptr[--i]->blknr);
597 	tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_LAST_TAG);
598 	memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag,
599 	       sizeof(struct ext3_journal_block_tag));
600 	put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
601 
602 	free(temp_buff);
603 	free(buf);
604 }
605 
606 static void update_commit_block(long int blknr)
607 {
608 	struct journal_header_t jdb;
609 	struct ext_filesystem *fs = get_fs();
610 	char *buf = NULL;
611 	struct ext2_inode inode_journal;
612 	struct journal_superblock_t *jsb;
613 	long int jsb_blknr;
614 	char *temp_buff = zalloc(fs->blksz);
615 	if (!temp_buff)
616 		return;
617 
618 	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
619 			  &inode_journal);
620 	jsb_blknr = read_allocated_block(&inode_journal,
621 					 EXT2_JOURNAL_SUPERBLOCK);
622 	ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
623 		       temp_buff);
624 	jsb = (struct journal_superblock_t *) temp_buff;
625 
626 	jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_COMMIT_BLOCK);
627 	jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
628 	jdb.h_sequence = jsb->s_sequence;
629 	buf = zalloc(fs->blksz);
630 	if (!buf) {
631 		free(temp_buff);
632 		return;
633 	}
634 	memcpy(buf, &jdb, sizeof(struct journal_header_t));
635 	put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
636 
637 	free(temp_buff);
638 	free(buf);
639 }
640 
641 void ext4fs_update_journal(void)
642 {
643 	struct ext2_inode inode_journal;
644 	struct ext_filesystem *fs = get_fs();
645 	long int blknr;
646 	int i;
647 	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
648 	blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
649 	update_descriptor_block(blknr);
650 	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
651 		if (journal_ptr[i]->blknr == -1)
652 			break;
653 		blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
654 		put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
655 			 journal_ptr[i]->buf, fs->blksz);
656 	}
657 	blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
658 	update_commit_block(blknr);
659 	printf("update journal finished\n");
660 }
661