Пример #1
0
static int ocfs2_validate_group_descriptor(struct super_block *sb,
					   struct buffer_head *bh)
{
	int rc;
	struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;

	trace_ocfs2_validate_group_descriptor(
					(unsigned long long)bh->b_blocknr);

	BUG_ON(!buffer_uptodate(bh));

	/*
	 * If the ecc fails, we return the error but otherwise
	 * leave the filesystem running.  We know any error is
	 * local to this block.
	 */
	rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &gd->bg_check);
	if (rc)
		return rc;

	/*
	 * Errors after here are fatal.
	 */

	return ocfs2_validate_gd_self(sb, bh, 0);
}
Пример #2
0
/*
 * This version only prints errors.  It does not fail the filesystem, and
 * exists only for resize.
 */
int ocfs2_check_group_descriptor(struct super_block *sb,
				 struct ocfs2_dinode *di,
				 struct buffer_head *bh)
{
	int rc;
	struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;

	BUG_ON(!buffer_uptodate(bh));

	/*
	 * If the ecc fails, we return the error but otherwise
	 * leave the filesystem running.  We know any error is
	 * local to this block.
	 */
	rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &gd->bg_check);
	if (rc) {
		mlog(ML_ERROR,
		     "Checksum failed for group descriptor %llu\n",
		     (unsigned long long)bh->b_blocknr);
	} else
		rc = ocfs2_validate_gd_self(sb, bh, 1);
	if (!rc)
		rc = ocfs2_validate_gd_parent(sb, di, bh, 1);

	return rc;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
errcode_t ocfs2_read_super(ocfs2_filesys *fs, uint64_t superblock, char *sb)
{
	errcode_t ret;
	char *blk, *swapblk;
	struct ocfs2_dinode *di, *orig_super;
	int orig_blocksize;
	int blocksize = io_get_blksize(fs->fs_io);

	ret = ocfs2_malloc_block(fs->fs_io, &blk);
	if (ret)
		return ret;

	ret = ocfs2_read_blocks(fs, superblock, 1, blk);
	if (ret)
		goto out_blk;

	di = (struct ocfs2_dinode *)blk;

	ret = OCFS2_ET_BAD_MAGIC;
	if (memcmp(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE,
		   strlen(OCFS2_SUPER_BLOCK_SIGNATURE)))
		goto out_blk;

	/*
	 * We want to use the latest superblock to validate.  We need
	 * a local-endian copy in fs->fs_super, and the unswapped copy to
	 * check in blk.  ocfs2_validate_meta_ecc() uses fs->fs_super and
	 * fs->fs_blocksize.
	 */
	ret = ocfs2_malloc_block(fs->fs_io, &swapblk);
	if (ret)
		goto out_blk;

	memcpy(swapblk, blk, blocksize);
	orig_super = fs->fs_super;
	orig_blocksize = fs->fs_blocksize;
	fs->fs_super = (struct ocfs2_dinode *)swapblk;
	fs->fs_blocksize = blocksize;
	ocfs2_swap_inode_to_cpu(fs, fs->fs_super);

	ret = ocfs2_validate_meta_ecc(fs, blk, &di->i_check);

	fs->fs_super = orig_super;
	fs->fs_blocksize = orig_blocksize;
	ocfs2_free(&swapblk);

	if (ret)
		goto out_blk;

	ocfs2_swap_inode_to_cpu(fs, di);
	if (!sb)
		fs->fs_super = di;
	else {
		memcpy(sb, blk, fs->fs_blocksize);
		ocfs2_free(&blk);
	}

	return 0;

out_blk:
	ocfs2_free(&blk);

	return ret;
}
Пример #6
0
int ocfs2_validate_inode_block(struct super_block *sb,
			       struct buffer_head *bh)
{
	int rc;
	struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;

	trace_ocfs2_validate_inode_block((unsigned long long)bh->b_blocknr);

	BUG_ON(!buffer_uptodate(bh));

