예제 #1
0
static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
				  handle_t *handle,
				  u32 bits_wanted,
				  u32 min_bits,
				  u16 *bit_off,
				  unsigned int *num_bits,
				  u64 gd_blkno,
				  u16 *bits_left)
{
	int ret;
	u16 found;
	struct buffer_head *group_bh = NULL;
	struct ocfs2_group_desc *gd;
	struct inode *alloc_inode = ac->ac_inode;

	ret = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb), gd_blkno,
			       &group_bh, OCFS2_BH_CACHED, alloc_inode);
	if (ret < 0) {
		mlog_errno(ret);
		return ret;
	}

	gd = (struct ocfs2_group_desc *) group_bh->b_data;
	if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {
		OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, gd);
		ret = -EIO;
		goto out;
	}

	ret = ac->ac_group_search(alloc_inode, group_bh, bits_wanted, min_bits,
				  bit_off, &found);
	if (ret < 0) {
		if (ret != -ENOSPC)
			mlog_errno(ret);
		goto out;
	}

	*num_bits = found;

	ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh,
					       *num_bits,
					       le16_to_cpu(gd->bg_chain));
	if (ret < 0) {
		mlog_errno(ret);
		goto out;
	}

	ret = ocfs2_block_group_set_bits(handle, alloc_inode, gd, group_bh,
					 *bit_off, *num_bits);
	if (ret < 0)
		mlog_errno(ret);

	*bits_left = le16_to_cpu(gd->bg_free_bits_count);

out:
	brelse(group_bh);

	return ret;
}
예제 #2
0
/* somewhat more expensive than our other checks, so use sparingly. */
static int ocfs2_check_group_descriptor(struct super_block *sb,
					struct ocfs2_dinode *di,
					struct ocfs2_group_desc *gd)
{
	unsigned int max_bits;

	if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {
		OCFS2_RO_ON_INVALID_GROUP_DESC(sb, gd);
		return -EIO;
	}

	if (di->i_blkno != gd->bg_parent_dinode) {
		ocfs2_error(sb, "Group descriptor # %llu has bad parent "
			    "pointer (%llu, expected %llu)",
			    (unsigned long long)le64_to_cpu(gd->bg_blkno),
			    (unsigned long long)le64_to_cpu(gd->bg_parent_dinode),
			    (unsigned long long)le64_to_cpu(di->i_blkno));
		return -EIO;
	}

	max_bits = le16_to_cpu(di->id2.i_chain.cl_cpg) * le16_to_cpu(di->id2.i_chain.cl_bpc);
	if (le16_to_cpu(gd->bg_bits) > max_bits) {
		ocfs2_error(sb, "Group descriptor # %llu has bit count of %u",
			    (unsigned long long)le64_to_cpu(gd->bg_blkno),
			    le16_to_cpu(gd->bg_bits));
		return -EIO;
	}

	if (le16_to_cpu(gd->bg_chain) >=
	    le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) {
		ocfs2_error(sb, "Group descriptor # %llu has bad chain %u",
			    (unsigned long long)le64_to_cpu(gd->bg_blkno),
			    le16_to_cpu(gd->bg_chain));
		return -EIO;
	}

