]> git.ozlabs.org Git - ccan/blobdiff - ccan/tdb2/transaction.c
tdb2: careful on wrap.
[ccan] / ccan / tdb2 / transaction.c
index a5f3c543e8194592f70e368d1f624b8833799a83..70e664fc2d60e5fe36bda442607fbdfba04677ff 100644 (file)
@@ -203,7 +203,7 @@ static enum TDB_ERROR transaction_write(struct tdb_context *tdb, tdb_off_t off,
                tdb_len_t len2 = PAGESIZE - (off % PAGESIZE);
                ecode = transaction_write(tdb, off, buf, len2);
                if (ecode != TDB_SUCCESS) {
-                       return -1;
+                       return ecode;
                }
                len -= len2;
                off += len2;
@@ -345,16 +345,16 @@ static void transaction_write_existing(struct tdb_context *tdb, tdb_off_t off,
 /*
   out of bounds check during a transaction
 */
-static enum TDB_ERROR transaction_oob(struct tdb_context *tdb, tdb_off_t len,
-                                     bool probe)
+static enum TDB_ERROR transaction_oob(struct tdb_context *tdb,
+                                     tdb_off_t off, tdb_len_t len, bool probe)
 {
-       if (len <= tdb->file->map_size || probe) {
+       if ((off + len >= off && off + len <= tdb->file->map_size) || probe) {
                return TDB_SUCCESS;
        }
 
        tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
                   "tdb_oob len %lld beyond transaction size %lld",
-                  (long long)len,
+                  (long long)(off + len),
                   (long long)tdb->file->map_size);
        return TDB_ERR_IO;
 }
@@ -521,6 +521,12 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
 {
        enum TDB_ERROR ecode;
 
+       if (tdb->flags & TDB_VERSION1) {
+               if (tdb1_transaction_start(tdb) == -1)
+                       return tdb->last_error;
+               return TDB_SUCCESS;
+       }
+
        tdb->stats.transactions++;
        /* some sanity checks */
        if (tdb->flags & TDB_INTERNAL) {
@@ -595,7 +601,7 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
 
        /* make sure we know about any file expansions already done by
           anyone else */
-       tdb->tdb2.io->oob(tdb, tdb->file->map_size + 1, true);
+       tdb->tdb2.io->oob(tdb, tdb->file->map_size, 1, true);
        tdb->tdb2.transaction->old_map_size = tdb->file->map_size;
 
        /* finally hook the io methods, replacing them with
@@ -617,6 +623,10 @@ fail_allrecord_lock:
 */
 void tdb_transaction_cancel(struct tdb_context *tdb)
 {
+       if (tdb->flags & TDB_VERSION1) {
+               tdb1_transaction_cancel(tdb);
+               return;
+       }
        tdb->stats.transaction_cancel++;
        _tdb_transaction_cancel(tdb);
 }
@@ -658,7 +668,7 @@ static enum TDB_ERROR tdb_recovery_area(struct tdb_context *tdb,
        *recovery_offset = tdb_read_off(tdb,
                                        offsetof(struct tdb_header, recovery));
        if (TDB_OFF_IS_ERR(*recovery_offset)) {
-               return *recovery_offset;
+               return TDB_OFF_TO_ERR(*recovery_offset);
        }
 
        if (*recovery_offset == 0) {
@@ -842,9 +852,10 @@ static tdb_off_t create_recovery_area(struct tdb_context *tdb,
        tdb->stats.transaction_expand_file++;
        ecode = methods->expand_file(tdb, addition);
        if (ecode != TDB_SUCCESS) {
-               return tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
-                                 "tdb_recovery_allocate:"
-                                 " failed to create recovery area");
+               tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
+                          "tdb_recovery_allocate:"
+                          " failed to create recovery area");
+               return TDB_ERR_TO_OFF(ecode);
        }
 
        /* we have to reset the old map size so that we don't try to
@@ -859,9 +870,10 @@ static tdb_off_t create_recovery_area(struct tdb_context *tdb,
        ecode = methods->twrite(tdb, offsetof(struct tdb_header, recovery),
                                &recovery_off, sizeof(tdb_off_t));
        if (ecode != TDB_SUCCESS) {
-               return tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
-                                 "tdb_recovery_allocate:"
-                                 " failed to write recovery head");
+               tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
+                          "tdb_recovery_allocate:"
+                          " failed to write recovery head");
+               return TDB_ERR_TO_OFF(ecode);
        }
        transaction_write_existing(tdb, offsetof(struct tdb_header, recovery),
                                   &recovery_off,
@@ -918,7 +930,7 @@ static enum TDB_ERROR transaction_setup_recovery(struct tdb_context *tdb)
                                                    recovery);
                if (TDB_OFF_IS_ERR(recovery_off)) {
                        free(recovery);
-                       return recovery_off;
+                       return TDB_OFF_TO_ERR(recovery_off);
                }
        }
 
@@ -1052,7 +1064,12 @@ static enum TDB_ERROR _tdb_transaction_prepare_commit(struct tdb_context *tdb)
 */
 enum TDB_ERROR tdb_transaction_prepare_commit(struct tdb_context *tdb)
 {
-       return _tdb_transaction_prepare_commit(tdb);
+       if (tdb->flags & TDB_VERSION1) {
+               if (tdb1_transaction_prepare_commit(tdb) == -1)
+                       return tdb->last_error;
+               return TDB_SUCCESS;
+       }
+       return tdb->last_error = _tdb_transaction_prepare_commit(tdb);
 }
 
 /*
@@ -1064,6 +1081,12 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb)
        int i;
        enum TDB_ERROR ecode;
 
+       if (tdb->flags & TDB_VERSION1) {
+               if (tdb1_transaction_commit(tdb) == -1)
+                       return tdb->last_error;
+               return TDB_SUCCESS;
+       }
+
        if (tdb->tdb2.transaction == NULL) {
                return tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL,
                                                    TDB_LOG_USE_ERROR,
@@ -1173,7 +1196,8 @@ enum TDB_ERROR tdb_transaction_recover(struct tdb_context *tdb)
        /* find the recovery area */
        recovery_head = tdb_read_off(tdb, offsetof(struct tdb_header,recovery));
        if (TDB_OFF_IS_ERR(recovery_head)) {
-               return tdb_logerr(tdb, recovery_head, TDB_LOG_ERROR,
+               ecode = TDB_OFF_TO_ERR(recovery_head);
+               return tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
                                  "tdb_transaction_recover:"
                                  " failed to read recovery head");
        }
@@ -1309,7 +1333,7 @@ tdb_bool_err tdb_needs_recovery(struct tdb_context *tdb)
        /* read the recovery record */
        ecode = tdb_read_convert(tdb, recovery_head, &rec, sizeof(rec));
        if (ecode != TDB_SUCCESS) {
-               return ecode;
+               return TDB_ERR_TO_OFF(ecode);
        }
 
        return (rec.magic == TDB_RECOVERY_MAGIC);