blob: 02c4ac2cb931b866d690461da1dcbb6054b143f4 [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;
134 for (i = 0; i < fs->no_blk_pergdt; i++) {
135 journal_ptr[gindex]->buf = zalloc(fs->blksz);
136 if (!journal_ptr[gindex]->buf)
137 return -ENOMEM;
138 memcpy(journal_ptr[gindex]->buf, gd_table, fs->blksz);
139 gd_table += fs->blksz;
140 journal_ptr[gindex++]->blknr = var++;
141 }
142
143 return 0;
144}
145
146/*
147 * This function stores the backup copy of meta data in RAM
148 * journal_buffer -- Buffer containing meta data
149 * blknr -- Block number on disk of the meta data buffer
150 */
Michael Walle13179c22016-09-01 11:21:40 +0200151int ext4fs_log_journal(char *journal_buffer, uint32_t blknr)
Uma Shankara74a99a2012-05-25 21:22:49 +0530152{
153 struct ext_filesystem *fs = get_fs();
154 short i;
155
156 if (!journal_buffer) {
157 printf("Invalid input arguments %s\n", __func__);
158 return -EINVAL;
159 }
160
161 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
162 if (journal_ptr[i]->blknr == -1)
163 break;
164 if (journal_ptr[i]->blknr == blknr)
165 return 0;
166 }
167
168 journal_ptr[gindex]->buf = zalloc(fs->blksz);
169 if (!journal_ptr[gindex]->buf)
170 return -ENOMEM;
171
172 memcpy(journal_ptr[gindex]->buf, journal_buffer, fs->blksz);
173 journal_ptr[gindex++]->blknr = blknr;
174
175 return 0;
176}
177
178/*
179 * This function stores the modified meta data in RAM
180 * metadata_buffer -- Buffer containing meta data
181 * blknr -- Block number on disk of the meta data buffer
182 */
Michael Walle13179c22016-09-01 11:21:40 +0200183int ext4fs_put_metadata(char *metadata_buffer, uint32_t blknr)
Uma Shankara74a99a2012-05-25 21:22:49 +0530184{
185 struct ext_filesystem *fs = get_fs();
186 if (!metadata_buffer) {
187 printf("Invalid input arguments %s\n", __func__);
188 return -EINVAL;
189 }
Stefan Brüns6cc369c2016-09-06 04:36:56 +0200190 if (dirty_block_ptr[gd_index]->buf)
191 assert(dirty_block_ptr[gd_index]->blknr == blknr);
192 else
193 dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz);
194
Uma Shankara74a99a2012-05-25 21:22:49 +0530195 if (!dirty_block_ptr[gd_index]->buf)
196 return -ENOMEM;
197 memcpy(dirty_block_ptr[gd_index]->buf, metadata_buffer, fs->blksz);
198 dirty_block_ptr[gd_index++]->blknr = blknr;
199
200 return 0;
201}
202
203void print_revoke_blks(char *revk_blk)
204{
205 int offset;
206 int max;
207 long int blocknr;
208 struct journal_revoke_header_t *header;
209
210 if (revk_blk == NULL)
211 return;
212
213 header = (struct journal_revoke_header_t *) revk_blk;
214 offset = sizeof(struct journal_revoke_header_t);
215 max = be32_to_cpu(header->r_count);
216 printf("total bytes %d\n", max);
217
218 while (offset < max) {
Michael Walle13179c22016-09-01 11:21:40 +0200219 blocknr = be32_to_cpu(*((__be32 *)(revk_blk + offset)));
Uma Shankara74a99a2012-05-25 21:22:49 +0530220 printf("revoke blknr is %ld\n", blocknr);
221 offset += 4;
222 }
223}
224
225static struct revoke_blk_list *_get_node(void)
226{
227 struct revoke_blk_list *tmp_node;
228 tmp_node = zalloc(sizeof(struct revoke_blk_list));
229 if (tmp_node == NULL)
230 return NULL;
231 tmp_node->content = NULL;
232 tmp_node->next = NULL;
233
234 return tmp_node;
235}
236
237void ext4fs_push_revoke_blk(char *buffer)
238{
239 struct revoke_blk_list *node = NULL;
240 struct ext_filesystem *fs = get_fs();
241 if (buffer == NULL) {
242 printf("buffer ptr is NULL\n");
243 return;
244 }
245 node = _get_node();
246 if (!node) {
247 printf("_get_node: malloc failed\n");
248 return;
249 }
250
251 node->content = zalloc(fs->blksz);
252 if (node->content == NULL)
253 return;
254 memcpy(node->content, buffer, fs->blksz);
255
York Sun4a598092013-04-01 11:29:11 -0700256 if (first_node == true) {
Uma Shankara74a99a2012-05-25 21:22:49 +0530257 revk_blk_list = node;
258 prev_node = node;
York Sun4a598092013-04-01 11:29:11 -0700259 first_node = false;
Uma Shankara74a99a2012-05-25 21:22:49 +0530260 } else {
261 prev_node->next = node;
262 prev_node = node;
263 }
264}
265
266void ext4fs_free_revoke_blks(void)
267{
268 struct revoke_blk_list *tmp_node = revk_blk_list;
269 struct revoke_blk_list *next_node = NULL;
270
271 while (tmp_node != NULL) {
Heinrich Schuchardt8179edf2020-04-28 21:50:02 +0200272 free(tmp_node->content);
Uma Shankara74a99a2012-05-25 21:22:49 +0530273 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;
York Sun4a598092013-04-01 11:29:11 -0700285 first_node = true;
Uma Shankara74a99a2012-05-25 21:22:49 +0530286}
287
288int 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) {
Michael Walle13179c22016-09-01 11:21:40 +0200305 blocknr = be32_to_cpu(*((__be32 *)
Uma Shankara74a99a2012-05-25 21:22:49 +0530306 (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
317found:
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 */
328void 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 *)
Stephen Warren02d6ca72019-01-30 12:58:05 -0700346 &inode_journal, i, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200347 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
348 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530349 p_jdb = (char *)temp_buff;
350 jdb = (struct journal_header_t *) temp_buff;
351 ofs = sizeof(struct journal_header_t);
352
353 do {
Tom Rini035f18e2017-08-20 22:30:15 -0400354 tag = (struct ext3_journal_block_tag *)(p_jdb + ofs);
Uma Shankara74a99a2012-05-25 21:22:49 +0530355 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 }
Stephen Warren02d6ca72019-01-30 12:58:05 -0700371 blknr = read_allocated_block(&inode_journal, i, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200372 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
Uma Shankara74a99a2012-05-25 21:22:49 +0530373 fs->blksz, metadata_buff);
Ma Haijune0996ca2014-01-08 08:15:33 +0800374 put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz),
Uma Shankara74a99a2012-05-25 21:22:49 +0530375 metadata_buff, (uint32_t) fs->blksz);
376 } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
377fail:
378 free(temp_buff);
379 free(metadata_buff);
380}
381
382void 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
390int 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;
Łukasz Majewskib55a7932012-12-05 08:06:39 +0000398 int ofs, flags;
Uma Shankara74a99a2012-05-25 21:22:49 +0530399 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
Arnaud Ferrarisebdcb602020-04-22 12:43:44 +0200408 if (le32_to_cpu(fs->sb->feature_ro_compat) & EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)
409 return 0;
410
Uma Shankara74a99a2012-05-25 21:22:49 +0530411 temp_buff = zalloc(fs->blksz);
412 if (!temp_buff)
413 return -ENOMEM;
414 temp_buff1 = zalloc(fs->blksz);
415 if (!temp_buff1) {
416 free(temp_buff);
417 return -ENOMEM;
418 }
419
420 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
Stephen Warren02d6ca72019-01-30 12:58:05 -0700421 blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK,
422 NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200423 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
424 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530425 jsb = (struct journal_superblock_t *) temp_buff;
426
Michael Walle13179c22016-09-01 11:21:40 +0200427 if (le32_to_cpu(fs->sb->feature_incompat) & EXT3_FEATURE_INCOMPAT_RECOVER) {
Uma Shankara74a99a2012-05-25 21:22:49 +0530428 if (recovery_flag == RECOVER)
429 printf("Recovery required\n");
430 } else {
431 if (recovery_flag == RECOVER)
Heinrich Schuchardtbe740192024-03-20 14:23:52 +0100432 log_debug("File System is consistent\n");
Uma Shankara74a99a2012-05-25 21:22:49 +0530433 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) {
Stephen Warren02d6ca72019-01-30 12:58:05 -0700446 blknr = read_allocated_block(&inode_journal, i, NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530447 memset(temp_buff1, '\0', fs->blksz);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200448 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
Uma Shankara74a99a2012-05-25 21:22:49 +0530449 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 *)
Tom Rini035f18e2017-08-20 22:30:15 -0400469 (p_jdb + ofs);
Uma Shankara74a99a2012-05-25 21:22:49 +0530470 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
522end:
523 if (recovery_flag == RECOVER) {
Michael Walle13179c22016-09-01 11:21:40 +0200524 uint32_t new_feature_incompat;
Uma Shankara74a99a2012-05-25 21:22:49 +0530525 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 */
Egbert Eich7b1b2552013-05-01 01:13:19 +0000528 ext4_read_superblock((char *)fs->sb);
Michael Walle13179c22016-09-01 11:21:40 +0200529 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);
Uma Shankara74a99a2012-05-25 21:22:49 +0530532
533 /* Update the super block */
534 put_ext4((uint64_t) (SUPERBLOCK_SIZE),
535 (struct ext2_sblock *)fs->sb,
536 (uint32_t) SUPERBLOCK_SIZE);
Egbert Eich7b1b2552013-05-01 01:13:19 +0000537 ext4_read_superblock((char *)fs->sb);
Uma Shankara74a99a2012-05-25 21:22:49 +0530538
539 blknr = read_allocated_block(&inode_journal,
Stephen Warren02d6ca72019-01-30 12:58:05 -0700540 EXT2_JOURNAL_SUPERBLOCK, NULL);
Ma Haijune0996ca2014-01-08 08:15:33 +0800541 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
Uma Shankara74a99a2012-05-25 21:22:49 +0530542 (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
552static 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,
Stephen Warren02d6ca72019-01-30 12:58:05 -0700569 EXT2_JOURNAL_SUPERBLOCK, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200570 ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
571 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530572 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));
Ma Haijune0996ca2014-01-08 08:15:33 +0800600 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
Uma Shankara74a99a2012-05-25 21:22:49 +0530601
602 free(temp_buff);
603 free(buf);
604}
605
606static 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
Frederic Leroye7ee0282013-06-26 18:11:25 +0200618 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
619 &inode_journal);
Uma Shankara74a99a2012-05-25 21:22:49 +0530620 jsb_blknr = read_allocated_block(&inode_journal,
Stephen Warren02d6ca72019-01-30 12:58:05 -0700621 EXT2_JOURNAL_SUPERBLOCK, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200622 ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
623 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530624 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));
Ma Haijune0996ca2014-01-08 08:15:33 +0800635 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
Uma Shankara74a99a2012-05-25 21:22:49 +0530636
637 free(temp_buff);
638 free(buf);
639}
640
641void 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;
Marek Szyprowskia9588152019-06-21 15:35:35 +0200647
648 if (!(fs->sb->feature_compatibility & EXT4_FEATURE_COMPAT_HAS_JOURNAL))
649 return;
650
Uma Shankara74a99a2012-05-25 21:22:49 +0530651 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
Stephen Warren02d6ca72019-01-30 12:58:05 -0700652 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++, NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530653 update_descriptor_block(blknr);
654 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
655 if (journal_ptr[i]->blknr == -1)
656 break;
Stephen Warren02d6ca72019-01-30 12:58:05 -0700657 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++,
658 NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530659 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
660 journal_ptr[i]->buf, fs->blksz);
661 }
Stephen Warren02d6ca72019-01-30 12:58:05 -0700662 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++, NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530663 update_commit_block(blknr);
664 printf("update journal finished\n");
665}