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 13 * SPDX-License-Identifier: GPL-2.0+ 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; 24 static int first_node = true; 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, uint32_t 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, uint32_t 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 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 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) { 222 blocknr = be32_to_cpu(*((__be32 *)(revk_blk + offset))); 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 259 if (first_node == true) { 260 revk_blk_list = node; 261 prev_node = node; 262 first_node = false; 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; 289 first_node = true; 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) { 309 blocknr = be32_to_cpu(*((__be32 *) 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); 351 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz, 352 temp_buff); 353 p_jdb = (char *)temp_buff; 354 jdb = (struct journal_header_t *) temp_buff; 355 ofs = sizeof(struct journal_header_t); 356 357 do { 358 tag = (struct ext3_journal_block_tag *)&p_jdb[ofs]; 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); 376 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, 377 fs->blksz, metadata_buff); 378 put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz), 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; 402 int ofs, flags; 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); 423 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz, 424 temp_buff); 425 jsb = (struct journal_superblock_t *) temp_buff; 426 427 if (le32_to_cpu(fs->sb->feature_incompat) & EXT3_FEATURE_INCOMPAT_RECOVER) { 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) { 446 blknr = read_allocated_block(&inode_journal, i); 447 memset(temp_buff1, '\0', fs->blksz); 448 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 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 *) 469 &p_jdb[ofs]; 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) { 524 uint32_t new_feature_incompat; 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 */ 528 ext4_read_superblock((char *)fs->sb); 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); 532 533 /* Update the super block */ 534 put_ext4((uint64_t) (SUPERBLOCK_SIZE), 535 (struct ext2_sblock *)fs->sb, 536 (uint32_t) SUPERBLOCK_SIZE); 537 ext4_read_superblock((char *)fs->sb); 538 539 blknr = read_allocated_block(&inode_journal, 540 EXT2_JOURNAL_SUPERBLOCK); 541 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), 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); 570 ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz, 571 temp_buff); 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)); 600 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz); 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 618 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, 619 &inode_journal); 620 jsb_blknr = read_allocated_block(&inode_journal, 621 EXT2_JOURNAL_SUPERBLOCK); 622 ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz, 623 temp_buff); 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)); 635 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz); 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 } 661