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