Merge branch 'akpm' (patches from Andrew)
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 12 Mar 2019 17:39:53 +0000 (10:39 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 12 Mar 2019 17:39:53 +0000 (10:39 -0700)
Merge misc updates from Andrew Morton:

 - a few misc things

 - the rest of MM

-  remove flex_arrays, replace with new simple radix-tree implementation

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (38 commits)
  Drop flex_arrays
  sctp: convert to genradix
  proc: commit to genradix
  generic radix trees
  selinux: convert to kvmalloc
  md: convert to kvmalloc
  openvswitch: convert to kvmalloc
  of: fix kmemleak crash caused by imbalance in early memory reservation
  mm: memblock: update comments and kernel-doc
  memblock: split checks whether a region should be skipped to a helper function
  memblock: remove memblock_{set,clear}_region_flags
  memblock: drop memblock_alloc_*_nopanic() variants
  memblock: memblock_alloc_try_nid: don't panic
  treewide: add checks for the return value of memblock_alloc*()
  swiotlb: add checks for the return value of memblock_alloc*()
  init/main: add checks for the return value of memblock_alloc*()
  mm/percpu: add checks for the return value of memblock_alloc*()
  sparc: add checks for the return value of memblock_alloc*()
  ia64: add checks for the return value of memblock_alloc*()
  arch: don't memset(0) memory returned by memblock_alloc()
  ...

159 files changed:
Documentation/core-api/flexible-arrays.rst [deleted file]
Documentation/core-api/generic-radix-tree.rst [new file with mode: 0644]
Documentation/core-api/index.rst
Documentation/flexible-arrays.txt [deleted file]
arch/alpha/kernel/core_cia.c
arch/alpha/kernel/core_marvel.c
arch/alpha/kernel/pci-noop.c
arch/alpha/kernel/pci.c
arch/alpha/kernel/pci_iommu.c
arch/alpha/kernel/setup.c
arch/arc/kernel/unwind.c
arch/arc/mm/highmem.c
arch/arm/kernel/setup.c
arch/arm/mm/init.c
arch/arm/mm/mmu.c
arch/arm64/kernel/setup.c
arch/arm64/mm/kasan_init.c
arch/arm64/mm/mmu.c
arch/arm64/mm/numa.c
arch/c6x/mm/dma-coherent.c
arch/c6x/mm/init.c
arch/csky/mm/highmem.c
arch/h8300/mm/init.c
arch/ia64/kernel/mca.c
arch/ia64/mm/contig.c
arch/ia64/mm/discontig.c
arch/ia64/mm/init.c
arch/ia64/mm/tlb.c
arch/ia64/sn/kernel/io_common.c
arch/ia64/sn/kernel/setup.c
arch/m68k/atari/stram.c
arch/m68k/mm/init.c
arch/m68k/mm/mcfmmu.c
arch/m68k/mm/motorola.c
arch/m68k/mm/sun3mmu.c
arch/m68k/sun3/sun3dvma.c
arch/microblaze/mm/init.c
arch/mips/cavium-octeon/dma-octeon.c
arch/mips/kernel/setup.c
arch/mips/kernel/traps.c
arch/mips/mm/init.c
arch/nds32/mm/init.c
arch/openrisc/mm/init.c
arch/openrisc/mm/ioremap.c
arch/powerpc/kernel/dt_cpu_ftrs.c
arch/powerpc/kernel/paca.c
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/lib/alloc.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/mmu_context_nohash.c
arch/powerpc/mm/numa.c
arch/powerpc/mm/pgtable-book3e.c
arch/powerpc/mm/pgtable-book3s64.c
arch/powerpc/mm/pgtable-radix.c
arch/powerpc/mm/ppc_mmu_32.c
arch/powerpc/platforms/pasemi/iommu.c
arch/powerpc/platforms/powermac/nvram.c
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/ps3/setup.c
arch/powerpc/sysdev/dart_iommu.c
arch/powerpc/sysdev/msi_bitmap.c
arch/s390/kernel/crash_dump.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/topology.c
arch/s390/numa/mode_emu.c
arch/s390/numa/numa.c
arch/sh/boards/mach-ap325rxa/setup.c
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-kfr2r09/setup.c
arch/sh/boards/mach-migor/setup.c
arch/sh/boards/mach-se/7724/setup.c
arch/sh/kernel/machine_kexec.c
arch/sh/mm/init.c
arch/sh/mm/numa.c
arch/sparc/kernel/prom_32.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/smp_64.c
arch/sparc/mm/init_32.c
arch/sparc/mm/init_64.c
arch/sparc/mm/srmmu.c
arch/um/drivers/net_kern.c
arch/um/drivers/vector_kern.c
arch/um/kernel/initrd.c
arch/um/kernel/mem.c
arch/unicore32/kernel/setup.c
arch/unicore32/mm/mmu.c
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/e820.c
arch/x86/kernel/setup_percpu.c
arch/x86/mm/kasan_init_64.c
arch/x86/mm/numa.c
arch/x86/platform/olpc/olpc_dt.c
arch/x86/xen/p2m.c
arch/xtensa/mm/kasan_init.c
arch/xtensa/mm/mmu.c
block/blk-core.c
drivers/clk/ti/clk.c
drivers/firmware/memmap.c
drivers/gpu/drm/nouveau/nouveau_dmem.c
drivers/macintosh/smu.c
drivers/md/raid5-ppl.c
drivers/md/raid5.c
drivers/md/raid5.h
drivers/of/fdt.c
drivers/of/of_reserved_mem.c
drivers/of/unittest.c
drivers/usb/early/xhci-dbc.c
drivers/xen/swiotlb-xen.c
fs/9p/vfs_super.c
fs/afs/super.c
fs/btrfs/disk-io.c
fs/fuse/inode.c
fs/io_uring.c
fs/proc/base.c
include/linux/flex_array.h [deleted file]
include/linux/generic-radix-tree.h [new file with mode: 0644]
include/linux/hmm.h
include/linux/memblock.h
include/linux/mm.h
include/linux/poison.h
include/net/sctp/structs.h
init/main.c
kernel/dma/swiotlb.c
kernel/power/snapshot.c
kernel/printk/printk.c
kernel/sysctl.c
lib/Makefile
lib/cpumask.c
lib/flex_array.c [deleted file]
lib/generic-radix-tree.c [new file with mode: 0644]
mm/cma.c
mm/hmm.c
mm/kasan/init.c
mm/memblock.c
mm/page_alloc.c
mm/page_ext.c
mm/percpu.c
mm/sparse.c
net/openvswitch/flow.h
net/openvswitch/flow_netlink.h
net/openvswitch/flow_table.c
net/openvswitch/flow_table.h
net/sctp/stream.c
net/sctp/stream_interleave.c
security/selinux/ss/avtab.c
security/selinux/ss/avtab.h
security/selinux/ss/conditional.c
security/selinux/ss/policydb.c
security/selinux/ss/policydb.h
security/selinux/ss/services.c
tools/include/linux/poison.h
tools/testing/selftests/sysctl/sysctl.sh

diff --git a/Documentation/core-api/flexible-arrays.rst b/Documentation/core-api/flexible-arrays.rst
deleted file mode 100644 (file)
index b6b85a1..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-
-===================================
-Using flexible arrays in the kernel
-===================================
-
-Large contiguous memory allocations can be unreliable in the Linux kernel.
-Kernel programmers will sometimes respond to this problem by allocating
-pages with :c:func:`vmalloc()`.  This solution not ideal, though.  On 32-bit
-systems, memory from vmalloc() must be mapped into a relatively small address
-space; it's easy to run out.  On SMP systems, the page table changes required
-by vmalloc() allocations can require expensive cross-processor interrupts on
-all CPUs.  And, on all systems, use of space in the vmalloc() range increases
-pressure on the translation lookaside buffer (TLB), reducing the performance
-of the system.
-
-In many cases, the need for memory from vmalloc() can be eliminated by piecing
-together an array from smaller parts; the flexible array library exists to make
-this task easier.
-
-A flexible array holds an arbitrary (within limits) number of fixed-sized
-objects, accessed via an integer index.  Sparse arrays are handled
-reasonably well.  Only single-page allocations are made, so memory
-allocation failures should be relatively rare.  The down sides are that the
-arrays cannot be indexed directly, individual object size cannot exceed the
-system page size, and putting data into a flexible array requires a copy
-operation.  It's also worth noting that flexible arrays do no internal
-locking at all; if concurrent access to an array is possible, then the
-caller must arrange for appropriate mutual exclusion.
-
-The creation of a flexible array is done with :c:func:`flex_array_alloc()`::
-
-    #include <linux/flex_array.h>
-
-    struct flex_array *flex_array_alloc(int element_size,
-                                       unsigned int total,
-                                       gfp_t flags);
-
-The individual object size is provided by ``element_size``, while total is the
-maximum number of objects which can be stored in the array.  The flags
-argument is passed directly to the internal memory allocation calls.  With
-the current code, using flags to ask for high memory is likely to lead to
-notably unpleasant side effects.
-
-It is also possible to define flexible arrays at compile time with::
-
-    DEFINE_FLEX_ARRAY(name, element_size, total);
-
-This macro will result in a definition of an array with the given name; the
-element size and total will be checked for validity at compile time.
-
-Storing data into a flexible array is accomplished with a call to
-:c:func:`flex_array_put()`::
-
-    int flex_array_put(struct flex_array *array, unsigned int element_nr,
-                      void *src, gfp_t flags);
-
-This call will copy the data from src into the array, in the position
-indicated by ``element_nr`` (which must be less than the maximum specified when
-the array was created).  If any memory allocations must be performed, flags
-will be used.  The return value is zero on success, a negative error code
-otherwise.
-
-There might possibly be a need to store data into a flexible array while
-running in some sort of atomic context; in this situation, sleeping in the
-memory allocator would be a bad thing.  That can be avoided by using
-``GFP_ATOMIC`` for the flags value, but, often, there is a better way.  The
-trick is to ensure that any needed memory allocations are done before
-entering atomic context, using :c:func:`flex_array_prealloc()`::
-
-    int flex_array_prealloc(struct flex_array *array, unsigned int start,
-                           unsigned int nr_elements, gfp_t flags);
-
-This function will ensure that memory for the elements indexed in the range
-defined by ``start`` and ``nr_elements`` has been allocated.  Thereafter, a
-``flex_array_put()`` call on an element in that range is guaranteed not to
-block.
-
-Getting data back out of the array is done with :c:func:`flex_array_get()`::
-
-    void *flex_array_get(struct flex_array *fa, unsigned int element_nr);
-
-The return value is a pointer to the data element, or NULL if that
-particular element has never been allocated.
-
-Note that it is possible to get back a valid pointer for an element which
-has never been stored in the array.  Memory for array elements is allocated
-one page at a time; a single allocation could provide memory for several
-adjacent elements.  Flexible array elements are normally initialized to the
-value ``FLEX_ARRAY_FREE`` (defined as 0x6c in <linux/poison.h>), so errors
-involving that number probably result from use of unstored array entries.
-Note that, if array elements are allocated with ``__GFP_ZERO``, they will be
-initialized to zero and this poisoning will not happen.
-
-Individual elements in the array can be cleared with
-:c:func:`flex_array_clear()`::
-
-    int flex_array_clear(struct flex_array *array, unsigned int element_nr);
-
-This function will set the given element to ``FLEX_ARRAY_FREE`` and return
-zero.  If storage for the indicated element is not allocated for the array,
-``flex_array_clear()`` will return ``-EINVAL`` instead.  Note that clearing an
-element does not release the storage associated with it; to reduce the
-allocated size of an array, call :c:func:`flex_array_shrink()`::
-
-    int flex_array_shrink(struct flex_array *array);
-
-The return value will be the number of pages of memory actually freed.
-This function works by scanning the array for pages containing nothing but
-``FLEX_ARRAY_FREE`` bytes, so (1) it can be expensive, and (2) it will not work
-if the array's pages are allocated with ``__GFP_ZERO``.
-
-It is possible to remove all elements of an array with a call to
-:c:func:`flex_array_free_parts()`::
-
-    void flex_array_free_parts(struct flex_array *array);
-
-This call frees all elements, but leaves the array itself in place.
-Freeing the entire array is done with :c:func:`flex_array_free()`::
-
-    void flex_array_free(struct flex_array *array);
-
-As of this writing, there are no users of flexible arrays in the mainline
-kernel.  The functions described here are also not exported to modules;
-that will probably be fixed when somebody comes up with a need for it.
-
-
-Flexible array functions
-------------------------
-
-.. kernel-doc:: include/linux/flex_array.h
diff --git a/Documentation/core-api/generic-radix-tree.rst b/Documentation/core-api/generic-radix-tree.rst
new file mode 100644 (file)
index 0000000..ed42839
--- /dev/null
@@ -0,0 +1,12 @@
+=================================
+Generic radix trees/sparse arrays
+=================================
+
+.. kernel-doc:: include/linux/generic-radix-tree.h
+   :doc: Generic radix trees/sparse arrays
+
+generic radix tree functions
+----------------------------
+
+.. kernel-doc:: include/linux/generic-radix-tree.h
+   :functions:
index 3adee82be311e61e231857ae788bce06b5b87ef8..6870baffef82d470de7cc699a7599e075d3f71b5 100644 (file)
@@ -28,6 +28,7 @@ Core utilities
    errseq
    printk-formats
    circular-buffers
+   generic-radix-tree
    memory-allocation
    mm-api
    gfp_mask-from-fs-io
diff --git a/Documentation/flexible-arrays.txt b/Documentation/flexible-arrays.txt
deleted file mode 100644 (file)
index a0f2989..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-===================================
-Using flexible arrays in the kernel
-===================================
-
-:Updated: Last updated for 2.6.32
-:Author: Jonathan Corbet <corbet@lwn.net>
-
-Large contiguous memory allocations can be unreliable in the Linux kernel.
-Kernel programmers will sometimes respond to this problem by allocating
-pages with vmalloc().  This solution not ideal, though.  On 32-bit systems,
-memory from vmalloc() must be mapped into a relatively small address space;
-it's easy to run out.  On SMP systems, the page table changes required by
-vmalloc() allocations can require expensive cross-processor interrupts on
-all CPUs.  And, on all systems, use of space in the vmalloc() range
-increases pressure on the translation lookaside buffer (TLB), reducing the
-performance of the system.
-
-In many cases, the need for memory from vmalloc() can be eliminated by
-piecing together an array from smaller parts; the flexible array library
-exists to make this task easier.
-
-A flexible array holds an arbitrary (within limits) number of fixed-sized
-objects, accessed via an integer index.  Sparse arrays are handled
-reasonably well.  Only single-page allocations are made, so memory
-allocation failures should be relatively rare.  The down sides are that the
-arrays cannot be indexed directly, individual object size cannot exceed the
-system page size, and putting data into a flexible array requires a copy
-operation.  It's also worth noting that flexible arrays do no internal
-locking at all; if concurrent access to an array is possible, then the
-caller must arrange for appropriate mutual exclusion.
-
-The creation of a flexible array is done with::
-
-    #include <linux/flex_array.h>
-
-    struct flex_array *flex_array_alloc(int element_size,
-                                       unsigned int total,
-                                       gfp_t flags);
-
-The individual object size is provided by element_size, while total is the
-maximum number of objects which can be stored in the array.  The flags
-argument is passed directly to the internal memory allocation calls.  With
-the current code, using flags to ask for high memory is likely to lead to
-notably unpleasant side effects.
-
-It is also possible to define flexible arrays at compile time with::
-
-    DEFINE_FLEX_ARRAY(name, element_size, total);
-
-This macro will result in a definition of an array with the given name; the
-element size and total will be checked for validity at compile time.
-
-Storing data into a flexible array is accomplished with a call to::
-
-    int flex_array_put(struct flex_array *array, unsigned int element_nr,
-                      void *src, gfp_t flags);
-
-This call will copy the data from src into the array, in the position
-indicated by element_nr (which must be less than the maximum specified when
-the array was created).  If any memory allocations must be performed, flags
-will be used.  The return value is zero on success, a negative error code
-otherwise.
-
-There might possibly be a need to store data into a flexible array while
-running in some sort of atomic context; in this situation, sleeping in the
-memory allocator would be a bad thing.  That can be avoided by using
-GFP_ATOMIC for the flags value, but, often, there is a better way.  The
-trick is to ensure that any needed memory allocations are done before
-entering atomic context, using::
-
-    int flex_array_prealloc(struct flex_array *array, unsigned int start,
-                           unsigned int nr_elements, gfp_t flags);
-
-This function will ensure that memory for the elements indexed in the range
-defined by start and nr_elements has been allocated.  Thereafter, a
-flex_array_put() call on an element in that range is guaranteed not to
-block.
-
-Getting data back out of the array is done with::
-
-    void *flex_array_get(struct flex_array *fa, unsigned int element_nr);
-
-The return value is a pointer to the data element, or NULL if that
-particular element has never been allocated.
-
-Note that it is possible to get back a valid pointer for an element which
-has never been stored in the array.  Memory for array elements is allocated
-one page at a time; a single allocation could provide memory for several
-adjacent elements.  Flexible array elements are normally initialized to the
-value FLEX_ARRAY_FREE (defined as 0x6c in <linux/poison.h>), so errors
-involving that number probably result from use of unstored array entries.
-Note that, if array elements are allocated with __GFP_ZERO, they will be
-initialized to zero and this poisoning will not happen.
-
-Individual elements in the array can be cleared with::
-
-    int flex_array_clear(struct flex_array *array, unsigned int element_nr);
-
-This function will set the given element to FLEX_ARRAY_FREE and return
-zero.  If storage for the indicated element is not allocated for the array,
-flex_array_clear() will return -EINVAL instead.  Note that clearing an
-element does not release the storage associated with it; to reduce the
-allocated size of an array, call::
-
-    int flex_array_shrink(struct flex_array *array);
-
-The return value will be the number of pages of memory actually freed.
-This function works by scanning the array for pages containing nothing but
-FLEX_ARRAY_FREE bytes, so (1) it can be expensive, and (2) it will not work
-if the array's pages are allocated with __GFP_ZERO.
-
-It is possible to remove all elements of an array with a call to::
-
-    void flex_array_free_parts(struct flex_array *array);
-
-This call frees all elements, but leaves the array itself in place.
-Freeing the entire array is done with::
-
-    void flex_array_free(struct flex_array *array);
-
-As of this writing, there are no users of flexible arrays in the mainline
-kernel.  The functions described here are also not exported to modules;
-that will probably be fixed when somebody comes up with a need for it.
index 867e8730b0c5c4819a19983efa19522a0984f760..f489170201c345f7b56b17b8d8732f84d4e154c4 100644 (file)
@@ -331,7 +331,10 @@ cia_prepare_tbia_workaround(int window)
        long i;
 
        /* Use minimal 1K map. */
-       ppte = memblock_alloc_from(CIA_BROKEN_TBIA_SIZE, 32768, 0);
+       ppte = memblock_alloc(CIA_BROKEN_TBIA_SIZE, 32768);
+       if (!ppte)
+               panic("%s: Failed to allocate %u bytes align=0x%x\n",
+                     __func__, CIA_BROKEN_TBIA_SIZE, 32768);
        pte = (virt_to_phys(ppte) >> (PAGE_SHIFT - 1)) | 1;
 
        for (i = 0; i < CIA_BROKEN_TBIA_SIZE / sizeof(unsigned long); ++i)
index c1d0c18c71ca4c7d8523094d4ba4568418754336..1db9d0eb292211882aa6eb350024c7966415d9b7 100644 (file)
@@ -83,6 +83,9 @@ mk_resource_name(int pe, int port, char *str)
        
        sprintf(tmp, "PCI %s PE %d PORT %d", str, pe, port);
        name = memblock_alloc(strlen(tmp) + 1, SMP_CACHE_BYTES);
+       if (!name)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     strlen(tmp) + 1);
        strcpy(name, tmp);
 
        return name;
@@ -118,6 +121,9 @@ alloc_io7(unsigned int pe)
        }
 
        io7 = memblock_alloc(sizeof(*io7), SMP_CACHE_BYTES);
+       if (!io7)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(*io7));
        io7->pe = pe;
        raw_spin_lock_init(&io7->irq_lock);
 
index 091cff3c68fd47cfa860761eade0587b8df43408..ae82061edae995dc1ee2d9f711c9a1e604915849 100644 (file)
@@ -34,6 +34,9 @@ alloc_pci_controller(void)
        struct pci_controller *hose;
 
        hose = memblock_alloc(sizeof(*hose), SMP_CACHE_BYTES);
+       if (!hose)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(*hose));
 
        *hose_tail = hose;
        hose_tail = &hose->next;
@@ -44,7 +47,13 @@ alloc_pci_controller(void)
 struct resource * __init
 alloc_resource(void)
 {
-       return memblock_alloc(sizeof(struct resource), SMP_CACHE_BYTES);
+       void *ptr = memblock_alloc(sizeof(struct resource), SMP_CACHE_BYTES);
+
+       if (!ptr)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(struct resource));
+
+       return ptr;
 }
 
 SYSCALL_DEFINE3(pciconfig_iobase, long, which, unsigned long, bus,
@@ -54,7 +63,7 @@ SYSCALL_DEFINE3(pciconfig_iobase, long, which, unsigned long, bus,
 
        /* from hose or from bus.devfn */
        if (which & IOBASE_FROM_HOSE) {
-               for (hose = hose_head; hose; hose = hose->next) 
+               for (hose = hose_head; hose; hose = hose->next)
                        if (hose->index == bus)
                                break;
                if (!hose)
index 97098127df8389e70a3e74e243728d090744b87e..64fbfb0763b292975ce8fa47d1e2b2bc17be29bb 100644 (file)
@@ -393,6 +393,9 @@ alloc_pci_controller(void)
        struct pci_controller *hose;
 
        hose = memblock_alloc(sizeof(*hose), SMP_CACHE_BYTES);
+       if (!hose)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(*hose));
 
        *hose_tail = hose;
        hose_tail = &hose->next;
@@ -403,7 +406,13 @@ alloc_pci_controller(void)
 struct resource * __init
 alloc_resource(void)
 {
-       return memblock_alloc(sizeof(struct resource), SMP_CACHE_BYTES);
+       void *ptr = memblock_alloc(sizeof(struct resource), SMP_CACHE_BYTES);
+
+       if (!ptr)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(struct resource));
+
+       return ptr;
 }
 
 
index aa0f50d0f8237f73ec921239a509f51a6d20e167..3034d6d936d215240ceea3a300d78696800c429e 100644 (file)
@@ -80,6 +80,9 @@ iommu_arena_new_node(int nid, struct pci_controller *hose, dma_addr_t base,
                       "    falling back to system-wide allocation\n",
                       __func__, nid);
                arena = memblock_alloc(sizeof(*arena), SMP_CACHE_BYTES);
+               if (!arena)
+                       panic("%s: Failed to allocate %zu bytes\n", __func__,
+                             sizeof(*arena));
        }
 
        arena->ptes = memblock_alloc_node(sizeof(*arena), align, nid);
@@ -87,13 +90,22 @@ iommu_arena_new_node(int nid, struct pci_controller *hose, dma_addr_t base,
                printk("%s: couldn't allocate arena ptes from node %d\n"
                       "    falling back to system-wide allocation\n",
                       __func__, nid);
-               arena->ptes = memblock_alloc_from(mem_size, align, 0);
+               arena->ptes = memblock_alloc(mem_size, align);
+               if (!arena->ptes)
+                       panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                             __func__, mem_size, align);
        }
 
 #else /* CONFIG_DISCONTIGMEM */
 
        arena = memblock_alloc(sizeof(*arena), SMP_CACHE_BYTES);
-       arena->ptes = memblock_alloc_from(mem_size, align, 0);
+       if (!arena)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(*arena));
+       arena->ptes = memblock_alloc(mem_size, align);
+       if (!arena->ptes)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, mem_size, align);
 
 #endif /* CONFIG_DISCONTIGMEM */
 
index 4b5b1b244f86a108bdda89f33316e84c77950df3..5d4c76a77a9f3edd9d8769f91c9425bb293bbbbe 100644 (file)
@@ -293,7 +293,7 @@ move_initrd(unsigned long mem_limit)
        unsigned long size;
 
        size = initrd_end - initrd_start;
-       start = memblock_alloc_from(PAGE_ALIGN(size), PAGE_SIZE, 0);
+       start = memblock_alloc(PAGE_ALIGN(size), PAGE_SIZE);
        if (!start || __pa(start) + size > mem_limit) {
                initrd_start = initrd_end = 0;
                return NULL;
index d34f69eb1a955f593925d3f6e187206cdaa3ff20..271e9fafa4796ba18cc4ffb158cfc5d9aebbf3a4 100644 (file)
@@ -181,8 +181,7 @@ static void init_unwind_hdr(struct unwind_table *table,
  */
 static void *__init unw_hdr_alloc_early(unsigned long sz)
 {
-       return memblock_alloc_from_nopanic(sz, sizeof(unsigned int),
-                                          MAX_DMA_ADDRESS);
+       return memblock_alloc_from(sz, sizeof(unsigned int), MAX_DMA_ADDRESS);
 }
 
 static void *unw_hdr_alloc(unsigned long sz)
index 48e70015181048640e083e4c1f8b1deb9a02b95d..11f57e2ced8aae639f48acca52d8423dcb6cee3c 100644 (file)
@@ -124,6 +124,10 @@ static noinline pte_t * __init alloc_kmap_pgtable(unsigned long kvaddr)
        pmd_k = pmd_offset(pud_k, kvaddr);
 
        pte_k = (pte_t *)memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
+       if (!pte_k)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
+
        pmd_populate_kernel(&init_mm, pmd_k, pte_k);
        return pte_k;
 }
index 375b13f7e780663eddb3f04e632751064a6b5bfd..5d78b6ac0429a86bb8756d7ec56a60060f9f1c95 100644 (file)
@@ -867,6 +867,9 @@ static void __init request_standard_resources(const struct machine_desc *mdesc)
                boot_alias_start = phys_to_idmap(start);
                if (arm_has_idmap_alias() && boot_alias_start != IDMAP_INVALID_ADDR) {
                        res = memblock_alloc(sizeof(*res), SMP_CACHE_BYTES);
+                       if (!res)
+                               panic("%s: Failed to allocate %zu bytes\n",
+                                     __func__, sizeof(*res));
                        res->name = "System RAM (boot alias)";
                        res->start = boot_alias_start;
                        res->end = phys_to_idmap(end);
@@ -875,6 +878,9 @@ static void __init request_standard_resources(const struct machine_desc *mdesc)
                }
 
                res = memblock_alloc(sizeof(*res), SMP_CACHE_BYTES);
+               if (!res)
+                       panic("%s: Failed to allocate %zu bytes\n", __func__,
+                             sizeof(*res));
                res->name  = "System RAM";
                res->start = start;
                res->end = end;
index 478ea8b7db877ae7426ce55d1b61e616bb6dad4e..15dddfe43319547d2e3c81a80a33f0315a3e2c55 100644 (file)
@@ -205,7 +205,11 @@ phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align)
 
        BUG_ON(!arm_memblock_steal_permitted);
 
-       phys = memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE);
+       phys = memblock_phys_alloc(size, align);
+       if (!phys)
+               panic("Failed to steal %pa bytes at %pS\n",
+                     &size, (void *)_RET_IP_);
+
        memblock_free(phys, size);
        memblock_remove(phys, size);
 
index 57de0dde3ae0811a7290ff42578167ebb7dc208c..f3ce34113f8925ddb886dc03aa4558baef874e4c 100644 (file)
@@ -721,7 +721,13 @@ EXPORT_SYMBOL(phys_mem_access_prot);
 
 static void __init *early_alloc(unsigned long sz)
 {
-       return memblock_alloc(sz, sz);
+       void *ptr = memblock_alloc(sz, sz);
+
+       if (!ptr)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, sz, sz);
+
+       return ptr;
 }
 
 static void *__init late_alloc(unsigned long sz)
@@ -994,6 +1000,9 @@ void __init iotable_init(struct map_desc *io_desc, int nr)
                return;
 
        svm = memblock_alloc(sizeof(*svm) * nr, __alignof__(*svm));
+       if (!svm)
+               panic("%s: Failed to allocate %zu bytes align=0x%zx\n",
+                     __func__, sizeof(*svm) * nr, __alignof__(*svm));
 
        for (md = io_desc; nr; md++, nr--) {
                create_mapping(md);
@@ -1016,6 +1025,9 @@ void __init vm_reserve_area_early(unsigned long addr, unsigned long size,
        struct static_vm *svm;
 
        svm = memblock_alloc(sizeof(*svm), __alignof__(*svm));
+       if (!svm)
+               panic("%s: Failed to allocate %zu bytes align=0x%zx\n",
+                     __func__, sizeof(*svm), __alignof__(*svm));
 
        vm = &svm->vm;
        vm->addr = (void *)addr;
index 834b321a88f881d0badc700acc97cf42f381ba18..f8482fe5a190f47937ee188aa7ff3cbf67bcf2a2 100644 (file)
@@ -208,6 +208,7 @@ static void __init request_standard_resources(void)
        struct memblock_region *region;
        struct resource *res;
        unsigned long i = 0;
+       size_t res_size;
 
        kernel_code.start   = __pa_symbol(_text);
        kernel_code.end     = __pa_symbol(__init_begin - 1);
@@ -215,9 +216,10 @@ static void __init request_standard_resources(void)
        kernel_data.end     = __pa_symbol(_end - 1);
 
        num_standard_resources = memblock.memory.cnt;
-       standard_resources = memblock_alloc_low(num_standard_resources *
-                                               sizeof(*standard_resources),
-                                               SMP_CACHE_BYTES);
+       res_size = num_standard_resources * sizeof(*standard_resources);
+       standard_resources = memblock_alloc_low(res_size, SMP_CACHE_BYTES);
+       if (!standard_resources)
+               panic("%s: Failed to allocate %zu bytes\n", __func__, res_size);
 
        for_each_memblock(memory, region) {
                res = &standard_resources[i++];
index f37a86d2a69da5d8a93a53f43b5a9d075c6ba2a4..296de39ddee5966f25f0394cd617a9b84fc6a5f0 100644 (file)
@@ -40,6 +40,11 @@ static phys_addr_t __init kasan_alloc_zeroed_page(int node)
        void *p = memblock_alloc_try_nid(PAGE_SIZE, PAGE_SIZE,
                                              __pa(MAX_DMA_ADDRESS),
                                              MEMBLOCK_ALLOC_KASAN, node);
+       if (!p)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx nid=%d from=%llx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE, node,
+                     __pa(MAX_DMA_ADDRESS));
+
        return __pa(p);
 }
 
@@ -48,6 +53,11 @@ static phys_addr_t __init kasan_alloc_raw_page(int node)
        void *p = memblock_alloc_try_nid_raw(PAGE_SIZE, PAGE_SIZE,
                                                __pa(MAX_DMA_ADDRESS),
                                                MEMBLOCK_ALLOC_KASAN, node);
+       if (!p)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx nid=%d from=%llx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE, node,
+                     __pa(MAX_DMA_ADDRESS));
+
        return __pa(p);
 }
 
index 402b6495ff5815644e60d65679acd40a17ee8fbe..e97f018ff740f8a1cea437aa88a652882412928b 100644 (file)
@@ -103,6 +103,8 @@ static phys_addr_t __init early_pgtable_alloc(void)
        void *ptr;
 
        phys = memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
+       if (!phys)
+               panic("Failed to allocate page table page\n");
 
        /*
         * The FIX_{PGD,PUD,PMD} slots may be in active use, but the FIX_PTE
index 7a0a555b366af0aa8c56a801cf9f5ecdbd070112..06a6f264f2ddf27f1274802882f9cedb77e043d4 100644 (file)
@@ -237,6 +237,10 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
                pr_info("Initmem setup node %d [<memory-less node>]\n", nid);
 
        nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid);
+       if (!nd_pa)
+               panic("Cannot allocate %zu bytes for node %d data\n",
+                     nd_size, nid);
+
        nd = __va(nd_pa);
 
        /* report and initialize */
