bugfix: our "prev_slab" field of ngx_slab_page_t could get out of sync in the slab_defrag patch for nginx. thanks Shuxin Yang for the catch.

This commit is contained in:
Yichun Zhang (agentzh) 2014-05-09 15:15:44 -07:00
parent 20e69718ce
commit 52e622a26c
1 changed files with 37 additions and 16 deletions

View File

@ -1,7 +1,16 @@
diff -r 48c97d83ab7f src/core/ngx_slab.c diff --git a/src/core/ngx_slab.c b/src/core/ngx_slab.c
--- a/src/core/ngx_slab.c Tue Apr 29 22:22:38 2014 +0200 index c3a27f7..1bde432 100644
+++ b/src/core/ngx_slab.c Wed May 07 13:01:57 2014 -0700 --- a/src/core/ngx_slab.c
@@ -111,6 +111,7 @@ +++ b/src/core/ngx_slab.c
@@ -6,6 +6,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
+#include <assert.h>
#define NGX_SLAB_PAGE_MASK 3
@@ -111,6 +112,7 @@ ngx_slab_init(ngx_slab_pool_t *pool)
ngx_memzero(p, pages * sizeof(ngx_slab_page_t)); ngx_memzero(p, pages * sizeof(ngx_slab_page_t));
pool->pages = (ngx_slab_page_t *) p; pool->pages = (ngx_slab_page_t *) p;
@ -9,7 +18,7 @@ diff -r 48c97d83ab7f src/core/ngx_slab.c
pool->free.prev = 0; pool->free.prev = 0;
pool->free.next = (ngx_slab_page_t *) p; pool->free.next = (ngx_slab_page_t *) p;
@@ -118,6 +119,7 @@ @@ -118,6 +120,7 @@ ngx_slab_init(ngx_slab_pool_t *pool)
pool->pages->slab = pages; pool->pages->slab = pages;
pool->pages->next = &pool->free; pool->pages->next = &pool->free;
pool->pages->prev = (uintptr_t) &pool->free; pool->pages->prev = (uintptr_t) &pool->free;
@ -17,7 +26,16 @@ diff -r 48c97d83ab7f src/core/ngx_slab.c
pool->start = (u_char *) pool->start = (u_char *)
ngx_align_ptr((uintptr_t) p + pages * sizeof(ngx_slab_page_t), ngx_align_ptr((uintptr_t) p + pages * sizeof(ngx_slab_page_t),
@@ -629,6 +631,7 @@ @@ -625,9 +628,16 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *pool, ngx_uint_t pages)
if (page->slab >= pages) {
if (page->slab > pages) {
+ /* adjust the next adjacent block's "prev_slab" field */
+ p = &page[page->slab];
+ if (p < pool->pages + pool->npages) {
+ p->prev_slab = page->slab - pages;
+ }
+
page[pages].slab = page->slab - pages; page[pages].slab = page->slab - pages;
page[pages].next = page->next; page[pages].next = page->next;
page[pages].prev = page->prev; page[pages].prev = page->prev;
@ -25,7 +43,7 @@ diff -r 48c97d83ab7f src/core/ngx_slab.c
p = (ngx_slab_page_t *) page->prev; p = (ngx_slab_page_t *) page->prev;
p->next = &page[pages]; p->next = &page[pages];
@@ -652,6 +655,7 @@ @@ -651,6 +661,7 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *pool, ngx_uint_t pages)
p->slab = NGX_SLAB_PAGE_BUSY; p->slab = NGX_SLAB_PAGE_BUSY;
p->next = NULL; p->next = NULL;
p->prev = NGX_SLAB_PAGE; p->prev = NGX_SLAB_PAGE;
@ -33,7 +51,7 @@ diff -r 48c97d83ab7f src/core/ngx_slab.c
p++; p++;
} }
@@ -672,7 +676,7 @@ @@ -668,7 +679,7 @@ static void
ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page, ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page,
ngx_uint_t pages) ngx_uint_t pages)
{ {
@ -42,7 +60,7 @@ diff -r 48c97d83ab7f src/core/ngx_slab.c
page->slab = pages--; page->slab = pages--;
@@ -686,6 +690,51 @@ @@ -682,6 +693,53 @@ ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page,
page->next->prev = page->prev; page->next->prev = page->prev;
} }
@ -62,12 +80,12 @@ diff -r 48c97d83ab7f src/core/ngx_slab.c
+ prev->next = p->next; + prev->next = p->next;
+ p->next->prev = p->prev; + p->next->prev = p->prev;
+ +
+ ngx_memzero(p, sizeof(ngx_slab_page_t));
+
+ /* adjust the "prev_slab" field in the next next adjacent block */ + /* adjust the "prev_slab" field in the next next adjacent block */
+ if (p + p->slab < pool->pages + pool->npages) { + if (p + p->slab < pool->pages + pool->npages) {
+ p[p->slab].prev_slab = page->slab; + p[p->slab].prev_slab = page->slab;
+ } + }
+
+ ngx_memzero(p, sizeof(ngx_slab_page_t));
+ } + }
+ +
+ if (page->prev_slab) { + if (page->prev_slab) {
@ -78,6 +96,8 @@ diff -r 48c97d83ab7f src/core/ngx_slab.c
+ && p->next != NULL + && p->next != NULL
+ && (p->prev & NGX_SLAB_PAGE_MASK) == NGX_SLAB_PAGE) + && (p->prev & NGX_SLAB_PAGE_MASK) == NGX_SLAB_PAGE)
+ { + {
+ assert(p->slab == page->prev_slab);
+
+ p->slab += page->slab; + p->slab += page->slab;
+ ngx_memzero(page, sizeof(ngx_slab_page_t)); + ngx_memzero(page, sizeof(ngx_slab_page_t));
+ +
@ -94,10 +114,11 @@ diff -r 48c97d83ab7f src/core/ngx_slab.c
page->prev = (uintptr_t) &pool->free; page->prev = (uintptr_t) &pool->free;
page->next = pool->free.next; page->next = pool->free.next;
diff -r 48c97d83ab7f src/core/ngx_slab.h diff --git a/src/core/ngx_slab.h b/src/core/ngx_slab.h
--- a/src/core/ngx_slab.h Tue Apr 29 22:22:38 2014 +0200 index c5e420b..287ac79 100644
+++ b/src/core/ngx_slab.h Wed May 07 13:01:57 2014 -0700 --- a/src/core/ngx_slab.h
@@ -19,6 +19,8 @@ +++ b/src/core/ngx_slab.h
@@ -19,6 +19,8 @@ struct ngx_slab_page_s {
uintptr_t slab; uintptr_t slab;
ngx_slab_page_t *next; ngx_slab_page_t *next;
uintptr_t prev; uintptr_t prev;
@ -106,7 +127,7 @@ diff -r 48c97d83ab7f src/core/ngx_slab.h
}; };
@@ -31,6 +33,8 @@ @@ -31,6 +33,8 @@ typedef struct {
ngx_slab_page_t *pages; ngx_slab_page_t *pages;
ngx_slab_page_t free; ngx_slab_page_t free;