From c5d32fd76b0b47d55e897377df4a8a2c0f6ce1e9 Mon Sep 17 00:00:00 2001
From: Wietse Venema
Date: Sun, 17 Mar 2013 00:00:00 -0500
Subject: [PATCH] postfix-2.11-20130317
---
postfix/HISTORY | 37 ++++++--
postfix/README_FILES/LMDB_README | 137 ++++++++++++++-------------
postfix/RELEASE_NOTES | 8 +-
postfix/html/LMDB_README.html | 152 +++++++++++++++---------------
postfix/proto/LMDB_README.html | 152 +++++++++++++++---------------
postfix/src/global/mail_version.h | 2 +-
postfix/src/global/mkmap_lmdb.c | 2 +-
postfix/src/global/mkmap_open.c | 2 +-
postfix/src/postalias/postalias.c | 12 ++-
postfix/src/postmap/postmap.c | 12 ++-
postfix/src/tls/tls_scache.c | 4 +
postfix/src/util/dict.c | 16 +++-
postfix/src/util/dict.h | 2 +
postfix/src/util/dict_cache.c | 5 +
postfix/src/util/dict_lmdb.c | 61 +++++++++---
postfix/src/util/dict_open.c | 2 +-
postfix/src/util/dict_test.c | 21 ++---
17 files changed, 353 insertions(+), 274 deletions(-)
diff --git a/postfix/HISTORY b/postfix/HISTORY
index 1f3a451f6..4041b6f83 100644
--- a/postfix/HISTORY
+++ b/postfix/HISTORY
@@ -18256,12 +18256,31 @@ Apologies for any names omitted.
20130315
- Feature: preliminary LMDB (memory-mapped persistent file)
- support by Howard Chu. This feature has unexpected limitations
- that don't exist with other Postfix databases, and is
- therefore "snapshot only", i.e. it will not be part of a
- stable release without further changes to the Postfix LMDB
- client or the Postfix dictionary API. Files: proto/postconf.proto,
- proto/LMDB_README.html, proto/DATABASE_README.html,
- proto/INSTALL.html util/dict_lmdb.[hc], util/dict_open.c,
- global/mkmap_lmdb.[hc], global/mkmap_open.c, postconf/postconf.c.
+ Feature: LMDB (memory-mapped persistent file) support by
+ Howard Chu. This implementation has unexpected failure modes
+ that don't exist with other Postfix databases, so don't
+ just yet abandon CDB. See LMDB_README for details. Files:
+ proto/postconf.proto, proto/LMDB_README.html,
+ proto/DATABASE_README.html, proto/INSTALL.html util/dict_lmdb.[hc],
+ util/dict_open.c, global/mkmap_lmdb.[hc], global/mkmap_open.c,
+ postconf/postconf.c.
+
+20130316
+
+ Cleanup: new Postfix dictionary API flag to control the use
+ of (LMDB) bulk database transactions. With this, LMDB
+ databases no longer fail to commit any transactions with
+ tlsmgr(8), and LMDB databases no longer perform glacially
+ slow with postmap -i/postalias -i. Files: util/dict.h,
+ util/dict_lmdb.c, postmap/postmap.c, postalias/postalias.c.
+
+20130317
+
+ Debugging: generalized setting of dictionary API flags.
+ File: util/dict.[hc], util/dict_test.c.
+
+ Robustness: Postfix programs can now recover from LMDB
+ "database full" errors without requiring human intervention.
+ When a program opens an LMDB file larger than lmdb_map_size/3,
+ it logs a warning and uses a larger size limit instead.
+ Files: util/dict_lmdb.c, proto/LMDB_README.html.
diff --git a/postfix/README_FILES/LMDB_README b/postfix/README_FILES/LMDB_README
index dfd131373..e39d2777d 100644
--- a/postfix/README_FILES/LMDB_README
+++ b/postfix/README_FILES/LMDB_README
@@ -18,11 +18,9 @@ This document describes:
3. Missing pthread library trouble.
-Caution:
- The current Postfix LMDB client has unexpected limitations that don't exist
- with other Postfix databases. For this reason, LMDB support will not be
- part of the stable Postfix release without further changes to the Postfix
- LMDB client or the Postfix dictionary API.
+Note:
+ The Postfix LMDB client implementation introduces unexpected failure modes
+ that don't exist with other Postfix databases. Don't just yet abandon CDB.
BBuuiillddiinngg PPoossttffiixx wwiitthh OOppeennLLDDAAPP LLMMDDBB ssuuppppoorrtt
@@ -65,92 +63,95 @@ Add the "-lpthread" library to the "make makefiles" command.
Source code for OpenLDAP LMDB is available at http://www.openldap.org. More
information is available at http://highlandsun.com/hyc/mdb/.
-LLiimmiittaattiioonnss ooff PPoossttffiixx LLMMDDBB ddaattaabbaasseess..
+UUnneexxppeecctteedd ffaaiilluurree mmooddeess ooff PPoossttffiixx LLMMDDBB ddaattaabbaasseess..
+
+As documented below, conversion to LMDB introduces a number of failure modes
+that don't exist with other Postfix databases.
UUnneexxppeecctteedd ppoossttmmaapp((11))//ppoossttaalliiaass((11)) ""ddaattaabbaassee ffuullll"" eerrrroorrss..
Problem:
- Even if the "postmap lmdb:filename" command succeeds, the exact same
- command (with the exact same input data) may fail subsequently with an
- MDB_MAP_FULL error. This problem does not exist with other Postfix
- databases.
+ The "postmap lmdb:filename" command fails with an MDB_MAP_FULL error. This
+ problem does not exist with other Postfix databases.
Background:
LMDB databases have a hard size limit (configured with the lmdb_map_size
configuration parameter).
When executing "postmap lmdb:filename", the Postfix LMDB database client
- does not truncate the database file. Instead it saves the "drop" request
- and subsequent "store" requests to a transaction (which takes up space in
- addition to the existing data), and commits the transaction when it closes
- the database. Only then can the space for old data be reused.
+ stores the new data in a transaction which takes up space in addition to
+ the existing data, and commits the transaction when it closes the database.
+ Only then can the space for old data be reused.
Impact:
This failure does not affect Postfix availability, because the old data
still exists in the database.
-Recovery:
- Increase the lmdb_map_size limit in main.cf, and retry the postmap(1) or
- postalias(1) command.
+Mitigation:
+ When the postmap(1) or postalias(1) command opens an LMDB file larger than
+ lmdb_map_size/3, it logs a warning and uses a larger size limit instead:
-PPoossttffiixx ddaaeemmoonn ""ddaattaabbaassee ffuullll"" eerrrroorrss..
+ warning: filename.lmdb: file size 15024128 >= (lmdb map size limit
+ 16777216)/3 -- using a larger map size limit
+
+ This can be used to automate recovery and avoid the need for human
+ intervention. Just keep running "postmap lmdb:filename". After each failure
+ it will use a 3x larger size limit, and eventually the "database full"
+ error will disappear.
+
+Prevention:
+ Monitor your LMDB files and make sure that lmdb_map_size > 3x the largest
+ LMDB file size.
+
+UUnneexxppeecctteedd PPoossttffiixx ddaaeemmoonn ""ddaattaabbaassee ffuullll"" eerrrroorrss..
Problem:
- "database full" errors with daemon programs such as postscreen(8), tlsmgr
- (8) or verify(8). This problem does not exist with other Postfix databases.
+ Postfix daemon programs fail with "database full" errors, such as
+ postscreen(8), tlsmgr(8) or verify(8). This problem does not exist with
+ other Postfix databases.
+
+Impact:
+ This failure temporarily affects Postfix availability. The daemon restarts
+ automatically and tries to open the database again as described next.
+
+Mitigation:
+ When a Postfix daemon opens an LMDB file larger than lmdb_map_size/3, it
+ logs a warning and uses a larger size limit instead:
+
+ warning: filename.lmdb: file size 15024128 >= (lmdb map size limit
+ 16777216)/3 -- using a larger map size limit
+
+ This can be used to automate recovery and avoid the need for human
+ intervention. Each time the daemon runs into a "database full" error, it
+ restarts and uses a 3x larger size limit. The "database full" error will
+ disappear, at least for a while.
+
+Prevention:
+ Monitor your LMDB files and make sure that lmdb_map_size > 3x the largest
+ LMDB file size.
+
+NNoonn--oobbvviioouuss rreeccoovveerryy wwiitthh ppoossttmmaapp((11))//ppoossttaalliiaass((11))//ttllssmmggrr((88)) ffrroomm aa ccoorrrruupptteedd
+ddaattaabbaassee..
+
+Problem:
+ You cannot rebuild a corrupted LMDB database simply by running postmap(1)
+ or postalias(1), or by waiting until the tlsmgr(8) daemon restarts
+ automatically. This problem does not exist with other Postfix databases.
+
+Background:
+ The Postfix LMDB database client does not truncate the database file.
+ Instead it attempts to create a transaction for a "drop" request and
+ subsequent "store" requests. That is obviously not possible with a
+ corrupted database file.
Impact:
Postfix does not process mail until someone fixes the problem.
-Recovery:
- Increase the lmdb_map_size limit in main.cf, and "reload" Postfix.
-
-NNoonn--oobbvviioouuss rreeccoovveerryy wwiitthh ppoossttmmaapp((11))//ppoossttaalliiaass((11)) ffrroomm aa ccoorrrruupptteedd ddaattaabbaassee..
-
-Problem:
- You cannot rebuild a corrupted LMDB database simply by running postmap(1)
- or postalias(1). This problem does not exist with other Postfix databases.
-
-Background:
- The reason for this limitation is that the Postfix LMDB database client
- does not truncate the database file. Instead it attempts to save the "drop"
- request and subsequent "store" requests to a transaction for later
- processing. That is obviously not possible with a corrupted database file.
-
Recovery:
First delete the ".lmdb" file by hand, then rebuild the file with the
- postmap(1) or postalias(1) command.
+ postmap(1) or postalias(1) command, or wait until the tlsmgr(8) daemon
+ restarts automatically.
-IInnccoommppaattiibbiilliittyy wwiitthh ttllssmmggrr((88))..
-
-Problem:
- The Postfix LMDB database client never commits any tlsmgr(8) transaction.
- This problem does not exist with other Postfix databases.
-
-Background:
- Instead, it creates a single transaction that accumulates a "drop" request
- and all tlsmgr(8) "store" requests that are made during the lifetime of the
- process.
-
-Solution:
- This requires changes to the Postfix dictionary API, or to the Postfix LMDB
- database client.
-
-Problem:
- The Postfix LMDB database client breaks how tlsmgr(8) automatically
- recovers from a corrupted database file. This problem does not exist with
- other Postfix databases.
-
-Background:
- The Postfix LMDB database client does not truncate the database file.
- Instead it attempts to create a transaction which obviously is not possible
- when the database file is corrupted.
-
-Impact:
- The tlsmgr(8) process will keep crashing until someone removes the ".lmdb"
- file.
-
-Recovery:
- Remove the the ".lmdb" file by hand, and wait until the tlsmgr(8) process
- restarts.
+Prevention:
+ Arrange your file systems such that they never run out of free space.
diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES
index 64fee86b6..ef167571b 100644
--- a/postfix/RELEASE_NOTES
+++ b/postfix/RELEASE_NOTES
@@ -17,8 +17,6 @@ before proceeding.
Major changes with snapshot 20130315
====================================
-Preliminary LMDB support by Howard Chu. This implementation has
-unexpected limitations that don't exist with other Postfix databases,
-and therefore the code is "snapshot only", i.e. it will not be part
-of the stable release without further changes to the Postfix LMDB
-client or the Postfix dictionary API. See LMDB_README for details.
+LMDB support by Howard Chu. This implementation has unexpected
+failure modes that don't exist with other Postfix databases, so
+don't just yet abandon CDB. See LMDB_README for details.
diff --git a/postfix/html/LMDB_README.html b/postfix/html/LMDB_README.html
index e6f1bb984..4b3368145 100644
--- a/postfix/html/LMDB_README.html
+++ b/postfix/html/LMDB_README.html
@@ -39,12 +39,10 @@ LMDB support.
- - Caution:
-
The current Postfix LMDB client
-has unexpected limitations that don't
-exist with other Postfix databases. For this reason, LMDB support
-will not be part of the stable Postfix release without further
-changes to the Postfix LMDB client or the Postfix dictionary API.
-
+ - Note:
-
The Postfix LMDB client implementation
+introduces unexpected failure modes that
+don't exist with other Postfix databases. Don't just yet abandon
+CDB.
@@ -111,32 +109,33 @@ undefined reference to `pthread_mutex_lock'
More information is available at
http://highlandsun.com/hyc/mdb/.
-
+
- Unexpected postmap(1)/postalias(1) "database full" errors.
-
+ As documented below, conversion to LMDB introduces a number of
+failure modes that don't exist with other Postfix databases.
+
+ Unexpected postmap(1)/postalias(1) "database full"
+errors.
-- Problem:
-
Even if the "postmap lmdb:filename"
-command succeeds, the exact same command (with the exact same input
-data) may fail subsequently with an MDB_MAP_FULL error. This problem
-does not exist with other Postfix databases.
+- Problem:
-
The "postmap lmdb:filename" command
+fails with an MDB_MAP_FULL error. This problem does not exist with
+other Postfix databases.
-- Background:
+- Background:
--
+
-
LMDB databases have a hard size limit (configured with the
lmdb_map_size configuration parameter).
When executing "postmap lmdb:filename", the Postfix LMDB database
-client does not truncate the database file. Instead it saves the
-"drop" request and subsequent "store" requests to a transaction
-(which takes up space in addition to the existing data), and commits
-the transaction when it closes the database. Only then can the
-space for old data be reused.
+client stores the new data in a transaction which takes up space
+in addition to the existing data, and commits the transaction when
+it closes the database. Only then can the space for old data be
+reused.
@@ -144,82 +143,81 @@ space for old data be reused.
availability, because the old data still exists in the database.
-- Recovery:
-
Increase the lmdb_map_size limit in
-main.cf, and retry the postmap(1) or postalias(1) command.
-
+- Mitigation:
-
When the postmap(1) or postalias(1)
+command opens an LMDB file larger than lmdb_map_size/3, it logs a
+warning and uses a larger size limit instead:
-
+ warning: filename.lmdb: file size 15024128 ≥
+(lmdb map size limit 16777216)/3 -- using a larger map size limit
+
- Postfix daemon "database full" errors.
+ This can be used to automate recovery and avoid the need for
+human intervention. Just keep running "postmap lmdb:filename".
+After each failure it will use a 3x larger size limit, and eventually
+the "database full" error will disappear.
+
+ Prevention: Monitor your LMDB files and make
+sure that lmdb_map_size > 3x the largest LMDB file size.
+
+
+ Unexpected Postfix daemon "database full" errors.
+
-- Problem:
-
"database full" errors with daemon
-programs such as postscreen(8), tlsmgr(8) or verify(8). This problem
-does not exist with other Postfix databases.
+- Problem:
-
Postfix daemon programs fail with
+"database full" errors, such as postscreen(8), tlsmgr(8) or verify(8).
+This problem does not exist with other Postfix databases.
+
-- Impact:
-
Postfix does not process mail until
-someone fixes the problem.
+- Impact:
-
This failure temporarily affects Postfix
+availability. The daemon restarts automatically and tries to open
+the database again as described next.
-- Recovery:
-
Increase the lmdb_map_size limit in
-main.cf, and "reload" Postfix.
+- Mitigation:
-
When a Postfix daemon opens an LMDB
+file larger than lmdb_map_size/3, it logs a warning and uses a
+larger size limit instead:
+
+ warning: filename.lmdb: file size 15024128 ≥
+(lmdb map size limit 16777216)/3 -- using a larger map size limit
+
+
+ This can be used to automate recovery and avoid the need for
+human intervention. Each time the daemon runs into a "database full"
+error, it restarts and uses a 3x larger size limit. The "database
+full" error will disappear, at least for a while.
+
+ - Prevention:
-
Monitor your LMDB files and make
+sure that lmdb_map_size > 3x the largest LMDB file size.
+
- Non-obvious recovery with postmap(1)/postalias(1)
+ Non-obvious recovery with postmap(1)/postalias(1)/tlsmgr(8)
from a corrupted database.
- Problem:
-
You cannot rebuild a corrupted LMDB
-database simply by running postmap(1) or postalias(1). This problem
+database simply by running postmap(1) or postalias(1), or by waiting
+until the tlsmgr(8) daemon restarts automatically. This problem
does not exist with other Postfix databases.
-- Background:
-
The reason for this limitation is
-that the Postfix LMDB database client does not truncate the database
-file. Instead it attempts to save the "drop" request and subsequent
-"store" requests to a transaction for later processing. That is
-obviously not possible with a corrupted database file.
-
-- Recovery:
-
First delete the ".lmdb" file by hand,
-then rebuild the file with the postmap(1) or postalias(1) command.
-
-
-
-
- Incompatibility with tlsmgr(8).
-
-
-
-- Problem:
-
The Postfix LMDB database client never
-commits any tlsmgr(8) transaction. This problem does not exist with
-other Postfix databases.
-
-- Background:
-
Instead, it creates a single
-transaction that accumulates a "drop" request and all tlsmgr(8)
-"store" requests that are made during the lifetime of the process.
-
-
-- Solution:
-
This requires changes to the Postfix
-dictionary API, or to the Postfix LMDB database client.
-
-- Problem:
-
The Postfix LMDB database client breaks
-how tlsmgr(8) automatically recovers from a corrupted database file.
-This problem does not exist with other Postfix databases.
-
- Background:
-
The Postfix LMDB database client
does not truncate the database file. Instead it attempts to create
-a transaction which obviously is not possible when the database
-file is corrupted.
+a transaction for a "drop" request and subsequent "store" requests.
+That is obviously not possible with a corrupted database file.
+
- Impact: The tlsmgr(8) process will keep crashing
-until someone removes the ".lmdb" file.
+ Impact: Postfix does not process mail until
+someone fixes the problem.
- Recovery: Remove the the ".lmdb" file by hand,
-and wait until the tlsmgr(8) process restarts.
+ Recovery: First delete the ".lmdb" file by hand,
+then rebuild the file with the postmap(1) or postalias(1) command,
+or wait until the tlsmgr(8) daemon restarts automatically.
+
+
+ Prevention: Arrange your file systems such that
+they never run out of free space.
-
-