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 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; }
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; }
errcode_t ocfs2_write_backup_super(ocfs2_filesys *fs, uint64_t blkno) { errcode_t ret; char *buf = NULL; struct ocfs2_dinode *di; if (!(fs->fs_flags & OCFS2_FLAG_RW)) return OCFS2_ET_RO_FILESYS; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) goto out_blk; memcpy(buf, (char *)fs->fs_super, fs->fs_blocksize); di = (struct ocfs2_dinode *)buf; ret = OCFS2_ET_BAD_MAGIC; if (memcmp(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE, strlen(OCFS2_SUPER_BLOCK_SIGNATURE))) goto out_blk; di->i_blkno = blkno; OCFS2_SET_COMPAT_FEATURE(OCFS2_RAW_SB(di), OCFS2_FEATURE_COMPAT_BACKUP_SB); ret = ocfs2_write_inode(fs, blkno, buf); if (ret) goto out_blk; ret = 0; out_blk: 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; }
/* * Emtpy the blocks on the disk. */ static errcode_t empty_blocks(ocfs2_filesys *fs, uint64_t start_blk, uint64_t num_blocks) { errcode_t ret; char *buf = NULL; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) goto bail; memset(buf, 0, fs->fs_blocksize); while (num_blocks) { ret = io_write_block(fs->fs_io, start_blk, 1, buf); if (ret) goto bail; num_blocks--; start_blk++; } bail: if (buf) ocfs2_free(&buf); return ret; }
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; }
void dump_dx_entries(FILE *out, struct ocfs2_dinode *inode) { struct ocfs2_dx_root_block *dx_root; uint64_t dx_blkno; char *buf = NULL; errcode_t ret = 0; if (ocfs2_malloc_block(gbls.fs->fs_io, &buf)) return; if (!(ocfs2_dir_indexed(inode))) return; dx_blkno = (uint64_t) inode->i_dx_root; ret = ocfs2_read_dx_root(gbls.fs, dx_blkno, buf); if (ret) return; dx_root = (struct ocfs2_dx_root_block *)buf; dump_dx_root(out, dx_root); ocfs2_dx_entries_iterate(gbls.fs, inode, 0, entries_iter, out); return; }
static errcode_t ocfs2_validate_ocfs1_header(ocfs2_filesys *fs) { errcode_t ret; char *blk; struct ocfs1_vol_disk_hdr *hdr; ret = ocfs2_malloc_block(fs->fs_io, &blk); if (ret) return ret; ret = ocfs2_read_blocks(fs, 0, 1, blk); if (ret) goto out; hdr = (struct ocfs1_vol_disk_hdr *)blk; ret = OCFS2_ET_OCFS_REV; if (le32_to_cpu(hdr->major_version) == OCFS1_MAJOR_VERSION) goto out; if (!memcmp(hdr->signature, OCFS1_VOLUME_SIGNATURE, strlen(OCFS1_VOLUME_SIGNATURE))) goto out; ret = 0; out: ocfs2_free(&blk); 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 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; }
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; }
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_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; }
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; }
errcode_t ocfs2_get_last_cluster_offset(ocfs2_filesys *fs, struct ocfs2_dinode *di, uint32_t *v_cluster) { errcode_t ret = 0; char *buf = NULL; struct ocfs2_extent_list *el = NULL; struct ocfs2_extent_rec *er = NULL; el = &di->id2.i_list; *v_cluster = 0; if (!el->l_next_free_rec) return 0; if (el->l_tree_depth) { ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) goto bail; ret = ocfs2_read_extent_block(fs, di->i_last_eb_blk, buf); if (ret) goto bail; el = &((struct ocfs2_extent_block *)buf)->h_list; if (!el->l_next_free_rec || (el->l_next_free_rec == 1 && ocfs2_is_empty_extent(&el->l_recs[0]))) { ret = OCFS2_ET_CORRUPT_EXTENT_BLOCK; goto bail; } } er = &el->l_recs[el->l_next_free_rec - 1]; *v_cluster = er->e_cpos + er->e_leaf_clusters - 1; bail: if (buf) ocfs2_free(&buf); return ret; }
errcode_t ocfs2_read_extent_block_nocheck(ocfs2_filesys *fs, uint64_t blkno, char *eb_buf) { errcode_t ret; char *blk; struct ocfs2_extent_block *eb; if ((blkno < OCFS2_SUPER_BLOCK_BLKNO) || (blkno > fs->fs_blocks)) return OCFS2_ET_BAD_BLKNO; ret = ocfs2_malloc_block(fs->fs_io, &blk); if (ret) return ret; ret = ocfs2_read_blocks(fs, blkno, 1, blk); if (ret) goto out; eb = (struct ocfs2_extent_block *)blk; ret = ocfs2_validate_meta_ecc(fs, blk, &eb->h_check); if (ret) goto out; if (memcmp(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE, strlen(OCFS2_EXTENT_BLOCK_SIGNATURE))) { ret = OCFS2_ET_BAD_EXTENT_BLOCK_MAGIC; goto out; } memcpy(eb_buf, blk, fs->fs_blocksize); eb = (struct ocfs2_extent_block *) eb_buf; ocfs2_swap_extent_block_to_cpu(fs, eb); out: ocfs2_free(&blk); return ret; }
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; }
errcode_t ocfs2_read_group_desc(ocfs2_filesys *fs, uint64_t blkno, char *gd_buf) { errcode_t ret; char *blk; struct ocfs2_group_desc *gd; if ((blkno < OCFS2_SUPER_BLOCK_BLKNO) || (blkno > fs->fs_blocks)) return OCFS2_ET_BAD_BLKNO; ret = ocfs2_malloc_block(fs->fs_io, &blk); if (ret) return ret; ret = ocfs2_read_blocks(fs, blkno, 1, blk); if (ret) goto out; gd = (struct ocfs2_group_desc *)blk; ret = ocfs2_validate_meta_ecc(fs, blk, &gd->bg_check); if (ret) goto out; ret = OCFS2_ET_BAD_GROUP_DESC_MAGIC; if (memcmp(gd->bg_signature, OCFS2_GROUP_DESC_SIGNATURE, strlen(OCFS2_GROUP_DESC_SIGNATURE))) goto out; memcpy(gd_buf, blk, fs->fs_blocksize); gd = (struct ocfs2_group_desc *)gd_buf; ocfs2_swap_group_desc_to_cpu(fs, gd); ret = 0; out: ocfs2_free(&blk); return ret; }
static errcode_t io_validate_o_direct(io_channel *channel) { errcode_t ret = OCFS2_ET_UNEXPECTED_BLOCK_SIZE; int block_size; char *blk; for (block_size = io_get_blksize(channel); block_size <= OCFS2_MAX_BLOCKSIZE; block_size <<= 1) { io_set_blksize(channel, block_size); ret = ocfs2_malloc_block(channel, &blk); if (ret) break; ret = unix_io_read_block(channel, 0, 1, blk); ocfs2_free(&blk); if (!ret) break; } return ret; }
/* * dump_xattr_block() * */ errcode_t dump_xattr_block(FILE *out, ocfs2_filesys *fs, struct ocfs2_dinode *in, uint32_t *xattrs_block, uint64_t *xattrs_bucket, int verbose) { errcode_t ret; char *blk = NULL; struct ocfs2_xattr_block *xb = NULL; ret = ocfs2_malloc_block(fs->fs_io, &blk); if (ret) goto out; ret = ocfs2_read_xattr_block(fs, in->i_xattr_loc, blk); if (ret) goto out; xb = (struct ocfs2_xattr_block *)blk; if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) { struct ocfs2_xattr_header *xh = &xb->xb_attrs.xb_header; *xattrs_block = xh->xh_count; fprintf(out, "\tExtended Attributes in block #%"PRIu64": %u\n", (uint64_t)in->i_xattr_loc, *xattrs_block); if (verbose) dump_xattr(out, xh); } else { ret = dump_xattr_index_block(out, fs, in, xb, xattrs_bucket, verbose); } out: if (blk) ocfs2_free(&blk); return ret; }
errcode_t ocfs2_write_extent_block(ocfs2_filesys *fs, uint64_t blkno, char *eb_buf) { errcode_t ret; char *blk; struct ocfs2_extent_block *eb; if (!(fs->fs_flags & OCFS2_FLAG_RW)) return OCFS2_ET_RO_FILESYS; if ((blkno < OCFS2_SUPER_BLOCK_BLKNO) || (blkno > fs->fs_blocks)) return OCFS2_ET_BAD_BLKNO; ret = ocfs2_malloc_block(fs->fs_io, &blk); if (ret) return ret; memcpy(blk, eb_buf, fs->fs_blocksize); eb = (struct ocfs2_extent_block *) blk; ocfs2_swap_extent_block_from_cpu(fs, eb); ocfs2_compute_meta_ecc(fs, blk, &eb->h_check); ret = io_write_block(fs->fs_io, blkno, 1, blk); if (ret) goto out; fs->fs_flags |= OCFS2_FLAG_CHANGED; ret = 0; out: ocfs2_free(&blk); return ret; }
errcode_t ocfs2_write_group_desc(ocfs2_filesys *fs, uint64_t blkno, char *gd_buf) { errcode_t ret; char *blk; struct ocfs2_group_desc *gd; if (!(fs->fs_flags & OCFS2_FLAG_RW)) return OCFS2_ET_RO_FILESYS; if ((blkno < OCFS2_SUPER_BLOCK_BLKNO) || (blkno > fs->fs_blocks)) return OCFS2_ET_BAD_BLKNO; ret = ocfs2_malloc_block(fs->fs_io, &blk); if (ret) return ret; memcpy(blk, gd_buf, fs->fs_blocksize); gd = (struct ocfs2_group_desc *)blk; ocfs2_swap_group_desc_from_cpu(fs, gd); ocfs2_compute_meta_ecc(fs, blk, &gd->bg_check); ret = io_write_block(fs->fs_io, blkno, 1, blk); if (ret) goto out; fs->fs_flags |= OCFS2_FLAG_CHANGED; ret = 0; out: ocfs2_free(&blk); return ret; }
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; }