	if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits)) {
		ocfs2_error(sb, "Group descriptor # %llu has bit count %u but "
			    "claims that %u are free",
			    (unsigned long long)le64_to_cpu(gd->bg_blkno),
			    le16_to_cpu(gd->bg_bits),
			    le16_to_cpu(gd->bg_free_bits_count));
		return -EIO;
	}

	if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size))) {
		ocfs2_error(sb, "Group descriptor # %llu has bit count %u but "
			    "max bitmap bits of %u",
			    (unsigned long long)le64_to_cpu(gd->bg_blkno),
			    le16_to_cpu(gd->bg_bits),
			    8 * le16_to_cpu(gd->bg_size));
		return -EIO;
	}

	return 0;
}
예제 #3
0
static inline int ocfs2_block_group_set_bits(handle_t *handle,
					     struct inode *alloc_inode,
					     struct ocfs2_group_desc *bg,
					     struct buffer_head *group_bh,
					     unsigned int bit_off,
					     unsigned int num_bits)
{
	int status;
	void *bitmap = bg->bg_bitmap;
	int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;

	mlog_entry_void();

	if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
		OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
		status = -EIO;
		goto bail;
	}
	BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits);

	mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off,
	     num_bits);

	if (ocfs2_is_cluster_bitmap(alloc_inode))
		journal_type = OCFS2_JOURNAL_ACCESS_UNDO;

	status = ocfs2_journal_access(handle,
				      alloc_inode,
				      group_bh,
				      journal_type);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	le16_add_cpu(&bg->bg_free_bits_count, -num_bits);

	while(num_bits--)
		ocfs2_set_bit(bit_off++, bitmap);

	status = ocfs2_journal_dirty(handle,
				     group_bh);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

bail:
	mlog_exit(status);
	return status;
}
예제 #4
0
static inline int ocfs2_block_group_clear_bits(handle_t *handle,
					       struct inode *alloc_inode,
					       struct ocfs2_group_desc *bg,
					       struct buffer_head *group_bh,
					       unsigned int bit_off,
					       unsigned int num_bits)
{
	int status;
	unsigned int tmp;
	int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;
	struct ocfs2_group_desc *undo_bg = NULL;

	mlog_entry_void();

	if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
		OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
		status = -EIO;
		goto bail;
	}

	mlog(0, "off = %u, num = %u\n", bit_off, num_bits);

	if (ocfs2_is_cluster_bitmap(alloc_inode))
		journal_type = OCFS2_JOURNAL_ACCESS_UNDO;

	status = ocfs2_journal_access(handle, alloc_inode, group_bh,
				      journal_type);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	if (ocfs2_is_cluster_bitmap(alloc_inode))
		undo_bg = (struct ocfs2_group_desc *) bh2jh(group_bh)->b_committed_data;

	tmp = num_bits;
	while(tmp--) {
		ocfs2_clear_bit((bit_off + tmp),
				(unsigned long *) bg->bg_bitmap);
		if (ocfs2_is_cluster_bitmap(alloc_inode))
			ocfs2_set_bit(bit_off + tmp,
				      (unsigned long *) undo_bg->bg_bitmap);
	}
	le16_add_cpu(&bg->bg_free_bits_count, num_bits);

	status = ocfs2_journal_dirty(handle, group_bh);
	if (status < 0)
		mlog_errno(status);
