Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  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 "time.h"
 25#include "kmem.h"
 26#include "xfs_message.h"
 27
 28/*
 29 * Greedy allocation.  May fail and may return vmalloced memory.
 30 */
 31void *
 32kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize)
 33{
 34	void		*ptr;
 35	size_t		kmsize = maxsize;
 36
 37	while (!(ptr = vzalloc(kmsize))) {
 38		if ((kmsize >>= 1) <= minsize)
 39			kmsize = minsize;
 40	}
 41	if (ptr)
 42		*size = kmsize;
 43	return ptr;
 44}
 45
 46void *
 47kmem_alloc(size_t size, xfs_km_flags_t flags)
 48{
 49	int	retries = 0;
 50	gfp_t	lflags = kmem_flags_convert(flags);
 51	void	*ptr;
 52
 53	do {
 54		ptr = kmalloc(size, lflags);
 55		if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
 56			return ptr;
 57		if (!(++retries % 100))
 58			xfs_err(NULL,
 59		"possible memory allocation deadlock in %s (mode:0x%x)",
 60					__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_free(const void *ptr)
 97{
 98	if (!is_vmalloc_addr(ptr)) {
 99		kfree(ptr);
100	} else {
101		vfree(ptr);
102	}
103}
104
105void *
106kmem_realloc(const void *ptr, size_t newsize, size_t oldsize,
107	     xfs_km_flags_t flags)
108{
109	void	*new;
110
111	new = kmem_alloc(newsize, flags);
112	if (ptr) {
113		if (new)
114			memcpy(new, ptr,
115				((oldsize < newsize) ? oldsize : newsize));
116		kmem_free(ptr);
117	}
118	return new;
119}
120
121void *
122kmem_zone_alloc(kmem_zone_t *zone, xfs_km_flags_t flags)
123{
124	int	retries = 0;
125	gfp_t	lflags = kmem_flags_convert(flags);
126	void	*ptr;
127
128	do {
129		ptr = kmem_cache_alloc(zone, lflags);
130		if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
131			return ptr;
132		if (!(++retries % 100))
133			xfs_err(NULL,
134		"possible memory allocation deadlock in %s (mode:0x%x)",
135					__func__, lflags);
136		congestion_wait(BLK_RW_ASYNC, HZ/50);
137	} while (1);
138}