blob: 868a2c1804a5bc7eca6ac271229e890e291144b5 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Uma Shankara74a99a2012-05-25 21:22:49 +05302/*
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
Uma Shankara74a99a2012-05-25 21:22:49 +053014 */
15
Simon Glass655306c2020-05-10 11:39:58 -060016#include <blk.h>
Uma Shankara74a99a2012-05-25 21:22:49 +053017#include <ext4fs.h>
Simon Glass0f2af882020-05-10 11:40:05 -060018#include <log.h>
Uma Shankara74a99a2012-05-25 21:22:49 +053019#include <malloc.h>
20#include <ext_common.h>
21#include "ext4_common.h"
22
23static struct revoke_blk_list *revk_blk_list;
24static struct revoke_blk_list *prev_node;
York Sun4a598092013-04-01 11:29:11 -070025static int first_node = true;
Uma Shankara74a99a2012-05-25 21:22:49 +053026
27int gindex;
28int gd_index;
29int jrnl_blk_idx;
30struct journal_log *journal_ptr[MAX_JOURNAL_ENTRIES];
31struct dirty_blocks *dirty_block_ptr[MAX_JOURNAL_ENTRIES];
32
33int ext4fs_init_journal(void)
34{
35 int i;
36 char *temp = NULL;
37 struct ext_filesystem *fs = get_fs();
38
39 /* init globals */
40 revk_blk_list = NULL;
41 prev_node = NULL;
42 gindex = 0;
43 gd_index = 0;
44 jrnl_blk_idx = 1;
45
46 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
47 journal_ptr[i] = zalloc(sizeof(struct journal_log));
48 if (!journal_ptr[i])
49 goto fail;
50 dirty_block_ptr[i] = zalloc(sizeof(struct dirty_blocks));
51 if (!dirty_block_ptr[i])
52 goto fail;
53 journal_ptr[i]->buf = NULL;
54 journal_ptr[i]->blknr = -1;
55
56 dirty_block_ptr[i]->buf = NULL;
57 dirty_block_ptr[i]->blknr = -1;
58 }
59
60 if (fs->blksz == 4096) {
61 temp = zalloc(fs->blksz);
62 if (!temp)
63 goto fail;
64 journal_ptr[gindex]->buf = zalloc(fs->blksz);
65 if (!journal_ptr[gindex]->buf)
66 goto fail;
67 ext4fs_devread(0, 0, fs->blksz, temp);
68 memcpy(temp + SUPERBLOCK_SIZE, fs->sb, SUPERBLOCK_SIZE);
69 memcpy(journal_ptr[gindex]->buf, temp, fs->blksz);
70 journal_ptr[gindex++]->blknr = 0;
71 free(temp);
72 } else {
73 journal_ptr[gindex]->buf = zalloc(fs->blksz);
74 if (!journal_ptr[gindex]->buf)
75 goto fail;
76 memcpy(journal_ptr[gindex]->buf, fs->sb, SUPERBLOCK_SIZE);
77 journal_ptr[gindex++]->blknr = 1;
78 }
79
80 /* Check the file system state using journal super block */
81 if (ext4fs_check_journal_state(SCAN))
82 goto fail;
83 /* Check the file system state using journal super block */
84 if (ext4fs_check_journal_state(RECOVER))
85 goto fail;
86
87 return 0;
88fail:
89 return -1;
90}
91
92void ext4fs_dump_metadata(void)
93{
94 struct ext_filesystem *fs = get_fs();
95 int i;
96 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
97 if (dirty_block_ptr[i]->blknr == -1)
98 break;
99 put_ext4((uint64_t) ((uint64_t)dirty_block_ptr[i]->blknr *
100 (uint64_t)fs->blksz), dirty_block_ptr[i]->buf,
101 fs->blksz);
102 }
103}
104
105void ext4fs_free_journal(void)
106{
107 int i;
108 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
109 if (dirty_block_ptr[i]->blknr == -1)
110 break;
Heinrich Schuchardt8179edf2020-04-28 21:50:02 +0200111 free(dirty_block_ptr[i]->buf);
Uma Shankara74a99a2012-05-25 21:22:49 +0530112 }
113
114 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
115 if (journal_ptr[i]->blknr == -1)
116 break;
Heinrich Schuchardt8179edf2020-04-28 21:50:02 +0200117 free(journal_ptr[i]->buf);
Uma Shankara74a99a2012-05-25 21:22:49 +0530118 }
119
120 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
Heinrich Schuchardt8179edf2020-04-28 21:50:02 +0200121 free(journal_ptr[i]);
122 free(dirty_block_ptr[i]);
Uma Shankara74a99a2012-05-25 21:22:49 +0530123 }
124 gindex = 0;
125 gd_index = 0;
126 jrnl_blk_idx = 1;
127}
128
129int ext4fs_log_gdt(char *gd_table)
130{
131 struct ext_filesystem *fs = get_fs();
132 short i;
133 long int var = fs->gdtable_blkno;
Tony Dinhcd3b16d2025-06-02 21:50:22 -0700134
135 /* Make sure there is enough journal entries */
136 if (fs->no_blk_pergdt > MAX_JOURNAL_ENTRIES) {
137 log_err("*** Not enough journal entries allocated\n");
138 return -ENOMEM;
139 }
140
Uma Shankara74a99a2012-05-25 21:22:49 +0530141 for (i = 0; i < fs->no_blk_pergdt; i++) {
142 journal_ptr[gindex]->buf = zalloc(fs->blksz);
143 if (!journal_ptr[gindex]->buf)
144 return -ENOMEM;
145 memcpy(journal_ptr[gindex]->buf, gd_table, fs->blksz);
146 gd_table += fs->blksz;
147 journal_ptr[gindex++]->blknr = var++;
148 }
149
150 return 0;
151}
152
153/*
154 * This function stores the backup copy of meta data in RAM
155 * journal_buffer -- Buffer containing meta data
156 * blknr -- Block number on disk of the meta data buffer
157 */
Michael Walle13179c22016-09-01 11:21:40 +0200158int ext4fs_log_journal(char *journal_buffer, uint32_t blknr)
Uma Shankara74a99a2012-05-25 21:22:49 +0530159{
160 struct ext_filesystem *fs = get_fs();
161 short i;
162
163 if (!journal_buffer) {
164 printf("Invalid input arguments %s\n", __func__);
165 return -EINVAL;
166 }
167
168 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
169 if (journal_ptr[i]->blknr == -1)
170 break;
171 if (journal_ptr[i]->blknr == blknr)
172 return 0;
173 }
174
175 journal_ptr[gindex]->buf = zalloc(fs->blksz);
176 if (!journal_ptr[gindex]->buf)
177 return -ENOMEM;
178
179 memcpy(journal_ptr[gindex]->buf, journal_buffer, fs->blksz);
180 journal_ptr[gindex++]->blknr = blknr;
181
182 return 0;
183}
184
185/*
186 * This function stores the modified meta data in RAM
187 * metadata_buffer -- Buffer containing meta data
188 * blknr -- Block number on disk of the meta data buffer
189 */
Michael Walle13179c22016-09-01 11:21:40 +0200190int ext4fs_put_metadata(char *metadata_buffer, uint32_t blknr)
Uma Shankara74a99a2012-05-25 21:22:49 +0530191{
192 struct ext_filesystem *fs = get_fs();
193 if (!metadata_buffer) {
194 printf("Invalid input arguments %s\n", __func__);
195 return -EINVAL;
196 }
Stefan Brüns6cc369c2016-09-06 04:36:56 +0200197 if (dirty_block_ptr[gd_index]->buf)
198 assert(dirty_block_ptr[gd_index]->blknr == blknr);
199 else
200 dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz);
201
Uma Shankara74a99a2012-05-25 21:22:49 +0530202 if (!dirty_block_ptr[gd_index]->buf)
203 return -ENOMEM;
204 memcpy(dirty_block_ptr[gd_index]->buf, metadata_buffer, fs->blksz);
205 dirty_block_ptr[gd_index++]->blknr = blknr;
206
207 return 0;
208}
209
210void print_revoke_blks(char *revk_blk)
211{
212 int offset;
213 int max;
214 long int blocknr;
215 struct journal_revoke_header_t *header;
216
217 if (revk_blk == NULL)
218 return;
219
220 header = (struct journal_revoke_header_t *) revk_blk;
221 offset = sizeof(struct journal_revoke_header_t);
222 max = be32_to_cpu(header->r_count);
223 printf("total bytes %d\n", max);
224
225 while (offset < max) {
Michael Walle13179c22016-09-01 11:21:40 +0200226 blocknr = be32_to_cpu(*((__be32 *)(revk_blk + offset)));
Uma Shankara74a99a2012-05-25 21:22:49 +0530227 printf("revoke blknr is %ld\n", blocknr);
228 offset += 4;
229 }
230}
231
232static struct revoke_blk_list *_get_node(void)
233{
234 struct revoke_blk_list *tmp_node;
235 tmp_node = zalloc(sizeof(struct revoke_blk_list));
236 if (tmp_node == NULL)
237 return NULL;
238 tmp_node->content = NULL;
239 tmp_node->next = NULL;
240
241 return tmp_node;
242}
243
244void ext4fs_push_revoke_blk(char *buffer)
245{
246 struct revoke_blk_list *node = NULL;
247 struct ext_filesystem *fs = get_fs();
248 if (buffer == NULL) {
249 printf("buffer ptr is NULL\n");
250 return;
251 }
252 node = _get_node();
253 if (!node) {
254 printf("_get_node: malloc failed\n");
255 return;
256 }
257
258 node->content = zalloc(fs->blksz);
259 if (node->content == NULL)
260 return;
261 memcpy(node->content, buffer, fs->blksz);
262
York Sun4a598092013-04-01 11:29:11 -0700263 if (first_node == true) {
Uma Shankara74a99a2012-05-25 21:22:49 +0530264 revk_blk_list = node;
265 prev_node = node;
York Sun4a598092013-04-01 11:29:11 -0700266 first_node = false;
Uma Shankara74a99a2012-05-25 21:22:49 +0530267 } else {
268 prev_node->next = node;
269 prev_node = node;
270 }
271}
272
273void ext4fs_free_revoke_blks(void)
274{
275 struct revoke_blk_list *tmp_node = revk_blk_list;
276 struct revoke_blk_list *next_node = NULL;
277
278 while (tmp_node != NULL) {
Heinrich Schuchardt8179edf2020-04-28 21:50:02 +0200279 free(tmp_node->content);
Uma Shankara74a99a2012-05-25 21:22:49 +0530280 tmp_node = tmp_node->next;
281 }
282
283 tmp_node = revk_blk_list;
284 while (tmp_node != NULL) {
285 next_node = tmp_node->next;
286 free(tmp_node);
287 tmp_node = next_node;
288 }
289
290 revk_blk_list = NULL;
291 prev_node = NULL;
York Sun4a598092013-04-01 11:29:11 -0700292 first_node = true;
Uma Shankara74a99a2012-05-25 21:22:49 +0530293}
294
295int check_blknr_for_revoke(long int blknr, int sequence_no)
296{
297 struct journal_revoke_header_t *header;
298 int offset;
299 int max;
300 long int blocknr;
301 char *revk_blk;
302 struct revoke_blk_list *tmp_revk_node = revk_blk_list;
303 while (tmp_revk_node != NULL) {
304 revk_blk = tmp_revk_node->content;
305
306 header = (struct journal_revoke_header_t *) revk_blk;
307 if (sequence_no < be32_to_cpu(header->r_header.h_sequence)) {
308 offset = sizeof(struct journal_revoke_header_t);
309 max = be32_to_cpu(header->r_count);
310
311 while (offset < max) {
Michael Walle13179c22016-09-01 11:21:40 +0200312 blocknr = be32_to_cpu(*((__be32 *)
Uma Shankara74a99a2012-05-25 21:22:49 +0530313 (revk_blk + offset)));
314 if (blocknr == blknr)
315 goto found;
316 offset += 4;
317 }
318 }
319 tmp_revk_node = tmp_revk_node->next;
320 }
321
322 return -1;
323
324found:
325 return 0;
326}
327
328/*
329 * This function parses the journal blocks and replays the
330 * suceessful transactions. A transaction is successfull
331 * if commit block is found for a descriptor block
332 * The tags in descriptor block contain the disk block
333 * numbers of the metadata to be replayed
334 */
335void recover_transaction(int prev_desc_logical_no)
336{
337 struct ext2_inode inode_journal;
338 struct ext_filesystem *fs = get_fs();
339 struct journal_header_t *jdb;
340 long int blknr;
341 char *p_jdb;
342 int ofs, flags;
343 int i;
344 struct ext3_journal_block_tag *tag;
345 char *temp_buff = zalloc(fs->blksz);
346 char *metadata_buff = zalloc(fs->blksz);
347 if (!temp_buff || !metadata_buff)
348 goto fail;
349 i = prev_desc_logical_no;
350 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
351 (struct ext2_inode *)&inode_journal);
352 blknr = read_allocated_block((struct ext2_inode *)
Stephen Warren02d6ca72019-01-30 12:58:05 -0700353 &inode_journal, i, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200354 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
355 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530356 p_jdb = (char *)temp_buff;
357 jdb = (struct journal_header_t *) temp_buff;
358 ofs = sizeof(struct journal_header_t);
359
360 do {
Tom Rini035f18e2017-08-20 22:30:15 -0400361 tag = (struct ext3_journal_block_tag *)(p_jdb + ofs);
Uma Shankara74a99a2012-05-25 21:22:49 +0530362 ofs += sizeof(struct ext3_journal_block_tag);
363
364 if (ofs > fs->blksz)
365 break;
366
367 flags = be32_to_cpu(tag->flags);
368 if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
369 ofs += 16;
370
371 i++;
372 debug("\t\ttag %u\n", be32_to_cpu(tag->block));
373 if (revk_blk_list != NULL) {
374 if (check_blknr_for_revoke(be32_to_cpu(tag->block),
375 be32_to_cpu(jdb->h_sequence)) == 0)
376 continue;
377 }
Stephen Warren02d6ca72019-01-30 12:58:05 -0700378 blknr = read_allocated_block(&inode_journal, i, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200379 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
Uma Shankara74a99a2012-05-25 21:22:49 +0530380 fs->blksz, metadata_buff);
Ma Haijune0996ca2014-01-08 08:15:33 +0800381 put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz),
Uma Shankara74a99a2012-05-25 21:22:49 +0530382 metadata_buff, (uint32_t) fs->blksz);
383 } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
384fail:
385 free(temp_buff);
386 free(metadata_buff);
387}
388
389void print_jrnl_status(int recovery_flag)
390{
391 if (recovery_flag == RECOVER)
392 printf("Journal Recovery Completed\n");
393 else
394 printf("Journal Scan Completed\n");
395}
396
397int ext4fs_check_journal_state(int recovery_flag)
398{
399 int i;
400 int DB_FOUND = NO;
401 long int blknr;
402 int transaction_state = TRANSACTION_COMPLETE;
403 int prev_desc_logical_no = 0;
404 int curr_desc_logical_no = 0;
Łukasz Majewskib55a7932012-12-05 08:06:39 +0000405 int ofs, flags;
Uma Shankara74a99a2012-05-25 21:22:49 +0530406 struct ext2_inode inode_journal;
407 struct journal_superblock_t *jsb = NULL;
408 struct journal_header_t *jdb = NULL;
409 char *p_jdb = NULL;
410 struct ext3_journal_block_tag *tag = NULL;
411 char *temp_buff = NULL;
412 char *temp_buff1 = NULL;
413 struct ext_filesystem *fs = get_fs();
414
Arnaud Ferrarisebdcb602020-04-22 12:43:44 +0200415 if (le32_to_cpu(fs->sb->feature_ro_compat) & EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)
416 return 0;
417
Uma Shankara74a99a2012-05-25 21:22:49 +0530418 temp_buff = zalloc(fs->blksz);
419 if (!temp_buff)
420 return -ENOMEM;
421 temp_buff1 = zalloc(fs->blksz);
422 if (!temp_buff1) {
423 free(temp_buff);
424 return -ENOMEM;
425 }
426
427 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
Stephen Warren02d6ca72019-01-30 12:58:05 -0700428 blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK,
429 NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200430 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
431 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530432 jsb = (struct journal_superblock_t *) temp_buff;
433
Michael Walle13179c22016-09-01 11:21:40 +0200434 if (le32_to_cpu(fs->sb->feature_incompat) & EXT3_FEATURE_INCOMPAT_RECOVER) {
Uma Shankara74a99a2012-05-25 21:22:49 +0530435 if (recovery_flag == RECOVER)
436 printf("Recovery required\n");
437 } else {
438 if (recovery_flag == RECOVER)
Heinrich Schuchardtbe740192024-03-20 14:23:52 +0100439 log_debug("File System is consistent\n");
Uma Shankara74a99a2012-05-25 21:22:49 +0530440 goto end;
441 }
442
443 if (be32_to_cpu(jsb->s_start) == 0)
444 goto end;
445
446 if (!(jsb->s_feature_compat &
447 cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM)))
448 jsb->s_feature_compat |=
449 cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
450
451 i = be32_to_cpu(jsb->s_first);
452 while (1) {
Stephen Warren02d6ca72019-01-30 12:58:05 -0700453 blknr = read_allocated_block(&inode_journal, i, NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530454 memset(temp_buff1, '\0', fs->blksz);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200455 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
Uma Shankara74a99a2012-05-25 21:22:49 +0530456 0, fs->blksz, temp_buff1);
457 jdb = (struct journal_header_t *) temp_buff1;
458
459 if (be32_to_cpu(jdb->h_blocktype) ==
460 EXT3_JOURNAL_DESCRIPTOR_BLOCK) {
461 if (be32_to_cpu(jdb->h_sequence) !=
462 be32_to_cpu(jsb->s_sequence)) {
463 print_jrnl_status(recovery_flag);
464 break;
465 }
466
467 curr_desc_logical_no = i;
468 if (transaction_state == TRANSACTION_COMPLETE)
469 transaction_state = TRANSACTION_RUNNING;
470 else
471 return -1;
472 p_jdb = (char *)temp_buff1;
473 ofs = sizeof(struct journal_header_t);
474 do {
475 tag = (struct ext3_journal_block_tag *)
Tom Rini035f18e2017-08-20 22:30:15 -0400476 (p_jdb + ofs);
Uma Shankara74a99a2012-05-25 21:22:49 +0530477 ofs += sizeof(struct ext3_journal_block_tag);
478 if (ofs > fs->blksz)
479 break;
480 flags = be32_to_cpu(tag->flags);
481 if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
482 ofs += 16;
483 i++;
484 debug("\t\ttag %u\n", be32_to_cpu(tag->block));
485 } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
486 i++;
487 DB_FOUND = YES;
488 } else if (be32_to_cpu(jdb->h_blocktype) ==
489 EXT3_JOURNAL_COMMIT_BLOCK) {
490 if (be32_to_cpu(jdb->h_sequence) !=
491 be32_to_cpu(jsb->s_sequence)) {
492 print_jrnl_status(recovery_flag);
493 break;
494 }
495
496 if (transaction_state == TRANSACTION_RUNNING ||
497 (DB_FOUND == NO)) {
498 transaction_state = TRANSACTION_COMPLETE;
499 i++;
500 jsb->s_sequence =
501 cpu_to_be32(be32_to_cpu(
502 jsb->s_sequence) + 1);
503 }
504 prev_desc_logical_no = curr_desc_logical_no;
505 if ((recovery_flag == RECOVER) && (DB_FOUND == YES))
506 recover_transaction(prev_desc_logical_no);
507
508 DB_FOUND = NO;
509 } else if (be32_to_cpu(jdb->h_blocktype) ==
510 EXT3_JOURNAL_REVOKE_BLOCK) {
511 if (be32_to_cpu(jdb->h_sequence) !=
512 be32_to_cpu(jsb->s_sequence)) {
513 print_jrnl_status(recovery_flag);
514 break;
515 }
516 if (recovery_flag == SCAN)
517 ext4fs_push_revoke_blk((char *)jdb);
518 i++;
519 } else {
520 debug("Else Case\n");
521 if (be32_to_cpu(jdb->h_sequence) !=
522 be32_to_cpu(jsb->s_sequence)) {
523 print_jrnl_status(recovery_flag);
524 break;
525 }
526 }
527 }
528
529end:
530 if (recovery_flag == RECOVER) {
Michael Walle13179c22016-09-01 11:21:40 +0200531 uint32_t new_feature_incompat;
Uma Shankara74a99a2012-05-25 21:22:49 +0530532 jsb->s_start = cpu_to_be32(1);
533 jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1);
534 /* get the superblock */
Egbert Eich7b1b2552013-05-01 01:13:19 +0000535 ext4_read_superblock((char *)fs->sb);
Michael Walle13179c22016-09-01 11:21:40 +0200536 new_feature_incompat = le32_to_cpu(fs->sb->feature_incompat);
537 new_feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
538 fs->sb->feature_incompat = cpu_to_le32(new_feature_incompat);
Uma Shankara74a99a2012-05-25 21:22:49 +0530539
540 /* Update the super block */
541 put_ext4((uint64_t) (SUPERBLOCK_SIZE),
542 (struct ext2_sblock *)fs->sb,
543 (uint32_t) SUPERBLOCK_SIZE);
Egbert Eich7b1b2552013-05-01 01:13:19 +0000544 ext4_read_superblock((char *)fs->sb);
Uma Shankara74a99a2012-05-25 21:22:49 +0530545
546 blknr = read_allocated_block(&inode_journal,
Stephen Warren02d6ca72019-01-30 12:58:05 -0700547 EXT2_JOURNAL_SUPERBLOCK, NULL);
Ma Haijune0996ca2014-01-08 08:15:33 +0800548 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
Uma Shankara74a99a2012-05-25 21:22:49 +0530549 (struct journal_superblock_t *)temp_buff,
550 (uint32_t) fs->blksz);
551 ext4fs_free_revoke_blks();
552 }
553 free(temp_buff);
554 free(temp_buff1);
555
556 return 0;
557}
558
559static void update_descriptor_block(long int blknr)
560{
561 int i;
562 long int jsb_blknr;
563 struct journal_header_t jdb;
564 struct ext3_journal_block_tag tag;
565 struct ext2_inode inode_journal;
566 struct journal_superblock_t *jsb = NULL;
567 char *buf = NULL;
568 char *temp = NULL;
569 struct ext_filesystem *fs = get_fs();
570 char *temp_buff = zalloc(fs->blksz);
571 if (!temp_buff)
572 return;
573
574 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
575 jsb_blknr = read_allocated_block(&inode_journal,
Stephen Warren02d6ca72019-01-30 12:58:05 -0700576 EXT2_JOURNAL_SUPERBLOCK, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200577 ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
578 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530579 jsb = (struct journal_superblock_t *) temp_buff;
580
581 jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_DESCRIPTOR_BLOCK);
582 jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
583 jdb.h_sequence = jsb->s_sequence;
584 buf = zalloc(fs->blksz);
585 if (!buf) {
586 free(temp_buff);
587 return;
588 }
589 temp = buf;
590 memcpy(buf, &jdb, sizeof(struct journal_header_t));
591 temp += sizeof(struct journal_header_t);
592
593 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
594 if (journal_ptr[i]->blknr == -1)
595 break;
596
597 tag.block = cpu_to_be32(journal_ptr[i]->blknr);
598 tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_SAME_UUID);
599 memcpy(temp, &tag, sizeof(struct ext3_journal_block_tag));
600 temp = temp + sizeof(struct ext3_journal_block_tag);
601 }
602
603 tag.block = cpu_to_be32(journal_ptr[--i]->blknr);
604 tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_LAST_TAG);
605 memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag,
606 sizeof(struct ext3_journal_block_tag));
Ma Haijune0996ca2014-01-08 08:15:33 +0800607 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
Uma Shankara74a99a2012-05-25 21:22:49 +0530608
609 free(temp_buff);
610 free(buf);
611}
612
613static void update_commit_block(long int blknr)
614{
615 struct journal_header_t jdb;
616 struct ext_filesystem *fs = get_fs();
617 char *buf = NULL;
618 struct ext2_inode inode_journal;
619 struct journal_superblock_t *jsb;
620 long int jsb_blknr;
621 char *temp_buff = zalloc(fs->blksz);
622 if (!temp_buff)
623 return;
624
Frederic Leroye7ee0282013-06-26 18:11:25 +0200625 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
626 &inode_journal);
Uma Shankara74a99a2012-05-25 21:22:49 +0530627 jsb_blknr = read_allocated_block(&inode_journal,
Stephen Warren02d6ca72019-01-30 12:58:05 -0700628 EXT2_JOURNAL_SUPERBLOCK, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200629 ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
630 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530631 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));
Ma Haijune0996ca2014-01-08 08:15:33 +0800642 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
Uma Shankara74a99a2012-05-25 21:22:49 +0530643
644 free(temp_buff);
645 free(buf);
646}
647
648void 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;
Marek Szyprowskia9588152019-06-21 15:35:35 +0200654
655 if (!(fs->sb->feature_compatibility & EXT4_FEATURE_COMPAT_HAS_JOURNAL))
656 return;
657
Uma Shankara74a99a2012-05-25 21:22:49 +0530658 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
Stephen Warren02d6ca72019-01-30 12:58:05 -0700659 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++, NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530660 update_descriptor_block(blknr);
661 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
662 if (journal_ptr[i]->blknr == -1)
663 break;
Stephen Warren02d6ca72019-01-30 12:58:05 -0700664 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++,
665 NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530666 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
667 journal_ptr[i]->buf, fs->blksz);
668 }
Stephen Warren02d6ca72019-01-30 12:58:05 -0700669 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++, NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530670 update_commit_block(blknr);
671 printf("update journal finished\n");
672}