diff options
author | Pekka Enberg <penberg@kernel.org> | 2012-06-04 03:14:58 -0400 |
---|---|---|
committer | Pekka Enberg <penberg@kernel.org> | 2012-06-04 03:14:58 -0400 |
commit | 23910c50cced8f35d53e4f8ea0cc09ad58d286af (patch) | |
tree | 4e5c9ef6a09d234119a49d2623a0d042fe3af125 /mm/slub.c | |
parent | f8f5701bdaf9134b1f90e5044a82c66324d2073f (diff) | |
parent | 57d437d2aa680f42d75cef45205834d5f605550a (diff) |
Merge branch 'slub/cleanups' into slab/next
* Fix a merge conflict in mm/slub.c::acquire_slab() due to commit 02d7633
("slub: fix a memory leak in get_partial_node()").
Conflicts:
mm/slub.c
Signed-off-by: Pekka Enberg <penberg@kernel.org>
Diffstat (limited to 'mm/slub.c')
-rw-r--r-- | mm/slub.c | 173 |
1 files changed, 92 insertions, 81 deletions
@@ -1490,12 +1490,12 @@ static inline void remove_partial(struct kmem_cache_node *n, | |||
1490 | } | 1490 | } |
1491 | 1491 | ||
1492 | /* | 1492 | /* |
1493 | * Lock slab, remove from the partial list and put the object into the | 1493 | * Remove slab from the partial list, freeze it and |
1494 | * per cpu freelist. | 1494 | * return the pointer to the freelist. |
1495 | * | 1495 | * |
1496 | * Returns a list of objects or NULL if it fails. | 1496 | * Returns a list of objects or NULL if it fails. |
1497 | * | 1497 | * |
1498 | * Must hold list_lock. | 1498 | * Must hold list_lock since we modify the partial list. |
1499 | */ | 1499 | */ |
1500 | static inline void *acquire_slab(struct kmem_cache *s, | 1500 | static inline void *acquire_slab(struct kmem_cache *s, |
1501 | struct kmem_cache_node *n, struct page *page, | 1501 | struct kmem_cache_node *n, struct page *page, |
@@ -1510,26 +1510,27 @@ static inline void *acquire_slab(struct kmem_cache *s, | |||
1510 | * The old freelist is the list of objects for the | 1510 | * The old freelist is the list of objects for the |
1511 | * per cpu allocation list. | 1511 | * per cpu allocation list. |
1512 | */ | 1512 | */ |
1513 | do { | 1513 | freelist = page->freelist; |
1514 | freelist = page->freelist; | 1514 | counters = page->counters; |
1515 | counters = page->counters; | 1515 | new.counters = counters; |
1516 | new.counters = counters; | 1516 | if (mode) { |
1517 | if (mode) { | 1517 | new.inuse = page->objects; |
1518 | new.inuse = page->objects; | 1518 | new.freelist = NULL; |
1519 | new.freelist = NULL; | 1519 | } else { |
1520 | } else { | 1520 | new.freelist = freelist; |
1521 | new.freelist = freelist; | 1521 | } |
1522 | } | ||
1523 | 1522 | ||
1524 | VM_BUG_ON(new.frozen); | 1523 | VM_BUG_ON(new.frozen); |
1525 | new.frozen = 1; | 1524 | new.frozen = 1; |
1526 | 1525 | ||
1527 | } while (!__cmpxchg_double_slab(s, page, | 1526 | if (!__cmpxchg_double_slab(s, page, |
1528 | freelist, counters, | 1527 | freelist, counters, |
1529 | new.freelist, new.counters, | 1528 | new.freelist, new.counters, |
1530 | "lock and freeze")); | 1529 | "acquire_slab")) |
1530 | return NULL; | ||
1531 | 1531 | ||
1532 | remove_partial(n, page); | 1532 | remove_partial(n, page); |
1533 | WARN_ON(!freelist); | ||
1533 | return freelist; | 1534 | return freelist; |
1534 | } | 1535 | } |
1535 | 1536 | ||
@@ -1563,7 +1564,6 @@ static void *get_partial_node(struct kmem_cache *s, | |||
1563 | 1564 | ||
1564 | if (!object) { | 1565 | if (!object) { |
1565 | c->page = page; | 1566 | c->page = page; |
1566 | c->node = page_to_nid(page); | ||
1567 | stat(s, ALLOC_FROM_PARTIAL); | 1567 | stat(s, ALLOC_FROM_PARTIAL); |
1568 | object = t; | 1568 | object = t; |
1569 | available = page->objects - page->inuse; | 1569 | available = page->objects - page->inuse; |
@@ -1731,14 +1731,12 @@ void init_kmem_cache_cpus(struct kmem_cache *s) | |||
1731 | /* | 1731 | /* |
1732 | * Remove the cpu slab | 1732 | * Remove the cpu slab |
1733 | */ | 1733 | */ |
1734 | static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) | 1734 | static void deactivate_slab(struct kmem_cache *s, struct page *page, void *freelist) |
1735 | { | 1735 | { |
1736 | enum slab_modes { M_NONE, M_PARTIAL, M_FULL, M_FREE }; | 1736 | enum slab_modes { M_NONE, M_PARTIAL, M_FULL, M_FREE }; |
1737 | struct page *page = c->page; | ||
1738 | struct kmem_cache_node *n = get_node(s, page_to_nid(page)); | 1737 | struct kmem_cache_node *n = get_node(s, page_to_nid(page)); |
1739 | int lock = 0; | 1738 | int lock = 0; |
1740 | enum slab_modes l = M_NONE, m = M_NONE; | 1739 | enum slab_modes l = M_NONE, m = M_NONE; |
1741 | void *freelist; | ||
1742 | void *nextfree; | 1740 | void *nextfree; |
1743 | int tail = DEACTIVATE_TO_HEAD; | 1741 | int tail = DEACTIVATE_TO_HEAD; |
1744 | struct page new; | 1742 | struct page new; |
@@ -1749,11 +1747,6 @@ static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) | |||
1749 | tail = DEACTIVATE_TO_TAIL; | 1747 | tail = DEACTIVATE_TO_TAIL; |
1750 | } | 1748 | } |
1751 | 1749 | ||
1752 | c->tid = next_tid(c->tid); | ||
1753 | c->page = NULL; | ||
1754 | freelist = c->freelist; | ||
1755 | c->freelist = NULL; | ||
1756 | |||
1757 | /* | 1750 | /* |
1758 | * Stage one: Free all available per cpu objects back | 1751 | * Stage one: Free all available per cpu objects back |
1759 | * to the page freelist while it is still frozen. Leave the | 1752 | * to the page freelist while it is still frozen. Leave the |
@@ -2011,7 +2004,11 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) | |||
2011 | static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) | 2004 | static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) |
2012 | { | 2005 | { |
2013 | stat(s, CPUSLAB_FLUSH); | 2006 | stat(s, CPUSLAB_FLUSH); |
2014 | deactivate_slab(s, c); | 2007 | deactivate_slab(s, c->page, c->freelist); |
2008 | |||
2009 | c->tid = next_tid(c->tid); | ||
2010 | c->page = NULL; | ||
2011 | c->freelist = NULL; | ||
2015 | } | 2012 | } |
2016 | 2013 | ||
2017 | /* | 2014 | /* |
@@ -2055,10 +2052,10 @@ static void flush_all(struct kmem_cache *s) | |||
2055 | * Check if the objects in a per cpu structure fit numa | 2052 | * Check if the objects in a per cpu structure fit numa |
2056 | * locality expectations. | 2053 | * locality expectations. |
2057 | */ | 2054 | */ |
2058 | static inline int node_match(struct kmem_cache_cpu *c, int node) | 2055 | static inline int node_match(struct page *page, int node) |
2059 | { | 2056 | { |
2060 | #ifdef CONFIG_NUMA | 2057 | #ifdef CONFIG_NUMA |
2061 | if (node != NUMA_NO_NODE && c->node != node) | 2058 | if (node != NUMA_NO_NODE && page_to_nid(page) != node) |
2062 | return 0; | 2059 | return 0; |
2063 | #endif | 2060 | #endif |
2064 | return 1; | 2061 | return 1; |
@@ -2130,10 +2127,16 @@ slab_out_of_memory(struct kmem_cache *s, gfp_t gfpflags, int nid) | |||
2130 | static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, | 2127 | static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, |
2131 | int node, struct kmem_cache_cpu **pc) | 2128 | int node, struct kmem_cache_cpu **pc) |
2132 | { | 2129 | { |
2133 | void *object; | 2130 | void *freelist; |
2134 | struct kmem_cache_cpu *c; | 2131 | struct kmem_cache_cpu *c = *pc; |
2135 | struct page *page = new_slab(s, flags, node); | 2132 | struct page *page; |
2133 | |||
2134 | freelist = get_partial(s, flags, node, c); | ||
2136 | 2135 | ||
2136 | if (freelist) | ||
2137 | return freelist; | ||
2138 | |||
2139 | page = new_slab(s, flags, node); | ||
2137 | if (page) { | 2140 | if (page) { |
2138 | c = __this_cpu_ptr(s->cpu_slab); | 2141 | c = __this_cpu_ptr(s->cpu_slab); |
2139 | if (c->page) | 2142 | if (c->page) |
@@ -2143,17 +2146,16 @@ static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, | |||
2143 | * No other reference to the page yet so we can | 2146 | * No other reference to the page yet so we can |
2144 | * muck around with it freely without cmpxchg | 2147 | * muck around with it freely without cmpxchg |
2145 | */ | 2148 | */ |
2146 | object = page->freelist; | 2149 | freelist = page->freelist; |
2147 | page->freelist = NULL; | 2150 | page->freelist = NULL; |
2148 | 2151 | ||
2149 | stat(s, ALLOC_SLAB); | 2152 | stat(s, ALLOC_SLAB); |
2150 | c->node = page_to_nid(page); | ||
2151 | c->page = page; | 2153 | c->page = page; |
2152 | *pc = c; | 2154 | *pc = c; |
2153 | } else | 2155 | } else |
2154 | object = NULL; | 2156 | freelist = NULL; |
2155 | 2157 | ||
2156 | return object; | 2158 | return freelist; |
2157 | } | 2159 | } |
2158 | 2160 | ||
2159 | /* | 2161 | /* |
@@ -2173,6 +2175,7 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page) | |||
2173 | do { | 2175 | do { |
2174 | freelist = page->freelist; | 2176 | freelist = page->freelist; |
2175 | counters = page->counters; | 2177 | counters = page->counters; |
2178 | |||
2176 | new.counters = counters; | 2179 | new.counters = counters; |
2177 | VM_BUG_ON(!new.frozen); | 2180 | VM_BUG_ON(!new.frozen); |
2178 | 2181 | ||
@@ -2206,7 +2209,8 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page) | |||
2206 | static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, | 2209 | static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, |
2207 | unsigned long addr, struct kmem_cache_cpu *c) | 2210 | unsigned long addr, struct kmem_cache_cpu *c) |
2208 | { | 2211 | { |
2209 | void **object; | 2212 | void *freelist; |
2213 | struct page *page; | ||
2210 | unsigned long flags; | 2214 | unsigned long flags; |
2211 | 2215 | ||
2212 | local_irq_save(flags); | 2216 | local_irq_save(flags); |
@@ -2219,25 +2223,29 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, | |||
2219 | c = this_cpu_ptr(s->cpu_slab); | 2223 | c = this_cpu_ptr(s->cpu_slab); |
2220 | #endif | 2224 | #endif |
2221 | 2225 | ||
2222 | if (!c->page) | 2226 | page = c->page; |
2227 | if (!page) | ||
2223 | goto new_slab; | 2228 | goto new_slab; |
2224 | redo: | 2229 | redo: |
2225 | if (unlikely(!node_match(c, node))) { | 2230 | |
2231 | if (unlikely(!node_match(page, node))) { | ||
2226 | stat(s, ALLOC_NODE_MISMATCH); | 2232 | stat(s, ALLOC_NODE_MISMATCH); |
2227 | deactivate_slab(s, c); | 2233 | deactivate_slab(s, page, c->freelist); |
2234 | c->page = NULL; | ||
2235 | c->freelist = NULL; | ||
2228 | goto new_slab; | 2236 | goto new_slab; |
2229 | } | 2237 | } |
2230 | 2238 | ||
2231 | /* must check again c->freelist in case of cpu migration or IRQ */ | 2239 | /* must check again c->freelist in case of cpu migration or IRQ */ |
2232 | object = c->freelist; | 2240 | freelist = c->freelist; |
2233 | if (object) | 2241 | if (freelist) |
2234 | goto load_freelist; | 2242 | goto load_freelist; |
2235 | 2243 | ||
2236 | stat(s, ALLOC_SLOWPATH); | 2244 | stat(s, ALLOC_SLOWPATH); |
2237 | 2245 | ||
2238 | object = get_freelist(s, c->page); | 2246 | freelist = get_freelist(s, page); |
2239 | 2247 | ||
2240 | if (!object) { | 2248 | if (!freelist) { |
2241 | c->page = NULL; | 2249 | c->page = NULL; |
2242 | stat(s, DEACTIVATE_BYPASS); | 2250 | stat(s, DEACTIVATE_BYPASS); |
2243 | goto new_slab; | 2251 | goto new_slab; |
@@ -2246,50 +2254,50 @@ redo: | |||
2246 | stat(s, ALLOC_REFILL); | 2254 | stat(s, ALLOC_REFILL); |
2247 | 2255 | ||
2248 | load_freelist: | 2256 | load_freelist: |
2249 | c->freelist = get_freepointer(s, object); | 2257 | /* |
2258 | * freelist is pointing to the list of objects to be used. | ||
2259 | * page is pointing to the page from which the objects are obtained. | ||
2260 | * That page must be frozen for per cpu allocations to work. | ||
2261 | */ | ||
2262 | VM_BUG_ON(!c->page->frozen); | ||
2263 | c->freelist = get_freepointer(s, freelist); | ||
2250 | c->tid = next_tid(c->tid); | 2264 | c->tid = next_tid(c->tid); |
2251 | local_irq_restore(flags); | 2265 | local_irq_restore(flags); |
2252 | return object; | 2266 | return freelist; |
2253 | 2267 | ||
2254 | new_slab: | 2268 | new_slab: |
2255 | 2269 | ||
2256 | if (c->partial) { | 2270 | if (c->partial) { |
2257 | c->page = c->partial; | 2271 | page = c->page = c->partial; |
2258 | c->partial = c->page->next; | 2272 | c->partial = page->next; |
2259 | c->node = page_to_nid(c->page); | ||
2260 | stat(s, CPU_PARTIAL_ALLOC); | 2273 | stat(s, CPU_PARTIAL_ALLOC); |
2261 | c->freelist = NULL; | 2274 | c->freelist = NULL; |
2262 | goto redo; | 2275 | goto redo; |
2263 | } | 2276 | } |
2264 | 2277 | ||
2265 | /* Then do expensive stuff like retrieving pages from the partial lists */ | 2278 | freelist = new_slab_objects(s, gfpflags, node, &c); |
2266 | object = get_partial(s, gfpflags, node, c); | ||
2267 | |||
2268 | if (unlikely(!object)) { | ||
2269 | 2279 | ||
2270 | object = new_slab_objects(s, gfpflags, node, &c); | 2280 | if (unlikely(!freelist)) { |
2281 | if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit()) | ||
2282 | slab_out_of_memory(s, gfpflags, node); | ||
2271 | 2283 | ||
2272 | if (unlikely(!object)) { | 2284 | local_irq_restore(flags); |
2273 | if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit()) | 2285 | return NULL; |
2274 | slab_out_of_memory(s, gfpflags, node); | ||
2275 | |||
2276 | local_irq_restore(flags); | ||
2277 | return NULL; | ||
2278 | } | ||
2279 | } | 2286 | } |
2280 | 2287 | ||
2288 | page = c->page; | ||
2281 | if (likely(!kmem_cache_debug(s))) | 2289 | if (likely(!kmem_cache_debug(s))) |
2282 | goto load_freelist; | 2290 | goto load_freelist; |
2283 | 2291 | ||
2284 | /* Only entered in the debug case */ | 2292 | /* Only entered in the debug case */ |
2285 | if (!alloc_debug_processing(s, c->page, object, addr)) | 2293 | if (!alloc_debug_processing(s, page, freelist, addr)) |
2286 | goto new_slab; /* Slab failed checks. Next slab needed */ | 2294 | goto new_slab; /* Slab failed checks. Next slab needed */ |
2287 | 2295 | ||
2288 | c->freelist = get_freepointer(s, object); | 2296 | deactivate_slab(s, page, get_freepointer(s, freelist)); |
2289 | deactivate_slab(s, c); | 2297 | c->page = NULL; |
2290 | c->node = NUMA_NO_NODE; | 2298 | c->freelist = NULL; |
2291 | local_irq_restore(flags); | 2299 | local_irq_restore(flags); |
2292 | return object; | 2300 | return freelist; |
2293 | } | 2301 | } |
2294 | 2302 | ||
2295 | /* | 2303 | /* |
@@ -2307,6 +2315,7 @@ static __always_inline void *slab_alloc(struct kmem_cache *s, | |||
2307 | { | 2315 | { |
2308 | void **object; | 2316 | void **object; |
2309 | struct kmem_cache_cpu *c; | 2317 | struct kmem_cache_cpu *c; |
2318 | struct page *page; | ||
2310 | unsigned long tid; | 2319 | unsigned long tid; |
2311 | 2320 | ||
2312 | if (slab_pre_alloc_hook(s, gfpflags)) | 2321 | if (slab_pre_alloc_hook(s, gfpflags)) |
@@ -2332,7 +2341,8 @@ redo: | |||
2332 | barrier(); | 2341 | barrier(); |
2333 | 2342 | ||
2334 | object = c->freelist; | 2343 | object = c->freelist; |
2335 | if (unlikely(!object || !node_match(c, node))) | 2344 | page = c->page; |
2345 | if (unlikely(!object || !node_match(page, node))) | ||
2336 | 2346 | ||
2337 | object = __slab_alloc(s, gfpflags, node, addr, c); | 2347 | object = __slab_alloc(s, gfpflags, node, addr, c); |
2338 | 2348 | ||
@@ -4500,30 +4510,31 @@ static ssize_t show_slab_objects(struct kmem_cache *s, | |||
4500 | 4510 | ||
4501 | for_each_possible_cpu(cpu) { | 4511 | for_each_possible_cpu(cpu) { |
4502 | struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu); | 4512 | struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu); |
4503 | int node = ACCESS_ONCE(c->node); | 4513 | int node; |
4504 | struct page *page; | 4514 | struct page *page; |
4505 | 4515 | ||
4506 | if (node < 0) | ||
4507 | continue; | ||
4508 | page = ACCESS_ONCE(c->page); | 4516 | page = ACCESS_ONCE(c->page); |
4509 | if (page) { | 4517 | if (!page) |
4510 | if (flags & SO_TOTAL) | 4518 | continue; |
4511 | x = page->objects; | ||
4512 | else if (flags & SO_OBJECTS) | ||
4513 | x = page->inuse; | ||
4514 | else | ||
4515 | x = 1; | ||
4516 | 4519 | ||
4517 | total += x; | 4520 | node = page_to_nid(page); |
4518 | nodes[node] += x; | 4521 | if (flags & SO_TOTAL) |
4519 | } | 4522 | x = page->objects; |
4520 | page = c->partial; | 4523 | else if (flags & SO_OBJECTS) |
4524 | x = page->inuse; | ||
4525 | else | ||
4526 | x = 1; | ||
4521 | 4527 | ||
4528 | total += x; | ||
4529 | nodes[node] += x; | ||
4530 | |||
4531 | page = ACCESS_ONCE(c->partial); | ||
4522 | if (page) { | 4532 | if (page) { |
4523 | x = page->pobjects; | 4533 | x = page->pobjects; |
4524 | total += x; | 4534 | total += x; |
4525 | nodes[node] += x; | 4535 | nodes[node] += x; |
4526 | } | 4536 | } |
4537 | |||
4527 | per_cpu[node]++; | 4538 | per_cpu[node]++; |
4528 | } | 4539 | } |
4529 | } | 4540 | } |