diff options
author | Theodore Ts'o <tytso@mit.edu> | 2013-07-13 00:40:35 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-21 21:21:33 -0400 |
commit | 7557d8d5a46aaa4d0ec98bffdeedf9f3c7464088 (patch) | |
tree | 6606be5385d264bfb902f499c16540676dbba802 /fs/ext4 | |
parent | bbb1d9216c9d8f5ac0aca90719512deae7f989ea (diff) |
ext4: don't allow ext4_free_blocks() to fail due to ENOMEM
commit e7676a704ee0a1ef71a6b23760b5a8f6896cb1a1 upstream.
The filesystem should not be marked inconsistent if ext4_free_blocks()
is not able to allocate memory. Unfortunately some callers (most
notably ext4_truncate) don't have a way to reflect an error back up to
the VFS. And even if we did, most userspace applications won't deal
with most system calls returning ENOMEM anyway.
Reported-by: Nagachandra P <nagachandra@gmail.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/mballoc.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index def84082a9a9..59c6750b894f 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -4735,11 +4735,16 @@ do_more: | |||
4735 | * blocks being freed are metadata. these blocks shouldn't | 4735 | * blocks being freed are metadata. these blocks shouldn't |
4736 | * be used until this transaction is committed | 4736 | * be used until this transaction is committed |
4737 | */ | 4737 | */ |
4738 | retry: | ||
4738 | new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS); | 4739 | new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS); |
4739 | if (!new_entry) { | 4740 | if (!new_entry) { |
4740 | ext4_mb_unload_buddy(&e4b); | 4741 | /* |
4741 | err = -ENOMEM; | 4742 | * We use a retry loop because |
4742 | goto error_return; | 4743 | * ext4_free_blocks() is not allowed to fail. |
4744 | */ | ||
4745 | cond_resched(); | ||
4746 | congestion_wait(BLK_RW_ASYNC, HZ/50); | ||
4747 | goto retry; | ||
4743 | } | 4748 | } |
4744 | new_entry->efd_start_cluster = bit; | 4749 | new_entry->efd_start_cluster = bit; |
4745 | new_entry->efd_group = block_group; | 4750 | new_entry->efd_group = block_group; |