| From foo@baz Mon Nov 6 10:42:09 CET 2017 |
| From: Jan Kara <jack@suse.cz> |
| Date: Sat, 7 Oct 2017 22:37:59 +0000 |
| Subject: ext4: fix stripe-unaligned allocations |
| |
| From: Jan Kara <jack@suse.cz> |
| |
| |
| [ Upstream commit d9b22cf9f5466a057f2a4f1e642b469fa9d73117 ] |
| |
| When a filesystem is created using: |
| |
| mkfs.ext4 -b 4096 -E stride=512 <dev> |
| |
| and we try to allocate 64MB extent, we will end up directly in |
| ext4_mb_complex_scan_group(). This is because the request is detected |
| as power-of-two allocation (so we start in ext4_mb_regular_allocator() |
| with ac_criteria == 0) however the check before |
| ext4_mb_simple_scan_group() refuses the direct buddy scan because the |
| allocation request is too large. Since cr == 0, the check whether we |
| should use ext4_mb_scan_aligned() fails as well and we fall back to |
| ext4_mb_complex_scan_group(). |
| |
| Fix the problem by checking for upper limit on power-of-two requests |
| directly when detecting them. |
| |
| Reported-by: Ross Zwisler <ross.zwisler@linux.intel.com> |
| Signed-off-by: Jan Kara <jack@suse.cz> |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Signed-off-by: Sasha Levin <alexander.levin@verizon.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/ext4/mballoc.c | 6 ++++-- |
| 1 file changed, 4 insertions(+), 2 deletions(-) |
| |
| --- a/fs/ext4/mballoc.c |
| +++ b/fs/ext4/mballoc.c |
| @@ -2113,8 +2113,10 @@ ext4_mb_regular_allocator(struct ext4_al |
| * We search using buddy data only if the order of the request |
| * is greater than equal to the sbi_s_mb_order2_reqs |
| * You can tune it via /sys/fs/ext4/<partition>/mb_order2_req |
| + * We also support searching for power-of-two requests only for |
| + * requests upto maximum buddy size we have constructed. |
| */ |
| - if (i >= sbi->s_mb_order2_reqs) { |
| + if (i >= sbi->s_mb_order2_reqs && i <= sb->s_blocksize_bits + 2) { |
| /* |
| * This should tell if fe_len is exactly power of 2 |
| */ |
| @@ -2176,7 +2178,7 @@ repeat: |
| } |
| |
| ac->ac_groups_scanned++; |
| - if (cr == 0 && ac->ac_2order < sb->s_blocksize_bits+2) |
| + if (cr == 0) |
| ext4_mb_simple_scan_group(ac, &e4b); |
| else if (cr == 1 && sbi->s_stripe && |
| !(ac->ac_g_ex.fe_len % sbi->s_stripe)) |