xref: /openbmc/u-boot/fs/ext4/ext4_journal.c (revision a2ac1b3a)
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(blknr * fs->sect_perblk, 0, fs->blksz, temp_buff);
364 	p_jdb = (char *)temp_buff;
365 	jdb = (struct journal_header_t *) temp_buff;
366 	ofs = sizeof(struct journal_header_t);
367 
368 	do {
369 		tag = (struct ext3_journal_block_tag *)&p_jdb[ofs];
370 		ofs += sizeof(struct ext3_journal_block_tag);
371 
372 		if (ofs > fs->blksz)
373 			break;
374 
375 		flags = be32_to_cpu(tag->flags);
376 		if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
377 			ofs += 16;
378 
379 		i++;
380 		debug("\t\ttag %u\n", be32_to_cpu(tag->block));
381 		if (revk_blk_list != NULL) {
382 			if (check_blknr_for_revoke(be32_to_cpu(tag->block),
383 				be32_to_cpu(jdb->h_sequence)) == 0)
384 				continue;
385 		}
386 		blknr = read_allocated_block(&inode_journal, i);
387 		ext4fs_devread(blknr * fs->sect_perblk, 0,
388 			       fs->blksz, metadata_buff);
389 		put_ext4((uint64_t)(be32_to_cpu(tag->block) * fs->blksz),
390 			 metadata_buff, (uint32_t) fs->blksz);
391 	} while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
392 fail:
393 	free(temp_buff);
394 	free(metadata_buff);
395 }
396 
397 void print_jrnl_status(int recovery_flag)
398 {
399 	if (recovery_flag == RECOVER)
400 		printf("Journal Recovery Completed\n");
401 	else
402 		printf("Journal Scan Completed\n");
403 }
404 
405 int ext4fs_check_journal_state(int recovery_flag)
406 {
407 	int i;
408 	int DB_FOUND = NO;
409 	long int blknr;
410 	int transaction_state = TRANSACTION_COMPLETE;
411 	int prev_desc_logical_no = 0;
412 	int curr_desc_logical_no = 0;
413 	int ofs, flags, block;
414 	struct ext2_inode inode_journal;
415 	struct journal_superblock_t *jsb = NULL;
416 	struct journal_header_t *jdb = NULL;
417 	char *p_jdb = NULL;
418 	struct ext3_journal_block_tag *tag = NULL;
419 	char *temp_buff = NULL;
420 	char *temp_buff1 = NULL;
421 	struct ext_filesystem *fs = get_fs();
422 
423 	temp_buff = zalloc(fs->blksz);
424 	if (!temp_buff)
425 		return -ENOMEM;
426 	temp_buff1 = zalloc(fs->blksz);
427 	if (!temp_buff1) {
428 		free(temp_buff);
429 		return -ENOMEM;
430 	}
431 
432 	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
433 	blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK);
434 	ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, temp_buff);
435 	jsb = (struct journal_superblock_t *) temp_buff;
436 
437 	if (fs->sb->feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
438 		if (recovery_flag == RECOVER)
439 			printf("Recovery required\n");
440 	} else {
441 		if (recovery_flag == RECOVER)
442 			printf("File System is consistent\n");
443 		goto end;
444 	}
445 
446 	if (be32_to_cpu(jsb->s_start) == 0)
447 		goto end;
448 
449 	if (!(jsb->s_feature_compat &
450 				cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM)))
451 		jsb->s_feature_compat |=
452 				cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
453 
454 	i = be32_to_cpu(jsb->s_first);
455 	while (1) {
456 		block = be32_to_cpu(jsb->s_first);
457 		blknr = read_allocated_block(&inode_journal, i);
458 		memset(temp_buff1, '\0', fs->blksz);
459 		ext4fs_devread(blknr * fs->sect_perblk,
460 			       0, fs->blksz, temp_buff1);
461 		jdb = (struct journal_header_t *) temp_buff1;
462 
463 		if (be32_to_cpu(jdb->h_blocktype) ==
464 		    EXT3_JOURNAL_DESCRIPTOR_BLOCK) {
465 			if (be32_to_cpu(jdb->h_sequence) !=
466 			    be32_to_cpu(jsb->s_sequence)) {
467 				print_jrnl_status(recovery_flag);
468 				break;
469 			}
470 
471 			curr_desc_logical_no = i;
472 			if (transaction_state == TRANSACTION_COMPLETE)
473 				transaction_state = TRANSACTION_RUNNING;
474 			else
475 				return -1;
476 			p_jdb = (char *)temp_buff1;
477 			ofs = sizeof(struct journal_header_t);
478 			do {
479 				tag = (struct ext3_journal_block_tag *)
480 				    &p_jdb[ofs];
481 				ofs += sizeof(struct ext3_journal_block_tag);
482 				if (ofs > fs->blksz)
483 					break;
484 				flags = be32_to_cpu(tag->flags);
485 				if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
486 					ofs += 16;
487 				i++;
488 				debug("\t\ttag %u\n", be32_to_cpu(tag->block));
489 			} while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
490 			i++;
491 			DB_FOUND = YES;
492 		} else if (be32_to_cpu(jdb->h_blocktype) ==
493 				EXT3_JOURNAL_COMMIT_BLOCK) {
494 			if (be32_to_cpu(jdb->h_sequence) !=
495 			     be32_to_cpu(jsb->s_sequence)) {
496 				print_jrnl_status(recovery_flag);
497 				break;
498 			}
499 
500 			if (transaction_state == TRANSACTION_RUNNING ||
501 					(DB_FOUND == NO)) {
502 				transaction_state = TRANSACTION_COMPLETE;
503 				i++;
504 				jsb->s_sequence =
505 					cpu_to_be32(be32_to_cpu(
506 						jsb->s_sequence) + 1);
507 			}
508 			prev_desc_logical_no = curr_desc_logical_no;
509 			if ((recovery_flag == RECOVER) && (DB_FOUND == YES))
510 				recover_transaction(prev_desc_logical_no);
511 
512 			DB_FOUND = NO;
513 		} else if (be32_to_cpu(jdb->h_blocktype) ==
514 				EXT3_JOURNAL_REVOKE_BLOCK) {
515 			if (be32_to_cpu(jdb->h_sequence) !=
516 			    be32_to_cpu(jsb->s_sequence)) {
517 				print_jrnl_status(recovery_flag);
518 				break;
519 			}
520 			if (recovery_flag == SCAN)
521 				ext4fs_push_revoke_blk((char *)jdb);
522 			i++;
523 		} else {
524 			debug("Else Case\n");
525 			if (be32_to_cpu(jdb->h_sequence) !=
526 			    be32_to_cpu(jsb->s_sequence)) {
527 				print_jrnl_status(recovery_flag);
528 				break;
529 			}
530 		}
531 	}
532 
533 end:
534 	if (recovery_flag == RECOVER) {
535 		jsb->s_start = cpu_to_be32(1);
536 		jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1);
537 		/* get the superblock */
538 		ext4fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE,
539 			       (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 		ext4fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE,
547 			       (char *)fs->sb);
548 
549 		blknr = read_allocated_block(&inode_journal,
550 					 EXT2_JOURNAL_SUPERBLOCK);
551 		put_ext4((uint64_t) (blknr * fs->blksz),
552 			 (struct journal_superblock_t *)temp_buff,
553 			 (uint32_t) fs->blksz);
554 		ext4fs_free_revoke_blks();
555 	}
556 	free(temp_buff);
557 	free(temp_buff1);
558 
559 	return 0;
560 }
561 
562 static void update_descriptor_block(long int blknr)
563 {
564 	int i;
565 	long int jsb_blknr;
566 	struct journal_header_t jdb;
567 	struct ext3_journal_block_tag tag;
568 	struct ext2_inode inode_journal;
569 	struct journal_superblock_t *jsb = NULL;
570 	char *buf = NULL;
571 	char *temp = NULL;
572 	struct ext_filesystem *fs = get_fs();
573 	char *temp_buff = zalloc(fs->blksz);
574 	if (!temp_buff)
575 		return;
576 
577 	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
578 	jsb_blknr = read_allocated_block(&inode_journal,
579 					 EXT2_JOURNAL_SUPERBLOCK);
580 	ext4fs_devread(jsb_blknr * fs->sect_perblk, 0, fs->blksz, 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, &inode_journal);
628 	jsb_blknr = read_allocated_block(&inode_journal,
629 					 EXT2_JOURNAL_SUPERBLOCK);
630 	ext4fs_devread(jsb_blknr * fs->sect_perblk, 0, fs->blksz, temp_buff);
631 	jsb = (struct journal_superblock_t *) temp_buff;
632 
633 	jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_COMMIT_BLOCK);
634 	jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
635 	jdb.h_sequence = jsb->s_sequence;
636 	buf = zalloc(fs->blksz);
637 	if (!buf) {
638 		free(temp_buff);
639 		return;
640 	}
641 	memcpy(buf, &jdb, sizeof(struct journal_header_t));
642 	put_ext4((uint64_t) (blknr * fs->blksz), buf, (uint32_t) fs->blksz);
643 
644 	free(temp_buff);
645 	free(buf);
646 }
647 
648 void ext4fs_update_journal(void)
649 {
650 	struct ext2_inode inode_journal;
651 	struct ext_filesystem *fs = get_fs();
652 	long int blknr;
653 	int i;
654 	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
655 	blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
656 	update_descriptor_block(blknr);
657 	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
658 		if (journal_ptr[i]->blknr == -1)
659 			break;
660 		blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
661 		put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
662 			 journal_ptr[i]->buf, fs->blksz);
663 	}
664 	blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
665 	update_commit_block(blknr);
666 	printf("update journal finished\n");
667 }
668