This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / fs / xfs / linux / kmem.h
1 /*
2  * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  *
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  *
26  * http://www.sgi.com
27  *
28  * For further information regarding this notice, see:
29  *
30  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31  */
32 #ifndef __XFS_SUPPORT_KMEM_H__
33 #define __XFS_SUPPORT_KMEM_H__
34
35 #include <linux/mm.h>
36 #include <linux/highmem.h>
37 #include <linux/slab.h>
38 #include <linux/vmalloc.h>
39
40 /*
41  * Cutoff point to use vmalloc instead of kmalloc.
42  */
43 #define MAX_SLAB_SIZE   0x10000
44
45 /*
46  * XFS uses slightly different names for these due to the
47  * IRIX heritage.
48  */
49 #define kmem_zone       kmem_cache_s
50 #define kmem_zone_t     kmem_cache_t
51
52 #define KM_SLEEP        0x0001
53 #define KM_NOSLEEP      0x0002
54 #define KM_NOFS         0x0004
55
56 typedef unsigned long xfs_pflags_t;
57
58 #define PFLAGS_TEST_FSTRANS()           (current->flags & PF_FSTRANS)
59
60 /* these could be nested, so we save state */
61 #define PFLAGS_SET_FSTRANS(STATEP) do { \
62         *(STATEP) = current->flags;     \
63         current->flags |= PF_FSTRANS;   \
64 } while (0)
65
66 #define PFLAGS_CLEAR_FSTRANS(STATEP) do { \
67         *(STATEP) = current->flags;     \
68         current->flags &= ~PF_FSTRANS;  \
69 } while (0)
70
71 /* Restore the PF_FSTRANS state to what was saved in STATEP */
72 #define PFLAGS_RESTORE_FSTRANS(STATEP) do {                     \
73         current->flags = ((current->flags & ~PF_FSTRANS) |      \
74                           (*(STATEP) & PF_FSTRANS));            \
75 } while (0)
76
77 #define PFLAGS_DUP(OSTATEP, NSTATEP) do { \
78         *(NSTATEP) = *(OSTATEP);        \
79 } while (0)
80
81 /*
82  * XXX get rid of the unconditional  __GFP_NOFAIL by adding
83  * a KM_FAIL flag and using it where we're allowed to fail.
84  */
85 static __inline unsigned int
86 kmem_flags_convert(int flags)
87 {
88         int lflags;
89
90 #if DEBUG
91         if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS))) {
92                 printk(KERN_WARNING
93                     "XFS: memory allocation with wrong flags (%x)\n", flags);
94                 BUG();
95         }
96 #endif
97
98         lflags = (flags & KM_NOSLEEP) ? GFP_ATOMIC : (GFP_KERNEL|__GFP_NOFAIL);
99
100         /* avoid recusive callbacks to filesystem during transactions */
101         if (PFLAGS_TEST_FSTRANS() || (flags & KM_NOFS))
102                 lflags &= ~__GFP_FS;
103
104         return lflags;
105 }
106
107 static __inline void *
108 kmem_alloc(size_t size, int flags)
109 {
110         if (unlikely(MAX_SLAB_SIZE < size))
111                 /* Avoid doing filesystem sensitive stuff to get this */
112                 return __vmalloc(size, kmem_flags_convert(flags), PAGE_KERNEL);
113         return kmalloc(size, kmem_flags_convert(flags));
114 }
115
116 static __inline void *
117 kmem_zalloc(size_t size, int flags)
118 {
119         void *ptr = kmem_alloc(size, flags);
120         if (likely(ptr != NULL))
121                 memset(ptr, 0, size);
122         return ptr;
123 }
124
125 static __inline void
126 kmem_free(void *ptr, size_t size)
127 {
128         if (unlikely((unsigned long)ptr < VMALLOC_START ||
129                      (unsigned long)ptr >= VMALLOC_END))
130                 kfree(ptr);
131         else
132                 vfree(ptr);
133 }
134
135 static __inline void *
136 kmem_realloc(void *ptr, size_t newsize, size_t oldsize, int flags)
137 {
138         void *new = kmem_alloc(newsize, flags);
139
140         if (likely(ptr != NULL)) {
141                 if (likely(new != NULL))
142                         memcpy(new, ptr, min(oldsize, newsize));
143                 kmem_free(ptr, oldsize);
144         }
145
146         return new;
147 }
148
149 static __inline kmem_zone_t *
150 kmem_zone_init(int size, char *zone_name)
151 {
152         return kmem_cache_create(zone_name, size, 0, 0, NULL, NULL);
153 }
154
155 static __inline void *
156 kmem_zone_alloc(kmem_zone_t *zone, int flags)
157 {
158         return kmem_cache_alloc(zone, kmem_flags_convert(flags));
159 }
160
161 static __inline void *
162 kmem_zone_zalloc(kmem_zone_t *zone, int flags)
163 {
164         void *ptr = kmem_zone_alloc(zone, flags);
165         if (likely(ptr != NULL))
166                 memset(ptr, 0, kmem_cache_size(zone));
167         return ptr;
168 }
169
170 static __inline void
171 kmem_zone_free(kmem_zone_t *zone, void *ptr)
172 {
173         kmem_cache_free(zone, ptr);
174 }
175
176 typedef struct shrinker *kmem_shaker_t;
177 typedef int (*kmem_shake_func_t)(int, unsigned int);
178
179 static __inline kmem_shaker_t
180 kmem_shake_register(kmem_shake_func_t sfunc)
181 {
182         return set_shrinker(DEFAULT_SEEKS, sfunc);
183 }
184
185 static __inline void
186 kmem_shake_deregister(kmem_shaker_t shrinker)
187 {
188         remove_shrinker(shrinker);
189 }
190
191 static __inline int
192 kmem_shake_allow(unsigned int gfp_mask)
193 {
194         return (gfp_mask & __GFP_WAIT);
195 }
196
197 #endif /* __XFS_SUPPORT_KMEM_H__ */