[Ocfs2-devel] [PATCH 19/41] ocfs2: Integrate CoW in file write.
Joel Becker
Joel.Becker at oracle.com
Thu Aug 20 18:04:43 PDT 2009
On Tue, Aug 18, 2009 at 02:19:20PM +0800, Tao Ma wrote:
> @@ -1674,6 +1692,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
> struct ocfs2_alloc_context *meta_ac = NULL;
> handle_t *handle;
> struct ocfs2_extent_tree et;
> + unsigned int refcounted_cpos, cow_len;
>
> ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh);
> if (ret) {
> @@ -1701,12 +1720,36 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
> }
>
> ret = ocfs2_populate_write_desc(inode, wc, &clusters_to_alloc,
> - &extents_to_split);
> - if (ret) {
> + &extents_to_split, &refcounted_cpos);
> + if (ret && ret != -ETXTBSY) {
> mlog_errno(ret);
> goto out;
> }
>
> + if (ret == -ETXTBSY) {
> + BUG_ON(refcounted_cpos == UINT_MAX);
> + cow_len = wc->w_clen - (refcounted_cpos - wc->w_cpos);
> +
> + ret = ocfs2_refcount_cow(inode, di_bh,
> + refcounted_cpos, cow_len);
> + if (ret) {
> + mlog_errno(ret);
> + goto out;
> + }
> +
> + /* reinitialize write_desc and populate it again. */
> + ocfs2_clear_write_desc(wc);
> + ret = ocfs2_populate_write_desc(inode, wc, &clusters_to_alloc,
> + &extents_to_split,
> + &refcounted_cpos);
> + if (ret) {
> + mlog_errno(ret);
> + goto out;
> + }
> +
> + BUG_ON(refcounted_cpos != UINT_MAX);
> + }
First see my comment on the ocfs2_refcount_cal_clusters() and a
possible short CoW.
Basically, ocfs2_refcount_cow() can do a short CoW in two
situations. First, the one I described about
ocfs2_refcount_cal_clusters(). The second is if the write wants to
cover three extents, the middle of which is not refcounted:
|--refcounted--|--not refcounted--]--refcounted--|
ocfs2_refcount_cal_cow_clusters() will be called on the first extent.
It will set up *cow_len to cover that first extent, but then it will hit
the second extent and break out. ocfs2_refcount_cow() will then replace
the first extent. We end up with:
|--not refcounted--|--not refcounted--]--refcounted--|
Now we call to ocfs2_prepare_write_desc() again. It will see
the first and second extents as not refcounted, but then it will hit
the third extent and return -ETXTBSY. refcounted_cpos will be set to
the third extent. Then in ocfs2_write_begin_nolock(), we'll hit:
BUG_ON(refcounted_cpos != UINT_MAX);
Am I missing something?
Joel
--
"Where are my angels?
Where's my golden one?
And where is my hope
Now that my heroes are gone?"
Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127
More information about the Ocfs2-devel
mailing list