linux/fs/xfs/kmem.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
   3 * All Rights Reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it would be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write the Free Software Foundation,
  16 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  17 */
  18#include <linux/mm.h>
  19#include <linux/highmem.h>
  20#include <linux/slab.h>
  21#include <linux/swap.h>
  22#include <linux/blkdev.h>
  23#include <linux/backing-dev.h>
  24#include "kmem.h"
  25#include "xfs_message.h"
  26
  27/*
  28 * Greedy allocation.  May fail and may return vmalloced memory.
  29 */
  30void *
  31kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize)
  32{
  33        void            *ptr;
  34        size_t          kmsize = maxsize;
  35
  36        while (!(ptr = vzalloc(kmsize))) {
  37                if ((kmsize >>= 1) <= minsize)
  38                        kmsize = minsize;
  39        }
  40        if (ptr)
  41                *size = kmsize;
  42        return ptr;
  43}
  44
  45void *
  46kmem_alloc(size_t size, xfs_km_flags_t flags)
  47{
  48        int     retries = 0;
  49        gfp_t   lflags = kmem_flags_convert(flags);
  50        void    *ptr;
  51
  52        do {
  53                ptr = kmalloc(size, lflags);
  54                if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
  55                        return ptr;
  56                if (!(++retries % 100))
  57                        xfs_err(NULL,
  58        "%s(%u) possible memory allocation deadlock size %u in %s (mode:0x%x)",
  59                                current->comm, current->pid,
  60                                (unsigned int)size, __func__, lflags);
  61                congestion_wait(BLK_RW_ASYNC, HZ/50);
  62        } while (1);
  63}
  64
  65void *
  66kmem_zalloc_large(size_t size, xfs_km_flags_t flags)
  67{
  68        unsigned noio_flag = 0;
  69        void    *ptr;
  70        gfp_t   lflags;
  71
  72        ptr = kmem_zalloc(size, flags | KM_MAYFAIL);
  73        if (ptr)
  74                return ptr;
  75
  76        /*
  77         * __vmalloc() will allocate data pages and auxillary structures (e.g.
  78         * pagetables) with GFP_KERNEL, yet we may be under GFP_NOFS context
  79         * here. Hence we need to tell memory reclaim that we are in such a
  80         * context via PF_MEMALLOC_NOIO to prevent memory reclaim re-entering
  81         * the filesystem here and potentially deadlocking.
  82         */
  83        if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS))
  84                noio_flag = memalloc_noio_save();
  85
  86        lflags = kmem_flags_convert(flags);
  87        ptr = __vmalloc(size, lflags | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
  88
  89        if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS))
  90                memalloc_noio_restore(noio_flag);
  91
  92        return ptr;
  93}
  94
  95void *
  96kmem_realloc(const void *old, size_t newsize, xfs_km_flags_t flags)
  97{
  98        int     retries = 0;
  99        gfp_t   lflags = kmem_flags_convert(flags);
 100        void    *ptr;
 101
 102        do {
 103                ptr = krealloc(old, newsize, lflags);
 104                if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
 105                        return ptr;
 106                if (!(++retries % 100))
 107                        xfs_err(NULL,
 108        "%s(%u) possible memory allocation deadlock size %zu in %s (mode:0x%x)",
 109                                current->comm, current->pid,
 110                                newsize, __func__, lflags);
 111                congestion_wait(BLK_RW_ASYNC, HZ/50);
 112        } while (1);
 113}
 114
 115void *
 116kmem_zone_alloc(kmem_zone_t *zone, xfs_km_flags_t flags)
 117{
 118        int     retries = 0;
 119        gfp_t   lflags = kmem_flags_convert(flags);
 120        void    *ptr;
 121
 122        do {
 123                ptr = kmem_cache_alloc(zone, lflags);
 124                if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
 125                        return ptr;
 126                if (!(++retries % 100))
 127                        xfs_err(NULL,
 128                "%s(%u) possible memory allocation deadlock in %s (mode:0x%x)",
 129                                current->comm, current->pid,
 130                                __func__, lflags);
 131                congestion_wait(BLK_RW_ASYNC, HZ/50);
 132        } while (1);
 133}
 134