bail:
	return status;
}
예제 #5
0
static int ocfs2_validate_gd_self(struct super_block *sb,
				  struct buffer_head *bh,
				  int resize)
{
	struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;

	if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {
		do_error("Group descriptor #%llu has bad signature %.*s",
			 (unsigned long long)bh->b_blocknr, 7,
			 gd->bg_signature);
		return -EINVAL;
	}

	if (le64_to_cpu(gd->bg_blkno) != bh->b_blocknr) {
		do_error("Group descriptor #%llu has an invalid bg_blkno "
			 "of %llu",
			 (unsigned long long)bh->b_blocknr,
			 (unsigned long long)le64_to_cpu(gd->bg_blkno));
		return -EINVAL;
	}

	if (le32_to_cpu(gd->bg_generation) != OCFS2_SB(sb)->fs_generation) {
		do_error("Group descriptor #%llu has an invalid "
			 "fs_generation of #%u",
			 (unsigned long long)bh->b_blocknr,
			 le32_to_cpu(gd->bg_generation));
		return -EINVAL;
	}

	if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits)) {
		do_error("Group descriptor #%llu has bit count %u but "
			 "claims that %u are free",
			 (unsigned long long)bh->b_blocknr,
			 le16_to_cpu(gd->bg_bits),
			 le16_to_cpu(gd->bg_free_bits_count));
		return -EINVAL;
	}

	if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size))) {
		do_error("Group descriptor #%llu has bit count %u but "
			 "max bitmap bits of %u",
			 (unsigned long long)bh->b_blocknr,
			 le16_to_cpu(gd->bg_bits),
			 8 * le16_to_cpu(gd->bg_size));
		return -EINVAL;
	}

	return 0;
}
예제 #6
0
static inline int ocfs2_block_group_set_bits(handle_t *handle,
					     struct inode *alloc_inode,
					     struct ocfs2_group_desc *bg,
					     struct buffer_head *group_bh,
					     unsigned int bit_off,
					     unsigned int num_bits)
{
	int status;
	void *bitmap = bg->bg_bitmap;
	int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;

	mlog_entry_void();

	/* All callers get the descriptor via
	 * ocfs2_read_group_descriptor().  Any corruption is a code bug. */
	BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg));
	BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits);

	mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off,
	     num_bits);

	if (ocfs2_is_cluster_bitmap(alloc_inode))
		journal_type = OCFS2_JOURNAL_ACCESS_UNDO;

	status = ocfs2_journal_access_gd(handle,
					 INODE_CACHE(alloc_inode),
					 group_bh,
					 journal_type);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	le16_add_cpu(&bg->bg_free_bits_count, -num_bits);

	while(num_bits--)
		ocfs2_set_bit(bit_off++, bitmap);

	status = ocfs2_journal_dirty(handle,
				     group_bh);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

bail:
	mlog_exit(status);
	return status;
}
static inline int ocfs2_block_group_set_bits(handle_t *handle,
					     struct inode *alloc_inode,
					     struct ocfs2_group_desc *bg,
					     struct buffer_head *group_bh,
					     unsigned int bit_off,
					     unsigned int num_bits)
{
	int status;
	void *bitmap = bg->bg_bitmap;
	int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;

	/* All callers get the descriptor via
	 * ocfs2_read_group_descriptor().  Any corruption is a code bug. */
	BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg));
	BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits);

	mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off,
	     num_bits);

	if (ocfs2_is_cluster_bitmap(alloc_inode))
		journal_type = OCFS2_JOURNAL_ACCESS_UNDO;

	status = ocfs2_journal_access_gd(handle,
					 INODE_CACHE(alloc_inode),
					 group_bh,
					 journal_type);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	le16_add_cpu(&bg->bg_free_bits_count, -num_bits);
	if (le16_to_cpu(bg->bg_free_bits_count) > le16_to_cpu(bg->bg_bits)) {
		ocfs2_error(alloc_inode->i_sb, "Group descriptor # %llu has bit"
			    " count %u but claims %u are freed. num_bits %d",
			    (unsigned long long)le64_to_cpu(bg->bg_blkno),
			    le16_to_cpu(bg->bg_bits),
			    le16_to_cpu(bg->bg_free_bits_count), num_bits);
		return -EROFS;
	}
	while (num_bits--)
		ocfs2_set_bit(bit_off++, bitmap);

	ocfs2_journal_dirty(handle, group_bh);

bail:
	return status;
}
예제 #8
0
static int ocfs2_check_new_group(struct inode *inode,
				 struct ocfs2_dinode *di,
				 struct ocfs2_new_group_input *input,
				 struct buffer_head *group_bh)
{
	int ret;
	struct ocfs2_group_desc *gd;
	u16 cl_bpc = le16_to_cpu(di->id2.i_chain.cl_bpc);
	unsigned int max_bits = le16_to_cpu(di->id2.i_chain.cl_cpg) *
				le16_to_cpu(di->id2.i_chain.cl_bpc);


	gd = (struct ocfs2_group_desc *)group_bh->b_data;

