Пример #1
0
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;
}
Пример #2
0
/*
 * Write super block and backups doesn't need to collaborate with journal,
 * so we don't need to lock ip_io_mutex and ci doesn't need to bea passed
 * into this function.
 */
int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
				struct buffer_head *bh)
{
	int ret = 0;
	struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;

	BUG_ON(buffer_jbd(bh));
	ocfs2_check_super_or_backup(osb->sb, bh->b_blocknr);

	if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) {
		ret = -EROFS;
		mlog_errno(ret);
		goto out;
	}

	lock_buffer(bh);
	set_buffer_uptodate(bh);

	/* remove from dirty list before I/O. */
	clear_buffer_dirty(bh);

	get_bh(bh); /* for end_buffer_write_sync() */
	bh->b_end_io = end_buffer_write_sync;
	ocfs2_compute_meta_ecc(osb->sb, bh->b_data, &di->i_check);
	submit_bh(REQ_OP_WRITE, 0, bh);

	wait_on_buffer(bh);

	if (!buffer_uptodate(bh)) {
		ret = -EIO;
		mlog_errno(ret);
	}

out:
	return ret;
}
Пример #3
0
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;
}
Пример #4
0
/*
 * We want to free the bitmap bits outside of any recovery context as
 * we'll need a cluster lock to do so, but we must clear the local
 * alloc before giving up the recovered nodes journal. To solve this,
 * we kmalloc a copy of the local alloc before it's change for the
 * caller to process with ocfs2_complete_local_alloc_recovery
 */
int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb,
				     int slot_num,
				     struct ocfs2_dinode **alloc_copy)
{
	int status = 0;
	struct buffer_head *alloc_bh = NULL;
	struct inode *inode = NULL;
	struct ocfs2_dinode *alloc;

	trace_ocfs2_begin_local_alloc_recovery(slot_num);

	*alloc_copy = NULL;

	inode = ocfs2_get_system_file_inode(osb,
					    LOCAL_ALLOC_SYSTEM_INODE,
					    slot_num);
	if (!inode) {
		status = -EINVAL;
		mlog_errno(status);
		goto bail;
	}

	inode_lock(inode);

	status = ocfs2_read_inode_block_full(inode, &alloc_bh,
					     OCFS2_BH_IGNORE_CACHE);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	*alloc_copy = kmalloc(alloc_bh->b_size, GFP_KERNEL);
	if (!(*alloc_copy)) {
		status = -ENOMEM;
		goto bail;
	}
	memcpy((*alloc_copy), alloc_bh->b_data, alloc_bh->b_size);

	alloc = (struct ocfs2_dinode *) alloc_bh->b_data;
	ocfs2_clear_local_alloc(alloc);

	ocfs2_compute_meta_ecc(osb->sb, alloc_bh->b_data, &alloc->i_check);
	status = ocfs2_write_block(osb, alloc_bh, INODE_CACHE(inode));
	if (status < 0)
		mlog_errno(status);

bail:
	if (status < 0) {
		kfree(*alloc_copy);
		*alloc_copy = NULL;
	}

	brelse(alloc_bh);

	if (inode) {
		inode_unlock(inode);
		iput(inode);
	}

	if (status)
		mlog_errno(status);
	return status;
}
Пример #5
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;
}
Пример #6
0
/*
 * dump_block_check
 *
 */
void dump_block_check(FILE *out, struct ocfs2_block_check *bc, void *block)
{
    struct ocfs2_block_check tmp = *bc;
    int crc_fail;
    enum ocfs2_block_type bt = ocfs2_detect_block(block);

    /* Swap block to little endian for compute_meta_ecc */
    switch (bt) {
    case OCFS2_BLOCK_INODE:
    case OCFS2_BLOCK_SUPERBLOCK:
        ocfs2_swap_inode_from_cpu(gbls.fs, block);
        break;
    case OCFS2_BLOCK_EXTENT_BLOCK:
        ocfs2_swap_extent_block_from_cpu(gbls.fs, block);
        break;
    case OCFS2_BLOCK_GROUP_DESCRIPTOR:
        ocfs2_swap_group_desc_from_cpu(gbls.fs, block);
        break;
    case OCFS2_BLOCK_DIR_BLOCK:
        ocfs2_swap_dir_entries_from_cpu(block,
                                        gbls.fs->fs_blocksize);
        break;
    case OCFS2_BLOCK_XATTR:
        ocfs2_swap_xattr_block_from_cpu(gbls.fs, block);
        break;
    case OCFS2_BLOCK_REFCOUNT:
        ocfs2_swap_refcount_block_from_cpu(gbls.fs, block);
        break;
    case OCFS2_BLOCK_DXROOT:
        ocfs2_swap_dx_root_from_cpu(gbls.fs, block);
        break;
    case OCFS2_BLOCK_DXLEAF:
        ocfs2_swap_dx_leaf_from_cpu(block);
        break;
    default:
        fprintf(out, "Unable to determine block type");
        return;
    }

    /* Re-compute based on what we got from disk */
    ocfs2_compute_meta_ecc(gbls.fs, block, bc);

    /* Swap block back to CPU */
    switch (bt) {
    case OCFS2_BLOCK_INODE:
    case OCFS2_BLOCK_SUPERBLOCK:
        ocfs2_swap_inode_to_cpu(gbls.fs, block);
        break;
    case OCFS2_BLOCK_EXTENT_BLOCK:
        ocfs2_swap_extent_block_to_cpu(gbls.fs, block);
        break;
    case OCFS2_BLOCK_GROUP_DESCRIPTOR:
        ocfs2_swap_group_desc_to_cpu(gbls.fs, block);
        break;
    case OCFS2_BLOCK_DIR_BLOCK:
        ocfs2_swap_dir_entries_to_cpu(block,
                                      gbls.fs->fs_blocksize);
        break;
    case OCFS2_BLOCK_XATTR:
        ocfs2_swap_xattr_block_to_cpu(gbls.fs, block);
        break;
    case OCFS2_BLOCK_REFCOUNT:
        ocfs2_swap_refcount_block_to_cpu(gbls.fs, block);
        break;
    case OCFS2_BLOCK_DXROOT:
        ocfs2_swap_dx_root_to_cpu(gbls.fs, block);
        break;
    case OCFS2_BLOCK_DXLEAF:
        ocfs2_swap_dx_leaf_to_cpu(block);
        break;
    default:
        break;
    }

    crc_fail = memcmp(bc, &tmp, sizeof(*bc));

    fprintf(out, "\tCRC32: %.8"PRIx32"   ECC: %.4"PRIx16"\n",
            le32_to_cpu(tmp.bc_crc32e), le16_to_cpu(tmp.bc_ecc));
    if (crc_fail)
        fprintf(out, "\t**FAILED CHECKSUM** Computed CRC32: %.8"
                PRIx32"   ECC: %.4"PRIx16"\n",
                le32_to_cpu(bc->bc_crc32e), le16_to_cpu(bc->bc_ecc));

    /* Leave the block as we found it. */
    *bc = tmp;
}