From 887d796a28a0aa28db84f1c02a1873f7f9f0cb0d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 May 2001 22:23:37 +0000 Subject: Fix problem with OpenBSD mmap and write not being coherent. Jeremy. (This used to be commit 4c6a8273c6dd3e2aeda5a63c4a62aa55bc133099) --- source3/tdb/tdb.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) (limited to 'source3/tdb') diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c index b1335728ab..bf94e4cbd3 100644 --- a/source3/tdb/tdb.c +++ b/source3/tdb/tdb.c @@ -429,6 +429,7 @@ static int tdb_expand(TDB_CONTEXT *tdb, tdb_off size) struct list_struct rec; tdb_off offset; char b = 0; + void *old_map_ptr; if (tdb_lock(tdb, -1, F_WRLCK) == -1) return 0; @@ -439,20 +440,43 @@ static int tdb_expand(TDB_CONTEXT *tdb, tdb_off size) the database up to a multiple of TDB_PAGE_SIZE */ size = TDB_ALIGN(tdb->map_size + size*10, TDB_PAGE_SIZE) - tdb->map_size; - /* expand the file itself */ - if (!(tdb->flags & TDB_INTERNAL)) { - lseek(tdb->fd, tdb->map_size + size - 1, SEEK_SET); - if (write(tdb->fd, &b, 1) != 1) goto fail; - } + old_map_ptr = tdb->map_ptr; if (!(tdb->flags & TDB_INTERNAL) && tdb->map_ptr) tdb->map_ptr = tdb_munmap(tdb->map_ptr, tdb->map_size); + /* + * We must ensure the file is unmapped before doing this + * to ensure consistency with systems like OpenBSD where + * writes and mmaps are not consistent. + */ + + /* expand the file itself */ + if (!(tdb->flags & TDB_INTERNAL)) { + if (lseek(tdb->fd, tdb->map_size + size - 1, SEEK_SET)!=tdb->map_size + size - 1) + goto fail; + if (write(tdb->fd, &b, 1) != 1) + goto fail; + } + tdb->map_size += size; if (tdb->flags & TDB_INTERNAL) tdb->map_ptr = realloc(tdb->map_ptr, tdb->map_size); + /* + * We must ensure the file is remapped before adding the space + * to ensure consistency with systems like OpenBSD where + * writes and mmaps are not consistent. + */ + + if (!(tdb->flags & TDB_NOMMAP)) { + tdb->map_ptr = tdb_mmap(tdb->map_size, 0, tdb->fd); + /* if old_map_ptr was != NULL but the new one is, we have an error. */ + if (old_map_ptr && (tdb->map_ptr == NULL)) + goto fail; + } + /* form a new freelist record */ memset(&rec,'\0',sizeof(rec)); rec.rec_len = size - sizeof(rec); @@ -461,9 +485,6 @@ static int tdb_expand(TDB_CONTEXT *tdb, tdb_off size) offset = tdb->map_size - size; if (tdb_free(tdb, offset, &rec) == -1) goto fail; - if (!(tdb->flags & TDB_NOMMAP)) - tdb->map_ptr = tdb_mmap(tdb->map_size, 0, tdb->fd); - tdb_unlock(tdb, -1, F_WRLCK); return 0; fail: -- cgit