From: Rusty Russell Date: Fri, 22 Jun 2012 05:37:44 +0000 (+0930) Subject: tdb: make TDB_NOSYNC merely disable sync. X-Git-Tag: samba-4.0.0beta3~243 X-Git-Url: http://git.samba.org/?p=ddiss%2Fsamba.git;a=commitdiff_plain;h=1783fe34433f9bb4b939de3231a7c296390ec426 tdb: make TDB_NOSYNC merely disable sync. (As suggested by Stefan Metzmacher, based on the change to ntdb.) Since commit ec96ea690edbe3398d690b4a953d487ca1773f1c, we handle the case where a process dies during a transaction commit. Unfortunately, TDB_NOSYNC means this no longer works, as it disables the recovery area as well as the actual msync/fsync. We should do everything except the syncs. This also means we can do a complete test with $TDB_NO_FSYNC set; just to get more complete coverage, we disable it explicitly for one test (where we override the actual sync calls anyway). Signed-off-by: Rusty Russell --- diff --git a/lib/tdb/common/transaction.c b/lib/tdb/common/transaction.c index c3477eb80ca..f18b4c229eb 100644 --- a/lib/tdb/common/transaction.c +++ b/lib/tdb/common/transaction.c @@ -82,8 +82,9 @@ intervention. - if TDB_NOSYNC is passed to flags in tdb_open then transactions are - still available, but no transaction recovery area is used and no - fsync/msync calls are made. + still available, but no fsync/msync calls are made. This means we + are still proof against a process dying during transaction commit, + but not against machine reboot. - if TDB_ALLOW_NESTING is passed to flags in tdb open, or added using tdb_add_flags() transaction nesting is enabled. @@ -976,13 +977,11 @@ static int _tdb_transaction_prepare_commit(struct tdb_context *tdb) return -1; } - if (!(tdb->flags & TDB_NOSYNC)) { - /* write the recovery data to the end of the file */ - if (transaction_setup_recovery(tdb, &tdb->transaction->magic_offset) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_prepare_commit: failed to setup recovery data\n")); - _tdb_transaction_cancel(tdb); - return -1; - } + /* write the recovery data to the end of the file */ + if (transaction_setup_recovery(tdb, &tdb->transaction->magic_offset) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_prepare_commit: failed to setup recovery data\n")); + _tdb_transaction_cancel(tdb); + return -1; } tdb->transaction->prepared = true; diff --git a/lib/tdb/test/run-transaction-expand.c b/lib/tdb/test/run-transaction-expand.c index 3b79dbb6eae..bc22d2b53e4 100644 --- a/lib/tdb/test/run-transaction-expand.c +++ b/lib/tdb/test/run-transaction-expand.c @@ -1,8 +1,10 @@ #include "../common/tdb_private.h" -/* Speed up the tests: setting TDB_NOSYNC removed recovery altogether. */ +/* Speed up the tests, but do the actual sync tests. */ +static unsigned int sync_counts = 0; static inline int fake_fsync(int fd) { + sync_counts++; return 0; } #define fsync fake_fsync @@ -10,6 +12,7 @@ static inline int fake_fsync(int fd) #ifdef MS_SYNC static inline int fake_msync(void *addr, size_t length, int flags) { + sync_counts++; return 0; } #define msync fake_msync @@ -18,6 +21,7 @@ static inline int fake_msync(void *addr, size_t length, int flags) #ifdef HAVE_FDATASYNC static inline int fake_fdatasync(int fd) { + sync_counts++; return 0; } #define fdatasync fake_fdatasync @@ -59,7 +63,10 @@ int main(int argc, char *argv[]) struct tdb_record rec; tdb_off_t off; - plan_tests(4); + /* Do *not* suppress sync for this test; we do it ourselves. */ + unsetenv("TDB_NO_FSYNC"); + + plan_tests(5); tdb = tdb_open_ex("run-transaction-expand.tdb", 1024, TDB_CLEAR_IF_FIRST, O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); @@ -103,6 +110,9 @@ int main(int argc, char *argv[]) /* We should only be about 4 times larger than largest record. */ ok1(tdb->map_size < 5 * i * getpagesize()); + + /* We should have synchronized multiple times. */ + ok1(sync_counts); tdb_close(tdb); free(data.dptr); diff --git a/lib/tdb/wscript b/lib/tdb/wscript index 01b4892fb02..e28e43acac2 100644 --- a/lib/tdb/wscript +++ b/lib/tdb/wscript @@ -185,10 +185,6 @@ def testonly(ctx): if not os.path.exists(link): os.symlink(os.path.abspath(os.path.join(env.cwd, 'test')), link) - # unset TDB_NO_FSYNC, since we want to test sync code. - if 'TDB_NO_FSYNC' in os.environ: - del os.environ['TDB_NO_FSYNC'] - for f in 'tdb1-run-3G-file', 'tdb1-run-bad-tdb-header', 'tdb1-run', 'tdb1-run-check', 'tdb1-run-corrupt', 'tdb1-run-die-during-transaction', 'tdb1-run-endian', 'tdb1-run-incompatible', 'tdb1-run-nested-transactions', 'tdb1-run-nested-traverse', 'tdb1-run-no-lock-during-traverse', 'tdb1-run-oldhash', 'tdb1-run-open-during-transaction', 'tdb1-run-readonly-check', 'tdb1-run-rwlock-check', 'tdb1-run-summary', 'tdb1-run-transaction-expand', 'tdb1-run-traverse-in-transaction', 'tdb1-run-wronghash-fail', 'tdb1-run-zero-append': cmd = "cd " + testdir + " && " + os.path.abspath(os.path.join(Utils.g_module.blddir, f)) + " > test-output 2>&1" print("..." + f)