diff options
authorLinus Torvalds <torvalds@linux-foundation.org>2019-04-26 09:46:46 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2019-04-26 09:46:46 -0700
commitd0473f978e61557464daa8547008fa2cd0c63a17 (patch)
parent58130235bfcceb9198a3d979c91b04ea383a0fae (diff)
parenta3d46aea46f99d134b4e0726e4826b824c3e5980 (diff)
Merge tag 'for-5.1-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fix from David Sterba: "One patch to fix a crash in io submission path, due to memory allocation errors. In short, the multipage bio work that landed in 5.1 caused larger bios that in turn require larger temporary memory for checksums. The patch is a workaround, we're going to rework the allocation so it does not require the vmalloc fallback. It took a while to identify that it's caused by patches in 5.1 and not a patchset that did some changes in error handling in the code. I've tested it on various memory/cpu combinations, it could hit OOM but does not crash. The timestamp of the patch is less than a day due to updates in the changelog, tests were running meanwhile" * tag 'for-5.1-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: Switch memory allocations in async csum calculation path to kvmalloc
2 files changed, 13 insertions, 5 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index 920bf3b4b0ef..cccc75d15970 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -7,6 +7,7 @@
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
+#include <linux/sched/mm.h>
#include "ctree.h"
#include "disk-io.h"
#include "transaction.h"
@@ -427,9 +428,13 @@ blk_status_t btrfs_csum_one_bio(struct inode *inode, struct bio *bio,
unsigned long this_sum_bytes = 0;
int i;
u64 offset;
+ unsigned nofs_flag;
+ nofs_flag = memalloc_nofs_save();
+ sums = kvzalloc(btrfs_ordered_sum_size(fs_info, bio->bi_iter.bi_size),
+ memalloc_nofs_restore(nofs_flag);
- sums = kzalloc(btrfs_ordered_sum_size(fs_info, bio->bi_iter.bi_size),
if (!sums)
@@ -472,8 +477,10 @@ blk_status_t btrfs_csum_one_bio(struct inode *inode, struct bio *bio,
bytes_left = bio->bi_iter.bi_size - total_bytes;
- sums = kzalloc(btrfs_ordered_sum_size(fs_info, bytes_left),
+ nofs_flag = memalloc_nofs_save();
+ sums = kvzalloc(btrfs_ordered_sum_size(fs_info,
+ bytes_left), GFP_KERNEL);
+ memalloc_nofs_restore(nofs_flag);
BUG_ON(!sums); /* -ENOMEM */
sums->len = bytes_left;
ordered = btrfs_lookup_ordered_extent(inode,
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index 6fde2b2741ef..45e3cfd1198b 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -6,6 +6,7 @@
#include <linux/slab.h>
#include <linux/blkdev.h>
#include <linux/writeback.h>
+#include <linux/sched/mm.h>
#include "ctree.h"
#include "transaction.h"
#include "btrfs_inode.h"
@@ -442,7 +443,7 @@ void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry)
cur = entry->list.next;
sum = list_entry(cur, struct btrfs_ordered_sum, list);
- kfree(sum);
+ kvfree(sum);
kmem_cache_free(btrfs_ordered_extent_cache, entry);