linux/fs/xfs/linux-2.6/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/vmalloc.h>
  20#include <linux/highmem.h>
  21#include <linux/swap.h>
  22#include <linux/blkdev.h>
  23#include <linux/backing-dev.h>
  24#include "time.h"
  25#include "kmem.h"
  26
  27#define MAX_VMALLOCS    6
  28#define MAX_SLAB_SIZE   0x20000
  29
  30void *
  31kmem_alloc(size_t size, unsigned int __nocast flags)
  32{
  33        int     retries = 0;
  34        gfp_t   lflags = kmem_flags_convert(flags);
  35        void    *ptr;
  36
  37#ifdef DEBUG
  38        if (unlikely(!(flags & KM_LARGE) && (size > PAGE_SIZE))) {
  39                printk(KERN_WARNING "Large %s attempt, size=%ld\n",
  40                        __func__, (long)size);
  41                dump_stack();
  42        }
  43#endif
  44
  45        do {
  46                if (size < MAX_SLAB_SIZE || retries > MAX_VMALLOCS)
  47                        ptr = kmalloc(size, lflags);
  48                else
  49                        ptr = __vmalloc(size, lflags, PAGE_KERNEL);
  50                if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
  51                        return ptr;
  52                if (!(++retries % 100))
  53                        printk(KERN_ERR "XFS: possible memory allocation "
  54                                        "deadlock in %s (mode:0x%x)\n",
  55                                        __func__, lflags);
  56                congestion_wait(BLK_RW_ASYNC, HZ/50);
  57        } while (1);
  58}
  59
  60void *
  61kmem_zalloc(size_t size, unsigned int __nocast flags)
  62{
  63        void    *ptr;
  64
  65        ptr = kmem_alloc(size, flags);
  66        if (ptr)
  67                memset((char *)ptr, 0, (int)size);
  68        return ptr;
  69}
  70
  71void *
  72kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize,
  73                   unsigned int __nocast flags)
  74{
  75        void            *ptr;
  76        size_t          kmsize = maxsize;
  77        unsigned int    kmflags = (flags & ~KM_SLEEP) | KM_NOSLEEP;
  78
  79        while (!(ptr = kmem_zalloc(kmsize, kmflags))) {
  80                if ((kmsize <= minsize) && (flags & KM_NOSLEEP))
  81                        break;
  82                if ((kmsize >>= 1) <= minsize) {
  83                        kmsize = minsize;
  84                        kmflags = flags;
  85                }
  86        }
  87        if (ptr)
  88                *size = kmsize;
  89        return ptr;
  90}
  91
  92void
  93kmem_free(const void *ptr)
  94{
  95        if (!is_vmalloc_addr(ptr)) {
  96                kfree(ptr);
  97        } else {
  98                vfree(ptr);
  99        }
 100}
 101
 102void *
 103kmem_realloc(const void *ptr, size_t newsize, size_t oldsize,
 104             unsigned int __nocast flags)
 105{
 106        void    *new;
 107
 108        new = kmem_alloc(newsize, flags);
 109        if (ptr) {
 110                if (new)
 111                        memcpy(new, ptr,
 112                                ((oldsize < newsize) ? oldsize : newsize));
 113                kmem_free(ptr);
 114        }
 115        return new;
 116}
 117
 118void *
 119kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags)
 120{
 121        int     retries = 0;
 122        gfp_t   lflags = kmem_flags_convert(flags);
 123        void    *ptr;
 124
 125        do {
 126                ptr = kmem_cache_alloc(zone, lflags);
 127                if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
 128                        return ptr;
 129                if (!(++retries % 100))
 130                        printk(KERN_ERR "XFS: possible memory allocation "
 131                                        "deadlock in %s (mode:0x%x)\n",
 132                                        __func__, lflags);
 133                congestion_wait(BLK_RW_ASYNC, HZ/50);
 134        } while (1);
 135}
 136
 137void *
 138kmem_zone_zalloc(kmem_zone_t *zone, unsigned int __nocast flags)
 139{
 140        void    *ptr;
 141
 142        ptr = kmem_zone_alloc(zone, flags);
 143        if (ptr)
 144                memset((char *)ptr, 0, kmem_cache_size(zone));
 145        return ptr;
 146}
 147