]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
Fix problem with OpenBSD mmap and write not being coherent.
authorJeremy Allison <jra@samba.org>
Fri, 4 May 2001 22:23:37 +0000 (22:23 +0000)
committerJeremy Allison <jra@samba.org>
Fri, 4 May 2001 22:23:37 +0000 (22:23 +0000)
Jeremy.

source/tdb/tdb.c

index b1335728ab51a011a832a6df7b9765c160c759b6..bf94e4cbd3f7af90f54682571217039fe340b00b 100644 (file)
@@ -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: