x86: Fix error return sequence in __ioremap_caller()
authorXiaotian Feng <dfeng@redhat.com>
Thu, 5 Nov 2009 02:43:51 +0000 (10:43 +0800)
committerIngo Molnar <mingo@elte.hu>
Sun, 8 Nov 2009 11:48:58 +0000 (12:48 +0100)
kernel missed to free memtype if get_vm_area_caller failed in
__ioremap_caller.

This patch introduces error path to fix this and cleans up the
repetitive error return sequences that contributed to the
creation of the bug.

Signed-off-by: Xiaotian Feng <dfeng@redhat.com>
Acked-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
LKML-Reference: <1257389031-20429-1-git-send-email-dfeng@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/mm/ioremap.c

index 334e63ca7b2b468d096828cd56684604ca3ab0c4..2feb9bdedaaf01fd2f66e08899fb160bf810d220 100644 (file)
@@ -170,8 +170,7 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
                                (unsigned long long)phys_addr,
                                (unsigned long long)(phys_addr + size),
                                prot_val, new_prot_val);
-                       free_memtype(phys_addr, phys_addr + size);
-                       return NULL;
+                       goto err_free_memtype;
                }
                prot_val = new_prot_val;
        }
@@ -197,26 +196,25 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
         */
        area = get_vm_area_caller(size, VM_IOREMAP, caller);
        if (!area)
-               return NULL;
+               goto err_free_memtype;
        area->phys_addr = phys_addr;
        vaddr = (unsigned long) area->addr;
 
-       if (kernel_map_sync_memtype(phys_addr, size, prot_val)) {
-               free_memtype(phys_addr, phys_addr + size);
-               free_vm_area(area);
-               return NULL;
-       }
+       if (kernel_map_sync_memtype(phys_addr, size, prot_val))
+               goto err_free_area;
 
-       if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot)) {
-               free_memtype(phys_addr, phys_addr + size);
-               free_vm_area(area);
-               return NULL;
-       }
+       if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot))
+               goto err_free_area;
 
        ret_addr = (void __iomem *) (vaddr + offset);
        mmiotrace_ioremap(unaligned_phys_addr, unaligned_size, ret_addr);
 
        return ret_addr;
+err_free_area:
+       free_vm_area(area);
+err_free_memtype:
+       free_memtype(phys_addr, phys_addr + size);
+       return NULL;
 }
 
 /**