4a4cc4a368292dec6f231cb5ce4dad12ea6ee9ef
[linux-flexiantxendom0-3.2.10.git] / fs / xfs / support / kmem.h
1 /*
2  * Copyright (c) 2000-2002 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
57 /*
58  * XXX get rid of the unconditional  __GFP_NOFAIL by adding
59  * a KM_FAIL flag and using it where we're allowed to fail.
60  */
61 static __inline unsigned int
62 flag_convert(int flags)
63 {
64 #if DEBUG
65         if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS))) {
66                 printk(KERN_WARNING
67                     "XFS: memory allocation with wrong flags (%x)\n", flags);
68                 BUG();
69         }
70 #endif
71
72         if (flags & KM_NOSLEEP)
73                 return GFP_ATOMIC;
74         /* If we're in a transaction, FS activity is not ok */
75         else if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS))
76                 return GFP_NOFS | __GFP_NOFAIL;
77         return GFP_KERNEL | __GFP_NOFAIL;
78 }
79
80 static __inline void *
81 kmem_alloc(size_t size, int flags)
82 {
83         if (unlikely(MAX_SLAB_SIZE < size))
84                 /* Avoid doing filesystem sensitive stuff to get this */
85                 return __vmalloc(size, flag_convert(flags), PAGE_KERNEL);
86         return kmalloc(size, flag_convert(flags));
87 }
88
89 static __inline void *
90 kmem_zalloc(size_t size, int flags)
91 {
92         void *ptr = kmem_alloc(size, flags);
93         if (likely(ptr != NULL))
94                 memset(ptr, 0, size);
95         return ptr;
96 }
97
98 static __inline void
99 kmem_free(void *ptr, size_t size)
100 {
101         if (unlikely((unsigned long)ptr < VMALLOC_START ||
102                      (unsigned long)ptr >= VMALLOC_END))
103                 kfree(ptr);
104         else
105                 vfree(ptr);
106 }
107
108 static __inline void *
109 kmem_realloc(void *ptr, size_t newsize, size_t oldsize, int flags)
110 {
111         void *new = kmem_alloc(newsize, flags);
112
113         if (likely(ptr != NULL)) {
114                 if (likely(new != NULL))
115                         memcpy(new, ptr, min(oldsize, newsize));
116                 kmem_free(ptr, oldsize);
117         }
118
119         return new;
120 }
121
122 static __inline kmem_zone_t *
123 kmem_zone_init(int size, char *zone_name)
124 {
125         return kmem_cache_create(zone_name, size, 0, 0, NULL, NULL);
126 }
127
128 static __inline void *
129 kmem_zone_alloc(kmem_zone_t *zone, int flags)
130 {
131         return kmem_cache_alloc(zone, flag_convert(flags));
132 }
133
134 static __inline void *
135 kmem_zone_zalloc(kmem_zone_t *zone, int flags)
136 {
137         void *ptr = kmem_zone_alloc(zone, flags);
138         if (likely(ptr != NULL))
139                 memset(ptr, 0, kmem_cache_size(zone));
140         return ptr;
141 }
142
143 static __inline void
144 kmem_zone_free(kmem_zone_t *zone, void *ptr)
145 {
146         kmem_cache_free(zone, ptr);
147 }
148
149 #endif /* __XFS_SUPPORT_KMEM_H__ */