static void create_local_alloc(ocfs2_filesys *fs, uint64_t blkno) { errcode_t ret; char *buf = NULL; struct ocfs2_dinode *di; struct ocfs2_local_alloc *la; uint32_t la_size, found; uint64_t la_off; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) FSWRK_COM_FATAL(progname, ret); ret = ocfs2_read_inode(fs, blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); di = (struct ocfs2_dinode *)buf; if (!(di->i_flags & OCFS2_VALID_FL)) FSWRK_FATAL("not a file"); if (!(di->i_flags & OCFS2_LOCAL_ALLOC_FL)) FSWRK_FATAL("not a local alloc file"); if (di->id1.bitmap1.i_total > 0) { FSWRK_WARN("local alloc#%"PRIu64" file not empty." "Can't create a new one.\n", blkno); goto bail; } la_size = get_local_alloc_window_bits(); ret = ocfs2_new_clusters(fs, 1, la_size, &la_off, &found); if (ret) FSWRK_COM_FATAL(progname, ret); if(la_size != found) FSWRK_FATAL("can't allocate enough clusters for local alloc"); la = &(di->id2.i_lab); la->la_bm_off = la_off; di->id1.bitmap1.i_total = la_size; di->id1.bitmap1.i_used = 0; memset(la->la_bitmap, 0, la->la_size); ret = ocfs2_write_inode(fs, blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); bail: if(buf) ocfs2_free(&buf); return; }
void mess_up_inode_field(ocfs2_filesys *fs, enum fsck_type type, uint64_t blkno) { errcode_t ret; uint64_t tmpblkno; uint32_t clusters = 10; char *buf = NULL; struct ocfs2_dinode *di; create_file(fs, blkno, &tmpblkno); if ((type == INODE_SPARSE_SIZE) || (type == INODE_SPARSE_CLUSTERS)) { if (!ocfs2_sparse_alloc(OCFS2_RAW_SB(fs->fs_super))) FSWRK_FATAL("should specfiy a sparse file supported " "volume to do this corruption\n"); ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) FSWRK_COM_FATAL(progname, ret); ret = ocfs2_read_inode(fs, tmpblkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); di = (struct ocfs2_dinode *)buf; di->i_size = fs->fs_clustersize * 2; ret = ocfs2_write_inode(fs, tmpblkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); if (buf) ocfs2_free(&buf); } if ((type == INODE_CLUSTERS) || (type == INODE_SPARSE_CLUSTERS) || (type == INODE_SPARSE_SIZE)) { ret = ocfs2_extend_allocation(fs, tmpblkno, clusters); if (ret) FSWRK_COM_FATAL(progname, ret); } if (type == REFCOUNT_FLAG_INVALID && ocfs2_refcount_tree(OCFS2_RAW_SB(fs->fs_super))) FSWRK_FATAL("should specfiy a norefcount volume\n"); if (type == REFCOUNT_LOC_INVALID && !ocfs2_refcount_tree(OCFS2_RAW_SB(fs->fs_super))) FSWRK_FATAL("Should specify a refcount supported volume\n"); damage_inode(fs, tmpblkno, type); return; }
void corrupt_truncate_log(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) { void (*func)(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) = NULL; switch (type) { case DEALLOC_COUNT: func = mess_up_truncate_log_list; break; case DEALLOC_USED: func = mess_up_truncate_log_list; break; case TRUNCATE_REC_START_RANGE: func = mess_up_truncate_log_rec; break; case TRUNCATE_REC_WRAP: func = mess_up_truncate_log_rec; break; case TRUNCATE_REC_RANGE: func = mess_up_truncate_log_rec; break; default: FSWRK_FATAL("Invalid code = %d", type); } if (func) func(fs, type, slotnum); return; }
/* * corrupt_chains() * */ void corrupt_chains(ocfs2_filesys *fs, int code, uint16_t slotnum) { errcode_t ret; uint64_t blkno; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); char sysfile[40]; switch (code) { case 3: case 4: case 5: case 6: case 7: case 8: case 10: case 11: case 12: snprintf(sysfile, sizeof(sysfile), ocfs2_system_inodes[GLOBAL_BITMAP_SYSTEM_INODE].si_name); break; #ifdef _LATER_ case X: snprintf(sysfile, sizeof(sysfile), ocfs2_system_inodes[GLOBAL_INODE_ALLOC_SYSTEM_INODE].si_name); break; case Y: snprintf(sysfile, sizeof(sysfile), ocfs2_system_inodes[EXTENT_ALLOC_SYSTEM_INODE].si_name, slotnum); break; case Z: snprintf(sysfile, sizeof(sysfile), ocfs2_system_inodes[INODE_ALLOC_SYSTEM_INODE].si_name, slotnum); break; #endif default: FSWRK_FATAL("Invalid code=%d", code); } ret = ocfs2_lookup(fs, sb->s_system_dir_blkno, sysfile, strlen(sysfile), NULL, &blkno); if (ret) FSWRK_FATAL(); mess_up_chains(fs, blkno, code); return ; }
void mess_up_inline_flag(ocfs2_filesys *fs, enum fsck_type type, uint64_t blkno) { int i; errcode_t ret; char *buf = NULL, file_type[20]; uint64_t inline_blkno; struct ocfs2_dinode *di; struct ocfs2_super_block *osb; osb = OCFS2_RAW_SB(fs->fs_super); if (ocfs2_support_inline_data(osb)) FSWRK_FATAL("should specfiy a noinline-data supported " "volume to do this corruption\n"); ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) FSWRK_COM_FATAL(progname, ret); for (i = 0; i < 2; i++) { if (i == 0) { create_file(fs, blkno, &inline_blkno); snprintf(file_type, 20, "%s", "Regular file"); } else { create_directory(fs, blkno, &inline_blkno); snprintf(file_type, 20, "%s", "Diectory"); } ret = ocfs2_read_inode(fs, inline_blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); di = (struct ocfs2_dinode *)buf; if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL)) { di->i_dyn_features |= OCFS2_INLINE_DATA_FL; ret = ocfs2_write_inode(fs, inline_blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); } fprintf(stdout, "INLINE_DATA_FLAG_INVALID: " "Create an inlined inode#%"PRIu64"(%s) " "on a noinline-data supported volume\n", inline_blkno, file_type); } if (buf) ocfs2_free(&buf); return; }
void corrupt_group_desc(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) { void (*func)(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) = NULL; switch (type) { case GROUP_PARENT: func = mess_up_group_minor; break; case GROUP_BLKNO: func = mess_up_group_minor; break; case GROUP_CHAIN: func = mess_up_group_minor; break; case GROUP_FREE_BITS: func = mess_up_group_minor; break; case GROUP_CHAIN_LOOP: func = mess_up_group_minor; break; case GROUP_GEN: func = mess_up_group_gen; break; case GROUP_UNEXPECTED_DESC: func = mess_up_group_list; break; case GROUP_EXPECTED_DESC: func = mess_up_group_list; break; case CLUSTER_GROUP_DESC: func = mess_up_cluster_group_desc; break; case CLUSTER_ALLOC_BIT: func = mess_up_cluster_alloc_bits; break; default: FSWRK_FATAL("Invalid code=%d", type); } if (func) func(fs, type, slotnum); return; }
void corrupt_local_alloc(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) { void (*func)(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) = NULL; switch (type) { case LALLOC_SIZE: func = mess_up_local_alloc_empty; break; case LALLOC_NZ_USED: func = mess_up_local_alloc_empty; break; case LALLOC_NZ_BM: func = mess_up_local_alloc_empty; break; case LALLOC_BM_OVERRUN: func = mess_up_local_alloc_bitmap; break; case LALLOC_BM_STRADDLE: func = mess_up_local_alloc_bitmap; break; case LALLOC_BM_SIZE: func = mess_up_local_alloc_bitmap; break; case LALLOC_USED_OVERRUN: func = mess_up_local_alloc_used; break; case LALLOC_CLEAR: func = mess_up_local_alloc_used; break; default: FSWRK_FATAL("Invalid code = %d", type); } if (func) func(fs, type, slotnum); return; }
void corrupt_refcount(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) { uint64_t blkno; void (*func)(ocfs2_filesys *fs, enum fsck_type type, uint64_t blkno) = NULL; switch (type) { case RB_BLKNO: case RB_GEN: case RB_GEN_FIX: case RB_PARENT: case REFCOUNT_BLOCK_INVALID: case REFCOUNT_ROOT_BLOCK_INVALID: case REFCOUNT_LIST_COUNT: case REFCOUNT_LIST_USED: case REFCOUNT_CLUSTER_RANGE: case REFCOUNT_CLUSTER_COLLISION: case REFCOUNT_LIST_EMPTY: case REFCOUNT_REC_REDUNDANT: case REFCOUNT_COUNT_INVALID: case DUP_CLUSTERS_ADD_REFCOUNT: func = mess_up_refcount_tree_block; break; case REFCOUNT_CLUSTERS: case REFCOUNT_COUNT: func = mess_up_refcount_tree; break; default: FSWRK_FATAL("Invalid code = %d", type); } create_named_directory(fs, "tmp", &blkno); if (func) func(fs, type, blkno); return; }
static void damage_inode(ocfs2_filesys *fs, uint64_t blkno, enum fsck_type type) { errcode_t ret; char *buf = NULL; struct ocfs2_dinode *di; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) FSWRK_COM_FATAL(progname, ret); ret = ocfs2_read_inode(fs, blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); di = (struct ocfs2_dinode *)buf; if (!(di->i_flags & OCFS2_VALID_FL)) FSWRK_FATAL("not a file"); switch (type) { case INODE_GEN: fprintf(stdout, "INODE_GEN: " "Corrupt inode#%"PRIu64", change generation " " from %u to 0x1234\n", blkno, di->i_fs_generation); di->i_fs_generation = 0x1234; break; case INODE_GEN_FIX: fprintf(stdout, "INODE_GEN_FIX: " "Corrupt inode#%"PRIu64", change generation " " from %u to 0x1234, please answer 'n' when " "INODE_GEN error shows in fsck.ocfs2\n", blkno, di->i_fs_generation); di->i_fs_generation = 0x1234; break; case INODE_BLKNO: fprintf(stdout, "INODE_BLKNO: " "Corrupt inode#%"PRIu64", change i_blkno from %"PRIu64 " to %"PRIu64"\n", blkno, di->i_blkno, (di->i_blkno + 100)); di->i_blkno += 100; break; case INODE_NZ_DTIME: fprintf(stdout, "INODE_NZ_DTIME: " "Corrupt inode#%"PRIu64", change i_dtime from %"PRIu64 " to 100\n", blkno, di->i_dtime); di->i_dtime = 100; break; case INODE_SUBALLOC: fprintf(stdout, "INODE_SUBALLOC: " "Corrupt inode#%"PRIu64", change i_suballoc_slot" " from %u to %u\n", blkno, di->i_suballoc_slot, (di->i_suballoc_slot + 10)); di->i_suballoc_slot += 10; break; case INODE_SIZE: fprintf(stdout, "INODE_SIZE: " "Corrupt inode#%"PRIu64", change i_size" " from %"PRIu64" to %"PRIu64"\n", blkno, di->i_size, (di->i_size + 100)); di->i_size += 100; break; case INODE_SPARSE_SIZE: fprintf(stdout, "INODE_SPARSE_SIZE: " "Corrupt inode#%"PRIu64", change i_size " "from %"PRIu64" to %u\n", blkno, di->i_size, fs->fs_clustersize); di->i_size = fs->fs_clustersize; break; case INODE_CLUSTERS: fprintf(stdout, "INODE_CLUSTERS: " "Corrupt inode#%"PRIu64", change i_clusters" " from %u to 0\n", blkno, di->i_clusters); di->i_clusters = 0; break; case INODE_SPARSE_CLUSTERS: fprintf(stdout, "INODE_SPARSE_CLUSTERS: " "Corrupt inode#%"PRIu64", change i_clusters" " from %u to 0\n", blkno, di->i_clusters); di->i_clusters = 0; break; case INODE_COUNT: di->i_links_count = 0; fprintf(stdout, "INODE_COUNT: " "Corrupte inode#%"PRIu64", set link count to 0\n", blkno); break; case INODE_BLOCK_ECC: fprintf(stdout, "INODE_BLOCK_ECC: " "Corrupte inode#%"PRIu64", set both i_check.bc_crc32e" "=%"PRIu64" and i_check.bc_ecc=%"PRIu64" to 0x1234\n", blkno, di->i_check.bc_crc32e, di->i_check.bc_ecc); di->i_check.bc_crc32e = 0x1234; di->i_check.bc_ecc = 0x1234; break; case INODE_VALID_FLAG: fprintf(stdout, "INODE_VALID_FLAG: " "Corrupt inode#%"PRIu64", clear inode valid flag\n", blkno); di->i_flags &= ~OCFS2_VALID_FL; break; case REFCOUNT_FLAG_INVALID: di->i_dyn_features |= OCFS2_HAS_REFCOUNT_FL; fprintf(stdout, "REFCOUNT_FLAG_INVALD: " "Corrupt inode#%"PRIu64", add refcount feature\n", blkno); break; case REFCOUNT_LOC_INVALID: di->i_refcount_loc = 100; fprintf(stdout, "REFCOUNT_LOC_INVALID: " "Create an inode#%"PRIu64"," "whose i_refcount_loc has been messed up.\n", blkno); break; default: FSWRK_FATAL("Invalid type[%d]\n", type); } if (type != INODE_BLOCK_ECC) ret = ocfs2_write_inode(fs, blkno, buf); else ret = ocfs2_write_inode_without_meta_ecc(fs, blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); if (buf) ocfs2_free(&buf); return; }
void mess_up_dup_clusters(ocfs2_filesys *fs, enum fsck_type type, uint64_t blkno) { errcode_t err; char *buf = NULL; uint64_t inode1_blkno, inode2_blkno; struct ocfs2_dinode *di1, *di2; struct ocfs2_extent_list *el1, *el2; err = ocfs2_malloc_blocks(fs->fs_io, 2, &buf); if (err) FSWRK_COM_FATAL(progname, err); create_file(fs, blkno, &inode1_blkno); di1 = (struct ocfs2_dinode *)buf; err = ocfs2_read_inode(fs, inode1_blkno, (char *)di1); if (err) FSWRK_COM_FATAL(progname, err); if (ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super))) { if (di1->i_dyn_features & OCFS2_INLINE_DATA_FL) { di1->i_dyn_features &= ~OCFS2_INLINE_DATA_FL; err = ocfs2_write_inode(fs, inode1_blkno, (char *)di1); if (err) FSWRK_COM_FATAL(progname, err); } } if (type != DUP_CLUSTERS_SYSFILE_CLONE) { create_file(fs, blkno, &inode2_blkno); di2 = (struct ocfs2_dinode *)(buf + fs->fs_blocksize); err = ocfs2_read_inode(fs, inode2_blkno, (char *)di2); if (err) FSWRK_COM_FATAL(progname, err); if (ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super))) { if (di2->i_dyn_features & OCFS2_INLINE_DATA_FL) { di2->i_dyn_features &= ~OCFS2_INLINE_DATA_FL; err = ocfs2_write_inode(fs, inode2_blkno, (char *)di2); if (err) FSWRK_COM_FATAL(progname, err); } } err = ocfs2_extend_allocation(fs, inode2_blkno, 1); if (err) FSWRK_COM_FATAL(progname, err); /* Re-read the inode with the allocation */ err = ocfs2_read_inode(fs, inode2_blkno, (char *)di2); if (err) FSWRK_COM_FATAL(progname, err); /* Set i_size to non-zero so that the allocation is valid */ di2->i_size = fs->fs_clustersize; err = ocfs2_write_inode(fs, inode2_blkno, (char *)di2); if (err) FSWRK_COM_FATAL(progname, err); if (type == DUP_CLUSTERS_CLONE) fprintf(stdout, "DUP_CLUSTERS_CLONE: " "Create two inodes #%"PRIu64" and #%"PRIu64 " by allocating same cluster to them.\n", inode1_blkno, inode2_blkno); else fprintf(stdout, "DUP_CLUSTERS_DELETE: " "Create two inodes #%"PRIu64" and #%"PRIu64 " by allocating same cluster to them.\n", inode1_blkno, inode2_blkno); } else { /* Here use journal file*/ err = ocfs2_lookup_system_inode(fs, JOURNAL_SYSTEM_INODE, 0, &inode2_blkno); if (err) FSWRK_COM_FATAL(progname, err); di2 = (struct ocfs2_dinode *)(buf + fs->fs_blocksize); err = ocfs2_read_inode(fs, inode2_blkno, (char *)di2); if (err) FSWRK_COM_FATAL(progname, err); if (di2->id2.i_list.l_tree_depth) FSWRK_FATAL("Journal inode has non-zero tree " "depth. fswreck can't use it for " "DUP_CLUSTERS_SYSFILE_CLONE\n"); fprintf(stdout, "DUP_CLUSTERS_SYSFILE_CLONE: " "Allocate same cluster to journal file " "#%"PRIu64" and regular file #%"PRIu64".\n", inode1_blkno, inode2_blkno); } el1 = &(di1->id2.i_list); el2 = &(di2->id2.i_list); el1->l_next_free_rec = 1; el1->l_recs[0] = el2->l_recs[0]; di1->i_size = ocfs2_clusters_to_bytes(fs, el1->l_recs[0].e_leaf_clusters); di1->i_clusters = di2->i_clusters; err = ocfs2_write_inode(fs, inode1_blkno, (char *)di1); if (err) FSWRK_COM_FATAL(progname, err); ocfs2_free(&buf); }
void mess_up_inline_inode(ocfs2_filesys *fs, enum fsck_type type, uint64_t blkno) { int i; errcode_t ret; char *buf = NULL, file_type[20]; uint64_t inline_blkno; struct ocfs2_dinode *di; uint16_t max_inline_sz; struct ocfs2_super_block *osb; osb = OCFS2_RAW_SB(fs->fs_super); if (!ocfs2_support_inline_data(osb)) FSWRK_FATAL("Should specify a inline-data supported " "volume to do this corruption\n"); ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) FSWRK_COM_FATAL(progname, ret); for (i = 0; i < 2; i++) { if (i == 0) { create_file(fs, blkno, &inline_blkno); snprintf(file_type, 20, "%s", "Regular file"); } else { create_directory(fs, blkno, &inline_blkno); snprintf(file_type, 20, "%s", "Diectroy"); } ret = ocfs2_read_inode(fs, inline_blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); di = (struct ocfs2_dinode *)buf; max_inline_sz = ocfs2_max_inline_data_with_xattr(fs->fs_blocksize, di); if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL)) di->i_dyn_features |= OCFS2_INLINE_DATA_FL; switch (type) { case INLINE_DATA_COUNT_INVALID: di->id2.i_data.id_count = 0; fprintf(stdout, "INLINE_DATA_COUNT_INVALID: " "Create an inlined inode#%"PRIu64"(%s)," "whose id_count has been messed up.\n", inline_blkno, file_type); break; case INODE_INLINE_SIZE: di->i_size = max_inline_sz + 1; fprintf(stdout, "INODE_INLINE_SIZE: " "Create an inlined inode#%"PRIu64"(%s)," "whose i_size has been messed up.\n", inline_blkno, file_type); break; case INODE_INLINE_CLUSTERS: di->i_clusters = 1; fprintf(stdout, "INODE_INLINE_CLUSTERS: " "Create an inlined inode#%"PRIu64"(%s)," "whose i_clusters has been messed up.\n", inline_blkno, file_type); break; default: FSWRK_FATAL("Invalid type[%d]\n", type); } ret = ocfs2_write_inode(fs, inline_blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); } if (buf) ocfs2_free(&buf); return; }
void corrupt_sys_file(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) { void (*func)(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) = NULL; switch (type) { case CHAIN_COUNT: func = mess_up_chains_list; break; case CHAIN_NEXT_FREE: func = mess_up_chains_list; break; case CHAIN_EMPTY: func = mess_up_chains_rec; break; case CHAIN_HEAD_LINK_RANGE: func = mess_up_chains_rec; break; case CHAIN_BITS: func = mess_up_chains_rec; break; case CLUSTER_ALLOC_BIT: func = mess_up_chains_rec; break; case CHAIN_I_CLUSTERS: func = mess_up_chains_inode; break; case CHAIN_I_SIZE: func = mess_up_chains_inode; break; case CHAIN_GROUP_BITS: func = mess_up_chains_inode; break; case CHAIN_LINK_GEN: func = mess_up_chains_group; break; case CHAIN_LINK_RANGE: func = mess_up_chains_group; break; case CHAIN_LINK_MAGIC: func = mess_up_chains_group_magic; break; case CHAIN_CPG: func = mess_up_chains_cpg; break; case SUPERBLOCK_CLUSTERS_EXCESS: func = mess_up_superblock_clusters_excess; break; case SUPERBLOCK_CLUSTERS_LACK: func = mess_up_superblock_clusters_lack; break; case INODE_ORPHANED: func = mess_up_inode_orphaned; break; case INODE_ALLOC_REPAIR: func = mess_up_inode_alloc; break; case JOURNAL_FILE_INVALID: case JOURNAL_UNKNOWN_FEATURE: case JOURNAL_MISSING_FEATURE: case JOURNAL_TOO_SMALL: func = mess_up_journal; break; default: FSWRK_FATAL("Invalid code=%d", type); } if (func) func(fs, type, slotnum); return; }
void corrupt_file(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) { void (*func)(ocfs2_filesys *fs, enum fsck_type type, uint64_t blkno) = NULL; uint64_t blkno; switch (type) { case EB_BLKNO: func = mess_up_extent_block; break; case EB_GEN: func = mess_up_extent_block; break; case EB_GEN_FIX: func = mess_up_extent_block; break; case EXTENT_EB_INVALID: func = mess_up_extent_block; break; case EXTENT_MARKED_UNWRITTEN: case EXTENT_BLKNO_UNALIGNED: func = mess_up_extent_record; break; case EXTENT_CLUSTERS_OVERRUN: func = mess_up_extent_record; break; case EXTENT_BLKNO_RANGE: func = mess_up_extent_record; break; case EXTENT_LIST_DEPTH: func = mess_up_extent_list; break; case EXTENT_LIST_COUNT: func = mess_up_extent_list; break; case EXTENT_LIST_FREE: func = mess_up_extent_list; break; case INODE_SUBALLOC: func = mess_up_inode_field; break; case INODE_GEN: func = mess_up_inode_field; break; case INODE_GEN_FIX: func = mess_up_inode_field; break; case INODE_BLKNO: func = mess_up_inode_field; break; case INODE_NZ_DTIME: func = mess_up_inode_field; break; case INODE_SIZE: func = mess_up_inode_field; break; case INODE_SPARSE_SIZE: func = mess_up_inode_field; break; case INODE_CLUSTERS: func = mess_up_inode_field; break; case INODE_SPARSE_CLUSTERS: func = mess_up_inode_field; break; case INODE_COUNT: func = mess_up_inode_field; break; case INODE_LINK_NOT_CONNECTED: func = mess_up_inode_not_connected; break; case LINK_FAST_DATA: func = mess_up_symlink; break; case LINK_NULLTERM: func = mess_up_symlink; break; case LINK_SIZE: func = mess_up_symlink; break; case LINK_BLOCKS: func = mess_up_symlink; break; case ROOT_NOTDIR: func = mess_up_root; break; case ROOT_DIR_MISSING: func = mess_up_root; break; case LOSTFOUND_MISSING: func = mess_up_root; break; case DIR_ZERO: func = mess_up_dir_inode; break; case DIRENT_DOTTY_DUP: func = mess_up_dir_dot; break; case DIRENT_NOT_DOTTY: func = mess_up_dir_dot; break; case DIRENT_DOT_INODE: func = mess_up_dir_dot; break; case DIRENT_DOT_EXCESS: func = mess_up_dir_dot; break; case DIRENT_ZERO: func = mess_up_dir_ent; break; case DIRENT_NAME_CHARS: func = mess_up_dir_ent; break; case DIRENT_INODE_RANGE: func = mess_up_dir_ent; break; case DIRENT_INODE_FREE: func = mess_up_dir_ent; break; case DIRENT_TYPE: func = mess_up_dir_ent; break; case DIRENT_DUPLICATE: func = mess_up_dir_ent; break; case DIRENT_LENGTH: func = mess_up_dir_ent; break; case DIR_PARENT_DUP: func = mess_up_dir_parent_dup; break; case DIR_NOT_CONNECTED: func = mess_up_dir_not_connected; break; case INLINE_DATA_FLAG_INVALID: func = mess_up_inline_flag; break; case INLINE_DATA_COUNT_INVALID: func = mess_up_inline_inode; break; case INODE_INLINE_SIZE: func = mess_up_inline_inode; break; case INODE_INLINE_CLUSTERS: func = mess_up_inline_inode; break; case DUP_CLUSTERS_CLONE: case DUP_CLUSTERS_DELETE: case DUP_CLUSTERS_SYSFILE_CLONE: func = mess_up_dup_clusters; break; default: FSWRK_FATAL("Invalid code=%d", type); } create_named_directory(fs, "tmp", &blkno); if (func) func(fs, type, blkno); return; }
static void create_truncate_log(ocfs2_filesys *fs, uint64_t blkno, uint16_t used, uint32_t clusters) { errcode_t ret; char *buf = NULL; struct ocfs2_dinode *di; struct ocfs2_truncate_log *tl; uint16_t i, max; uint32_t found; uint64_t begin; max = ocfs2_truncate_recs_per_inode(fs->fs_blocksize); if (used > max) FSWRK_FATAL("recnum exceeds the limit of truncate log"); ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) FSWRK_COM_FATAL(progname, ret); ret = ocfs2_read_inode(fs, blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); di = (struct ocfs2_dinode *)buf; if (!(di->i_flags & OCFS2_VALID_FL)) FSWRK_FATAL("not a valid file"); if (!(di->i_flags & OCFS2_DEALLOC_FL)) FSWRK_FATAL("not a valid truncate log"); tl = &di->id2.i_dealloc; if (tl->tl_used > 0) { FSWRK_WARN("truncate log#%"PRIu64" file not empty." "Can't create a new one.\n", blkno); goto bail; } used = min(used, tl->tl_count); tl->tl_used = used; for (i = 0; i < tl->tl_used; i++) { ret = ocfs2_new_clusters(fs, 1, clusters, &begin, &found); if (ret) FSWRK_COM_FATAL(progname, ret); tl->tl_recs[i].t_start = cpu_to_le32(ocfs2_blocks_to_clusters(fs, begin)); tl->tl_recs[i].t_clusters = cpu_to_le32(found); } ret = ocfs2_write_inode(fs, blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); bail: if(buf) ocfs2_free(&buf); return; }
static void damage_local_alloc(ocfs2_filesys *fs, uint64_t blkno, enum fsck_type type) { errcode_t ret; char *buf = NULL; struct ocfs2_dinode *di; struct ocfs2_local_alloc *la; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) FSWRK_COM_FATAL(progname, ret); ret = ocfs2_read_inode(fs, blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); di = (struct ocfs2_dinode *)buf; if (!(di->i_flags & OCFS2_VALID_FL)) FSWRK_FATAL("not a file"); if (!(di->i_flags & OCFS2_LOCAL_ALLOC_FL)) FSWRK_FATAL("not a local alloc file"); la = &(di->id2.i_lab); /* For LALLOC_BM_OVERRUN, LALLOC_BM_STRADDLE,LALLOC_BM_SIZE, * LALLOC_USED_OVERRUN, LALLOC_CLEAR, i_total must be greater than 0. * So check it first. */ if (type == LALLOC_BM_OVERRUN || type == LALLOC_BM_STRADDLE || type == LALLOC_BM_SIZE || type == LALLOC_USED_OVERRUN) if (di->id1.bitmap1.i_total == 0) { FSWRK_WARN("local inode#%"PRIu64" is empty, so can't" "corrupt it for type[%d]\n", blkno, type); goto bail; } switch (type) { case LALLOC_SIZE: case LALLOC_CLEAR: if (type == LALLOC_SIZE) fprintf(stdout, "LALLOC_SIZE: "); else fprintf(stdout, "LALLOC_CLEAR: "); fprintf(stdout, "Corrupt local alloc inode#%"PRIu64 ", change size from %u to %u\n", blkno, la->la_size, (ocfs2_local_alloc_size(fs->fs_blocksize) + 10)); la->la_size = ocfs2_local_alloc_size(fs->fs_blocksize) + 10; break; case LALLOC_NZ_USED: di->id1.bitmap1.i_total = 0; di->id1.bitmap1.i_used = 10; fprintf(stdout, "LALLOC_NZ_USED: " "Corrupt local alloc inode#%"PRIu64", total = %d " " used = %d\n",blkno, di->id1.bitmap1.i_total, di->id1.bitmap1.i_used); break; case LALLOC_NZ_BM: di->id1.bitmap1.i_total = 0; la->la_bm_off = 100; fprintf(stdout, "LALLOC_NZ_BM: " "Corrupt local alloc inode#%"PRIu64", total = %d " " la_bm_off = %d\n",blkno, di->id1.bitmap1.i_total, la->la_bm_off); break; case LALLOC_BM_OVERRUN: case LALLOC_BM_STRADDLE: la->la_bm_off = fs->fs_clusters + 10; if (type == LALLOC_BM_OVERRUN) fprintf(stdout, "LALLOC_BM_OVERRUN: "); else fprintf(stdout, "LALLOC_BM_STRADDLE: "); fprintf(stdout, "Corrupt local alloc inode#%"PRIu64 ", la_bm_off =%u\n", blkno, la->la_bm_off); break; case LALLOC_BM_SIZE: fprintf(stdout, "LALLOC_SIZE: " "Corrupt local alloc inode#%"PRIu64", change i_total" " from %u to %u\n", blkno, di->id1.bitmap1.i_total, (la->la_size * 8 + 10)); di->id1.bitmap1.i_total = la->la_size * 8 + 10; break; case LALLOC_USED_OVERRUN: fprintf(stdout, "LALLOC_USED_OVERRUN: " "Corrupt local alloc inode#%"PRIu64", change i_used" " from %u to %u\n", blkno, di->id1.bitmap1.i_used, (di->id1.bitmap1.i_total + 10)); di->id1.bitmap1.i_used = di->id1.bitmap1.i_total + 10; break; default: FSWRK_FATAL("Unknown type = %d", type); } ret = ocfs2_write_inode(fs, blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); bail: if (buf) ocfs2_free(&buf); return; }
static void damage_truncate_log(ocfs2_filesys *fs, uint64_t blkno, enum fsck_type type, int recnum) { errcode_t ret; char *buf = NULL; struct ocfs2_dinode *di; struct ocfs2_truncate_log *tl; struct ocfs2_truncate_rec *tr; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) FSWRK_COM_FATAL(progname, ret); ret = ocfs2_read_inode(fs, blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); di = (struct ocfs2_dinode *)buf; if (!(di->i_flags & OCFS2_VALID_FL)) FSWRK_FATAL("not a valid file"); if (!(di->i_flags & OCFS2_DEALLOC_FL)) FSWRK_FATAL("not a valid truncate log"); tl = &di->id2.i_dealloc; /* For TRUNCATE_REC_START_RANGE, TRUNCATE_REC_WRAP, TRUNCATE_REC_RANGE, * tl_used must be greater than 0 and recnum must be less than tl_used. * So check it first. */ if (type == TRUNCATE_REC_START_RANGE || type == TRUNCATE_REC_WRAP || type == TRUNCATE_REC_RANGE) { if (tl->tl_used == 0) { FSWRK_WARN("truncate log#%"PRIu64" is empty, so can't" "corrupt it for type[%d]\n", blkno, type); goto bail; } if(tl->tl_used <= recnum) { FSWRK_WARN("truncate log#%"PRIu64" can't corrupt " "item[%d] corrupt it for type[%d]\n", blkno, recnum, type); goto bail; } } switch (type) { case DEALLOC_COUNT: fprintf(stdout, "DEALLOC_COUNT: " "Corrupt truncate log inode#%"PRIu64", change tl_count" " from %u to %u\n", blkno, tl->tl_count, (tl->tl_count + 10)); tl->tl_count += 10; break; case DEALLOC_USED: fprintf(stdout, "DEALLOC_USED: " "Corrupt truncate log inode#%"PRIu64", change tl_used" " from %u to %u\n", blkno, tl->tl_used, (tl->tl_count + 10)); tl->tl_used = tl->tl_count + 10; break; case TRUNCATE_REC_START_RANGE: tr = &tl->tl_recs[recnum]; fprintf(stdout, "TRUNCATE_REC_START_RANGE: " "Corrupt truncate log inode#%"PRIu64",rec#%d " "change t_start from %u to %u\n", blkno, recnum, tr->t_start, (fs->fs_clusters + 10)); tr->t_start = fs->fs_clusters + 10; break; case TRUNCATE_REC_WRAP: tr = &tl->tl_recs[recnum]; fprintf(stdout, "TRUNCATE_REC_WRAP: " "Corrupt truncate log inode#%"PRIu64",rec#%d " "change t_start from %u to 10000\n," "change t_clusters from %u to %u\n", blkno, recnum, tr->t_start,tr->t_clusters, (UINT32_MAX - 10)); tr->t_start = 10000; tr->t_clusters = UINT32_MAX - 10; break; case TRUNCATE_REC_RANGE: tr = &tl->tl_recs[recnum]; fprintf(stdout, "TRUNCATE_REC_RANGE: " "Corrupt truncate log inode#%"PRIu64",rec#%d " "change t_clusters from %u to %u\n", blkno, recnum, tr->t_clusters, (fs->fs_clusters + 10)); tr->t_clusters = fs->fs_clusters + 10; break; default: FSWRK_FATAL("Unknown type = %d", type); } ret = ocfs2_write_inode(fs, blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); bail: if (buf) ocfs2_free(&buf); return; }
static void mess_up_sys_file(ocfs2_filesys *fs, uint64_t blkno, enum fsck_type type) { errcode_t ret; char *buf = NULL, *bufgroup = NULL; struct ocfs2_dinode *di; struct ocfs2_chain_list *cl; struct ocfs2_chain_rec *cr; uint64_t oldblkno; struct ocfs2_group_desc *bg = NULL; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) FSWRK_COM_FATAL(progname, ret); ret = ocfs2_read_inode(fs, blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); di = (struct ocfs2_dinode *)buf; if (!(di->i_flags & OCFS2_BITMAP_FL)) FSWRK_COM_FATAL(progname, ret); if (!(di->i_flags & OCFS2_CHAIN_FL)) FSWRK_COM_FATAL(progname, ret); cl = &(di->id2.i_chain); /* for CHAIN_EMPTY, CHAIN_HEAD_LINK_RANGE, CHAIN_LINK_RANGE, * CHAIN_BITS, CHAIN_LINK_GEN, CHAIN_LINK_MAGIC, * we need to corrupt some chain rec, so check it first. */ if (type == CHAIN_EMPTY || type == CHAIN_HEAD_LINK_RANGE || type == CHAIN_LINK_RANGE || type == CHAIN_BITS || type == CHAIN_LINK_GEN || type == CHAIN_LINK_MAGIC) if (!cl->cl_next_free_rec) { FSWRK_WARN("No chain record found at block#%"PRIu64 ",so can't corrupt it for type[%d].\n", blkno, type); goto bail; } switch (type) { case CHAIN_COUNT: fprintf(stdout, "Corrupt CHAIN_COUNT: " "Modified cl_count " "in block#%"PRIu64" from %u to %u\n", blkno, cl->cl_count, (cl->cl_count + 100)); cl->cl_count += 100; break; case CHAIN_NEXT_FREE: fprintf(stdout, "Corrupt CHAIN_NEXT_FREE:" " Modified cl_next_free_rec " "in block#%"PRIu64" from %u to %u\n", blkno, cl->cl_next_free_rec, (cl->cl_count + 10)); cl->cl_next_free_rec = cl->cl_count + 10; break; case CHAIN_EMPTY: cr = cl->cl_recs; fprintf(stdout, "Corrupt CHAIN_EMPTY:" " Modified e_blkno " "in block#%"PRIu64" from %"PRIu64" to 0\n", blkno, (uint64_t)cr->c_blkno); cr->c_blkno = 0; break; case CHAIN_I_CLUSTERS: fprintf(stdout, "Corrupt CHAIN_I_CLUSTERS:" "change i_clusters in block#%"PRIu64" from %u to %u\n", blkno, di->i_clusters, (di->i_clusters + 10)); di->i_clusters += 10; break; case CHAIN_I_SIZE: fprintf(stdout, "Corrupt CHAIN_I_SIZE:" "change i_size " "in block#%"PRIu64" from %"PRIu64" to %"PRIu64"\n", blkno, (uint64_t)di->i_size, ((uint64_t)di->i_size + 10)); di->i_size += 10; break; case CHAIN_GROUP_BITS: fprintf(stdout, "Corrupt CHAIN_GROUP_BITS:" "change i_used of bitmap " "in block#%"PRIu64" from %u to %u\n", blkno, di->id1.bitmap1.i_used, (di->id1.bitmap1.i_used + 10)); di->id1.bitmap1.i_used += 10; break; case CHAIN_HEAD_LINK_RANGE: cr = cl->cl_recs; oldblkno = cr->c_blkno; cr->c_blkno = ocfs2_clusters_to_blocks(fs, fs->fs_clusters) + 10; fprintf(stdout, "Corrupt CHAIN_HEAD_LINK_RANGE:" "change " "in block#%"PRIu64" from %"PRIu64" to %"PRIu64"\n", blkno, oldblkno, (uint64_t)cr->c_blkno); break; case CHAIN_LINK_GEN: case CHAIN_LINK_MAGIC: case CHAIN_LINK_RANGE: ret = ocfs2_malloc_block(fs->fs_io, &bufgroup); if (ret) FSWRK_COM_FATAL(progname, ret); bg = (struct ocfs2_group_desc *)bufgroup; cr = cl->cl_recs; ret = ocfs2_read_group_desc(fs, cr->c_blkno, (char *)bg); if (ret) FSWRK_COM_FATAL(progname, ret); if (type == CHAIN_LINK_GEN) { fprintf(stdout, "Corrupt CHAIN_LINK_GEN: " "change generation num from %u to 0x1234\n", bg->bg_generation); bg->bg_generation = 0x1234; } else if (type == CHAIN_LINK_MAGIC) { fprintf(stdout, "Corrupt CHAIN_LINK_MAGIC: " "change signature to '1234'\n"); sprintf((char *)bg->bg_signature,"1234"); } else { oldblkno = bg->bg_next_group; bg->bg_next_group = ocfs2_clusters_to_blocks(fs, fs->fs_clusters) + 10; fprintf(stdout, "Corrupt CHAIN_LINK_RANGE: " "change next group from %"PRIu64" to %"PRIu64 " \n", oldblkno, (uint64_t)bg->bg_next_group); } ret = ocfs2_write_group_desc(fs, cr->c_blkno, (char *)bg); if (ret) FSWRK_COM_FATAL(progname, ret); break; case CHAIN_BITS: cr = cl->cl_recs; fprintf(stdout, "Corrupt CHAIN_BITS:" "change inode#%"PRIu64" c_total from %u to %u\n", blkno, cr->c_total, (cr->c_total + 10)); cr->c_total += 10; break; case CHAIN_CPG: fprintf(stdout, "Corrupt CHAIN_CPG: " "change cl_cpg of global_bitmap from %u to %u.\n", cl->cl_cpg, (cl->cl_cpg + 16)); cl->cl_cpg += 16; cl->cl_next_free_rec = 1; break; default: FSWRK_FATAL("Unknown fsck_type[%d]\n", type); } ret = ocfs2_write_inode(fs, blkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); bail: if (bufgroup) ocfs2_free(&bufgroup); if (buf) ocfs2_free(&buf); return ; }