static void update_commit_block(long int blknr) { struct journal_header_t jdb; struct ext_filesystem *fs = get_fs(); char *buf = NULL; struct ext2_inode inode_journal; struct journal_superblock_t *jsb; long int jsb_blknr; char *temp_buff = zalloc(fs->blksz); if (!temp_buff) return; ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal); jsb_blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK, NULL); ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz, temp_buff); jsb = (struct journal_superblock_t *) temp_buff; jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_COMMIT_BLOCK); jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER); jdb.h_sequence = jsb->s_sequence; buf = zalloc(fs->blksz); if (!buf) { free(temp_buff); return; } memcpy(buf, &jdb, sizeof(struct journal_header_t)); put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz); free(temp_buff); free(buf); }
void ext4fs_dump_metadata(void) { struct ext_filesystem *fs = get_fs(); int i; for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) { if (dirty_block_ptr[i]->blknr == -1) break; put_ext4((uint64_t) ((uint64_t)dirty_block_ptr[i]->blknr * (uint64_t)fs->blksz), dirty_block_ptr[i]->buf, fs->blksz); } }
static void update_descriptor_block(long int blknr) { int i; long int jsb_blknr; struct journal_header_t jdb; struct ext3_journal_block_tag tag; struct ext2_inode inode_journal; struct journal_superblock_t *jsb = NULL; char *buf = NULL; char *temp = NULL; struct ext_filesystem *fs = get_fs(); char *temp_buff = zalloc(fs->blksz); if (!temp_buff) return; ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal); jsb_blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK, NULL); ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz, temp_buff); jsb = (struct journal_superblock_t *) temp_buff; jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_DESCRIPTOR_BLOCK); jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER); jdb.h_sequence = jsb->s_sequence; buf = zalloc(fs->blksz); if (!buf) { free(temp_buff); return; } temp = buf; memcpy(buf, &jdb, sizeof(struct journal_header_t)); temp += sizeof(struct journal_header_t); for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) { if (journal_ptr[i]->blknr == -1) break; tag.block = cpu_to_be32(journal_ptr[i]->blknr); tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_SAME_UUID); memcpy(temp, &tag, sizeof(struct ext3_journal_block_tag)); temp = temp + sizeof(struct ext3_journal_block_tag); } tag.block = cpu_to_be32(journal_ptr[--i]->blknr); tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_LAST_TAG); memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag, sizeof(struct ext3_journal_block_tag)); put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz); free(temp_buff); free(buf); }
/* * This function parses the journal blocks and replays the * suceessful transactions. A transaction is successfull * if commit block is found for a descriptor block * The tags in descriptor block contain the disk block * numbers of the metadata to be replayed */ void recover_transaction(int prev_desc_logical_no) { struct ext2_inode inode_journal; struct ext_filesystem *fs = get_fs(); struct journal_header_t *jdb; long int blknr; char *p_jdb; int ofs, flags; int i; struct ext3_journal_block_tag *tag; char *temp_buff = zalloc(fs->blksz); char *metadata_buff = zalloc(fs->blksz); if (!temp_buff || !metadata_buff) goto fail; i = prev_desc_logical_no; ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, (struct ext2_inode *)&inode_journal); blknr = read_allocated_block((struct ext2_inode *) &inode_journal, i, NULL); ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz, temp_buff); p_jdb = (char *)temp_buff; jdb = (struct journal_header_t *) temp_buff; ofs = sizeof(struct journal_header_t); do { tag = (struct ext3_journal_block_tag *)(p_jdb + ofs); ofs += sizeof(struct ext3_journal_block_tag); if (ofs > fs->blksz) break; flags = be32_to_cpu(tag->flags); if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID)) ofs += 16; i++; debug("\t\ttag %u\n", be32_to_cpu(tag->block)); if (revk_blk_list != NULL) { if (check_blknr_for_revoke(be32_to_cpu(tag->block), be32_to_cpu(jdb->h_sequence)) == 0) continue; } blknr = read_allocated_block(&inode_journal, i, NULL); ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz, metadata_buff); put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz), metadata_buff, (uint32_t) fs->blksz); } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG)); fail: free(temp_buff); free(metadata_buff); }
void ext4fs_update_journal(void) { struct ext2_inode inode_journal; struct ext_filesystem *fs = get_fs(); long int blknr; int i; ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal); blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++); update_descriptor_block(blknr); for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) { if (journal_ptr[i]->blknr == -1) break; blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++); put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), journal_ptr[i]->buf, fs->blksz); } blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++); update_commit_block(blknr); printf("update journal finished\n"); }
int ext4fs_check_journal_state(int recovery_flag) { int i; int DB_FOUND = NO; long int blknr; int transaction_state = TRANSACTION_COMPLETE; int prev_desc_logical_no = 0; int curr_desc_logical_no = 0; int ofs, flags; struct ext2_inode inode_journal; struct journal_superblock_t *jsb = NULL; struct journal_header_t *jdb = NULL; char *p_jdb = NULL; struct ext3_journal_block_tag *tag = NULL; char *temp_buff = NULL; char *temp_buff1 = NULL; struct ext_filesystem *fs = get_fs(); temp_buff = zalloc(fs->blksz); if (!temp_buff) return -ENOMEM; temp_buff1 = zalloc(fs->blksz); if (!temp_buff1) { free(temp_buff); return -ENOMEM; } ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal); blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK, NULL); ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz, temp_buff); jsb = (struct journal_superblock_t *) temp_buff; if (le32_to_cpu(fs->sb->feature_incompat) & EXT3_FEATURE_INCOMPAT_RECOVER) { if (recovery_flag == RECOVER) printf("Recovery required\n"); } else { if (recovery_flag == RECOVER) printf("File System is consistent\n"); goto end; } if (be32_to_cpu(jsb->s_start) == 0) goto end; if (!(jsb->s_feature_compat & cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM))) jsb->s_feature_compat |= cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM); i = be32_to_cpu(jsb->s_first); while (1) { blknr = read_allocated_block(&inode_journal, i, NULL); memset(temp_buff1, '\0', fs->blksz); ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz, temp_buff1); jdb = (struct journal_header_t *) temp_buff1; if (be32_to_cpu(jdb->h_blocktype) == EXT3_JOURNAL_DESCRIPTOR_BLOCK) { if (be32_to_cpu(jdb->h_sequence) != be32_to_cpu(jsb->s_sequence)) { print_jrnl_status(recovery_flag); break; } curr_desc_logical_no = i; if (transaction_state == TRANSACTION_COMPLETE) transaction_state = TRANSACTION_RUNNING; else return -1; p_jdb = (char *)temp_buff1; ofs = sizeof(struct journal_header_t); do { tag = (struct ext3_journal_block_tag *) (p_jdb + ofs); ofs += sizeof(struct ext3_journal_block_tag); if (ofs > fs->blksz) break; flags = be32_to_cpu(tag->flags); if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID)) ofs += 16; i++; debug("\t\ttag %u\n", be32_to_cpu(tag->block)); } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG)); i++; DB_FOUND = YES; } else if (be32_to_cpu(jdb->h_blocktype) == EXT3_JOURNAL_COMMIT_BLOCK) { if (be32_to_cpu(jdb->h_sequence) != be32_to_cpu(jsb->s_sequence)) { print_jrnl_status(recovery_flag); break; } if (transaction_state == TRANSACTION_RUNNING || (DB_FOUND == NO)) { transaction_state = TRANSACTION_COMPLETE; i++; jsb->s_sequence = cpu_to_be32(be32_to_cpu( jsb->s_sequence) + 1); } prev_desc_logical_no = curr_desc_logical_no; if ((recovery_flag == RECOVER) && (DB_FOUND == YES)) recover_transaction(prev_desc_logical_no); DB_FOUND = NO; } else if (be32_to_cpu(jdb->h_blocktype) == EXT3_JOURNAL_REVOKE_BLOCK) { if (be32_to_cpu(jdb->h_sequence) != be32_to_cpu(jsb->s_sequence)) { print_jrnl_status(recovery_flag); break; } if (recovery_flag == SCAN) ext4fs_push_revoke_blk((char *)jdb); i++; } else { debug("Else Case\n"); if (be32_to_cpu(jdb->h_sequence) != be32_to_cpu(jsb->s_sequence)) { print_jrnl_status(recovery_flag); break; } } } end: if (recovery_flag == RECOVER) { uint32_t new_feature_incompat; jsb->s_start = cpu_to_be32(1); jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1); /* get the superblock */ ext4_read_superblock((char *)fs->sb); new_feature_incompat = le32_to_cpu(fs->sb->feature_incompat); new_feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER; fs->sb->feature_incompat = cpu_to_le32(new_feature_incompat); /* Update the super block */ put_ext4((uint64_t) (SUPERBLOCK_SIZE), (struct ext2_sblock *)fs->sb, (uint32_t) SUPERBLOCK_SIZE); ext4_read_superblock((char *)fs->sb); blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK, NULL); put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), (struct journal_superblock_t *)temp_buff, (uint32_t) fs->blksz); ext4fs_free_revoke_blks(); } free(temp_buff); free(temp_buff1); return 0; }