]> git.ozlabs.org Git - ccan/blobdiff - ccan/tdb2/io.c
tdb2: move mmap into struct tdb_file
[ccan] / ccan / tdb2 / io.c
index 7d20f46ad388614eba4cb56a7b9688ea08ee4fcd..7e5dcb73160f4a441e6e978349e04c2bca5cbaa4 100644 (file)
 #include <assert.h>
 #include <ccan/likely/likely.h>
 
-void tdb_munmap(struct tdb_context *tdb)
+void tdb_munmap(struct tdb_file *file)
 {
-       if (tdb->flags & TDB_INTERNAL)
+       if (file->fd == -1)
                return;
 
-       if (tdb->map_ptr) {
-               munmap(tdb->map_ptr, tdb->map_size);
-               tdb->map_ptr = NULL;
+       if (file->map_ptr) {
+               munmap(file->map_ptr, file->map_size);
+               file->map_ptr = NULL;
        }
 }
 
@@ -48,17 +48,17 @@ void tdb_mmap(struct tdb_context *tdb)
        if (tdb->flags & TDB_NOMMAP)
                return;
 
-       tdb->map_ptr = mmap(NULL, tdb->map_size, tdb->mmap_flags,
-                           MAP_SHARED, tdb->fd, 0);
+       tdb->file->map_ptr = mmap(NULL, tdb->file->map_size, tdb->mmap_flags,
+                                 MAP_SHARED, tdb->file->fd, 0);
 
        /*
         * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!!
         */
-       if (tdb->map_ptr == MAP_FAILED) {
-               tdb->map_ptr = NULL;
+       if (tdb->file->map_ptr == MAP_FAILED) {
+               tdb->file->map_ptr = NULL;
                tdb_logerr(tdb, TDB_SUCCESS, TDB_LOG_WARNING,
                           "tdb_mmap failed for size %lld (%s)",
-                          (long long)tdb->map_size, strerror(errno));
+                          (long long)tdb->file->map_size, strerror(errno));
        }
 }
 
@@ -78,7 +78,7 @@ static enum TDB_ERROR tdb_oob(struct tdb_context *tdb, tdb_off_t len,
               || (tdb->flags & TDB_NOLOCK)
               || tdb_has_expansion_lock(tdb));
 
-       if (len <= tdb->map_size)
+       if (len <= tdb->file->map_size)
                return 0;
        if (tdb->flags & TDB_INTERNAL) {
                if (!probe) {
@@ -86,7 +86,7 @@ static enum TDB_ERROR tdb_oob(struct tdb_context *tdb, tdb_off_t len,
                                 "tdb_oob len %lld beyond internal"
                                 " malloc size %lld",
                                 (long long)len,
-                                (long long)tdb->map_size);
+                                (long long)tdb->file->map_size);
                }
                return TDB_ERR_IO;
        }
@@ -96,7 +96,7 @@ static enum TDB_ERROR tdb_oob(struct tdb_context *tdb, tdb_off_t len,
                return ecode;
        }
 
-       if (fstat(tdb->fd, &st) != 0) {
+       if (fstat(tdb->file->fd, &st) != 0) {
                tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
                           "Failed to fstat file: %s", strerror(errno));
                tdb_unlock_expand(tdb, F_RDLCK);
@@ -115,9 +115,9 @@ static enum TDB_ERROR tdb_oob(struct tdb_context *tdb, tdb_off_t len,
        }
 
        /* Unmap, update size, remap */
-       tdb_munmap(tdb);
+       tdb_munmap(tdb->file);
 
-       tdb->map_size = st.st_size;
+       tdb->file->map_size = st.st_size;
        tdb_mmap(tdb);
        return TDB_SUCCESS;
 }
@@ -133,6 +133,7 @@ void *tdb_convert(const struct tdb_context *tdb, void *buf, tdb_len_t size)
        return buf;
 }
 
+/* Return first non-zero offset in offset array, or end, or -ve error. */
 /* FIXME: Return the off? */
 uint64_t tdb_find_nonzero_off(struct tdb_context *tdb,
                              tdb_off_t base, uint64_t start, uint64_t end)
