blob: 0ceb73d9c916201327f89dcc04bfc546ac4bc4dc [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
16#include <common.h>
17#include <ext4fs.h>
18#include <malloc.h>
19#include <ext_common.h>
20#include "ext4_common.h"
21
22static struct revoke_blk_list *revk_blk_list;
23static struct revoke_blk_list *prev_node;
York Sun4a598092013-04-01 11:29:11 -070024static int first_node = true;
Uma Shankara74a99a2012-05-25 21:22:49 +053025
26int gindex;
27int gd_index;
28int jrnl_blk_idx;
29struct journal_log *journal_ptr[MAX_JOURNAL_ENTRIES];
30struct dirty_blocks *dirty_block_ptr[MAX_JOURNAL_ENTRIES];
31
32int 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;
87fail:
88 return -1;
89}
90
91void 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
104void 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;
Heinrich Schuchardt8179edf2020-04-28 21:50:02 +0200110 free(dirty_block_ptr[i]->buf);
Uma Shankara74a99a2012-05-25 21:22:49 +0530111 }
112
113 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
114 if (journal_ptr[i]->blknr == -1)
115 break;
Heinrich Schuchardt8179edf2020-04-28 21:50:02 +0200116 free(journal_ptr[i]->buf);
Uma Shankara74a99a2012-05-25 21:22:49 +0530117 }
118
119 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
Heinrich Schuchardt8179edf2020-04-28 21:50:02 +0200120 free(journal_ptr[i]);
121 free(dirty_block_ptr[i]);
Uma Shankara74a99a2012-05-25 21:22:49 +0530122 }
123 gindex = 0;
124 gd_index = 0;
125 jrnl_blk_idx = 1;
126}
127
128int ext4fs_log_gdt(char *gd_table)
129{
130 struct ext_filesystem *fs = get_fs();
131 short i;
132 long int var = fs->gdtable_blkno;
133 for (i = 0; i < fs->no_blk_pergdt; i++) {
134 journal_ptr[gindex]->buf = zalloc(fs->blksz);
135 if (!journal_ptr[gindex]->buf)
136 return -ENOMEM;
137 memcpy(journal_ptr[gindex]->buf, gd_table, fs->blksz);
138 gd_table += fs->blksz;
139 journal_ptr[gindex++]->blknr = var++;
140 }
141
142 return 0;
143}
144
145/*
146 * This function stores the backup copy of meta data in RAM
147 * journal_buffer -- Buffer containing meta data
148 * blknr -- Block number on disk of the meta data buffer
149 */
Michael Walle13179c22016-09-01 11:21:40 +0200150int ext4fs_log_journal(char *journal_buffer, uint32_t blknr)
Uma Shankara74a99a2012-05-25 21:22:49 +0530151{
152 struct ext_filesystem *fs = get_fs();
153 short i;
154
155 if (!journal_buffer) {
156 printf("Invalid input arguments %s\n", __func__);
157 return -EINVAL;
158 }
159
160 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
161 if (journal_ptr[i]->blknr == -1)
162 break;
163 if (journal_ptr[i]->blknr == blknr)
164 return 0;
165 }
166
167 journal_ptr[gindex]->buf = zalloc(fs->blksz);
168 if (!journal_ptr[gindex]->buf)
169 return -ENOMEM;
170
171 memcpy(journal_ptr[gindex]->buf, journal_buffer, fs->blksz);
172 journal_ptr[gindex++]->blknr = blknr;
173
174 return 0;
175}
176
177/*
178 * This function stores the modified meta data in RAM
179 * metadata_buffer -- Buffer containing meta data
180 * blknr -- Block number on disk of the meta data buffer
181 */
Michael Walle13179c22016-09-01 11:21:40 +0200182int ext4fs_put_metadata(char *metadata_buffer, uint32_t blknr)
Uma Shankara74a99a2012-05-25 21:22:49 +0530183{
184 struct ext_filesystem *fs = get_fs();
185 if (!metadata_buffer) {
186 printf("Invalid input arguments %s\n", __func__);
187 return -EINVAL;
188 }
Stefan Brüns6cc369c2016-09-06 04:36:56 +0200189 if (dirty_block_ptr[gd_index]->buf)
190 assert(dirty_block_ptr[gd_index]->blknr == blknr);
191 else
192 dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz);
193
Uma Shankara74a99a2012-05-25 21:22:49 +0530194 if (!dirty_block_ptr[gd_index]->buf)
195 return -ENOMEM;
196 memcpy(dirty_block_ptr[gd_index]->buf, metadata_buffer, fs->blksz);
197 dirty_block_ptr[gd_index++]->blknr = blknr;
198
199 return 0;
200}
201
202void print_revoke_blks(char *revk_blk)
203{
204 int offset;
205 int max;
206 long int blocknr;
207 struct journal_revoke_header_t *header;
208
209 if (revk_blk == NULL)
210 return;
211
212 header = (struct journal_revoke_header_t *) revk_blk;
213 offset = sizeof(struct journal_revoke_header_t);
214 max = be32_to_cpu(header->r_count);
215 printf("total bytes %d\n", max);
216
217 while (offset < max) {
Michael Walle13179c22016-09-01 11:21:40 +0200218 blocknr = be32_to_cpu(*((__be32 *)(revk_blk + offset)));
Uma Shankara74a99a2012-05-25 21:22:49 +0530219 printf("revoke blknr is %ld\n", blocknr);
220 offset += 4;
221 }
222}
223
224static struct revoke_blk_list *_get_node(void)
225{
226 struct revoke_blk_list *tmp_node;
227 tmp_node = zalloc(sizeof(struct revoke_blk_list));
228 if (tmp_node == NULL)
229 return NULL;
230 tmp_node->content = NULL;
231 tmp_node->next = NULL;
232
233 return tmp_node;
234}
235
236void ext4fs_push_revoke_blk(char *buffer)
237{
238 struct revoke_blk_list *node = NULL;
239 struct ext_filesystem *fs = get_fs();
240 if (buffer == NULL) {
241 printf("buffer ptr is NULL\n");
242 return;
243 }
244 node = _get_node();
245 if (!node) {
246 printf("_get_node: malloc failed\n");
247 return;
248 }
249
250 node->content = zalloc(fs->blksz);
251 if (node->content == NULL)
252 return;
253 memcpy(node->content, buffer, fs->blksz);
254
York Sun4a598092013-04-01 11:29:11 -0700255 if (first_node == true) {
Uma Shankara74a99a2012-05-25 21:22:49 +0530256 revk_blk_list = node;
257 prev_node = node;
York Sun4a598092013-04-01 11:29:11 -0700258 first_node = false;
Uma Shankara74a99a2012-05-25 21:22:49 +0530259 } else {
260 prev_node->next = node;
261 prev_node = node;
262 }
263}
264
265void ext4fs_free_revoke_blks(void)
266{
267 struct revoke_blk_list *tmp_node = revk_blk_list;
268 struct revoke_blk_list *next_node = NULL;
269
270 while (tmp_node != NULL) {
Heinrich Schuchardt8179edf2020-04-28 21:50:02 +0200271 free(tmp_node->content);
Uma Shankara74a99a2012-05-25 21:22:49 +0530272 tmp_node = tmp_node->next;
273 }
274
275 tmp_node = revk_blk_list;
276 while (tmp_node != NULL) {
277 next_node = tmp_node->next;
278 free(tmp_node);
279 tmp_node = next_node;
280 }
281
282 revk_blk_list = NULL;
283 prev_node = NULL;
York Sun4a598092013-04-01 11:29:11 -0700284 first_node = true;
Uma Shankara74a99a2012-05-25 21:22:49 +0530285}
286
287int check_blknr_for_revoke(long int blknr, int sequence_no)
288{
289 struct journal_revoke_header_t *header;
290 int offset;
291 int max;
292 long int blocknr;
293 char *revk_blk;
294 struct revoke_blk_list *tmp_revk_node = revk_blk_list;
295 while (tmp_revk_node != NULL) {
296 revk_blk = tmp_revk_node->content;
297
298 header = (struct journal_revoke_header_t *) revk_blk;
299 if (sequence_no < be32_to_cpu(header->r_header.h_sequence)) {
300 offset = sizeof(struct journal_revoke_header_t);
301 max = be32_to_cpu(header->r_count);
302
303 while (offset < max) {
Michael Walle13179c22016-09-01 11:21:40 +0200304 blocknr = be32_to_cpu(*((__be32 *)
Uma Shankara74a99a2012-05-25 21:22:49 +0530305 (revk_blk + offset)));
306 if (blocknr == blknr)
307 goto found;
308 offset += 4;
309 }
310 }
311 tmp_revk_node = tmp_revk_node->next;
312 }
313
314 return -1;
315
316found:
317 return 0;
318}
319
320/*
321 * This function parses the journal blocks and replays the
322 * suceessful transactions. A transaction is successfull
323 * if commit block is found for a descriptor block
324 * The tags in descriptor block contain the disk block
325 * numbers of the metadata to be replayed
326 */
327void recover_transaction(int prev_desc_logical_no)
328{
329 struct ext2_inode inode_journal;
330 struct ext_filesystem *fs = get_fs();
331 struct journal_header_t *jdb;
332 long int blknr;
333 char *p_jdb;
334 int ofs, flags;
335 int i;
336 struct ext3_journal_block_tag *tag;
337 char *temp_buff = zalloc(fs->blksz);
338 char *metadata_buff = zalloc(fs->blksz);
339 if (!temp_buff || !metadata_buff)
340 goto fail;
341 i = prev_desc_logical_no;
342 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
343 (struct ext2_inode *)&inode_journal);
344 blknr = read_allocated_block((struct ext2_inode *)
Stephen Warren02d6ca72019-01-30 12:58:05 -0700345 &inode_journal, i, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200346 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
347 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530348 p_jdb = (char *)temp_buff;
349 jdb = (struct journal_header_t *) temp_buff;
350 ofs = sizeof(struct journal_header_t);
351
352 do {
Tom Rini035f18e2017-08-20 22:30:15 -0400353 tag = (struct ext3_journal_block_tag *)(p_jdb + ofs);
Uma Shankara74a99a2012-05-25 21:22:49 +0530354 ofs += sizeof(struct ext3_journal_block_tag);
355
356 if (ofs > fs->blksz)
357 break;
358
359 flags = be32_to_cpu(tag->flags);
360 if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
361 ofs += 16;
362
363 i++;
364 debug("\t\ttag %u\n", be32_to_cpu(tag->block));
365 if (revk_blk_list != NULL) {
366 if (check_blknr_for_revoke(be32_to_cpu(tag->block),
367 be32_to_cpu(jdb->h_sequence)) == 0)
368 continue;
369 }
Stephen Warren02d6ca72019-01-30 12:58:05 -0700370 blknr = read_allocated_block(&inode_journal, i, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200371 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
Uma Shankara74a99a2012-05-25 21:22:49 +0530372 fs->blksz, metadata_buff);
Ma Haijune0996ca2014-01-08 08:15:33 +0800373 put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz),
Uma Shankara74a99a2012-05-25 21:22:49 +0530374 metadata_buff, (uint32_t) fs->blksz);
375 } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
376fail:
377 free(temp_buff);
378 free(metadata_buff);
379}
380
381void print_jrnl_status(int recovery_flag)
382{
383 if (recovery_flag == RECOVER)
384 printf("Journal Recovery Completed\n");
385 else
386 printf("Journal Scan Completed\n");
387}
388
389int ext4fs_check_journal_state(int recovery_flag)
390{
391 int i;
392 int DB_FOUND = NO;
393 long int blknr;
394 int transaction_state = TRANSACTION_COMPLETE;
395 int prev_desc_logical_no = 0;
396 int curr_desc_logical_no = 0;
Łukasz Majewskib55a7932012-12-05 08:06:39 +0000397 int ofs, flags;
Uma Shankara74a99a2012-05-25 21:22:49 +0530398 struct ext2_inode inode_journal;
399 struct journal_superblock_t *jsb = NULL;
400 struct journal_header_t *jdb = NULL;
401 char *p_jdb = NULL;
402 struct ext3_journal_block_tag *tag = NULL;
403 char *temp_buff = NULL;
404 char *temp_buff1 = NULL;
405 struct ext_filesystem *fs = get_fs();
406
Arnaud Ferrarisebdcb602020-04-22 12:43:44 +0200407 if (le32_to_cpu(fs->sb->feature_ro_compat) & EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)
408 return 0;
409
Uma Shankara74a99a2012-05-25 21:22:49 +0530410 temp_buff = zalloc(fs->blksz);
411 if (!temp_buff)
412 return -ENOMEM;
413 temp_buff1 = zalloc(fs->blksz);
414 if (!temp_buff1) {
415 free(temp_buff);
416 return -ENOMEM;
417 }
418
419 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
Stephen Warren02d6ca72019-01-30 12:58:05 -0700420 blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK,
421 NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200422 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
423 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530424 jsb = (struct journal_superblock_t *) temp_buff;
425
Michael Walle13179c22016-09-01 11:21:40 +0200426 if (le32_to_cpu(fs->sb->feature_incompat) & EXT3_FEATURE_INCOMPAT_RECOVER) {
Uma Shankara74a99a2012-05-25 21:22:49 +0530427 if (recovery_flag == RECOVER)
428 printf("Recovery required\n");
429 } else {
430 if (recovery_flag == RECOVER)
431 printf("File System is consistent\n");
432 goto end;
433 }
434
435 if (be32_to_cpu(jsb->s_start) == 0)
436 goto end;
437
438 if (!(jsb->s_feature_compat &
439 cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM)))
440 jsb->s_feature_compat |=
441 cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
442
443 i = be32_to_cpu(jsb->s_first);
444 while (1) {
Stephen Warren02d6ca72019-01-30 12:58:05 -0700445 blknr = read_allocated_block(&inode_journal, i, NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530446 memset(temp_buff1, '\0', fs->blksz);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200447 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
Uma Shankara74a99a2012-05-25 21:22:49 +0530448 0, fs->blksz, temp_buff1);
449 jdb = (struct journal_header_t *) temp_buff1;
450
451 if (be32_to_cpu(jdb->h_blocktype) ==
452 EXT3_JOURNAL_DESCRIPTOR_BLOCK) {
453 if (be32_to_cpu(jdb->h_sequence) !=
454 be32_to_cpu(jsb->s_sequence)) {
455 print_jrnl_status(recovery_flag);
456 break;
457 }
458
459 curr_desc_logical_no = i;
460 if (transaction_state == TRANSACTION_COMPLETE)
461 transaction_state = TRANSACTION_RUNNING;
462 else
463 return -1;
464 p_jdb = (char *)temp_buff1;
465 ofs = sizeof(struct journal_header_t);
466 do {
467 tag = (struct ext3_journal_block_tag *)
Tom Rini035f18e2017-08-20 22:30:15 -0400468 (p_jdb + ofs);
Uma Shankara74a99a2012-05-25 21:22:49 +0530469 ofs += sizeof(struct ext3_journal_block_tag);
470 if (ofs > fs->blksz)
471 break;
472 flags = be32_to_cpu(tag->flags);
473 if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
474 ofs += 16;
475 i++;
476 debug("\t\ttag %u\n", be32_to_cpu(tag->block));
477 } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
478 i++;
479 DB_FOUND = YES;
480 } else if (be32_to_cpu(jdb->h_blocktype) ==
481 EXT3_JOURNAL_COMMIT_BLOCK) {
482 if (be32_to_cpu(jdb->h_sequence) !=
483 be32_to_cpu(jsb->s_sequence)) {
484 print_jrnl_status(recovery_flag);
485 break;
486 }
487
488 if (transaction_state == TRANSACTION_RUNNING ||
489 (DB_FOUND == NO)) {
490 transaction_state = TRANSACTION_COMPLETE;
491 i++;
492 jsb->s_sequence =
493 cpu_to_be32(be32_to_cpu(
494 jsb->s_sequence) + 1);
495 }
496 prev_desc_logical_no = curr_desc_logical_no;
497 if ((recovery_flag == RECOVER) && (DB_FOUND == YES))
498 recover_transaction(prev_desc_logical_no);
499
500 DB_FOUND = NO;
501 } else if (be32_to_cpu(jdb->h_blocktype) ==
502 EXT3_JOURNAL_REVOKE_BLOCK) {
503 if (be32_to_cpu(jdb->h_sequence) !=
504 be32_to_cpu(jsb->s_sequence)) {
505 print_jrnl_status(recovery_flag);
506 break;
507 }
508 if (recovery_flag == SCAN)
509 ext4fs_push_revoke_blk((char *)jdb);
510 i++;
511 } else {
512 debug("Else Case\n");
513 if (be32_to_cpu(jdb->h_sequence) !=
514 be32_to_cpu(jsb->s_sequence)) {
515 print_jrnl_status(recovery_flag);
516 break;
517 }
518 }
519 }
520
521end:
522 if (recovery_flag == RECOVER) {
Michael Walle13179c22016-09-01 11:21:40 +0200523 uint32_t new_feature_incompat;
Uma Shankara74a99a2012-05-25 21:22:49 +0530524 jsb->s_start = cpu_to_be32(1);
525 jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1);
526 /* get the superblock */
Egbert Eich7b1b2552013-05-01 01:13:19 +0000527 ext4_read_superblock((char *)fs->sb);
Michael Walle13179c22016-09-01 11:21:40 +0200528 new_feature_incompat = le32_to_cpu(fs->sb->feature_incompat);
529 new_feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
530 fs->sb->feature_incompat = cpu_to_le32(new_feature_incompat);
Uma Shankara74a99a2012-05-25 21:22:49 +0530531
532 /* Update the super block */
533 put_ext4((uint64_t) (SUPERBLOCK_SIZE),
534 (struct ext2_sblock *)fs->sb,
535 (uint32_t) SUPERBLOCK_SIZE);
Egbert Eich7b1b2552013-05-01 01:13:19 +0000536 ext4_read_superblock((char *)fs->sb);
Uma Shankara74a99a2012-05-25 21:22:49 +0530537
538 blknr = read_allocated_block(&inode_journal,
Stephen Warren02d6ca72019-01-30 12:58:05 -0700539 EXT2_JOURNAL_SUPERBLOCK, NULL);
Ma Haijune0996ca2014-01-08 08:15:33 +0800540 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
Uma Shankara74a99a2012-05-25 21:22:49 +0530541 (struct journal_superblock_t *)temp_buff,
542 (uint32_t) fs->blksz);
543 ext4fs_free_revoke_blks();
544 }
545 free(temp_buff);
546 free(temp_buff1);
547
548 return 0;
549}
550
551static void update_descriptor_block(long int blknr)
552{
553 int i;
554 long int jsb_blknr;
555 struct journal_header_t jdb;
556 struct ext3_journal_block_tag tag;
557 struct ext2_inode inode_journal;
558 struct journal_superblock_t *jsb = NULL;
559 char *buf = NULL;
560 char *temp = NULL;
561 struct ext_filesystem *fs = get_fs();
562 char *temp_buff = zalloc(fs->blksz);
563 if (!temp_buff)
564 return;
565
566 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
567 jsb_blknr = read_allocated_block(&inode_journal,
Stephen Warren02d6ca72019-01-30 12:58:05 -0700568 EXT2_JOURNAL_SUPERBLOCK, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200569 ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
570 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530571 jsb = (struct journal_superblock_t *) temp_buff;
572
573 jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_DESCRIPTOR_BLOCK);
574 jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
575 jdb.h_sequence = jsb->s_sequence;
576 buf = zalloc(fs->blksz);
577 if (!buf) {
578 free(temp_buff);
579 return;
580 }
581 temp = buf;
582 memcpy(buf, &jdb, sizeof(struct journal_header_t));
583 temp += sizeof(struct journal_header_t);
584
585 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
586 if (journal_ptr[i]->blknr == -1)
587 break;
588
589 tag.block = cpu_to_be32(journal_ptr[i]->blknr);
590 tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_SAME_UUID);
591 memcpy(temp, &tag, sizeof(struct ext3_journal_block_tag));
592 temp = temp + sizeof(struct ext3_journal_block_tag);
593 }
594
595 tag.block = cpu_to_be32(journal_ptr[--i]->blknr);
596 tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_LAST_TAG);
597 memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag,
598 sizeof(struct ext3_journal_block_tag));
Ma Haijune0996ca2014-01-08 08:15:33 +0800599 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
Uma Shankara74a99a2012-05-25 21:22:49 +0530600
601 free(temp_buff);
602 free(buf);
603}
604
605static void update_commit_block(long int blknr)
606{
607 struct journal_header_t jdb;
608 struct ext_filesystem *fs = get_fs();
609 char *buf = NULL;
610 struct ext2_inode inode_journal;
611 struct journal_superblock_t *jsb;
612 long int jsb_blknr;
613 char *temp_buff = zalloc(fs->blksz);
614 if (!temp_buff)
615 return;
616
Frederic Leroye7ee0282013-06-26 18:11:25 +0200617 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
618 &inode_journal);
Uma Shankara74a99a2012-05-25 21:22:49 +0530619 jsb_blknr = read_allocated_block(&inode_journal,
Stephen Warren02d6ca72019-01-30 12:58:05 -0700620 EXT2_JOURNAL_SUPERBLOCK, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200621 ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
622 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530623 jsb = (struct journal_superblock_t *) temp_buff;
624
625 jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_COMMIT_BLOCK);
626 jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
627 jdb.h_sequence = jsb->s_sequence;
628 buf = zalloc(fs->blksz);
629 if (!buf) {
630 free(temp_buff);
631 return;
632 }
633 memcpy(buf, &jdb, sizeof(struct journal_header_t));
Ma Haijune0996ca2014-01-08 08:15:33 +0800634 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
Uma Shankara74a99a2012-05-25 21:22:49 +0530635
636 free(temp_buff);
637 free(buf);
638}
639
640void ext4fs_update_journal(void)
641{
642 struct ext2_inode inode_journal;
643 struct ext_filesystem *fs = get_fs();
644 long int blknr;
645 int i;
Marek Szyprowskia9588152019-06-21 15:35:35 +0200646
647 if (!(fs->sb->feature_compatibility & EXT4_FEATURE_COMPAT_HAS_JOURNAL))
648 return;
649
Uma Shankara74a99a2012-05-25 21:22:49 +0530650 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
Stephen Warren02d6ca72019-01-30 12:58:05 -0700651 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++, NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530652 update_descriptor_block(blknr);
653 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
654 if (journal_ptr[i]->blknr == -1)
655 break;
Stephen Warren02d6ca72019-01-30 12:58:05 -0700656 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++,
657 NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530658 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
659 journal_ptr[i]->buf, fs->blksz);
660 }
Stephen Warren02d6ca72019-01-30 12:58:05 -0700661 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++, NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530662 update_commit_block(blknr);
663 printf("update journal finished\n");
664}