diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2012-03-23 10:45:18 +1030 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2012-03-23 02:53:15 +0100 |
commit | 4442c0b2c92e4b2e88661e15022228c5f6547112 (patch) | |
tree | ceae95a83ff2c21ed57bfacac66dee324a34316c /lib/tdb/common | |
parent | c12970cc91cb4da8976801e194e29e33e02b340a (diff) | |
download | samba-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/tdb/common')
-rw-r--r-- | lib/tdb/common/io.c | 21 |
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; |