index 0be289839ce0d08a4401ab1e7816dbffe9ff4a11..0d3701bc88f603a1c43f2366d6578010735db873 100644 (file)
@@ -138,6 +138,10 @@ void __init coherent_mem_init(phys_addr_t start, u32 size)
 
        dma_bitmap = memblock_alloc(BITS_TO_LONGS(dma_pages) * sizeof(long),
                                    sizeof(long));
+       if (!dma_bitmap)
+               panic("%s: Failed to allocate %zu bytes align=0x%zx\n",
+                     __func__, BITS_TO_LONGS(dma_pages) * sizeof(long),
+                     sizeof(long));
 }
 
 static void c6x_dma_sync(struct device *dev, phys_addr_t paddr, size_t size,
index af5ada0520bea716b306209448e3235deb830ac6..fe582c3a1794143baff4a686e85f2b24d526fe4a 100644 (file)
@@ -40,7 +40,9 @@ void __init paging_init(void)
 
        empty_zero_page      = (unsigned long) memblock_alloc(PAGE_SIZE,
                                                              PAGE_SIZE);
-       memset((void *)empty_zero_page, 0, PAGE_SIZE);
+       if (!empty_zero_page)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
 
        /*
         * Set up user data space
index 53b1bfa4c462e798aa3753d4d4d838639d4f6cf4..3317b774f6dc145eae07b562689d975404279bb9 100644 (file)
@@ -141,6 +141,11 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
                        for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
                                if (pmd_none(*pmd)) {
                                        pte = (pte_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
+                                       if (!pte)
+                                               panic("%s: Failed to allocate %lu bytes align=%lx\n",
+                                                     __func__, PAGE_SIZE,
+                                                     PAGE_SIZE);
+
                                        set_pmd(pmd, __pmd(__pa(pte)));
                                        BUG_ON(pte != pte_offset_kernel(pmd, 0));
                                }
index 6519252ac4dbd7669ca5ebc95930e91773d4f397..0f04a5e9aa4f393226d7b1c287d2111826d944ec 100644 (file)
@@ -68,7 +68,9 @@ void __init paging_init(void)
         * to a couple of allocated pages.
         */
        empty_zero_page = (unsigned long)memblock_alloc(PAGE_SIZE, PAGE_SIZE);
-       memset((void *)empty_zero_page, 0, PAGE_SIZE);
+       if (!empty_zero_page)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
 
        /*
         * Set up SFC/DFC registers (user data space).
index 91bd1e129379db09a7cc0ac60c41d5d94d04fc70..5cabb3fd159ffecd62b71d501338b635f332199c 100644 (file)
@@ -359,11 +359,6 @@ typedef struct ia64_state_log_s
 
 static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES];
 
-#define IA64_LOG_ALLOCATE(it, size) \
-       {ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = \
-               (ia64_err_rec_t *)memblock_alloc(size, SMP_CACHE_BYTES); \
-       ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = \
-               (ia64_err_rec_t *)memblock_alloc(size, SMP_CACHE_BYTES);}
 #define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock)
 #define IA64_LOG_LOCK(it)      spin_lock_irqsave(&ia64_state_log[it].isl_lock, s)
 #define IA64_LOG_UNLOCK(it)    spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s)
@@ -378,6 +373,19 @@ static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES];
 #define IA64_LOG_CURR_BUFFER(it)   (void *)((ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)]))
 #define IA64_LOG_COUNT(it)         ia64_state_log[it].isl_count
 
+static inline void ia64_log_allocate(int it, u64 size)
+{
+       ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] =
+               (ia64_err_rec_t *)memblock_alloc(size, SMP_CACHE_BYTES);
+       if (!ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)])
+               panic("%s: Failed to allocate %llu bytes\n", __func__, size);
+
+       ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] =
+               (ia64_err_rec_t *)memblock_alloc(size, SMP_CACHE_BYTES);
+       if (!ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)])
+               panic("%s: Failed to allocate %llu bytes\n", __func__, size);
+}
+
 /*
  * ia64_log_init
  *     Reset the OS ia64 log buffer
@@ -399,9 +407,7 @@ ia64_log_init(int sal_info_type)
                return;
 
        // set up OS data structures to hold error info
-       IA64_LOG_ALLOCATE(sal_info_type, max_size);
-       memset(IA64_LOG_CURR_BUFFER(sal_info_type), 0, max_size);
-       memset(IA64_LOG_NEXT_BUFFER(sal_info_type), 0, max_size);
+       ia64_log_allocate(sal_info_type, max_size);
 }
 
 /*
@@ -1835,8 +1841,7 @@ format_mca_init_stack(void *mca_data, unsigned long offset,
 /* Caller prevents this from being called after init */
 static void * __ref mca_bootmem(void)
 {
-       return memblock_alloc_from(sizeof(struct ia64_mca_cpu),
-                                  KERNEL_STACK_SIZE, 0);
+       return memblock_alloc(sizeof(struct ia64_mca_cpu), KERNEL_STACK_SIZE);
 }
 
 /* Do per-CPU MCA-related initialization.  */
index 6e447234205c6f94fe5b6d2d276c0eca22c0b9dd..d29fb6b9fa331030fbdad1247d09cb7e77b2317c 100644 (file)
@@ -84,9 +84,13 @@ skip:
 static inline void
 alloc_per_cpu_data(void)
 {
-       cpu_data = memblock_alloc_from(PERCPU_PAGE_SIZE * num_possible_cpus(),
-                                      PERCPU_PAGE_SIZE,
+       size_t size = PERCPU_PAGE_SIZE * num_possible_cpus();
+
+       cpu_data = memblock_alloc_from(size, PERCPU_PAGE_SIZE,
                                       __pa(MAX_DMA_ADDRESS));
+       if (!cpu_data)
+               panic("%s: Failed to allocate %lu bytes align=%lx from=%lx\n",
+                     __func__, size, PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
 }
 
 /**
index f9c36750c6a47feeb6190060a71817fe851dc464..05490dd073e6c3f44cc69f77a305da83e7abc818 100644 (file)
@@ -454,6 +454,10 @@ static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize)
                                     __pa(MAX_DMA_ADDRESS),
                                     MEMBLOCK_ALLOC_ACCESSIBLE,
                                     bestnode);
+       if (!ptr)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx nid=%d from=%lx\n",
+                     __func__, pernodesize, PERCPU_PAGE_SIZE, bestnode,
+                     __pa(MAX_DMA_ADDRESS));
 
        return ptr;
 }
index 29d841525ca1fef5adf33247fa3e9ebebbda4fa0..e49200e31750d1a78a98ab33bb5b8982de6b1cc1 100644 (file)
@@ -444,23 +444,45 @@ int __init create_mem_map_page_table(u64 start, u64 end, void *arg)
 
        for (address = start_page; address < end_page; address += PAGE_SIZE) {
                pgd = pgd_offset_k(address);
-               if (pgd_none(*pgd))
-                       pgd_populate(&init_mm, pgd, memblock_alloc_node(PAGE_SIZE, PAGE_SIZE, node));
+               if (pgd_none(*pgd)) {
+                       pud = memblock_alloc_node(PAGE_SIZE, PAGE_SIZE, node);
+                       if (!pud)
+                               goto err_alloc;
+                       pgd_populate(&init_mm, pgd, pud);
+               }
                pud = pud_offset(pgd, address);
 
-               if (pud_none(*pud))
-                       pud_populate(&init_mm, pud, memblock_alloc_node(PAGE_SIZE, PAGE_SIZE, node));
+               if (pud_none(*pud)) {
+                       pmd = memblock_alloc_node(PAGE_SIZE, PAGE_SIZE, node);
+                       if (!pmd)
+                               goto err_alloc;
+                       pud_populate(&init_mm, pud, pmd);
+               }
                pmd = pmd_offset(pud, address);
 
-               if (pmd_none(*pmd))
-                       pmd_populate_kernel(&init_mm, pmd, memblock_alloc_node(PAGE_SIZE, PAGE_SIZE, node));
+               if (pmd_none(*pmd)) {
+                       pte = memblock_alloc_node(PAGE_SIZE, PAGE_SIZE, node);
+                       if (!pte)
+                               goto err_alloc;
+                       pmd_populate_kernel(&init_mm, pmd, pte);
+               }
                pte = pte_offset_kernel(pmd, address);
 
-               if (pte_none(*pte))
-                       set_pte(pte, pfn_pte(__pa(memblock_alloc_node(PAGE_SIZE, PAGE_SIZE, node)) >> PAGE_SHIFT,
+               if (pte_none(*pte)) {
+                       void *page = memblock_alloc_node(PAGE_SIZE, PAGE_SIZE,
+                                                        node);
+                       if (!page)
+                               goto err_alloc;
+                       set_pte(pte, pfn_pte(__pa(page) >> PAGE_SHIFT,
                                             PAGE_KERNEL));
+               }
        }
        return 0;
+
+err_alloc:
+       panic("%s: Failed to allocate %lu bytes align=0x%lx nid=%d\n",
+             __func__, PAGE_SIZE, PAGE_SIZE, node);
+       return -ENOMEM;
 }
 
 struct memmap_init_callback_data {
index 9340bcb4f29c4ee0f0fa9868ae0571efff635d4a..5fc89aabdce1f8be105e8cb1e1805218cf9f77d9 100644 (file)
@@ -61,8 +61,14 @@ mmu_context_init (void)
 {
        ia64_ctx.bitmap = memblock_alloc((ia64_ctx.max_ctx + 1) >> 3,
                                         SMP_CACHE_BYTES);
+       if (!ia64_ctx.bitmap)
+               panic("%s: Failed to allocate %u bytes\n", __func__,
+                     (ia64_ctx.max_ctx + 1) >> 3);
        ia64_ctx.flushmap = memblock_alloc((ia64_ctx.max_ctx + 1) >> 3,
                                           SMP_CACHE_BYTES);
+       if (!ia64_ctx.flushmap)
+               panic("%s: Failed to allocate %u bytes\n", __func__,
+                     (ia64_ctx.max_ctx + 1) >> 3);
 }
 
 /*
index 8df13d0d96fa30f25ec94040715c3e93978e1d00..d46847323ef6a64ee02c0f4aca2ed494e1c534c9 100644 (file)
@@ -394,6 +394,9 @@ void __init hubdev_init_node(nodepda_t * npda, cnodeid_t node)
        hubdev_info = (struct hubdev_info *)memblock_alloc_node(size,
                                                                SMP_CACHE_BYTES,
                                                                node);
+       if (!hubdev_info)
+               panic("%s: Failed to allocate %d bytes align=0x%x nid=%d\n",
+                     __func__, size, SMP_CACHE_BYTES, node);
 
        npda->pdinfo = (void *)hubdev_info;
 }
index a6d40a2c5bffcc5b19a66311a832a5522af278de..e6a5049ef5031bcc702a4ba5a937618033221409 100644 (file)
@@ -513,6 +513,10 @@ static void __init sn_init_pdas(char **cmdline_p)
                nodepdaindr[cnode] =
                    memblock_alloc_node(sizeof(nodepda_t), SMP_CACHE_BYTES,
                                        cnode);
+               if (!nodepdaindr[cnode])
+                       panic("%s: Failed to allocate %lu bytes align=0x%x nid=%d\n",
+                             __func__, sizeof(nodepda_t), SMP_CACHE_BYTES,
+                             cnode);
                memset(nodepdaindr[cnode]->phys_cpuid, -1,
                    sizeof(nodepdaindr[cnode]->phys_cpuid));
                spin_lock_init(&nodepdaindr[cnode]->ptc_lock);
@@ -521,9 +525,15 @@ static void __init sn_init_pdas(char **cmdline_p)
        /*
         * Allocate & initialize nodepda for TIOs.  For now, put them on node 0.
         */
-       for (cnode = num_online_nodes(); cnode < num_cnodes; cnode++)
+       for (cnode = num_online_nodes(); cnode < num_cnodes; cnode++) {
                nodepdaindr[cnode] =
                    memblock_alloc_node(sizeof(nodepda_t), SMP_CACHE_BYTES, 0);
+               if (!nodepdaindr[cnode])
+                       panic("%s: Failed to allocate %lu bytes align=0x%x nid=%d\n",
+                             __func__, sizeof(nodepda_t), SMP_CACHE_BYTES,
+                             cnode);
+       }
+
 
        /*
         * Now copy the array of nodepda pointers to each nodepda.
index 6ffc204eb07dec522ac8e6eae286c86948590ed1..6152f9f631d2a8f2f97a34578672e65af4227ae3 100644 (file)
@@ -97,6 +97,10 @@ void __init atari_stram_reserve_pages(void *start_mem)
                pr_debug("atari_stram pool: kernel in ST-RAM, using alloc_bootmem!\n");
                stram_pool.start = (resource_size_t)memblock_alloc_low(pool_size,
                                                                       PAGE_SIZE);
+               if (!stram_pool.start)
+                       panic("%s: Failed to allocate %lu bytes align=%lx\n",
+                             __func__, pool_size, PAGE_SIZE);
+
                stram_pool.end = stram_pool.start + pool_size - 1;
                request_resource(&iomem_resource, &stram_pool);
                stram_virt_offset = 0;
index 933c33e76a4831a2148115025009e2ed57d34341..8868a4c9adaefb3914f0c775a4205504d391ec87 100644 (file)
@@ -94,6 +94,9 @@ void __init paging_init(void)
        high_memory = (void *) end_mem;
 
        empty_zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+       if (!empty_zero_page)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
 
        /*
         * Set up SFC/DFC registers (user data space).
index 0de4999a3810db9441b44251da67d537af90f682..6cb1e41d58d0088c01658b7564f1fe691f5211ad 100644 (file)
@@ -44,7 +44,9 @@ void __init paging_init(void)
        int i;
 
        empty_zero_page = (void *) memblock_alloc(PAGE_SIZE, PAGE_SIZE);
-       memset((void *) empty_zero_page, 0, PAGE_SIZE);
+       if (!empty_zero_page)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
 
        pg_dir = swapper_pg_dir;
        memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
@@ -52,6 +54,9 @@ void __init paging_init(void)
        size = num_pages * sizeof(pte_t);
        size = (size + PAGE_SIZE) & ~(PAGE_SIZE-1);
        next_pgtable = (unsigned long) memblock_alloc(size, PAGE_SIZE);
+       if (!next_pgtable)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, size, PAGE_SIZE);
 
        bootmem_end = (next_pgtable + size + PAGE_SIZE) & PAGE_MASK;
        pg_dir += PAGE_OFFSET >> PGDIR_SHIFT;
index 3f3d0bf360910c0d45095a0ef51db604afe5b02b..356601bf96d947d8115beb6747976d721b440f8a 100644 (file)
@@ -55,6 +55,9 @@ static pte_t * __init kernel_page_table(void)
        pte_t *ptablep;
 
        ptablep = (pte_t *)memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
+       if (!ptablep)
+               panic("%s: Failed to allocate %lu bytes align=%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
 
        clear_page(ptablep);
        __flush_page_to_ram(ptablep);
@@ -96,6 +99,9 @@ static pmd_t * __init kernel_ptr_table(void)
        if (((unsigned long)last_pgtable & ~PAGE_MASK) == 0) {
                last_pgtable = (pmd_t *)memblock_alloc_low(PAGE_SIZE,
                                                           PAGE_SIZE);
+               if (!last_pgtable)
+                       panic("%s: Failed to allocate %lu bytes align=%lx\n",
+                             __func__, PAGE_SIZE, PAGE_SIZE);
 
                clear_page(last_pgtable);
                __flush_page_to_ram(last_pgtable);
@@ -278,6 +284,9 @@ void __init paging_init(void)
         * to a couple of allocated pages
         */
        empty_zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+       if (!empty_zero_page)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
 
        /*
         * Set up SFC/DFC registers
index f736db48a2e1bad63ae15d0a1b30b86542b47d59..eca1c46bb90abff694a901e8c593461f90c24ca1 100644 (file)
@@ -46,6 +46,9 @@ void __init paging_init(void)
        unsigned long size;
 
        empty_zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+       if (!empty_zero_page)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
 
        address = PAGE_OFFSET;
        pg_dir = swapper_pg_dir;
@@ -56,6 +59,9 @@ void __init paging_init(void)
        size = (size + PAGE_SIZE) & ~(PAGE_SIZE-1);
 
        next_pgtable = (unsigned long)memblock_alloc(size, PAGE_SIZE);
+       if (!next_pgtable)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, size, PAGE_SIZE);
        bootmem_end = (next_pgtable + size + PAGE_SIZE) & PAGE_MASK;
 
        /* Map whole memory from PAGE_OFFSET (0x0E000000) */
index 4d64711d3d47410cead0940360885ccf22617cae..399f3d06125fe963fe7984273202cdcc55741715 100644 (file)
@@ -269,6 +269,9 @@ void __init dvma_init(void)
 
        iommu_use = memblock_alloc(IOMMU_TOTAL_ENTRIES * sizeof(unsigned long),
                                   SMP_CACHE_BYTES);
+       if (!iommu_use)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     IOMMU_TOTAL_ENTRIES * sizeof(unsigned long));
 
        dvma_unmap_iommu(DVMA_START, DVMA_SIZE);
 
index 44f4b8910c2140a7025022f10969a70266a45e59..7e97d44f653801ddd8972320988aa376c8ccc2b3 100644 (file)
@@ -374,12 +374,14 @@ void * __ref zalloc_maybe_bootmem(size_t size, gfp_t mask)
 {
        void *p;
 
-       if (mem_init_done)
+       if (mem_init_done) {
                p = kzalloc(size, mask);
-       else {
+       else {
                p = memblock_alloc(size, SMP_CACHE_BYTES);
-               if (p)
-                       memset(p, 0, size);
+               if (!p)
+                       panic("%s: Failed to allocate %zu bytes\n",
+                             __func__, size);
        }
+
        return p;
 }
index e8eb60ed99f2a8f877b0cdf2bc673e1ee643f40b..11d5a4e90736a6747dd0e88226543dadac136395 100644 (file)
@@ -245,6 +245,9 @@ void __init plat_swiotlb_setup(void)
        swiotlbsize = swiotlb_nslabs << IO_TLB_SHIFT;
 
        octeon_swiotlb = memblock_alloc_low(swiotlbsize, PAGE_SIZE);
+       if (!octeon_swiotlb)
+               panic("%s: Failed to allocate %zu bytes align=%lx\n",
+                     __func__, swiotlbsize, PAGE_SIZE);
 
        if (swiotlb_init_with_tbl(octeon_swiotlb, swiotlb_nslabs, 1) == -ENOMEM)
                panic("Cannot allocate SWIOTLB buffer");
index 5151532ad9590b522171bae0d41d88fd66af43fb..8d1dc6c71173bbddb837eaeb891c8387613864ba 100644 (file)
@@ -919,6 +919,9 @@ static void __init resource_init(void)
                        end = HIGHMEM_START - 1;
 
                res = memblock_alloc(sizeof(struct resource), SMP_CACHE_BYTES);
+               if (!res)
+                       panic("%s: Failed to allocate %zu bytes\n", __func__,
+                             sizeof(struct resource));
 
                res->start = start;
                res->end = end;
index 42d411125690fa7c31950d6618c76c0d5798e59c..98ca55d622018d8afed59ce068a5a8e79719a6d2 100644 (file)
@@ -2293,7 +2293,10 @@ void __init trap_init(void)
                phys_addr_t ebase_pa;
 
                ebase = (unsigned long)
-                       memblock_alloc_from(size, 1 << fls(size), 0);
+                       memblock_alloc(size, 1 << fls(size));
+               if (!ebase)
+                       panic("%s: Failed to allocate %lu bytes align=0x%x\n",
+                             __func__, size, 1 << fls(size));
 
                /*
                 * Try to ensure ebase resides in KSeg0 if possible.
index c3b45e248806a045e48ed251c20d28cff31efc09..bbb196ad5f26b08e07b7e808dd905e0818f6bef8 100644 (file)
@@ -252,6 +252,11 @@ void __init fixrange_init(unsigned long start, unsigned long end,
                                if (pmd_none(*pmd)) {
                                        pte = (pte_t *) memblock_alloc_low(PAGE_SIZE,
                                                                           PAGE_SIZE);
+                                       if (!pte)
+                                               panic("%s: Failed to allocate %lu bytes align=%lx\n",
+                                                     __func__, PAGE_SIZE,
+                                                     PAGE_SIZE);
+
                                        set_pmd(pmd, __pmd((unsigned long)pte));
                                        BUG_ON(pte != pte_offset_kernel(pmd, 0));
                                }
index d1e521cce3177698c1a6a09bbfb2008524273ff1..1d03633f89a9f3e7b953db45001cec2839c25deb 100644 (file)
@@ -79,6 +79,9 @@ static void __init map_ram(void)
 
                /* Alloc one page for holding PTE's... */
                pte = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+               if (!pte)
+                       panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                             __func__, PAGE_SIZE, PAGE_SIZE);
                set_pmd(pme, __pmd(__pa(pte) + _PAGE_KERNEL_TABLE));
 
                /* Fill the newly allocated page with PTE'S */
@@ -111,6 +114,9 @@ static void __init fixedrange_init(void)
        pud = pud_offset(pgd, vaddr);
        pmd = pmd_offset(pud, vaddr);
        fixmap_pmd_p = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+       if (!fixmap_pmd_p)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
        set_pmd(pmd, __pmd(__pa(fixmap_pmd_p) + _PAGE_KERNEL_TABLE));
 
 #ifdef CONFIG_HIGHMEM
@@ -123,6 +129,9 @@ static void __init fixedrange_init(void)
        pud = pud_offset(pgd, vaddr);
        pmd = pmd_offset(pud, vaddr);
        pte = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+       if (!pte)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
        set_pmd(pmd, __pmd(__pa(pte) + _PAGE_KERNEL_TABLE));
        pkmap_page_table = pte;
 #endif /* CONFIG_HIGHMEM */
@@ -148,6 +157,9 @@ void __init paging_init(void)
 
        /* allocate space for empty_zero_page */
        zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+       if (!zero_page)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
        zone_sizes_init();
 
        empty_zero_page = virt_to_page(zero_page);
index d157310eb377a7d574a03a386641b2fae46027cb..caeb4184e8a6bb030f93b647e0cbd076b8918a48 100644 (file)
@@ -105,7 +105,10 @@ static void __init map_ram(void)
                        }
 
                        /* Alloc one page for holding PTE's... */
-                       pte = (pte_t *) __va(memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE));
+                       pte = memblock_alloc_raw(PAGE_SIZE, PAGE_SIZE);
+                       if (!pte)
+                               panic("%s: Failed to allocate page for PTEs\n",
+                                     __func__);
                        set_pmd(pme, __pmd(_KERNPG_TABLE + __pa(pte)));
 
                        /* Fill the newly allocated page with PTE'S */
index 051bcb4fefd389dad1ab20ae23d6ab72fe89f472..a8509950dbbc8da4e7d10ed0b14b8bfdc5ab2ab2 100644 (file)
@@ -122,10 +122,14 @@ pte_t __ref *pte_alloc_one_kernel(struct mm_struct *mm)
 {
        pte_t *pte;
 
-       if (likely(mem_init_done))
+       if (likely(mem_init_done)) {
                pte = (pte_t *)get_zeroed_page(GFP_KERNEL);
-       else
+       } else {
                pte = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+               if (!pte)
+                       panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                             __func__, PAGE_SIZE, PAGE_SIZE);
+       }
 
        return pte;
 }
index e49bd5efcfe66b5092f241bca00a2688ce5ac396..c66fd3ce64780601f08d4353186fee18f0ebfca1 100644 (file)
@@ -810,7 +810,6 @@ static int __init process_cpufeatures_node(unsigned long node,
        int len;
 
        f = &dt_cpu_features[i];
-       memset(f, 0, sizeof(struct dt_cpu_feature));
 
        f->node = node;
 
@@ -1005,7 +1004,12 @@ static int __init dt_cpu_ftrs_scan_callback(unsigned long node, const char
        /* Count and allocate space for cpu features */
        of_scan_flat_dt_subnodes(node, count_cpufeatures_subnodes,
                                                &nr_dt_cpu_features);
-       dt_cpu_features = __va(memblock_phys_alloc(sizeof(struct dt_cpu_feature) * nr_dt_cpu_features, PAGE_SIZE));
+       dt_cpu_features = memblock_alloc(sizeof(struct dt_cpu_feature) * nr_dt_cpu_features, PAGE_SIZE);
+       if (!dt_cpu_features)
+               panic("%s: Failed to allocate %zu bytes align=0x%lx\n",
+                     __func__,
+                     sizeof(struct dt_cpu_feature) * nr_dt_cpu_features,
+                     PAGE_SIZE);
 
        cpufeatures_setup_start(isa);
 
index 8c890c6557edea1c1335d3df1fab94685e06ec42..e7382abee86849f136a6337eedf58a417dba6ea9 100644 (file)
@@ -196,7 +196,11 @@ void __init allocate_paca_ptrs(void)
        paca_nr_cpu_ids = nr_cpu_ids;
 
        paca_ptrs_size = sizeof(struct paca_struct *) * nr_cpu_ids;
-       paca_ptrs = __va(memblock_phys_alloc(paca_ptrs_size, SMP_CACHE_BYTES));
+       paca_ptrs = memblock_alloc_raw(paca_ptrs_size, SMP_CACHE_BYTES);
+       if (!paca_ptrs)
+               panic("Failed to allocate %d bytes for paca pointers\n",
+                     paca_ptrs_size);
+
        memset(paca_ptrs, 0x88, paca_ptrs_size);
 }
 
index d3f04f2d824944d9947993b00fa8aec0bb0fdf08..0417fda13636aef01b6f962d56e48b683a6b0282 100644 (file)
@@ -205,6 +205,9 @@ pci_create_OF_bus_map(void)
 
        of_prop = memblock_alloc(sizeof(struct property) + 256,
                                 SMP_CACHE_BYTES);
+       if (!of_prop)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(struct property) + 256);
        dn = of_find_node_by_path("/");
        if (dn) {
                memset(of_prop, -1, sizeof(struct property) + 256);
index 4181ec715f8889c4bf041b74da247632c7a2f651..4221527b082f40d1989a0fa86660a394b9380892 100644 (file)
@@ -126,7 +126,10 @@ static void __init move_device_tree(void)
        if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) ||
            !memblock_is_memory(start + size - 1) ||
            overlaps_crashkernel(start, size) || overlaps_initrd(start, size)) {
-               p = __va(memblock_phys_alloc(size, PAGE_SIZE));
+               p = memblock_alloc_raw(size, PAGE_SIZE);
+               if (!p)
+                       panic("Failed to allocate %lu bytes to move device tree\n",
+                             size);
                memcpy(p, initial_boot_params, size);
                initial_boot_params = p;
                DBG("Moved device tree to 0x%px\n", p);
index de35bd8f047fc315e29058223e71bc731bafc6e7..fbc676160adf76f2f007a91685678faf9cad8a54 100644 (file)
@@ -1187,7 +1187,11 @@ void __init rtas_initialize(void)
                ibm_suspend_me_token = rtas_token("ibm,suspend-me");
        }
 #endif
-       rtas_rmo_buf = memblock_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region);
+       rtas_rmo_buf = memblock_phys_alloc_range(RTAS_RMOBUF_MAX, PAGE_SIZE,
+                                                0, rtas_region);
+       if (!rtas_rmo_buf)
+               panic("ERROR: RTAS: Failed to allocate %lx bytes below %pa\n",
+                     PAGE_SIZE, &rtas_region);
 
 #ifdef CONFIG_RTAS_ERROR_LOGGING
        rtas_last_error_token = rtas_token("rtas-last-error");
index f17868e19e2c508166df2eeabea94a56bbc0a13f..2e5dfb6e0823999d967eadfb9b569d396192f910 100644 (file)
@@ -461,6 +461,9 @@ void __init smp_setup_cpu_maps(void)
 
        cpu_to_phys_id = memblock_alloc(nr_cpu_ids * sizeof(u32),
                                        __alignof__(u32));
+       if (!cpu_to_phys_id)
+               panic("%s: Failed to allocate %zu bytes align=0x%zx\n",
+                     __func__, nr_cpu_ids * sizeof(u32), __alignof__(u32));
 
        for_each_node_by_type(dn, "cpu") {
                const __be32 *intserv;
index ff0aac42bb33d6c20e90ee1c0d26d2b759d37870..ba404dd9ce1d88809e0a6e70f0decc286caf576a 100644 (file)
@@ -905,6 +905,10 @@ static void __ref init_fallback_flush(void)
        l1d_flush_fallback_area = memblock_alloc_try_nid(l1d_size * 2,
                                                l1d_size, MEMBLOCK_LOW_LIMIT,
                                                limit, NUMA_NO_NODE);
+       if (!l1d_flush_fallback_area)
+               panic("%s: Failed to allocate %llu bytes align=0x%llx max_addr=%pa\n",
+                     __func__, l1d_size * 2, l1d_size, &limit);
+
 
        for_each_possible_cpu(cpu) {
                struct paca_struct *paca = paca_ptrs[cpu];
index dedf88a76f58cc81c0de00bbb6e8e96420f78094..ce180870bd52f700a71ecb09ac65d1d5040baf36 100644 (file)
@@ -15,6 +15,9 @@ void * __ref zalloc_maybe_bootmem(size_t size, gfp_t mask)
                p = kzalloc(size, mask);
        else {
                p = memblock_alloc(size, SMP_CACHE_BYTES);
+               if (!p)
+                       panic("%s: Failed to allocate %zu bytes\n", __func__,
+                             size);
        }
        return p;
 }
index 3d4b2399192f89359c2ca343d97b3e07a11e7eca..0a4f939a8161e810585a95faae113e8e37354bc1 100644 (file)
@@ -882,8 +882,12 @@ static void __init htab_initialize(void)
                }
 #endif /* CONFIG_PPC_CELL */
 
-               table = memblock_alloc_base(htab_size_bytes, htab_size_bytes,
-                                           limit);
+               table = memblock_phys_alloc_range(htab_size_bytes,
+                                                 htab_size_bytes,
+                                                 0, limit);
+               if (!table)
+                       panic("ERROR: Failed to allocate %pa bytes below %pa\n",
+                             &htab_size_bytes, &limit);
 
                DBG("Hash table allocated at %lx, size: %lx\n", table,
                    htab_size_bytes);
@@ -911,6 +915,9 @@ static void __init htab_initialize(void)
                linear_map_hash_slots = memblock_alloc_try_nid(
                                linear_map_hash_count, 1, MEMBLOCK_LOW_LIMIT,
                                ppc64_rma_size, NUMA_NO_NODE);
+               if (!linear_map_hash_slots)
+                       panic("%s: Failed to allocate %lu bytes max_addr=%pa\n",
+                             __func__, linear_map_hash_count, &ppc64_rma_size);
        }
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
index 22d71a58167f55bb69e7c98819925c61ff565b1d..1945c5f19f5efb312084664a5531161d92005f4e 100644 (file)
@@ -461,10 +461,19 @@ void __init mmu_context_init(void)
         * Allocate the maps used by context management
         */
        context_map = memblock_alloc(CTX_MAP_SIZE, SMP_CACHE_BYTES);
+       if (!context_map)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     CTX_MAP_SIZE);
        context_mm = memblock_alloc(sizeof(void *) * (LAST_CONTEXT + 1),
                                    SMP_CACHE_BYTES);
+       if (!context_mm)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(void *) * (LAST_CONTEXT + 1));
 #ifdef CONFIG_SMP
        stale_map[boot_cpuid] = memblock_alloc(CTX_MAP_SIZE, SMP_CACHE_BYTES);
+       if (!stale_map[boot_cpuid])
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     CTX_MAP_SIZE);
 
        cpuhp_setup_state_nocalls(CPUHP_POWERPC_MMU_CTX_PREPARE,
                                  "powerpc/mmu/ctx:prepare",
index ac49e4158e50880ee5bdc86af956f728b533f250..f976676004ad048606e396ebe9b395dcb28835d0 100644 (file)
@@ -788,6 +788,10 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
        int tnid;
 
        nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid);
+       if (!nd_pa)
+               panic("Cannot allocate %zu bytes for node %d data\n",
+                     nd_size, nid);
+
        nd = __va(nd_pa);
 
        /* report and initialize */
index 53cbc7dc2df293e43e158d08b3b3cb2c3d804c89..1032ef7aaf62a551b28de439332d451d8f807158 100644 (file)
@@ -57,8 +57,16 @@ void vmemmap_remove_mapping(unsigned long start,
 
 static __ref void *early_alloc_pgtable(unsigned long size)
 {
-       return memblock_alloc_try_nid(size, size, MEMBLOCK_LOW_LIMIT,
-                                     __pa(MAX_DMA_ADDRESS), NUMA_NO_NODE);
+       void *ptr;
+
+       ptr = memblock_alloc_try_nid(size, size, MEMBLOCK_LOW_LIMIT,
+                                    __pa(MAX_DMA_ADDRESS), NUMA_NO_NODE);
+
+       if (!ptr)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx max_addr=%lx\n",
+                     __func__, size, size, __pa(MAX_DMA_ADDRESS));
+
+       return ptr;
 }
 
 /*
index 92a3e4c39540ced19d68b65573ff2c572d93dbf9..a4341aba0af4dab36898cb5f62c1f8ae629c70b6 100644 (file)
@@ -197,6 +197,9 @@ void __init mmu_partition_table_init(void)
        BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 36), "Partition table size too large.");
        /* Initialize the Partition Table with no entries */
        partition_tb = memblock_alloc(patb_size, patb_size);
+       if (!partition_tb)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, patb_size, patb_size);
 
        /*
         * update partition table control register,
index e377684ac6ad40b960ada944e32015290053ffcf..154472a28c77b953bbf75996c3cdb017172d79a1 100644 (file)
@@ -53,13 +53,20 @@ static __ref void *early_alloc_pgtable(unsigned long size, int nid,
 {
        phys_addr_t min_addr = MEMBLOCK_LOW_LIMIT;
        phys_addr_t max_addr = MEMBLOCK_ALLOC_ANYWHERE;
+       void *ptr;
 
        if (region_start)
                min_addr = region_start;
        if (region_end)
                max_addr = region_end;
 
-       return memblock_alloc_try_nid(size, size, min_addr, max_addr, nid);
+       ptr = memblock_alloc_try_nid(size, size, min_addr, max_addr, nid);
+
+       if (!ptr)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx nid=%d from=%pa max_addr=%pa\n",
+                     __func__, size, size, nid, &min_addr, &max_addr);
+
+       return ptr;
 }
 
 static int early_map_kernel_page(unsigned long ea, unsigned long pa,
index 6c8a60b1e31dd4c2dab22e49d82fcbda3f5d6d12..f29d2f118b444aa6b060bcfa6fab6fb0bf321949 100644 (file)
@@ -340,6 +340,9 @@ void __init MMU_init_hw(void)
         */
        if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
        Hash = memblock_alloc(Hash_size, Hash_size);
+       if (!Hash)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, Hash_size, Hash_size);
        _SDR1 = __pa(Hash) | SDR1_LOW_BITS;
 
        Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size);
index 86368e238f6e6398501aaf6f94e3810afa691db5..044c6089462c02739b8241d659906342811ab447 100644 (file)
@@ -211,6 +211,9 @@ static int __init iob_init(struct device_node *dn)
        iob_l2_base = memblock_alloc_try_nid_raw(1UL << 21, 1UL << 21,
                                        MEMBLOCK_LOW_LIMIT, 0x80000000,
                                        NUMA_NO_NODE);
+       if (!iob_l2_base)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx max_addr=%x\n",
+                     __func__, 1UL << 21, 1UL << 21, 0x80000000);
 
        pr_info("IOBMAP L2 allocated at: %p\n", iob_l2_base);
 
index 9360cdc408c18078b1cab9c512964fbd5e748fc8..86989c5779c2c4abc0e724c8213460d1d5484e62 100644 (file)
@@ -519,6 +519,9 @@ static int __init core99_nvram_setup(struct device_node *dp, unsigned long addr)
                return -EINVAL;
        }
        nvram_image = memblock_alloc(NVRAM_SIZE, SMP_CACHE_BYTES);
+       if (!nvram_image)
+               panic("%s: Failed to allocate %u bytes\n", __func__,
+                     NVRAM_SIZE);
        nvram_data = ioremap(addr, NVRAM_SIZE*2);
        nvram_naddrs = 1; /* Make sure we get the correct case */
 
index 727a7de086351a53738f4dd16779fecb7db64006..2b0eca104f86a2649b96df900068e3b334d28d1d 100644 (file)
@@ -171,6 +171,9 @@ int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
         * Allocate a buffer to hold the MC recoverable ranges.
         */
        mc_recoverable_range = memblock_alloc(size, __alignof__(u64));
+       if (!mc_recoverable_range)
+               panic("%s: Failed to allocate %u bytes align=0x%lx\n",
+                     __func__, size, __alignof__(u64));
 
        for (i = 0; i < mc_recoverable_range_len; i++) {
                mc_recoverable_range[i].start_addr =
index fa6af52b5219f309a3451589a341fecb3c83edf5..3ead4c237ed0ec9254035f133b9e70fec9951b29 100644 (file)
@@ -3657,6 +3657,9 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
        pr_debug("  PHB-ID  : 0x%016llx\n", phb_id);
 
        phb = memblock_alloc(sizeof(*phb), SMP_CACHE_BYTES);
+       if (!phb)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(*phb));
 
        /* Allocate PCI controller */
        phb->hose = hose = pcibios_alloc_controller(np);
@@ -3703,6 +3706,9 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
                phb->diag_data_size = PNV_PCI_DIAG_BUF_SIZE;
 
        phb->diag_data = memblock_alloc(phb->diag_data_size, SMP_CACHE_BYTES);
+       if (!phb->diag_data)
+               panic("%s: Failed to allocate %u bytes\n", __func__,
+                     phb->diag_data_size);
 
        /* Parse 32-bit and IO ranges (if any) */
        pci_process_bridge_OF_ranges(hose, np, !hose->global_number);
@@ -3762,6 +3768,8 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
        pemap_off = size;
        size += phb->ioda.total_pe_num * sizeof(struct pnv_ioda_pe);
        aux = memblock_alloc(size, SMP_CACHE_BYTES);
+       if (!aux)
+               panic("%s: Failed to allocate %lu bytes\n", __func__, size);
        phb->ioda.pe_alloc = aux;
        phb->ioda.m64_segmap = aux + m64map_off;
        phb->ioda.m32_segmap = aux + m32map_off;
index 658bfab3350b928493ce0bf2b435bc2d602923cd..4ce5458eb0f8909128b60b9c1deb8934d5815897 100644 (file)
@@ -127,6 +127,9 @@ static void __init prealloc(struct ps3_prealloc *p)
                return;
 
        p->address = memblock_alloc(p->size, p->align);
+       if (!p->address)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, p->size, p->align);
 
        printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size,
               p->address);
index fc5c5c23303edde535e8aa3d75f4dfcf55d88445..2a751795ec1eb2dcdfbcd40c9ff4a1bd6624deb7 100644 (file)
@@ -265,6 +265,9 @@ static void allocate_dart(void)
         * prefetching into invalid pages and corrupting data
         */
        tmp = memblock_phys_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE);
+       if (!tmp)
+               panic("DART: table allocation failed\n");
+
        dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) &
                                         DARTMAP_RPNMASK);
 
index d45450f6666a9966e63eb15c74ed5cb89a9ff98c..51a679a1c40355819360ea985adb29c4a317f0cb 100644 (file)
@@ -129,6 +129,9 @@ int __ref msi_bitmap_alloc(struct msi_bitmap *bmp, unsigned int irq_count,
                bmp->bitmap = kzalloc(size, GFP_KERNEL);
        else {
                bmp->bitmap = memblock_alloc(size, SMP_CACHE_BYTES);
+               if (!bmp->bitmap)
+                       panic("%s: Failed to allocate %u bytes\n", __func__,
+                             size);
                /* the bitmap won't be freed from memblock allocator */
                kmemleak_not_leak(bmp->bitmap);
        }
index 97eae387186875ea834c635d0608e49658bf355a..f96a5857bbfde04d4ed7fe59b0d0900c7a916a1c 100644 (file)
@@ -61,6 +61,9 @@ struct save_area * __init save_area_alloc(bool is_boot_cpu)
        struct save_area *sa;
 
        sa = (void *) memblock_phys_alloc(sizeof(*sa), 8);
+       if (!sa)
+               panic("Failed to allocate save area\n");
+
        if (is_boot_cpu)
                list_add(&sa->list, &dump_save_areas);
        else
index 12934e8fbb9194ca51c6b775e8339088c281a3c4..2c642af526ce83658504e50b7d95700086589bd2 100644 (file)
@@ -378,6 +378,10 @@ static void __init setup_lowcore_dat_off(void)
         */
        BUILD_BUG_ON(sizeof(struct lowcore) != LC_PAGES * PAGE_SIZE);
        lc = memblock_alloc_low(sizeof(*lc), sizeof(*lc));
+       if (!lc)
+               panic("%s: Failed to allocate %zu bytes align=%zx\n",
+                     __func__, sizeof(*lc), sizeof(*lc));
+
        lc->restart_psw.mask = PSW_KERNEL_BITS;
        lc->restart_psw.addr = (unsigned long) restart_int_handler;
        lc->external_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK;
@@ -419,6 +423,9 @@ static void __init setup_lowcore_dat_off(void)
         * all CPUs in cast *one* of them does a PSW restart.
         */
        restart_stack = memblock_alloc(THREAD_SIZE, THREAD_SIZE);
+       if (!restart_stack)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, THREAD_SIZE, THREAD_SIZE);
        restart_stack += STACK_INIT_OFFSET;
 
        /*
@@ -495,6 +502,9 @@ static void __init setup_resources(void)
 
        for_each_memblock(memory, reg) {
                res = memblock_alloc(sizeof(*res), 8);
+               if (!res)
+                       panic("%s: Failed to allocate %zu bytes align=0x%x\n",
+                             __func__, sizeof(*res), 8);
                res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM;
 
                res->name = "System RAM";
@@ -509,6 +519,9 @@ static void __init setup_resources(void)
                                continue;
                        if (std_res->end > res->end) {
                                sub_res = memblock_alloc(sizeof(*sub_res), 8);
+                               if (!sub_res)
+                                       panic("%s: Failed to allocate %zu bytes align=0x%x\n",
+                                             __func__, sizeof(*sub_res), 8);
                                *sub_res = *std_res;
                                sub_res->end = res->end;
                                std_res->start = res->end + 1;
@@ -966,6 +979,9 @@ static void __init setup_randomness(void)
 
        vmms = (struct sysinfo_3_2_2 *) memblock_phys_alloc(PAGE_SIZE,
                                                            PAGE_SIZE);
+       if (!vmms)
+               panic("Failed to allocate memory for sysinfo structure\n");
+
        if (stsi(vmms, 3, 2, 2) == 0 && vmms->count)
                add_device_randomness(&vmms->vm, sizeof(vmms->vm[0]) * vmms->count);
        memblock_free((unsigned long) vmms, PAGE_SIZE);
index b198ece2aad63d70f58b2acde1c280ce5534cf7a..3fe1c77c361b98a9a4443bf1a2941f486d024030 100644 (file)
@@ -656,7 +656,11 @@ void __init smp_save_dump_cpus(void)
                /* No previous system present, normal boot. */
                return;
        /* Allocate a page as dumping area for the store status sigps */
-       page = memblock_alloc_base(PAGE_SIZE, PAGE_SIZE, 1UL << 31);
+       page = memblock_phys_alloc_range(PAGE_SIZE, PAGE_SIZE, 0, 1UL << 31);
+       if (!page)
+               panic("ERROR: Failed to allocate %lx bytes below %lx\n",
+                     PAGE_SIZE, 1UL << 31);
+
        /* Set multi-threading state to the previous system. */
        pcpu_set_smt(sclp.mtid_prev);
        boot_cpu_addr = stap();
@@ -766,6 +770,9 @@ void __init smp_detect_cpus(void)
 
        /* Get CPU information */
        info = memblock_alloc(sizeof(*info), 8);
+       if (!info)
+               panic("%s: Failed to allocate %zu bytes align=0x%x\n",
+                     __func__, sizeof(*info), 8);
        smp_get_core_info(info, 1);
        /* Find boot CPU type */
        if (sclp.has_core_type) {
index 8992b04c0adea6329299e30c4aaf8013a94b2de1..8964a3f60aadbb1fdc5d7c884acd44d565c72265 100644 (file)
@@ -520,6 +520,9 @@ static void __init alloc_masks(struct sysinfo_15_1_x *info,
        nr_masks = max(nr_masks, 1);
        for (i = 0; i < nr_masks; i++) {
                mask->next = memblock_alloc(sizeof(*mask->next), 8);
+               if (!mask->next)
+                       panic("%s: Failed to allocate %zu bytes align=0x%x\n",
+                             __func__, sizeof(*mask->next), 8);
                mask = mask->next;
        }
 }
@@ -538,6 +541,9 @@ void __init topology_init_early(void)
        if (!MACHINE_HAS_TOPOLOGY)
                goto out;
        tl_info = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+       if (!tl_info)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
        info = tl_info;
        store_topology(info);
        pr_info("The CPU configuration topology of the machine is: %d %d %d %d %d %d / %d\n",
index bfba273c32c01ae70497f4cf32c1c8a28b17179a..71a12a4f49069624a85c5fb78a0f5c4241ba3b85 100644 (file)
@@ -313,6 +313,9 @@ static void __ref create_core_to_node_map(void)
        int i;
 
        emu_cores = memblock_alloc(sizeof(*emu_cores), 8);
+       if (!emu_cores)
+               panic("%s: Failed to allocate %zu bytes align=0x%x\n",
+                     __func__, sizeof(*emu_cores), 8);
        for (i = 0; i < ARRAY_SIZE(emu_cores->to_node_id); i++)
                emu_cores->to_node_id[i] = NODE_ID_FREE;
 }
index 2d1271e2a70db2a73813ce51923bd42ac88d85ef..8eb9e9743f5d8d4d85bf62c8a7bfebce8c248259 100644 (file)
@@ -92,8 +92,12 @@ static void __init numa_setup_memory(void)
        } while (cur_base < end_of_dram);
 
        /* Allocate and fill out node_data */
-       for (nid = 0; nid < MAX_NUMNODES; nid++)
+       for (nid = 0; nid < MAX_NUMNODES; nid++) {
                NODE_DATA(nid) = memblock_alloc(sizeof(pg_data_t), 8);
+               if (!NODE_DATA(nid))
+                       panic("%s: Failed to allocate %zu bytes align=0x%x\n",
+                             __func__, sizeof(pg_data_t), 8);
+       }
 
        for_each_online_node(nid) {
                unsigned long start_pfn, end_pfn;
index 7899b4f51fdddddfc61adc227453b358e0b444ed..8301a4378f502cdcf8ce87da797013708dab32ce 100644 (file)
@@ -556,7 +556,10 @@ static void __init ap325rxa_mv_mem_reserve(void)
        phys_addr_t phys;
        phys_addr_t size = CEU_BUFFER_MEMORY_SIZE;
 
-       phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE);
+       phys = memblock_phys_alloc(size, PAGE_SIZE);
+       if (!phys)
+               panic("Failed to allocate CEU memory\n");
+
        memblock_free(phys, size);
        memblock_remove(phys, size);
 
index 3c59019c4695ec99543192d3348109d11b0792c3..34e5414c556391469ed7a72119a653109f570e6b 100644 (file)
@@ -1476,12 +1476,18 @@ static void __init ecovec_mv_mem_reserve(void)
        phys_addr_t phys;
        phys_addr_t size = CEU_BUFFER_MEMORY_SIZE;
 
-       phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE);
+       phys = memblock_phys_alloc(size, PAGE_SIZE);
+       if (!phys)
+               panic("Failed to allocate CEU0 memory\n");
+
        memblock_free(phys, size);
        memblock_remove(phys, size);
        ceu0_dma_membase = phys;
 
-       phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE);
+       phys = memblock_phys_alloc(size, PAGE_SIZE);
+       if (!phys)
+               panic("Failed to allocate CEU1 memory\n");
+
        memblock_free(phys, size);
        memblock_remove(phys, size);
        ceu1_dma_membase = phys;
index b8bf67c86eab60438fce39b687f6fd1b29b91195..1cf9a47ac90ed7fcb1580e5cb4526d980d3d918f 100644 (file)
@@ -630,7 +630,10 @@ static void __init kfr2r09_mv_mem_reserve(void)
        phys_addr_t phys;
        phys_addr_t size = CEU_BUFFER_MEMORY_SIZE;
 
-       phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE);
+       phys = memblock_phys_alloc(size, PAGE_SIZE);
+       if (!phys)
+               panic("Failed to allocate CEU memory\n");
+
        memblock_free(phys, size);
        memblock_remove(phys, size);
 
index 03579faa4ce3efd88cb566577b3bd16ad51a7e1f..90702740f207c783f1a50b2c90ea22ab728da0a1 100644 (file)
@@ -630,7 +630,10 @@ static void __init migor_mv_mem_reserve(void)
        phys_addr_t phys;
        phys_addr_t size = CEU_BUFFER_MEMORY_SIZE;
 
-       phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE);
+       phys = memblock_phys_alloc(size, PAGE_SIZE);
+       if (!phys)
+               panic("Failed to allocate CEU memory\n");
+
        memblock_free(phys, size);
        memblock_remove(phys, size);
 
index 13c2d3ce78f4ffde8b547ff3f0dd9a27bf747f55..3674064816c73c7e6ee371f607d1b5b5f88bfbc9 100644 (file)
@@ -963,12 +963,18 @@ static void __init ms7724se_mv_mem_reserve(void)
        phys_addr_t phys;
        phys_addr_t size = CEU_BUFFER_MEMORY_SIZE;
 
-       phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE);
+       phys = memblock_phys_alloc(size, PAGE_SIZE);
+       if (!phys)
+               panic("Failed to allocate CEU0 memory\n");
+
        memblock_free(phys, size);
        memblock_remove(phys, size);
        ceu0_dma_membase = phys;
 
-       phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE);
+       phys = memblock_phys_alloc(size, PAGE_SIZE);
+       if (!phys)
+               panic("Failed to allocate CEU1 memory\n");
+
        memblock_free(phys, size);
        memblock_remove(phys, size);
        ceu1_dma_membase = phys;
index b9f9f1a5afdc1a2d71f61dce066f39e4cf11fc87..63d63a36f6f29e8299fa8625374daf52cfe8a33c 100644 (file)
@@ -168,7 +168,8 @@ void __init reserve_crashkernel(void)
        crash_size = PAGE_ALIGN(resource_size(&crashk_res));
        if (!crashk_res.start) {
                unsigned long max = memblock_end_of_DRAM() - memory_limit;
-               crashk_res.start = __memblock_alloc_base(crash_size, PAGE_SIZE, max);
+               crashk_res.start = memblock_phys_alloc_range(crash_size,
+                                                            PAGE_SIZE, 0, max);
                if (!crashk_res.start) {
                        pr_err("crashkernel allocation failed\n");
                        goto disable;
index a0fa4de03dd51d7d8a7ee41678e4099913a7127f..70621324db4128f5f805f80a3b58f1360fe2d527 100644 (file)
@@ -128,6 +128,9 @@ static pmd_t * __init one_md_table_init(pud_t *pud)
                pmd_t *pmd;
 
                pmd = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+               if (!pmd)
+                       panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                             __func__, PAGE_SIZE, PAGE_SIZE);
                pud_populate(&init_mm, pud, pmd);
                BUG_ON(pmd != pmd_offset(pud, 0));
        }
@@ -141,6 +144,9 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
                pte_t *pte;
 
                pte = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+               if (!pte)
+                       panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                             __func__, PAGE_SIZE, PAGE_SIZE);
                pmd_populate_kernel(&init_mm, pmd, pte);
                BUG_ON(pte != pte_offset_kernel(pmd, 0));
        }
@@ -196,7 +202,7 @@ void __init allocate_pgdat(unsigned int nid)
        get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
 
 #ifdef CONFIG_NEED_MULTIPLE_NODES
-       NODE_DATA(nid) = memblock_alloc_try_nid_nopanic(
+       NODE_DATA(nid) = memblock_alloc_try_nid(
                                sizeof(struct pglist_data),
                                SMP_CACHE_BYTES, MEMBLOCK_LOW_LIMIT,
                                MEMBLOCK_ALLOC_ACCESSIBLE, nid);
index c4bde614881086edf4febcd82e47da5e3918a527..f7e4439deb17629b3071359df114b8b7772c460a 100644 (file)
@@ -43,6 +43,10 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
        /* Node-local pgdat */
        NODE_DATA(nid) = memblock_alloc_node(sizeof(struct pglist_data),
                                             SMP_CACHE_BYTES, nid);
+       if (!NODE_DATA(nid))
+               panic("%s: Failed to allocate %zu bytes align=0x%x nid=%d\n",
+                     __func__, sizeof(struct pglist_data), SMP_CACHE_BYTES,
+                     nid);
 
        NODE_DATA(nid)->node_start_pfn = start_pfn;
        NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
index 42d7f2a7da6d080d138c931a1589b39e95735415..869b16c96157e52f238304031e47bd2c64e6153d 100644 (file)
@@ -32,9 +32,9 @@ void * __init prom_early_alloc(unsigned long size)
 {
        void *ret;
 
-       ret = memblock_alloc_from(size, SMP_CACHE_BYTES, 0UL);
-       if (ret != NULL)
-               memset(ret, 0, size);
+       ret = memblock_alloc(size, SMP_CACHE_BYTES);
+       if (!ret)
+               panic("%s: Failed to allocate %lu bytes\n", __func__, size);
 
        prom_early_allocated += size;
 
index 51c4d12c085338c9a293c3374256d9dccbe2aa44..fd2182a5c32db11414e690c66dfd7c2455bfc6e1 100644 (file)
@@ -624,8 +624,14 @@ void __init alloc_irqstack_bootmem(void)
 
                softirq_stack[i] = memblock_alloc_node(THREAD_SIZE,
                                                       THREAD_SIZE, node);
+               if (!softirq_stack[i])
+                       panic("%s: Failed to allocate %lu bytes align=%lx nid=%d\n",
+                             __func__, THREAD_SIZE, THREAD_SIZE, node);
                hardirq_stack[i] = memblock_alloc_node(THREAD_SIZE,
                                                       THREAD_SIZE, node);
+               if (!hardirq_stack[i])
+                       panic("%s: Failed to allocate %lu bytes align=%lx nid=%d\n",
+                             __func__, THREAD_SIZE, THREAD_SIZE, node);
        }
 }
 
index f45d876983f152fbda3ecab15e2a4a37be82c40e..a8275fea4b70c02019718fb0dfe93df1f6e12e6d 100644 (file)
@@ -1628,6 +1628,8 @@ static void __init pcpu_populate_pte(unsigned long addr)
                pud_t *new;
 
                new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
+               if (!new)
+                       goto err_alloc;
                pgd_populate(&init_mm, pgd, new);
        }
 
@@ -1636,6 +1638,8 @@ static void __init pcpu_populate_pte(unsigned long addr)
                pmd_t *new;
 
                new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
+               if (!new)
+                       goto err_alloc;
                pud_populate(&init_mm, pud, new);
        }
 
@@ -1644,8 +1648,16 @@ static void __init pcpu_populate_pte(unsigned long addr)
                pte_t *new;
 
                new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
+               if (!new)
+                       goto err_alloc;
                pmd_populate_kernel(&init_mm, pmd, new);
        }
+
+       return;
+
+err_alloc:
+       panic("%s: Failed to allocate %lu bytes align=%lx from=%lx\n",
+             __func__, PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
 }
 
 void __init setup_per_cpu_areas(void)
index d900952bfc5f3b0da140e722025f9aea21bfcef4..a8ff29821bdbc44466481b310fdedf3729c50047 100644 (file)
@@ -264,7 +264,7 @@ void __init mem_init(void)
        i = last_valid_pfn >> ((20 - PAGE_SHIFT) + 5);
        i += 1;
        sparc_valid_addr_bitmap = (unsigned long *)
-               memblock_alloc_from(i << 2, SMP_CACHE_BYTES, 0UL);
+               memblock_alloc(i << 2, SMP_CACHE_BYTES);
 
        if (sparc_valid_addr_bitmap == NULL) {
                prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n");
index ef340e8f209ff173114dc8ff77c7e12d5d3075c8..f2d70ff7a28427a2b83d82a7c075c17d2a62f123 100644 (file)
@@ -1809,6 +1809,8 @@ static unsigned long __ref kernel_map_range(unsigned long pstart,
 
                        new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE,
                                                  PAGE_SIZE);
+                       if (!new)
+                               goto err_alloc;
                        alloc_bytes += PAGE_SIZE;
                        pgd_populate(&init_mm, pgd, new);
                }
@@ -1822,6 +1824,8 @@ static unsigned long __ref kernel_map_range(unsigned long pstart,
                        }
                        new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE,
                                                  PAGE_SIZE);
+                       if (!new)
+                               goto err_alloc;
                        alloc_bytes += PAGE_SIZE;
                        pud_populate(&init_mm, pud, new);
                }
@@ -1836,6 +1840,8 @@ static unsigned long __ref kernel_map_range(unsigned long pstart,
                        }
                        new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE,
                                                  PAGE_SIZE);
+                       if (!new)
+                               goto err_alloc;
                        alloc_bytes += PAGE_SIZE;
                        pmd_populate_kernel(&init_mm, pmd, new);
                }
@@ -1855,6 +1861,11 @@ static unsigned long __ref kernel_map_range(unsigned long pstart,
        }
 
        return alloc_bytes;
+
+err_alloc:
+       panic("%s: Failed to allocate %lu bytes align=%lx from=%lx\n",
+             __func__, PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
+       return -ENOMEM;
 }
 
 static void __init flush_all_kernel_tsbs(void)
index b609362e846fcce0ceceba0795598cad03358ec7..aaebbc00d26236c01688ebc50dde58fb2921ef24 100644 (file)
@@ -303,13 +303,19 @@ static void __init srmmu_nocache_init(void)
 
        bitmap_bits = srmmu_nocache_size >> SRMMU_NOCACHE_BITMAP_SHIFT;
 
-       srmmu_nocache_pool = memblock_alloc_from(srmmu_nocache_size,
-                                                SRMMU_NOCACHE_ALIGN_MAX, 0UL);
+       srmmu_nocache_pool = memblock_alloc(srmmu_nocache_size,
+                                           SRMMU_NOCACHE_ALIGN_MAX);
+       if (!srmmu_nocache_pool)
+               panic("%s: Failed to allocate %lu bytes align=0x%x\n",
+                     __func__, srmmu_nocache_size, SRMMU_NOCACHE_ALIGN_MAX);
        memset(srmmu_nocache_pool, 0, srmmu_nocache_size);
 
        srmmu_nocache_bitmap =
-               memblock_alloc_from(BITS_TO_LONGS(bitmap_bits) * sizeof(long),
-                                   SMP_CACHE_BYTES, 0UL);
+               memblock_alloc(BITS_TO_LONGS(bitmap_bits) * sizeof(long),
+                              SMP_CACHE_BYTES);
+       if (!srmmu_nocache_bitmap)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     BITS_TO_LONGS(bitmap_bits) * sizeof(long));
        bit_map_init(&srmmu_nocache_map, srmmu_nocache_bitmap, bitmap_bits);
 
        srmmu_swapper_pg_dir = __srmmu_get_nocache(SRMMU_PGD_TABLE_SIZE, SRMMU_PGD_TABLE_SIZE);
@@ -467,7 +473,9 @@ static void __init sparc_context_init(int numctx)
        unsigned long size;
 
        size = numctx * sizeof(struct ctx_list);
-       ctx_list_pool = memblock_alloc_from(size, SMP_CACHE_BYTES, 0UL);
+       ctx_list_pool = memblock_alloc(size, SMP_CACHE_BYTES);
+       if (!ctx_list_pool)
+               panic("%s: Failed to allocate %lu bytes\n", __func__, size);
 
        for (ctx = 0; ctx < numctx; ctx++) {
                struct ctx_list *clist;
index d80cfb1d943077c5551bd9c1a60528cf7eec4c62..6e5be5fb4143695379ae4fc218971d23446d0b2f 100644 (file)
@@ -649,6 +649,9 @@ static int __init eth_setup(char *str)
        }
 
        new = memblock_alloc(sizeof(*new), SMP_CACHE_BYTES);
+       if (!new)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(*new));
 
        INIT_LIST_HEAD(&new->list);
        new->index = n;
index 046fa9ea0ccc7dae2ee80381c224916700e612d1..596e7056f37607229afa47e280f01ede39b42412 100644 (file)
@@ -1576,6 +1576,9 @@ static int __init vector_setup(char *str)
                return 1;
        }
        new = memblock_alloc(sizeof(*new), SMP_CACHE_BYTES);
+       if (!new)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(*new));
        INIT_LIST_HEAD(&new->list);
        new->unit = n;
        new->arguments = str;
index ce169ea87e6189e6ca025a41711638ab5ff9d483..1dcd310cb34d04417e2696d1bcecf54a3e6031d4 100644 (file)
@@ -37,6 +37,8 @@ int __init read_initrd(void)
        }
 
        area = memblock_alloc(size, SMP_CACHE_BYTES);
+       if (!area)
+               panic("%s: Failed to allocate %llu bytes\n", __func__, size);
 
        if (load_initrd(initrd, area, size) == -1)
                return 0;
index 799b571a8f884b9356b3ea9f6c849c51337e3f0d..99aa11bf53d108d9bb5878d70e7b762b07334b1d 100644 (file)
@@ -66,6 +66,10 @@ static void __init one_page_table_init(pmd_t *pmd)
        if (pmd_none(*pmd)) {
                pte_t *pte = (pte_t *) memblock_alloc_low(PAGE_SIZE,
                                                          PAGE_SIZE);
+               if (!pte)
+                       panic("%s: Failed to allocate %lu bytes align=%lx\n",
+                             __func__, PAGE_SIZE, PAGE_SIZE);
+
                set_pmd(pmd, __pmd(_KERNPG_TABLE +
                                           (unsigned long) __pa(pte)));
                if (pte != pte_offset_kernel(pmd, 0))
@@ -77,6 +81,10 @@ static void __init one_md_table_init(pud_t *pud)
 {
 #ifdef CONFIG_3_LEVEL_PGTABLES
        pmd_t *pmd_table = (pmd_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
+       if (!pmd_table)
+               panic("%s: Failed to allocate %lu bytes align=%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
+
        set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table)));
        if (pmd_table != pmd_offset(pud, 0))
                BUG();
@@ -126,6 +134,10 @@ static void __init fixaddr_user_init( void)
 
        fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir);
        v = (unsigned long) memblock_alloc_low(size, PAGE_SIZE);
+       if (!v)
+               panic("%s: Failed to allocate %lu bytes align=%lx\n",
+                     __func__, size, PAGE_SIZE);
+
        memcpy((void *) v , (void *) FIXADDR_USER_START, size);
        p = __pa(v);
        for ( ; size > 0; size -= PAGE_SIZE, vaddr += PAGE_SIZE,
@@ -146,6 +158,10 @@ void __init paging_init(void)
 
        empty_zero_page = (unsigned long *) memblock_alloc_low(PAGE_SIZE,
                                                               PAGE_SIZE);
+       if (!empty_zero_page)
+               panic("%s: Failed to allocate %lu bytes align=%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
+
        for (i = 0; i < ARRAY_SIZE(zones_size); i++)
                zones_size[i] = 0;
 
index 4b0cb68c355ac0458653613be25571f557393e04..d3239cf2e83753c4388c150e22bb44521ac60895 100644 (file)
@@ -207,6 +207,10 @@ request_standard_resources(struct meminfo *mi)
                        continue;
 
                res = memblock_alloc_low(sizeof(*res), SMP_CACHE_BYTES);
+               if (!res)
+                       panic("%s: Failed to allocate %zu bytes align=%x\n",
+                             __func__, sizeof(*res), SMP_CACHE_BYTES);
+
                res->name  = "System RAM";
                res->start = mi->bank[i].start;
                res->end   = mi->bank[i].start + mi->bank[i].size - 1;
index a40219291965de0cce772c0c6a2c763358a68b15..aa2060beb40840d91b9023fce78f116f26c8952d 100644 (file)
@@ -145,8 +145,13 @@ static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr,
                unsigned long prot)
 {
        if (pmd_none(*pmd)) {
-               pte_t *pte = memblock_alloc(PTRS_PER_PTE * sizeof(pte_t),
-                                           PTRS_PER_PTE * sizeof(pte_t));
+               size_t size = PTRS_PER_PTE * sizeof(pte_t);
+               pte_t *pte = memblock_alloc(size, size);
+
+               if (!pte)
+                       panic("%s: Failed to allocate %zu bytes align=%zx\n",
+                             __func__, size, size);
+
                __pmd_populate(pmd, __pa(pte) | prot);
        }
        BUG_ON(pmd_bad(*pmd));
@@ -349,6 +354,9 @@ static void __init devicemaps_init(void)
         * Allocate the vector page early.
         */
        vectors = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+       if (!vectors)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
 
        for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
                pmd_clear(pmd_off_k(addr));
@@ -426,6 +434,9 @@ void __init paging_init(void)
 
        /* allocate the zero page. */
        zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+       if (!zero_page)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, PAGE_SIZE, PAGE_SIZE);
 
        bootmem_init();
 
index 2624de16cd7abd3d3443d411abc5fb57919e5f70..8dcbf68907146512a839da60817c6b292c135e47 100644 (file)
@@ -935,6 +935,9 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table)
 #define HPET_RESOURCE_NAME_SIZE 9
        hpet_res = memblock_alloc(sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE,
                                  SMP_CACHE_BYTES);
+       if (!hpet_res)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE);
 
        hpet_res->name = (void *)&hpet_res[1];
        hpet_res->flags = IORESOURCE_MEM;
index 264e3221d9233eaf0505338ae6f21c365540f1d6..53aa234a6803f295aa7d24fc81e17c38dd99b216 100644 (file)
@@ -2581,6 +2581,8 @@ static struct resource * __init ioapic_setup_resources(void)
        n *= nr_ioapics;
 
        mem = memblock_alloc(n, SMP_CACHE_BYTES);
+       if (!mem)
+               panic("%s: Failed to allocate %lu bytes\n", __func__, n);
        res = (void *)mem;
 
        mem += sizeof(struct resource) * nr_ioapics;
@@ -2625,6 +2627,9 @@ fake_ioapic_page:
 #endif
                        ioapic_phys = (unsigned long)memblock_alloc(PAGE_SIZE,
                                                                    PAGE_SIZE);
+                       if (!ioapic_phys)
+                               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                                     __func__, PAGE_SIZE, PAGE_SIZE);
                        ioapic_phys = __pa(ioapic_phys);
                }
                set_fixmap_nocache(idx, ioapic_phys);
index 666e4af145a25dd6be6113269259c45d6aa4a895..2879e234e1936f76e59383d56ee5c26b58ce6b53 100644 (file)
@@ -776,7 +776,7 @@ u64 __init e820__memblock_alloc_reserved(u64 size, u64 align)
 {
        u64 addr;
 
-       addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
+       addr = memblock_phys_alloc(size, align);
        if (addr) {
                e820__range_update_kexec(addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED);
                pr_info("update e820_table_kexec for e820__memblock_alloc_reserved()\n");
@@ -1097,6 +1097,9 @@ void __init e820__reserve_resources(void)
 
        res = memblock_alloc(sizeof(*res) * e820_table->nr_entries,
                             SMP_CACHE_BYTES);
+       if (!res)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(*res) * e820_table->nr_entries);
        e820_res = res;
 
        for (i = 0; i < e820_table->nr_entries; i++) {
index 13af08827eefc61e4252f7ffc6cc014f661e1f27..4bf46575568a237678eb4a710d885cd4e033d07f 100644 (file)
@@ -106,22 +106,22 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size,
        void *ptr;
 
        if (!node_online(node) || !NODE_DATA(node)) {
-               ptr = memblock_alloc_from_nopanic(size, align, goal);
+               ptr = memblock_alloc_from(size, align, goal);
                pr_info("cpu %d has no node %d or node-local memory\n",
                        cpu, node);
                pr_debug("per cpu data for cpu%d %lu bytes at %016lx\n",
                         cpu, size, __pa(ptr));
        } else {
-               ptr = memblock_alloc_try_nid_nopanic(size, align, goal,
-                                                    MEMBLOCK_ALLOC_ACCESSIBLE,
-                                                    node);
+               ptr = memblock_alloc_try_nid(size, align, goal,
+                                            MEMBLOCK_ALLOC_ACCESSIBLE,
+                                            node);
 
                pr_debug("per cpu data for cpu%d %lu bytes on node%d at %016lx\n",
                         cpu, size, node, __pa(ptr));
        }
        return ptr;
 #else
-       return memblock_alloc_from_nopanic(size, align, goal);
+       return memblock_alloc_from(size, align, goal);
 #endif
 }
 
index 462fde83b515e60c8b83aea1fa57827eccd09f22..8dc0fc0b1382b6cde08e2774449b39b0607a1a64 100644 (file)
@@ -24,14 +24,16 @@ extern struct range pfn_mapped[E820_MAX_ENTRIES];
 
 static p4d_t tmp_p4d_table[MAX_PTRS_PER_P4D] __initdata __aligned(PAGE_SIZE);
 
-static __init void *early_alloc(size_t size, int nid, bool panic)
+static __init void *early_alloc(size_t size, int nid, bool should_panic)
 {
-       if (panic)
-               return memblock_alloc_try_nid(size, size,
-                       __pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_ACCESSIBLE, nid);
-       else
-               return memblock_alloc_try_nid_nopanic(size, size,
+       void *ptr = memblock_alloc_try_nid(size, size,
                        __pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_ACCESSIBLE, nid);
+
+       if (!ptr && should_panic)
+               panic("%pS: Failed to allocate page, nid=%d from=%lx\n",
+                     (void *)_RET_IP_, nid, __pa(MAX_DMA_ADDRESS));
+
+       return ptr;
 }
 
 static void __init kasan_populate_pmd(pmd_t *pmd, unsigned long addr,
index 12c1b7a83ed7b03145ed487e1fbe54a8f60c78cd..dfb6c4df639ab14f647a3efa4b25c2b8449aa0d7 100644 (file)
@@ -195,15 +195,11 @@ static void __init alloc_node_data(int nid)
         * Allocate node data.  Try node-local memory and then any node.
         * Never allocate in DMA zone.
         */
-       nd_pa = memblock_phys_alloc_nid(nd_size, SMP_CACHE_BYTES, nid);
+       nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid);
        if (!nd_pa) {
-               nd_pa = __memblock_alloc_base(nd_size, SMP_CACHE_BYTES,
-                                             MEMBLOCK_ALLOC_ACCESSIBLE);
-               if (!nd_pa) {
-                       pr_err("Cannot find %zu bytes in any node (initial node: %d)\n",
-                              nd_size, nid);
-                       return;
-               }
+               pr_err("Cannot find %zu bytes in any node (initial node: %d)\n",
+                      nd_size, nid);
+               return;
        }
        nd = __va(nd_pa);
 
index b4ab779f1d47aa0bc634a5eecf18fbcf79e67d9f..ac9e7bf49b6670216f9220979a261603304cc311 100644 (file)
@@ -141,6 +141,9 @@ void * __init prom_early_alloc(unsigned long size)
                 * wasted bootmem) and hand off chunks of it to callers.
                 */
                res = memblock_alloc(chunk_size, SMP_CACHE_BYTES);
+               if (!res)
+                       panic("%s: Failed to allocate %zu bytes\n", __func__,
+                             chunk_size);
                BUG_ON(!res);
                prom_early_allocated += chunk_size;
                memset(res, 0, chunk_size);
index 055e37e43541ed17d11cf4a194085b7fc3a3192c..95ce9b5be41124cb6f48db15d433a069fc76f69d 100644 (file)
@@ -181,8 +181,15 @@ static void p2m_init_identity(unsigned long *p2m, unsigned long pfn)
 
 static void * __ref alloc_p2m_page(void)
 {
-       if (unlikely(!slab_is_available()))
-               return memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+       if (unlikely(!slab_is_available())) {
+               void *ptr = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+
+               if (!ptr)
+                       panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                             __func__, PAGE_SIZE, PAGE_SIZE);
+
+               return ptr;
+       }
 
        return (void *)__get_free_page(GFP_KERNEL);
 }
index 1734cda6bc4ae5f51f3b44ebfe63fb21fe0c2ecb..af7152560bc3ff3fd6a1d6bb0c194193057004f2 100644 (file)
@@ -45,6 +45,10 @@ static void __init populate(void *start, void *end)
        pmd_t *pmd = pmd_offset(pgd, vaddr);
        pte_t *pte = memblock_alloc(n_pages * sizeof(pte_t), PAGE_SIZE);
 
+       if (!pte)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, n_pages * sizeof(pte_t), PAGE_SIZE);
+
        pr_debug("%s: %p - %p\n", __func__, start, end);
 
        for (i = j = 0; i < n_pmds; ++i) {
@@ -52,8 +56,10 @@ static void __init populate(void *start, void *end)
 
                for (k = 0; k < PTRS_PER_PTE; ++k, ++j) {
                        phys_addr_t phys =
-                               memblock_alloc_base(PAGE_SIZE, PAGE_SIZE,
-                                                   MEMBLOCK_ALLOC_ANYWHERE);
+                               memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
+
+                       if (!phys)
+                               panic("Failed to allocate page table page\n");
 
                        set_pte(pte + j, pfn_pte(PHYS_PFN(phys), PAGE_KERNEL));
                }
index a4dcfd39bc5c1c54f170e83c405f51980a8e84f4..2fb7d117222840da05f44cf7eed39348d27502e5 100644 (file)
@@ -32,6 +32,9 @@ static void * __init init_pmd(unsigned long vaddr, unsigned long n_pages)
                 __func__, vaddr, n_pages);
 
        pte = memblock_alloc_low(n_pages * sizeof(pte_t), PAGE_SIZE);
+       if (!pte)
+               panic("%s: Failed to allocate %zu bytes align=%lx\n",
+                     __func__, n_pages * sizeof(pte_t), PAGE_SIZE);
 
        for (i = 0; i < n_pages; ++i)
                pte_clear(NULL, 0, pte + i);
index 6b78ec56a4f2daef624edb1bb025a76aa3520b52..4673ebe4225534dc9965089ba76ad127963dcb0f 100644 (file)
@@ -500,8 +500,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
        if (!q->stats)
                goto fail_stats;
 
-       q->backing_dev_info->ra_pages =
-                       (VM_MAX_READAHEAD * 1024) / PAGE_SIZE;
+       q->backing_dev_info->ra_pages = VM_READAHEAD_PAGES;
        q->backing_dev_info->capabilities = BDI_CAP_CGROUP_WRITEBACK;
        q->backing_dev_info->name = "block";
        q->node = node_id;
index d0cd58534781d8b51f62fc256f30d0d04d96182a..5d7fb2eecce4540ca4ce4279cdc75c0cbb871b91 100644 (file)
@@ -351,6 +351,9 @@ void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
        struct clk_iomap *io;
 
        io = memblock_alloc(sizeof(*io), SMP_CACHE_BYTES);
+       if (!io)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(*io));
 
        io->mem = mem;
 
index ec4fd253a4e92aa0375d10d8fd70873ed54f9f26..d168c87c7d3085655d1fd627a6b65b792129cb03 100644 (file)
@@ -333,7 +333,7 @@ int __init firmware_map_add_early(u64 start, u64 end, const char *type)
 {
        struct firmware_map_entry *entry;
 
-       entry = memblock_alloc_nopanic(sizeof(struct firmware_map_entry),
+       entry = memblock_alloc(sizeof(struct firmware_map_entry),
                               SMP_CACHE_BYTES);
        if (WARN_ON(!entry))
                return -ENOMEM;
index 8be7a83ced9b5351e194c0bf0b98abc39df50eb3..aa9fec80492d167f720a07ee58f8e0196d858c3a 100644 (file)
@@ -261,7 +261,7 @@ static const struct migrate_vma_ops nouveau_dmem_fault_migrate_ops = {
        .finalize_and_map       = nouveau_dmem_fault_finalize_and_map,
 };
 
-static int
+static vm_fault_t
 nouveau_dmem_fault(struct hmm_devmem *devmem,
                   struct vm_area_struct *vma,
                   unsigned long addr,
index 0a0b8e1f4236f701640a5c0e7c9056c0c3c88d01..6a844125cf2d83107dbfdb7d8adfc42e6b2d16c4 100644 (file)
@@ -485,7 +485,7 @@ int __init smu_init (void)
         * SMU based G5s need some memory below 2Gb. Thankfully this is
         * called at a time where memblock is still available.
         */
-       smu_cmdbuf_abs = memblock_alloc_base(4096, 4096, 0x80000000UL);
+       smu_cmdbuf_abs = memblock_phys_alloc_range(4096, 4096, 0, 0x80000000UL);
        if (smu_cmdbuf_abs == 0) {
                printk(KERN_ERR "SMU: Command buffer allocation failed !\n");
                ret = -EINVAL;
@@ -493,6 +493,9 @@ int __init smu_init (void)
        }
 
        smu = memblock_alloc(sizeof(struct smu_device), SMP_CACHE_BYTES);
+       if (!smu)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     sizeof(struct smu_device));
 
        spin_lock_init(&smu->lock);
        INIT_LIST_HEAD(&smu->cmd_list);
index 3a7c363265893ade48ae5b3f929b039b0673bcdb..0b096ddc9c1e62cd6f5bc0ba050dee8fa4936017 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/blkdev.h>
 #include <linux/slab.h>
 #include <linux/crc32c.h>
-#include <linux/flex_array.h>
 #include <linux/async_tx.h>
 #include <linux/raid/md_p.h>
 #include "md.h"
@@ -165,7 +164,7 @@ ops_run_partial_parity(struct stripe_head *sh, struct raid5_percpu *percpu,
                       struct dma_async_tx_descriptor *tx)
 {
        int disks = sh->disks;
-       struct page **srcs = flex_array_get(percpu->scribble, 0);
+       struct page **srcs = percpu->scribble;
        int count = 0, pd_idx = sh->pd_idx, i;
        struct async_submit_ctl submit;
 
@@ -196,8 +195,7 @@ ops_run_partial_parity(struct stripe_head *sh, struct raid5_percpu *percpu,
        }
 
        init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST, tx,
-                         NULL, sh, flex_array_get(percpu->scribble, 0)
-                         + sizeof(struct page *) * (sh->disks + 2));
+                         NULL, sh, (void *) (srcs + sh->disks + 2));
 
        if (count == 1)
                tx = async_memcpy(sh->ppl_page, srcs[0], 0, 0, PAGE_SIZE,
index cecea901ab8c5f666a7eb7ea4c345323efcbff1a..77ffd09be486da312dd0e3d02067672ad69ee340 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/slab.h>
 #include <linux/ratelimit.h>
 #include <linux/nodemask.h>
-#include <linux/flex_array.h>
 
 #include <trace/events/block.h>
 #include <linux/list_sort.h>
@@ -1394,22 +1393,16 @@ static void ops_complete_compute(void *stripe_head_ref)
 }
 
 /* return a pointer to the address conversion region of the scribble buffer */
-static addr_conv_t *to_addr_conv(struct stripe_head *sh,
-                                struct raid5_percpu *percpu, int i)
+static struct page **to_addr_page(struct raid5_percpu *percpu, int i)
 {
-       void *addr;
-
-       addr = flex_array_get(percpu->scribble, i);
-       return addr + sizeof(struct page *) * (sh->disks + 2);
+       return percpu->scribble + i * percpu->scribble_obj_size;
 }
 
 /* return a pointer to the address conversion region of the scribble buffer */
-static struct page **to_addr_page(struct raid5_percpu *percpu, int i)
+static addr_conv_t *to_addr_conv(struct stripe_head *sh,
+                                struct raid5_percpu *percpu, int i)
 {
-       void *addr;
-
-       addr = flex_array_get(percpu->scribble, i);
-       return addr;
+       return (void *) (to_addr_page(percpu, i) + sh->disks + 2);
 }
 
 static struct dma_async_tx_descriptor *
@@ -2238,21 +2231,23 @@ static int grow_stripes(struct r5conf *conf, int num)
  * calculate over all devices (not just the data blocks), using zeros in place
  * of the P and Q blocks.
  */
-static struct flex_array *scribble_alloc(int num, int cnt, gfp_t flags)
+static int scribble_alloc(struct raid5_percpu *percpu,
+                         int num, int cnt, gfp_t flags)
 {
-       struct flex_array *ret;
-       size_t len;
+       size_t obj_size =
+               sizeof(struct page *) * (num+2) +
+               sizeof(addr_conv_t) * (num+2);
+       void *scribble;
 
-       len = sizeof(struct page *) * (num+2) + sizeof(addr_conv_t) * (num+2);
-       ret = flex_array_alloc(len, cnt, flags);
-       if (!ret)
-               return NULL;
-       /* always prealloc all elements, so no locking is required */
-       if (flex_array_prealloc(ret, 0, cnt, flags)) {
-               flex_array_free(ret);
-               return NULL;
-       }
-       return ret;
+       scribble = kvmalloc_array(cnt, obj_size, flags);
+       if (!scribble)
+               return -ENOMEM;
+
+       kvfree(percpu->scribble);
+
+       percpu->scribble = scribble;
+       percpu->scribble_obj_size = obj_size;
+       return 0;
 }
 
 static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors)
@@ -2270,23 +2265,18 @@ static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors)
                return 0;
        mddev_suspend(conf->mddev);
        get_online_cpus();
+
        for_each_present_cpu(cpu) {
                struct raid5_percpu *percpu;
-               struct flex_array *scribble;
 
                percpu = per_cpu_ptr(conf->percpu, cpu);
-               scribble = scribble_alloc(new_disks,
-                                         new_sectors / STRIPE_SECTORS,
-                                         GFP_NOIO);
-
-               if (scribble) {
-                       flex_array_free(percpu->scribble);
-                       percpu->scribble = scribble;
-               } else {
-                       err = -ENOMEM;
+               err = scribble_alloc(percpu, new_disks,
+                                    new_sectors / STRIPE_SECTORS,
+                                    GFP_NOIO);
+               if (err)
                        break;
-               }
        }
+
        put_online_cpus();
        mddev_resume(conf->mddev);
        if (!err) {
@@ -6742,25 +6732,26 @@ raid5_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 static void free_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu)
 {
        safe_put_page(percpu->spare_page);
-       if (percpu->scribble)
-               flex_array_free(percpu->scribble);
        percpu->spare_page = NULL;
+       kvfree(percpu->scribble);
        percpu->scribble = NULL;
 }
 
 static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu)
 {
-       if (conf->level == 6 && !percpu->spare_page)
+       if (conf->level == 6 && !percpu->spare_page) {
                percpu->spare_page = alloc_page(GFP_KERNEL);
-       if (!percpu->scribble)
-               percpu->scribble = scribble_alloc(max(conf->raid_disks,
-                                                     conf->previous_raid_disks),
-                                                 max(conf->chunk_sectors,
-                                                     conf->prev_chunk_sectors)
-                                                  / STRIPE_SECTORS,
-                                                 GFP_KERNEL);
-
-       if (!percpu->scribble || (conf->level == 6 && !percpu->spare_page)) {
+               if (!percpu->spare_page)
+                       return -ENOMEM;
+       }
+
+       if (scribble_alloc(percpu,
+                          max(conf->raid_disks,
+                              conf->previous_raid_disks),
+                          max(conf->chunk_sectors,
+                              conf->prev_chunk_sectors)
+                          / STRIPE_SECTORS,
+                          GFP_KERNEL)) {
                free_scratch_buffer(conf, percpu);
                return -ENOMEM;
        }
index 8474c224127bf3f47266e8570458945230626692..cf991f13403eb224ec7f467f4f57874e21ba4c89 100644 (file)
@@ -638,10 +638,11 @@ struct r5conf {
        /* per cpu variables */
        struct raid5_percpu {
                struct page     *spare_page; /* Used when checking P/Q in raid6 */
-               struct flex_array *scribble;   /* space for constructing buffer
-                                             * lists and performing address
-                                             * conversions
-                                             */
+               void            *scribble;  /* space for constructing buffer
+                                            * lists and performing address
+                                            * conversions
+                                            */
+               int scribble_obj_size;
        } __percpu *percpu;
        int scribble_disks;
        int scribble_sectors;
index 9cc1461aac7dd0a6d073571111bdad94f9902655..4734223ab7022f8cd1b3cc484f0538df0785dac8 100644 (file)
@@ -1181,7 +1181,13 @@ int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
 
 static void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
 {
-       return memblock_alloc(size, align);
+       void *ptr = memblock_alloc(size, align);
+
+       if (!ptr)
+               panic("%s: Failed to allocate %llu bytes align=0x%llx\n",
+                     __func__, size, align);
+
+       return ptr;
 }
 
 bool __init early_init_dt_verify(void *params)
index e773063c6de95cf5310868548df4801fbeac6344..6a36bc0b3d6414e556a9b253f71ac3119252233f 100644 (file)
@@ -31,28 +31,18 @@ static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
        phys_addr_t *res_base)
 {
        phys_addr_t base;
-       /*
-        * We use __memblock_alloc_base() because memblock_alloc_base()
-        * panic()s on allocation failure.
-        */
+
        end = !end ? MEMBLOCK_ALLOC_ANYWHERE : end;
        align = !align ? SMP_CACHE_BYTES : align;
-       base = __memblock_alloc_base(size, align, end);
+       base = memblock_find_in_range(start, end, size, align);
        if (!base)
                return -ENOMEM;
 
-       /*
-        * Check if the allocated region fits in to start..end window
-        */
-       if (base < start) {
-               memblock_free(base, size);
-               return -ENOMEM;
-       }
-
        *res_base = base;
        if (nomap)
                return memblock_remove(base, size);
-       return 0;
+
+       return memblock_reserve(base, size);
 }
 
 /**
index 66037511f2d707ae0d0f2392cfcf5e607500c4df..cccde756b51097d4c762b6e41ea1770d5118466e 100644 (file)
@@ -2241,7 +2241,13 @@ static struct device_node *overlay_base_root;
 
 static void * __init dt_alloc_memory(u64 size, u64 align)
 {
-       return memblock_alloc(size, align);
+       void *ptr = memblock_alloc(size, align);
+
+       if (!ptr)
+               panic("%s: Failed to allocate %llu bytes align=0x%llx\n",
+                     __func__, size, align);
+
+       return ptr;
 }
 
 /*
index d2652dccc69975b6733fa597863561dc5bb92dc0..c9cfb100ecdca4e2d75800340cf8b90ee418f2fe 100644 (file)
@@ -94,7 +94,7 @@ static void * __init xdbc_get_page(dma_addr_t *dma_addr)
 {
        void *virt;
 
-       virt = memblock_alloc_nopanic(PAGE_SIZE, PAGE_SIZE);
+       virt = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
        if (!virt)
                return NULL;
 
index bb7888429be6b98dec9cd7fcfd13f9827a515d05..877baf2a94f4070a345923e05467cf9e320a8b2c 100644 (file)
@@ -214,10 +214,13 @@ retry:
        /*
         * Get IO TLB memory from any location.
         */
-       if (early)
+       if (early) {
                xen_io_tlb_start = memblock_alloc(PAGE_ALIGN(bytes),
                                                  PAGE_SIZE);
-       else {
+               if (!xen_io_tlb_start)
+                       panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                             __func__, PAGE_ALIGN(bytes), PAGE_SIZE);
+       } else {
 #define SLABS_PER_PAGE (1 << (PAGE_SHIFT - IO_TLB_SHIFT))
 #define IO_TLB_MIN_SLABS ((1<<20) >> IO_TLB_SHIFT)
                while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) {
index 48ce50484e80e280990dc822bf3e833025cbbc10..10d3bd3f534bce3a40b780d176fdb95ed4e0a772 100644 (file)
@@ -92,7 +92,7 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
                return ret;
 
        if (v9ses->cache)
-               sb->s_bdi->ra_pages = (VM_MAX_READAHEAD * 1024)/PAGE_SIZE;
+               sb->s_bdi->ra_pages = VM_READAHEAD_PAGES;
 
        sb->s_flags |= SB_ACTIVE | SB_DIRSYNC;
        if (!v9ses->cache)
index dcd07fe99871b9b38541293b164ac1cf8328a005..e684f6769b1510796d31f3f80ec15724f17e3f49 100644 (file)
@@ -399,7 +399,7 @@ static int afs_fill_super(struct super_block *sb,
        ret = super_setup_bdi(sb);
        if (ret)
                return ret;
-       sb->s_bdi->ra_pages     = VM_MAX_READAHEAD * 1024 / PAGE_SIZE;
+       sb->s_bdi->ra_pages     = VM_READAHEAD_PAGES;
 
        /* allocate the root inode and dentry */
        if (as->dyn_root) {
index f0cdb53f3e2dc86f0dee6080d3b719482214170d..6fe9197f6ee44c54a726435da5a83ac4a7490ac1 100644 (file)
@@ -2958,7 +2958,7 @@ int open_ctree(struct super_block *sb,
        sb->s_bdi->congested_fn = btrfs_congested_fn;
        sb->s_bdi->congested_data = fs_info;
        sb->s_bdi->capabilities |= BDI_CAP_CGROUP_WRITEBACK;
-       sb->s_bdi->ra_pages = VM_MAX_READAHEAD * SZ_1K / PAGE_SIZE;
+       sb->s_bdi->ra_pages = VM_READAHEAD_PAGES;
        sb->s_bdi->ra_pages *= btrfs_super_num_devices(disk_super);
        sb->s_bdi->ra_pages = max(sb->s_bdi->ra_pages, SZ_4M / PAGE_SIZE);
 
index c2d4099429be0d73c32c87a82dc1a939e89d009b..16750ed591aea4a0954a72eaa5ca05b09818b3a0 100644 (file)
@@ -1010,7 +1010,7 @@ static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb)
        if (err)
                return err;
 
-       sb->s_bdi->ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_SIZE;
+       sb->s_bdi->ra_pages = VM_READAHEAD_PAGES;
        /* fuse does it's own writeback accounting */
        sb->s_bdi->capabilities = BDI_CAP_NO_ACCT_WB | BDI_CAP_STRICTLIMIT;
 
index 5d99376d2369c219e372a847adcd8d12d150341f..c88088d92613595eecf6f1119a2c53f0b63bab27 100644 (file)
@@ -923,7 +923,7 @@ static void io_async_list_note(int rw, struct io_kiocb *req, size_t len)
                /* Use 8x RA size as a decent limiter for both reads/writes */
                max_pages = filp->f_ra.ra_pages;
                if (!max_pages)
-                       max_pages = VM_MAX_READAHEAD >> (PAGE_SHIFT - 10);
+                       max_pages = VM_READAHEAD_PAGES;
                max_pages *= 8;
 
                /* If max pages are exceeded, reset the state */
index 5ab1849971b460bb7d5539f5c7a01a1af1e016c4..f5ebdd87afb244fefa0cd3342728e1ade5342d83 100644 (file)
@@ -59,6 +59,7 @@
 #include <linux/capability.h>
 #include <linux/file.h>
 #include <linux/fdtable.h>
+#include <linux/generic-radix-tree.h>
 #include <linux/string.h>
 #include <linux/seq_file.h>
 #include <linux/namei.h>
@@ -92,7 +93,6 @@
 #include <linux/sched/coredump.h>
 #include <linux/sched/debug.h>
 #include <linux/sched/stat.h>
-#include <linux/flex_array.h>
 #include <linux/posix-timers.h>
 #include <trace/events/oom.h>
 #include "internal.h"
@@ -2142,11 +2142,12 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
        struct task_struct *task;
        struct mm_struct *mm;
        unsigned long nr_files, pos, i;
-       struct flex_array *fa = NULL;
-       struct map_files_info info;
+       GENRADIX(struct map_files_info) fa;
        struct map_files_info *p;
        int ret;
 
+       genradix_init(&fa);
+
        ret = -ENOENT;
        task = get_proc_task(file_inode(file));
        if (!task)
@@ -2178,35 +2179,22 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
         */
 
        for (vma = mm->mmap, pos = 2; vma; vma = vma->vm_next) {
-               if (vma->vm_file && ++pos > ctx->pos)
-                       nr_files++;
-       }
+               if (!vma->vm_file)
+                       continue;
+               if (++pos <= ctx->pos)
+                       continue;
 
-       if (nr_files) {
-               fa = flex_array_alloc(sizeof(info), nr_files,
-                                       GFP_KERNEL);
-               if (!fa || flex_array_prealloc(fa, 0, nr_files,
-                                               GFP_KERNEL)) {
+               p = genradix_ptr_alloc(&fa, nr_files++, GFP_KERNEL);
+               if (!p) {
                        ret = -ENOMEM;
-                       if (fa)
-                               flex_array_free(fa);
                        up_read(&mm->mmap_sem);
                        mmput(mm);
                        goto out_put_task;
                }
-               for (i = 0, vma = mm->mmap, pos = 2; vma;
-                               vma = vma->vm_next) {
-                       if (!vma->vm_file)
-                               continue;
-                       if (++pos <= ctx->pos)
-                               continue;
 
-                       info.start = vma->vm_start;
-                       info.end = vma->vm_end;
-                       info.mode = vma->vm_file->f_mode;
-                       if (flex_array_put(fa, i++, &info, GFP_KERNEL))
-                               BUG();
-               }
+               p->start = vma->vm_start;
+               p->end = vma->vm_end;
+               p->mode = vma->vm_file->f_mode;
        }
        up_read(&mm->mmap_sem);
        mmput(mm);
@@ -2215,7 +2203,7 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
                char buf[4 * sizeof(long) + 2]; /* max: %lx-%lx\0 */
                unsigned int len;
 
-               p = flex_array_get(fa, i);
+               p = genradix_ptr(&fa, i);
                len = snprintf(buf, sizeof(buf), "%lx-%lx", p->start, p->end);
                if (!proc_fill_cache(file, ctx,
                                      buf, len,
@@ -2225,12 +2213,11 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
                        break;
                ctx->pos++;
        }
-       if (fa)
-               flex_array_free(fa);
 
 out_put_task:
        put_task_struct(task);
 out:
+       genradix_free(&fa);
        return ret;
 }
 
@@ -2459,11 +2446,10 @@ static struct dentry *proc_pident_instantiate(struct dentry *dentry,
 
 static struct dentry *proc_pident_lookup(struct inode *dir, 
                                         struct dentry *dentry,
-                                        const struct pid_entry *ents,
-                                        unsigned int nents)
+                                        const struct pid_entry *p,
+                                        const struct pid_entry *end)
 {
        struct task_struct *task = get_proc_task(dir);
-       const struct pid_entry *p, *last;
        struct dentry *res = ERR_PTR(-ENOENT);
 
        if (!task)
@@ -2473,8 +2459,7 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
         * Yes, it does not scale. And it should not. Don't add
         * new entries into /proc/<tgid>/ without very good reasons.
         */
-       last = &ents[nents];
-       for (p = ents; p < last; p++) {
+       for (; p < end; p++) {
                if (p->len != dentry->d_name.len)
                        continue;
                if (!memcmp(dentry->d_name.name, p->name, p->len)) {
@@ -2610,7 +2595,7 @@ static struct dentry *proc_##LSM##_attr_dir_lookup(struct inode *dir, \
 { \
        return proc_pident_lookup(dir, dentry, \
                                  LSM##_attr_dir_stuff, \
-                                 ARRAY_SIZE(LSM##_attr_dir_stuff)); \
+                                 LSM##_attr_dir_stuff + ARRAY_SIZE(LSM##_attr_dir_stuff)); \
 } \
 \
 static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \
@@ -2655,7 +2640,8 @@ static struct dentry *proc_attr_dir_lookup(struct inode *dir,
                                struct dentry *dentry, unsigned int flags)
 {
        return proc_pident_lookup(dir, dentry,
-                                 attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff));
+                                 attr_dir_stuff,
+                                 attr_dir_stuff + ARRAY_SIZE(attr_dir_stuff));
 }
 
 static const struct inode_operations proc_attr_dir_inode_operations = {
@@ -3091,7 +3077,8 @@ static const struct file_operations proc_tgid_base_operations = {
 static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        return proc_pident_lookup(dir, dentry,
-                                 tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff));
+                                 tgid_base_stuff,
+                                 tgid_base_stuff + ARRAY_SIZE(tgid_base_stuff));
 }
 
 static const struct inode_operations proc_tgid_base_inode_operations = {
@@ -3463,7 +3450,8 @@ static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx)
 static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        return proc_pident_lookup(dir, dentry,
-                                 tid_base_stuff, ARRAY_SIZE(tid_base_stuff));
+                                 tid_base_stuff,
+                                 tid_base_stuff + ARRAY_SIZE(tid_base_stuff));
 }
 
 static const struct file_operations proc_tid_base_operations = {
diff --git a/include/linux/flex_array.h b/include/linux/flex_array.h
deleted file mode 100644 (file)
index b94fa61..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _FLEX_ARRAY_H
-#define _FLEX_ARRAY_H
-
-#include <linux/types.h>
-#include <linux/reciprocal_div.h>
-#include <asm/page.h>
-
-#define FLEX_ARRAY_PART_SIZE PAGE_SIZE
-#define FLEX_ARRAY_BASE_SIZE PAGE_SIZE
-
-struct flex_array_part;
-
-/*
- * This is meant to replace cases where an array-like
- * structure has gotten too big to fit into kmalloc()
- * and the developer is getting tempted to use
- * vmalloc().
- */
-
-struct flex_array {
-       union {
-               struct {
-                       int element_size;
-                       int total_nr_elements;
-                       int elems_per_part;
-                       struct reciprocal_value reciprocal_elems;
-                       struct flex_array_part *parts[];
-               };
-               /*
-                * This little trick makes sure that
-                * sizeof(flex_array) == PAGE_SIZE
-                */
-               char padding[FLEX_ARRAY_BASE_SIZE];
-       };
-};
-
-/* Number of bytes left in base struct flex_array, excluding metadata */
-#define FLEX_ARRAY_BASE_BYTES_LEFT                                     \
-       (FLEX_ARRAY_BASE_SIZE - offsetof(struct flex_array, parts))
-
-/* Number of pointers in base to struct flex_array_part pages */
-#define FLEX_ARRAY_NR_BASE_PTRS                                                \
-       (FLEX_ARRAY_BASE_BYTES_LEFT / sizeof(struct flex_array_part *))
-
-/* Number of elements of size that fit in struct flex_array_part */
-#define FLEX_ARRAY_ELEMENTS_PER_PART(size)                             \
-       (FLEX_ARRAY_PART_SIZE / size)
-
-/*
- * Defines a statically allocated flex array and ensures its parameters are
- * valid.
- */
-#define DEFINE_FLEX_ARRAY(__arrayname, __element_size, __total)                \
-       struct flex_array __arrayname = { { {                           \
-               .element_size = (__element_size),                       \
-               .total_nr_elements = (__total),                         \
-       } } };                                                          \
-       static inline void __arrayname##_invalid_parameter(void)        \
-       {                                                               \
-               BUILD_BUG_ON((__total) > FLEX_ARRAY_NR_BASE_PTRS *      \
-                       FLEX_ARRAY_ELEMENTS_PER_PART(__element_size));  \
-       }
-
-/**
- * flex_array_alloc() - Creates a flexible array.
- * @element_size:      individual object size.
- * @total:             maximum number of objects which can be stored.
- * @flags:             GFP flags
- *
- * Return:             Returns an object of structure flex_array.
- */
-struct flex_array *flex_array_alloc(int element_size, unsigned int total,
-               gfp_t flags);
-
-/**
- * flex_array_prealloc() - Ensures that memory for the elements indexed in the
- * range defined by start and nr_elements has been allocated.
- * @fa:                        array to allocate memory to.
- * @start:             start address
- * @nr_elements:       number of elements to be allocated.
- * @flags:             GFP flags
- *
- */
-int flex_array_prealloc(struct flex_array *fa, unsigned int start,
-               unsigned int nr_elements, gfp_t flags);
-
-/**
- * flex_array_free() - Removes all elements of a flexible array.
- * @fa:                array to be freed.
- */
-void flex_array_free(struct flex_array *fa);
-
-/**
- * flex_array_free_parts() - Removes all elements of a flexible array, but
- * leaves the array itself in place.
- * @fa:                array to be emptied.
- */
-void flex_array_free_parts(struct flex_array *fa);
-
-/**
- * flex_array_put() - Stores data into a flexible array.
- * @fa:                array where element is to be stored.
- * @element_nr:        position to copy, must be less than the maximum specified when
- *             the array was created.
- * @src:       data source to be copied into the array.
- * @flags:     GFP flags
- *
- * Return:     Returns zero on success, a negative error code otherwise.
- */
-int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src,
-               gfp_t flags);
-
-/**
- * flex_array_clear() - Clears an individual element in the array, sets the
- * given element to FLEX_ARRAY_FREE.
- * @element_nr:        element position to clear.
- * @fa:                array to which element to be cleared belongs.
- *
- * Return:     Returns zero on success, -EINVAL otherwise.
- */
-int flex_array_clear(struct flex_array *fa, unsigned int element_nr);
-
-/**
- * flex_array_get() - Retrieves data into a flexible array.
- *
- * @element_nr:        Element position to retrieve data from.
- * @fa:                array from which data is to be retrieved.
- *
- * Return:     Returns a pointer to the data element, or NULL if that
- *             particular element has never been allocated.
- */
-void *flex_array_get(struct flex_array *fa, unsigned int element_nr);
-
-/**
- * flex_array_shrink() - Reduces the allocated size of an array.
- * @fa:                array to shrink.
- *
- * Return:     Returns number of pages of memory actually freed.
- *
- */
-int flex_array_shrink(struct flex_array *fa);
-
-#define flex_array_put_ptr(fa, nr, src, gfp) \
-       flex_array_put(fa, nr, (void *)&(src), gfp)
-
-void *flex_array_get_ptr(struct flex_array *fa, unsigned int element_nr);
-
-#endif /* _FLEX_ARRAY_H */
diff --git a/include/linux/generic-radix-tree.h b/include/linux/generic-radix-tree.h
new file mode 100644 (file)
index 0000000..3a91130
--- /dev/null
@@ -0,0 +1,231 @@
+#ifndef _LINUX_GENERIC_RADIX_TREE_H
+#define _LINUX_GENERIC_RADIX_TREE_H
+
+/**
+ * DOC: Generic radix trees/sparse arrays:
+ *
+ * Very simple and minimalistic, supporting arbitrary size entries up to
+ * PAGE_SIZE.
+ *
+ * A genradix is defined with the type it will store, like so:
+ *
+ * static GENRADIX(struct foo) foo_genradix;
+ *
+ * The main operations are:
+ *
+ * - genradix_init(radix) - initialize an empty genradix
+ *
+ * - genradix_free(radix) - free all memory owned by the genradix and
+ *   reinitialize it
+ *
+ * - genradix_ptr(radix, idx) - gets a pointer to the entry at idx, returning
+ *   NULL if that entry does not exist
+ *
+ * - genradix_ptr_alloc(radix, idx, gfp) - gets a pointer to an entry,
+ *   allocating it if necessary
+ *
+ * - genradix_for_each(radix, iter, p) - iterate over each entry in a genradix
+ *
+ * The radix tree allocates one page of entries at a time, so entries may exist
+ * that were never explicitly allocated - they will be initialized to all
+ * zeroes.
+ *
+ * Internally, a genradix is just a radix tree of pages, and indexing works in
+ * terms of byte offsets. The wrappers in this header file use sizeof on the
+ * type the radix contains to calculate a byte offset from the index - see
+ * __idx_to_offset.
+ */
+
+#include <asm/page.h>
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/log2.h>
+
+struct genradix_root;
+
+struct __genradix {
+       struct genradix_root __rcu      *root;
+};
+
+/*
+ * NOTE: currently, sizeof(_type) must not be larger than PAGE_SIZE:
+ */
+
+#define __GENRADIX_INITIALIZER                                 \
+       {                                                       \
+               .tree = {                                       \
+                       .root = NULL,                           \
+               }                                               \
+       }
+
+/*
+ * We use a 0 size array to stash the type we're storing without taking any
+ * space at runtime - then the various accessor macros can use typeof() to get
+ * to it for casts/sizeof - we also force the alignment so that storing a type
+ * with a ridiculous alignment doesn't blow up the alignment or size of the
+ * genradix.
+ */
+
+#define GENRADIX(_type)                                                \
+struct {                                                       \
+       struct __genradix       tree;                           \
+       _type                   type[0] __aligned(1);           \
+}
+
+#define DEFINE_GENRADIX(_name, _type)                          \
+       GENRADIX(_type) _name = __GENRADIX_INITIALIZER
+
+/**
+ * genradix_init - initialize a genradix
+ * @_radix:    genradix to initialize
+ *
+ * Does not fail
+ */
+#define genradix_init(_radix)                                  \
+do {                                                           \
+       *(_radix) = (typeof(*_radix)) __GENRADIX_INITIALIZER;   \
+} while (0)
+
+void __genradix_free(struct __genradix *);
+
+/**
+ * genradix_free: free all memory owned by a genradix
+ * @_radix: the genradix to free
+ *
+ * After freeing, @_radix will be reinitialized and empty
+ */
+#define genradix_free(_radix)  __genradix_free(&(_radix)->tree)
+
+static inline size_t __idx_to_offset(size_t idx, size_t obj_size)
+{
+       if (__builtin_constant_p(obj_size))
+               BUILD_BUG_ON(obj_size > PAGE_SIZE);
+       else
+               BUG_ON(obj_size > PAGE_SIZE);
+
+       if (!is_power_of_2(obj_size)) {
+               size_t objs_per_page = PAGE_SIZE / obj_size;
+
+               return (idx / objs_per_page) * PAGE_SIZE +
+                       (idx % objs_per_page) * obj_size;
+       } else {
+               return idx * obj_size;
+       }
+}
+
+#define __genradix_cast(_radix)                (typeof((_radix)->type[0]) *)
+#define __genradix_obj_size(_radix)    sizeof((_radix)->type[0])
+#define __genradix_idx_to_offset(_radix, _idx)                 \
+       __idx_to_offset(_idx, __genradix_obj_size(_radix))
+
+void *__genradix_ptr(struct __genradix *, size_t);
+
+/**
+ * genradix_ptr - get a pointer to a genradix entry
+ * @_radix:    genradix to access
+ * @_idx:      index to fetch
+ *
+ * Returns a pointer to entry at @_idx, or NULL if that entry does not exist.
+ */
+#define genradix_ptr(_radix, _idx)                             \
+       (__genradix_cast(_radix)                                \
+        __genradix_ptr(&(_radix)->tree,                        \
+                       __genradix_idx_to_offset(_radix, _idx)))
+
+void *__genradix_ptr_alloc(struct __genradix *, size_t, gfp_t);
+
+/**
+ * genradix_ptr_alloc - get a pointer to a genradix entry, allocating it
+ *                     if necessary
+ * @_radix:    genradix to access
+ * @_idx:      index to fetch
+ * @_gfp:      gfp mask
+ *
+ * Returns a pointer to entry at @_idx, or NULL on allocation failure
+ */
+#define genradix_ptr_alloc(_radix, _idx, _gfp)                 \
+       (__genradix_cast(_radix)                                \
+        __genradix_ptr_alloc(&(_radix)->tree,                  \
+                       __genradix_idx_to_offset(_radix, _idx), \
+                       _gfp))
+
+struct genradix_iter {
+       size_t                  offset;
+       size_t                  pos;
+};
+
+/**
+ * genradix_iter_init - initialize a genradix_iter
+ * @_radix:    genradix that will be iterated over
+ * @_idx:      index to start iterating from
+ */
+#define genradix_iter_init(_radix, _idx)                       \
+       ((struct genradix_iter) {                               \
+               .pos    = (_idx),                               \
+               .offset = __genradix_idx_to_offset((_radix), (_idx)),\
+       })
+
+void *__genradix_iter_peek(struct genradix_iter *, struct __genradix *, size_t);
+
+/**
+ * genradix_iter_peek - get first entry at or above iterator's current
+ *                     position
+ * @_iter:     a genradix_iter
+ * @_radix:    genradix being iterated over
+ *
+ * If no more entries exist at or above @_iter's current position, returns NULL
+ */
+#define genradix_iter_peek(_iter, _radix)                      \
+       (__genradix_cast(_radix)                                \
+        __genradix_iter_peek(_iter, &(_radix)->tree,           \
+                             PAGE_SIZE / __genradix_obj_size(_radix)))
+
+static inline void __genradix_iter_advance(struct genradix_iter *iter,
+                                          size_t obj_size)
+{
+       iter->offset += obj_size;
+
+       if (!is_power_of_2(obj_size) &&
+           (iter->offset & (PAGE_SIZE - 1)) + obj_size > PAGE_SIZE)
+               iter->offset = round_up(iter->offset, PAGE_SIZE);
+
+       iter->pos++;
+}
+
+#define genradix_iter_advance(_iter, _radix)                   \
+       __genradix_iter_advance(_iter, __genradix_obj_size(_radix))
+
+#define genradix_for_each_from(_radix, _iter, _p, _start)      \
+       for (_iter = genradix_iter_init(_radix, _start);        \
+            (_p = genradix_iter_peek(&_iter, _radix)) != NULL; \
+            genradix_iter_advance(&_iter, _radix))
+
+/**
+ * genradix_for_each - iterate over entry in a genradix
+ * @_radix:    genradix to iterate over
+ * @_iter:     a genradix_iter to track current position
+ * @_p:                pointer to genradix entry type
+ *
+ * On every iteration, @_p will point to the current entry, and @_iter.pos
+ * will be the current entry's index.
+ */
+#define genradix_for_each(_radix, _iter, _p)                   \
+       genradix_for_each_from(_radix, _iter, _p, 0)
+
+int __genradix_prealloc(struct __genradix *, size_t, gfp_t);
+
+/**
+ * genradix_prealloc - preallocate entries in a generic radix tree
+ * @_radix:    genradix to preallocate
+ * @_nr:       number of entries to preallocate
+ * @_gfp:      gfp mask
+ *
+ * Returns 0 on success, -ENOMEM on failure
+ */
+#define genradix_prealloc(_radix, _nr, _gfp)                   \
+        __genradix_prealloc(&(_radix)->tree,                   \
+                       __genradix_idx_to_offset(_radix, _nr + 1),\
+                       _gfp)
+
+
+#endif /* _LINUX_GENERIC_RADIX_TREE_H */
index 66f9ebbb1df3ffb91120bcaae4987ced0781e98e..ad50b7b4f141ce7eeb22c46c3d2ef61c672919a8 100644 (file)
@@ -468,7 +468,7 @@ struct hmm_devmem_ops {
         * Note that mmap semaphore is held in read mode at least when this
         * callback occurs, hence the vma is valid upon callback entry.
         */
-       int (*fault)(struct hmm_devmem *devmem,
+       vm_fault_t (*fault)(struct hmm_devmem *devmem,
                     struct vm_area_struct *vma,
                     unsigned long addr,
                     const struct page *page,
@@ -511,7 +511,7 @@ struct hmm_devmem_ops {
  * chunk, as an optimization. It must, however, prioritize the faulting address
  * over all the others.
  */
-typedef int (*dev_page_fault_t)(struct vm_area_struct *vma,
+typedef vm_fault_t (*dev_page_fault_t)(struct vm_area_struct *vma,
                                unsigned long addr,
                                const struct page *page,
                                unsigned int flags,
index 859b55b66db2ab5bd6142868e677f2b02bc23ebe..294d5d80e1500998dd8a52752fee5e288b761204 100644 (file)
@@ -108,9 +108,6 @@ void memblock_discard(void);
 #define memblock_dbg(fmt, ...) \
        if (memblock_debug) printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
 
-phys_addr_t memblock_find_in_range_node(phys_addr_t size, phys_addr_t align,
-                                       phys_addr_t start, phys_addr_t end,
-                                       int nid, enum memblock_flags flags);
 phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end,
                                   phys_addr_t size, phys_addr_t align);
 void memblock_allow_resize(void);
@@ -127,7 +124,6 @@ int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
 int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
 int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
 int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
-enum memblock_flags choose_memblock_flags(void);
 
 unsigned long memblock_free_all(void);
 void reset_node_managed_pages(pg_data_t *pgdat);
@@ -277,18 +273,6 @@ void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
        for_each_mem_range_rev(i, &memblock.memory, &memblock.reserved, \
                               nid, flags, p_start, p_end, p_nid)
 
-static inline void memblock_set_region_flags(struct memblock_region *r,
-                                            enum memblock_flags flags)
-{
-       r->flags |= flags;
-}
-
-static inline void memblock_clear_region_flags(struct memblock_region *r,
-                                              enum memblock_flags flags)
-{
-       r->flags &= ~flags;
-}
-
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 int memblock_set_node(phys_addr_t base, phys_addr_t size,
                      struct memblock_type *type, int nid);
@@ -325,17 +309,20 @@ static inline int memblock_get_region_node(const struct memblock_region *r)
 #define ARCH_LOW_ADDRESS_LIMIT  0xffffffffUL
 #endif
 
-phys_addr_t memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, int nid);
+phys_addr_t memblock_phys_alloc_range(phys_addr_t size, phys_addr_t align,
+                                     phys_addr_t start, phys_addr_t end);
 phys_addr_t memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid);
 
-phys_addr_t memblock_phys_alloc(phys_addr_t size, phys_addr_t align);
+static inline phys_addr_t memblock_phys_alloc(phys_addr_t size,
+                                             phys_addr_t align)
+{
+       return memblock_phys_alloc_range(size, align, 0,
+                                        MEMBLOCK_ALLOC_ACCESSIBLE);
+}
 
 void *memblock_alloc_try_nid_raw(phys_addr_t size, phys_addr_t align,
                                 phys_addr_t min_addr, phys_addr_t max_addr,
                                 int nid);
-void *memblock_alloc_try_nid_nopanic(phys_addr_t size, phys_addr_t align,
-                                    phys_addr_t min_addr, phys_addr_t max_addr,
-                                    int nid);
 void *memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align,
                             phys_addr_t min_addr, phys_addr_t max_addr,
                             int nid);
@@ -362,36 +349,12 @@ static inline void * __init memblock_alloc_from(phys_addr_t size,
                                      MEMBLOCK_ALLOC_ACCESSIBLE, NUMA_NO_NODE);
 }
 
-static inline void * __init memblock_alloc_nopanic(phys_addr_t size,
-                                                  phys_addr_t align)
-{
-       return memblock_alloc_try_nid_nopanic(size, align, MEMBLOCK_LOW_LIMIT,
-                                             MEMBLOCK_ALLOC_ACCESSIBLE,
-                                             NUMA_NO_NODE);
-}
-
 static inline void * __init memblock_alloc_low(phys_addr_t size,
                                               phys_addr_t align)
 {
        return memblock_alloc_try_nid(size, align, MEMBLOCK_LOW_LIMIT,
                                      ARCH_LOW_ADDRESS_LIMIT, NUMA_NO_NODE);
 }
-static inline void * __init memblock_alloc_low_nopanic(phys_addr_t size,
-                                                      phys_addr_t align)
-{
-       return memblock_alloc_try_nid_nopanic(size, align, MEMBLOCK_LOW_LIMIT,
-                                             ARCH_LOW_ADDRESS_LIMIT,
-                                             NUMA_NO_NODE);
-}
-
-static inline void * __init memblock_alloc_from_nopanic(phys_addr_t size,
-                                                       phys_addr_t align,
-                                                       phys_addr_t min_addr)
-{
-       return memblock_alloc_try_nid_nopanic(size, align, min_addr,
-                                             MEMBLOCK_ALLOC_ACCESSIBLE,
-                                             NUMA_NO_NODE);
-}
 
 static inline void * __init memblock_alloc_node(phys_addr_t size,
                                                phys_addr_t align, int nid)
@@ -400,14 +363,6 @@ static inline void * __init memblock_alloc_node(phys_addr_t size,
                                      MEMBLOCK_ALLOC_ACCESSIBLE, nid);
 }
 
-static inline void * __init memblock_alloc_node_nopanic(phys_addr_t size,
-                                                       int nid)
-{
-       return memblock_alloc_try_nid_nopanic(size, SMP_CACHE_BYTES,
-                                             MEMBLOCK_LOW_LIMIT,
-                                             MEMBLOCK_ALLOC_ACCESSIBLE, nid);
-}
-
 static inline void __init memblock_free_early(phys_addr_t base,
                                              phys_addr_t size)
 {
@@ -443,16 +398,6 @@ static inline bool memblock_bottom_up(void)
        return memblock.bottom_up;
 }
 
-phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,
-                                       phys_addr_t start, phys_addr_t end,
-                                       enum memblock_flags flags);
-phys_addr_t memblock_alloc_base_nid(phys_addr_t size,
-                                       phys_addr_t align, phys_addr_t max_addr,
-                                       int nid, enum memblock_flags flags);
-phys_addr_t memblock_alloc_base(phys_addr_t size, phys_addr_t align,
-                               phys_addr_t max_addr);
-phys_addr_t __memblock_alloc_base(phys_addr_t size, phys_addr_t align,
-                                 phys_addr_t max_addr);
 phys_addr_t memblock_phys_mem_size(void);
 phys_addr_t memblock_reserved_size(void);
 phys_addr_t memblock_mem_size(unsigned long limit_pfn);
index 5801ee849f36729c0357bdf5e29b85f63a2830a9..76769749b5a5d546daf7f7513318ad65a494da4c 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/page_ref.h>
 #include <linux/memremap.h>
 #include <linux/overflow.h>
+#include <linux/sizes.h>
 
 struct mempolicy;
 struct anon_vma;
@@ -2402,8 +2403,7 @@ int __must_check write_one_page(struct page *page);
 void task_dirty_inc(struct task_struct *tsk);
 
 /* readahead.c */
-#define VM_MAX_READAHEAD       128     /* kbytes */
-#define VM_MIN_READAHEAD       16      /* kbytes (includes current page) */
+#define VM_READAHEAD_PAGES     (SZ_128K / PAGE_SIZE)
 
 int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
                        pgoff_t offset, unsigned long nr_to_read);
index 5046bad0c1c5e6c9418d3f10e7d15ff2004abe99..d6d980a681c7fbfdf4f5740694e99fe5f0b08fde 100644 (file)
@@ -83,9 +83,6 @@
 #define MUTEX_DEBUG_FREE       0x22
 #define MUTEX_POISON_WW_CTX    ((void *) 0x500 + POISON_POINTER_DELTA)
 
-/********** lib/flex_array.c **********/
-#define FLEX_ARRAY_FREE        0x6c    /* for use-after-free poisoning */
-
 /********** security/ **********/
 #define KEY_DESTROY            0xbd
 
index 58e4b23cecf4352378379f6e2c859d54a00ea17b..140fd836a396735100dee7660b5ece5485cc2a15 100644 (file)
@@ -48,6 +48,7 @@
 #define __sctp_structs_h__
 
 #include <linux/ktime.h>
+#include <linux/generic-radix-tree.h>
 #include <linux/rhashtable-types.h>
 #include <linux/socket.h>      /* linux/in.h needs this!!    */
 #include <linux/in.h>          /* We get struct sockaddr_in. */
@@ -57,7 +58,6 @@
 #include <linux/atomic.h>              /* This gets us atomic counters.  */
 #include <linux/skbuff.h>      /* We need sk_buff_head. */
 #include <linux/workqueue.h>   /* We need tq_struct.    */
-#include <linux/flex_array.h>  /* We need flex_array.   */
 #include <linux/sctp.h>                /* We need sctp* header structs.  */
 #include <net/sctp/auth.h>     /* We need auth specific structs */
 #include <net/ip.h>            /* For inet_skb_parm */
@@ -1449,8 +1449,9 @@ struct sctp_stream_in {
 };
 
 struct sctp_stream {
-       struct flex_array *out;
-       struct flex_array *in;
+       GENRADIX(struct sctp_stream_out) out;
+       GENRADIX(struct sctp_stream_in) in;
+
        __u16 outcnt;
        __u16 incnt;
        /* Current stream being sent, if any */
@@ -1473,17 +1474,17 @@ struct sctp_stream {
 };
 
 static inline struct sctp_stream_out *sctp_stream_out(
-       const struct sctp_stream *stream,
+       struct sctp_stream *stream,
        __u16 sid)
 {
-       return flex_array_get(stream->out, sid);
+       return genradix_ptr(&stream->out, sid);
 }
 
 static inline struct sctp_stream_in *sctp_stream_in(
-       const struct sctp_stream *stream,
+       struct sctp_stream *stream,
        __u16 sid)
 {
-       return flex_array_get(stream->in, sid);
+       return genradix_ptr(&stream->in, sid);
 }
 
 #define SCTP_SO(s, i) sctp_stream_out((s), (i))
index c86a1c8f19f40be9508b7b979959bc57a47e70ce..598e278b46f743d777e6f9375ac1c932896ef99c 100644 (file)
@@ -373,12 +373,20 @@ static inline void smp_prepare_cpus(unsigned int maxcpus) { }
  */
 static void __init setup_command_line(char *command_line)
 {
-       saved_command_line =
-               memblock_alloc(strlen(boot_command_line) + 1, SMP_CACHE_BYTES);
-       initcall_command_line =
-               memblock_alloc(strlen(boot_command_line) + 1, SMP_CACHE_BYTES);
-       static_command_line = memblock_alloc(strlen(command_line) + 1,
-                                            SMP_CACHE_BYTES);
+       size_t len = strlen(boot_command_line) + 1;
+
+       saved_command_line = memblock_alloc(len, SMP_CACHE_BYTES);
+       if (!saved_command_line)
+               panic("%s: Failed to allocate %zu bytes\n", __func__, len);
+
+       initcall_command_line = memblock_alloc(len, SMP_CACHE_BYTES);
+       if (!initcall_command_line)
+               panic("%s: Failed to allocate %zu bytes\n", __func__, len);
+
+       static_command_line = memblock_alloc(len, SMP_CACHE_BYTES);
+       if (!static_command_line)
+               panic("%s: Failed to allocate %zu bytes\n", __func__, len);
+
        strcpy(saved_command_line, boot_command_line);
        strcpy(static_command_line, command_line);
 }
@@ -770,8 +778,14 @@ static int __init initcall_blacklist(char *str)
                        pr_debug("blacklisting initcall %s\n", str_entry);
                        entry = memblock_alloc(sizeof(*entry),
                                               SMP_CACHE_BYTES);
+                       if (!entry)
+                               panic("%s: Failed to allocate %zu bytes\n",
+                                     __func__, sizeof(*entry));
                        entry->buf = memblock_alloc(strlen(str_entry) + 1,
                                                    SMP_CACHE_BYTES);
+                       if (!entry->buf)
+                               panic("%s: Failed to allocate %zu bytes\n",
+                                     __func__, strlen(str_entry) + 1);
                        strcpy(entry->buf, str_entry);
                        list_add(&entry->next, &blacklisted_initcalls);
                }
index 9f5851064aea6854b426fa34ffe3ab10588666fe..53012db1e53c6915ee29b0bcd7e543def476232b 100644 (file)
@@ -199,6 +199,7 @@ void __init swiotlb_update_mem_attributes(void)
 int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
 {
        unsigned long i, bytes;
+       size_t alloc_size;
 
        bytes = nslabs << IO_TLB_SHIFT;
 
@@ -211,12 +212,18 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
         * to find contiguous free memory regions of size up to IO_TLB_SEGSIZE
         * between io_tlb_start and io_tlb_end.
         */
-       io_tlb_list = memblock_alloc(
-                               PAGE_ALIGN(io_tlb_nslabs * sizeof(int)),
-                               PAGE_SIZE);
-       io_tlb_orig_addr = memblock_alloc(
-                               PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)),
-                               PAGE_SIZE);
+       alloc_size = PAGE_ALIGN(io_tlb_nslabs * sizeof(int));
+       io_tlb_list = memblock_alloc(alloc_size, PAGE_SIZE);
+       if (!io_tlb_list)
+               panic("%s: Failed to allocate %zu bytes align=0x%lx\n",
+                     __func__, alloc_size, PAGE_SIZE);
+
+       alloc_size = PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t));
+       io_tlb_orig_addr = memblock_alloc(alloc_size, PAGE_SIZE);
+       if (!io_tlb_orig_addr)
+               panic("%s: Failed to allocate %zu bytes align=0x%lx\n",
+                     __func__, alloc_size, PAGE_SIZE);
+
        for (i = 0; i < io_tlb_nslabs; i++) {
                io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
                io_tlb_orig_addr[i] = INVALID_PHYS_ADDR;
@@ -249,7 +256,7 @@ swiotlb_init(int verbose)
        bytes = io_tlb_nslabs << IO_TLB_SHIFT;
 
        /* Get IO TLB memory from the low pages */
-       vstart = memblock_alloc_low_nopanic(PAGE_ALIGN(bytes), PAGE_SIZE);
+       vstart = memblock_alloc_low(PAGE_ALIGN(bytes), PAGE_SIZE);
        if (vstart && !swiotlb_init_with_tbl(vstart, io_tlb_nslabs, verbose))
                return;
 
index 4802b039b89f54f60d458405a7db128ff1c09648..f08a1e4ee1d4559ea7dd17f094a5f0e029dcf7fc 100644 (file)
@@ -965,6 +965,9 @@ void __init __register_nosave_region(unsigned long start_pfn,
                /* This allocation cannot fail */
                region = memblock_alloc(sizeof(struct nosave_region),
                                        SMP_CACHE_BYTES);
+               if (!region)
+                       panic("%s: Failed to allocate %zu bytes\n", __func__,
+                             sizeof(struct nosave_region));
        }
        region->start_pfn = start_pfn;
        region->end_pfn = end_pfn;
index 8eee85bb26877f407b43d7f6a0a7c806956b0075..6b7654b8001fc4d07dc8bcd4a00eddee31e09891 100644 (file)
@@ -1143,14 +1143,7 @@ void __init setup_log_buf(int early)
        if (!new_log_buf_len)
                return;
 
-       if (early) {
-               new_log_buf =
-                       memblock_alloc(new_log_buf_len, LOG_ALIGN);
-       } else {
-               new_log_buf = memblock_alloc_nopanic(new_log_buf_len,
-                                                         LOG_ALIGN);
-       }
-
+       new_log_buf = memblock_alloc(new_log_buf_len, LOG_ALIGN);
        if (unlikely(!new_log_buf)) {
                pr_err("log_buf_len: %lu bytes not available\n",
                        new_log_buf_len);
index 7bb3988425ee13f69ded2c827552d638c5d4258b..e5da394d1ca3675ef6bc050660c1d5a0892915ca 100644 (file)
@@ -2643,23 +2643,25 @@ static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
                                        int *valp,
                                        int write, void *data)
 {
+       int tmp, ret;
        struct do_proc_dointvec_minmax_conv_param *param = data;
+       /*
+        * If writing, first do so via a temporary local int so we can
+        * bounds-check it before touching *valp.
+        */
+       int *ip = write ? &tmp : valp;
+
+       ret = do_proc_dointvec_conv(negp, lvalp, ip, write, data);
+       if (ret)
+               return ret;
+
        if (write) {
-               int val = *negp ? -*lvalp : *lvalp;
-               if ((param->min && *param->min > val) ||
-                   (param->max && *param->max < val))
+               if ((param->min && *param->min > tmp) ||
+                   (param->max && *param->max < tmp))
                        return -EINVAL;
-               *valp = val;
-       } else {
-               int val = *valp;
-               if (val < 0) {
-                       *negp = true;
-                       *lvalp = -(unsigned long)val;
-               } else {
-                       *negp = false;
-                       *lvalp = (unsigned long)val;
-               }
+               *valp = tmp;
        }
+
        return 0;
 }
 
@@ -2708,22 +2710,22 @@ static int do_proc_douintvec_minmax_conv(unsigned long *lvalp,
                                         unsigned int *valp,
                                         int write, void *data)
 {
+       int ret;
+       unsigned int tmp;
        struct do_proc_douintvec_minmax_conv_param *param = data;
+       /* write via temporary local uint for bounds-checking */
+       unsigned int *up = write ? &tmp : valp;
 
-       if (write) {
-               unsigned int val = *lvalp;
-
-               if (*lvalp > UINT_MAX)
-                       return -EINVAL;
+       ret = do_proc_douintvec_conv(lvalp, up, write, data);
+       if (ret)
+               return ret;
 
-               if ((param->min && *param->min > val) ||
-                   (param->max && *param->max < val))
+       if (write) {
+               if ((param->min && *param->min > tmp) ||
+                   (param->max && *param->max < tmp))
                        return -ERANGE;
 
-               *valp = val;
-       } else {
-               unsigned int val = *valp;
-               *lvalp = (unsigned long) val;
+               *valp = tmp;
        }
 
        return 0;
index 647517940b298ccb72e732499b226ba0d044fe63..4e066120a0d6be50ed8161b87d6297095d12cbf9 100644 (file)
@@ -35,10 +35,11 @@ obj-y       += lockref.o
 
 obj-y += bcd.o div64.o sort.o parser.o debug_locks.o random32.o \
         bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \
-        gcd.o lcm.o list_sort.o uuid.o flex_array.o iov_iter.o clz_ctz.o \
+        gcd.o lcm.o list_sort.o uuid.o iov_iter.o clz_ctz.o \
         bsearch.o find_bit.o llist.o memweight.o kfifo.o \
         percpu-refcount.o rhashtable.o reciprocal_div.o \
-        once.o refcount.o usercopy.o errseq.o bucket_locks.o
+        once.o refcount.o usercopy.o errseq.o bucket_locks.o \
+        generic-radix-tree.o
 obj-$(CONFIG_STRING_SELFTEST) += test_string.o
 obj-y += string_helpers.o
 obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o
index 087a3e9a0202bd4ee0c6c03afb6137d284d4a671..0cb672eb107cef6eeb42c5e76ad3fcd5d22de23a 100644 (file)
@@ -165,6 +165,9 @@ EXPORT_SYMBOL(zalloc_cpumask_var);
 void __init alloc_bootmem_cpumask_var(cpumask_var_t *mask)
 {
        *mask = memblock_alloc(cpumask_size(), SMP_CACHE_BYTES);
+       if (!*mask)
+               panic("%s: Failed to allocate %u bytes\n", __func__,
+                     cpumask_size());
 }
 
 /**
diff --git a/lib/flex_array.c b/lib/flex_array.c
deleted file mode 100644 (file)
index 2eed22f..0000000
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * Flexible array managed in PAGE_SIZE parts
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright IBM Corporation, 2009
- *
- * Author: Dave Hansen <dave@linux.vnet.ibm.com>
- */
-
-#include <linux/flex_array.h>
-#include <linux/slab.h>
-#include <linux/stddef.h>
-#include <linux/export.h>
-#include <linux/reciprocal_div.h>
-
-struct flex_array_part {
-       char elements[FLEX_ARRAY_PART_SIZE];
-};
-
-/*
- * If a user requests an allocation which is small
- * enough, we may simply use the space in the
- * flex_array->parts[] array to store the user
- * data.
- */
-static inline int elements_fit_in_base(struct flex_array *fa)
-{
-       int data_size = fa->element_size * fa->total_nr_elements;
-       if (data_size <= FLEX_ARRAY_BASE_BYTES_LEFT)
-               return 1;
-       return 0;
-}
-
-/**
- * flex_array_alloc - allocate a new flexible array
- * @element_size:      the size of individual elements in the array
- * @total:             total number of elements that this should hold
- * @flags:             page allocation flags to use for base array
- *
- * Note: all locking must be provided by the caller.
- *
- * @total is used to size internal structures.  If the user ever
- * accesses any array indexes >=@total, it will produce errors.
- *
- * The maximum number of elements is defined as: the number of
- * elements that can be stored in a page times the number of
- * page pointers that we can fit in the base structure or (using
- * integer math):
- *
- *     (PAGE_SIZE/element_size) * (PAGE_SIZE-8)/sizeof(void *)
- *
- * Here's a table showing example capacities.  Note that the maximum
- * index that the get/put() functions is just nr_objects-1.   This
- * basically means that you get 4MB of storage on 32-bit and 2MB on
- * 64-bit.
- *
- *
- * Element size | Objects | Objects |
- * PAGE_SIZE=4k |  32-bit |  64-bit |
- * ---------------------------------|
- *      1 bytes | 4177920 | 2088960 |
- *      2 bytes | 2088960 | 1044480 |
- *      3 bytes | 1392300 |  696150 |
- *      4 bytes | 1044480 |  522240 |
- *     32 bytes |  130560 |   65408 |
- *     33 bytes |  126480 |   63240 |
- *   2048 bytes |    2040 |    1020 |
- *   2049 bytes |    1020 |     510 |
- *       void * | 1044480 |  261120 |
- *
- * Since 64-bit pointers are twice the size, we lose half the
- * capacity in the base structure.  Also note that no effort is made
- * to efficiently pack objects across page boundaries.
- */
-struct flex_array *flex_array_alloc(int element_size, unsigned int total,
-                                       gfp_t flags)
-{
-       struct flex_array *ret;
-       int elems_per_part = 0;
-       int max_size = 0;
-       struct reciprocal_value reciprocal_elems = { 0 };
-
-       if (element_size) {
-               elems_per_part = FLEX_ARRAY_ELEMENTS_PER_PART(element_size);
-               reciprocal_elems = reciprocal_value(elems_per_part);
-               max_size = FLEX_ARRAY_NR_BASE_PTRS * elems_per_part;
-       }
-
-       /* max_size will end up 0 if element_size > PAGE_SIZE */
-       if (total > max_size)
-               return NULL;
-       ret = kzalloc(sizeof(struct flex_array), flags);
-       if (!ret)
-               return NULL;
-       ret->element_size = element_size;
-       ret->total_nr_elements = total;
-       ret->elems_per_part = elems_per_part;
-       ret->reciprocal_elems = reciprocal_elems;
-       if (elements_fit_in_base(ret) && !(flags & __GFP_ZERO))
-               memset(&ret->parts[0], FLEX_ARRAY_FREE,
-                                               FLEX_ARRAY_BASE_BYTES_LEFT);
-       return ret;
-}
-EXPORT_SYMBOL(flex_array_alloc);
-
-static int fa_element_to_part_nr(struct flex_array *fa,
-                                       unsigned int element_nr)
-{
-       /*
-        * if element_size == 0 we don't get here, so we never touch
-        * the zeroed fa->reciprocal_elems, which would yield invalid
-        * results
-        */
-       return reciprocal_divide(element_nr, fa->reciprocal_elems);
-}
-
-/**
- * flex_array_free_parts - just free the second-level pages
- * @fa:                the flex array from which to free parts
- *
- * This is to be used in cases where the base 'struct flex_array'
- * has been statically allocated and should not be free.
- */
-void flex_array_free_parts(struct flex_array *fa)
-{
-       int part_nr;
-
-       if (elements_fit_in_base(fa))
-               return;
-       for (part_nr = 0; part_nr < FLEX_ARRAY_NR_BASE_PTRS; part_nr++)
-               kfree(fa->parts[part_nr]);
-}
-EXPORT_SYMBOL(flex_array_free_parts);
-
-void flex_array_free(struct flex_array *fa)
-{
-       flex_array_free_parts(fa);
-       kfree(fa);
-}
-EXPORT_SYMBOL(flex_array_free);
-
-static unsigned int index_inside_part(struct flex_array *fa,
-                                       unsigned int element_nr,
-                                       unsigned int part_nr)
-{
-       unsigned int part_offset;
-
-       part_offset = element_nr - part_nr * fa->elems_per_part;
-       return part_offset * fa->element_size;
-}
-
-static struct flex_array_part *
-__fa_get_part(struct flex_array *fa, int part_nr, gfp_t flags)
-{
-       struct flex_array_part *part = fa->parts[part_nr];
-       if (!part) {
-               part = kmalloc(sizeof(struct flex_array_part), flags);
-               if (!part)
-                       return NULL;
-               if (!(flags & __GFP_ZERO))
-                       memset(part, FLEX_ARRAY_FREE,
-                               sizeof(struct flex_array_part));
-               fa->parts[part_nr] = part;
-       }
-       return part;
-}
-
-/**
- * flex_array_put - copy data into the array at @element_nr
- * @fa:                the flex array to copy data into
- * @element_nr:        index of the position in which to insert
- *             the new element.
- * @src:       address of data to copy into the array
- * @flags:     page allocation flags to use for array expansion
- *
- *
- * Note that this *copies* the contents of @src into
- * the array.  If you are trying to store an array of
- * pointers, make sure to pass in &ptr instead of ptr.
- * You may instead wish to use the flex_array_put_ptr()
- * helper function.
- *
- * Locking must be provided by the caller.
- */
-int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src,
-                       gfp_t flags)
-{
-       int part_nr = 0;
-       struct flex_array_part *part;
-       void *dst;
-
-       if (element_nr >= fa->total_nr_elements)
-               return -ENOSPC;
-       if (!fa->element_size)
-               return 0;
-       if (elements_fit_in_base(fa))
-               part = (struct flex_array_part *)&fa->parts[0];
-       else {
-               part_nr = fa_element_to_part_nr(fa, element_nr);
-               part = __fa_get_part(fa, part_nr, flags);
-               if (!part)
-                       return -ENOMEM;
-       }
-       dst = &part->elements[index_inside_part(fa, element_nr, part_nr)];
-       memcpy(dst, src, fa->element_size);
-       return 0;
-}
-EXPORT_SYMBOL(flex_array_put);
-
-/**
- * flex_array_clear - clear element in array at @element_nr
- * @fa:                the flex array of the element.
- * @element_nr:        index of the position to clear.
- *
- * Locking must be provided by the caller.
- */
-int flex_array_clear(struct flex_array *fa, unsigned int element_nr)
-{
-       int part_nr = 0;
-       struct flex_array_part *part;
-       void *dst;
-
-       if (element_nr >= fa->total_nr_elements)
-               return -ENOSPC;
-       if (!fa->element_size)
-               return 0;
-       if (elements_fit_in_base(fa))
-               part = (struct flex_array_part *)&fa->parts[0];
-       else {
-               part_nr = fa_element_to_part_nr(fa, element_nr);
-               part = fa->parts[part_nr];
-               if (!part)
-                       return -EINVAL;
-       }
-       dst = &part->elements[index_inside_part(fa, element_nr, part_nr)];
-       memset(dst, FLEX_ARRAY_FREE, fa->element_size);
-       return 0;
-}
-EXPORT_SYMBOL(flex_array_clear);
-
-/**
- * flex_array_prealloc - guarantee that array space exists
- * @fa:                        the flex array for which to preallocate parts
- * @start:             index of first array element for which space is allocated
- * @nr_elements:       number of elements for which space is allocated
- * @flags:             page allocation flags
- *
- * This will guarantee that no future calls to flex_array_put()
- * will allocate memory.  It can be used if you are expecting to
- * be holding a lock or in some atomic context while writing
- * data into the array.
- *
- * Locking must be provided by the caller.
- */
-int flex_array_prealloc(struct flex_array *fa, unsigned int start,
-                       unsigned int nr_elements, gfp_t flags)
-{
-       int start_part;
-       int end_part;
-       int part_nr;
-       unsigned int end;
-       struct flex_array_part *part;
-
-       if (!start && !nr_elements)
-               return 0;
-       if (start >= fa->total_nr_elements)
-               return -ENOSPC;
-       if (!nr_elements)
-               return 0;
-
-       end = start + nr_elements - 1;
-
-       if (end >= fa->total_nr_elements)
-               return -ENOSPC;
-       if (!fa->element_size)
-               return 0;
-       if (elements_fit_in_base(fa))
-               return 0;
-       start_part = fa_element_to_part_nr(fa, start);
-       end_part = fa_element_to_part_nr(fa, end);
-       for (part_nr = start_part; part_nr <= end_part; part_nr++) {
-               part = __fa_get_part(fa, part_nr, flags);
-               if (!part)
-                       return -ENOMEM;
-       }
-       return 0;
-}
-EXPORT_SYMBOL(flex_array_prealloc);
-
-/**
- * flex_array_get - pull data back out of the array
- * @fa:                the flex array from which to extract data
- * @element_nr:        index of the element to fetch from the array
- *
- * Returns a pointer to the data at index @element_nr.  Note
- * that this is a copy of the data that was passed in.  If you
- * are using this to store pointers, you'll get back &ptr.  You
- * may instead wish to use the flex_array_get_ptr helper.
- *
- * Locking must be provided by the caller.
- */
-void *flex_array_get(struct flex_array *fa, unsigned int element_nr)
-{
-       int part_nr = 0;
-       struct flex_array_part *part;
-
-       if (!fa->element_size)
-               return NULL;
-       if (element_nr >= fa->total_nr_elements)
-               return NULL;
-       if (elements_fit_in_base(fa))
-               part = (struct flex_array_part *)&fa->parts[0];
-       else {
-               part_nr = fa_element_to_part_nr(fa, element_nr);
-               part = fa->parts[part_nr];
-               if (!part)
-                       return NULL;
-       }
-       return &part->elements[index_inside_part(fa, element_nr, part_nr)];
-}
-EXPORT_SYMBOL(flex_array_get);
-
-/**
- * flex_array_get_ptr - pull a ptr back out of the array
- * @fa:                the flex array from which to extract data
- * @element_nr:        index of the element to fetch from the array
- *
- * Returns the pointer placed in the flex array at element_nr using
- * flex_array_put_ptr().  This function should not be called if the
- * element in question was not set using the _put_ptr() helper.
- */
-void *flex_array_get_ptr(struct flex_array *fa, unsigned int element_nr)
-{
-       void **tmp;
-
-       tmp = flex_array_get(fa, element_nr);
-       if (!tmp)
-               return NULL;
-
-       return *tmp;
-}
-EXPORT_SYMBOL(flex_array_get_ptr);
-
-static int part_is_free(struct flex_array_part *part)
-{
-       int i;
-
-       for (i = 0; i < sizeof(struct flex_array_part); i++)
-               if (part->elements[i] != FLEX_ARRAY_FREE)
-                       return 0;
-       return 1;
-}
-
-/**
- * flex_array_shrink - free unused second-level pages
- * @fa:                the flex array to shrink
- *
- * Frees all second-level pages that consist solely of unused
- * elements.  Returns the number of pages freed.
- *
- * Locking must be provided by the caller.
- */
-int flex_array_shrink(struct flex_array *fa)
-{
-       struct flex_array_part *part;
-       int part_nr;
-       int ret = 0;
-
-       if (!fa->total_nr_elements || !fa->element_size)
-               return 0;
-       if (elements_fit_in_base(fa))
-               return ret;
-       for (part_nr = 0; part_nr < FLEX_ARRAY_NR_BASE_PTRS; part_nr++) {
-               part = fa->parts[part_nr];
-               if (!part)
-                       continue;
-               if (part_is_free(part)) {
-                       fa->parts[part_nr] = NULL;
-                       kfree(part);
-                       ret++;
-               }
-       }
-       return ret;
-}
-EXPORT_SYMBOL(flex_array_shrink);
diff --git a/lib/generic-radix-tree.c b/lib/generic-radix-tree.c
new file mode 100644 (file)
index 0000000..a7bafc4
--- /dev/null
@@ -0,0 +1,217 @@
+
+#include <linux/export.h>
+#include <linux/generic-radix-tree.h>
+#include <linux/gfp.h>
+
+#define GENRADIX_ARY           (PAGE_SIZE / sizeof(struct genradix_node *))
+#define GENRADIX_ARY_SHIFT     ilog2(GENRADIX_ARY)
+
+struct genradix_node {
+       union {
+               /* Interior node: */
+               struct genradix_node    *children[GENRADIX_ARY];
+
+               /* Leaf: */
+               u8                      data[PAGE_SIZE];
+       };
+};
+
+static inline int genradix_depth_shift(unsigned depth)
+{
+       return PAGE_SHIFT + GENRADIX_ARY_SHIFT * depth;
+}
+
+/*
+ * Returns size (of data, in bytes) that a tree of a given depth holds:
+ */
+static inline size_t genradix_depth_size(unsigned depth)
+{
+       return 1UL << genradix_depth_shift(depth);
+}
+
+/* depth that's needed for a genradix that can address up to ULONG_MAX: */
+#define GENRADIX_MAX_DEPTH     \
+       DIV_ROUND_UP(BITS_PER_LONG - PAGE_SHIFT, GENRADIX_ARY_SHIFT)
+
+#define GENRADIX_DEPTH_MASK                            \
+       ((unsigned long) (roundup_pow_of_two(GENRADIX_MAX_DEPTH + 1) - 1))
+
+unsigned genradix_root_to_depth(struct genradix_root *r)
+{
+       return (unsigned long) r & GENRADIX_DEPTH_MASK;
+}
+
+struct genradix_node *genradix_root_to_node(struct genradix_root *r)
+{
+       return (void *) ((unsigned long) r & ~GENRADIX_DEPTH_MASK);
+}
+
+/*
+ * Returns pointer to the specified byte @offset within @radix, or NULL if not
+ * allocated
+ */
+void *__genradix_ptr(struct __genradix *radix, size_t offset)
+{
+       struct genradix_root *r = READ_ONCE(radix->root);
+       struct genradix_node *n = genradix_root_to_node(r);
+       unsigned level          = genradix_root_to_depth(r);
+
+       if (ilog2(offset) >= genradix_depth_shift(level))
+               return NULL;
+
+       while (1) {
+               if (!n)
+                       return NULL;
+               if (!level)
+                       break;
+
+               level--;
+
+               n = n->children[offset >> genradix_depth_shift(level)];
+               offset &= genradix_depth_size(level) - 1;
+       }
+
+       return &n->data[offset];
+}
+EXPORT_SYMBOL(__genradix_ptr);
+
+/*
+ * Returns pointer to the specified byte @offset within @radix, allocating it if
+ * necessary - newly allocated slots are always zeroed out:
+ */
+void *__genradix_ptr_alloc(struct __genradix *radix, size_t offset,
+                          gfp_t gfp_mask)
+{
+       struct genradix_root *v = READ_ONCE(radix->root);
+       struct genradix_node *n, *new_node = NULL;
+       unsigned level;
+
+       /* Increase tree depth if necessary: */
+       while (1) {
+               struct genradix_root *r = v, *new_root;
+
+               n       = genradix_root_to_node(r);
+               level   = genradix_root_to_depth(r);
+
+               if (n && ilog2(offset) < genradix_depth_shift(level))
+                       break;
+
+               if (!new_node) {
+                       new_node = (void *)
+                               __get_free_page(gfp_mask|__GFP_ZERO);
+                       if (!new_node)
+                               return NULL;
+               }
+
+               new_node->children[0] = n;
+               new_root = ((struct genradix_root *)
+                           ((unsigned long) new_node | (n ? level + 1 : 0)));
+
+               if ((v = cmpxchg_release(&radix->root, r, new_root)) == r) {
+                       v = new_root;
+                       new_node = NULL;
+               }
+       }
+
+       while (level--) {
+               struct genradix_node **p =
+                       &n->children[offset >> genradix_depth_shift(level)];
+               offset &= genradix_depth_size(level) - 1;
+
+               n = READ_ONCE(*p);
+               if (!n) {
+                       if (!new_node) {
+                               new_node = (void *)
+                                       __get_free_page(gfp_mask|__GFP_ZERO);
+                               if (!new_node)
+                                       return NULL;
+                       }
+
+                       if (!(n = cmpxchg_release(p, NULL, new_node)))
+                               swap(n, new_node);
+               }
+       }
+
+       if (new_node)
+               free_page((unsigned long) new_node);
+
+       return &n->data[offset];
+}
+EXPORT_SYMBOL(__genradix_ptr_alloc);
+
+void *__genradix_iter_peek(struct genradix_iter *iter,
+                          struct __genradix *radix,
+                          size_t objs_per_page)
+{
+       struct genradix_root *r;
+       struct genradix_node *n;
+       unsigned level, i;
+restart:
+       r = READ_ONCE(radix->root);
+       if (!r)
+               return NULL;
+
+       n       = genradix_root_to_node(r);
+       level   = genradix_root_to_depth(r);
+
+       if (ilog2(iter->offset) >= genradix_depth_shift(level))
+               return NULL;
+
+       while (level) {
+               level--;
+
+               i = (iter->offset >> genradix_depth_shift(level)) &
+                       (GENRADIX_ARY - 1);
+
+               while (!n->children[i]) {
+                       i++;
+                       iter->offset = round_down(iter->offset +
+                                          genradix_depth_size(level),
+                                          genradix_depth_size(level));
+                       iter->pos = (iter->offset >> PAGE_SHIFT) *
+                               objs_per_page;
+                       if (i == GENRADIX_ARY)
+                               goto restart;
+               }
+
+               n = n->children[i];
+       }
+
+       return &n->data[iter->offset & (PAGE_SIZE - 1)];
+}
+EXPORT_SYMBOL(__genradix_iter_peek);
+
+static void genradix_free_recurse(struct genradix_node *n, unsigned level)
+{
+       if (level) {
+               unsigned i;
+
+               for (i = 0; i < GENRADIX_ARY; i++)
+                       if (n->children[i])
+                               genradix_free_recurse(n->children[i], level - 1);
+       }
+
+       free_page((unsigned long) n);
+}
+
+int __genradix_prealloc(struct __genradix *radix, size_t size,
+                       gfp_t gfp_mask)
+{
+       size_t offset;
+
+       for (offset = 0; offset < size; offset += PAGE_SIZE)
+               if (!__genradix_ptr_alloc(radix, offset, gfp_mask))
+                       return -ENOMEM;
+
+       return 0;
+}
+EXPORT_SYMBOL(__genradix_prealloc);
+
+void __genradix_free(struct __genradix *radix)
+{
+       struct genradix_root *r = xchg(&radix->root, NULL);
+
+       genradix_free_recurse(genradix_root_to_node(r),
+                             genradix_root_to_depth(r));
+}
+EXPORT_SYMBOL(__genradix_free);
index f4f3a8a57d8623aa4bdbb71ddb232a33a6493378..bb2d333ffcb3128db361fbe6053818e5db677170 100644 (file)
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -327,16 +327,14 @@ int __init cma_declare_contiguous(phys_addr_t base,
                 * memory in case of failure.
                 */
                if (base < highmem_start && limit > highmem_start) {
-                       addr = memblock_alloc_range(size, alignment,
-                                                   highmem_start, limit,
-                                                   MEMBLOCK_NONE);
+                       addr = memblock_phys_alloc_range(size, alignment,
+                                                        highmem_start, limit);
                        limit = highmem_start;
                }
 
                if (!addr) {
-                       addr = memblock_alloc_range(size, alignment, base,
-                                                   limit,
-                                                   MEMBLOCK_NONE);
+                       addr = memblock_phys_alloc_range(size, alignment, base,
+                                                        limit);
                        if (!addr) {
                                ret = -ENOMEM;
                                goto err;
index a04e4b81061012b003c260d8e3cabc388947090c..fe1cd87e49acc94641eaf7178dc07e5c4306e408 100644 (file)
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -990,7 +990,7 @@ static void hmm_devmem_ref_kill(struct percpu_ref *ref)
        percpu_ref_kill(ref);
 }
 
-static int hmm_devmem_fault(struct vm_area_struct *vma,
+static vm_fault_t hmm_devmem_fault(struct vm_area_struct *vma,
                            unsigned long addr,
                            const struct page *page,
                            unsigned int flags,
index fcaa1ca031754018260ff53ab87c67e9fdd944c2..ce45c491ebcdbde1a0d3c5cc374d381c405b4823 100644 (file)
@@ -83,8 +83,14 @@ static inline bool kasan_early_shadow_page_entry(pte_t pte)
 
 static __init void *early_alloc(size_t size, int node)
 {
-       return memblock_alloc_try_nid(size, size, __pa(MAX_DMA_ADDRESS),
-                                       MEMBLOCK_ALLOC_ACCESSIBLE, node);
+       void *ptr = memblock_alloc_try_nid(size, size, __pa(MAX_DMA_ADDRESS),
+                                          MEMBLOCK_ALLOC_ACCESSIBLE, node);
+
+       if (!ptr)
+               panic("%s: Failed to allocate %zu bytes align=%zx nid=%d from=%llx\n",
+                     __func__, size, size, node, (u64)__pa(MAX_DMA_ADDRESS));
+
+       return ptr;
 }
 
 static void __ref zero_pte_populate(pmd_t *pmd, unsigned long addr,
index 470601115892740fad5e687a35c929d5a43ea97f..e7665cf914b136ab6fca01999b97afe1631e9c1f 100644 (file)
  * :c:func:`memblock_set_node`. The :c:func:`memblock_add_node`
  * performs such an assignment directly.
  *
- * Once memblock is setup the memory can be allocated using either
- * memblock or bootmem APIs.
+ * Once memblock is setup the memory can be allocated using one of the
+ * API variants:
+ *
+ * * :c:func:`memblock_phys_alloc*` - these functions return the
+ *   **physical** address of the allocated memory
+ * * :c:func:`memblock_alloc*` - these functions return the **virtual**
+ *   address of the allocated memory.
+ *
+ * Note, that both API variants use implict assumptions about allowed
+ * memory ranges and the fallback methods. Consult the documentation
+ * of :c:func:`memblock_alloc_internal` and
+ * :c:func:`memblock_alloc_range_nid` functions for more elaboarte
+ * description.
  *
  * As the system boot progresses, the architecture specific
  * :c:func:`mem_init` function frees all the memory to the buddy page
@@ -132,7 +143,7 @@ static int memblock_can_resize __initdata_memblock;
 static int memblock_memory_in_slab __initdata_memblock = 0;
 static int memblock_reserved_in_slab __initdata_memblock = 0;
 
-enum memblock_flags __init_memblock choose_memblock_flags(void)
+static enum memblock_flags __init_memblock choose_memblock_flags(void)
 {
        return system_has_some_mirror ? MEMBLOCK_MIRROR : MEMBLOCK_NONE;
 }
@@ -261,7 +272,7 @@ __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end,
  * Return:
  * Found address on success, 0 on failure.
  */
-phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size,
+static phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size,
                                        phys_addr_t align, phys_addr_t start,
                                        phys_addr_t end, int nid,
                                        enum memblock_flags flags)
@@ -435,17 +446,7 @@ static int __init_memblock memblock_double_array(struct memblock_type *type,
        else
                in_slab = &memblock_reserved_in_slab;
 
-       /* Try to find some space for it.
-        *
-        * WARNING: We assume that either slab_is_available() and we use it or
-        * we use MEMBLOCK for allocations. That means that this is unsafe to
-        * use when bootmem is currently active (unless bootmem itself is
-        * implemented on top of MEMBLOCK which isn't the case yet)
-        *
-        * This should however not be an issue for now, as we currently only
-        * call into MEMBLOCK while it's still active, or much later when slab
-        * is active for memory hotplug operations
-        */
+       /* Try to find some space for it */
        if (use_slab) {
                new_array = kmalloc(new_size, GFP_KERNEL);
                addr = new_array ? __pa(new_array) : 0;
@@ -858,11 +859,14 @@ static int __init_memblock memblock_setclr_flag(phys_addr_t base,
        if (ret)
                return ret;
 
-       for (i = start_rgn; i < end_rgn; i++)
+       for (i = start_rgn; i < end_rgn; i++) {
+               struct memblock_region *r = &type->regions[i];
+
                if (set)
-                       memblock_set_region_flags(&type->regions[i], flag);
+                       r->flags |= flag;
                else
-                       memblock_clear_region_flags(&type->regions[i], flag);
+                       r->flags &= ~flag;
+       }
 
        memblock_merge_regions(type);
        return 0;
@@ -962,8 +966,31 @@ void __init_memblock __next_reserved_mem_region(u64 *idx,
        *idx = ULLONG_MAX;
 }
 
+static bool should_skip_region(struct memblock_region *m, int nid, int flags)
+{
+       int m_nid = memblock_get_region_node(m);
+
+       /* only memory regions are associated with nodes, check it */
+       if (nid != NUMA_NO_NODE && nid != m_nid)
+               return true;
+
+       /* skip hotpluggable memory regions if needed */
+       if (movable_node_is_enabled() && memblock_is_hotpluggable(m))
+               return true;
+
+       /* if we want mirror memory skip non-mirror memory regions */
+       if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
+               return true;
+
+       /* skip nomap memory unless we were asked for it explicitly */
+       if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
+               return true;
+
+       return false;
+}
+
 /**
- * __next__mem_range - next function for for_each_free_mem_range() etc.
+ * __next_mem_range - next function for for_each_free_mem_range() etc.
  * @idx: pointer to u64 loop variable
  * @nid: node selector, %NUMA_NO_NODE for all nodes
  * @flags: pick from blocks based on memory attributes
@@ -1009,20 +1036,7 @@ void __init_memblock __next_mem_range(u64 *idx, int nid,
                phys_addr_t m_end = m->base + m->size;
                int         m_nid = memblock_get_region_node(m);
 
-               /* only memory regions are associated with nodes, check it */
-               if (nid != NUMA_NO_NODE && nid != m_nid)
-                       continue;
-
-               /* skip hotpluggable memory regions if needed */
-               if (movable_node_is_enabled() && memblock_is_hotpluggable(m))
-                       continue;
-
-               /* if we want mirror memory skip non-mirror memory regions */
-               if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
-                       continue;
-
-               /* skip nomap memory unless we were asked for it explicitly */
-               if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
+               if (should_skip_region(m, nid, flags))
                        continue;
 
                if (!type_b) {
@@ -1126,20 +1140,7 @@ void __init_memblock __next_mem_range_rev(u64 *idx, int nid,
                phys_addr_t m_end = m->base + m->size;
                int m_nid = memblock_get_region_node(m);
 
-               /* only memory regions are associated with nodes, check it */
-               if (nid != NUMA_NO_NODE && nid != m_nid)
-                       continue;
-
-               /* skip hotpluggable memory regions if needed */
-               if (movable_node_is_enabled() && memblock_is_hotpluggable(m))
-                       continue;
-
-               /* if we want mirror memory skip non-mirror memory regions */
-               if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
-                       continue;
-
-               /* skip nomap memory unless we were asked for it explicitly */
-               if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
+               if (should_skip_region(m, nid, flags))
                        continue;
 
                if (!type_b) {
@@ -1255,94 +1256,123 @@ int __init_memblock memblock_set_node(phys_addr_t base, phys_addr_t size,
 }
 #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
 
+/**
+ * memblock_alloc_range_nid - allocate boot memory block
+ * @size: size of memory block to be allocated in bytes
+ * @align: alignment of the region and block's size
+ * @start: the lower bound of the memory region to allocate (phys address)
+ * @end: the upper bound of the memory region to allocate (phys address)
+ * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
+ *
+ * The allocation is performed from memory region limited by
+ * memblock.current_limit if @max_addr == %MEMBLOCK_ALLOC_ACCESSIBLE.
+ *
+ * If the specified node can not hold the requested memory the
+ * allocation falls back to any node in the system
+ *
+ * For systems with memory mirroring, the allocation is attempted first
+ * from the regions with mirroring enabled and then retried from any
+ * memory region.
+ *
+ * In addition, function sets the min_count to 0 using kmemleak_alloc_phys for
+ * allocated boot memory block, so that it is never reported as leaks.
+ *
+ * Return:
+ * Physical address of allocated memory block on success, %0 on failure.
+ */
 static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
                                        phys_addr_t align, phys_addr_t start,
-                                       phys_addr_t end, int nid,
-                                       enum memblock_flags flags)
+                                       phys_addr_t end, int nid)
 {
+       enum memblock_flags flags = choose_memblock_flags();
        phys_addr_t found;
 
+       if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n"))
+               nid = NUMA_NO_NODE;
+
        if (!align) {
                /* Can't use WARNs this early in boot on powerpc */
                dump_stack();
                align = SMP_CACHE_BYTES;
        }
 
+       if (end > memblock.current_limit)
+               end = memblock.current_limit;
+
+again:
        found = memblock_find_in_range_node(size, align, start, end, nid,
                                            flags);
-       if (found && !memblock_reserve(found, size)) {
-               /*
-                * The min_count is set to 0 so that memblock allocations are
-                * never reported as leaks.
-                */
-               kmemleak_alloc_phys(found, size, 0, 0);
-               return found;
-       }
-       return 0;
-}
-
-phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,
-                                       phys_addr_t start, phys_addr_t end,
-                                       enum memblock_flags flags)
-{
-       return memblock_alloc_range_nid(size, align, start, end, NUMA_NO_NODE,
-                                       flags);
-}
-
-phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
-                                       phys_addr_t align, phys_addr_t max_addr,
-                                       int nid, enum memblock_flags flags)
-{
-       return memblock_alloc_range_nid(size, align, 0, max_addr, nid, flags);
-}
-
-phys_addr_t __init memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, int nid)
-{
-       enum memblock_flags flags = choose_memblock_flags();
-       phys_addr_t ret;
+       if (found && !memblock_reserve(found, size))
+               goto done;
 
-again:
-       ret = memblock_alloc_base_nid(size, align, MEMBLOCK_ALLOC_ACCESSIBLE,
-                                     nid, flags);
+       if (nid != NUMA_NO_NODE) {
+               found = memblock_find_in_range_node(size, align, start,
+                                                   end, NUMA_NO_NODE,
+                                                   flags);
+               if (found && !memblock_reserve(found, size))
+                       goto done;
+       }
 
-       if (!ret && (flags & MEMBLOCK_MIRROR)) {
+       if (flags & MEMBLOCK_MIRROR) {
                flags &= ~MEMBLOCK_MIRROR;
+               pr_warn("Could not allocate %pap bytes of mirrored memory\n",
+                       &size);
                goto again;
        }
-       return ret;
-}
-
-phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
-{
-       return memblock_alloc_base_nid(size, align, max_addr, NUMA_NO_NODE,
-                                      MEMBLOCK_NONE);
-}
 
-phys_addr_t __init memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
-{
-       phys_addr_t alloc;
-
-       alloc = __memblock_alloc_base(size, align, max_addr);
+       return 0;
 
-       if (alloc == 0)
-               panic("ERROR: Failed to allocate %pa bytes below %pa.\n",
-                     &size, &max_addr);
+done:
+       /* Skip kmemleak for kasan_init() due to high volume. */
+       if (end != MEMBLOCK_ALLOC_KASAN)
+               /*
+                * The min_count is set to 0 so that memblock allocated
+                * blocks are never reported as leaks. This is because many
+                * of these blocks are only referred via the physical
+                * address which is not looked up by kmemleak.
+                */
+               kmemleak_alloc_phys(found, size, 0, 0);
 
-       return alloc;
+       return found;
 }
 
-phys_addr_t __init memblock_phys_alloc(phys_addr_t size, phys_addr_t align)
+/**
+ * memblock_phys_alloc_range - allocate a memory block inside specified range
+ * @size: size of memory block to be allocated in bytes
+ * @align: alignment of the region and block's size
+ * @start: the lower bound of the memory region to allocate (physical address)
+ * @end: the upper bound of the memory region to allocate (physical address)
+ *
+ * Allocate @size bytes in the between @start and @end.
+ *
+ * Return: physical address of the allocated memory block on success,
+ * %0 on failure.
+ */
+phys_addr_t __init memblock_phys_alloc_range(phys_addr_t size,
+                                            phys_addr_t align,
+                                            phys_addr_t start,
+                                            phys_addr_t end)
 {
-       return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
+       return memblock_alloc_range_nid(size, align, start, end, NUMA_NO_NODE);
 }
 
+/**
+ * memblock_phys_alloc_try_nid - allocate a memory block from specified MUMA node
+ * @size: size of memory block to be allocated in bytes
+ * @align: alignment of the region and block's size
+ * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
+ *
+ * Allocates memory block from the specified NUMA node. If the node
+ * has no available memory, attempts to allocated from any node in the
+ * system.
+ *
+ * Return: physical address of the allocated memory block on success,
+ * %0 on failure.
+ */
 phys_addr_t __init memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid)
 {
-       phys_addr_t res = memblock_phys_alloc_nid(size, align, nid);
-
-       if (res)
-               return res;
-       return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
+       return memblock_alloc_range_nid(size, align, 0,
+                                       MEMBLOCK_ALLOC_ACCESSIBLE, nid);
 }
 
 /**
@@ -1353,19 +1383,13 @@ phys_addr_t __init memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t ali
  * @max_addr: the upper bound of the memory region to allocate (phys address)
  * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
  *
- * The @min_addr limit is dropped if it can not be satisfied and the allocation
- * will fall back to memory below @min_addr. Also, allocation may fall back
- * to any node in the system if the specified node can not
- * hold the requested memory.
+ * Allocates memory block using memblock_alloc_range_nid() and
+ * converts the returned physical address to virtual.
  *
- * The allocation is performed from memory region limited by
- * memblock.current_limit if @max_addr == %MEMBLOCK_ALLOC_ACCESSIBLE.
- *
- * The phys address of allocated boot memory block is converted to virtual and
- * allocated memory is reset to 0.
- *
- * In addition, function sets the min_count to 0 using kmemleak_alloc for
- * allocated boot memory block, so that it is never reported as leaks.
+ * The @min_addr limit is dropped if it can not be satisfied and the allocation
+ * will fall back to memory below @min_addr. Other constraints, such
+ * as node and mirrored memory will be handled again in
+ * memblock_alloc_range_nid().
  *
  * Return:
  * Virtual address of allocated memory block on success, NULL on failure.
@@ -1376,11 +1400,6 @@ static void * __init memblock_alloc_internal(
                                int nid)
 {
        phys_addr_t alloc;
-       void *ptr;
-       enum memblock_flags flags = choose_memblock_flags();
-
-       if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n"))
-               nid = NUMA_NO_NODE;
 
        /*
         * Detect any accidental use of these APIs after slab is ready, as at
@@ -1390,54 +1409,16 @@ static void * __init memblock_alloc_internal(
        if (WARN_ON_ONCE(slab_is_available()))
                return kzalloc_node(size, GFP_NOWAIT, nid);
 
-       if (!align) {
-               dump_stack();
-               align = SMP_CACHE_BYTES;
-       }
+       alloc = memblock_alloc_range_nid(size, align, min_addr, max_addr, nid);
 
-       if (max_addr > memblock.current_limit)
-               max_addr = memblock.current_limit;
-again:
-       alloc = memblock_find_in_range_node(size, align, min_addr, max_addr,
-                                           nid, flags);
-       if (alloc && !memblock_reserve(alloc, size))
-               goto done;
+       /* retry allocation without lower limit */
+       if (!alloc && min_addr)
+               alloc = memblock_alloc_range_nid(size, align, 0, max_addr, nid);
 
-       if (nid != NUMA_NO_NODE) {
-               alloc = memblock_find_in_range_node(size, align, min_addr,
-                                                   max_addr, NUMA_NO_NODE,
-                                                   flags);
-               if (alloc && !memblock_reserve(alloc, size))
-                       goto done;
-       }
-
-       if (min_addr) {
-               min_addr = 0;
-               goto again;
-       }
+       if (!alloc)
+               return NULL;
 
-       if (flags & MEMBLOCK_MIRROR) {
-               flags &= ~MEMBLOCK_MIRROR;
-               pr_warn("Could not allocate %pap bytes of mirrored memory\n",
-                       &size);
-               goto again;
-       }
-
-       return NULL;
-done:
-       ptr = phys_to_virt(alloc);
-
-       /* Skip kmemleak for kasan_init() due to high volume. */
-       if (max_addr != MEMBLOCK_ALLOC_KASAN)
-               /*
-                * The min_count is set to 0 so that bootmem allocated
-                * blocks are never reported as leaks. This is because many
-                * of these blocks are only referred via the physical
-                * address which is not looked up by kmemleak.
-                */
-               kmemleak_alloc(ptr, size, 0, 0);
-
-       return ptr;
+       return phys_to_virt(alloc);
 }
 
 /**
@@ -1479,7 +1460,7 @@ void * __init memblock_alloc_try_nid_raw(
 }
 
 /**
- * memblock_alloc_try_nid_nopanic - allocate boot memory block
+ * memblock_alloc_try_nid - allocate boot memory block
  * @size: size of memory block to be allocated in bytes
  * @align: alignment of the region and block's size
  * @min_addr: the lower bound of the memory region from where the allocation
@@ -1495,42 +1476,6 @@ void * __init memblock_alloc_try_nid_raw(
  * Return:
  * Virtual address of allocated memory block on success, NULL on failure.
  */
-void * __init memblock_alloc_try_nid_nopanic(
-                               phys_addr_t size, phys_addr_t align,
-                               phys_addr_t min_addr, phys_addr_t max_addr,
-                               int nid)
-{
-       void *ptr;
-
-       memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa %pF\n",
-                    __func__, (u64)size, (u64)align, nid, &min_addr,
-                    &max_addr, (void *)_RET_IP_);
-
-       ptr = memblock_alloc_internal(size, align,
-                                          min_addr, max_addr, nid);
-       if (ptr)
-               memset(ptr, 0, size);
-       return ptr;
-}
-
-/**
- * memblock_alloc_try_nid - allocate boot memory block with panicking
- * @size: size of memory block to be allocated in bytes
- * @align: alignment of the region and block's size
- * @min_addr: the lower bound of the memory region from where the allocation
- *       is preferred (phys address)
- * @max_addr: the upper bound of the memory region from where the allocation
- *           is preferred (phys address), or %MEMBLOCK_ALLOC_ACCESSIBLE to
- *           allocate only from memory limited by memblock.current_limit value
- * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
- *
- * Public panicking version of memblock_alloc_try_nid_nopanic()
- * which provides debug information (including caller info), if enabled,
- * and panics if the request can not be satisfied.
- *
- * Return:
- * Virtual address of allocated memory block on success, NULL on failure.
- */
 void * __init memblock_alloc_try_nid(
                        phys_addr_t size, phys_addr_t align,
                        phys_addr_t min_addr, phys_addr_t max_addr,
@@ -1543,24 +1488,20 @@ void * __init memblock_alloc_try_nid(
                     &max_addr, (void *)_RET_IP_);
        ptr = memblock_alloc_internal(size, align,
                                           min_addr, max_addr, nid);
-       if (ptr) {
+       if (ptr)
                memset(ptr, 0, size);
-               return ptr;
-       }
 
-       panic("%s: Failed to allocate %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa\n",
-             __func__, (u64)size, (u64)align, nid, &min_addr, &max_addr);
-       return NULL;
+       return ptr;
 }
 
 /**
- * __memblock_free_late - free bootmem block pages directly to buddy allocator
+ * __memblock_free_late - free pages directly to buddy allocator
  * @base: phys starting address of the  boot memory block
  * @size: size of the boot memory block in bytes
  *
- * This is only useful when the bootmem allocator has already been torn
+ * This is only useful when the memblock allocator has already been torn
  * down, but we are still initializing the system.  Pages are released directly
- * to the buddy allocator, no bootmem metadata is updated because it is gone.
+ * to the buddy allocator.
  */
 void __init __memblock_free_late(phys_addr_t base, phys_addr_t size)
 {
index 3eb01dedfb5059ac59d8825c6f6eb18c11720a2c..03fcf73d47dabde0987f3542c3c87fca33bf5a5d 100644 (file)
@@ -6445,8 +6445,8 @@ static void __ref setup_usemap(struct pglist_data *pgdat,
        zone->pageblock_flags = NULL;
        if (usemapsize) {
                zone->pageblock_flags =
-                       memblock_alloc_node_nopanic(usemapsize,
-                                                        pgdat->node_id);
+                       memblock_alloc_node(usemapsize, SMP_CACHE_BYTES,
+                                           pgdat->node_id);
                if (!zone->pageblock_flags)
                        panic("Failed to allocate %ld bytes for zone %s pageblock flags on node %d\n",
                              usemapsize, zone->name, pgdat->node_id);
@@ -6679,7 +6679,8 @@ static void __ref alloc_node_mem_map(struct pglist_data *pgdat)
                end = pgdat_end_pfn(pgdat);
                end = ALIGN(end, MAX_ORDER_NR_PAGES);
                size =  (end - start) * sizeof(struct page);
-               map = memblock_alloc_node_nopanic(size, pgdat->node_id);
+               map = memblock_alloc_node(size, SMP_CACHE_BYTES,
+                                         pgdat->node_id);
                if (!map)
                        panic("Failed to allocate %ld bytes for node %d memory map\n",
                              size, pgdat->node_id);
@@ -7959,8 +7960,7 @@ void *__init alloc_large_system_hash(const char *tablename,
                size = bucketsize << log2qty;
                if (flags & HASH_EARLY) {
                        if (flags & HASH_ZERO)
-                               table = memblock_alloc_nopanic(size,
-                                                              SMP_CACHE_BYTES);
+                               table = memblock_alloc(size, SMP_CACHE_BYTES);
                        else
                                table = memblock_alloc_raw(size,
                                                           SMP_CACHE_BYTES);
index ab4244920e0f83ac71134d9a3de2c9b2888faaea..d8f1aca4ad43696aa8f368c335a04c69918b77ef 100644 (file)
@@ -161,7 +161,7 @@ static int __init alloc_node_page_ext(int nid)
 
        table_size = get_entry_size() * nr_pages;
 
-       base = memblock_alloc_try_nid_nopanic(
+       base = memblock_alloc_try_nid(
                        table_size, PAGE_SIZE, __pa(MAX_DMA_ADDRESS),
                        MEMBLOCK_ALLOC_ACCESSIBLE, nid);
        if (!base)
index c5c750781628d7a793488dc8fd7d62019932bf90..2e6fc8d552c96d58f615be2fd3addadefd01f5c0 100644 (file)
@@ -1086,6 +1086,7 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(unsigned long tmp_addr,
        struct pcpu_chunk *chunk;
        unsigned long aligned_addr, lcm_align;
        int start_offset, offset_bits, region_size, region_bits;
+       size_t alloc_size;
 
        /* region calculations */
        aligned_addr = tmp_addr & PAGE_MASK;
@@ -1101,9 +1102,12 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(unsigned long tmp_addr,
        region_size = ALIGN(start_offset + map_size, lcm_align);
 
        /* allocate chunk */
-       chunk = memblock_alloc(sizeof(struct pcpu_chunk) +
-                              BITS_TO_LONGS(region_size >> PAGE_SHIFT),
-                              SMP_CACHE_BYTES);
+       alloc_size = sizeof(struct pcpu_chunk) +
+               BITS_TO_LONGS(region_size >> PAGE_SHIFT);
+       chunk = memblock_alloc(alloc_size, SMP_CACHE_BYTES);
+       if (!chunk)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     alloc_size);
 
        INIT_LIST_HEAD(&chunk->list);
 
@@ -1114,12 +1118,25 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(unsigned long tmp_addr,
        chunk->nr_pages = region_size >> PAGE_SHIFT;
        region_bits = pcpu_chunk_map_bits(chunk);
 
-       chunk->alloc_map = memblock_alloc(BITS_TO_LONGS(region_bits) * sizeof(chunk->alloc_map[0]),
-                                         SMP_CACHE_BYTES);
-       chunk->bound_map = memblock_alloc(BITS_TO_LONGS(region_bits + 1) * sizeof(chunk->bound_map[0]),
-                                         SMP_CACHE_BYTES);
-       chunk->md_blocks = memblock_alloc(pcpu_chunk_nr_blocks(chunk) * sizeof(chunk->md_blocks[0]),
-                                         SMP_CACHE_BYTES);
+       alloc_size = BITS_TO_LONGS(region_bits) * sizeof(chunk->alloc_map[0]);
+       chunk->alloc_map = memblock_alloc(alloc_size, SMP_CACHE_BYTES);
+       if (!chunk->alloc_map)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     alloc_size);
+
+       alloc_size =
+               BITS_TO_LONGS(region_bits + 1) * sizeof(chunk->bound_map[0]);
+       chunk->bound_map = memblock_alloc(alloc_size, SMP_CACHE_BYTES);
+       if (!chunk->bound_map)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     alloc_size);
+
+       alloc_size = pcpu_chunk_nr_blocks(chunk) * sizeof(chunk->md_blocks[0]);
+       chunk->md_blocks = memblock_alloc(alloc_size, SMP_CACHE_BYTES);
+       if (!chunk->md_blocks)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     alloc_size);
+
        pcpu_init_md_blocks(chunk);
 
        /* manage populated page bitmap */
@@ -1888,7 +1905,7 @@ struct pcpu_alloc_info * __init pcpu_alloc_alloc_info(int nr_groups,
                          __alignof__(ai->groups[0].cpu_map[0]));
        ai_size = base_size + nr_units * sizeof(ai->groups[0].cpu_map[0]);
 
-       ptr = memblock_alloc_nopanic(PFN_ALIGN(ai_size), PAGE_SIZE);
+       ptr = memblock_alloc(PFN_ALIGN(ai_size), PAGE_SIZE);
        if (!ptr)
                return NULL;
        ai = ptr;
@@ -2044,6 +2061,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
        int group, unit, i;
        int map_size;
        unsigned long tmp_addr;
+       size_t alloc_size;
 
 #define PCPU_SETUP_BUG_ON(cond)        do {                                    \
        if (unlikely(cond)) {                                           \
@@ -2075,14 +2093,29 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
        PCPU_SETUP_BUG_ON(pcpu_verify_alloc_info(ai) < 0);
 
        /* process group information and build config tables accordingly */
-       group_offsets = memblock_alloc(ai->nr_groups * sizeof(group_offsets[0]),
-                                      SMP_CACHE_BYTES);
-       group_sizes = memblock_alloc(ai->nr_groups * sizeof(group_sizes[0]),
-                                    SMP_CACHE_BYTES);
-       unit_map = memblock_alloc(nr_cpu_ids * sizeof(unit_map[0]),
-                                 SMP_CACHE_BYTES);
-       unit_off = memblock_alloc(nr_cpu_ids * sizeof(unit_off[0]),
-                                 SMP_CACHE_BYTES);
+       alloc_size = ai->nr_groups * sizeof(group_offsets[0]);
+       group_offsets = memblock_alloc(alloc_size, SMP_CACHE_BYTES);
+       if (!group_offsets)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     alloc_size);
+
+       alloc_size = ai->nr_groups * sizeof(group_sizes[0]);
+       group_sizes = memblock_alloc(alloc_size, SMP_CACHE_BYTES);
+       if (!group_sizes)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     alloc_size);
+
+       alloc_size = nr_cpu_ids * sizeof(unit_map[0]);
+       unit_map = memblock_alloc(alloc_size, SMP_CACHE_BYTES);
+       if (!unit_map)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     alloc_size);
+
+       alloc_size = nr_cpu_ids * sizeof(unit_off[0]);
+       unit_off = memblock_alloc(alloc_size, SMP_CACHE_BYTES);
+       if (!unit_off)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     alloc_size);
 
        for (cpu = 0; cpu < nr_cpu_ids; cpu++)
                unit_map[cpu] = UINT_MAX;
@@ -2148,6 +2181,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
        pcpu_nr_slots = __pcpu_size_to_slot(pcpu_unit_size) + 2;
        pcpu_slot = memblock_alloc(pcpu_nr_slots * sizeof(pcpu_slot[0]),
                                   SMP_CACHE_BYTES);
+       if (!pcpu_slot)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     pcpu_nr_slots * sizeof(pcpu_slot[0]));
        for (i = 0; i < pcpu_nr_slots; i++)
                INIT_LIST_HEAD(&pcpu_slot[i]);
 
@@ -2460,7 +2496,7 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, size_t dyn_size,
        size_sum = ai->static_size + ai->reserved_size + ai->dyn_size;
        areas_size = PFN_ALIGN(ai->nr_groups * sizeof(void *));
 
-       areas = memblock_alloc_nopanic(areas_size, SMP_CACHE_BYTES);
+       areas = memblock_alloc(areas_size, SMP_CACHE_BYTES);
        if (!areas) {
                rc = -ENOMEM;
                goto out_free;
@@ -2602,6 +2638,9 @@ int __init pcpu_page_first_chunk(size_t reserved_size,
        pages_size = PFN_ALIGN(unit_pages * num_possible_cpus() *
                               sizeof(pages[0]));
        pages = memblock_alloc(pages_size, SMP_CACHE_BYTES);
+       if (!pages)
+               panic("%s: Failed to allocate %zu bytes\n", __func__,
+                     pages_size);
 
        /* allocate pages */
        j = 0;
@@ -2690,8 +2729,7 @@ EXPORT_SYMBOL(__per_cpu_offset);
 static void * __init pcpu_dfl_fc_alloc(unsigned int cpu, size_t size,
                                       size_t align)
 {
-       return  memblock_alloc_from_nopanic(
-                       size, align, __pa(MAX_DMA_ADDRESS));
+       return  memblock_alloc_from(size, align, __pa(MAX_DMA_ADDRESS));
 }
 
 static void __init pcpu_dfl_fc_free(void *ptr, size_t size)
@@ -2739,9 +2777,7 @@ void __init setup_per_cpu_areas(void)
        void *fc;
 
        ai = pcpu_alloc_alloc_info(1, 1);
-       fc = memblock_alloc_from_nopanic(unit_size,
-                                             PAGE_SIZE,
-                                             __pa(MAX_DMA_ADDRESS));
+       fc = memblock_alloc_from(unit_size, PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
        if (!ai || !fc)
                panic("Failed to allocate memory for percpu areas.");
        /* kmemleak tracks the percpu allocations separately */
index 77a0554fa5bd3ea12fb78fd47eccce42603f474b..69904aa6165bf13b89a44d6abf84609fea2076ba 100644 (file)
@@ -65,11 +65,15 @@ static noinline struct mem_section __ref *sparse_index_alloc(int nid)
        unsigned long array_size = SECTIONS_PER_ROOT *
                                   sizeof(struct mem_section);
 
-       if (slab_is_available())
+       if (slab_is_available()) {
                section = kzalloc_node(array_size, GFP_KERNEL, nid);
-       else
+       } else {
                section = memblock_alloc_node(array_size, SMP_CACHE_BYTES,
                                              nid);
+               if (!section)
+                       panic("%s: Failed to allocate %lu bytes nid=%d\n",
+                             __func__, array_size, nid);
+       }
 
        return section;
 }
@@ -218,6 +222,9 @@ void __init memory_present(int nid, unsigned long start, unsigned long end)
                size = sizeof(struct mem_section*) * NR_SECTION_ROOTS;
                align = 1 << (INTERNODE_CACHE_SHIFT);
                mem_section = memblock_alloc(size, align);
+               if (!mem_section)
+                       panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                             __func__, size, align);
        }
 #endif
 
@@ -323,9 +330,7 @@ sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat,
        limit = goal + (1UL << PA_SECTION_SHIFT);
        nid = early_pfn_to_nid(goal >> PAGE_SHIFT);
 again:
-       p = memblock_alloc_try_nid_nopanic(size,
-                                               SMP_CACHE_BYTES, goal, limit,
-                                               nid);
+       p = memblock_alloc_try_nid(size, SMP_CACHE_BYTES, goal, limit, nid);
        if (!p && limit) {
                limit = 0;
                goto again;
@@ -379,7 +384,7 @@ static unsigned long * __init
 sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat,
                                         unsigned long size)
 {
-       return memblock_alloc_node_nopanic(size, pgdat->node_id);
+       return memblock_alloc_node(size, SMP_CACHE_BYTES, pgdat->node_id);
 }
 
 static void __init check_usemap_section_nr(int nid, unsigned long *usemap)
@@ -404,13 +409,18 @@ struct page __init *sparse_mem_map_populate(unsigned long pnum, int nid,
 {
        unsigned long size = section_map_size();
        struct page *map = sparse_buffer_alloc(size);
+       phys_addr_t addr = __pa(MAX_DMA_ADDRESS);
 
        if (map)
                return map;
 
        map = memblock_alloc_try_nid(size,
-                                         PAGE_SIZE, __pa(MAX_DMA_ADDRESS),
+                                         PAGE_SIZE, addr,
                                          MEMBLOCK_ALLOC_ACCESSIBLE, nid);
+       if (!map)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx nid=%d from=%pa\n",
+                     __func__, size, PAGE_SIZE, nid, &addr);
+
        return map;
 }
 #endif /* !CONFIG_SPARSEMEM_VMEMMAP */
@@ -420,10 +430,11 @@ static void *sparsemap_buf_end __meminitdata;
 
 static void __init sparse_buffer_init(unsigned long size, int nid)
 {
+       phys_addr_t addr = __pa(MAX_DMA_ADDRESS);
        WARN_ON(sparsemap_buf); /* forgot to call sparse_buffer_fini()? */
        sparsemap_buf =
                memblock_alloc_try_nid_raw(size, PAGE_SIZE,
-                                               __pa(MAX_DMA_ADDRESS),
+                                               addr,
                                                MEMBLOCK_ALLOC_ACCESSIBLE, nid);
        sparsemap_buf_end = sparsemap_buf + size;
 }
index ba01fc4270bdcebc12743e5f32625fc14d9e9a0a..5b8e5bd7457b4b418c4131d5e87e54e4614d351e 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/in6.h>
 #include <linux/jiffies.h>
 #include <linux/time.h>
-#include <linux/flex_array.h>
 #include <linux/cpumask.h>
 #include <net/inet_ecn.h>
 #include <net/ip_tunnels.h>
index 6657606b2b4767fe5c2fa4b2c362bc834c806f93..66f9553758a5ad5681246c2199f42f82246dd36d 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/in6.h>
 #include <linux/jiffies.h>
 #include <linux/time.h>
-#include <linux/flex_array.h>
 
 #include <net/inet_ecn.h>
 #include <net/ip_tunnels.h>
index 80ea2a71852e57b26936f3563527c066c4bc3312..cfb0098c9a016abf8b4e9329818210aef83f4aa8 100644 (file)
@@ -111,29 +111,6 @@ int ovs_flow_tbl_count(const struct flow_table *table)
        return table->count;
 }
 
-static struct flex_array *alloc_buckets(unsigned int n_buckets)
-{
-       struct flex_array *buckets;
-       int i, err;
-
-       buckets = flex_array_alloc(sizeof(struct hlist_head),
-                                  n_buckets, GFP_KERNEL);
-       if (!buckets)
-               return NULL;
-
-       err = flex_array_prealloc(buckets, 0, n_buckets, GFP_KERNEL);
-       if (err) {
-               flex_array_free(buckets);
-               return NULL;
-       }
-
-       for (i = 0; i < n_buckets; i++)
-               INIT_HLIST_HEAD((struct hlist_head *)
-                                       flex_array_get(buckets, i));
-
-       return buckets;
-}
-
 static void flow_free(struct sw_flow *flow)
 {
        int cpu;
@@ -168,31 +145,30 @@ void ovs_flow_free(struct sw_flow *flow, bool deferred)
                flow_free(flow);
 }
 
-static void free_buckets(struct flex_array *buckets)
-{
-       flex_array_free(buckets);
-}
-
-
 static void __table_instance_destroy(struct table_instance *ti)
 {
-       free_buckets(ti->buckets);
+       kvfree(ti->buckets);
        kfree(ti);
 }
 
 static struct table_instance *table_instance_alloc(int new_size)
 {
        struct table_instance *ti = kmalloc(sizeof(*ti), GFP_KERNEL);
+       int i;
 
        if (!ti)
                return NULL;
 
-       ti->buckets = alloc_buckets(new_size);
-
+       ti->buckets = kvmalloc_array(new_size, sizeof(struct hlist_head),
+                                    GFP_KERNEL);
        if (!ti->buckets) {
                kfree(ti);
                return NULL;
        }
+
+       for (i = 0; i < new_size; i++)
+               INIT_HLIST_HEAD(&ti->buckets[i]);
+
        ti->n_buckets = new_size;
        ti->node_ver = 0;
        ti->keep_flows = false;
@@ -249,7 +225,7 @@ static void table_instance_destroy(struct table_instance *ti,
 
        for (i = 0; i < ti->n_buckets; i++) {
                struct sw_flow *flow;
-               struct hlist_head *head = flex_array_get(ti->buckets, i);
+               struct hlist_head *head = &ti->buckets[i];
                struct hlist_node *n;
                int ver = ti->node_ver;
                int ufid_ver = ufid_ti->node_ver;
@@ -294,7 +270,7 @@ struct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *ti,
        ver = ti->node_ver;
        while (*bucket < ti->n_buckets) {
                i = 0;
-               head = flex_array_get(ti->buckets, *bucket);
+               head = &ti->buckets[*bucket];
                hlist_for_each_entry_rcu(flow, head, flow_table.node[ver]) {
                        if (i < *last) {
                                i++;
@@ -313,8 +289,7 @@ struct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *ti,
 static struct hlist_head *find_bucket(struct table_instance *ti, u32 hash)
 {
        hash = jhash_1word(hash, ti->hash_seed);
-       return flex_array_get(ti->buckets,
-                               (hash & (ti->n_buckets - 1)));
+       return &ti->buckets[hash & (ti->n_buckets - 1)];
 }
 
 static void table_instance_insert(struct table_instance *ti,
@@ -347,9 +322,7 @@ static void flow_table_copy_flows(struct table_instance *old,
        /* Insert in new table. */
        for (i = 0; i < old->n_buckets; i++) {
                struct sw_flow *flow;
-               struct hlist_head *head;
-
-               head = flex_array_get(old->buckets, i);
+               struct hlist_head *head = &old->buckets[i];
 
                if (ufid)
                        hlist_for_each_entry(flow, head,
index 2dd9900f533df364fb5fb7b1772b9805b28092cc..de5ec6cf51744701e6f954c9264472e45f916a05 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/in6.h>
 #include <linux/jiffies.h>
 #include <linux/time.h>
-#include <linux/flex_array.h>
 
 #include <net/inet_ecn.h>
 #include <net/ip_tunnels.h>
@@ -37,7 +36,7 @@
 #include "flow.h"
 
 struct table_instance {
-       struct flex_array *buckets;
+       struct hlist_head *buckets;
        unsigned int n_buckets;
        struct rcu_head rcu;
        int node_ver;
index 3b47457862ccdac668a8947f6191507d1b83ee68..b6bb68adac6e294b1d4caee5efaab8f93e6a683a 100644 (file)
 #include <net/sctp/sm.h>
 #include <net/sctp/stream_sched.h>
 
-static struct flex_array *fa_alloc(size_t elem_size, size_t elem_count,
-                                  gfp_t gfp)
-{
-       struct flex_array *result;
-       int err;
-
-       result = flex_array_alloc(elem_size, elem_count, gfp);
-       if (result) {
-               err = flex_array_prealloc(result, 0, elem_count, gfp);
-               if (err) {
-                       flex_array_free(result);
-                       result = NULL;
-               }
-       }
-
-       return result;
-}
-
-static void fa_free(struct flex_array *fa)
-{
-       if (fa)
-               flex_array_free(fa);
-}
-
-static void fa_copy(struct flex_array *fa, struct flex_array *from,
-                   size_t index, size_t count)
-{
-       void *elem;
-
-       while (count--) {
-               elem = flex_array_get(from, index);
-               flex_array_put(fa, index, elem, 0);
-               index++;
-       }
-}
-
-static void fa_zero(struct flex_array *fa, size_t index, size_t count)
-{
-       void *elem;
-
-       while (count--) {
-               elem = flex_array_get(fa, index);
-               memset(elem, 0, fa->element_size);
-               index++;
-       }
-}
-
-static size_t fa_index(struct flex_array *fa, void *elem, size_t count)
-{
-       size_t index = 0;
-
-       while (count--) {
-               if (elem == flex_array_get(fa, index))
-                       break;
-               index++;
-       }
-
-       return index;
-}
-
 /* Migrates chunks from stream queues to new stream queues if needed,
  * but not across associations. Also, removes those chunks to streams
  * higher than the new max.
@@ -153,53 +93,32 @@ static void sctp_stream_outq_migrate(struct sctp_stream *stream,
 static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt,
                                 gfp_t gfp)
 {
-       struct flex_array *out;
-       size_t elem_size = sizeof(struct sctp_stream_out);
-
-       out = fa_alloc(elem_size, outcnt, gfp);
-       if (!out)
-               return -ENOMEM;
-
-       if (stream->out) {
-               fa_copy(out, stream->out, 0, min(outcnt, stream->outcnt));
-               if (stream->out_curr) {
-                       size_t index = fa_index(stream->out, stream->out_curr,
-                                               stream->outcnt);
-
-                       BUG_ON(index == stream->outcnt);
-                       stream->out_curr = flex_array_get(out, index);
-               }
-               fa_free(stream->out);
-       }
+       int ret;
 
-       if (outcnt > stream->outcnt)
-               fa_zero(out, stream->outcnt, (outcnt - stream->outcnt));
+       if (outcnt <= stream->outcnt)
+               return 0;
 
-       stream->out = out;
+       ret = genradix_prealloc(&stream->out, outcnt, gfp);
+       if (ret)
+               return ret;
 
+       stream->outcnt = outcnt;
        return 0;
 }
 
 static int sctp_stream_alloc_in(struct sctp_stream *stream, __u16 incnt,
                                gfp_t gfp)
 {
-       struct flex_array *in;
-       size_t elem_size = sizeof(struct sctp_stream_in);
-
-       in = fa_alloc(elem_size, incnt, gfp);
-       if (!in)
-               return -ENOMEM;
-
-       if (stream->in) {
-               fa_copy(in, stream->in, 0, min(incnt, stream->incnt));
-               fa_free(stream->in);
-       }
+       int ret;
 
-       if (incnt > stream->incnt)
-               fa_zero(in, stream->incnt, (incnt - stream->incnt));
+       if (incnt <= stream->incnt)
+               return 0;
 
-       stream->in = in;
+       ret = genradix_prealloc(&stream->in, incnt, gfp);
+       if (ret)
+               return ret;
 
+       stream->incnt = incnt;
        return 0;
 }
 
@@ -226,7 +145,6 @@ int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,
        if (ret)
                goto out;
 
-       stream->outcnt = outcnt;
        for (i = 0; i < stream->outcnt; i++)
                SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
 
@@ -238,14 +156,11 @@ in:
        ret = sctp_stream_alloc_in(stream, incnt, gfp);
        if (ret) {
                sched->free(stream);
-               fa_free(stream->out);
-               stream->out = NULL;
+               genradix_free(&stream->out);
                stream->outcnt = 0;
                goto out;
        }
 
-       stream->incnt = incnt;
-
 out:
        return ret;
 }
@@ -270,8 +185,8 @@ void sctp_stream_free(struct sctp_stream *stream)
        sched->free(stream);
        for (i = 0; i < stream->outcnt; i++)
                kfree(SCTP_SO(stream, i)->ext);
-       fa_free(stream->out);
-       fa_free(stream->in);
+       genradix_free(&stream->out);
+       genradix_free(&stream->in);
 }
 
 void sctp_stream_clear(struct sctp_stream *stream)
@@ -302,8 +217,8 @@ void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new)
 
        sched->sched_all(stream);
 
-       new->out = NULL;
-       new->in  = NULL;
+       new->out.tree.root = NULL;
+       new->in.tree.root  = NULL;
        new->outcnt = 0;
        new->incnt  = 0;
 }
@@ -555,8 +470,6 @@ int sctp_send_add_streams(struct sctp_association *asoc,
                goto out;
        }
 
-       stream->outcnt = outcnt;
-
        asoc->strreset_outstanding = !!out + !!in;
 
 out:
index a6bf215794661db08ab7373c2a34b402e1605b2d..102c6fefe38c93be2760ca7df0adfe62bead1313 100644 (file)
@@ -101,7 +101,7 @@ static void sctp_chunk_assign_mid(struct sctp_chunk *chunk)
 
 static bool sctp_validate_data(struct sctp_chunk *chunk)
 {
-       const struct sctp_stream *stream;
+       struct sctp_stream *stream;
        __u16 sid, ssn;
 
        if (chunk->chunk_hdr->type != SCTP_CID_DATA)
index c0417cf17feeee9bf5a94876553b02ac3119cb59..8c5800750fa85ba4ac329f70e52b8ced05e13ad7 100644 (file)
@@ -93,12 +93,10 @@ avtab_insert_node(struct avtab *h, int hvalue,
                newnode->next = prev->next;
                prev->next = newnode;
        } else {
-               newnode->next = flex_array_get_ptr(h->htable, hvalue);
-               if (flex_array_put_ptr(h->htable, hvalue, newnode,
-                                      GFP_KERNEL|__GFP_ZERO)) {
-                       kmem_cache_free(avtab_node_cachep, newnode);
-                       return NULL;
-               }
+               struct avtab_node **n = &h->htable[hvalue];
+
+               newnode->next = *n;
+               *n = newnode;
        }
 
        h->nel++;
@@ -111,11 +109,11 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
        struct avtab_node *prev, *cur, *newnode;
        u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
 
-       if (!h || !h->htable)
+       if (!h)
                return -EINVAL;
 
        hvalue = avtab_hash(key, h->mask);
-       for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue);
+       for (prev = NULL, cur = h->htable[hvalue];
             cur;
             prev = cur, cur = cur->next) {
                if (key->source_type == cur->key.source_type &&
@@ -156,10 +154,10 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu
        struct avtab_node *prev, *cur;
        u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
 
-       if (!h || !h->htable)
+       if (!h)
                return NULL;
        hvalue = avtab_hash(key, h->mask);
-       for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue);
+       for (prev = NULL, cur = h->htable[hvalue];
             cur;
             prev = cur, cur = cur->next) {
                if (key->source_type == cur->key.source_type &&
@@ -186,11 +184,11 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
        struct avtab_node *cur;
        u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
 
-       if (!h || !h->htable)
+       if (!h)
                return NULL;
 
        hvalue = avtab_hash(key, h->mask);
-       for (cur = flex_array_get_ptr(h->htable, hvalue); cur;
+       for (cur = h->htable[hvalue]; cur;
             cur = cur->next) {
                if (key->source_type == cur->key.source_type &&
                    key->target_type == cur->key.target_type &&
@@ -222,11 +220,11 @@ avtab_search_node(struct avtab *h, struct avtab_key *key)
        struct avtab_node *cur;
        u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
 
-       if (!h || !h->htable)
+       if (!h)
                return NULL;
 
        hvalue = avtab_hash(key, h->mask);
-       for (cur = flex_array_get_ptr(h->htable, hvalue); cur;
+       for (cur = h->htable[hvalue]; cur;
             cur = cur->next) {
                if (key->source_type == cur->key.source_type &&
                    key->target_type == cur->key.target_type &&
@@ -281,11 +279,11 @@ void avtab_destroy(struct avtab *h)
        int i;
        struct avtab_node *cur, *temp;
 
-       if (!h || !h->htable)
+       if (!h)
                return;
 
        for (i = 0; i < h->nslot; i++) {
-               cur = flex_array_get_ptr(h->htable, i);
+               cur = h->htable[i];
                while (cur) {
                        temp = cur;
                        cur = cur->next;
@@ -295,7 +293,7 @@ void avtab_destroy(struct avtab *h)
                        kmem_cache_free(avtab_node_cachep, temp);
                }
        }
-       flex_array_free(h->htable);
+       kvfree(h->htable);
        h->htable = NULL;
        h->nslot = 0;
        h->mask = 0;
@@ -303,6 +301,7 @@ void avtab_destroy(struct avtab *h)
 
 int avtab_init(struct avtab *h)
 {
+       kvfree(h->htable);
        h->htable = NULL;
        h->nel = 0;
        return 0;
@@ -329,8 +328,7 @@ int avtab_alloc(struct avtab *h, u32 nrules)
                nslot = MAX_AVTAB_HASH_BUCKETS;
        mask = nslot - 1;
 
-       h->htable = flex_array_alloc(sizeof(struct avtab_node *), nslot,
-                                    GFP_KERNEL | __GFP_ZERO);
+       h->htable = kvcalloc(nslot, sizeof(void *), GFP_KERNEL);
        if (!h->htable)
                return -ENOMEM;
 
@@ -353,7 +351,7 @@ void avtab_hash_eval(struct avtab *h, char *tag)
        max_chain_len = 0;
        chain2_len_sum = 0;
        for (i = 0; i < h->nslot; i++) {
-               cur = flex_array_get_ptr(h->htable, i);
+               cur = h->htable[i];
                if (cur) {
                        slots_used++;
                        chain_len = 0;
@@ -646,7 +644,7 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp)
                return rc;
 
        for (i = 0; i < a->nslot; i++) {
-               for (cur = flex_array_get_ptr(a->htable, i); cur;
+               for (cur = a->htable[i]; cur;
                     cur = cur->next) {
                        rc = avtab_write_item(p, cur, fp);
                        if (rc)
index 0d652fad5319743528d27eb20263325e147cf570..de16673b2314a9bcf93673dea1a42f224aa50600 100644 (file)
@@ -24,7 +24,6 @@
 #define _SS_AVTAB_H_
 
 #include "security.h"
-#include <linux/flex_array.h>
 
 struct avtab_key {
        u16 source_type;        /* source type */
@@ -84,11 +83,10 @@ struct avtab_node {
 };
 
 struct avtab {
-       struct flex_array *htable;
+       struct avtab_node **htable;
        u32 nel;        /* number of elements */
        u32 nslot;      /* number of hash slots */
        u32 mask;       /* mask to compute hash func */
-
 };
 
 int avtab_init(struct avtab *);
index f49e522e932d43e35fcc903e6e4cffed12c83ed0..3bbb6034520905f4cb8080d206b528cc3de06d40 100644 (file)
@@ -195,7 +195,6 @@ int cond_index_bool(void *key, void *datum, void *datap)
 {
        struct policydb *p;
        struct cond_bool_datum *booldatum;
-       struct flex_array *fa;
 
        booldatum = datum;
        p = datap;
@@ -203,10 +202,7 @@ int cond_index_bool(void *key, void *datum, void *datap)
        if (!booldatum->value || booldatum->value > p->p_bools.nprim)
                return -EINVAL;
 
-       fa = p->sym_val_to_name[SYM_BOOLS];
-       if (flex_array_put_ptr(fa, booldatum->value - 1, key,
-                              GFP_KERNEL | __GFP_ZERO))
-               BUG();
+       p->sym_val_to_name[SYM_BOOLS][booldatum->value - 1] = key;
        p->bool_val_to_struct[booldatum->value - 1] = booldatum;
 
        return 0;
index c1c31e33657ae6d6b9f6247a4c7ac29f6026bc4d..6b576e58872550b991e9ae941999f9a3ffb968b7 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/audit.h>
-#include <linux/flex_array.h>
 #include "security.h"
 
 #include "policydb.h"
@@ -341,17 +340,14 @@ static int common_index(void *key, void *datum, void *datap)
 {
        struct policydb *p;
        struct common_datum *comdatum;
-       struct flex_array *fa;
 
        comdatum = datum;
        p = datap;
        if (!comdatum->value || comdatum->value > p->p_commons.nprim)
                return -EINVAL;
 
-       fa = p->sym_val_to_name[SYM_COMMONS];
-       if (flex_array_put_ptr(fa, comdatum->value - 1, key,
-                              GFP_KERNEL | __GFP_ZERO))
-               BUG();
+       p->sym_val_to_name[SYM_COMMONS][comdatum->value - 1] = key;
+
        return 0;
 }
 
@@ -359,16 +355,13 @@ static int class_index(void *key, void *datum, void *datap)
 {
        struct policydb *p;
        struct class_datum *cladatum;
-       struct flex_array *fa;
 
        cladatum = datum;
        p = datap;
        if (!cladatum->value || cladatum->value > p->p_classes.nprim)
                return -EINVAL;
-       fa = p->sym_val_to_name[SYM_CLASSES];
-       if (flex_array_put_ptr(fa, cladatum->value - 1, key,
-                              GFP_KERNEL | __GFP_ZERO))
-               BUG();
+
+       p->sym_val_to_name[SYM_CLASSES][cladatum->value - 1] = key;
        p->class_val_to_struct[cladatum->value - 1] = cladatum;
        return 0;
 }
@@ -377,7 +370,6 @@ static int role_index(void *key, void *datum, void *datap)
 {
        struct policydb *p;
        struct role_datum *role;
-       struct flex_array *fa;
 
        role = datum;
        p = datap;
@@ -386,10 +378,7 @@ static int role_index(void *key, void *datum, void *datap)
            || role->bounds > p->p_roles.nprim)
                return -EINVAL;
 
-       fa = p->sym_val_to_name[SYM_ROLES];
-       if (flex_array_put_ptr(fa, role->value - 1, key,
-                              GFP_KERNEL | __GFP_ZERO))
-               BUG();
+       p->sym_val_to_name[SYM_ROLES][role->value - 1] = key;
        p->role_val_to_struct[role->value - 1] = role;
        return 0;
 }
@@ -398,7 +387,6 @@ static int type_index(void *key, void *datum, void *datap)
 {
        struct policydb *p;
        struct type_datum *typdatum;
-       struct flex_array *fa;
 
        typdatum = datum;
        p = datap;
@@ -408,15 +396,8 @@ static int type_index(void *key, void *datum, void *datap)
                    || typdatum->value > p->p_types.nprim
                    || typdatum->bounds > p->p_types.nprim)
                        return -EINVAL;
-               fa = p->sym_val_to_name[SYM_TYPES];
-               if (flex_array_put_ptr(fa, typdatum->value - 1, key,
-                                      GFP_KERNEL | __GFP_ZERO))
-                       BUG();
-
-               fa = p->type_val_to_struct_array;
-               if (flex_array_put_ptr(fa, typdatum->value - 1, typdatum,
-                                      GFP_KERNEL | __GFP_ZERO))
-                       BUG();
+               p->sym_val_to_name[SYM_TYPES][typdatum->value - 1] = key;
+               p->type_val_to_struct_array[typdatum->value - 1] = typdatum;
        }
 
        return 0;
@@ -426,7 +407,6 @@ static int user_index(void *key, void *datum, void *datap)
 {
        struct policydb *p;
        struct user_datum *usrdatum;
-       struct flex_array *fa;
 
        usrdatum = datum;
        p = datap;
@@ -435,10 +415,7 @@ static int user_index(void *key, void *datum, void *datap)
            || usrdatum->bounds > p->p_users.nprim)
                return -EINVAL;
 
-       fa = p->sym_val_to_name[SYM_USERS];
-       if (flex_array_put_ptr(fa, usrdatum->value - 1, key,
-                              GFP_KERNEL | __GFP_ZERO))
-               BUG();
+       p->sym_val_to_name[SYM_USERS][usrdatum->value - 1] = key;
        p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
        return 0;
 }
@@ -447,7 +424,6 @@ static int sens_index(void *key, void *datum, void *datap)
 {
        struct policydb *p;
        struct level_datum *levdatum;
-       struct flex_array *fa;
 
        levdatum = datum;
        p = datap;
@@ -456,10 +432,8 @@ static int sens_index(void *key, void *datum, void *datap)
                if (!levdatum->level->sens ||
                    levdatum->level->sens > p->p_levels.nprim)
                        return -EINVAL;
-               fa = p->sym_val_to_name[SYM_LEVELS];
-               if (flex_array_put_ptr(fa, levdatum->level->sens - 1, key,
-                                      GFP_KERNEL | __GFP_ZERO))
-                       BUG();
+
+               p->sym_val_to_name[SYM_LEVELS][levdatum->level->sens - 1] = key;
        }
 
        return 0;
@@ -469,7 +443,6 @@ static int cat_index(void *key, void *datum, void *datap)
 {
        struct policydb *p;
        struct cat_datum *catdatum;
-       struct flex_array *fa;
 
        catdatum = datum;
        p = datap;
@@ -477,10 +450,8 @@ static int cat_index(void *key, void *datum, void *datap)
        if (!catdatum->isalias) {
                if (!catdatum->value || catdatum->value > p->p_cats.nprim)
                        return -EINVAL;
-               fa = p->sym_val_to_name[SYM_CATS];
-               if (flex_array_put_ptr(fa, catdatum->value - 1, key,
-                                      GFP_KERNEL | __GFP_ZERO))
-                       BUG();
+
+               p->sym_val_to_name[SYM_CATS][catdatum->value - 1] = key;
        }
 
        return 0;
@@ -568,35 +539,23 @@ static int policydb_index(struct policydb *p)
        if (!p->user_val_to_struct)
                return -ENOMEM;
 
-       /* Yes, I want the sizeof the pointer, not the structure */
-       p->type_val_to_struct_array = flex_array_alloc(sizeof(struct type_datum *),
-                                                      p->p_types.nprim,
-                                                      GFP_KERNEL | __GFP_ZERO);
+       p->type_val_to_struct_array = kvcalloc(p->p_types.nprim,
+                                              sizeof(*p->type_val_to_struct_array),
+                                              GFP_KERNEL);
        if (!p->type_val_to_struct_array)
                return -ENOMEM;
 
-       rc = flex_array_prealloc(p->type_val_to_struct_array, 0,
-                                p->p_types.nprim, GFP_KERNEL | __GFP_ZERO);
-       if (rc)
-               goto out;
-
        rc = cond_init_bool_indexes(p);
        if (rc)
                goto out;
 
        for (i = 0; i < SYM_NUM; i++) {
-               p->sym_val_to_name[i] = flex_array_alloc(sizeof(char *),
-                                                        p->symtab[i].nprim,
-                                                        GFP_KERNEL | __GFP_ZERO);
+               p->sym_val_to_name[i] = kvcalloc(p->symtab[i].nprim,
+                                                sizeof(char *),
+                                                GFP_KERNEL);
                if (!p->sym_val_to_name[i])
                        return -ENOMEM;
 
-               rc = flex_array_prealloc(p->sym_val_to_name[i],
-                                        0, p->symtab[i].nprim,
-                                        GFP_KERNEL | __GFP_ZERO);
-               if (rc)
-                       goto out;
-
                rc = hashtab_map(p->symtab[i].table, index_f[i], p);
                if (rc)
                        goto out;
@@ -810,16 +769,13 @@ void policydb_destroy(struct policydb *p)
                hashtab_destroy(p->symtab[i].table);
        }
 
-       for (i = 0; i < SYM_NUM; i++) {
-               if (p->sym_val_to_name[i])
-                       flex_array_free(p->sym_val_to_name[i]);
-       }
+       for (i = 0; i < SYM_NUM; i++)
+               kvfree(p->sym_val_to_name[i]);
 
        kfree(p->class_val_to_struct);
        kfree(p->role_val_to_struct);
        kfree(p->user_val_to_struct);
-       if (p->type_val_to_struct_array)
-               flex_array_free(p->type_val_to_struct_array);
+       kvfree(p->type_val_to_struct_array);
 
        avtab_destroy(&p->te_avtab);
 
@@ -872,17 +828,9 @@ void policydb_destroy(struct policydb *p)
        hashtab_map(p->range_tr, range_tr_destroy, NULL);
        hashtab_destroy(p->range_tr);
 
-       if (p->type_attr_map_array) {
-               for (i = 0; i < p->p_types.nprim; i++) {
-                       struct ebitmap *e;
-
-                       e = flex_array_get(p->type_attr_map_array, i);
-                       if (!e)
-                               continue;
-                       ebitmap_destroy(e);
-               }
-               flex_array_free(p->type_attr_map_array);
-       }
+       for (i = 0; i < p->p_types.nprim; i++)
+               ebitmap_destroy(&p->type_attr_map_array[i]);
+       kvfree(p->type_attr_map_array);
 
        ebitmap_destroy(&p->filename_trans_ttypes);
        ebitmap_destroy(&p->policycaps);
@@ -1770,8 +1718,7 @@ static int type_bounds_sanity_check(void *key, void *datum, void *datap)
                        return -EINVAL;
                }
 
-               upper = flex_array_get_ptr(p->type_val_to_struct_array,
-                                          upper->bounds - 1);
+               upper = p->type_val_to_struct_array[upper->bounds - 1];
                BUG_ON(!upper);
 
                if (upper->attribute) {
@@ -2543,23 +2490,15 @@ int policydb_read(struct policydb *p, void *fp)
        if (rc)
                goto bad;
 
-       rc = -ENOMEM;
-       p->type_attr_map_array = flex_array_alloc(sizeof(struct ebitmap),
-                                                 p->p_types.nprim,
-                                                 GFP_KERNEL | __GFP_ZERO);
+       p->type_attr_map_array = kvcalloc(p->p_types.nprim,
+                                         sizeof(*p->type_attr_map_array),
+                                         GFP_KERNEL);
        if (!p->type_attr_map_array)
                goto bad;
 
-       /* preallocate so we don't have to worry about the put ever failing */
-       rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim,
-                                GFP_KERNEL | __GFP_ZERO);
-       if (rc)
-               goto bad;
-
        for (i = 0; i < p->p_types.nprim; i++) {
-               struct ebitmap *e = flex_array_get(p->type_attr_map_array, i);
+               struct ebitmap *e = &p->type_attr_map_array[i];
 
-               BUG_ON(!e);
                ebitmap_init(e);
                if (p->policyvers >= POLICYDB_VERSION_AVTAB) {
                        rc = ebitmap_read(e, fp);
@@ -3554,9 +3493,8 @@ int policydb_write(struct policydb *p, void *fp)
                return rc;
 
        for (i = 0; i < p->p_types.nprim; i++) {
-               struct ebitmap *e = flex_array_get(p->type_attr_map_array, i);
+               struct ebitmap *e = &p->type_attr_map_array[i];
 
-               BUG_ON(!e);
                rc = ebitmap_write(e, fp);
                if (rc)
                        return rc;
index 215f8f30ac5a5dcfa5126c8357da7cebf9639a1b..27039149ff0ae17610b31a2690a98197449020b0 100644 (file)
@@ -24,8 +24,6 @@
 #ifndef _SS_POLICYDB_H_
 #define _SS_POLICYDB_H_
 
-#include <linux/flex_array.h>
-
 #include "symtab.h"
 #include "avtab.h"
 #include "sidtab.h"
@@ -251,13 +249,13 @@ struct policydb {
 #define p_cats symtab[SYM_CATS]
 
        /* symbol names indexed by (value - 1) */
-       struct flex_array *sym_val_to_name[SYM_NUM];
+       char            **sym_val_to_name[SYM_NUM];
 
        /* class, role, and user attributes indexed by (value - 1) */
        struct class_datum **class_val_to_struct;
        struct role_datum **role_val_to_struct;
        struct user_datum **user_val_to_struct;
-       struct flex_array *type_val_to_struct_array;
+       struct type_datum **type_val_to_struct_array;
 
        /* type enforcement access vectors and transitions */
        struct avtab te_avtab;
@@ -294,7 +292,7 @@ struct policydb {
        struct hashtab *range_tr;
 
        /* type -> attribute reverse mapping */
-       struct flex_array *type_attr_map_array;
+       struct ebitmap *type_attr_map_array;
 
        struct ebitmap policycaps;
 
@@ -369,9 +367,7 @@ static inline int put_entry(const void *buf, size_t bytes, int num, struct polic
 
 static inline char *sym_name(struct policydb *p, unsigned int sym_num, unsigned int element_nr)
 {
-       struct flex_array *fa = p->sym_val_to_name[sym_num];
-
-       return flex_array_get_ptr(fa, element_nr);
+       return p->sym_val_to_name[sym_num][element_nr];
 }
 
 extern u16 string_to_security_class(struct policydb *p, const char *name);
index 1269e2be3c2d9ff1b03f21376c7354e2cb354b0c..ec62918521b1706ed0216d7eb2c2575e6640970f 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/sched.h>
 #include <linux/audit.h>
 #include <linux/mutex.h>
-#include <linux/flex_array.h>
 #include <linux/vmalloc.h>
 #include <net/netlabel.h>
 
@@ -545,15 +544,13 @@ static void type_attribute_bounds_av(struct policydb *policydb,
        struct type_datum *target;
        u32 masked = 0;
 
-       source = flex_array_get_ptr(policydb->type_val_to_struct_array,
-                                   scontext->type - 1);
+       source = policydb->type_val_to_struct_array[scontext->type - 1];
        BUG_ON(!source);
 
        if (!source->bounds)
                return;
 
-       target = flex_array_get_ptr(policydb->type_val_to_struct_array,
-                                   tcontext->type - 1);
+       target = policydb->type_val_to_struct_array[tcontext->type - 1];
        BUG_ON(!target);
 
        memset(&lo_avd, 0, sizeof(lo_avd));
@@ -653,11 +650,9 @@ static void context_struct_compute_av(struct policydb *policydb,
         */
        avkey.target_class = tclass;
        avkey.specified = AVTAB_AV | AVTAB_XPERMS;
-       sattr = flex_array_get(policydb->type_attr_map_array,
-                              scontext->type - 1);
+       sattr = &policydb->type_attr_map_array[scontext->type - 1];
        BUG_ON(!sattr);
-       tattr = flex_array_get(policydb->type_attr_map_array,
-                              tcontext->type - 1);
+       tattr = &policydb->type_attr_map_array[tcontext->type - 1];
        BUG_ON(!tattr);
        ebitmap_for_each_positive_bit(sattr, snode, i) {
                ebitmap_for_each_positive_bit(tattr, tnode, j) {
@@ -900,8 +895,7 @@ int security_bounded_transition(struct selinux_state *state,
 
        index = new_context->type;
        while (true) {
-               type = flex_array_get_ptr(policydb->type_val_to_struct_array,
-                                         index - 1);
+               type = policydb->type_val_to_struct_array[index - 1];
                BUG_ON(!type);
 
                /* not bounded anymore */
@@ -1064,11 +1058,9 @@ void security_compute_xperms_decision(struct selinux_state *state,
 
        avkey.target_class = tclass;
        avkey.specified = AVTAB_XPERMS;
-       sattr = flex_array_get(policydb->type_attr_map_array,
-                               scontext->type - 1);
+       sattr = &policydb->type_attr_map_array[scontext->type - 1];
        BUG_ON(!sattr);
-       tattr = flex_array_get(policydb->type_attr_map_array,
-                               tcontext->type - 1);
+       tattr = &policydb->type_attr_map_array[tcontext->type - 1];
        BUG_ON(!tattr);
        ebitmap_for_each_positive_bit(sattr, snode, i) {
                ebitmap_for_each_positive_bit(tattr, tnode, j) {
index 9fdcd3eaac3b3b92ead5246b324aa42d68c6dbdb..d2972576910778a2a73898c456a83c6ede2cd577 100644 (file)
@@ -87,9 +87,6 @@
 #define MUTEX_DEBUG_INIT       0x11
 #define MUTEX_DEBUG_FREE       0x22
 
-/********** lib/flex_array.c **********/
-#define FLEX_ARRAY_FREE        0x6c    /* for use-after-free poisoning */
-
 /********** security/ **********/
 #define KEY_DESTROY            0xbd
 
index 584eb8ea780a49220782d08e104756199fc19934..780ce71233743f4c3b9b36e9435f9eae2d676641 100755 (executable)
@@ -290,6 +290,58 @@ run_numerictests()
        test_rc
 }
 
+check_failure()
+{
+       echo -n "Testing that $1 fails as expected..."
+       reset_vals
+       TEST_STR="$1"
+       orig="$(cat $TARGET)"
+       echo -n "$TEST_STR" > $TARGET 2> /dev/null
+
+       # write should fail and $TARGET should retain its original value
+       if [ $? = 0 ] || [ "$(cat $TARGET)" != "$orig" ]; then
+               echo "FAIL" >&2
+               rc=1
+       else
+               echo "ok"
+       fi
+       test_rc
+}
+
+run_wideint_tests()
+{
+       # sysctl conversion functions receive a boolean sign and ulong
+       # magnitude; here we list the magnitudes we want to test (each of
+       # which will be tested in both positive and negative forms).  Since
+       # none of these values fit in 32 bits, writing them to an int- or
+       # uint-typed sysctl should fail.
+       local magnitudes=(
+               # common boundary-condition values (zero, +1, -1, INT_MIN,
+               # and INT_MAX respectively) if truncated to lower 32 bits
+               # (potential for being falsely deemed in range)
+               0x0000000100000000
+               0x0000000100000001
+               0x00000001ffffffff
+               0x0000000180000000
+               0x000000017fffffff
+
+               # these look like negatives, but without a leading '-' are
+               # actually large positives (should be rejected as above
+               # despite being zero/+1/-1/INT_MIN/INT_MAX in the lower 32)
+               0xffffffff00000000
+               0xffffffff00000001
+               0xffffffffffffffff
+               0xffffffff80000000
+               0xffffffff7fffffff
+       )
+
+       for sign in '' '-'; do
+               for mag in "${magnitudes[@]}"; do
+                       check_failure "${sign}${mag}"
+               done
+       done
+}
+
 # Your test must accept digits 3 and 4 to use this
 run_limit_digit()
 {
@@ -556,6 +608,7 @@ sysctl_test_0001()
        TEST_STR=$(( $ORIG + 1 ))
 
        run_numerictests
+       run_wideint_tests
        run_limit_digit
 }
 
@@ -580,6 +633,7 @@ sysctl_test_0003()
        TEST_STR=$(( $ORIG + 1 ))
 
        run_numerictests
+       run_wideint_tests
        run_limit_digit
        run_limit_digit_int
 }
@@ -592,6 +646,7 @@ sysctl_test_0004()
        TEST_STR=$(( $ORIG + 1 ))
 
        run_numerictests
+       run_wideint_tests
        run_limit_digit
        run_limit_digit_uint
 }