parisc: Fix vmap memory leak in ioremap()/iounmap()
Helge Deller
maintainerPATCH 1/1 parisc: Fix vmap memory leak in ioremap()/iounmap()
Sven noticed that calling ioremap() and iounmap() multiple times leads to a vmap memory leak:
vmap allocation for size 4198400 failed:
use vmalloc=<size> to increase size
It seems we missed calling remove_vm_area() for ioummap().
arch/parisc/mm/ioremap.c +23 -4
@@ -3,13 +3,14 @@* arch/parisc/mm/ioremap.c * * (C) Copyright 1995 1996 Linus Torvalds -* (C) Copyright 2001-2006 Helge Deller <[email protected]> +* (C) Copyright 2001-2019 Helge Deller <[email protected]> * (C) Copyright 2005 Kyle McMartin <[email protected]> */ #include <linux/vmalloc.h> #include <linux/errno.h> #include <linux/module.h> +#include <linux/slab.h> #include <linux/io.h> #include <asm/pgalloc.h>
@@ -84,7 +85,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l addr = (void __iomem *) area->addr;if (ioremap_page_range ((unsigned long )addr, (unsigned long )addr + size, phys_addr, pgprot)) { -vfree (addr); +remove_vm_area ((void __force *)addr); +kfree (area);return NULL ; }
@@ -94,7 +96,24 @@ EXPORT_SYMBOL(__ioremap);void iounmap (const volatile void __iomem *addr) { -if (addr > high_memory) -return vfree ((void *) (PAGE_MASK & (unsigned long __force ) addr)); +struct vm_struct *p, *o; + +if (addr <= high_memory) +return ; + + addr = (volatile void __iomem *) + (PAGE_MASK & (unsigned long __force )addr); + + p =find_vm_area ((void __force *)addr); +if (!p) { +printk (KERN_ERR "iounmap: bad address %p\n" , addr); +dump_stack (); +return ; + } + +/* Finally remove it */ + o =remove_vm_area ((void __force *)addr); +BUG_ON (p != o || o ==NULL ); +kfree (p); }EXPORT_SYMBOL (iounmap);
Quoted 6 lines · On Mon, 9 Sep 2019 15:38:56 +0200 Helge Deller <[email protected]> wrote:
Sven noticed that calling
ioremap()andiounmap()multiple times leads to a vmap memory leak:
vmap allocation for size 4198400 failed:
use vmalloc=<size> to increase sizeIt seems we missed calling
remove_vm_area()forioummap().
That patch seems to work (tested on a C8000 for a couple of weeks). I was surprised it wasn't part of the "parisc architecture updates for kernel v5.4" pull request.
Kind regards,
jer
has it already been tested on C36xx and C37xx?
Il giorno lun 30 set 2019 alle ore 08:22 Jeroen Roovers <[email protected]> ha scritto:
Quoted 18 lines
Quoted 6 lines · On Mon, 9 Sep 2019 15:38:56 +0200 Helge Deller <[email protected]> wrote:
Sven noticed that calling
ioremap()andiounmap()multiple times leads to a vmap memory leak:
vmap allocation for size 4198400 failed:
use vmalloc=<size> to increase sizeIt seems we missed calling
remove_vm_area()forioummap().That patch seems to work (tested on a C8000 for a couple of weeks). I was surprised it wasn't part of the "parisc architecture updates for kernel v5.4" pull request.
Kind regards,
jer
Helge Deller
maintainerQuoted 11 lines · Jeroen Roovers
Quoted 6 lines · On Mon, 9 Sep 2019 15:38:56 +0200 Helge Deller <[email protected]> wrote:
Sven noticed that calling
ioremap()andiounmap()multiple times leads to a vmap memory leak:
vmap allocation for size 4198400 failed:
use vmalloc=<size> to increase sizeIt seems we missed calling
remove_vm_area()forioummap().That patch seems to work (tested on a C8000 for a couple of weeks).
Did you actually stress-tested it?
modprobe/rmmod is not used that often if you have the patch simply compiled in...
Quoted 2 lines
I was surprised it wasn't part of the "parisc architecture updates for kernel v5.4" pull request.
My hope was that some mm-knowledgeable person would doublecheck. It seems we could e.g. use vunmap() instead of remove_vm_area() & kfree()...
The patch is not forgotten, it just needs some more thoughts/discussions.
Helge
Helge Deller
maintainerPATCH v2 1/1 parisc: Fix vmap memory leak in ioremap()/iounmap()
Sven noticed that calling ioremap() and iounmap() multiple times leads to a vmap memory leak:
vmap allocation for size 4198400 failed:
use vmalloc=<size> to increase size
It seems we missed calling vunmap() in ioummap().
arch/parisc/mm/ioremap.c +7 -5
@@ -3,7 +3,7 @@* arch/parisc/mm/ioremap.c * * (C) Copyright 1995 1996 Linus Torvalds -* (C) Copyright 2001-2006 Helge Deller <[email protected]> +* (C) Copyright 2001-2019 Helge Deller <[email protected]> * (C) Copyright 2005 Kyle McMartin <[email protected]> */
@@ -84,7 +84,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l addr = (void __iomem *) area->addr;if (ioremap_page_range ((unsigned long )addr, (unsigned long )addr + size, phys_addr, pgprot)) { -vfree (addr); +vunmap (addr);return NULL ; }
@@ -92,9 +92,11 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l }EXPORT_SYMBOL (__ioremap); -void iounmap (const volatile void __iomem *addr) +void iounmap (const volatile void __iomem *io_addr) { -if (addr > high_memory) -return vfree ((void *) (PAGE_MASK & (unsigned long __force ) addr)); +unsigned long addr = (unsigned long )io_addr &PAGE_MASK ; + +if (is_vmalloc_addr ((void *)addr)) +vunmap ((void *)addr); }EXPORT_SYMBOL (iounmap);
pATA Promise Technologies PDC20265 (datasheet)
In reply to Helge Dellerhi
perhaps a bit OT, but I really don't know where to ask. I googled a lot these days, but couldn't find a datasheet about the Promise Technologies PDC20265 chip.
does anyone happen to have a copy of it?
thanks
=)