blob: f8524e5a99abb51dcb5400c2c666c3ec2a656b91 [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;
110 if (dirty_block_ptr[i]->buf)
111 free(dirty_block_ptr[i]->buf);
112 }
113
114 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
115 if (journal_ptr[i]->blknr == -1)
116 break;
117 if (journal_ptr[i]->buf)
118 free(journal_ptr[i]->buf);
119 }
120
121 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
122 if (journal_ptr[i])
123 free(journal_ptr[i]);
124 if (dirty_block_ptr[i])
125 free(dirty_block_ptr[i]);
126 }
127 gindex = 0;
128 gd_index = 0;
129 jrnl_blk_idx = 1;
130}
131
132int ext4fs_log_gdt(char *gd_table)
133{
134 struct ext_filesystem *fs = get_fs();
135 short i;
136 long int var = fs->gdtable_blkno;
137 for (i = 0; i < fs->no_blk_pergdt; i++) {
138 journal_ptr[gindex]->buf = zalloc(fs->blksz);
139 if (!journal_ptr[gindex]->buf)
140 return -ENOMEM;
141 memcpy(journal_ptr[gindex]->buf, gd_table, fs->blksz);
142 gd_table += fs->blksz;
143 journal_ptr[gindex++]->blknr = var++;
144 }
145
146 return 0;
147}
148
149/*
150 * This function stores the backup copy of meta data in RAM
151 * journal_buffer -- Buffer containing meta data
152 * blknr -- Block number on disk of the meta data buffer
153 */
Michael Walle13179c22016-09-01 11:21:40 +0200154int ext4fs_log_journal(char *journal_buffer, uint32_t blknr)
Uma Shankara74a99a2012-05-25 21:22:49 +0530155{
156 struct ext_filesystem *fs = get_fs();
157 short i;
158
159 if (!journal_buffer) {
160 printf("Invalid input arguments %s\n", __func__);
161 return -EINVAL;
162 }
163
164 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
165 if (journal_ptr[i]->blknr == -1)
166 break;
167 if (journal_ptr[i]->blknr == blknr)
168 return 0;
169 }
170
171 journal_ptr[gindex]->buf = zalloc(fs->blksz);
172 if (!journal_ptr[gindex]->buf)
173 return -ENOMEM;
174
175 memcpy(journal_ptr[gindex]->buf, journal_buffer, fs->blksz);
176 journal_ptr[gindex++]->blknr = blknr;
177
178 return 0;
179}
180
181/*
182 * This function stores the modified meta data in RAM
183 * metadata_buffer -- Buffer containing meta data
184 * blknr -- Block number on disk of the meta data buffer
185 */
Michael Walle13179c22016-09-01 11:21:40 +0200186int ext4fs_put_metadata(char *metadata_buffer, uint32_t blknr)
Uma Shankara74a99a2012-05-25 21:22:49 +0530187{
188 struct ext_filesystem *fs = get_fs();
189 if (!metadata_buffer) {
190 printf("Invalid input arguments %s\n", __func__);
191 return -EINVAL;
192 }
Stefan Brüns6cc369c2016-09-06 04:36:56 +0200193 if (dirty_block_ptr[gd_index]->buf)
194 assert(dirty_block_ptr[gd_index]->blknr == blknr);
195 else
196 dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz);
197
Uma Shankara74a99a2012-05-25 21:22:49 +0530198 if (!dirty_block_ptr[gd_index]->buf)
199 return -ENOMEM;
200 memcpy(dirty_block_ptr[gd_index]->buf, metadata_buffer, fs->blksz);
201 dirty_block_ptr[gd_index++]->blknr = blknr;
202
203 return 0;
204}
205
206void print_revoke_blks(char *revk_blk)
207{
208 int offset;
209 int max;
210 long int blocknr;
211 struct journal_revoke_header_t *header;
212
213 if (revk_blk == NULL)
214 return;
215
216 header = (struct journal_revoke_header_t *) revk_blk;
217 offset = sizeof(struct journal_revoke_header_t);
218 max = be32_to_cpu(header->r_count);
219 printf("total bytes %d\n", max);
220
221 while (offset < max) {
Michael Walle13179c22016-09-01 11:21:40 +0200222 blocknr = be32_to_cpu(*((__be32 *)(revk_blk + offset)));
Uma Shankara74a99a2012-05-25 21:22:49 +0530223 printf("revoke blknr is %ld\n", blocknr);
224 offset += 4;
225 }
226}
227
228static struct revoke_blk_list *_get_node(void)
229{
230 struct revoke_blk_list *tmp_node;
231 tmp_node = zalloc(sizeof(struct revoke_blk_list));
232 if (tmp_node == NULL)
233 return NULL;
234 tmp_node->content = NULL;
235 tmp_node->next = NULL;
236
237 return tmp_node;
238}
239
240void ext4fs_push_revoke_blk(char *buffer)
241{
242 struct revoke_blk_list *node = NULL;
243 struct ext_filesystem *fs = get_fs();
244 if (buffer == NULL) {
245 printf("buffer ptr is NULL\n");
246 return;
247 }
248 node = _get_node();
249 if (!node) {
250 printf("_get_node: malloc failed\n");
251 return;
252 }
253
254 node->content = zalloc(fs->blksz);
255 if (node->content == NULL)
256 return;
257 memcpy(node->content, buffer, fs->blksz);
258
York Sun4a598092013-04-01 11:29:11 -0700259 if (first_node == true) {
Uma Shankara74a99a2012-05-25 21:22:49 +0530260 revk_blk_list = node;
261 prev_node = node;
York Sun4a598092013-04-01 11:29:11 -0700262 first_node = false;
Uma Shankara74a99a2012-05-25 21:22:49 +0530263 } else {
264 prev_node->next = node;
265 prev_node = node;
266 }
267}
268
269void ext4fs_free_revoke_blks(void)
270{
271 struct revoke_blk_list *tmp_node = revk_blk_list;
272 struct revoke_blk_list *next_node = NULL;
273
274 while (tmp_node != NULL) {
275 if (tmp_node->content)
276 free(tmp_node->content);
277 tmp_node = tmp_node->next;
278 }
279
280 tmp_node = revk_blk_list;
281 while (tmp_node != NULL) {
282 next_node = tmp_node->next;
283 free(tmp_node);
284 tmp_node = next_node;
285 }
286
287 revk_blk_list = NULL;
288 prev_node = NULL;
York Sun4a598092013-04-01 11:29:11 -0700289 first_node = true;
Uma Shankara74a99a2012-05-25 21:22:49 +0530290}
291
292int check_blknr_for_revoke(long int blknr, int sequence_no)
293{
294 struct journal_revoke_header_t *header;
295 int offset;
296 int max;
297 long int blocknr;
298 char *revk_blk;
299 struct revoke_blk_list *tmp_revk_node = revk_blk_list;
300 while (tmp_revk_node != NULL) {
301 revk_blk = tmp_revk_node->content;
302
303 header = (struct journal_revoke_header_t *) revk_blk;
304 if (sequence_no < be32_to_cpu(header->r_header.h_sequence)) {
305 offset = sizeof(struct journal_revoke_header_t);
306 max = be32_to_cpu(header->r_count);
307
308 while (offset < max) {
Michael Walle13179c22016-09-01 11:21:40 +0200309 blocknr = be32_to_cpu(*((__be32 *)
Uma Shankara74a99a2012-05-25 21:22:49 +0530310 (revk_blk + offset)));
311 if (blocknr == blknr)
312 goto found;
313 offset += 4;
314 }
315 }
316 tmp_revk_node = tmp_revk_node->next;
317 }
318
319 return -1;
320
321found:
322 return 0;
323}
324
325/*
326 * This function parses the journal blocks and replays the
327 * suceessful transactions. A transaction is successfull
328 * if commit block is found for a descriptor block
329 * The tags in descriptor block contain the disk block
330 * numbers of the metadata to be replayed
331 */
332void recover_transaction(int prev_desc_logical_no)
333{
334 struct ext2_inode inode_journal;
335 struct ext_filesystem *fs = get_fs();
336 struct journal_header_t *jdb;
337 long int blknr;
338 char *p_jdb;
339 int ofs, flags;
340 int i;
341 struct ext3_journal_block_tag *tag;
342 char *temp_buff = zalloc(fs->blksz);
343 char *metadata_buff = zalloc(fs->blksz);
344 if (!temp_buff || !metadata_buff)
345 goto fail;
346 i = prev_desc_logical_no;
347 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
348 (struct ext2_inode *)&inode_journal);
349 blknr = read_allocated_block((struct ext2_inode *)
Stephen Warren02d6ca72019-01-30 12:58:05 -0700350 &inode_journal, i, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200351 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
352 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530353 p_jdb = (char *)temp_buff;
354 jdb = (struct journal_header_t *) temp_buff;
355 ofs = sizeof(struct journal_header_t);
356
357 do {
Tom Rini035f18e2017-08-20 22:30:15 -0400358 tag = (struct ext3_journal_block_tag *)(p_jdb + ofs);
Uma Shankara74a99a2012-05-25 21:22:49 +0530359 ofs += sizeof(struct ext3_journal_block_tag);
360
361 if (ofs > fs->blksz)
362 break;
363
364 flags = be32_to_cpu(tag->flags);
365 if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
366 ofs += 16;
367
368 i++;
369 debug("\t\ttag %u\n", be32_to_cpu(tag->block));
370 if (revk_blk_list != NULL) {
371 if (check_blknr_for_revoke(be32_to_cpu(tag->block),
372 be32_to_cpu(jdb->h_sequence)) == 0)
373 continue;
374 }
Stephen Warren02d6ca72019-01-30 12:58:05 -0700375 blknr = read_allocated_block(&inode_journal, i, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200376 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
Uma Shankara74a99a2012-05-25 21:22:49 +0530377 fs->blksz, metadata_buff);
Ma Haijune0996ca2014-01-08 08:15:33 +0800378 put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz),
Uma Shankara74a99a2012-05-25 21:22:49 +0530379 metadata_buff, (uint32_t) fs->blksz);
380 } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
381fail:
382 free(temp_buff);
383 free(metadata_buff);
384}
385
386void print_jrnl_status(int recovery_flag)
387{
388 if (recovery_flag == RECOVER)
389 printf("Journal Recovery Completed\n");
390 else
391 printf("Journal Scan Completed\n");
392}
393
394int ext4fs_check_journal_state(int recovery_flag)
395{
396 int i;
397 int DB_FOUND = NO;
398 long int blknr;
399 int transaction_state = TRANSACTION_COMPLETE;
400 int prev_desc_logical_no = 0;
401 int curr_desc_logical_no = 0;
Łukasz Majewskib55a7932012-12-05 08:06:39 +0000402 int ofs, flags;
Uma Shankara74a99a2012-05-25 21:22:49 +0530403 struct ext2_inode inode_journal;
404 struct journal_superblock_t *jsb = NULL;
405 struct journal_header_t *jdb = NULL;
406 char *p_jdb = NULL;
407 struct ext3_journal_block_tag *tag = NULL;
408 char *temp_buff = NULL;
409 char *temp_buff1 = NULL;
410 struct ext_filesystem *fs = get_fs();
411
Arnaud Ferrarisebdcb602020-04-22 12:43:44 +0200412 if (le32_to_cpu(fs->sb->feature_ro_compat) & EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)
413 return 0;
414
Uma Shankara74a99a2012-05-25 21:22:49 +0530415 temp_buff = zalloc(fs->blksz);
416 if (!temp_buff)
417 return -ENOMEM;
418 temp_buff1 = zalloc(fs->blksz);
419 if (!temp_buff1) {
420 free(temp_buff);
421 return -ENOMEM;
422 }
423
424 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
Stephen Warren02d6ca72019-01-30 12:58:05 -0700425 blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK,
426 NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200427 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
428 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530429 jsb = (struct journal_superblock_t *) temp_buff;
430
Michael Walle13179c22016-09-01 11:21:40 +0200431 if (le32_to_cpu(fs->sb->feature_incompat) & EXT3_FEATURE_INCOMPAT_RECOVER) {
Uma Shankara74a99a2012-05-25 21:22:49 +0530432 if (recovery_flag == RECOVER)
433 printf("Recovery required\n");
434 } else {
435 if (recovery_flag == RECOVER)
436 printf("File System is consistent\n");
437 goto end;
438 }
439
440 if (be32_to_cpu(jsb->s_start) == 0)
441 goto end;
442
443 if (!(jsb->s_feature_compat &
444 cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM)))
445 jsb->s_feature_compat |=
446 cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
447
448 i = be32_to_cpu(jsb->s_first);
449 while (1) {
Stephen Warren02d6ca72019-01-30 12:58:05 -0700450 blknr = read_allocated_block(&inode_journal, i, NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530451 memset(temp_buff1, '\0', fs->blksz);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200452 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
Uma Shankara74a99a2012-05-25 21:22:49 +0530453 0, fs->blksz, temp_buff1);
454 jdb = (struct journal_header_t *) temp_buff1;
455
456 if (be32_to_cpu(jdb->h_blocktype) ==
457 EXT3_JOURNAL_DESCRIPTOR_BLOCK) {
458 if (be32_to_cpu(jdb->h_sequence) !=
459 be32_to_cpu(jsb->s_sequence)) {
460 print_jrnl_status(recovery_flag);
461 break;
462 }
463
464 curr_desc_logical_no = i;
465 if (transaction_state == TRANSACTION_COMPLETE)
466 transaction_state = TRANSACTION_RUNNING;
467 else
468 return -1;
469 p_jdb = (char *)temp_buff1;
470 ofs = sizeof(struct journal_header_t);
471 do {
472 tag = (struct ext3_journal_block_tag *)
Tom Rini035f18e2017-08-20 22:30:15 -0400473 (p_jdb + ofs);
Uma Shankara74a99a2012-05-25 21:22:49 +0530474 ofs += sizeof(struct ext3_journal_block_tag);
475 if (ofs > fs->blksz)
476 break;
477 flags = be32_to_cpu(tag->flags);
478 if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
479 ofs += 16;
480 i++;
481 debug("\t\ttag %u\n", be32_to_cpu(tag->block));
482 } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
483 i++;
484 DB_FOUND = YES;
485 } else if (be32_to_cpu(jdb->h_blocktype) ==
486 EXT3_JOURNAL_COMMIT_BLOCK) {
487 if (be32_to_cpu(jdb->h_sequence) !=
488 be32_to_cpu(jsb->s_sequence)) {
489 print_jrnl_status(recovery_flag);
490 break;
491 }
492
493 if (transaction_state == TRANSACTION_RUNNING ||
494 (DB_FOUND == NO)) {
495 transaction_state = TRANSACTION_COMPLETE;
496 i++;
497 jsb->s_sequence =
498 cpu_to_be32(be32_to_cpu(
499 jsb->s_sequence) + 1);
500 }
501 prev_desc_logical_no = curr_desc_logical_no;
502 if ((recovery_flag == RECOVER) && (DB_FOUND == YES))
503 recover_transaction(prev_desc_logical_no);
504
505 DB_FOUND = NO;
506 } else if (be32_to_cpu(jdb->h_blocktype) ==
507 EXT3_JOURNAL_REVOKE_BLOCK) {
508 if (be32_to_cpu(jdb->h_sequence) !=
509 be32_to_cpu(jsb->s_sequence)) {
510 print_jrnl_status(recovery_flag);
511 break;
512 }
513 if (recovery_flag == SCAN)
514 ext4fs_push_revoke_blk((char *)jdb);
515 i++;
516 } else {
517 debug("Else Case\n");
518 if (be32_to_cpu(jdb->h_sequence) !=
519 be32_to_cpu(jsb->s_sequence)) {
520 print_jrnl_status(recovery_flag);
521 break;
522 }
523 }
524 }
525
526end:
527 if (recovery_flag == RECOVER) {
Michael Walle13179c22016-09-01 11:21:40 +0200528 uint32_t new_feature_incompat;
Uma Shankara74a99a2012-05-25 21:22:49 +0530529 jsb->s_start = cpu_to_be32(1);
530 jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1);
531 /* get the superblock */
Egbert Eich7b1b2552013-05-01 01:13:19 +0000532 ext4_read_superblock((char *)fs->sb);
Michael Walle13179c22016-09-01 11:21:40 +0200533 new_feature_incompat = le32_to_cpu(fs->sb->feature_incompat);
534 new_feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
535 fs->sb->feature_incompat = cpu_to_le32(new_feature_incompat);
Uma Shankara74a99a2012-05-25 21:22:49 +0530536
537 /* Update the super block */
538 put_ext4((uint64_t) (SUPERBLOCK_SIZE),
539 (struct ext2_sblock *)fs->sb,
540 (uint32_t) SUPERBLOCK_SIZE);
Egbert Eich7b1b2552013-05-01 01:13:19 +0000541 ext4_read_superblock((char *)fs->sb);
Uma Shankara74a99a2012-05-25 21:22:49 +0530542
543 blknr = read_allocated_block(&inode_journal,
Stephen Warren02d6ca72019-01-30 12:58:05 -0700544 EXT2_JOURNAL_SUPERBLOCK, NULL);
Ma Haijune0996ca2014-01-08 08:15:33 +0800545 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
Uma Shankara74a99a2012-05-25 21:22:49 +0530546 (struct journal_superblock_t *)temp_buff,
547 (uint32_t) fs->blksz);
548 ext4fs_free_revoke_blks();
549 }
550 free(temp_buff);
551 free(temp_buff1);
552
553 return 0;
554}
555
556static void update_descriptor_block(long int blknr)
557{
558 int i;
559 long int jsb_blknr;
560 struct journal_header_t jdb;
561 struct ext3_journal_block_tag tag;
562 struct ext2_inode inode_journal;
563 struct journal_superblock_t *jsb = NULL;
564 char *buf = NULL;
565 char *temp = NULL;
566 struct ext_filesystem *fs = get_fs();
567 char *temp_buff = zalloc(fs->blksz);
568 if (!temp_buff)
569 return;
570
571 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
572 jsb_blknr = read_allocated_block(&inode_journal,
Stephen Warren02d6ca72019-01-30 12:58:05 -0700573 EXT2_JOURNAL_SUPERBLOCK, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200574 ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
575 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530576 jsb = (struct journal_superblock_t *) temp_buff;
577
578 jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_DESCRIPTOR_BLOCK);
579 jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
580 jdb.h_sequence = jsb->s_sequence;
581 buf = zalloc(fs->blksz);
582 if (!buf) {
583 free(temp_buff);
584 return;
585 }
586 temp = buf;
587 memcpy(buf, &jdb, sizeof(struct journal_header_t));
588 temp += sizeof(struct journal_header_t);
589
590 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
591 if (journal_ptr[i]->blknr == -1)
592 break;
593
594 tag.block = cpu_to_be32(journal_ptr[i]->blknr);
595 tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_SAME_UUID);
596 memcpy(temp, &tag, sizeof(struct ext3_journal_block_tag));
597 temp = temp + sizeof(struct ext3_journal_block_tag);
598 }
599
600 tag.block = cpu_to_be32(journal_ptr[--i]->blknr);
601 tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_LAST_TAG);
602 memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag,
603 sizeof(struct ext3_journal_block_tag));
Ma Haijune0996ca2014-01-08 08:15:33 +0800604 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
Uma Shankara74a99a2012-05-25 21:22:49 +0530605
606 free(temp_buff);
607 free(buf);
608}
609
610static void update_commit_block(long int blknr)
611{
612 struct journal_header_t jdb;
613 struct ext_filesystem *fs = get_fs();
614 char *buf = NULL;
615 struct ext2_inode inode_journal;
616 struct journal_superblock_t *jsb;
617 long int jsb_blknr;
618 char *temp_buff = zalloc(fs->blksz);
619 if (!temp_buff)
620 return;
621
Frederic Leroye7ee0282013-06-26 18:11:25 +0200622 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
623 &inode_journal);
Uma Shankara74a99a2012-05-25 21:22:49 +0530624 jsb_blknr = read_allocated_block(&inode_journal,
Stephen Warren02d6ca72019-01-30 12:58:05 -0700625 EXT2_JOURNAL_SUPERBLOCK, NULL);
Frederic Leroye7ee0282013-06-26 18:11:25 +0200626 ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
627 temp_buff);
Uma Shankara74a99a2012-05-25 21:22:49 +0530628 jsb = (struct journal_superblock_t *) temp_buff;
629
630 jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_COMMIT_BLOCK);
631 jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
632 jdb.h_sequence = jsb->s_sequence;
633 buf = zalloc(fs->blksz);
634 if (!buf) {
635 free(temp_buff);
636 return;
637 }
638 memcpy(buf, &jdb, sizeof(struct journal_header_t));
Ma Haijune0996ca2014-01-08 08:15:33 +0800639 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
Uma Shankara74a99a2012-05-25 21:22:49 +0530640
641 free(temp_buff);
642 free(buf);
643}
644
645void ext4fs_update_journal(void)
646{
647 struct ext2_inode inode_journal;
648 struct ext_filesystem *fs = get_fs();
649 long int blknr;
650 int i;
Marek Szyprowskia9588152019-06-21 15:35:35 +0200651
652 if (!(fs->sb->feature_compatibility & EXT4_FEATURE_COMPAT_HAS_JOURNAL))
653 return;
654
Uma Shankara74a99a2012-05-25 21:22:49 +0530655 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
Stephen Warren02d6ca72019-01-30 12:58:05 -0700656 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++, NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530657 update_descriptor_block(blknr);
658 for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
659 if (journal_ptr[i]->blknr == -1)
660 break;
Stephen Warren02d6ca72019-01-30 12:58:05 -0700661 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++,
662 NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530663 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
664 journal_ptr[i]->buf, fs->blksz);
665 }
Stephen Warren02d6ca72019-01-30 12:58:05 -0700666 blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++, NULL);
Uma Shankara74a99a2012-05-25 21:22:49 +0530667 update_commit_block(blknr);
668 printf("update journal finished\n");
669}