| From d707d31c972b657dfc2efefd0b99cc4e14223dab Mon Sep 17 00:00:00 2001 |
| From: Mingming Cao <cmm@us.ibm.com> |
| Date: Wed, 15 Oct 2008 22:04:01 -0700 |
| Subject: ext2: fix ext2 block reservation early ENOSPC issue |
| |
| From: Mingming Cao <cmm@us.ibm.com> |
| |
| commit d707d31c972b657dfc2efefd0b99cc4e14223dab upstream. |
| |
| We could run into ENOSPC error on ext2, even when there is free blocks on |
| the filesystem. |
| |
| The problem is triggered in the case the goal block group has 0 free |
| blocks , and the rest block groups are skipped due to the check of |
| "free_blocks < windowsz/2". Current code could fall back to non |
| reservation allocation to prevent early ENOSPC after examing all the block |
| groups with reservation on , but this code was bypassed if the reservation |
| window is turned off already, which is true in this case. |
| |
| This patch fixed two issues: |
| 1) We don't need to turn off block reservation if the goal block group has |
| 0 free blocks left and continue search for the rest of block groups. |
| |
| Current code the intention is to turn off the block reservation if the |
| goal allocation group has a few (some) free blocks left (not enough for |
| make the desired reservation window),to try to allocation in the goal |
| block group, to get better locality. But if the goal blocks have 0 free |
| blocks, it should leave the block reservation on, and continues search for |
| the next block groups,rather than turn off block reservation completely. |
| |
| 2) we don't need to check the window size if the block reservation is off. |
| |
| The problem was originally found and fixed in ext4. |
| |
| Signed-off-by: Mingming Cao <cmm@us.ibm.com> |
| Cc: Theodore Ts'o <tytso@mit.edu> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Willy Tarreau <w@1wt.eu> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| fs/ext2/balloc.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| --- a/fs/ext2/balloc.c |
| +++ b/fs/ext2/balloc.c |
| @@ -1295,6 +1295,7 @@ retry_alloc: |
| * turn off reservation for this allocation |
| */ |
| if (my_rsv && (free_blocks < windowsz) |
| + && (free_blocks > 0) |
| && (rsv_is_empty(&my_rsv->rsv_window))) |
| my_rsv = NULL; |
| |
| @@ -1332,7 +1333,7 @@ retry_alloc: |
| * free blocks is less than half of the reservation |
| * window size. |
| */ |
| - if (free_blocks <= (windowsz/2)) |
| + if (my_rsv && (free_blocks <= (windowsz/2))) |
| continue; |
| |
| brelse(bitmap_bh); |