	/*
	 * If the ecc fails, we return the error but otherwise
	 * leave the filesystem running.  We know any error is
	 * local to this block.
	 */
	rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &di->i_check);
	if (rc) {
		mlog(ML_ERROR, "Checksum failed for dinode %llu\n",
		     (unsigned long long)bh->b_blocknr);
		goto bail;
	}

	/*
	 * Errors after here are fatal.
	 */

	rc = -EINVAL;

	if (!OCFS2_IS_VALID_DINODE(di)) {
		ocfs2_error(sb, "Invalid dinode #%llu: signature = %.*s\n",
			    (unsigned long long)bh->b_blocknr, 7,
			    di->i_signature);
		goto bail;
	}

	if (le64_to_cpu(di->i_blkno) != bh->b_blocknr) {
		ocfs2_error(sb, "Invalid dinode #%llu: i_blkno is %llu\n",
			    (unsigned long long)bh->b_blocknr,
			    (unsigned long long)le64_to_cpu(di->i_blkno));
		goto bail;
	}

	if (!(di->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {
		ocfs2_error(sb,
			    "Invalid dinode #%llu: OCFS2_VALID_FL not set\n",
			    (unsigned long long)bh->b_blocknr);
		goto bail;
	}

	if (le32_to_cpu(di->i_fs_generation) !=
	    OCFS2_SB(sb)->fs_generation) {
		ocfs2_error(sb,
			    "Invalid dinode #%llu: fs_generation is %u\n",
			    (unsigned long long)bh->b_blocknr,
			    le32_to_cpu(di->i_fs_generation));
		goto bail;
	}

	rc = 0;

bail:
	return rc;
}
Пример #7
0
errcode_t ocfs2_cache_chain_allocator_blocks(ocfs2_filesys *fs,
					     struct ocfs2_dinode *di)
{
	struct io_vec_unit *ivus = NULL;
	char *buf = NULL;
	errcode_t ret = 0;
	int i, j, count;
	struct ocfs2_chain_list *cl;
	struct ocfs2_chain_rec *cr;
	struct ocfs2_group_desc *gd;
	io_channel *channel = fs->fs_io;
	int blocksize = fs->fs_blocksize;
	int64_t group_size;

	if (!(di->i_flags & OCFS2_CHAIN_FL)) {
		ret = OCFS2_ET_INODE_NOT_VALID;
		goto out;
	}

	if (!channel)
		goto out;

	if (!di->i_clusters)
		goto out;

	group_size = (int64_t)di->i_clusters / di->id2.i_chain.cl_cpg;
	group_size *= blocksize;

	if (group_size > io_get_cache_size(channel))
		goto out;

	cl = &(di->id2.i_chain);
	count = cl->cl_next_free_rec;

	ret = ocfs2_malloc_blocks(channel, count, &buf);
	if (ret)
		goto out;
	memset(buf, 0, count * blocksize);

	ret = ocfs2_malloc(sizeof(struct io_vec_unit) * count, &ivus);
	if (ret)
		goto out;

	for (i = 0; i < count; ++i) {
		cr = &(cl->cl_recs[i]);
		ivus[i].ivu_blkno = cr->c_blkno;
		ivus[i].ivu_buf = buf + (i * blocksize);
		ivus[i].ivu_buflen = blocksize;
	}

	while (count) {
		ret = io_vec_read_blocks(channel, ivus, count);
		if (ret)
			goto out;

		for (i = 0, j = 0; i < count; ++i) {
			gd = (struct ocfs2_group_desc *)ivus[i].ivu_buf;

			ret = ocfs2_validate_meta_ecc(fs, ivus[i].ivu_buf,
						      &gd->bg_check);
			if (ret)
				goto out;

			if (memcmp(gd->bg_signature, OCFS2_GROUP_DESC_SIGNATURE,
				   strlen(OCFS2_GROUP_DESC_SIGNATURE))) {
				ret = OCFS2_ET_BAD_GROUP_DESC_MAGIC;
				goto out;
			}
			ocfs2_swap_group_desc_to_cpu(fs, gd);

			if ((gd->bg_next_group > OCFS2_SUPER_BLOCK_BLKNO) &&
			    (gd->bg_next_group < fs->fs_blocks)) {
				ivus[j].ivu_blkno = gd->bg_next_group;
				memset(ivus[j].ivu_buf, 0, blocksize);
				ivus[j].ivu_buflen = blocksize;
				j++;
			}
		}

		count = j;
	}

out:
	ocfs2_free(&ivus);
	ocfs2_free(&buf);
	return ret;
}
Пример #8
0
static int ocfs2_filecheck_repair_inode_block(struct super_block *sb,
					      struct buffer_head *bh)
{
	int changed = 0;
	struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;

	if (!ocfs2_filecheck_validate_inode_block(sb, bh))
		return 0;

	trace_ocfs2_filecheck_repair_inode_block(
		(unsigned long long)bh->b_blocknr);

	if (ocfs2_is_hard_readonly(OCFS2_SB(sb)) ||
	    ocfs2_is_soft_readonly(OCFS2_SB(sb))) {
		mlog(ML_ERROR,
		     "Filecheck: cannot repair dinode #%llu "
		     "on readonly filesystem\n",
		     (unsigned long long)bh->b_blocknr);
		return -OCFS2_FILECHECK_ERR_READONLY;
	}

	if (buffer_jbd(bh)) {
		mlog(ML_ERROR,
		     "Filecheck: cannot repair dinode #%llu, "
		     "its buffer is in jbd\n",
		     (unsigned long long)bh->b_blocknr);
		return -OCFS2_FILECHECK_ERR_INJBD;
	}

	if (!OCFS2_IS_VALID_DINODE(di)) {
		/* Cannot fix invalid inode block */
		return -OCFS2_FILECHECK_ERR_INVALIDINO;
	}

	if (!(di->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {
		/* Cannot just add VALID_FL flag back as a fix,
		 * need more things to check here.
		 */
		return -OCFS2_FILECHECK_ERR_VALIDFLAG;
	}

	if (le64_to_cpu(di->i_blkno) != bh->b_blocknr) {
		di->i_blkno = cpu_to_le64(bh->b_blocknr);
		changed = 1;
		mlog(ML_ERROR,
		     "Filecheck: reset dinode #%llu: i_blkno to %llu\n",
		     (unsigned long long)bh->b_blocknr,
		     (unsigned long long)le64_to_cpu(di->i_blkno));
	}

	if (le32_to_cpu(di->i_fs_generation) !=
	    OCFS2_SB(sb)->fs_generation) {
		di->i_fs_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation);
		changed = 1;
		mlog(ML_ERROR,
		     "Filecheck: reset dinode #%llu: fs_generation to %u\n",
		     (unsigned long long)bh->b_blocknr,
		     le32_to_cpu(di->i_fs_generation));
	}

	if (changed || ocfs2_validate_meta_ecc(sb, bh->b_data, &di->i_check)) {
		ocfs2_compute_meta_ecc(sb, bh->b_data, &di->i_check);
		mark_buffer_dirty(bh);
		mlog(ML_ERROR,
		     "Filecheck: reset dinode #%llu: compute meta ecc\n",
		     (unsigned long long)bh->b_blocknr);
	}

	return 0;
}
Пример #9
0
static int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
						struct buffer_head *bh)
{
	int rc = 0;
	struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;

	trace_ocfs2_filecheck_validate_inode_block(
		(unsigned long long)bh->b_blocknr);

	BUG_ON(!buffer_uptodate(bh));

	/*
	 * Call ocfs2_validate_meta_ecc() first since it has ecc repair
	 * function, but we should not return error immediately when ecc
	 * validation fails, because the reason is quite likely the invalid
	 * inode number inputed.
	 */
	rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &di->i_check);
	if (rc) {
		mlog(ML_ERROR,
		     "Filecheck: checksum failed for dinode %llu\n",
		     (unsigned long long)bh->b_blocknr);
		rc = -OCFS2_FILECHECK_ERR_BLOCKECC;
	}

	if (!OCFS2_IS_VALID_DINODE(di)) {
		mlog(ML_ERROR,
		     "Filecheck: invalid dinode #%llu: signature = %.*s\n",
		     (unsigned long long)bh->b_blocknr, 7, di->i_signature);
		rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
		goto bail;
	} else if (rc)
		goto bail;

	if (le64_to_cpu(di->i_blkno) != bh->b_blocknr) {
		mlog(ML_ERROR,
		     "Filecheck: invalid dinode #%llu: i_blkno is %llu\n",
		     (unsigned long long)bh->b_blocknr,
		     (unsigned long long)le64_to_cpu(di->i_blkno));
		rc = -OCFS2_FILECHECK_ERR_BLOCKNO;
		goto bail;
	}

	if (!(di->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {
		mlog(ML_ERROR,
		     "Filecheck: invalid dinode #%llu: OCFS2_VALID_FL "
		     "not set\n",
		     (unsigned long long)bh->b_blocknr);
		rc = -OCFS2_FILECHECK_ERR_VALIDFLAG;
		goto bail;
	}

	if (le32_to_cpu(di->i_fs_generation) !=
	    OCFS2_SB(sb)->fs_generation) {
		mlog(ML_ERROR,
		     "Filecheck: invalid dinode #%llu: fs_generation is %u\n",
		     (unsigned long long)bh->b_blocknr,
		     le32_to_cpu(di->i_fs_generation));
		rc = -OCFS2_FILECHECK_ERR_GENERATION;
	}

bail:
	return rc;
}