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
Unified · Split
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/slab.h> |
| 8 | 8 | #include <linux/pagemap.h> |
| 9 | 9 | #include <linux/highmem.h> |
| 10 | +#include <linux/sched/mm.h> | |
| 10 | 11 | #include "ctree.h" |
| 11 | 12 | #include "disk-io.h" |
| 12 | 13 | #include "transaction.h" |
| @@ -427,9 +428,13 @@ blk_status_t btrfs_csum_one_bio(struct inode *inode, struct bio *bio, · 414 unmodified lines | ||
| 427 | 428 | unsigned long this_sum_bytes = 0; |
| 428 | 429 | int i; |
| 429 | 430 | u64 offset; |
| 431 | + unsigned nofs_flag; | |
| 432 | + | |
| 433 | + nofs_flag = memalloc_nofs_save(); | |
| 434 | + sums = kvzalloc(btrfs_ordered_sum_size(fs_info, bio->bi_iter.bi_size), | |
| 435 | + GFP_KERNEL); | |
| 436 | + memalloc_nofs_restore(nofs_flag); | |
| 430 | 437 | |
| 431 | − sums = kzalloc(btrfs_ordered_sum_size(fs_info, bio->bi_iter.bi_size), | |
| 432 | − GFP_NOFS); | |
| 433 | 438 | if (!sums) |
| 434 | 439 | return BLK_STS_RESOURCE; |
| 435 | 440 | |
| @@ -472,8 +477,10 @@ blk_status_t btrfs_csum_one_bio(struct inode *inode, struct bio *bio, · 36 unmodified lines | ||
| 472 | 477 | |
| 473 | 478 | bytes_left = bio->bi_iter.bi_size - total_bytes; |
| 474 | 479 | |
| 475 | − sums = kzalloc(btrfs_ordered_sum_size(fs_info, bytes_left), | |
| 476 | − GFP_NOFS); | |
| 480 | + nofs_flag = memalloc_nofs_save(); | |
| 481 | + sums = kvzalloc(btrfs_ordered_sum_size(fs_info, | |
| 482 | + bytes_left), GFP_KERNEL); | |
| 483 | + memalloc_nofs_restore(nofs_flag); | |
| 477 | 484 | BUG_ON(!sums); /* -ENOMEM */ |
| 478 | 485 | sums->len = bytes_left; |
| 479 | 486 | ordered = btrfs_lookup_ordered_extent(inode, |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <linux/slab.h> |
| 7 | 7 | #include <linux/blkdev.h> |
| 8 | 8 | #include <linux/writeback.h> |
| 9 | +#include <linux/sched/mm.h> | |
| 9 | 10 | #include "ctree.h" |
| 10 | 11 | #include "transaction.h" |
| 11 | 12 | #include "btrfs_inode.h" |
| @@ -442,7 +443,7 @@ void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) · 430 unmodified lines | ||
| 442 | 443 | cur = entry->list.next; |
| 443 | 444 | sum = list_entry(cur, struct btrfs_ordered_sum, list); |
| 444 | 445 | list_del(&sum->list); |
| 445 | − kfree(sum); | |
| 446 | + kvfree(sum); | |
| 446 | 447 | } |
| 447 | 448 | kmem_cache_free(btrfs_ordered_extent_cache, entry); |
| 448 | 449 | } |