linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH]ext4: fix s_dirty_blocks_counter if block allocation failed with nodelalloc
@ 2008-12-01 10:21 Akira Fujita
  2008-12-01 10:36 ` Aneesh Kumar K.V
  0 siblings, 1 reply; 8+ messages in thread
From: Akira Fujita @ 2008-12-01 10:21 UTC (permalink / raw)
  To: Theodore Tso; +Cc: Li Zefan, linux-ext4

ext4: Fix s_dirty_blocks_counter if block allocation failed with nodelalloc

From: Akira Fujita <a-fujita@rs.jp.nec.com>

If block allocation failed after marking claimed blocks as dirty blocks
with nodelalloc, we have to subtract these blocks from
s_dirty_blocks_counter in error handling.
Otherwise s_dirty_blocks_counter goes wrong so that
filesystem's free blocks decreases incorrectly.

This issue was reported as ext4 online defrag's bug by Li Zefan.
http://marc.info/?l=linux-ext4&m=122697235715170&w=2

Reported-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: Akira Fujita <a-fujita@rs.jp.nec.com>
---
 mballoc.c |    9 +++++++++
 1 file changed, 9 insertions(+)
diff -X linux-2.6.28-rc6-ext4/Documentation/dontdiff -upNr linux-2.6.28-rc6-ext4/fs/ext4/mballoc.c linux-2.6.28-rc6-mballoc-fix/fs/ext4/mballoc.c
--- linux-2.6.28-rc6-ext4/fs/ext4/mballoc.c	2008-12-01 11:44:28.000000000 +0900
+++ linux-2.6.28-rc6-mballoc-fix/fs/ext4/mballoc.c	2008-12-01 12:04:06.000000000 +0900
@@ -4495,12 +4495,18 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t
 	if (!ac) {
 		ar->len = 0;
 		*errp = -ENOMEM;
+		if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED))
+			percpu_counter_sub(&sbi->s_dirtyblocks_counter,
+						reserv_blks);
 		goto out1;
 	}

 	*errp = ext4_mb_initialize_context(ac, ar);
 	if (*errp) {
 		ar->len = 0;
+		if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED))
+			percpu_counter_sub(&sbi->s_dirtyblocks_counter,
+						reserv_blks);
 		goto out2;
 	}

@@ -4541,6 +4547,9 @@ repeat:
 		if (freed)
 			goto repeat;
 		*errp = -ENOSPC;
+		if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED))
+			percpu_counter_sub(&sbi->s_dirtyblocks_counter,
+						reserv_blks);
 		ac->ac_b_ex.fe_len = 0;
 		ar->len = 0;
 		ext4_mb_show_ac(ac);


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH]ext4: fix s_dirty_blocks_counter if block allocation failed with nodelalloc
  2008-12-01 10:21 [PATCH]ext4: fix s_dirty_blocks_counter if block allocation failed with nodelalloc Akira Fujita
@ 2008-12-01 10:36 ` Aneesh Kumar K.V
  2008-12-04  1:27   ` Akira Fujita
  0 siblings, 1 reply; 8+ messages in thread
From: Aneesh Kumar K.V @ 2008-12-01 10:36 UTC (permalink / raw)
  To: Akira Fujita; +Cc: Theodore Tso, Li Zefan, linux-ext4

On Mon, Dec 01, 2008 at 07:21:54PM +0900, Akira Fujita wrote:
> ext4: Fix s_dirty_blocks_counter if block allocation failed with nodelalloc
> 
> From: Akira Fujita <a-fujita@rs.jp.nec.com>
> 
> If block allocation failed after marking claimed blocks as dirty blocks
> with nodelalloc, we have to subtract these blocks from
> s_dirty_blocks_counter in error handling.
> Otherwise s_dirty_blocks_counter goes wrong so that
> filesystem's free blocks decreases incorrectly.

Why did the block allocation fail ? With delayed allocation ENOSPC
should not happen during block allocation. That would mean we did
something wrong in block reservation.

> 
> This issue was reported as ext4 online defrag's bug by Li Zefan.
> http://marc.info/?l=linux-ext4&m=122697235715170&w=2

-aneesh

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH]ext4: fix s_dirty_blocks_counter if block allocation failed with nodelalloc
  2008-12-01 10:36 ` Aneesh Kumar K.V
@ 2008-12-04  1:27   ` Akira Fujita
  2008-12-04  5:07     ` Aneesh Kumar K.V
  0 siblings, 1 reply; 8+ messages in thread
From: Akira Fujita @ 2008-12-04  1:27 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: Theodore Tso, Li Zefan, linux-ext4


