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.
Unified · Split
| @@ -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 | ||
| 1178 | static int cow_file_range_async(struct inode *inode, struct page *locked_page, | 1179 | static 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 | |