diff options
author | Christoph Hellwig <hch@infradead.org> | 2010-01-20 16:55:30 -0500 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2010-01-21 14:44:56 -0500 |
commit | bdfb04301fa5fdd95f219539a9a5b9663b1e5fc2 (patch) | |
tree | 6d50b1c71d1f227cf1800ee0531a475266ef6da8 | |
parent | a14a348bff2f99471a28e5928eb6801224c053d8 (diff) |
xfs: replace KM_LARGE with explicit vmalloc use
We use the KM_LARGE flag to make kmem_alloc and friends use vmalloc
if necessary. As we only need this for a few boot/mount time
allocations just switch to explicit vmalloc calls there.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Alex Elder <aelder@sgi.com>
-rw-r--r-- | fs/xfs/linux-2.6/kmem.c | 56 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/kmem.h | 21 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.c | 6 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_qm.c | 26 | ||||
-rw-r--r-- | fs/xfs/xfs_itable.c | 8 |
5 files changed, 66 insertions, 51 deletions
diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c index 2d3f90afe5f1..bc7405585def 100644 --- a/fs/xfs/linux-2.6/kmem.c +++ b/fs/xfs/linux-2.6/kmem.c | |||
@@ -16,7 +16,6 @@ | |||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | #include <linux/vmalloc.h> | ||
20 | #include <linux/highmem.h> | 19 | #include <linux/highmem.h> |
21 | #include <linux/swap.h> | 20 | #include <linux/swap.h> |
22 | #include <linux/blkdev.h> | 21 | #include <linux/blkdev.h> |
@@ -24,8 +23,25 @@ | |||
24 | #include "time.h" | 23 | #include "time.h" |
25 | #include "kmem.h" | 24 | #include "kmem.h" |
26 | 25 | ||
27 | #define MAX_VMALLOCS 6 | 26 | /* |
28 | #define MAX_SLAB_SIZE 0x20000 | 27 | * Greedy allocation. May fail and may return vmalloced memory. |
28 | * | ||
29 | * Must be freed using kmem_free_large. | ||
30 | */ | ||
31 | void * | ||
32 | kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize) | ||
33 | { | ||
34 | void *ptr; | ||
35 | size_t kmsize = maxsize; | ||
36 | |||
37 | while (!(ptr = kmem_zalloc_large(kmsize))) { | ||
38 | if ((kmsize >>= 1) <= minsize) | ||
39 | kmsize = minsize; | ||
40 | } | ||
41 | if (ptr) | ||
42 | *size = kmsize; | ||
43 | return ptr; | ||
44 | } | ||
29 | 45 | ||
30 | void * | 46 | void * |
31 | kmem_alloc(size_t size, unsigned int __nocast flags) | 47 | kmem_alloc(size_t size, unsigned int __nocast flags) |
@@ -34,19 +50,8 @@ kmem_alloc(size_t size, unsigned int __nocast flags) | |||
34 | gfp_t lflags = kmem_flags_convert(flags); | 50 | gfp_t lflags = kmem_flags_convert(flags); |
35 | void *ptr; | 51 | void *ptr; |
36 | 52 | ||
37 | #ifdef DEBUG | ||
38 | if (unlikely(!(flags & KM_LARGE) && (size > PAGE_SIZE))) { | ||
39 | printk(KERN_WARNING "Large %s attempt, size=%ld\n", | ||
40 | __func__, (long)size); | ||
41 | dump_stack(); | ||
42 | } | ||
43 | #endif | ||
44 | |||
45 | do { | 53 | do { |
46 | if (size < MAX_SLAB_SIZE || retries > MAX_VMALLOCS) | 54 | ptr = kmalloc(size, lflags); |
47 | ptr = kmalloc(size, lflags); | ||
48 | else | ||
49 | ptr = __vmalloc(size, lflags, PAGE_KERNEL); | ||
50 | if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP))) | 55 | if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP))) |
51 | return ptr; | 56 | return ptr; |
52 | if (!(++retries % 100)) | 57 | if (!(++retries % 100)) |
@@ -68,27 +73,6 @@ kmem_zalloc(size_t size, unsigned int __nocast flags) | |||
68 | return ptr; | 73 | return ptr; |
69 | } | 74 | } |
70 | 75 | ||
71 | void * | ||
72 | kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize, | ||
73 | unsigned int __nocast flags) | ||
74 | { | ||
75 | void *ptr; | ||
76 | size_t kmsize = maxsize; | ||
77 | unsigned int kmflags = (flags & ~KM_SLEEP) | KM_NOSLEEP; | ||
78 | |||
79 | while (!(ptr = kmem_zalloc(kmsize, kmflags))) { | ||
80 | if ((kmsize <= minsize) && (flags & KM_NOSLEEP)) | ||
81 | break; | ||
82 | if ((kmsize >>= 1) <= minsize) { | ||
83 | kmsize = minsize; | ||
84 | kmflags = flags; | ||
85 | } | ||
86 | } | ||
87 | if (ptr) | ||
88 | *size = kmsize; | ||
89 | return ptr; | ||
90 | } | ||
91 | |||
92 | void | 76 | void |
93 | kmem_free(const void *ptr) | 77 | kmem_free(const void *ptr) |
94 | { | 78 | { |
diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h index 179cbd630f69..f7c8f7a9ea6d 100644 --- a/fs/xfs/linux-2.6/kmem.h +++ b/fs/xfs/linux-2.6/kmem.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/vmalloc.h> | ||
24 | 25 | ||
25 | /* | 26 | /* |
26 | * General memory allocation interfaces | 27 | * General memory allocation interfaces |
@@ -30,7 +31,6 @@ | |||
30 | #define KM_NOSLEEP 0x0002u | 31 | #define KM_NOSLEEP 0x0002u |
31 | #define KM_NOFS 0x0004u | 32 | #define KM_NOFS 0x0004u |
32 | #define KM_MAYFAIL 0x0008u | 33 | #define KM_MAYFAIL 0x0008u |
33 | #define KM_LARGE 0x0010u | ||
34 | 34 | ||
35 | /* | 35 | /* |
36 | * We use a special process flag to avoid recursive callbacks into | 36 | * We use a special process flag to avoid recursive callbacks into |
@@ -42,7 +42,7 @@ kmem_flags_convert(unsigned int __nocast flags) | |||
42 | { | 42 | { |
43 | gfp_t lflags; | 43 | gfp_t lflags; |
44 | 44 | ||
45 | BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL|KM_LARGE)); | 45 | BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL)); |
46 | 46 | ||
47 | if (flags & KM_NOSLEEP) { | 47 | if (flags & KM_NOSLEEP) { |
48 | lflags = GFP_ATOMIC | __GFP_NOWARN; | 48 | lflags = GFP_ATOMIC | __GFP_NOWARN; |
@@ -56,10 +56,25 @@ kmem_flags_convert(unsigned int __nocast flags) | |||
56 | 56 | ||
57 | extern void *kmem_alloc(size_t, unsigned int __nocast); | 57 | extern void *kmem_alloc(size_t, unsigned int __nocast); |
58 | extern void *kmem_zalloc(size_t, unsigned int __nocast); | 58 | extern void *kmem_zalloc(size_t, unsigned int __nocast); |
59 | extern void *kmem_zalloc_greedy(size_t *, size_t, size_t, unsigned int __nocast); | ||
60 | extern void *kmem_realloc(const void *, size_t, size_t, unsigned int __nocast); | 59 | extern void *kmem_realloc(const void *, size_t, size_t, unsigned int __nocast); |
61 | extern void kmem_free(const void *); | 60 | extern void kmem_free(const void *); |
62 | 61 | ||
62 | static inline void *kmem_zalloc_large(size_t size) | ||
63 | { | ||
64 | void *ptr; | ||
65 | |||
66 | ptr = vmalloc(size); | ||
67 | if (ptr) | ||
68 | memset(ptr, 0, size); | ||
69 | return ptr; | ||
70 | } | ||
71 | static inline void kmem_free_large(void *ptr) | ||
72 | { | ||
73 | vfree(ptr); | ||
74 | } | ||
75 | |||
76 | extern void *kmem_zalloc_greedy(size_t *, size_t, size_t); | ||
77 | |||
63 | /* | 78 | /* |
64 | * Zone interfaces | 79 | * Zone interfaces |
65 | */ | 80 | */ |
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 730eff1e71a3..44e20e578ba0 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -1525,8 +1525,8 @@ xfs_alloc_bufhash( | |||
1525 | 1525 | ||
1526 | btp->bt_hashshift = external ? 3 : 8; /* 8 or 256 buckets */ | 1526 | btp->bt_hashshift = external ? 3 : 8; /* 8 or 256 buckets */ |
1527 | btp->bt_hashmask = (1 << btp->bt_hashshift) - 1; | 1527 | btp->bt_hashmask = (1 << btp->bt_hashshift) - 1; |
1528 | btp->bt_hash = kmem_zalloc((1 << btp->bt_hashshift) * | 1528 | btp->bt_hash = kmem_zalloc_large((1 << btp->bt_hashshift) * |
1529 | sizeof(xfs_bufhash_t), KM_SLEEP | KM_LARGE); | 1529 | sizeof(xfs_bufhash_t)); |
1530 | for (i = 0; i < (1 << btp->bt_hashshift); i++) { | 1530 | for (i = 0; i < (1 << btp->bt_hashshift); i++) { |
1531 | spin_lock_init(&btp->bt_hash[i].bh_lock); | 1531 | spin_lock_init(&btp->bt_hash[i].bh_lock); |
1532 | INIT_LIST_HEAD(&btp->bt_hash[i].bh_list); | 1532 | INIT_LIST_HEAD(&btp->bt_hash[i].bh_list); |
@@ -1537,7 +1537,7 @@ STATIC void | |||
1537 | xfs_free_bufhash( | 1537 | xfs_free_bufhash( |
1538 | xfs_buftarg_t *btp) | 1538 | xfs_buftarg_t *btp) |
1539 | { | 1539 | { |
1540 | kmem_free(btp->bt_hash); | 1540 | kmem_free_large(btp->bt_hash); |
1541 | btp->bt_hash = NULL; | 1541 | btp->bt_hash = NULL; |
1542 | } | 1542 | } |
1543 | 1543 | ||
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 9e627a8b5b0e..11cfd8245c7c 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
@@ -118,9 +118,14 @@ xfs_Gqm_init(void) | |||
118 | */ | 118 | */ |
119 | udqhash = kmem_zalloc_greedy(&hsize, | 119 | udqhash = kmem_zalloc_greedy(&hsize, |
120 | XFS_QM_HASHSIZE_LOW * sizeof(xfs_dqhash_t), | 120 | XFS_QM_HASHSIZE_LOW * sizeof(xfs_dqhash_t), |
121 | XFS_QM_HASHSIZE_HIGH * sizeof(xfs_dqhash_t), | 121 | XFS_QM_HASHSIZE_HIGH * sizeof(xfs_dqhash_t)); |
122 | KM_SLEEP | KM_MAYFAIL | KM_LARGE); | 122 | if (!udqhash) |
123 | gdqhash = kmem_zalloc(hsize, KM_SLEEP | KM_LARGE); | 123 | goto out; |
124 | |||
125 | gdqhash = kmem_zalloc_large(hsize); | ||
126 | if (!udqhash) | ||
127 | goto out_free_udqhash; | ||
128 | |||
124 | hsize /= sizeof(xfs_dqhash_t); | 129 | hsize /= sizeof(xfs_dqhash_t); |
125 | ndquot = hsize << 8; | 130 | ndquot = hsize << 8; |
126 | 131 | ||
@@ -170,6 +175,11 @@ xfs_Gqm_init(void) | |||
170 | mutex_init(&qcheck_lock); | 175 | mutex_init(&qcheck_lock); |
171 | #endif | 176 | #endif |
172 | return xqm; | 177 | return xqm; |
178 | |||
179 | out_free_udqhash: | ||
180 | kmem_free_large(udqhash); | ||
181 | out: | ||
182 | return NULL; | ||
173 | } | 183 | } |
174 | 184 | ||
175 | /* | 185 | /* |
@@ -189,8 +199,8 @@ xfs_qm_destroy( | |||
189 | xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i])); | 199 | xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i])); |
190 | xfs_qm_list_destroy(&(xqm->qm_grp_dqhtable[i])); | 200 | xfs_qm_list_destroy(&(xqm->qm_grp_dqhtable[i])); |
191 | } | 201 | } |
192 | kmem_free(xqm->qm_usr_dqhtable); | 202 | kmem_free_large(xqm->qm_usr_dqhtable); |
193 | kmem_free(xqm->qm_grp_dqhtable); | 203 | kmem_free_large(xqm->qm_grp_dqhtable); |
194 | xqm->qm_usr_dqhtable = NULL; | 204 | xqm->qm_usr_dqhtable = NULL; |
195 | xqm->qm_grp_dqhtable = NULL; | 205 | xqm->qm_grp_dqhtable = NULL; |
196 | xqm->qm_dqhashmask = 0; | 206 | xqm->qm_dqhashmask = 0; |
@@ -219,8 +229,12 @@ xfs_qm_hold_quotafs_ref( | |||
219 | */ | 229 | */ |
220 | mutex_lock(&xfs_Gqm_lock); | 230 | mutex_lock(&xfs_Gqm_lock); |
221 | 231 | ||
222 | if (xfs_Gqm == NULL) | 232 | if (!xfs_Gqm) { |
223 | xfs_Gqm = xfs_Gqm_init(); | 233 | xfs_Gqm = xfs_Gqm_init(); |
234 | if (!xfs_Gqm) | ||
235 | return ENOMEM; | ||
236 | } | ||
237 | |||
224 | /* | 238 | /* |
225 | * We can keep a list of all filesystems with quotas mounted for | 239 | * We can keep a list of all filesystems with quotas mounted for |
226 | * debugging and statistical purposes, but ... | 240 | * debugging and statistical purposes, but ... |
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 940307a6a60b..3af02314c605 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -408,8 +408,10 @@ xfs_bulkstat( | |||
408 | (XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog); | 408 | (XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog); |
409 | nimask = ~(nicluster - 1); | 409 | nimask = ~(nicluster - 1); |
410 | nbcluster = nicluster >> mp->m_sb.sb_inopblog; | 410 | nbcluster = nicluster >> mp->m_sb.sb_inopblog; |
411 | irbuf = kmem_zalloc_greedy(&irbsize, PAGE_SIZE, PAGE_SIZE * 4, | 411 | irbuf = kmem_zalloc_greedy(&irbsize, PAGE_SIZE, PAGE_SIZE * 4); |
412 | KM_SLEEP | KM_MAYFAIL | KM_LARGE); | 412 | if (!irbuf) |
413 | return ENOMEM; | ||
414 | |||
413 | nirbuf = irbsize / sizeof(*irbuf); | 415 | nirbuf = irbsize / sizeof(*irbuf); |
414 | 416 | ||
415 | /* | 417 | /* |
@@ -727,7 +729,7 @@ xfs_bulkstat( | |||
727 | /* | 729 | /* |
728 | * Done, we're either out of filesystem or space to put the data. | 730 | * Done, we're either out of filesystem or space to put the data. |
729 | */ | 731 | */ |
730 | kmem_free(irbuf); | 732 | kmem_free_large(irbuf); |
731 | *ubcountp = ubelem; | 733 | *ubcountp = ubelem; |
732 | /* | 734 | /* |
733 | * Found some inodes, return them now and return the error next time. | 735 | * Found some inodes, return them now and return the error next time. |