Hi Aneesh,
Aneesh Kumar K.V wrote:
> On Mon, Dec 01, 2008 at 07:21:54PM +0900, Akira Fujita wrote:
>> ext4: Fix s_dirty_blocks_counter if block allocation failed with nodelalloc
>>
>> From: Akira Fujita <a-fujita@rs.jp.nec.com>
>>
>> If block allocation failed after marking claimed blocks as dirty blocks
>> with nodelalloc, we have to subtract these blocks from
>> s_dirty_blocks_counter in error handling.
>> Otherwise s_dirty_blocks_counter goes wrong so that
>> filesystem's free blocks decreases incorrectly.
> 
> Why did the block allocation fail ? With delayed allocation ENOSPC
> should not happen during block allocation. That would mean we did
> something wrong in block reservation.

My case was *nodelalloc* and FS was almost full.
This problem occurs in multiple defrag running in short time.
Usually defrag releases temporary inode's blocks with iput,
then FS free blocks are recover but contiguous blocks do not recover
until next journal commit.
so we can not re-use contiguous blocks immediately.
There are enough free blocks in FS so that
ext4_claim_free_blocks marks claimed blocks as dirty,
but ext4_regular_allocator can not find enough blocks,
so mb_new_blocks returns ENOSPC without decreasing dirty blocks.

Regards,
Akira Fujita


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH]ext4: fix s_dirty_blocks_counter if block allocation failed with nodelalloc
  2008-12-04  1:27   ` Akira Fujita
@ 2008-12-04  5:07     ` Aneesh Kumar K.V
  2008-12-04  8:32       ` Akira Fujita
  0 siblings, 1 reply; 8+ messages in thread
From: Aneesh Kumar K.V @ 2008-12-04  5:07 UTC (permalink / raw)
  To: Akira Fujita; +Cc: Theodore Tso, Li Zefan, linux-ext4

On Thu, Dec 04, 2008 at 10:27:25AM +0900, Akira Fujita wrote:
>
> Hi Aneesh,
> Aneesh Kumar K.V wrote:
>> On Mon, Dec 01, 2008 at 07:21:54PM +0900, Akira Fujita wrote:
>>> ext4: Fix s_dirty_blocks_counter if block allocation failed with nodelalloc
>>>
>>> From: Akira Fujita <a-fujita@rs.jp.nec.com>
>>>
>>> If block allocation failed after marking claimed blocks as dirty blocks
>>> with nodelalloc, we have to subtract these blocks from
>>> s_dirty_blocks_counter in error handling.
>>> Otherwise s_dirty_blocks_counter goes wrong so that
>>> filesystem's free blocks decreases incorrectly.
>>
>> Why did the block allocation fail ? With delayed allocation ENOSPC
>> should not happen during block allocation. That would mean we did
>> something wrong in block reservation.
>
> My case was *nodelalloc* and FS was almost full.
> This problem occurs in multiple defrag running in short time.
> Usually defrag releases temporary inode's blocks with iput,
> then FS free blocks are recover but contiguous blocks do not recover
> until next journal commit.
> so we can not re-use contiguous blocks immediately.
> There are enough free blocks in FS so that
> ext4_claim_free_blocks marks claimed blocks as dirty,
> but ext4_regular_allocator can not find enough blocks,
> so mb_new_blocks returns ENOSPC without decreasing dirty blocks.
>
ok how about doing the check once in ext4_mb_new_blocks.

diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index bacc2f4..22d31c3 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -4550,7 +4550,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
 	}
 	if (ar->len == 0) {
 		*errp = -EDQUOT;
-		return 0;
+		goto out3;
 	}
 	inquota = ar->len;
 
@@ -4623,6 +4623,13 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
 out1:
 	if (ar->len < inquota)
 		DQUOT_FREE_BLOCK(ar->inode, inquota - ar->len);
+out3:
+	if (!ar->len) {
+		if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag)
+			/* release all the reserved blocks if non delalloc */
+			percpu_counter_sub(&sbi->s_dirtyblocks_counter,
+						reserv_blks);
+	}
 
 	return block;
 }

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH]ext4: fix s_dirty_blocks_counter if block allocation failed with nodelalloc
  2008-12-04  5:07     ` Aneesh Kumar K.V
@ 2008-12-04  8:32       ` Akira Fujita
  2008-12-04  8:38         ` Li Zefan
  0 siblings, 1 reply; 8+ messages in thread
From: Akira Fujita @ 2008-12-04  8:32 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: Theodore Tso, Li Zefan, linux-ext4


