* [Ocfs2-devel] Non-sparse write fix -v4 @ 2009-08-06 23:12 Sunil Mushran 2009-08-06 23:12 ` [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend Sunil Mushran 0 siblings, 1 reply; 7+ messages in thread From: Sunil Mushran @ 2009-08-06 23:12 UTC (permalink / raw) To: ocfs2-devel So the problem with the last patch was that it did not handle blocksize < pagesize. On a x86 box, with a 2K/4K file system, it was only initializing the first 2K block. This fixes it. Sunil ^ permalink raw reply [flat|nested] 7+ messages in thread
* [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend 2009-08-06 23:12 [Ocfs2-devel] Non-sparse write fix -v4 Sunil Mushran @ 2009-08-06 23:12 ` Sunil Mushran 2009-08-07 20:19 ` Joel Becker 0 siblings, 1 reply; 7+ messages in thread From: Sunil Mushran @ 2009-08-06 23:12 UTC (permalink / raw) To: ocfs2-devel In a non-sparse extend, we correctly allocate (and zero) the clusters between the old_i_size and pos, but we don't zero the portions of the cluster we're writing to outside of pos<->len. It handles clustersize > pagesize and blocksize < pagesize. [Cleaned up by Joel Becker.] Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com> --- fs/ocfs2/aops.c | 65 +++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 47 insertions(+), 18 deletions(-) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index b745ad0..f896ea2 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -922,18 +922,17 @@ struct ocfs2_write_cluster_desc { */ unsigned c_new; unsigned c_unwritten; + unsigned c_needs_zero; }; -static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d) -{ - return d->c_new || d->c_unwritten; -} - struct ocfs2_write_ctxt { /* Logical cluster position / len of write */ u32 w_cpos; u32 w_clen; + /* First cluster allocated in a nonsparse extend */ + u32 w_first_new_cpos; + struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE]; /* @@ -1011,6 +1010,7 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp, return -ENOMEM; wc->w_cpos = pos >> osb->s_clustersize_bits; + wc->w_first_new_cpos = UINT_MAX; cend = (pos + len - 1) >> osb->s_clustersize_bits; wc->w_clen = cend - wc->w_cpos + 1; get_bh(di_bh); @@ -1248,18 +1248,17 @@ out: */ static int ocfs2_write_cluster(struct address_space *mapping, u32 phys, unsigned int unwritten, + unsigned int should_zero, struct ocfs2_alloc_context *data_ac, struct ocfs2_alloc_context *meta_ac, struct ocfs2_write_ctxt *wc, u32 cpos, loff_t user_pos, unsigned user_len) { - int ret, i, new, should_zero = 0; + int ret, i, new; u64 v_blkno, p_blkno; struct inode *inode = mapping->host; new = phys == 0 ? 1 : 0; - if (new || unwritten) - should_zero = 1; if (new) { u32 tmp_pos; @@ -1370,7 +1369,9 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping, local_len = osb->s_clustersize - cluster_off; ret = ocfs2_write_cluster(mapping, desc->c_phys, - desc->c_unwritten, data_ac, meta_ac, + desc->c_unwritten, + desc->c_needs_zero, + data_ac, meta_ac, wc, desc->c_cpos, pos, local_len); if (ret) { mlog_errno(ret); @@ -1420,14 +1421,14 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb, * newly allocated cluster. */ desc = &wc->w_desc[0]; - if (ocfs2_should_zero_cluster(desc)) + if (desc->c_needs_zero) ocfs2_figure_cluster_boundaries(osb, desc->c_cpos, &wc->w_target_from, NULL); desc = &wc->w_desc[wc->w_clen - 1]; - if (ocfs2_should_zero_cluster(desc)) + if (desc->c_needs_zero) ocfs2_figure_cluster_boundaries(osb, desc->c_cpos, NULL, @@ -1495,13 +1496,28 @@ static int ocfs2_populate_write_desc(struct inode *inode, phys++; } + /* + * If w_first_new_cpos is < UINT_MAX, we have a non-sparse + * file that got extended. w_first_new_cpos tells us + * where the newly allocated clusters are so we can + * zero them. + */ + if (desc->c_cpos >= wc->w_first_new_cpos) { + BUG_ON(phys == 0); + desc->c_needs_zero = 1; + } + desc->c_phys = phys; if (phys == 0) { desc->c_new = 1; + desc->c_needs_zero = 1; *clusters_to_alloc = *clusters_to_alloc + 1; } - if (ext_flags & OCFS2_EXT_UNWRITTEN) + + if (ext_flags & OCFS2_EXT_UNWRITTEN) { desc->c_unwritten = 1; + desc->c_needs_zero = 1; + } num_clusters--; } @@ -1658,10 +1674,13 @@ static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos, if (newsize <= i_size_read(inode)) return 0; - ret = ocfs2_extend_no_holes(inode, newsize, newsize - len); + ret = ocfs2_extend_no_holes(inode, newsize, pos); if (ret) mlog_errno(ret); + wc->w_first_new_cpos = + ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode)); + return ret; } @@ -1670,7 +1689,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, struct page **pagep, void **fsdata, struct buffer_head *di_bh, struct page *mmap_page) { - int ret, credits = OCFS2_INODE_UPDATE_CREDITS; + int ret, cluster_of_pages, credits = OCFS2_INODE_UPDATE_CREDITS; unsigned int clusters_to_alloc, extents_to_split; struct ocfs2_write_ctxt *wc; struct inode *inode = mapping->host; @@ -1738,8 +1757,19 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, } - ocfs2_set_target_boundaries(osb, wc, pos, len, - clusters_to_alloc + extents_to_split); + /* + * We have to zero sparse allocated clusters, unwritten extent clusters, + * and non-sparse clusters we just extended. For non-sparse writes, + * we know zeros will only be needed in the first and/or last cluster. + */ + if (clusters_to_alloc || extents_to_split || + wc->w_desc[0].c_needs_zero || + wc->w_desc[wc->w_clen - 1].c_needs_zero) + cluster_of_pages = 1; + else + cluster_of_pages = 0; + + ocfs2_set_target_boundaries(osb, wc, pos, len, cluster_of_pages); handle = ocfs2_start_trans(osb, credits); if (IS_ERR(handle)) { @@ -1767,8 +1797,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, * extent. */ ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, - clusters_to_alloc + extents_to_split, - mmap_page); + cluster_of_pages, mmap_page); if (ret) { mlog_errno(ret); goto out_commit; -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend 2009-08-06 23:12 ` [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend Sunil Mushran @ 2009-08-07 20:19 ` Joel Becker 0 siblings, 0 replies; 7+ messages in thread From: Joel Becker @ 2009-08-07 20:19 UTC (permalink / raw) To: ocfs2-devel On Thu, Aug 06, 2009 at 04:12:58PM -0700, Sunil Mushran wrote: > In a non-sparse extend, we correctly allocate (and zero) the clusters between > the old_i_size and pos, but we don't zero the portions of the cluster we're > writing to outside of pos<->len. > > It handles clustersize > pagesize and blocksize < pagesize. > > [Cleaned up by Joel Becker.] > > Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com> This is now in the fixes branch of ocfs2.git. Joel -- "Born under a bad sign. I been down since I began to crawl. If it wasn't for bad luck, I wouldn't have no luck at all." Joel Becker Principal Software Developer Oracle E-mail: joel.becker at oracle.com Phone: (650) 506-8127 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [Ocfs2-devel] Non sparse init fix v3 @ 2009-08-03 18:13 Sunil Mushran 2009-08-03 18:13 ` [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend Sunil Mushran 0 siblings, 1 reply; 7+ messages in thread From: Sunil Mushran @ 2009-08-03 18:13 UTC (permalink / raw) To: ocfs2-devel One line fix from Joel's version. Also, some comments removed. 18:58 <sunil> wc->w_first_new_cpos = 18:58 <sunil> - ocfs2_align_bytes_to_clusters(inode->i_sb, i_size_read(inode)); 18:58 <sunil> + ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode)); ^ permalink raw reply [flat|nested] 7+ messages in thread
* [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend 2009-08-03 18:13 [Ocfs2-devel] Non sparse init fix v3 Sunil Mushran @ 2009-08-03 18:13 ` Sunil Mushran 2009-08-03 21:15 ` Mark Fasheh 0 siblings, 1 reply; 7+ messages in thread From: Sunil Mushran @ 2009-08-03 18:13 UTC (permalink / raw) To: ocfs2-devel In a non-sparse extend, we correctly allocate (and zero) the clusters between the old_i_size and pos, but we don't zero the portions of the cluster we're writing to outside of pos<->len. [Cleaned up by Joel Becker.] Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com> --- fs/ocfs2/aops.c | 54 +++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 41 insertions(+), 13 deletions(-) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index b745ad0..4d9881c 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -922,18 +922,17 @@ struct ocfs2_write_cluster_desc { */ unsigned c_new; unsigned c_unwritten; + unsigned c_needs_zero; }; -static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d) -{ - return d->c_new || d->c_unwritten; -} - struct ocfs2_write_ctxt { /* Logical cluster position / len of write */ u32 w_cpos; u32 w_clen; + /* First cluster allocated in a nonsparse extend */ + u32 w_first_new_cpos; + struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE]; /* @@ -1011,6 +1010,7 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp, return -ENOMEM; wc->w_cpos = pos >> osb->s_clustersize_bits; + wc->w_first_new_cpos = UINT_MAX; cend = (pos + len - 1) >> osb->s_clustersize_bits; wc->w_clen = cend - wc->w_cpos + 1; get_bh(di_bh); @@ -1248,18 +1248,17 @@ out: */ static int ocfs2_write_cluster(struct address_space *mapping, u32 phys, unsigned int unwritten, + unsigned int should_zero, struct ocfs2_alloc_context *data_ac, struct ocfs2_alloc_context *meta_ac, struct ocfs2_write_ctxt *wc, u32 cpos, loff_t user_pos, unsigned user_len) { - int ret, i, new, should_zero = 0; + int ret, i, new; u64 v_blkno, p_blkno; struct inode *inode = mapping->host; new = phys == 0 ? 1 : 0; - if (new || unwritten) - should_zero = 1; if (new) { u32 tmp_pos; @@ -1370,7 +1369,9 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping, local_len = osb->s_clustersize - cluster_off; ret = ocfs2_write_cluster(mapping, desc->c_phys, - desc->c_unwritten, data_ac, meta_ac, + desc->c_unwritten, + desc->c_needs_zero, + data_ac, meta_ac, wc, desc->c_cpos, pos, local_len); if (ret) { mlog_errno(ret); @@ -1420,14 +1421,14 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb, * newly allocated cluster. */ desc = &wc->w_desc[0]; - if (ocfs2_should_zero_cluster(desc)) + if (desc->c_needs_zero) ocfs2_figure_cluster_boundaries(osb, desc->c_cpos, &wc->w_target_from, NULL); desc = &wc->w_desc[wc->w_clen - 1]; - if (ocfs2_should_zero_cluster(desc)) + if (desc->c_needs_zero) ocfs2_figure_cluster_boundaries(osb, desc->c_cpos, NULL, @@ -1495,17 +1496,41 @@ static int ocfs2_populate_write_desc(struct inode *inode, phys++; } + /* + * If w_first_new_cpos is < UINT_MAX, we have a non-sparse + * file that got extended. w_first_new_cpos tells us + * where the newly allocated clusters are so we can + * zero them. + */ + if (desc->c_cpos >= wc->w_first_new_cpos) { + BUG_ON(phys == 0); + desc->c_needs_zero = 1; + } desc->c_phys = phys; if (phys == 0) { desc->c_new = 1; + desc->c_needs_zero = 1; *clusters_to_alloc = *clusters_to_alloc + 1; } - if (ext_flags & OCFS2_EXT_UNWRITTEN) + if (ext_flags & OCFS2_EXT_UNWRITTEN) { desc->c_unwritten = 1; + desc->c_needs_zero = 1; + } num_clusters--; } + mlog(0, "inode %llu, wc 0x%p, cpos %u, clen %u, fcpos %u\n", + OCFS2_I(inode)->ip_blkno, wc, wc->w_cpos, wc->w_clen, + wc->w_first_new_cpos); + + for (i = 0; i < wc->w_clen; i++) { + desc = &wc->w_desc[i]; + mlog(0, "%d => cpos %u, phys %u, new %u, unw %u, zero %u\n", + i, desc->c_cpos, desc->c_phys, desc->c_new, + desc->c_unwritten, desc->c_needs_zero); + } + ret = 0; out: return ret; @@ -1658,10 +1683,13 @@ static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos, if (newsize <= i_size_read(inode)) return 0; - ret = ocfs2_extend_no_holes(inode, newsize, newsize - len); + ret = ocfs2_extend_no_holes(inode, newsize, pos); if (ret) mlog_errno(ret); + wc->w_first_new_cpos = + ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode)); + return ret; } -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend 2009-08-03 18:13 ` [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend Sunil Mushran @ 2009-08-03 21:15 ` Mark Fasheh 0 siblings, 0 replies; 7+ messages in thread From: Mark Fasheh @ 2009-08-03 21:15 UTC (permalink / raw) To: ocfs2-devel On Mon, Aug 03, 2009 at 11:13:29AM -0700, Sunil Mushran wrote: > In a non-sparse extend, we correctly allocate (and zero) the clusters between > the old_i_size and pos, but we don't zero the portions of the cluster we're > writing to outside of pos<->len. > > [Cleaned up by Joel Becker.] > > Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com> Looks reasonable to me... Acked-by: Mark Fasheh <mfasheh@suse.com> -- Mark Fasheh ^ permalink raw reply [flat|nested] 7+ messages in thread
* [Ocfs2-devel] Non sparse extend init issue @ 2009-08-02 20:04 Sunil Mushran 2009-08-02 20:04 ` [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend Sunil Mushran 0 siblings, 1 reply; 7+ messages in thread From: Sunil Mushran @ 2009-08-02 20:04 UTC (permalink / raw) To: ocfs2-devel The patch was created against a 1.4 tree. However, it applies cleanly to mainline too. The patch has been lightly tested. I am running fill_verify_holes on a non sparse volume currently. Please review. Sunil ^ permalink raw reply [flat|nested] 7+ messages in thread
* [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend 2009-08-02 20:04 [Ocfs2-devel] Non sparse extend init issue Sunil Mushran @ 2009-08-02 20:04 ` Sunil Mushran 2009-08-02 22:05 ` Joel Becker 0 siblings, 1 reply; 7+ messages in thread From: Sunil Mushran @ 2009-08-02 20:04 UTC (permalink / raw) To: ocfs2-devel In a non-sparse extend, we correctly allocate (and zero) the clusters between the old_i_size and pos, but we don't zero the portions of the cluster we're writing to outside of pos<->len. Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com> --- fs/ocfs2/aops.c | 42 ++++++++++++++++++++++++++++++++++++------ 1 files changed, 36 insertions(+), 6 deletions(-) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index b745ad0..8b1498e 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -920,13 +920,14 @@ struct ocfs2_write_cluster_desc { * Give this a unique field because c_phys eventually gets * filled. */ - unsigned c_new; - unsigned c_unwritten; + unsigned c_new; /* needs to be allocated */ + unsigned c_unwritten; /* unwritten extent */ + unsigned c_needs_zero; /* nonsparse allocation */ }; static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d) { - return d->c_new || d->c_unwritten; + return d->c_new || d->c_unwritten || d->c_needs_zero; } struct ocfs2_write_ctxt { @@ -934,6 +935,8 @@ struct ocfs2_write_ctxt { u32 w_cpos; u32 w_clen; + u32 w_first_new_cpos; + struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE]; /* @@ -1011,6 +1014,7 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp, return -ENOMEM; wc->w_cpos = pos >> osb->s_clustersize_bits; + wc->w_first_new_cpos = UINT_MAX; cend = (pos + len - 1) >> osb->s_clustersize_bits; wc->w_clen = cend - wc->w_cpos + 1; get_bh(di_bh); @@ -1248,6 +1252,7 @@ out: */ static int ocfs2_write_cluster(struct address_space *mapping, u32 phys, unsigned int unwritten, + unsigned int zero_it, struct ocfs2_alloc_context *data_ac, struct ocfs2_alloc_context *meta_ac, struct ocfs2_write_ctxt *wc, u32 cpos, @@ -1258,7 +1263,7 @@ static int ocfs2_write_cluster(struct address_space *mapping, struct inode *inode = mapping->host; new = phys == 0 ? 1 : 0; - if (new || unwritten) + if (new || unwritten || zero_it) should_zero = 1; if (new) { @@ -1370,7 +1375,9 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping, local_len = osb->s_clustersize - cluster_off; ret = ocfs2_write_cluster(mapping, desc->c_phys, - desc->c_unwritten, data_ac, meta_ac, + desc->c_unwritten, + desc->c_needs_zero, + data_ac, meta_ac, wc, desc->c_cpos, pos, local_len); if (ret) { mlog_errno(ret); @@ -1495,6 +1502,12 @@ static int ocfs2_populate_write_desc(struct inode *inode, phys++; } + desc->c_needs_zero = 0; + if (desc->c_cpos == wc->w_first_new_cpos) { + BUG_ON(phys == 0); + desc->c_needs_zero = 1; + } + desc->c_phys = phys; if (phys == 0) { desc->c_new = 1; @@ -1506,6 +1519,20 @@ static int ocfs2_populate_write_desc(struct inode *inode, num_clusters--; } + if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb) + wc->w_desc[wc->w_clen - 1].c_needs_zero = 1; + + mlog(0, "inode %llu, wc 0x%p, cpos %lu, clen %lu, fcpos %lu\n", + OCFS2_I(inode)->ip_blkno, wc, wc->w_cpos, wc->w_clen, + wc->w_first_new_cpos); + + for (i = 0; i < wc->w_clen; i++) { + desc = &wc->w_desc[i]; + mlog(0, ("%d => cpos %lu, phys %lu, new %u, unw %u, zero %u\n", + i, desc->c_cpos, desc->c_phys, desc->c_new, + desc->c_unwritten, desc->c_needs_zero); + } + ret = 0; out: return ret; @@ -1658,10 +1685,13 @@ static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos, if (newsize <= i_size_read(inode)) return 0; - ret = ocfs2_extend_no_holes(inode, newsize, newsize - len); + ret = ocfs2_extend_no_holes(inode, newsize, pos); if (ret) mlog_errno(ret); + wc->w_first_new_cpos = + ocfs2_align_bytes_to_clusters(inode->i_sb, i_size_read(inode)); + return ret; } -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend 2009-08-02 20:04 ` [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend Sunil Mushran @ 2009-08-02 22:05 ` Joel Becker 0 siblings, 0 replies; 7+ messages in thread From: Joel Becker @ 2009-08-02 22:05 UTC (permalink / raw) To: ocfs2-devel On Sun, Aug 02, 2009 at 01:04:10PM -0700, Sunil Mushran wrote: > In a non-sparse extend, we correctly allocate (and zero) the clusters between > the old_i_size and pos, but we don't zero the portions of the cluster we're > writing to outside of pos<->len. I'd do it more like this. Rather than have magic based on c_new, c_unwritten, and c_needs_zero_but_is_only_set_for_nonsparse, let's set c_needs_zero for all types that need zeroing. Then we can just trust c_needs_zero everywhere. I saw your attempt at optimization, setting c_needs_zero on only the first and last cluster of a non-sparse write, but it's not necessary. ocfs2_write_cluster() will figure out that user_pos and user_len cover the entire cluster. Joel diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index e511df1..8b853e5 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -893,20 +893,18 @@ struct ocfs2_write_cluster_desc { * Give this a unique field because c_phys eventually gets * filled. */ - unsigned c_new; - unsigned c_unwritten; + unsigned c_new; /* needs to be allocated */ + unsigned c_unwritten; /* unwritten extent */ + unsigned c_needs_zero; /* nonsparse allocation */ }; -static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d) -{ - return d->c_new || d->c_unwritten; -} - struct ocfs2_write_ctxt { /* Logical cluster position / len of write */ u32 w_cpos; u32 w_clen; + u32 w_first_new_cpos; + struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE]; /* @@ -984,6 +982,7 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp, return -ENOMEM; wc->w_cpos = pos >> osb->s_clustersize_bits; + wc->w_first_new_cpos = UINT_MAX; cend = (pos + len - 1) >> osb->s_clustersize_bits; wc->w_clen = cend - wc->w_cpos + 1; get_bh(di_bh); @@ -1218,19 +1217,18 @@ out: */ static int ocfs2_write_cluster(struct address_space *mapping, u32 phys, unsigned int unwritten, + unsigned int should_zero, struct ocfs2_alloc_context *data_ac, struct ocfs2_alloc_context *meta_ac, struct ocfs2_write_ctxt *wc, u32 cpos, loff_t user_pos, unsigned user_len) { - int ret, i, new, should_zero = 0; + int ret, i, new; u64 v_blkno, p_blkno; struct inode *inode = mapping->host; struct ocfs2_extent_tree et; new = phys == 0 ? 1 : 0; - if (new || unwritten) - should_zero = 1; if (new) { u32 tmp_pos; @@ -1342,7 +1340,9 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping, local_len = osb->s_clustersize - cluster_off; ret = ocfs2_write_cluster(mapping, desc->c_phys, - desc->c_unwritten, data_ac, meta_ac, + desc->c_unwritten, + desc->c_needs_zero, + data_ac, meta_ac, wc, desc->c_cpos, pos, local_len); if (ret) { mlog_errno(ret); @@ -1392,14 +1392,14 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb, * newly allocated cluster. */ desc = &wc->w_desc[0]; - if (ocfs2_should_zero_cluster(desc)) + if (desc->c_needs_zero) ocfs2_figure_cluster_boundaries(osb, desc->c_cpos, &wc->w_target_from, NULL); desc = &wc->w_desc[wc->w_clen - 1]; - if (ocfs2_should_zero_cluster(desc)) + if (desc->c_needs_zero) ocfs2_figure_cluster_boundaries(osb, desc->c_cpos, NULL, @@ -1467,17 +1467,41 @@ static int ocfs2_populate_write_desc(struct inode *inode, phys++; } + /* + * If w_first_new_cpos is < UINT_MAX, we have a non-sparse + * file that got extended. w_first_new_cpos tells us + * where the newly allocated clusters are so we can + * zero them. + */ + if (desc->c_cpos >= wc->w_first_new_cpos) { + BUG_ON(phys == 0); + desc->c_needs_zero = 1; + } desc->c_phys = phys; if (phys == 0) { desc->c_new = 1; + desc->c_needs_zero = 1; *clusters_to_alloc = *clusters_to_alloc + 1; } - if (ext_flags & OCFS2_EXT_UNWRITTEN) + if (ext_flags & OCFS2_EXT_UNWRITTEN) { desc->c_unwritten = 1; + desc->c_needs_zero = 1; + } num_clusters--; } + mlog(0, "inode %llu, wc 0x%p, cpos %u, clen %u, fcpos %u\n", + OCFS2_I(inode)->ip_blkno, wc, wc->w_cpos, wc->w_clen, + wc->w_first_new_cpos); + + for (i = 0; i < wc->w_clen; i++) { + desc = &wc->w_desc[i]; + mlog(0, "%d => cpos %u, phys %u, new %u, unw %u, zero %u\n", + i, desc->c_cpos, desc->c_phys, desc->c_new, + desc->c_unwritten, desc->c_needs_zero); + } + ret = 0; out: return ret; @@ -1633,10 +1657,13 @@ static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos, if (newsize <= i_size_read(inode)) return 0; - ret = ocfs2_extend_no_holes(inode, newsize, newsize - len); + ret = ocfs2_extend_no_holes(inode, newsize, pos); if (ret) mlog_errno(ret); + wc->w_first_new_cpos = + ocfs2_align_bytes_to_clusters(inode->i_sb, i_size_read(inode)); + return ret; } -- #!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj $/=unpack('H*',$_);$_=`echo 16dio\U$k"SK$/SM$n\EsN0p[lN*1 lK[d2%Sa2/d0$^Ixp"|dc`;s/\W//g;$_=pack('H*',/((..)*)$/) Joel Becker Principal Software Developer Oracle E-mail: joel.becker@oracle.com Phone: (650) 506-8127 ^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-08-07 20:19 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-08-06 23:12 [Ocfs2-devel] Non-sparse write fix -v4 Sunil Mushran 2009-08-06 23:12 ` [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend Sunil Mushran 2009-08-07 20:19 ` Joel Becker -- strict thread matches above, loose matches on Subject: below -- 2009-08-03 18:13 [Ocfs2-devel] Non sparse init fix v3 Sunil Mushran 2009-08-03 18:13 ` [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend Sunil Mushran 2009-08-03 21:15 ` Mark Fasheh 2009-08-02 20:04 [Ocfs2-devel] Non sparse extend init issue Sunil Mushran 2009-08-02 20:04 ` [Ocfs2-devel] [PATCH 1/1] ocfs2: Initialize the cluster we're writing to in a non-sparse extend Sunil Mushran 2009-08-02 22:05 ` Joel Becker
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.