@@ -144,8 +145,7 @@ uint64_t tdb_find_nonzero_off(struct tdb_context *tdb,
        val = tdb_access_read(tdb, base + start * sizeof(tdb_off_t),
                              (end - start) * sizeof(tdb_off_t), false);
        if (TDB_PTR_IS_ERR(val)) {
-               tdb->ecode = TDB_PTR_ERR(val);
-               return end;
+               return TDB_PTR_ERR(val);
        }
 
        for (i = 0; i < (end - start); i++) {
@@ -156,7 +156,7 @@ uint64_t tdb_find_nonzero_off(struct tdb_context *tdb,
        return start + i;
 }
 
-/* Return first zero offset in num offset array, or num. */
+/* Return first zero offset in num offset array, or num, or -ve error. */
 uint64_t tdb_find_zero_off(struct tdb_context *tdb, tdb_off_t off,
                           uint64_t num)
 {
@@ -166,8 +166,7 @@ uint64_t tdb_find_zero_off(struct tdb_context *tdb, tdb_off_t off,
        /* Zero vs non-zero is the same unconverted: minor optimization. */
        val = tdb_access_read(tdb, off, num * sizeof(tdb_off_t), false);
        if (TDB_PTR_IS_ERR(val)) {
-               tdb->ecode = TDB_PTR_ERR(val);
-               return num;
+               return TDB_PTR_ERR(val);
        }
 
        for (i = 0; i < num; i++) {
@@ -213,8 +212,7 @@ tdb_off_t tdb_read_off(struct tdb_context *tdb, tdb_off_t off)
                tdb_off_t *p = tdb->methods->direct(tdb, off, sizeof(*p),
                                                    false);
                if (TDB_PTR_IS_ERR(p)) {
-                       tdb->ecode = TDB_PTR_ERR(p);
-                       return TDB_OFF_ERR;
+                       return TDB_PTR_ERR(p);
                }
                if (p)
                        return *p;
@@ -222,8 +220,7 @@ tdb_off_t tdb_read_off(struct tdb_context *tdb, tdb_off_t off)
 
        ecode = tdb_read_convert(tdb, off, &ret, sizeof(ret));
        if (ecode != TDB_SUCCESS) {
-               tdb->ecode = ecode;
-               return TDB_OFF_ERR;
+               return ecode;
        }
        return ret;
 }
@@ -239,22 +236,17 @@ static enum TDB_ERROR tdb_write(struct tdb_context *tdb, tdb_off_t off,
                                  "Write to read-only database");
        }
 
-       /* FIXME: Bogus optimization? */
-       if (len == 0) {
-               return TDB_SUCCESS;
-       }
-
        ecode = tdb->methods->oob(tdb, off + len, 0);
        if (ecode != TDB_SUCCESS) {
                return ecode;
        }
 
-       if (tdb->map_ptr) {
-               memcpy(off + (char *)tdb->map_ptr, buf, len);
+       if (tdb->file->map_ptr) {
+               memcpy(off + (char *)tdb->file->map_ptr, buf, len);
        } else {
                ssize_t ret;
-               ret = pwrite(tdb->fd, buf, len, off);
-               if (ret < len) {
+               ret = pwrite(tdb->file->fd, buf, len, off);
+               if (ret != len) {
                        /* This shouldn't happen: we avoid sparse files. */
                        if (ret >= 0)
                                errno = ENOSPC;
@@ -279,17 +271,17 @@ static enum TDB_ERROR tdb_read(struct tdb_context *tdb, tdb_off_t off,
                return ecode;
        }
 
-       if (tdb->map_ptr) {
-               memcpy(buf, off + (char *)tdb->map_ptr, len);
+       if (tdb->file->map_ptr) {
+               memcpy(buf, off + (char *)tdb->file->map_ptr, len);
        } else {
-               ssize_t r = pread(tdb->fd, buf, len, off);
+               ssize_t r = pread(tdb->file->fd, buf, len, off);
                if (r != len) {
                        return tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
                                          "tdb_read failed with %zi at %zu "
                                          "len=%zu (%s) map_size=%zu",
                                          r, (size_t)off, (size_t)len,
                                          strerror(errno),
-                                         (size_t)tdb->map_size);
+                                         (size_t)tdb->file->map_size);
                }
        }
        return TDB_SUCCESS;
@@ -382,8 +374,8 @@ static enum TDB_ERROR fill(struct tdb_context *tdb,
 {
        while (len) {
                size_t n = len > size ? size : len;
-               ssize_t ret = pwrite(tdb->fd, buf, n, off);
-               if (ret < n) {
+               ssize_t ret = pwrite(tdb->file->fd, buf, n, off);
+               if (ret != n) {
                        if (ret >= 0)
                                errno = ENOSPC;
 
@@ -413,30 +405,32 @@ static enum TDB_ERROR tdb_expand_file(struct tdb_context *tdb,
        }
 
        if (tdb->flags & TDB_INTERNAL) {
-               char *new = realloc(tdb->map_ptr, tdb->map_size + addition);
+               char *new = realloc(tdb->file->map_ptr,
+                                   tdb->file->map_size + addition);
                if (!new) {
                        return tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
                                          "No memory to expand database");
                }
-               tdb->map_ptr = new;
-               tdb->map_size += addition;
+               tdb->file->map_ptr = new;
+               tdb->file->map_size += addition;
        } else {
                /* Unmap before trying to write; old TDB claimed OpenBSD had
                 * problem with this otherwise. */
-               tdb_munmap(tdb);
+               tdb_munmap(tdb->file);
 
                /* If this fails, we try to fill anyway. */
-               if (ftruncate(tdb->fd, tdb->map_size + addition))
+               if (ftruncate(tdb->file->fd, tdb->file->map_size + addition))
                        ;
 
                /* now fill the file with something. This ensures that the
                   file isn't sparse, which would be very bad if we ran out of
                   disk. This must be done with write, not via mmap */
                memset(buf, 0x43, sizeof(buf));
-               ecode = fill(tdb, buf, sizeof(buf), tdb->map_size, addition);
+               ecode = fill(tdb, buf, sizeof(buf), tdb->file->map_size,
+                            addition);
                if (ecode != TDB_SUCCESS)
                        return ecode;
-               tdb->map_size += addition;
+               tdb->file->map_size += addition;
                tdb_mmap(tdb);
        }
        return TDB_SUCCESS;
@@ -560,13 +554,13 @@ static void *tdb_direct(struct tdb_context *tdb, tdb_off_t off, size_t len,
 {
        enum TDB_ERROR ecode;
 
-       if (unlikely(!tdb->map_ptr))
+       if (unlikely(!tdb->file->map_ptr))
                return NULL;
 
        ecode = tdb_oob(tdb, off + len, true);
        if (unlikely(ecode != TDB_SUCCESS))
                return TDB_ERR_PTR(ecode);
-       return (char *)tdb->map_ptr + off;
+       return (char *)tdb->file->map_ptr + off;
 }
 
 void add_stat_(struct tdb_context *tdb, uint64_t *s, size_t val)