Aneesh Kumar K.V wrote:
> On Thu, Dec 04, 2008 at 10:27:25AM +0900, Akira Fujita wrote:
>> Hi Aneesh,
>> Aneesh Kumar K.V wrote:
>>> On Mon, Dec 01, 2008 at 07:21:54PM +0900, Akira Fujita wrote:
>>>> ext4: Fix s_dirty_blocks_counter if block allocation failed with nodelalloc
>>>>
>>>> From: Akira Fujita <a-fujita@rs.jp.nec.com>
>>>>
>>>> If block allocation failed after marking claimed blocks as dirty blocks
>>>> with nodelalloc, we have to subtract these blocks from
>>>> s_dirty_blocks_counter in error handling.
>>>> Otherwise s_dirty_blocks_counter goes wrong so that
>>>> filesystem's free blocks decreases incorrectly.
>>> Why did the block allocation fail ? With delayed allocation ENOSPC
>>> should not happen during block allocation. That would mean we did
>>> something wrong in block reservation.
>> My case was *nodelalloc* and FS was almost full.
>> This problem occurs in multiple defrag running in short time.
>> Usually defrag releases temporary inode's blocks with iput,
>> then FS free blocks are recover but contiguous blocks do not recover
>> until next journal commit.
>> so we can not re-use contiguous blocks immediately.
>> There are enough free blocks in FS so that
>> ext4_claim_free_blocks marks claimed blocks as dirty,
>> but ext4_regular_allocator can not find enough blocks,
>> so mb_new_blocks returns ENOSPC without decreasing dirty blocks.
>>
> ok how about doing the check once in ext4_mb_new_blocks.

It works fine.  Thank you.
Tested-by: Akira Fujita <a-fujita@rs.jp.nec.com>

> diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
> index bacc2f4..22d31c3 100644
> --- a/fs/ext4/mballoc.c
> +++ b/fs/ext4/mballoc.c
> @@ -4550,7 +4550,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
>  	}
>  	if (ar->len == 0) {
>  		*errp = -EDQUOT;
> -		return 0;
> +		goto out3;
>  	}
>  	inquota = ar->len;
>  
> @@ -4623,6 +4623,13 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
>  out1:
>  	if (ar->len < inquota)
>  		DQUOT_FREE_BLOCK(ar->inode, inquota - ar->len);
> +out3:
> +	if (!ar->len) {
> +		if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag)
> +			/* release all the reserved blocks if non delalloc */
> +			percpu_counter_sub(&sbi->s_dirtyblocks_counter,
> +						reserv_blks);
> +	}
>  
>  	return block;
>  }

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH]ext4: fix s_dirty_blocks_counter if block allocation failed with nodelalloc
  2008-12-04  8:32       ` Akira Fujita
@ 2008-12-04  8:38         ` Li Zefan
  0 siblings, 0 replies; 8+ messages in thread
From: Li Zefan @ 2008-12-04  8:38 UTC (permalink / raw)
  To: Akira Fujita; +Cc: Aneesh Kumar K.V, Theodore Tso, linux-ext4

Akira Fujita wrote:
> 
> Aneesh Kumar K.V wrote:
>> On Thu, Dec 04, 2008 at 10:27:25AM +0900, Akira Fujita wrote:
>>> Hi Aneesh,
>>> Aneesh Kumar K.V wrote:
>>>> On Mon, Dec 01, 2008 at 07:21:54PM +0900, Akira Fujita wrote:
>>>>> ext4: Fix s_dirty_blocks_counter if block allocation failed with
>>>>> nodelalloc
>>>>>
>>>>> From: Akira Fujita <a-fujita@rs.jp.nec.com>
>>>>>
>>>>> If block allocation failed after marking claimed blocks as dirty
>>>>> blocks
>>>>> with nodelalloc, we have to subtract these blocks from
>>>>> s_dirty_blocks_counter in error handling.
>>>>> Otherwise s_dirty_blocks_counter goes wrong so that
>>>>> filesystem's free blocks decreases incorrectly.
>>>> Why did the block allocation fail ? With delayed allocation ENOSPC
>>>> should not happen during block allocation. That would mean we did
>>>> something wrong in block reservation.
>>> My case was *nodelalloc* and FS was almost full.
>>> This problem occurs in multiple defrag running in short time.
>>> Usually defrag releases temporary inode's blocks with iput,
>>> then FS free blocks are recover but contiguous blocks do not recover
>>> until next journal commit.
>>> so we can not re-use contiguous blocks immediately.
>>> There are enough free blocks in FS so that
>>> ext4_claim_free_blocks marks claimed blocks as dirty,
>>> but ext4_regular_allocator can not find enough blocks,
>>> so mb_new_blocks returns ENOSPC without decreasing dirty blocks.
>>>
>> ok how about doing the check once in ext4_mb_new_blocks.
> 
> It works fine.  Thank you.
> Tested-by: Akira Fujita <a-fujita@rs.jp.nec.com>
> 

I'll test it when I'm free and have access to the test machine. :)

But not this week..

>> diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
>> index bacc2f4..22d31c3 100644
>> --- a/fs/ext4/mballoc.c
>> +++ b/fs/ext4/mballoc.c
>> @@ -4550,7 +4550,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
>>      }
>>      if (ar->len == 0) {
>>          *errp = -EDQUOT;
>> -        return 0;
>> +        goto out3;
>>      }
>>      inquota = ar->len;
>>  
>> @@ -4623,6 +4623,13 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
>>  out1:
>>      if (ar->len < inquota)
>>          DQUOT_FREE_BLOCK(ar->inode, inquota - ar->len);
>> +out3:
>> +    if (!ar->len) {
>> +        if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag)
>> +            /* release all the reserved blocks if non delalloc */
>> +            percpu_counter_sub(&sbi->s_dirtyblocks_counter,
>> +                        reserv_blks);
>> +    }
>>  
>>      return block;
>>  }
> 
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] ext4: Fix s_dirty_blocks_counter if block allocation failed with nodelalloc
@ 2008-12-04 14:04 Aneesh Kumar K.V
  2008-12-04 18:19 ` Mingming Cao
  0 siblings, 1 reply; 8+ messages in thread
From: Aneesh Kumar K.V @ 2008-12-04 14:04 UTC (permalink / raw)
  To: cmm, tytso, sandeen; +Cc: linux-ext4, Aneesh Kumar K.V

With nodelalloc option we need to update the dirty block counter on
block allocation failure. This is needed because we increment the
dirty block counter early in the block allocation phase. Without
the patch s_dirty_blocks_counter goes wrong so that filesystem's
free blocks decreases incorrectly.

Tested-by: Akira Fujita <a-fujita@rs.jp.nec.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 fs/ext4/mballoc.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index bacc2f4..22d31c3 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -4550,7 +4550,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
 	}
 	if (ar->len == 0) {
 		*errp = -EDQUOT;
-		return 0;
+		goto out3;
 	}
 	inquota = ar->len;
 
@@ -4623,6 +4623,13 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
 out1:
 	if (ar->len < inquota)
 		DQUOT_FREE_BLOCK(ar->inode, inquota - ar->len);
+out3:
+	if (!ar->len) {
+		if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag)
+			/* release all the reserved blocks if non delalloc */
+			percpu_counter_sub(&sbi->s_dirtyblocks_counter,
+						reserv_blks);
+	}
 
 	return block;
 }
-- 
1.6.1.rc1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] ext4: Fix s_dirty_blocks_counter if block allocation failed with nodelalloc
  2008-12-04 14:04 [PATCH] ext4: Fix " Aneesh Kumar K.V
@ 2008-12-04 18:19 ` Mingming Cao
  0 siblings, 0 replies; 8+ messages in thread
From: Mingming Cao @ 2008-12-04 18:19 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: tytso, sandeen, linux-ext4


在 2008-12-04四的 19:34 +0530,Aneesh Kumar K.V写道:
> With nodelalloc option we need to update the dirty block counter on
> block allocation failure. This is needed because we increment the
> dirty block counter early in the block allocation phase. Without
> the patch s_dirty_blocks_counter goes wrong so that filesystem's
> free blocks decreases incorrectly.
> 

Reviewed by: Mingming Cao <cmm@us.ibm.com>

> Tested-by: Akira Fujita <a-fujita@rs.jp.nec.com>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> ---
>  fs/ext4/mballoc.c |    9 ++++++++-
>  1 files changed, 8 insertions(+), 1 deletions(-)
> 
> diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
> index bacc2f4..22d31c3 100644
> --- a/fs/ext4/mballoc.c
> +++ b/fs/ext4/mballoc.c
> @@ -4550,7 +4550,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
>  	}
>  	if (ar->len == 0) {
>  		*errp = -EDQUOT;
> -		return 0;
> +		goto out3;
>  	}
>  	inquota = ar->len;
> 
> @@ -4623,6 +4623,13 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
>  out1:
>  	if (ar->len < inquota)
>  		DQUOT_FREE_BLOCK(ar->inode, inquota - ar->len);
> +out3:
> +	if (!ar->len) {
> +		if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag)
> +			/* release all the reserved blocks if non delalloc */
> +			percpu_counter_sub(&sbi->s_dirtyblocks_counter,
> +						reserv_blks);
> +	}
> 
>  	return block;
>  }

--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2008-12-04 18:19 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-01 10:21 [PATCH]ext4: fix s_dirty_blocks_counter if block allocation failed with nodelalloc Akira Fujita
2008-12-01 10:36 ` Aneesh Kumar K.V
2008-12-04  1:27   ` Akira Fujita
2008-12-04  5:07     ` Aneesh Kumar K.V
2008-12-04  8:32       ` Akira Fujita
2008-12-04  8:38         ` Li Zefan
  -- strict thread matches above, loose matches on Subject: below --
2008-12-04 14:04 [PATCH] ext4: Fix " Aneesh Kumar K.V
2008-12-04 18:19 ` Mingming Cao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).