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/sched/mm.h>
  20#include <linux/highmem.h>
  21#include <linux/slab.h>
  22#include <linux/swap.h>
  23#include <linux/blkdev.h>
  24#include <linux/backing-dev.h>
  25#include "kmem.h"
  26#include "xfs_message.h"
  27
  28void *
  29kmem_alloc(size_t size, xfs_km_flags_t flags)
  30{
  31        int     retries = 0;
  32        gfp_t   lflags = kmem_flags_convert(flags);
  33        void    *ptr;
  34
  35        do {
  36                ptr = kmalloc(size, lflags);
  37                if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
  38                        return ptr;
  39                if (!(++retries % 100))
  40                        xfs_err(NULL,
  41        "%s(%u) possible memory allocation deadlock size %u in %s (mode:0x%x)",
  42                                current->comm, current->pid,
  43                                (unsigned int)size, __func__, lflags);
  44                congestion_wait(BLK_RW_ASYNC, HZ/50);
  45        } while (1);
  46}
  47
  48void *
  49kmem_alloc_large(size_t size, xfs_km_flags_t flags)
  50{
  51        unsigned nofs_flag = 0;
  52        void    *ptr;
  53        gfp_t   lflags;
  54
  55        ptr = kmem_alloc(size, flags | KM_MAYFAIL);
  56        if (ptr)
  57                return ptr;
  58
  59        /*
  60         * __vmalloc() will allocate data pages and auxillary structures (e.g.
  61         * pagetables) with GFP_KERNEL, yet we may be under GFP_NOFS context
  62         * here. Hence we need to tell memory reclaim that we are in such a
  63         * context via PF_MEMALLOC_NOFS to prevent memory reclaim re-entering
  64         * the filesystem here and potentially deadlocking.
  65         */
  66        if (flags & KM_NOFS)
  67                nofs_flag = memalloc_nofs_save();
  68
  69        lflags = kmem_flags_convert(flags);
  70        ptr = __vmalloc(size, lflags, PAGE_KERNEL);
  71
  72        if (flags & KM_NOFS)
  73                memalloc_nofs_restore(nofs_flag);
  74
  75        return ptr;
  76}
  77
  78void *
  79kmem_realloc(const void *old, size_t newsize, xfs_km_flags_t flags)
  80{
  81        int     retries = 0;
  82        gfp_t   lflags = kmem_flags_convert(flags);
  83        void    *ptr;
  84
  85        do {
  86                ptr = krealloc(old, newsize, lflags);
  87                if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
  88                        return ptr;
  89                if (!(++retries % 100))
  90                        xfs_err(NULL,
  91        "%s(%u) possible memory allocation deadlock size %zu in %s (mode:0x%x)",
  92                                current->comm, current->pid,
  93                                newsize, __func__, lflags);
  94                congestion_wait(BLK_RW_ASYNC, HZ/50);
  95        } while (1);
  96}
  97
  98void *
  99kmem_zone_alloc(kmem_zone_t *zone, xfs_km_flags_t flags)
 100{
 101        int     retries = 0;
 102        gfp_t   lflags = kmem_flags_convert(flags);
 103        void    *ptr;
 104
 105        do {
 106                ptr = kmem_cache_alloc(zone, lflags);
 107                if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
 108                        return ptr;
 109                if (!(++retries % 100))
 110                        xfs_err(NULL,
 111                "%s(%u) possible memory allocation deadlock in %s (mode:0x%x)",
 112                                current->comm, current->pid,
 113                                __func__, lflags);
 114                congestion_wait(BLK_RW_ASYNC, HZ/50);
 115        } while (1);
 116}
 117