diff options
Diffstat (limited to 'mm/slub.c')
-rw-r--r-- | mm/slub.c | 39 |
1 files changed, 28 insertions, 11 deletions
@@ -1113,28 +1113,43 @@ static inline void dec_slabs_node(struct kmem_cache *s, int node, | |||
1113 | /* | 1113 | /* |
1114 | * Slab allocation and freeing | 1114 | * Slab allocation and freeing |
1115 | */ | 1115 | */ |
1116 | static inline struct page *alloc_slab_page(gfp_t flags, int node, | ||
1117 | struct kmem_cache_order_objects oo) | ||
1118 | { | ||
1119 | int order = oo_order(oo); | ||
1120 | |||
1121 | if (node == -1) | ||
1122 | return alloc_pages(flags, order); | ||
1123 | else | ||
1124 | return alloc_pages_node(node, flags, order); | ||
1125 | } | ||
1126 | |||
1116 | static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) | 1127 | static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) |
1117 | { | 1128 | { |
1118 | struct page *page; | 1129 | struct page *page; |
1119 | struct kmem_cache_order_objects oo = s->oo; | 1130 | struct kmem_cache_order_objects oo = s->oo; |
1120 | int order = oo_order(oo); | ||
1121 | int pages = 1 << order; | ||
1122 | 1131 | ||
1123 | flags |= s->allocflags; | 1132 | flags |= s->allocflags; |
1124 | 1133 | ||
1125 | if (node == -1) | 1134 | page = alloc_slab_page(flags | __GFP_NOWARN | __GFP_NORETRY, node, |
1126 | page = alloc_pages(flags, order); | 1135 | oo); |
1127 | else | 1136 | if (unlikely(!page)) { |
1128 | page = alloc_pages_node(node, flags, order); | 1137 | oo = s->min; |
1129 | 1138 | /* | |
1130 | if (!page) | 1139 | * Allocation may have failed due to fragmentation. |
1131 | return NULL; | 1140 | * Try a lower order alloc if possible |
1141 | */ | ||
1142 | page = alloc_slab_page(flags, node, oo); | ||
1143 | if (!page) | ||
1144 | return NULL; | ||
1132 | 1145 | ||
1146 | stat(get_cpu_slab(s, raw_smp_processor_id()), ORDER_FALLBACK); | ||
1147 | } | ||
1133 | page->objects = oo_objects(oo); | 1148 | page->objects = oo_objects(oo); |
1134 | mod_zone_page_state(page_zone(page), | 1149 | mod_zone_page_state(page_zone(page), |
1135 | (s->flags & SLAB_RECLAIM_ACCOUNT) ? | 1150 | (s->flags & SLAB_RECLAIM_ACCOUNT) ? |
1136 | NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE, | 1151 | NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE, |
1137 | pages); | 1152 | 1 << oo_order(oo)); |
1138 | 1153 | ||
1139 | return page; | 1154 | return page; |
1140 | } | 1155 | } |
@@ -2347,6 +2362,7 @@ static int calculate_sizes(struct kmem_cache *s) | |||
2347 | * Determine the number of objects per slab | 2362 | * Determine the number of objects per slab |
2348 | */ | 2363 | */ |
2349 | s->oo = oo_make(order, size); | 2364 | s->oo = oo_make(order, size); |
2365 | s->min = oo_make(get_order(size), size); | ||
2350 | if (oo_objects(s->oo) > oo_objects(s->max)) | 2366 | if (oo_objects(s->oo) > oo_objects(s->max)) |
2351 | s->max = s->oo; | 2367 | s->max = s->oo; |
2352 | 2368 | ||
@@ -4163,7 +4179,7 @@ STAT_ATTR(DEACTIVATE_EMPTY, deactivate_empty); | |||
4163 | STAT_ATTR(DEACTIVATE_TO_HEAD, deactivate_to_head); | 4179 | STAT_ATTR(DEACTIVATE_TO_HEAD, deactivate_to_head); |
4164 | STAT_ATTR(DEACTIVATE_TO_TAIL, deactivate_to_tail); | 4180 | STAT_ATTR(DEACTIVATE_TO_TAIL, deactivate_to_tail); |
4165 | STAT_ATTR(DEACTIVATE_REMOTE_FREES, deactivate_remote_frees); | 4181 | STAT_ATTR(DEACTIVATE_REMOTE_FREES, deactivate_remote_frees); |
4166 | 4182 | STAT_ATTR(ORDER_FALLBACK, order_fallback); | |
4167 | #endif | 4183 | #endif |
4168 | 4184 | ||
4169 | static struct attribute *slab_attrs[] = { | 4185 | static struct attribute *slab_attrs[] = { |
@@ -4216,6 +4232,7 @@ static struct attribute *slab_attrs[] = { | |||
4216 | &deactivate_to_head_attr.attr, | 4232 | &deactivate_to_head_attr.attr, |
4217 | &deactivate_to_tail_attr.attr, | 4233 | &deactivate_to_tail_attr.attr, |
4218 | &deactivate_remote_frees_attr.attr, | 4234 | &deactivate_remote_frees_attr.attr, |
4235 | &order_fallback_attr.attr, | ||
4219 | #endif | 4236 | #endif |
4220 | NULL | 4237 | NULL |
4221 | }; | 4238 | }; |