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