	ret = -EIO;
	if (!OCFS2_IS_VALID_GROUP_DESC(gd))
		mlog(ML_ERROR, "Group descriptor # %llu isn't valid.\n",
		     (unsigned long long)le64_to_cpu(gd->bg_blkno));
	else if (di->i_blkno != gd->bg_parent_dinode)
		mlog(ML_ERROR, "Group descriptor # %llu has bad parent "
		     "pointer (%llu, expected %llu)\n",
		     (unsigned long long)le64_to_cpu(gd->bg_blkno),
		     (unsigned long long)le64_to_cpu(gd->bg_parent_dinode),
		     (unsigned long long)le64_to_cpu(di->i_blkno));
	else if (le16_to_cpu(gd->bg_bits) > max_bits)
		mlog(ML_ERROR, "Group descriptor # %llu has bit count of %u\n",
		     (unsigned long long)le64_to_cpu(gd->bg_blkno),
		     le16_to_cpu(gd->bg_bits));
	else if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits))
		mlog(ML_ERROR, "Group descriptor # %llu has bit count %u but "
		     "claims that %u are free\n",
		     (unsigned long long)le64_to_cpu(gd->bg_blkno),
		     le16_to_cpu(gd->bg_bits),
		     le16_to_cpu(gd->bg_free_bits_count));
	else if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size)))
		mlog(ML_ERROR, "Group descriptor # %llu has bit count %u but "
		     "max bitmap bits of %u\n",
		     (unsigned long long)le64_to_cpu(gd->bg_blkno),
		     le16_to_cpu(gd->bg_bits),
		     8 * le16_to_cpu(gd->bg_size));
	else if (le16_to_cpu(gd->bg_chain) != input->chain)
		mlog(ML_ERROR, "Group descriptor # %llu has bad chain %u "
		     "while input has %u set.\n",
		     (unsigned long long)le64_to_cpu(gd->bg_blkno),
		     le16_to_cpu(gd->bg_chain), input->chain);
	else if (le16_to_cpu(gd->bg_bits) != input->clusters * cl_bpc)
		mlog(ML_ERROR, "Group descriptor # %llu has bit count %u but "
		     "input has %u clusters set\n",
		     (unsigned long long)le64_to_cpu(gd->bg_blkno),
		     le16_to_cpu(gd->bg_bits), input->clusters);
	else if (le16_to_cpu(gd->bg_free_bits_count) != input->frees * cl_bpc)
		mlog(ML_ERROR, "Group descriptor # %llu has free bit count %u "
		     "but it should have %u set\n",
		     (unsigned long long)le64_to_cpu(gd->bg_blkno),
		     le16_to_cpu(gd->bg_bits),
		     input->frees * cl_bpc);
	else
		ret = 0;

	return ret;
}
예제 #9
0
static int ocfs2_relink_block_group(handle_t *handle,
				    struct inode *alloc_inode,
				    struct buffer_head *fe_bh,
				    struct buffer_head *bg_bh,
				    struct buffer_head *prev_bg_bh,
				    u16 chain)
{
	int status;
	/* there is a really tiny chance the journal calls could fail,
	 * but we wouldn't want inconsistent blocks in *any* case. */
	u64 fe_ptr, bg_ptr, prev_bg_ptr;
	struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data;
	struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;
	struct ocfs2_group_desc *prev_bg = (struct ocfs2_group_desc *) prev_bg_bh->b_data;

	if (!OCFS2_IS_VALID_DINODE(fe)) {
		OCFS2_RO_ON_INVALID_DINODE(alloc_inode->i_sb, fe);
		status = -EIO;
		goto out;
	}
	if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
		OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
		status = -EIO;
		goto out;
	}
	if (!OCFS2_IS_VALID_GROUP_DESC(prev_bg)) {
		OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, prev_bg);
		status = -EIO;
		goto out;
	}

	mlog(0, "Suballoc %llu, chain %u, move group %llu to top, prev = %llu\n",
	     (unsigned long long)le64_to_cpu(fe->i_blkno), chain,
	     (unsigned long long)le64_to_cpu(bg->bg_blkno),
	     (unsigned long long)le64_to_cpu(prev_bg->bg_blkno));

	fe_ptr = le64_to_cpu(fe->id2.i_chain.cl_recs[chain].c_blkno);
	bg_ptr = le64_to_cpu(bg->bg_next_group);
	prev_bg_ptr = le64_to_cpu(prev_bg->bg_next_group);

	status = ocfs2_journal_access(handle, alloc_inode, prev_bg_bh,
				      OCFS2_JOURNAL_ACCESS_WRITE);
	if (status < 0) {
		mlog_errno(status);
		goto out_rollback;
	}

	prev_bg->bg_next_group = bg->bg_next_group;

	status = ocfs2_journal_dirty(handle, prev_bg_bh);
	if (status < 0) {
		mlog_errno(status);
		goto out_rollback;
	}

	status = ocfs2_journal_access(handle, alloc_inode, bg_bh,
				      OCFS2_JOURNAL_ACCESS_WRITE);
	if (status < 0) {
		mlog_errno(status);
		goto out_rollback;
	}

	bg->bg_next_group = fe->id2.i_chain.cl_recs[chain].c_blkno;

	status = ocfs2_journal_dirty(handle, bg_bh);
	if (status < 0) {
		mlog_errno(status);
		goto out_rollback;
	}

	status = ocfs2_journal_access(handle, alloc_inode, fe_bh,
				      OCFS2_JOURNAL_ACCESS_WRITE);
	if (status < 0) {
		mlog_errno(status);
		goto out_rollback;
	}

	fe->id2.i_chain.cl_recs[chain].c_blkno = bg->bg_blkno;

	status = ocfs2_journal_dirty(handle, fe_bh);
	if (status < 0) {
		mlog_errno(status);
		goto out_rollback;
	}

	status = 0;
