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; }
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_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 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 ; }