Messages in this thread Patch in this message |  | | From | Tvrtko Ursulin <> | Subject | [PATCH 4/6] lib/scatterlist: Do not leak pages when high-order allocation fails | Date | Wed, 26 Sep 2018 15:16:23 +0100 |
| |
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
If a higher-order allocation fails, the existing abort and cleanup path would consider all segments allocated so far as 0-order page allocations and would therefore leak memory.
Fix this by cleaning up using sgl_free_n_order which allows the correct page order to be passed in.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: Bart Van Assche <bart.vanassche@wdc.com> Cc: Hannes Reinecke <hare@suse.com> Cc: Johannes Thumshirn <jthumshirn@suse.de> Cc: Jens Axboe <axboe@kernel.dk> --- lib/scatterlist.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 3cc01cd82242..0caed79d7291 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -481,7 +481,7 @@ struct scatterlist *sgl_alloc_order(unsigned long length, unsigned int order, { struct scatterlist *sgl, *sg; struct page *page; - unsigned int nent, nalloc; + unsigned int nent, nalloc, i; u32 elem_len; nent = round_up(length, PAGE_SIZE << order) >> (PAGE_SHIFT + order); @@ -501,17 +501,19 @@ struct scatterlist *sgl_alloc_order(unsigned long length, unsigned int order, sg_init_table(sgl, nalloc); sg = sgl; + i = 0; while (length) { elem_len = min_t(u64, length, PAGE_SIZE << order); page = alloc_pages(gfp, order); if (!page) { - sgl_free(sgl); + sgl_free_n_order(sgl, i, order); return NULL; } sg_set_page(sg, page, elem_len, 0); length -= elem_len; sg = sg_next(sg); + i++; } WARN_ONCE(length, "length = %ld\n", length); if (nent_p) -- 2.17.1
|  |