Index: configure.in =================================================================== --- configure.in (Revision 10235) +++ configure.in (Arbeitskopie) @@ -2465,6 +2465,7 @@ if test x"$samba_cv_HAVE_MMAP" = x"yes"; then AC_DEFINE(HAVE_MMAP,1,[Whether mmap works]) fi +AC_CHECK_FUNCS(msync) AC_CACHE_CHECK([for fcntl locking],samba_cv_HAVE_FCNTL_LOCK,[ AC_TRY_RUN([#include "${srcdir-.}/tests/fcntl_lock.c"], Index: tdb/tdb.c =================================================================== --- tdb/tdb.c (Revision 10235) +++ tdb/tdb.c (Arbeitskopie) @@ -144,7 +144,25 @@ #ifdef HAVE_MMAP if (tdb->map_ptr) { - int ret = munmap(tdb->map_ptr, tdb->map_size); + int ret; +#ifdef HAVE_MSYNC + if (tdb->flags & TDB_MSYNC) { + /* At least on Linux 2.4 and 2.6 there appears to be + * the problem that without this call data might never + * make it to disk. I've seen cases where new mappings + * in winbindd_idmap of days ago have never made it + * after a crash, and there have been reports that + * even normally shutting down processes loses mmap'ed + * info. "use mmap = no" helps, but also makes stuff + * slower. This is a hack to sync the persistent + * databases (without CLEAR_IF_FIRST) before + * closing. It seems to solve some cases. Maybe we + * have to expand it to an msync after every real + * unlock. -- vl */ + msync(tdb->map_ptr, tdb->map_size, MS_SYNC); + } +#endif + ret = munmap(tdb->map_ptr, tdb->map_size); if (ret != 0) return ret; } @@ -1924,6 +1942,11 @@ goto fail; } + if ((tdb->flags & TDB_CLEAR_IF_FIRST) == 0) { + /* This is a persistent database, so better ensure this goes + * to disk. */ + tdb->flags |= TDB_MSYNC; + } internal: /* Internal (memory-only) databases skip all the code above to Index: tdb/tdb.h =================================================================== --- tdb/tdb.h (Revision 10235) +++ tdb/tdb.h (Arbeitskopie) @@ -55,6 +55,7 @@ #define TDB_NOLOCK 4 /* don't do any locking */ #define TDB_NOMMAP 8 /* don't use mmap */ #define TDB_CONVERT 16 /* convert endian (internal use) */ +#define TDB_MSYNC 32 /* Sync after unlock */ #define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */ #define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret)