diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2012-06-22 09:44:40 +0930 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2012-06-22 07:35:17 +0200 |
commit | 0a34f342c3facace0767ff08f05532c9f161e305 (patch) | |
tree | c227f755f1933e797ac49f74a856c8d60b11539d /lib/ntdb/io.c | |
parent | 66d151d6893657b31c419d422bffeefc506e2319 (diff) | |
download | samba-0a34f342c3facace0767ff08f05532c9f161e305.tar.gz samba-0a34f342c3facace0767ff08f05532c9f161e305.tar.bz2 samba-0a34f342c3facace0767ff08f05532c9f161e305.zip |
ntdb: enhancement to allow direct access to the ntdb map during expansion.
This means keeping the old mmap around when we expand the database.
We could revert to read/write, except for platforms with incoherent
mmap (ie. OpenBSD), where we need to use mmap for all accesses.
Thus we keep a linked list of old maps, and unmap them when the last access
finally goes away.
This is required if we want ntdb_parse_record() callbacks to be able
to expand the database.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'lib/ntdb/io.c')
-rw-r--r-- | lib/ntdb/io.c | 80 |
1 files changed, 59 insertions, 21 deletions
diff --git a/lib/ntdb/io.c b/lib/ntdb/io.c index a54f1a661c..6749d282d9 100644 --- a/lib/ntdb/io.c +++ b/lib/ntdb/io.c @@ -28,17 +28,48 @@ #include "private.h" #include <ccan/likely/likely.h> -void ntdb_munmap(struct ntdb_file *file) +static void free_old_mmaps(struct ntdb_context *ntdb) { - if (file->fd == -1) - return; + struct ntdb_old_mmap *i; - if (file->map_ptr) { - munmap(file->map_ptr, file->map_size); - file->map_ptr = NULL; + assert(ntdb->file->direct_count == 0); + + while ((i = ntdb->file->old_mmaps) != NULL) { + ntdb->file->old_mmaps = i->next; + munmap(i->map_ptr, i->map_size); + ntdb->free_fn(i, ntdb->alloc_data); } } +enum NTDB_ERROR ntdb_munmap(struct ntdb_context *ntdb) +{ + if (ntdb->file->fd == -1) { + return NTDB_SUCCESS; + } + + if (!ntdb->file->map_ptr) { + return NTDB_SUCCESS; + } + + /* We can't unmap now if there are accessors. */ + if (ntdb->file->direct_count) { + struct ntdb_old_mmap *old + = ntdb->alloc_fn(ntdb, sizeof(*old), ntdb->alloc_data); + if (!old) { + return ntdb_logerr(ntdb, NTDB_ERR_OOM, NTDB_LOG_ERROR, + "ntdb_munmap alloc failed"); + } + old->next = ntdb->file->old_mmaps; + old->map_ptr = ntdb->file->map_ptr; + old->map_size = ntdb->file->map_size; + ntdb->file->old_mmaps = old; + } else { + munmap(ntdb->file->map_ptr, ntdb->file->map_size); + ntdb->file->map_ptr = NULL; + } + return NTDB_SUCCESS; +} + enum NTDB_ERROR ntdb_mmap(struct ntdb_context *ntdb) { int mmap_flags; @@ -98,11 +129,6 @@ static enum NTDB_ERROR ntdb_normal_oob(struct ntdb_context *ntdb, struct stat st; enum NTDB_ERROR ecode; - /* We can't hold pointers during this: we could unmap! */ - assert(!ntdb->direct_access - || (ntdb->flags & NTDB_NOLOCK) - || ntdb_has_expansion_lock(ntdb)); - if (len + off < len) { if (probe) return NTDB_SUCCESS; @@ -149,7 +175,10 @@ static enum NTDB_ERROR ntdb_normal_oob(struct ntdb_context *ntdb, } /* Unmap, update size, remap */ - ntdb_munmap(ntdb->file); + ecode = ntdb_munmap(ntdb); + if (ecode) { + return ecode; + } ntdb->file->map_size = st.st_size; return ntdb_mmap(ntdb); @@ -418,7 +447,10 @@ static enum NTDB_ERROR ntdb_expand_file(struct ntdb_context *ntdb, } else { /* Unmap before trying to write; old NTDB claimed OpenBSD had * problem with this otherwise. */ - ntdb_munmap(ntdb->file); + ecode = ntdb_munmap(ntdb); + if (ecode) { + return ecode; + } /* If this fails, we try to fill anyway. */ if (ftruncate(ntdb->file->fd, ntdb->file->map_size + addition)) @@ -461,8 +493,9 @@ const void *ntdb_access_read(struct ntdb_context *ntdb, if (convert) { ntdb_convert(ntdb, (void *)ret, len); } - } else - ntdb->direct_access++; + } else { + ntdb->file->direct_count++; + } return ret; } @@ -500,9 +533,9 @@ void *ntdb_access_write(struct ntdb_context *ntdb, ret = hdr + 1; if (convert) ntdb_convert(ntdb, (void *)ret, len); - } else - ntdb->direct_access++; - + } else { + ntdb->file->direct_count++; + } return ret; } @@ -525,8 +558,11 @@ void ntdb_access_release(struct ntdb_context *ntdb, const void *p) hdr = *hp; *hp = hdr->next; ntdb->free_fn(hdr, ntdb->alloc_data); - } else - ntdb->direct_access--; + } else { + if (--ntdb->file->direct_count == 0) { + free_old_mmaps(ntdb); + } + } } enum NTDB_ERROR ntdb_access_commit(struct ntdb_context *ntdb, void *p) @@ -543,7 +579,9 @@ enum NTDB_ERROR ntdb_access_commit(struct ntdb_context *ntdb, void *p) *hp = hdr->next; ntdb->free_fn(hdr, ntdb->alloc_data); } else { - ntdb->direct_access--; + if (--ntdb->file->direct_count == 0) { + free_old_mmaps(ntdb); + } ecode = NTDB_SUCCESS; } |