[Ocfs2-devel] [PATCH 13/15] Enable xattr set in index btree. v3

Mark Fasheh mfasheh at suse.com
Mon Aug 11 17:11:10 PDT 2008


On Thu, Aug 07, 2008 at 06:31:33AM +0800, Tao Ma wrote:
> +/*
> + * Add a new cluster for xattr storage.
> + *
> + * If the new cluster is contiguous with the previous one, it will be
> + * appended to the same extent record, and num_clusters will be updated.
> + * If not, we will insert a new extent for it and move some xattrs in
> + * the last cluster into the new allocated one.
> + * We also need to limit the maximum size of a btree leaf, otherwise we'll
> + * lose the benefits of hashing because we'll have to search large leaves.
> + * So now the maximum size is OCFS2_MAX_XATTR_TREE_LEAF_SIZE(or clustersize,
> + * if it's bigger).
> + *
> + * first_bh is the first block of the previous extent rec and header_bh
> + * indicates the bucket we will insert the new xattrs. They will be updated
> + * when the header_bh is moved into the new cluster.
> + */
> +static int ocfs2_add_new_xattr_cluster(struct inode *inode,
> +				       struct buffer_head *root_bh,
> +				       struct buffer_head **first_bh,
> +				       struct buffer_head **header_bh,
> +				       u32 *num_clusters,
> +				       u32 prev_cpos,
> +				       u64 prev_blkno,
> +				       int *extend)
> +{
> +	int ret, credits;
> +	u16 bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
> +	u32 prev_clusters = *num_clusters;
> +	u32 clusters_to_add = 1, bit_off, num_bits, v_start = 0;
> +	u64 block;
> +	handle_t *handle = NULL;
> +	struct ocfs2_alloc_context *data_ac = NULL;
> +	struct ocfs2_alloc_context *meta_ac = NULL;
> +	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
> +	struct ocfs2_xattr_block *xb =
> +			(struct ocfs2_xattr_block *)root_bh->b_data;
> +	struct ocfs2_xattr_tree_root *xb_root = &xb->xb_attrs.xb_root;
> +	struct ocfs2_extent_list *root_el = &xb_root->xt_list;
> +	enum ocfs2_extent_tree_type type = OCFS2_XATTR_TREE_EXTENT;
> +
> +	mlog(0, "Add new xattr cluster for %llu, previous xattr hash = %u, "
> +	     "previous xattr blkno = %llu\n",
> +	     (unsigned long long)OCFS2_I(inode)->ip_blkno,
> +	     prev_cpos, prev_blkno);
> +
> +	ret = ocfs2_lock_allocators(inode, root_bh, root_el,
> +				    clusters_to_add, 0, &data_ac,
> +				    &meta_ac, type, NULL);
> +	if (ret) {
> +		mlog_errno(ret);
> +		goto leave;
> +	}
> +
> +	credits = ocfs2_calc_extend_credits(osb->sb, root_el, clusters_to_add);
> +	handle = ocfs2_start_trans(osb, credits);
> +	if (IS_ERR(handle)) {
> +		ret = PTR_ERR(handle);
> +		handle = NULL;
> +		mlog_errno(ret);
> +		goto leave;
> +	}
> +
> +	ret = ocfs2_journal_access(handle, inode, root_bh,
> +				   OCFS2_JOURNAL_ACCESS_WRITE);
> +	if (ret < 0) {
> +		mlog_errno(ret);
> +		goto leave;
> +	}
> +
> +	ret = __ocfs2_claim_clusters(osb, handle, data_ac, 1,
> +				     clusters_to_add, &bit_off, &num_bits);
> +	if (ret < 0) {
> +		if (ret != -ENOSPC)
> +			mlog_errno(ret);
> +		goto leave;
> +	}
> +
> +	BUG_ON(num_bits > clusters_to_add);
> +
> +	block = ocfs2_clusters_to_blocks(osb->sb, bit_off);
> +	mlog(0, "Allocating %u clusters at block %u for xattr in inode %llu\n",
> +	     num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
> +
> +	if (prev_blkno + prev_clusters * bpc == block &&
> +	    (prev_clusters + num_bits) << osb->s_clustersize_bits <=
> +	     OCFS2_MAX_XATTR_TREE_LEAF_SIZE) {
> +		/*
> +		 * If this cluster is contiguous with the old one and
> +		 * adding this new cluster, we don't surpass the limit of
> +		 * OCFS2_MAX_XATTR_TREE_LEAF_SIZE, cool. We will let it be
> +		 * initialized and used like other buckets in the previous
> +		 * cluster.
> +		 * So add it as a contiguous one. The caller will handle
> +		 * its init process.
> +		 */
> +		v_start = prev_cpos + prev_clusters;
> +		*num_clusters = prev_clusters + num_bits;
> +		mlog(0, "Add contiguous %u clusters to previous extent rec.\n",
> +		     num_bits);
> +	} else {
> +		ret = ocfs2_adjust_xattr_cross_cluster(inode,
> +						       handle,
> +						       first_bh,
> +						       header_bh,
> +						       block,
> +						       prev_blkno,
> +						       prev_clusters,
> +						       &v_start,
> +						       extend);
> +		if (ret) {
> +			mlog_errno(ret);
> +			goto leave;
> +		}
> +	}
> +
> +	mlog(0, "Insert %u clusters at block %llu for xattr at %u\n",
> +	     num_bits, block, v_start);
> +	ret = ocfs2_xattr_tree_insert_extent(osb, handle, inode, root_bh,
> +					     v_start, block, num_bits,
> +					     0, meta_ac);

I think we need to do something down in the extent insertion code to prevent
merging in the OCFS2_MAX_XATTR_TREE_LEAF_SIZE cases - what's preventing it
from appending that allocation to the end of an extent (any extent) in the
btree?
	--Mark

--
Mark Fasheh



More information about the Ocfs2-devel mailing list