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; }
static int ocfs2_truncate_clusters(ocfs2_filesys *fs, struct ocfs2_extent_rec *rec, uint64_t ino, uint32_t len, uint64_t start) { if (!ocfs2_refcount_tree(OCFS2_RAW_SB(fs->fs_super)) || !(rec->e_flags & OCFS2_EXT_REFCOUNTED)) return ocfs2_free_clusters(fs, len, start); assert(ino); return ocfs2_decrease_refcount(fs, ino, ocfs2_blocks_to_clusters(fs, start), len, 1); }
static errcode_t ocfs2_file_block_write(ocfs2_cached_inode *ci, void *buf, uint32_t count, uint64_t offset, uint32_t *wrote) { ocfs2_filesys *fs = ci->ci_fs; errcode_t ret = 0; char *ptr = (char *) buf; uint32_t wanted_blocks; uint64_t contig_blocks; uint64_t v_blkno; uint64_t p_blkno, p_start, p_end; uint64_t begin_blocks = 0, end_blocks = 0; uint32_t tmp; uint64_t num_blocks; int bs_bits = OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits; uint32_t n_clusters, cluster_begin, cluster_end; uint64_t bpc = fs->fs_clustersize/fs->fs_blocksize; int insert = 0; uint16_t extent_flags = 0; /* o_direct requires aligned io */ tmp = fs->fs_blocksize - 1; if ((count & tmp) || (offset & (uint64_t)tmp) || ((unsigned long)ptr & tmp)) return OCFS2_ET_INVALID_ARGUMENT; wanted_blocks = count >> bs_bits; v_blkno = offset >> bs_bits; *wrote = 0; num_blocks = (ci->ci_inode->i_size + fs->fs_blocksize - 1) >> bs_bits; if (v_blkno >= num_blocks) return 0; if (v_blkno + wanted_blocks > num_blocks) wanted_blocks = (uint32_t) (num_blocks - v_blkno); if (ocfs2_refcount_tree(OCFS2_RAW_SB(fs->fs_super)) && (ci->ci_inode->i_dyn_features & OCFS2_HAS_REFCOUNT_FL)) { cluster_begin = ocfs2_blocks_to_clusters(fs, v_blkno); cluster_end = ocfs2_blocks_to_clusters(fs, v_blkno + wanted_blocks - 1); n_clusters = cluster_end - cluster_begin + 1; ret = ocfs2_refcount_cow(ci, cluster_begin, n_clusters, UINT_MAX); if (ret) return ret; } while(wanted_blocks) { ret = ocfs2_extent_map_get_blocks(ci, v_blkno, 1, &p_blkno, &contig_blocks, &extent_flags); if (ret) return ret; if (contig_blocks > wanted_blocks) contig_blocks = wanted_blocks; begin_blocks = 0; end_blocks = 0; p_end = 0; if (!p_blkno) { /* * We meet with a hole here, so we allocate clusters * and empty the both ends in case. * * We will postpone the extent insertion after we * successfully write the extent block, so that and * problems happens in block writing would not affect * the file. */ cluster_begin = ocfs2_blocks_to_clusters(fs, v_blkno); cluster_end = ocfs2_blocks_to_clusters(fs, v_blkno + contig_blocks -1); n_clusters = cluster_end - cluster_begin + 1; ret = ocfs2_new_clusters(fs, 1, n_clusters, &p_start, &n_clusters); if (ret || n_clusters == 0) return ret; begin_blocks = v_blkno & (bpc - 1); p_blkno = p_start + begin_blocks; contig_blocks = n_clusters * bpc - begin_blocks; if (contig_blocks > wanted_blocks) { end_blocks = contig_blocks - wanted_blocks; contig_blocks = wanted_blocks; p_end = p_blkno + wanted_blocks; } insert = 1; } else if (extent_flags & OCFS2_EXT_UNWRITTEN) { begin_blocks = v_blkno & (bpc - 1); p_start = p_blkno - begin_blocks; p_end = p_blkno + wanted_blocks; end_blocks = (p_end & (bpc - 1)) ? bpc - (p_end & (bpc - 1 )) : 0; } if (begin_blocks) { /* * The user don't write the first blocks, * so we have to empty them. */ ret = empty_blocks(fs, p_start, begin_blocks); if (ret) return ret; } if (end_blocks) { /* * we don't need to write that many blocks, * so empty the blocks at the bottom. */ ret = empty_blocks(fs, p_end, end_blocks); if (ret) return ret; } ret = io_write_block(fs->fs_io, p_blkno, contig_blocks, ptr); if (ret) return ret; if (insert) { ret = ocfs2_cached_inode_insert_extent(ci, ocfs2_blocks_to_clusters(fs,v_blkno), p_start, n_clusters, 0); if (ret) { /* * XXX: We don't wan't to overwrite the error * from insert_extent(). But we probably need * to BE LOUDLY UPSET. */ ocfs2_free_clusters(fs, n_clusters, p_start); return ret; } /* save up what we have done. */ ret = ocfs2_write_cached_inode(fs, ci); if (ret) return ret; ret = ocfs2_extent_map_get_blocks(ci, v_blkno, 1, &p_blkno, NULL, NULL); /* now we shouldn't find a hole. */ if (!p_blkno || p_blkno != p_start + begin_blocks) ret = OCFS2_ET_INTERNAL_FAILURE; if (ret) return ret; insert = 0; } else if (extent_flags & OCFS2_EXT_UNWRITTEN) { cluster_begin = ocfs2_blocks_to_clusters(fs, v_blkno); cluster_end = ocfs2_blocks_to_clusters(fs, v_blkno + contig_blocks -1); n_clusters = cluster_end - cluster_begin + 1; ret = ocfs2_mark_extent_written(fs, ci->ci_inode, cluster_begin, n_clusters, p_blkno & ~(bpc - 1)); if (ret) return ret; /* * We don't cache in the library right now, so any * work done in mark_extent_written won't be reflected * in our now stale copy. So refresh it. */ ret = ocfs2_refresh_cached_inode(fs, ci); if (ret) return ret; } *wrote += (contig_blocks << bs_bits); wanted_blocks -= contig_blocks; if (wanted_blocks) { ptr += (contig_blocks << bs_bits); v_blkno += (uint64_t)contig_blocks; } else { if (*wrote + offset > ci->ci_inode->i_size) *wrote = (uint32_t) (ci->ci_inode->i_size - offset); /* break */ } } return ret; }