aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2018-05-29 19:44:59 -0400
committerDavid Sterba <dsterba@suse.com>2018-05-30 11:15:43 -0400
commit1389053e1bed93b75b0c3cd292f61032334c81b3 (patch)
tree71087216205118034caf293b8bf84090bc791bac
parent090a127afa8f73e9618d4058d6755f7ec7453dd6 (diff)
btrfs: raid56: Remove VLA usage
In the quest to remove all stack VLA usage from the kernel[1], this allocates the working buffers during regular init, instead of using stack space. This refactors the allocation code a bit to make it easier to review. [1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com Signed-off-by: Kees Cook <keescook@chromium.org> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/raid56.c38
1 files changed, 28 insertions, 10 deletions
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index 9abd950e7f78..5e4ad134b9ad 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -163,6 +163,12 @@ struct btrfs_raid_bio {
163 * bitmap to record which horizontal stripe has data 163 * bitmap to record which horizontal stripe has data
164 */ 164 */
165 unsigned long *dbitmap; 165 unsigned long *dbitmap;
166
167 /* allocated with real_stripes-many pointers for finish_*() calls */
168 void **finish_pointers;
169
170 /* allocated with stripe_npages-many bits for finish_*() calls */
171 unsigned long *finish_pbitmap;
166}; 172};
167 173
168static int __raid56_parity_recover(struct btrfs_raid_bio *rbio); 174static int __raid56_parity_recover(struct btrfs_raid_bio *rbio);
@@ -981,9 +987,14 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
981 int stripe_npages = DIV_ROUND_UP(stripe_len, PAGE_SIZE); 987 int stripe_npages = DIV_ROUND_UP(stripe_len, PAGE_SIZE);
982 void *p; 988 void *p;
983 989
984 rbio = kzalloc(sizeof(*rbio) + num_pages * sizeof(struct page *) * 2 + 990 rbio = kzalloc(sizeof(*rbio) +
985 DIV_ROUND_UP(stripe_npages, BITS_PER_LONG) * 991 sizeof(*rbio->stripe_pages) * num_pages +
986 sizeof(long), GFP_NOFS); 992 sizeof(*rbio->bio_pages) * num_pages +
993 sizeof(*rbio->finish_pointers) * real_stripes +
994 sizeof(*rbio->dbitmap) * BITS_TO_LONGS(stripe_npages) +
995 sizeof(*rbio->finish_pbitmap) *
996 BITS_TO_LONGS(stripe_npages),
997 GFP_NOFS);
987 if (!rbio) 998 if (!rbio)
988 return ERR_PTR(-ENOMEM); 999 return ERR_PTR(-ENOMEM);
989 1000
@@ -1005,13 +1016,20 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
1005 atomic_set(&rbio->stripes_pending, 0); 1016 atomic_set(&rbio->stripes_pending, 0);
1006 1017
1007 /* 1018 /*
1008 * the stripe_pages and bio_pages array point to the extra 1019 * the stripe_pages, bio_pages, etc arrays point to the extra
1009 * memory we allocated past the end of the rbio 1020 * memory we allocated past the end of the rbio
1010 */ 1021 */
1011 p = rbio + 1; 1022 p = rbio + 1;
1012 rbio->stripe_pages = p; 1023#define CONSUME_ALLOC(ptr, count) do { \
1013 rbio->bio_pages = p + sizeof(struct page *) * num_pages; 1024 ptr = p; \
1014 rbio->dbitmap = p + sizeof(struct page *) * num_pages * 2; 1025 p = (unsigned char *)p + sizeof(*(ptr)) * (count); \
1026 } while (0)
1027 CONSUME_ALLOC(rbio->stripe_pages, num_pages);
1028 CONSUME_ALLOC(rbio->bio_pages, num_pages);
1029 CONSUME_ALLOC(rbio->finish_pointers, real_stripes);
1030 CONSUME_ALLOC(rbio->dbitmap, BITS_TO_LONGS(stripe_npages));
1031 CONSUME_ALLOC(rbio->finish_pbitmap, BITS_TO_LONGS(stripe_npages));
1032#undef CONSUME_ALLOC
1015 1033
1016 if (bbio->map_type & BTRFS_BLOCK_GROUP_RAID5) 1034 if (bbio->map_type & BTRFS_BLOCK_GROUP_RAID5)
1017 nr_data = real_stripes - 1; 1035 nr_data = real_stripes - 1;
@@ -1180,7 +1198,7 @@ static void index_rbio_pages(struct btrfs_raid_bio *rbio)
1180static noinline void finish_rmw(struct btrfs_raid_bio *rbio) 1198static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
1181{ 1199{
1182 struct btrfs_bio *bbio = rbio->bbio; 1200 struct btrfs_bio *bbio = rbio->bbio;
1183 void *pointers[rbio->real_stripes]; 1201 void **pointers = rbio->finish_pointers;
1184 int nr_data = rbio->nr_data; 1202 int nr_data = rbio->nr_data;
1185 int stripe; 1203 int stripe;
1186 int pagenr; 1204 int pagenr;
@@ -2350,8 +2368,8 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
2350 int need_check) 2368 int need_check)
2351{ 2369{
2352 struct btrfs_bio *bbio = rbio->bbio; 2370 struct btrfs_bio *bbio = rbio->bbio;
2353 void *pointers[rbio->real_stripes]; 2371 void **pointers = rbio->finish_pointers;
2354 DECLARE_BITMAP(pbitmap, rbio->stripe_npages); 2372 unsigned long *pbitmap = rbio->finish_pbitmap;
2355 int nr_data = rbio->nr_data; 2373 int nr_data = rbio->nr_data;
2356 int stripe; 2374 int stripe;
2357 int pagenr; 2375 int pagenr;