]>
Commit | Line | Data |
---|---|---|
ed34f34d US |
1 | /* |
2 | * (C) Copyright 2011 - 2012 Samsung Electronics | |
3 | * EXT4 filesystem implementation in Uboot by | |
4 | * Uma Shankar <uma.shankar@samsung.com> | |
5 | * Manjunatha C Achar <a.manjunatha@samsung.com> | |
6 | * | |
7 | * Journal data structures and headers for Journaling feature of ext4 | |
8 | * have been referred from JBD2 (Journaling Block device 2) | |
9 | * implementation in Linux Kernel. | |
10 | * Written by Stephen C. Tweedie <sct@redhat.com> | |
11 | * | |
12 | * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved | |
1a459660 | 13 | * SPDX-License-Identifier: GPL-2.0+ |
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 | */ | |
154 | int ext4fs_log_journal(char *journal_buffer, long int blknr) | |
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 | */ | |
186 | int ext4fs_put_metadata(char *metadata_buffer, long int blknr) | |
187 | { | |
188 | struct ext_filesystem *fs = get_fs(); | |
189 | if (!metadata_buffer) { | |
190 | printf("Invalid input arguments %s\n", __func__); | |
191 | return -EINVAL; | |
192 | } | |
193 | dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz); | |
194 | 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 | ||
202 | void 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) { | |
218 | blocknr = be32_to_cpu(*((long int *)(revk_blk + offset))); | |
219 | printf("revoke blknr is %ld\n", blocknr); | |
220 | offset += 4; | |
221 | } | |
222 | } | |
223 | ||
224 | static 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 | ||
236 | void 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 | ||
472d5460 | 255 | if (first_node == true) { |
ed34f34d US |
256 | revk_blk_list = node; |
257 | prev_node = node; | |
472d5460 | 258 | first_node = false; |
ed34f34d US |
259 | } else { |
260 | prev_node->next = node; | |
261 | prev_node = node; | |
262 | } | |
263 | } | |
264 | ||
265 | void 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) { | |
271 | if (tmp_node->content) | |
272 | free(tmp_node->content); | |
273 | 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; | |
472d5460 | 285 | first_node = true; |
ed34f34d US |
286 | } |
287 | ||
288 | int 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) { | |
305 | blocknr = be32_to_cpu(*((long int *) | |
306 | (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 | ||
317 | found: | |
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 | */ | |
328 | void 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 *) | |
346 | &inode_journal, i); | |
04735e9c FL |
347 | ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz, |
348 | temp_buff); | |
ed34f34d US |
349 | p_jdb = (char *)temp_buff; |
350 | jdb = (struct journal_header_t *) temp_buff; | |
351 | ofs = sizeof(struct journal_header_t); | |
352 | ||
353 | do { | |
354 | tag = (struct ext3_journal_block_tag *)&p_jdb[ofs]; | |
355 | 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 | } | |
371 | blknr = read_allocated_block(&inode_journal, i); | |
04735e9c | 372 | ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, |
ed34f34d | 373 | fs->blksz, metadata_buff); |
0550870b | 374 | put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz), |
ed34f34d US |
375 | metadata_buff, (uint32_t) fs->blksz); |
376 | } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG)); | |
377 | fail: | |
378 | free(temp_buff); | |
379 | free(metadata_buff); | |
380 | } | |
381 | ||
382 | void 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 | ||
390 | int 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; | |
d429ca0d | 398 | int ofs, flags; |
ed34f34d US |
399 | 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 | ||
408 | temp_buff = zalloc(fs->blksz); | |
409 | if (!temp_buff) | |
410 | return -ENOMEM; | |
411 | temp_buff1 = zalloc(fs->blksz); | |
412 | if (!temp_buff1) { | |
413 | free(temp_buff); | |
414 | return -ENOMEM; | |
415 | } | |
416 | ||
417 | ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal); | |
418 | blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK); | |
04735e9c FL |
419 | ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz, |
420 | temp_buff); | |
ed34f34d US |
421 | jsb = (struct journal_superblock_t *) temp_buff; |
422 | ||
423 | if (fs->sb->feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) { | |
424 | if (recovery_flag == RECOVER) | |
425 | printf("Recovery required\n"); | |
426 | } else { | |
427 | if (recovery_flag == RECOVER) | |
428 | printf("File System is consistent\n"); | |
429 | goto end; | |
430 | } | |
431 | ||
432 | if (be32_to_cpu(jsb->s_start) == 0) | |
433 | goto end; | |
434 | ||
435 | if (!(jsb->s_feature_compat & | |
436 | cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM))) | |
437 | jsb->s_feature_compat |= | |
438 | cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM); | |
439 | ||
440 | i = be32_to_cpu(jsb->s_first); | |
441 | while (1) { | |
ed34f34d US |
442 | blknr = read_allocated_block(&inode_journal, i); |
443 | memset(temp_buff1, '\0', fs->blksz); | |
04735e9c | 444 | ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, |
ed34f34d US |
445 | 0, fs->blksz, temp_buff1); |
446 | jdb = (struct journal_header_t *) temp_buff1; | |
447 | ||
448 | if (be32_to_cpu(jdb->h_blocktype) == | |
449 | EXT3_JOURNAL_DESCRIPTOR_BLOCK) { | |
450 | if (be32_to_cpu(jdb->h_sequence) != | |
451 | be32_to_cpu(jsb->s_sequence)) { | |
452 | print_jrnl_status(recovery_flag); | |
453 | break; | |
454 | } | |
455 | ||
456 | curr_desc_logical_no = i; | |
457 | if (transaction_state == TRANSACTION_COMPLETE) | |
458 | transaction_state = TRANSACTION_RUNNING; | |
459 | else | |
460 | return -1; | |
461 | p_jdb = (char *)temp_buff1; | |
462 | ofs = sizeof(struct journal_header_t); | |
463 | do { | |
464 | tag = (struct ext3_journal_block_tag *) | |
465 | &p_jdb[ofs]; | |
466 | ofs += sizeof(struct ext3_journal_block_tag); | |
467 | if (ofs > fs->blksz) | |
468 | break; | |
469 | flags = be32_to_cpu(tag->flags); | |
470 | if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID)) | |
471 | ofs += 16; | |
472 | i++; | |
473 | debug("\t\ttag %u\n", be32_to_cpu(tag->block)); | |
474 | } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG)); | |
475 | i++; | |
476 | DB_FOUND = YES; | |
477 | } else if (be32_to_cpu(jdb->h_blocktype) == | |
478 | EXT3_JOURNAL_COMMIT_BLOCK) { | |
479 | if (be32_to_cpu(jdb->h_sequence) != | |
480 | be32_to_cpu(jsb->s_sequence)) { | |
481 | print_jrnl_status(recovery_flag); | |
482 | break; | |
483 | } | |
484 | ||
485 | if (transaction_state == TRANSACTION_RUNNING || | |
486 | (DB_FOUND == NO)) { | |
487 | transaction_state = TRANSACTION_COMPLETE; | |
488 | i++; | |
489 | jsb->s_sequence = | |
490 | cpu_to_be32(be32_to_cpu( | |
491 | jsb->s_sequence) + 1); | |
492 | } | |
493 | prev_desc_logical_no = curr_desc_logical_no; | |
494 | if ((recovery_flag == RECOVER) && (DB_FOUND == YES)) | |
495 | recover_transaction(prev_desc_logical_no); | |
496 | ||
497 | DB_FOUND = NO; | |
498 | } else if (be32_to_cpu(jdb->h_blocktype) == | |
499 | EXT3_JOURNAL_REVOKE_BLOCK) { | |
500 | if (be32_to_cpu(jdb->h_sequence) != | |
501 | be32_to_cpu(jsb->s_sequence)) { | |
502 | print_jrnl_status(recovery_flag); | |
503 | break; | |
504 | } | |
505 | if (recovery_flag == SCAN) | |
506 | ext4fs_push_revoke_blk((char *)jdb); | |
507 | i++; | |
508 | } else { | |
509 | debug("Else Case\n"); | |
510 | if (be32_to_cpu(jdb->h_sequence) != | |
511 | be32_to_cpu(jsb->s_sequence)) { | |
512 | print_jrnl_status(recovery_flag); | |
513 | break; | |
514 | } | |
515 | } | |
516 | } | |
517 | ||
518 | end: | |
519 | if (recovery_flag == RECOVER) { | |
520 | jsb->s_start = cpu_to_be32(1); | |
521 | jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1); | |
522 | /* get the superblock */ | |
50ce4c07 | 523 | ext4_read_superblock((char *)fs->sb); |
ed34f34d US |
524 | fs->sb->feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER; |
525 | ||
526 | /* Update the super block */ | |
527 | put_ext4((uint64_t) (SUPERBLOCK_SIZE), | |
528 | (struct ext2_sblock *)fs->sb, | |
529 | (uint32_t) SUPERBLOCK_SIZE); | |
50ce4c07 | 530 | ext4_read_superblock((char *)fs->sb); |
ed34f34d US |
531 | |
532 | blknr = read_allocated_block(&inode_journal, | |
533 | EXT2_JOURNAL_SUPERBLOCK); | |
0550870b | 534 | put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), |
ed34f34d US |
535 | (struct journal_superblock_t *)temp_buff, |
536 | (uint32_t) fs->blksz); | |
537 | ext4fs_free_revoke_blks(); | |
538 | } | |
539 | free(temp_buff); | |
540 | free(temp_buff1); | |
541 | ||
542 | return 0; | |
543 | } | |
544 | ||
545 | static void update_descriptor_block(long int blknr) | |
546 | { | |
547 | int i; | |
548 | long int jsb_blknr; | |
549 | struct journal_header_t jdb; | |
550 | struct ext3_journal_block_tag tag; | |
551 | struct ext2_inode inode_journal; | |
552 | struct journal_superblock_t *jsb = NULL; | |
553 | char *buf = NULL; | |
554 | char *temp = NULL; | |
555 | struct ext_filesystem *fs = get_fs(); | |
556 | char *temp_buff = zalloc(fs->blksz); | |
557 | if (!temp_buff) | |
558 | return; | |
559 | ||
560 | ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal); | |
561 | jsb_blknr = read_allocated_block(&inode_journal, | |
562 | EXT2_JOURNAL_SUPERBLOCK); | |
04735e9c FL |
563 | ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz, |
564 | temp_buff); | |
ed34f34d US |
565 | jsb = (struct journal_superblock_t *) temp_buff; |
566 | ||
567 | jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_DESCRIPTOR_BLOCK); | |
568 | jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER); | |
569 | jdb.h_sequence = jsb->s_sequence; | |
570 | buf = zalloc(fs->blksz); | |
571 | if (!buf) { | |
572 | free(temp_buff); | |
573 | return; | |
574 | } | |
575 | temp = buf; | |
576 | memcpy(buf, &jdb, sizeof(struct journal_header_t)); | |
577 | temp += sizeof(struct journal_header_t); | |
578 | ||
579 | for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) { | |
580 | if (journal_ptr[i]->blknr == -1) | |
581 | break; | |
582 | ||
583 | tag.block = cpu_to_be32(journal_ptr[i]->blknr); | |
584 | tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_SAME_UUID); | |
585 | memcpy(temp, &tag, sizeof(struct ext3_journal_block_tag)); | |
586 | temp = temp + sizeof(struct ext3_journal_block_tag); | |
587 | } | |
588 | ||
589 | tag.block = cpu_to_be32(journal_ptr[--i]->blknr); | |
590 | tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_LAST_TAG); | |
591 | memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag, | |
592 | sizeof(struct ext3_journal_block_tag)); | |
0550870b | 593 | put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz); |
ed34f34d US |
594 | |
595 | free(temp_buff); | |
596 | free(buf); | |
597 | } | |
598 | ||
599 | static void update_commit_block(long int blknr) | |
600 | { | |
601 | struct journal_header_t jdb; | |
602 | struct ext_filesystem *fs = get_fs(); | |
603 | char *buf = NULL; | |
604 | struct ext2_inode inode_journal; | |
605 | struct journal_superblock_t *jsb; | |
606 | long int jsb_blknr; | |
607 | char *temp_buff = zalloc(fs->blksz); | |
608 | if (!temp_buff) | |
609 | return; | |
610 | ||
04735e9c FL |
611 | ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, |
612 | &inode_journal); | |
ed34f34d US |
613 | jsb_blknr = read_allocated_block(&inode_journal, |
614 | EXT2_JOURNAL_SUPERBLOCK); | |
04735e9c FL |
615 | ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz, |
616 | temp_buff); | |
ed34f34d US |
617 | jsb = (struct journal_superblock_t *) temp_buff; |
618 | ||
619 | jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_COMMIT_BLOCK); | |
620 | jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER); | |
621 | jdb.h_sequence = jsb->s_sequence; | |
622 | buf = zalloc(fs->blksz); | |
623 | if (!buf) { | |
624 | free(temp_buff); | |
625 | return; | |
626 | } | |
627 | memcpy(buf, &jdb, sizeof(struct journal_header_t)); | |
0550870b | 628 | put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz); |
ed34f34d US |
629 | |
630 | free(temp_buff); | |
631 | free(buf); | |
632 | } | |
633 | ||
634 | void ext4fs_update_journal(void) | |
635 | { | |
636 | struct ext2_inode inode_journal; | |
637 | struct ext_filesystem *fs = get_fs(); | |
638 | long int blknr; | |
639 | int i; | |
640 | ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal); | |
641 | blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++); | |
642 | update_descriptor_block(blknr); | |
643 | for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) { | |
644 | if (journal_ptr[i]->blknr == -1) | |
645 | break; | |
646 | blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++); | |
647 | put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), | |
648 | journal_ptr[i]->buf, fs->blksz); | |
649 | } | |
650 | blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++); | |
651 | update_commit_block(blknr); | |
652 | printf("update journal finished\n"); | |
653 | } |