*) back out r2040
*) refactor ngx_palloc()
*) introduce ngx_pnalloc()
*) additional pool blocks have smaller header
diff --git a/src/core/nginx.c b/src/core/nginx.c
index 48e085b..450edf3 100644
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -826,7 +826,7 @@
 
     ccf->oldpid.len = ccf->pid.len + sizeof(NGX_OLDPID_EXT);
 
-    ccf->oldpid.data = ngx_palloc(cycle->pool, ccf->oldpid.len);
+    ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len);
     if (ccf->oldpid.data == NULL) {
         return NGX_CONF_ERROR;
     }
@@ -870,7 +870,7 @@
 
     } else {
         cycle->lock_file.len = ccf->lock_file.len + 1;
-        cycle->lock_file.data = ngx_palloc(cycle->pool,
+        cycle->lock_file.data = ngx_pnalloc(cycle->pool,
                                       ccf->lock_file.len + sizeof(".accept"));
         if (cycle->lock_file.data == NULL) {
             return NGX_CONF_ERROR;
diff --git a/src/core/ngx_array.c b/src/core/ngx_array.c
index 1b9f7cb..a536d87 100644
--- a/src/core/ngx_array.c
+++ b/src/core/ngx_array.c
@@ -39,12 +39,12 @@
 
     p = a->pool;
 
-    if ((u_char *) a->elts + a->size * a->nalloc == p->last) {
-        p->last -= a->size * a->nalloc;
+    if ((u_char *) a->elts + a->size * a->nalloc == p->d.last) {
+        p->d.last -= a->size * a->nalloc;
     }
 
-    if ((u_char *) a + sizeof(ngx_array_t) == p->last) {
-        p->last = (u_char *) a;
+    if ((u_char *) a + sizeof(ngx_array_t) == p->d.last) {
+        p->d.last = (u_char *) a;
     }
 }
 
@@ -64,14 +64,15 @@
 
         p = a->pool;
 
-        if ((u_char *) a->elts + size == p->last && p->last + a->size <= p->end)
+        if ((u_char *) a->elts + size == p->d.last
+            && p->d.last + a->size <= p->d.end)
         {
             /*
              * the array allocation is the last in the pool
              * and there is space for new allocation
              */
 
-            p->last += a->size;
+            p->d.last += a->size;
             a->nalloc++;
 
         } else {
@@ -111,15 +112,15 @@
 
         p = a->pool;
 
-        if ((u_char *) a->elts + a->size * a->nalloc == p->last
-            && p->last + size <= p->end)
+        if ((u_char *) a->elts + a->size * a->nalloc == p->d.last
+            && p->d.last + size <= p->d.end)
         {
             /*
              * the array allocation is the last in the pool
              * and there is space for new allocation
              */
 
-            p->last += size;
+            p->d.last += size;
             a->nalloc += n;
 
         } else {
diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c
index 6efcd8b..b32f0f0 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -574,7 +574,7 @@
                     return NGX_ERROR;
                 }
 
-                word->data = ngx_palloc(cf->pool, b->pos - start + 1);
+                word->data = ngx_pnalloc(cf->pool, b->pos - start + 1);
                 if (word->data == NULL) {
                     return NGX_ERROR;
                 }
@@ -726,7 +726,7 @@
     }
 
     name->len = len + old.len;
-    name->data = ngx_palloc(cycle->pool, name->len + 1);
+    name->data = ngx_pnalloc(cycle->pool, name->len + 1);
     if (name->data == NULL) {
         return  NGX_ERROR;
     }
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index b49a696..03662b3 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -36,7 +36,7 @@
     sin->sin_port = htons(port);
 
 
-    ls->addr_text.data = ngx_palloc(cf->pool,
+    ls->addr_text.data = ngx_pnalloc(cf->pool,
                                     INET_ADDRSTRLEN - 1 + sizeof(":65535") - 1);
     if (ls->addr_text.data == NULL) {
         return NULL;
@@ -106,8 +106,8 @@
 
         ls[i].addr_text_max_len = INET_ADDRSTRLEN;
 
-        ls[i].addr_text.data = ngx_palloc(cycle->pool, INET_ADDRSTRLEN - 1
-                                                       + sizeof(":65535") - 1);
+        ls[i].addr_text.data = ngx_pnalloc(cycle->pool,
+                                   INET_ADDRSTRLEN - 1 + sizeof(":65535") - 1);
         if (ls[i].addr_text.data == NULL) {
             return NGX_ERROR;
         }
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index 9cdbb2d..a82e850 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -81,7 +81,7 @@
 
 
     cycle->conf_file.len = old_cycle->conf_file.len;
-    cycle->conf_file.data = ngx_palloc(pool, old_cycle->conf_file.len + 1);
+    cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1);
     if (cycle->conf_file.data == NULL) {
         ngx_destroy_pool(pool);
         return NULL;
@@ -182,7 +182,7 @@
     hostname[NGX_MAXHOSTNAMELEN - 1] = '\0';
     cycle->hostname.len = ngx_strlen(hostname);
 
-    cycle->hostname.data = ngx_palloc(pool, cycle->hostname.len);
+    cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len);
     if (cycle->hostname.data == NULL) {
         ngx_destroy_pool(pool);
         return NULL;
@@ -460,8 +460,8 @@
 
 #else
 
-        lock_file = ngx_palloc(cycle->pool,
-                               cycle->lock_file.len + shm_zone[i].name.len);
+        lock_file = ngx_pnalloc(cycle->pool,
+                                cycle->lock_file.len + shm_zone[i].name.len);
 
         if (lock_file == NULL) {
             goto failed;
diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c
index b98108a..28980df 100644
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -46,7 +46,7 @@
 
     file->name.len = path->name.len + 1 + path->len + 10;
 
-    file->name.data = ngx_palloc(pool, file->name.len + 1);
+    file->name.data = ngx_pnalloc(pool, file->name.len + 1);
     if (file->name.data == NULL) {
         return NGX_ERROR;
     }
diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c
index 7213f9f..abd2cf1 100644
--- a/src/core/ngx_hash.c
+++ b/src/core/ngx_hash.c
@@ -839,7 +839,7 @@
         }
 
         name->len = last - 1;
-        name->data = ngx_palloc(ha->temp_pool, name->len);
+        name->data = ngx_pnalloc(ha->temp_pool, name->len);
         if (name->data == NULL) {
             return NGX_ERROR;
         }
@@ -855,7 +855,7 @@
          *      and ".example.com" to "com.example\0"
          */
 
-        p = ngx_palloc(ha->temp_pool, last);
+        p = ngx_pnalloc(ha->temp_pool, last);
         if (p == NULL) {
             return NGX_ERROR;
         }
@@ -891,7 +891,7 @@
 
         last++;
 
-        p = ngx_palloc(ha->temp_pool, last);
+        p = ngx_pnalloc(ha->temp_pool, last);
         if (p == NULL) {
             return NGX_ERROR;
         }
@@ -944,7 +944,7 @@
     }
 
     name->len = last - skip;
-    name->data = ngx_palloc(ha->temp_pool, name->len);
+    name->data = ngx_pnalloc(ha->temp_pool, name->len);
     if (name->data == NULL) {
         return NGX_ERROR;
     }
diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c
index f54a057..aefdfcd 100644
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -578,7 +578,7 @@
 
             len = INET_ADDRSTRLEN - 1 + 1 + sizeof(":65536") - 1;
 
-            p = ngx_palloc(pool, len);
+            p = ngx_pnalloc(pool, len);
             if (p == NULL) {
                 return NGX_ERROR;
             }
@@ -614,7 +614,7 @@
         u->addrs[0].sockaddr = (struct sockaddr *) sin;
         u->addrs[0].socklen = sizeof(struct sockaddr_in);
 
-        p = ngx_palloc(pool, u->host.len + sizeof(":65536") - 1);
+        p = ngx_pnalloc(pool, u->host.len + sizeof(":65536") - 1);
         if (p == NULL) {
             return NGX_ERROR;
         }
diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c
index 130c670..64f958e 100644
--- a/src/core/ngx_palloc.c
+++ b/src/core/ngx_palloc.c
@@ -8,6 +8,10 @@
 #include <ngx_core.h>
 
 
+static void *ngx_palloc_block(ngx_pool_t *pool, size_t size);
+static void *ngx_palloc_large(ngx_pool_t *pool, size_t size);
+
+
 ngx_pool_t *
 ngx_create_pool(size_t size, ngx_log_t *log)
 {
@@ -18,11 +22,14 @@
         return NULL;
     }
 
-    p->last = (u_char *) p + sizeof(ngx_pool_t);
-    p->end = (u_char *) p + size;
+    p->d.last = (u_char *) p + sizeof(ngx_pool_t);
+    p->d.end = (u_char *) p + size;
+    p->d.next = NULL;
+
+    p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size - sizeof(ngx_pool_t):
+                                                NGX_MAX_ALLOC_FROM_POOL;
     p->current = p;
     p->chain = NULL;
-    p->next = NULL;
     p->large = NULL;
     p->cleanup = NULL;
     p->log = log;
@@ -62,9 +69,9 @@
      * so we can not use this log while the free()ing the pool
      */
 
-    for (p = pool, n = pool->next; /* void */; p = n, n = n->next) {
+    for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
         ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
-                       "free: %p, unused: %uz", p, p->end - p->last);
+                       "free: %p, unused: %uz", p, p->d.end - p->d.last);
 
         if (n == NULL) {
             break;
@@ -73,7 +80,7 @@
 
 #endif
 
-    for (p = pool, n = pool->next; /* void */; p = n, n = n->next) {
+    for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
         ngx_free(p);
 
         if (n == NULL) {
@@ -86,66 +93,99 @@
 void *
 ngx_palloc(ngx_pool_t *pool, size_t size)
 {
-    u_char            *m;
-    ngx_pool_t        *p, *n, *current;
-    ngx_pool_large_t  *large;
+    u_char      *m;
+    ngx_pool_t  *p;
 
-    if (size <= (size_t) NGX_MAX_ALLOC_FROM_POOL
-        && size <= (size_t) (pool->end - (u_char *) pool)
-                   - (size_t) ngx_align_ptr(sizeof(ngx_pool_t), NGX_ALIGNMENT))
-    {
+    if (size <= pool->max) {
+
         p = pool->current;
-        current = p;
 
-        for ( ;; ) {
+        do {
+            m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);
 
-            /*
-             * allow non-aligned memory blocks for small allocations (1, 2,
-             * or 3 bytes) and for odd length strings (struct's have aligned
-             * size)
-             */
-
-            if (size < sizeof(int) || (size & 1)) {
-                m = p->last;
-
-            } else {
-                m = ngx_align_ptr(p->last, NGX_ALIGNMENT);
-            }
-
-            if ((size_t) (p->end - m) >= size) {
-                p->last = m + size;
+            if ((size_t) (p->d.end - m) >= size) {
+                p->d.last = m + size;
 
                 return m;
             }
 
-            if ((size_t) (p->end - m) < NGX_ALIGNMENT) {
-                current = p->next;
-            }
+            p = p->d.next;
 
-            if (p->next == NULL) {
-                break;
-            }
+        } while (p);
 
-            p = p->next;
-            pool->current = current;
-        }
-
-        /* allocate a new pool block */
-
-        n = ngx_create_pool((size_t) (p->end - (u_char *) p), p->log);
-        if (n == NULL) {
-            return NULL;
-        }
-
-        pool->current = current ? current : n;
-
-        p->next = n;
-        m = ngx_align_ptr(n->last, NGX_ALIGNMENT);
-        n->last = m + size;
-
-        return m;
+        return ngx_palloc_block(pool, size);
     }
 
+    return ngx_palloc_large(pool, size);
+}
+
+
+void *
+ngx_pnalloc(ngx_pool_t *pool, size_t size)
+{
+    u_char      *m;
+    ngx_pool_t  *p;
+
+    if (size <= pool->max) {
+
+        p = pool->current;
+
+        do {
+            m = p->d.last;
+
+            if ((size_t) (p->d.end - m) >= size) {
+                p->d.last = m + size;
+
+                return m;
+            }
+
+            p = p->d.next;
+
+        } while (p);
+
+        return ngx_palloc_block(pool, size);
+    }
+
+    return ngx_palloc_large(pool, size);
+}
+
+
+static void *
+ngx_palloc_block(ngx_pool_t *pool, size_t size)
+{
+    u_char      *m;
+    ngx_pool_t  *p, *new, *current;
+
+    new = ngx_create_pool((size_t) (pool->d.end - (u_char *) pool), pool->log);
+    if (new == NULL) {
+        return NULL;
+    }
+
+    current = pool->current;
+
+    for (p = current; p->d.next; p = p->d.next) {
+        if ((size_t) (p->d.end - p->d.last) < NGX_ALIGNMENT) {
+            current = p->d.next;
+        }
+    }
+
+    p->d.next = new;
+
+    pool->current = current ? current : new;
+
+    m = (u_char *) new + sizeof(ngx_pool_data_t);
+    new->d.last = m + size;
+
+    return m;
+}
+
+
+static void *
+ngx_palloc_large(ngx_pool_t *pool, size_t size)
+{
+    void              *p;
+    ngx_pool_large_t  *large;
+
 #if 0
     p = ngx_memalign(ngx_pagesize, size, pool->log);
     if (p == NULL) {
@@ -172,17 +212,6 @@
 }
 
 
-void *
-ngx_palloc_aligned(ngx_pool_t *pool, size_t size)
-{
-    if (size & 1) {
-        size++;
-    }
-
-    return ngx_palloc(pool, size);
-}
-
-
 ngx_int_t
 ngx_pfree(ngx_pool_t *pool, void *p)
 {
diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h
index 11e2b41..34878f5 100644
--- a/src/core/ngx_palloc.h
+++ b/src/core/ngx_palloc.h
@@ -43,12 +43,18 @@
 };
 
 
-struct ngx_pool_s {
+typedef struct {
     u_char               *last;
     u_char               *end;
+    ngx_pool_t           *next;
+} ngx_pool_data_t;
+
+
+struct ngx_pool_s {
+    ngx_pool_data_t       d;
+    size_t                max;
     ngx_pool_t           *current;
     ngx_chain_t          *chain;
-    ngx_pool_t           *next;
     ngx_pool_large_t     *large;
     ngx_pool_cleanup_t   *cleanup;
     ngx_log_t            *log;
@@ -69,7 +75,7 @@
 void ngx_destroy_pool(ngx_pool_t *pool);
 
 void *ngx_palloc(ngx_pool_t *pool, size_t size);
-void *ngx_palloc_aligned(ngx_pool_t *pool, size_t size);
+void *ngx_pnalloc(ngx_pool_t *pool, size_t size);
 void *ngx_pcalloc(ngx_pool_t *pool, size_t size);
 ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);
 
diff --git a/src/core/ngx_regex.c b/src/core/ngx_regex.c
index fb12ab1..be2dae7 100644
--- a/src/core/ngx_regex.c
+++ b/src/core/ngx_regex.c
@@ -165,7 +165,7 @@
 #endif
 
     if (pool) {
-        return ngx_palloc_aligned(pool, size);
+        return ngx_palloc(pool, size);
     }
 
     return NULL;
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index 01d792f..c919315 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -34,7 +34,7 @@
 {
     u_char  *dst;
 
-    dst = ngx_palloc(pool, src->len);
+    dst = ngx_pnalloc(pool, src->len);
     if (dst == NULL) {
         return NULL;
     }