summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2012-03-23 10:45:18 +1030
committerRusty Russell <rusty@rustcorp.com.au>2012-03-23 02:53:15 +0100
commit4442c0b2c92e4b2e88661e15022228c5f6547112 (patch)
treeceae95a83ff2c21ed57bfacac66dee324a34316c /lib
parentc12970cc91cb4da8976801e194e29e33e02b340a (diff)
downloadsamba-4442c0b2c92e4b2e88661e15022228c5f6547112.tar.gz
samba-4442c0b2c92e4b2e88661e15022228c5f6547112.tar.bz2
samba-4442c0b2c92e4b2e88661e15022228c5f6547112.zip
lib/tdb: fix transaction issue for HAVE_INCOHERENT_MMAP.
We unmap the tdb on expand, the remap. But when we have INCOHERENT_MMAP (ie. OpenBSD) and we're inside a transaction, doing the expand can mean we need to read from the database to partially fill a transaction block. This fails, because if mmap is incoherent we never allow accessing the database via read/write. The solution is not to unmap and remap until we've actually written the padding at the end of the file. Reported-by: Amitay Isaacs <amitay@gmail.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Autobuild-User: Rusty Russell <rusty@rustcorp.com.au> Autobuild-Date: Fri Mar 23 02:53:15 CET 2012 on sn-devel-104
Diffstat (limited to 'lib')
-rw-r--r--lib/tdb/common/io.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/lib/tdb/common/io.c b/lib/tdb/common/io.c
index be5a9ca5b2..3131f4fa0a 100644
--- a/lib/tdb/common/io.c
+++ b/lib/tdb/common/io.c
@@ -381,37 +381,36 @@ int tdb_expand(struct tdb_context *tdb, tdb_off_t size)
size = tdb_expand_adjust(tdb->map_size, size, tdb->page_size);
- if (!(tdb->flags & TDB_INTERNAL))
- tdb_munmap(tdb);
-
/* expand the file itself */
if (!(tdb->flags & TDB_INTERNAL)) {
if (tdb->methods->tdb_expand_file(tdb, tdb->map_size, size) != 0)
goto fail;
}
- tdb->map_size += size;
+ /* form a new freelist record */
+ offset = tdb->map_size;
+ memset(&rec,'\0',sizeof(rec));
+ rec.rec_len = size - sizeof(rec);
if (tdb->flags & TDB_INTERNAL) {
char *new_map_ptr = (char *)realloc(tdb->map_ptr,
- tdb->map_size);
+ tdb->map_size + size);
if (!new_map_ptr) {
- tdb->map_size -= size;
goto fail;
}
tdb->map_ptr = new_map_ptr;
+ tdb->map_size += size;
} else {
+ /* Explicitly remap: if we're in a transaction, this won't
+ * happen automatically! */
+ tdb_munmap(tdb);
+ tdb->map_size += size;
if (tdb_mmap(tdb) != 0) {
goto fail;
}
}
- /* form a new freelist record */
- memset(&rec,'\0',sizeof(rec));
- rec.rec_len = size - sizeof(rec);
-
/* link it into the free list */
- offset = tdb->map_size - size;
if (tdb_free(tdb, offset, &rec) == -1)
goto fail;