Пример #1
0
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;
}
Пример #2
0
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);
}
Пример #3
0
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;
}