Re: [PATCH] lib/scatterlist: Hook sg_kmalloc into kmemleak (v2)

From: Catalin Marinas
Date: Tue Aug 10 2010 - 18:01:41 EST


Jens,

On Tue, 2010-07-27 at 09:44 +0100, Chris Wilson wrote:
> kmemleak ignores page_alloc() and so believes the final sub-page
> allocation using the plain kmalloc is decoupled and lost. This leads to
> lots of false-positives with code that uses scatterlists.
>
> The options seem to be either to tell kmemleak that the kmalloc is not
> leaked or to notify kmemleak of the page allocations. The danger of the
> first approach is that we may hide a real leak, so choose the latter
> approach (of which I am not sure of the downsides).
>
> v2: Added comments on the suggestion of Catalin.
>
> Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
> Cc: Tejun Heo <tj@xxxxxxxxxx>
> Cc: Jens Axboe <jaxboe@xxxxxxxxxxxx>
> Cc: Catalin Marinas <catalin.marinas@xxxxxxx>

Since you are the author of lib/scatterlist.c would you (or Tejun) mind
ack'ing this patch? Thanks.

> ---
> lib/scatterlist.c | 21 ++++++++++++++++-----
> 1 files changed, 16 insertions(+), 5 deletions(-)
>
> diff --git a/lib/scatterlist.c b/lib/scatterlist.c
> index 9afa25b..fc85552 100644
> --- a/lib/scatterlist.c
> +++ b/lib/scatterlist.c
> @@ -115,17 +115,28 @@ EXPORT_SYMBOL(sg_init_one);
> */
> static struct scatterlist *sg_kmalloc(unsigned int nents, gfp_t gfp_mask)
> {
> - if (nents == SG_MAX_SINGLE_ALLOC)
> - return (struct scatterlist *) __get_free_page(gfp_mask);
> - else
> + if (nents == SG_MAX_SINGLE_ALLOC) {
> + /* kmemleak doesn't track page allocations as they are not
> + * commonly used (in a raw form) for kernel data structures.
> + * As we chain together a list of pages and then a normal
> + * kmalloc (tracked by kmemleak), in order to for that last
> + * allocation not to become decoupled (and thus a
> + * false-positive) we need to inform kmemleak of all the
> + * intermediate allocations.
> + */
> + void *ptr = (void *) __get_free_page(gfp_mask);
> + kmemleak_alloc(ptr, PAGE_SIZE, 1, gfp_mask);
> + return ptr;
> + } else
> return kmalloc(nents * sizeof(struct scatterlist), gfp_mask);
> }
>
> static void sg_kfree(struct scatterlist *sg, unsigned int nents)
> {
> - if (nents == SG_MAX_SINGLE_ALLOC)
> + if (nents == SG_MAX_SINGLE_ALLOC) {
> + kmemleak_free(sg);
> free_page((unsigned long) sg);
> - else
> + } else
> kfree(sg);
> }

--
Catalin

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/