out_rollback:
	if (status < 0) {
		fe->id2.i_chain.cl_recs[chain].c_blkno = cpu_to_le64(fe_ptr);
		bg->bg_next_group = cpu_to_le64(bg_ptr);
		prev_bg->bg_next_group = cpu_to_le64(prev_bg_ptr);
	}
out:
	mlog_exit(status);
	return status;
}
예제 #10
0
static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
					     struct buffer_head *bg_bh,
					     unsigned int bits_wanted,
					     unsigned int total_bits,
					     u16 *bit_off,
					     u16 *bits_found)
{
	void *bitmap;
	u16 best_offset, best_size;
	int offset, start, found, status = 0;
	struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;

	if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
		OCFS2_RO_ON_INVALID_GROUP_DESC(osb->sb, bg);
		return -EIO;
	}

	found = start = best_offset = best_size = 0;
	bitmap = bg->bg_bitmap;

	while((offset = ocfs2_find_next_zero_bit(bitmap, total_bits, start)) != -1) {
		if (offset == total_bits)
			break;

		if (!ocfs2_test_bg_bit_allocatable(bg_bh, offset)) {
			/* We found a zero, but we can't use it as it
			 * hasn't been put to disk yet! */
			found = 0;
			start = offset + 1;
		} else if (offset == start) {
			/* we found a zero */
			found++;
			/* move start to the next bit to test */
			start++;
		} else {
			/* got a zero after some ones */
			found = 1;
			start = offset + 1;
		}
		if (found > best_size) {
			best_size = found;
			best_offset = start - found;
		}
		/* we got everything we needed */
		if (found == bits_wanted) {
			/* mlog(0, "Found it all!\n"); */
			break;
		}
	}

	/* XXX: I think the first clause is equivalent to the second
	 * 	- jlbec */
	if (found == bits_wanted) {
		*bit_off = start - found;
		*bits_found = found;
	} else if (best_size) {
		*bit_off = best_offset;
		*bits_found = best_size;
	} else {
		status = -ENOSPC;
		/* No error log here -- see the comment above
		 * ocfs2_test_bg_bit_allocatable */
	}

	return status;
}