errcode_t ocfs2_block_iterate(ocfs2_filesys *fs, uint64_t blkno, int flags, int (*func)(ocfs2_filesys *fs, uint64_t blkno, uint64_t bcount, uint16_t ext_flags, void *priv_data), void *priv_data) { struct ocfs2_dinode *inode; errcode_t ret; char *buf; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) return ret; ret = ocfs2_read_inode(fs, blkno, buf); if (ret) goto out_buf; inode = (struct ocfs2_dinode *)buf; ret = ocfs2_block_iterate_inode(fs, inode, flags, func, priv_data); out_buf: ocfs2_free(&buf); return ret; }
errcode_t o2fsck_type_from_dinode(o2fsck_state *ost, uint64_t ino, uint8_t *type) { char *buf = NULL; errcode_t ret; struct ocfs2_dinode *dinode; const char *whoami = __FUNCTION__; *type = 0; ret = ocfs2_malloc_block(ost->ost_fs->fs_io, &buf); if (ret) { com_err(whoami, ret, "while allocating an inode buffer to " "read and discover the type of inode %"PRIu64, ino); goto out; } ret = ocfs2_read_inode(ost->ost_fs, ino, buf); if (ret) { com_err(whoami, ret, "while reading inode %"PRIu64" to " "discover its file type", ino); goto out; } dinode = (struct ocfs2_dinode *)buf; *type = ocfs2_type_by_mode[(dinode->i_mode & S_IFMT)>>S_SHIFT]; out: if (buf) ocfs2_free(&buf); return ret; }
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; }
errcode_t ocfs2_extend_file(ocfs2_filesys *fs, uint64_t ino, uint64_t new_size) { errcode_t ret = 0; char *buf = NULL; struct ocfs2_dinode* di = NULL; if (!(fs->fs_flags & OCFS2_FLAG_RW)) return OCFS2_ET_RO_FILESYS; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) return ret; ret = ocfs2_read_inode(fs, ino, buf); if (ret) goto out_free_buf; di = (struct ocfs2_dinode *)buf; if (di->i_size >= new_size) { ret = EINVAL; goto out_free_buf; } di->i_size = new_size; ret = ocfs2_write_inode(fs, ino, buf); out_free_buf: if (buf) ocfs2_free(&buf); return ret; }
/* * dump_dir_entry() * */ int dump_dir_entry(struct ocfs2_dir_entry *rec, uint64_t blocknr, int offset, int blocksize, char *buf, void *priv_data) { struct list_dir_opts *ls = (struct list_dir_opts *)priv_data; char tmp = rec->name[rec->name_len]; struct ocfs2_dinode *di; char perms[20]; char timestr[40]; rec->name[rec->name_len] = '\0'; if (!ls->long_opt) { fprintf(ls->out, "\t%-15"PRIu64" %-4u %-4u %-2u %s\n", (uint64_t)rec->inode, rec->rec_len, rec->name_len, rec->file_type, rec->name); } else { memset(ls->buf, 0, ls->fs->fs_blocksize); ocfs2_read_inode(ls->fs, rec->inode, ls->buf); di = (struct ocfs2_dinode *)ls->buf; inode_perms_to_str(di->i_mode, perms, sizeof(perms)); inode_time_to_str(di->i_mtime, timestr, sizeof(timestr)); fprintf(ls->out, "\t%-15"PRIu64" %10s %3u %5u %5u %15"PRIu64" %s %s\n", (uint64_t)rec->inode, perms, di->i_links_count, di->i_uid, di->i_gid, (uint64_t)di->i_size, timestr, rec->name); } rec->name[rec->name_len] = tmp; return 0; }
errcode_t ocfs2_extent_iterate(ocfs2_filesys *fs, uint64_t blkno, int flags, char *block_buf, int (*func)(ocfs2_filesys *fs, struct ocfs2_extent_rec *rec, int tree_depth, uint32_t ccount, uint64_t ref_blkno, int ref_recno, void *priv_data), void *priv_data) { char *buf = NULL; struct ocfs2_dinode *inode; errcode_t ret; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) return ret; ret = ocfs2_read_inode(fs, blkno, buf); if (ret) goto out_buf; inode = (struct ocfs2_dinode *)buf; ret = ocfs2_extent_iterate_inode(fs, inode, flags, block_buf, func, priv_data); out_buf: if (buf) ocfs2_free(&buf); return ret; }
static errcode_t create_local_alloc(ocfs2_filesys *fs, uint16_t slot) { errcode_t ret; char *buf = NULL; struct ocfs2_dinode *di; struct ocfs2_local_alloc *la; uint32_t la_size, found; uint64_t la_off, blkno; ret = ocfs2_lookup_system_inode(fs, LOCAL_ALLOC_SYSTEM_INODE, slot, &blkno); if (ret) goto bail; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) goto bail; ret = ocfs2_read_inode(fs, blkno, buf); if (ret) goto bail; di = (struct ocfs2_dinode *)buf; if (!(di->i_flags & OCFS2_VALID_FL)) goto bail; if (!(di->i_flags & OCFS2_LOCAL_ALLOC_FL)) goto bail; if (di->id1.bitmap1.i_total > 0) { fprintf(stderr, "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) goto bail; if(la_size != found) goto bail; la = &(di->id2.i_lab); la->la_bm_off = ocfs2_blocks_to_clusters(fs, 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); bail: if(buf) ocfs2_free(&buf); return ret; }
errcode_t ocfs2_chain_iterate(ocfs2_filesys *fs, uint64_t blkno, int (*func)(ocfs2_filesys *fs, uint64_t gd_blkno, int chain_num, void *priv_data), void *priv_data) { int iret = 0; char *buf; struct ocfs2_dinode *inode; errcode_t ret; struct chain_context ctxt; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) return ret; ret = ocfs2_read_inode(fs, blkno, buf); if (ret) goto out_buf; inode = (struct ocfs2_dinode *)buf; ret = OCFS2_ET_INODE_NOT_VALID; if (!(inode->i_flags & OCFS2_VALID_FL)) goto out_buf; ret = OCFS2_ET_INODE_CANNOT_BE_ITERATED; if (!(inode->i_flags & OCFS2_CHAIN_FL)) goto out_buf; ret = ocfs2_malloc0(fs->fs_blocksize, &ctxt.gd_buf); if (ret) goto out_gd_buf; ctxt.fs = fs; ctxt.func = func; ctxt.priv_data = priv_data; ret = 0; iret |= chain_iterate_cl(&inode->id2.i_chain, &ctxt); if (iret & OCFS2_EXTENT_ERROR) ret = ctxt.errcode; if (iret & OCFS2_EXTENT_CHANGED) { /* Do something */ } out_gd_buf: if (ctxt.gd_buf) ocfs2_free(&ctxt.gd_buf); out_buf: ocfs2_free(&buf); return ret; }
static errcode_t truncate_log_check(ocfs2_filesys *fs, uint16_t new_slots) { errcode_t ret = 0; uint16_t i; uint64_t blkno; char *buf = NULL; struct ocfs2_dinode *di = NULL; uint16_t max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) { verbosef(VL_APP, "%s while allocating inode buffer for " "truncate log check\n", error_message(ret)); goto bail; } for (i = new_slots; i < max_slots; ++i) { ret = ocfs2_lookup_system_inode(fs, TRUNCATE_LOG_SYSTEM_INODE, i, &blkno); if (ret) { verbosef(VL_APP, "%s while looking up truncate log for " "slot %u during truncate log check\n", error_message(ret), i); goto bail; } ret = ocfs2_read_inode(fs, blkno, buf); if (ret) { verbosef(VL_APP, "%s while reading inode %"PRIu64" " "during truncate log check\n", error_message(ret), blkno); goto bail; } di = (struct ocfs2_dinode *)buf; if (di->id2.i_dealloc.tl_used > 0) { ret = TUNEFS_ET_TRUNCATE_LOG_NOT_EMPTY; verbosef(VL_APP, "Truncate log for slot %u is not empty\n", i); goto bail; } } bail: if (buf) ocfs2_free(&buf); return ret; }
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 errcode_t local_alloc_check(ocfs2_filesys *fs, uint16_t new_slots) { errcode_t ret = 0; uint16_t i; uint64_t blkno; char *buf = NULL; struct ocfs2_dinode *di = NULL; uint16_t max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) { verbosef(VL_APP, "%s while allocating inode buffer for local " "alloc check\n", error_message(ret)); goto bail; } for (i = new_slots ; i < max_slots; ++i) { ret = ocfs2_lookup_system_inode(fs, LOCAL_ALLOC_SYSTEM_INODE, i, &blkno); if (ret) { verbosef(VL_APP, "%s while looking up local alloc for " "slot %u during local alloc check\n", error_message(ret), i); break; } ret = ocfs2_read_inode(fs, blkno, buf); if (ret) { verbosef(VL_APP, "%s while reading inode %"PRIu64" " "during local alloc check\n", error_message(ret), blkno); break; } di = (struct ocfs2_dinode *)buf; if (di->id1.bitmap1.i_total > 0) { ret = TUNEFS_ET_LOCAL_ALLOC_NOT_EMPTY; verbosef(VL_APP, "Local alloc for slot %u is not empty\n", i); break; } } bail: if (buf) ocfs2_free(&buf); return ret; }
int is_dir_inlined(char *dirent_name, unsigned long *i_size, unsigned int *id_count) { int ret; uint64_t workplace_blk_no = 1; uint64_t testdir_blk_no = 1; char *buf = NULL; struct ocfs2_dinode *di; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); sync(); ocfs2_malloc_block(fs->fs_io, &buf); /*lookup worksplace inode*/ ret = ocfs2_lookup(fs, sb->s_root_blkno, WORK_PLACE, strlen(WORK_PLACE), NULL, &workplace_blk_no); if (ret < 0) { fprintf(stderr, "failed to lookup work_place(%s)'s" " inode blkno\n", work_place); ocfs2_free(&buf); exit(ret); } /*lookup file inode,then read*/ ret = ocfs2_lookup(fs, workplace_blk_no, dirent_name, strlen(dirent_name), NULL, &testdir_blk_no); if (ret < 0) { fprintf(stderr, "failed to lookup file(%s/%s)'s" " inode blkno\n", work_place, dirent_name); ocfs2_free(&buf); exit(ret); } ret = ocfs2_read_inode(fs, testdir_blk_no, buf); if (ret < 0) { fprintf(stderr, "failed to read file(%s/%s/%s)'s" " inode.\n", mount_point, WORK_PLACE, dirent_name); ocfs2_free(&buf); exit(ret); } di = (struct ocfs2_dinode *)buf; *i_size = di->i_size; *id_count = ((di->id2).i_data).id_count; if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) ret = 1; else ret = 0; ocfs2_free(&buf); return ret; }
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; }
/* * NOTE: ocfs2_truncate_inline() also handles fast symlink, * since truncating for inline file and fasy symlink are * almost the same thing per se. */ errcode_t ocfs2_truncate_inline(ocfs2_filesys *fs, uint64_t ino, uint64_t new_i_size) { errcode_t ret = 0; char *buf = NULL; struct ocfs2_dinode *di = NULL; struct ocfs2_inline_data *idata = NULL; if (!(fs->fs_flags & OCFS2_FLAG_RW)) return OCFS2_ET_RO_FILESYS; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) return ret; ret = ocfs2_read_inode(fs, ino, buf); if (ret) goto out_free_buf; di = (struct ocfs2_dinode *)buf; if (di->i_size < new_i_size) { ret = EINVAL; goto out_free_buf; } idata = &di->id2.i_data; if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL) && !(S_ISLNK(di->i_mode) && !di->i_clusters)) { ret = EINVAL; goto out_free_buf; } if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) memset(idata->id_data + new_i_size, 0, di->i_size - new_i_size); else memset(di->id2.i_symlink + new_i_size, 0, di->i_size - new_i_size); di->i_size = new_i_size; ret = ocfs2_write_inode(fs, ino, buf); out_free_buf: if (buf) ocfs2_free(&buf); return ret; }
/* this could certainly be more clever to issue reads in groups */ static unsigned pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe, void *priv_data) { struct dirblock_data *dd = priv_data; struct ocfs2_dir_entry *dirent, *prev = NULL; unsigned int offset = 0, ret_flags = 0, end = dd->fs->fs_blocksize; struct ocfs2_dinode *di = (struct ocfs2_dinode *)dd->inoblock_buf; errcode_t ret = 0; if (!o2fsck_test_inode_allocated(dd->ost, dbe->e_ino)) { printf("Directory block %"PRIu64" belongs to directory inode " "%"PRIu64" which isn't allocated. Ignoring this " "block.", dbe->e_blkno, dbe->e_ino); goto out; } if (dbe->e_ino != dd->last_ino) { o2fsck_strings_free(&dd->strings); dd->last_ino = dbe->e_ino; ret = ocfs2_read_inode(dd->ost->ost_fs, dbe->e_ino, dd->inoblock_buf); if (ret) { com_err(whoami, ret, "while reading dir inode %"PRIu64, dbe->e_ino); ret_flags |= OCFS2_DIRENT_ABORT; goto out; } verbosef("dir inode %"PRIu64" i_size %"PRIu64"\n", dbe->e_ino, (uint64_t)di->i_size); } verbosef("dir block %"PRIu64" block offs %"PRIu64" in ino\n", dbe->e_blkno, dbe->e_blkcount); if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) { if (dbe->e_ino != dbe->e_blkno) goto out; memcpy(dd->dirblock_buf, dd->inoblock_buf, dd->fs->fs_blocksize); offset = offsetof(struct ocfs2_dinode, id2.i_data.id_data); } else { if (dbe->e_blkcount >= ocfs2_blocks_in_bytes(dd->fs,
static errcode_t remove_slot_entry(ocfs2_filesys *fs, uint16_t removed_slot) { struct remove_slot_ctxt ctxt = { .fs = fs, .removed_slot = removed_slot, .errcode = 0 }; ocfs2_dir_iterate(fs, fs->fs_sysdir_blkno, OCFS2_DIRENT_FLAG_EXCLUDE_DOTS, NULL, remove_slot_iterate, &ctxt); return ctxt.errcode; } static errcode_t decrease_link_count(ocfs2_filesys *fs, uint16_t blkno) { errcode_t ret; char *buf = NULL; struct ocfs2_dinode *di = NULL; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) goto bail; ret = ocfs2_read_inode(fs, blkno, buf); if (ret) goto bail; di = (struct ocfs2_dinode *)buf; if (di->i_links_count > 0) di->i_links_count--; else { ret = OCFS2_ET_INODE_NOT_VALID; goto bail; } ret = ocfs2_write_inode(fs, blkno, buf); bail: if (buf) ocfs2_free(&buf); return ret; }
errcode_t handle_slots_system_file(ocfs2_filesys *fs, int type, errcode_t (*func)(ocfs2_filesys *fs, struct ocfs2_dinode *di, int slot)) { errcode_t ret; uint64_t blkno; int slot, max_slots; char *buf = NULL; struct ocfs2_dinode *di; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) goto bail; di = (struct ocfs2_dinode *)buf; max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots; for (slot = 0; slot < max_slots; slot++) { ret = ocfs2_lookup_system_inode(fs, type, slot, &blkno); if (ret) goto bail; ret = ocfs2_read_inode(fs, blkno, buf); if (ret) goto bail; if (func) { ret = func(fs, di, slot); if (ret) goto bail; } } bail: if (buf) ocfs2_free(&buf); return ret; }
static errcode_t change_sub_alloc_slot(ocfs2_filesys *fs, uint64_t blkno, struct relink_ctxt *ctxt) { errcode_t ret; struct ocfs2_dinode *di = NULL; struct ocfs2_extent_block *eb = NULL; if (ctxt->inode_type == EXTENT_ALLOC_SYSTEM_INODE) { /* change sub alloc bit in the extent block. */ ret = ocfs2_read_extent_block(fs, blkno, ctxt->ex_buf); if (ret) goto bail; eb = (struct ocfs2_extent_block *)ctxt->ex_buf; eb->h_suballoc_slot = ctxt->new_slot; ret = ocfs2_write_extent_block(fs, blkno, ctxt->ex_buf); if (ret) goto bail; } else { /* change sub alloc bit in the inode. */ ret = ocfs2_read_inode(fs, blkno, ctxt->ex_buf); if (ret) goto bail; di = (struct ocfs2_dinode *)ctxt->ex_buf; di->i_suballoc_slot = ctxt->new_slot; ret = ocfs2_write_inode(fs, blkno, ctxt->ex_buf); if (ret) goto bail; } bail: return ret; }
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; }
int main(int argc, char *argv[]) { errcode_t ret; uint64_t blkno; int c; char *filename, *buf; ocfs2_filesys *fs; struct ocfs2_dinode *di; struct walk_it wi; blkno = OCFS2_SUPER_BLOCK_BLKNO; initialize_ocfs_error_table(); while ((c = getopt(argc, argv, "bei:")) != EOF) { switch (c) { case 'i': blkno = read_number(optarg); if (blkno <= OCFS2_SUPER_BLOCK_BLKNO) { fprintf(stderr, "Invalid inode block: %s\n", optarg); print_usage(); return 1; } break; default: print_usage(); return 1; break; } } if (blkno == OCFS2_SUPER_BLOCK_BLKNO) { fprintf(stderr, "You must specify an inode block\n"); print_usage(); return 1; } if (optind >= argc) { fprintf(stderr, "Missing filename\n"); print_usage(); return 1; } filename = argv[optind]; ret = ocfs2_open(filename, OCFS2_FLAG_RO, 0, 0, &fs); if (ret) { com_err(argv[0], ret, "while opening file \"%s\"", filename); goto out; } ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) { com_err(argv[0], ret, "while allocating inode buffer"); goto out_close; } memset(&wi, 0, sizeof(wi)); ret = ocfs2_read_inode(fs, blkno, buf); if (ret) { com_err(argv[0], ret, "while reading inode %"PRIu64, blkno); goto out_free; } di = (struct ocfs2_dinode *)buf; fprintf(stdout, "OCFS2 inode %"PRIu64" on \"%s\"\n", blkno, filename); ret = ocfs2_malloc_block(fs->fs_io, &wi.gd_buf); if (ret) { com_err(argv[0], ret, "while allocating gd buffer"); goto out_free; } wi.di = di; wi.last_chain = -1; ret = ocfs2_chain_iterate(fs, blkno, walk_chain_func, &wi); if (ret) { com_err(argv[0], ret, "while walking extents"); } out_free: if (wi.gd_buf) ocfs2_free(&wi.gd_buf); ocfs2_free(&buf); out_close: ret = ocfs2_close(fs); if (ret) { com_err(argv[0], ret, "while closing file \"%s\"", filename); } out: return 0; }
errcode_t ocfs2_fill_heartbeat_desc(ocfs2_filesys *fs, struct o2cb_region_desc *desc) { errcode_t ret; char *filename; char *buf = NULL; uint64_t blkno, blocks, start_block; uint32_t block_bits, cluster_bits; int sectsize, sectsize_bits; struct ocfs2_dinode *di; struct ocfs2_extent_rec *rec; ret = ocfs2_get_device_sectsize(fs->fs_devname, §size); if (ret) { if (ret == OCFS2_ET_CANNOT_DETERMINE_SECTOR_SIZE) sectsize = OCFS2_MIN_BLOCKSIZE; else goto leave; } sectsize_bits = ffs(sectsize) - 1; filename = ocfs2_system_inodes[HEARTBEAT_SYSTEM_INODE].si_name; ret = ocfs2_lookup(fs, fs->fs_sysdir_blkno, filename, strlen(filename), NULL, &blkno); if (ret) goto leave; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) goto leave; ret = ocfs2_read_inode(fs, blkno, buf); if (ret) goto leave; di = (struct ocfs2_dinode *)buf; if (di->id2.i_list.l_tree_depth || di->id2.i_list.l_next_free_rec != 1) { ret = OCFS2_ET_BAD_HEARTBEAT_FILE; goto leave; } rec = &(di->id2.i_list.l_recs[0]); block_bits = OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits; cluster_bits = OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits; if (block_bits < sectsize_bits) { ret = OCFS2_ET_BLOCK_SIZE_TOO_SMALL_FOR_HARDWARE; goto leave; } blocks = ocfs2_rec_clusters(0, rec) << cluster_bits; blocks >>= block_bits; if (blocks > O2NM_MAX_NODES) blocks = O2NM_MAX_NODES; start_block = rec->e_blkno << block_bits; start_block >>= sectsize_bits; desc->r_name = fs->uuid_str; desc->r_device_name = fs->fs_devname; desc->r_block_bytes = sectsize; desc->r_start_block = start_block; desc->r_blocks = blocks; leave: if (buf) ocfs2_free(&buf); return ret; }
int main(int argc, char *argv[]) { errcode_t ret; uint64_t blkno, sys_blkno; int c; char *filename, *buf; const char *bitmap_name = ocfs2_system_inodes[GLOBAL_BITMAP_SYSTEM_INODE].si_name; ocfs2_filesys *fs; struct ocfs2_dinode *di; struct walk_block wb; blkno = OCFS2_SUPER_BLOCK_BLKNO; initialize_ocfs_error_table(); while ((c = getopt(argc, argv, "i:")) != EOF) { switch (c) { case 'i': blkno = read_number(optarg); if (blkno <= OCFS2_SUPER_BLOCK_BLKNO) { fprintf(stderr, "Invalid inode block: %s\n", optarg); print_usage(); return 1; } break; default: print_usage(); return 1; break; } } if (optind >= argc) { fprintf(stderr, "Missing filename\n"); print_usage(); return 1; } filename = argv[optind]; ret = ocfs2_open(filename, OCFS2_FLAG_RW, 0, 0, &fs); if (ret) { com_err(argv[0], ret, "while opening file \"%s\"", filename); goto out; } if (blkno == OCFS2_SUPER_BLOCK_BLKNO) { sys_blkno = OCFS2_RAW_SB(fs->fs_super)->s_system_dir_blkno; ret = ocfs2_lookup(fs, sys_blkno, bitmap_name, strlen(bitmap_name), NULL, &blkno); if (ret) { com_err(argv[0], ret, "while looking up \"%s\"", bitmap_name); goto out; } } ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) { com_err(argv[0], ret, "while allocating inode buffer"); goto out_close; } memset(&wb, 0, sizeof(wb)); ret = ocfs2_read_inode(fs, blkno, buf); if (ret) { com_err(argv[0], ret, "while reading inode %"PRIu64, blkno); goto out_free; } di = (struct ocfs2_dinode *)buf; wb.di = di; ret = ocfs2_malloc_block(fs->fs_io, &wb.buf); if (ret) { com_err(argv[0], ret, "while allocating block buffer"); goto out_free; } ret = ocfs2_block_iterate(fs, blkno, 0, walk_blocks_func, &wb); if (ret) { com_err(argv[0], ret, "while walking blocks"); goto out_free; } di->id1.bitmap1.i_used = wb.used; ret = ocfs2_write_inode(fs, blkno, buf); if (ret) { com_err(argv[0], ret, "while reading inode %"PRIu64, blkno); goto out_free; } out_free: if (wb.buf) ocfs2_free(&wb.buf); ocfs2_free(&buf); out_close: ret = ocfs2_close(fs); if (ret) { com_err(argv[0], ret, "while closing file \"%s\"", filename); } out: return 0; }
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; }
/* this could certainly be more clever to issue reads in groups */ static unsigned pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe, void *priv_data) { struct dirblock_data *dd = priv_data; struct ocfs2_dir_entry *dirent, *prev = NULL; unsigned int offset = 0, ret_flags = 0, end = dd->fs->fs_blocksize; unsigned int write_off, saved_reclen; struct ocfs2_dinode *di = (struct ocfs2_dinode *)dd->inoblock_buf; errcode_t ret = 0; if (!o2fsck_test_inode_allocated(dd->ost, dbe->e_ino)) { printf("Directory block %"PRIu64" belongs to directory inode " "%"PRIu64" which isn't allocated. Ignoring this " "block.", dbe->e_blkno, dbe->e_ino); goto out; } if (dbe->e_ino != dd->last_ino) { o2fsck_strings_free(&dd->strings); dd->last_ino = dbe->e_ino; ret = ocfs2_read_inode(dd->ost->ost_fs, dbe->e_ino, dd->inoblock_buf); if (ret == OCFS2_ET_BAD_CRC32) { if (prompt(dd->ost, PY, PR_BAD_CRC32, "Directory inode %"PRIu64" " "has bad CRC32. Recalculate CRC32 " "and write inode block?", dbe->e_ino)) { ocfs2_write_inode(dd->ost->ost_fs, dbe->e_ino, dd->inoblock_buf); } } else if (ret) { com_err(whoami, ret, "while reading dir inode %"PRIu64, dbe->e_ino); ret_flags |= OCFS2_DIRENT_ABORT; goto out; } verbosef("dir inode %"PRIu64" i_size %"PRIu64"\n", dbe->e_ino, (uint64_t)di->i_size); /* Set the flag for index rebuilding */ if (ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(dd->fs->fs_super)) && !(di->i_dyn_features & OCFS2_INLINE_DATA_FL) && !(di->i_dyn_features & OCFS2_INDEXED_DIR_FL) && prompt(dd->ost, PY, PR_DX_TREE_MISSING, "Directory %"PRIu64" is missing index. " "Rebuild?", dbe->e_ino)) ret_flags |= OCFS2_DIRENT_CHANGED; } verbosef("dir block %"PRIu64" block offs %"PRIu64" in ino\n", dbe->e_blkno, dbe->e_blkcount); if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) { if (dbe->e_ino != dbe->e_blkno) goto out; memcpy(dd->dirblock_buf, dd->inoblock_buf, dd->fs->fs_blocksize); offset = offsetof(struct ocfs2_dinode, id2.i_data.id_data); } else { if (dbe->e_blkcount >= ocfs2_blocks_in_bytes(dd->fs,
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_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 errcode_t create_truncate_log(ocfs2_filesys *fs, uint16_t slot) { errcode_t ret; char *buf = NULL; struct ocfs2_dinode *di; struct ocfs2_truncate_log *tl; uint16_t i, used = 10; uint32_t found, clusters = 10; uint64_t begin, blkno; ret = ocfs2_lookup_system_inode(fs, TRUNCATE_LOG_SYSTEM_INODE, slot, &blkno); if (ret) goto bail; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) goto bail; ret = ocfs2_read_inode(fs, blkno, buf); if (ret) goto bail; di = (struct ocfs2_dinode *)buf; if (!(di->i_flags & OCFS2_VALID_FL)) { fprintf(stderr,"not a valid file\n"); goto bail; } if (!(di->i_flags & OCFS2_DEALLOC_FL)) { fprintf(stderr,"not a valid truncate log\n"); goto bail; } tl = &di->id2.i_dealloc; if (le16_to_cpu(tl->tl_used) > 0) { fprintf(stderr,"truncate log#%"PRIu64" file not empty." "Can't create a new one.\n", blkno); goto bail; } tl->tl_used = used; for (i = 0; i < tl->tl_used; i++) { ret = ocfs2_new_clusters(fs, 1, clusters, &begin, &found); if (ret) goto bail; tl->tl_recs[i].t_start = ocfs2_blocks_to_clusters(fs, begin); tl->tl_recs[i].t_clusters = found; } ret = ocfs2_write_inode(fs, blkno, buf); bail: if(buf) ocfs2_free(&buf); return ret; }