]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
ed34f34d US |
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 | |
ed34f34d US |
14 | */ |
15 | ||
16 | #include <common.h> | |
17 | #include <ext4fs.h> | |
18 | #include <malloc.h> | |
19 | #include <ext_common.h> | |
20 | #include "ext4_common.h" | |
21 | ||
22 | static struct revoke_blk_list *revk_blk_list; | |
23 | static struct revoke_blk_list *prev_node; | |
472d5460 | 24 | static int first_node = true; |
ed34f34d US |
25 | |
26 | int gindex; | |
27 | int gd_index; | |
28 | int jrnl_blk_idx; | |
29 | struct journal_log *journal_ptr[MAX_JOURNAL_ENTRIES]; | |
30 | struct dirty_blocks *dirty_block_ptr[MAX_JOURNAL_ENTRIES]; | |
31 | ||
32 | int 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; | |
87 | fail: | |
88 | return -1; | |
89 | } | |
90 | ||
91 | void 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 | ||
104 | void 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 | ||
132 | int 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 | */ | |
58a9ecba | 154 | int ext4fs_log_journal(char *journal_buffer, uint32_t blknr) |
ed34f34d US |
155 | { |
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 | */ | |
58a9ecba | 186 | int ext4fs_put_metadata(char *metadata_buffer, uint32_t blknr) |
ed34f34d US |
187 | { |
188 | struct ext_filesystem *fs = get_fs(); | |
189 | if (!metadata_buffer) { | |
190 | printf("Invalid input arguments %s\n", __func__); | |
191 | return -EINVAL; | |
192 | } | |
b1edcf0d SB |
193 | 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 | ||
ed34f34d US |
198 | 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 | ||
206 | void 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) { | |
58a9ecba | 222 | blocknr = be32_to_cpu(*((__be32 *)(revk_blk + offset))); |
ed34f34d US |
223 | printf("revoke blknr is %ld\n", blocknr); |
224 | offset += 4; | |
225 | } | |
226 | } | |
227 | ||
228 | static 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 | ||
240 | void 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 | ||
472d5460 | 259 | if (first_node == true) { |
ed34f34d US |
260 | revk_blk_list = node; |
261 | prev_node = node; | |
472d5460 | 262 | first_node = false; |
ed34f34d US |
263 | } else { |
264 | prev_node->next = node; | |
265 | prev_node = node; | |
266 | } | |
267 | } | |
268 | ||
269 | void 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; | |
472d5460 | 289 | first_node = true; |
ed34f34d US |
290 | } |
291 | ||
292 | int 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) { | |
58a9ecba | 309 | blocknr = be32_to_cpu(*((__be32 *) |
ed34f34d US |
310 | (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 | ||
321 | found: | |
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 | */ | |
332 | void 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 *) | |
350 | &inode_journal, i); | |
04735e9c FL |
351 | ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz, |
352 | temp_buff); | |
ed34f34d US |
353 | p_jdb = (char *)temp_buff; |
354 | jdb = (struct journal_header_t *) temp_buff; | |
355 | ofs = sizeof(struct journal_header_t); | |
356 | ||
357 | do { | |
10b078d8 | 358 | tag = (struct ext3_journal_block_tag *)(p_jdb + ofs); |
ed34f34d US |
359 | 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 | } | |
375 | blknr = read_allocated_block(&inode_journal, i); | |
04735e9c | 376 | ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, |
ed34f34d | 377 | fs->blksz, metadata_buff); |
0550870b | 378 | put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz), |
ed34f34d US |
379 | metadata_buff, (uint32_t) fs->blksz); |
380 | } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG)); | |
381 | fail: | |
382 | free(temp_buff); | |
383 | free(metadata_buff); | |
384 | } | |
385 | ||
386 | void 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 | ||
394 | int 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; | |
d429ca0d | 402 | int ofs, flags; |
ed34f34d US |
403 | 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 | ||
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); | |
04735e9c FL |
423 | ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz, |
424 | temp_buff); | |
ed34f34d US |
425 | jsb = (struct journal_superblock_t *) temp_buff; |
426 | ||
58a9ecba | 427 | if (le32_to_cpu(fs->sb->feature_incompat) & EXT3_FEATURE_INCOMPAT_RECOVER) { |
ed34f34d US |
428 | if (recovery_flag == RECOVER) |
429 | printf("Recovery required\n"); | |
430 | } else { | |
431 | if (recovery_flag == RECOVER) | |
432 | printf("File System is consistent\n"); | |
433 | 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) { | |
ed34f34d US |
446 | blknr = read_allocated_block(&inode_journal, i); |
447 | memset(temp_buff1, '\0', fs->blksz); | |
04735e9c | 448 | ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, |
ed34f34d US |
449 | 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 *) | |
10b078d8 | 469 | (p_jdb + ofs); |
ed34f34d US |
470 | 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 | ||
522 | end: | |
523 | if (recovery_flag == RECOVER) { | |
58a9ecba | 524 | uint32_t new_feature_incompat; |
ed34f34d US |
525 | 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 */ | |
50ce4c07 | 528 | ext4_read_superblock((char *)fs->sb); |
58a9ecba MW |
529 | 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); | |
ed34f34d US |
532 | |
533 | /* Update the super block */ | |
534 | put_ext4((uint64_t) (SUPERBLOCK_SIZE), | |
535 | (struct ext2_sblock *)fs->sb, | |
536 | (uint32_t) SUPERBLOCK_SIZE); | |
50ce4c07 | 537 | ext4_read_superblock((char *)fs->sb); |
ed34f34d US |
538 | |
539 | blknr = read_allocated_block(&inode_journal, | |
540 | EXT2_JOURNAL_SUPERBLOCK); | |
0550870b | 541 | put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), |
ed34f34d US |
542 | (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 | ||
552 | static 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, | |
569 | EXT2_JOURNAL_SUPERBLOCK); | |
04735e9c FL |
570 | ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz, |
571 | temp_buff); | |
ed34f34d US |
572 | 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)); | |
0550870b | 600 | put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz); |
ed34f34d US |
601 | |
602 | free(temp_buff); | |
603 | free(buf); | |
604 | } | |
605 | ||
606 | static 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 | ||
04735e9c FL |
618 | ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, |
619 | &inode_journal); | |
ed34f34d US |
620 | jsb_blknr = read_allocated_block(&inode_journal, |
621 | EXT2_JOURNAL_SUPERBLOCK); | |
04735e9c FL |
622 | ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz, |
623 | temp_buff); | |
ed34f34d US |
624 | 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)); | |
0550870b | 635 | put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz); |
ed34f34d US |
636 | |
637 | free(temp_buff); | |
638 | free(buf); | |
639 | } | |
640 | ||
641 | void 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; | |
647 | ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal); | |
648 | blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++); | |
649 | update_descriptor_block(blknr); | |
650 | for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) { | |
651 | if (journal_ptr[i]->blknr == -1) | |
652 | break; | |
653 | blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++); | |
654 | put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), | |
655 | journal_ptr[i]->buf, fs->blksz); | |
656 | } | |
657 | blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++); | |
658 | update_commit_block(blknr); | |
659 | printf("update journal finished\n"); | |
660 | } |