[Ocfs2-devel] [PATCH 17/41] ocfs2: Add CoW support.
Tao Ma
tao.ma at oracle.com
Thu Aug 20 23:25:35 PDT 2009
Joel Becker wrote:
> On Thu, Aug 20, 2009 at 07:51:36PM -0700, Joel Becker wrote:
>> I'm halfway through a modification of this code that splits out
>> MAX_COW_BYTES from write_len. Let me finish it tomorrow.
>
> I just did it. What do you think?
>
> Joel
>
> diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
> index d59860d..7790e1d 100644
> --- a/fs/ocfs2/refcounttree.c
> +++ b/fs/ocfs2/refcounttree.c
> @@ -2499,7 +2499,7 @@ out:
> return ret;
> }
>
> -#define MAX_COW_BYTES 1048576
> +#define MAX_CONTIG_BYTES 1048576
> /*
> * Calculate out the start and number of virtual clusters we need to to CoW.
> *
> @@ -2508,9 +2508,8 @@ out:
> * max_cpos is the place where we want to stop CoW intentionally.
> *
> * Normal we will start CoW from the beginning of extent record cotaining cpos.
> - * And We will try to Cow as much clusters as we can until we reach
> - * MAX_COW_BYTES. If the write_len is larger than MAX_COW_BYTES, we will
> - * use that value as the maximum clusters.
> + * We try to break up extents on boundaries of MAX_CONTIG_BYTES so that we
> + * get good I/O from the resulting extent tree.
> */
> static int ocfs2_refcount_cal_cow_clusters(struct inode *inode,
> struct ocfs2_extent_list *el,
> @@ -2525,10 +2524,11 @@ static int ocfs2_refcount_cal_cow_clusters(struct inode *inode,
> struct buffer_head *eb_bh = NULL;
> struct ocfs2_extent_block *eb = NULL;
> struct ocfs2_extent_rec *rec;
> - int max_clusters = ocfs2_clusters_for_bytes(inode->i_sb, MAX_COW_BYTES);
> + int want_clusters;
> + int contig_clusters =
> + ocfs2_clusters_for_bytes(inode->i_sb, MAX_CONTIG_BYTES);
> int leaf_clusters, rec_end = 0;
>
> - max_clusters = max_clusters < write_len ? write_len : max_clusters;
> if (tree_height > 0) {
> ret = ocfs2_find_leaf(INODE_CACHE(inode), el, cpos, &eb_bh);
> if (ret) {
> @@ -2587,53 +2587,84 @@ static int ocfs2_refcount_cal_cow_clusters(struct inode *inode,
> leaf_clusters = rec_end - le32_to_cpu(rec->e_cpos);
> }
>
> - if (*cow_len + leaf_clusters >= max_clusters) {
> - if (*cow_len == 0) {
> - /*
> - * cpos is in a very large extent record.
> - * So just split max_clusters from the
> - * extent record.
> - */
> - if ((rec_end - cpos) <= max_clusters) {
> - /*
> - * We can take max_clusters off
> - * the end and cover all of our
> - * write.
> - */
> - *cow_start = rec_end - max_clusters;
> - } else if ((*cow_start + max_clusters) >
> - (cpos + write_len)) {
> - /*
> - * We can take max_clusters off
> - * the front and cover all of
> - * our write.
> - */
> - /* NOOP, *cow_start is already set */
> - } else {
> - /*
> - * We're CoWing more data than
> - * write_len for contiguousness,
> - * but it doesn't fit at the
> - * front or end of this extent.
> - * Let's try to slice the extent
> - * up nicely. Optimally, our
> - * CoW region starts at a
> - * multiple of max_clusters. If
> - * that doesn't fit, we give up
> - * and just CoW at cpos.
> - */
> - *cow_start +=
> - (cpos - *cow_start) &
> - ~(max_clusters - 1);
> - if ((*cow_start + max_clusters) <
> - (cpos + write_len))
> - *cow_start = cpos;
> - }
> - }
> - *cow_len = max_clusters;
> - break;
> - } else
> + /*
> + * How many clusters do we actually need from
> + * this extent? First we see how many we actually
> + * need to complete the write. If that's smaller
> + * than contig_clusters, we try for
> + * contig_clustes.
> + */
> + if (!*cow_len)
> + want_clusters = write_len;
> + else
> + want_clusters = (cpos + write_len) -
> + (*cow_start + *cow_len);
> + if (want_clusters < contig_clusters)
> + want_clusters = contig_clusters;
> +
> + /*
> + * If the write does not cover the whole extent, we
> + * need to calculate how we're going to split the extent.
> + * We try to do it on contig_clusters boundaries.
> + *
> + * Any extent smaller than contig_clusters will be
> + * CoWed in its entirety.
> + */
> + if (leaf_clusters < contig_clusters)
"<=" ?
> *cow_len += leaf_clusters;
> + else if (*cow_len || (*cow_start == cpos)) {
> + /*
> + * This extent needs to be CoW'd from its
> + * beginning, so all we have to do is compute
> + * how many clusters to grab.
> + */
> + if (leaf_clusters < want_clusters)
> + *cow_len += leaf_clusters;
> + else
> + *cow_len += want_clusters;
> + } else if ((*cow_start + contig_clusters) >
> + (cpos + write_len)) {
">="?
otherwise, it looks good to me.
btw, you will create a separate patch for this or I should integrate it
into my original one?
Regards,
Tao
> + /*
> + * Breaking off contig_clusters at the front
> + * of the extent will cover our write. That's
> + * easy.
> + */
> + *cow_len = contig_clusters;
> + } else if ((rec_end - cpos) <= contig_clusters) {
> + /*
> + * Breaking off contig_clusters at the tail of
> + * this extent will cover cpos.
> + */
> + *cow_start = rec_end - cpos;
> + *cow_len = contig_clusters;
> + } else if ((rec_end - cpos) <= want_clusters) {
> + /*
> + * While we can't fit the entire write in this
> + * extent, we know that the write goes from cpos
> + * to the end of the extent. Break that off.
> + */
> + *cow_start = cpos;
> + *cow_len = rec_end - cpos;
> + } else {
> + /*
> + * Ok, the entire write lives in the middle of
> + * this extent.
> + * Let's try to slice the extentup nicely.
> + * Optimally, our CoW region starts at a
> + * multiple of contig_clusters. If that doesn't
> + * fit, we give up and just CoW at cpos.
> + */
> + *cow_start += (cpos - *cow_start) &
> + ~(contig_clusters - 1);
> + if ((*cow_start + want_clusters) <
> + (cpos + write_len))
> + *cow_start = cpos;
> + *cow_len = want_clusters;
> + }
> +
> + /* Have we covered our entire write yet? */
> + if ((*cow_start + *cow_len) >= (cpos + write_len))
> + break;
>
> /*
> * If we reach the end of the extent block and don't get enough
>
>
More information about the Ocfs2-devel
mailing list