All of lore.kernel.org
 help / color / mirror / Atom feed
* [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

* [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 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

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.