summaryrefslogtreecommitdiff
path: root/source3/tdb
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2001-05-04 22:23:37 +0000
committerJeremy Allison <jra@samba.org>2001-05-04 22:23:37 +0000
commit887d796a28a0aa28db84f1c02a1873f7f9f0cb0d (patch)
tree59159577b32e630f791309c841b570feb608768d /source3/tdb
parentf35157f39293f9fa240a28642c41708b55d301c8 (diff)
downloadsamba-887d796a28a0aa28db84f1c02a1873f7f9f0cb0d.tar.gz
samba-887d796a28a0aa28db84f1c02a1873f7f9f0cb0d.tar.bz2
samba-887d796a28a0aa28db84f1c02a1873f7f9f0cb0d.zip
Fix problem with OpenBSD mmap and write not being coherent.
Jeremy. (This used to be commit 4c6a8273c6dd3e2aeda5a63c4a62aa55bc133099)
Diffstat (limited to 'source3/tdb')
-rw-r--r--source3/tdb/tdb.c37
1 files changed, 29 insertions, 8 deletions
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: