diff options
author | Joe Thornber <ejt@redhat.com> | 2015-07-03 10:22:42 +0100 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2015-08-12 16:33:20 +0200 |
commit | 24e67c60b3cf0178876b52bff9f5478d87d79bd8 (patch) | |
tree | ceaf51f0933d8d373281c803d9115c96da7513b8 /drivers/md/dm-thin.c | |
parent | c44d39ea4ed5ded11e448f9be6faef72b5924634 (diff) | |
download | kernel_samsung_smdk4412-24e67c60b3cf0178876b52bff9f5478d87d79bd8.zip kernel_samsung_smdk4412-24e67c60b3cf0178876b52bff9f5478d87d79bd8.tar.gz kernel_samsung_smdk4412-24e67c60b3cf0178876b52bff9f5478d87d79bd8.tar.bz2 |
dm thin: allocate the cell_sort_array dynamically
commit a822c83e47d97cdef38c4352e1ef62d9f46cfe98 upstream.
Given the pool's cell_sort_array holds 8192 pointers it triggers an
order 5 allocation via kmalloc. This order 5 allocation is prone to
failure as system memory gets more fragmented over time.
Fix this by allocating the cell_sort_array using vmalloc.
Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
[bwh: Backported to 3.2: make a similar change in prison_{create,destroy}()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'drivers/md/dm-thin.c')
-rw-r--r-- | drivers/md/dm-thin.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 80f8bd5..d9f23a4 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/vmalloc.h> #define DM_MSG_PREFIX "thin" @@ -158,9 +159,7 @@ static struct bio_prison *prison_create(unsigned nr_cells) { unsigned i; uint32_t nr_buckets = calc_nr_buckets(nr_cells); - size_t len = sizeof(struct bio_prison) + - (sizeof(struct hlist_head) * nr_buckets); - struct bio_prison *prison = kmalloc(len, GFP_KERNEL); + struct bio_prison *prison = kmalloc(sizeof(*prison), GFP_KERNEL); if (!prison) return NULL; @@ -173,9 +172,15 @@ static struct bio_prison *prison_create(unsigned nr_cells) return NULL; } + prison->cells = vmalloc(sizeof(*prison->cells) * nr_buckets); + if (!prison->cells) { + mempool_destroy(prison->cell_pool); + kfree(prison); + return NULL; + } + prison->nr_buckets = nr_buckets; prison->hash_mask = nr_buckets - 1; - prison->cells = (struct hlist_head *) (prison + 1); for (i = 0; i < nr_buckets; i++) INIT_HLIST_HEAD(prison->cells + i); @@ -184,6 +189,7 @@ static struct bio_prison *prison_create(unsigned nr_cells) static void prison_destroy(struct bio_prison *prison) { + vfree(prison->cells); mempool_destroy(prison->cell_pool); kfree(prison); } |