diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-29 14:13:22 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-29 14:13:22 -0500 |
commit | 57db53b07429c0d648f48727dd6c7c2b64c5708d (patch) | |
tree | b6dcc299de4e3ab26d9acf5ec4b572789eb38cda /mm | |
parent | 883381d9f1c5a6329bbb796e23ae52c939940310 (diff) | |
parent | bc6697d8a506dedf09e8e9974ffa3a316183e608 (diff) |
Merge branch 'slab/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/penberg/linux
* 'slab/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/penberg/linux:
slub: avoid potential NULL dereference or corruption
slub: use irqsafe_cpu_cmpxchg for put_cpu_partial
slub: move discard_slab out of node lock
slub: use correct parameter to add a page to partial list tail
Diffstat (limited to 'mm')
-rw-r--r-- | mm/slub.c | 42 |
1 files changed, 26 insertions, 16 deletions
@@ -1862,7 +1862,7 @@ static void unfreeze_partials(struct kmem_cache *s) | |||
1862 | { | 1862 | { |
1863 | struct kmem_cache_node *n = NULL; | 1863 | struct kmem_cache_node *n = NULL; |
1864 | struct kmem_cache_cpu *c = this_cpu_ptr(s->cpu_slab); | 1864 | struct kmem_cache_cpu *c = this_cpu_ptr(s->cpu_slab); |
1865 | struct page *page; | 1865 | struct page *page, *discard_page = NULL; |
1866 | 1866 | ||
1867 | while ((page = c->partial)) { | 1867 | while ((page = c->partial)) { |
1868 | enum slab_modes { M_PARTIAL, M_FREE }; | 1868 | enum slab_modes { M_PARTIAL, M_FREE }; |
@@ -1904,7 +1904,8 @@ static void unfreeze_partials(struct kmem_cache *s) | |||
1904 | if (l == M_PARTIAL) | 1904 | if (l == M_PARTIAL) |
1905 | remove_partial(n, page); | 1905 | remove_partial(n, page); |
1906 | else | 1906 | else |
1907 | add_partial(n, page, 1); | 1907 | add_partial(n, page, |
1908 | DEACTIVATE_TO_TAIL); | ||
1908 | 1909 | ||
1909 | l = m; | 1910 | l = m; |
1910 | } | 1911 | } |
@@ -1915,14 +1916,22 @@ static void unfreeze_partials(struct kmem_cache *s) | |||
1915 | "unfreezing slab")); | 1916 | "unfreezing slab")); |
1916 | 1917 | ||
1917 | if (m == M_FREE) { | 1918 | if (m == M_FREE) { |
1918 | stat(s, DEACTIVATE_EMPTY); | 1919 | page->next = discard_page; |
1919 | discard_slab(s, page); | 1920 | discard_page = page; |
1920 | stat(s, FREE_SLAB); | ||
1921 | } | 1921 | } |
1922 | } | 1922 | } |
1923 | 1923 | ||
1924 | if (n) | 1924 | if (n) |
1925 | spin_unlock(&n->list_lock); | 1925 | spin_unlock(&n->list_lock); |
1926 | |||
1927 | while (discard_page) { | ||
1928 | page = discard_page; | ||
1929 | discard_page = discard_page->next; | ||
1930 | |||
1931 | stat(s, DEACTIVATE_EMPTY); | ||
1932 | discard_slab(s, page); | ||
1933 | stat(s, FREE_SLAB); | ||
1934 | } | ||
1926 | } | 1935 | } |
1927 | 1936 | ||
1928 | /* | 1937 | /* |
@@ -1969,7 +1978,7 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) | |||
1969 | page->pobjects = pobjects; | 1978 | page->pobjects = pobjects; |
1970 | page->next = oldpage; | 1979 | page->next = oldpage; |
1971 | 1980 | ||
1972 | } while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage); | 1981 | } while (irqsafe_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage); |
1973 | stat(s, CPU_PARTIAL_FREE); | 1982 | stat(s, CPU_PARTIAL_FREE); |
1974 | return pobjects; | 1983 | return pobjects; |
1975 | } | 1984 | } |
@@ -4435,30 +4444,31 @@ static ssize_t show_slab_objects(struct kmem_cache *s, | |||
4435 | 4444 | ||
4436 | for_each_possible_cpu(cpu) { | 4445 | for_each_possible_cpu(cpu) { |
4437 | struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu); | 4446 | struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu); |
4447 | int node = ACCESS_ONCE(c->node); | ||
4438 | struct page *page; | 4448 | struct page *page; |
4439 | 4449 | ||
4440 | if (!c || c->node < 0) | 4450 | if (node < 0) |
4441 | continue; | 4451 | continue; |
4442 | 4452 | page = ACCESS_ONCE(c->page); | |
4443 | if (c->page) { | 4453 | if (page) { |
4444 | if (flags & SO_TOTAL) | 4454 | if (flags & SO_TOTAL) |
4445 | x = c->page->objects; | 4455 | x = page->objects; |
4446 | else if (flags & SO_OBJECTS) | 4456 | else if (flags & SO_OBJECTS) |
4447 | x = c->page->inuse; | 4457 | x = page->inuse; |
4448 | else | 4458 | else |
4449 | x = 1; | 4459 | x = 1; |
4450 | 4460 | ||
4451 | total += x; | 4461 | total += x; |
4452 | nodes[c->node] += x; | 4462 | nodes[node] += x; |
4453 | } | 4463 | } |
4454 | page = c->partial; | 4464 | page = c->partial; |
4455 | 4465 | ||
4456 | if (page) { | 4466 | if (page) { |
4457 | x = page->pobjects; | 4467 | x = page->pobjects; |
4458 | total += x; | 4468 | total += x; |
4459 | nodes[c->node] += x; | 4469 | nodes[node] += x; |
4460 | } | 4470 | } |
4461 | per_cpu[c->node]++; | 4471 | per_cpu[node]++; |
4462 | } | 4472 | } |
4463 | } | 4473 | } |
4464 | 4474 | ||