History

btrfs: Use kvmalloc for allocating compressed path context

Recent refactoring of cow_file_range_async means it's now possible to request a rather large physically contiguous memory via kmalloc. The size is dependent on the number of 512k chunks that the compressed range consists of. David reported multiple OOM messages on such large allocations. Fix it by switching to using kvmalloc.

Nikolay Borisov committed 7 years ago

Commit b1c16ac1 parent 74475551 file · +7 −2Browse files

Unified · Split

fs/btrfs/inode.c+7−2
@@ -28,6 +28,7 @@ · 27 unmodified lines
28#include <linux/magic.h>28#include <linux/magic.h>
29#include <linux/iversion.h>29#include <linux/iversion.h>
30#include <linux/swap.h>30#include <linux/swap.h>
31#include <linux/sched/mm.h>
31#include <asm/unaligned.h>32#include <asm/unaligned.h>
32#include "ctree.h"33#include "ctree.h"
33#include "disk-io.h"34#include "disk-io.h"
@@ -1172,7 +1173,7 @@ static noinline void async_cow_free(struct btrfs_work *work) · 1138 unmodified lines
1172 * async_chunk's, freeing it ensures the whole array has been freed.1173 * async_chunk's, freeing it ensures the whole array has been freed.
1173 */1174 */
1174 if (atomic_dec_and_test(async_chunk->pending))1175 if (atomic_dec_and_test(async_chunk->pending))
1175 kfree(async_chunk->pending);1176 kvfree(async_chunk->pending);
1176}1177}
1177 1178
1178static int cow_file_range_async(struct inode *inode, struct page *locked_page,1179static int cow_file_range_async(struct inode *inode, struct page *locked_page,
@@ -1188,6 +1189,7 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page, · 9 unmodified lines
1188 u64 num_chunks = DIV_ROUND_UP(end - start, SZ_512K);1189 u64 num_chunks = DIV_ROUND_UP(end - start, SZ_512K);
1189 int i;1190 int i;
1190 bool should_compress;1191 bool should_compress;
1192 unsigned nofs_flag;
1191 1193
1192 unlock_extent(&BTRFS_I(inode)->io_tree, start, end);1194 unlock_extent(&BTRFS_I(inode)->io_tree, start, end);
1193 1195
@@ -1199,7 +1201,10 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page, · 5 unmodified lines
1199 should_compress = true;1201 should_compress = true;
1200 }1202 }
1201 1203
1202 ctx = kmalloc(struct_size(ctx, chunks, num_chunks), GFP_NOFS);1204 nofs_flag = memalloc_nofs_save();
1205 ctx = kvmalloc(struct_size(ctx, chunks, num_chunks), GFP_KERNEL);
1206 memalloc_nofs_restore(nofs_flag);
1207
1203 if (!ctx) {1208 if (!ctx) {
1204 unsigned clear_bits = EXTENT_LOCKED | EXTENT_DELALLOC |1209 unsigned clear_bits = EXTENT_LOCKED | EXTENT_DELALLOC |
1205 EXTENT_DELALLOC_NEW | EXTENT_DEFRAG |1210 EXTENT_DELALLOC_NEW | EXTENT_DEFRAG |