void mess_up_inode_alloc(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) { errcode_t ret; uint64_t tmpblkno; char *buf = NULL; struct ocfs2_dinode *di; ret = ocfs2_new_inode(fs, &tmpblkno, S_IFREG | 0755); if (ret) FSWRK_COM_FATAL(progname, ret); 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_flags &= ~OCFS2_VALID_FL; ret = ocfs2_write_inode(fs, tmpblkno, buf); if (ret) FSWRK_COM_FATAL(progname, ret); fprintf(stdout, "INODE_ALLOC_REPAIR: " "Create an inode#%"PRIu64" and invalidate it.\n", tmpblkno); if (buf) ocfs2_free(&buf); return; }
static void create_named_directory(ocfs2_filesys *fs, char *dirname, uint64_t *blkno) { errcode_t ret; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); ret = ocfs2_lookup(fs, sb->s_root_blkno, dirname, strlen(dirname), NULL, blkno); if (!ret) return; else if (ret != OCFS2_ET_FILE_NOT_FOUND) FSWRK_COM_FATAL(progname, ret); ret = ocfs2_new_inode(fs, blkno, S_IFDIR | 0755); if (ret) FSWRK_COM_FATAL(progname, ret); ret = ocfs2_init_dir(fs, *blkno, fs->fs_root_blkno); if (ret) FSWRK_COM_FATAL(progname, ret); ret = ocfs2_link(fs, fs->fs_root_blkno, dirname, *blkno, OCFS2_FT_DIR); if (ret) FSWRK_COM_FATAL(progname, ret); return; }
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 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 mess_up_local_alloc_used(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) { errcode_t ret; uint64_t blkno; char alloc_inode[OCFS2_MAX_FILENAME_LEN]; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); if (slotnum == UINT16_MAX) slotnum = 0; snprintf(alloc_inode, sizeof(alloc_inode), ocfs2_system_inodes[LOCAL_ALLOC_SYSTEM_INODE].si_name,slotnum); ret = ocfs2_lookup(fs, sb->s_system_dir_blkno, alloc_inode, strlen(alloc_inode), NULL, &blkno); if (ret) FSWRK_COM_FATAL(progname, ret); create_local_alloc(fs, blkno); damage_local_alloc(fs, blkno, type); return; }
void mess_up_inode_orphaned(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) { errcode_t ret; uint64_t blkno, tmpblkno; char parentdir[OCFS2_MAX_FILENAME_LEN]; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); if (slotnum == UINT16_MAX) slotnum = 0; snprintf(parentdir, sizeof(parentdir), ocfs2_system_inodes[ORPHAN_DIR_SYSTEM_INODE].si_name, slotnum); ret = ocfs2_lookup(fs, sb->s_system_dir_blkno, parentdir, strlen(parentdir), NULL, &blkno); if (ret) FSWRK_COM_FATAL(progname, ret); create_file(fs, blkno, &tmpblkno); fprintf(stdout, "INODE_ORPHANED: " "Create an inode#%"PRIu64" under directory %s\n", tmpblkno, parentdir); return; }
static void mess_up_sys_chains(ocfs2_filesys *fs, uint16_t slotnum, enum fsck_type type) { errcode_t ret; char sysfile[OCFS2_MAX_FILENAME_LEN]; uint64_t blkno; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); if (slotnum == UINT16_MAX) snprintf(sysfile, sizeof(sysfile), "%s", ocfs2_system_inodes[GLOBAL_BITMAP_SYSTEM_INODE].si_name); else snprintf(sysfile, sizeof(sysfile), ocfs2_system_inodes[INODE_ALLOC_SYSTEM_INODE].si_name, slotnum); ret = ocfs2_lookup(fs, sb->s_system_dir_blkno, sysfile, strlen(sysfile), NULL, &blkno); if (ret) FSWRK_COM_FATAL(progname, ret); mess_up_sys_file(fs, blkno, type); return ; }
static void mess_up_superblock_clusters(ocfs2_filesys *fs, int excess) { errcode_t ret; char *buf = NULL; struct ocfs2_dinode *di = fs->fs_super; uint32_t new_clusters, cpg, wrong; /* corrupt superblock, just copy the * superblock, change it and * write it back to disk. */ ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) FSWRK_COM_FATAL(progname, ret); memcpy(buf, (char *)di, fs->fs_blocksize); di = (struct ocfs2_dinode *)buf; cpg = 8 * ocfs2_group_bitmap_size(fs->fs_blocksize, 0, OCFS2_RAW_SB(fs->fs_super)->s_feature_incompat); /* make the wrong value to 2.5 times of cluster_per_group. */ wrong = cpg * 2 + cpg / 2; if (excess) new_clusters = di->i_clusters + wrong; else new_clusters = di->i_clusters - wrong; fprintf(stdout, "Corrupt SUPERBLOCK_CLUSTERS: " "change superblock i_clusters from %u to %u.\n", di->i_clusters, new_clusters); di->i_clusters = new_clusters; ret = io_write_block(fs->fs_io, di->i_blkno, 1, buf); if (ret) FSWRK_COM_FATAL(progname, ret); if(buf) ocfs2_free(&buf); return; }
void mess_up_inode_not_connected(ocfs2_filesys *fs, enum fsck_type type, uint64_t blkno) { errcode_t ret; uint64_t tmpblkno; ret = ocfs2_new_inode(fs, &tmpblkno, S_IFREG | 0755); if (ret) FSWRK_COM_FATAL(progname, ret); fprintf(stdout, "INODE_NOT_CONNECTED: " "Create an inode#%"PRIu64" which has no links\n", tmpblkno); return ; }
static void get_truncate_log(ocfs2_filesys *fs, uint16_t slotnum, uint64_t *blkno) { errcode_t ret; char truncate_log[OCFS2_MAX_FILENAME_LEN]; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); if (slotnum == UINT16_MAX) slotnum = 0; snprintf(truncate_log, sizeof(truncate_log), ocfs2_system_inodes[TRUNCATE_LOG_SYSTEM_INODE].si_name, slotnum); ret = ocfs2_lookup(fs, sb->s_system_dir_blkno, truncate_log, strlen(truncate_log), NULL, blkno); if (ret) FSWRK_COM_FATAL(progname, ret); 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 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_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; }
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 ; }
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; }