/*
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;
}
/* 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
*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) {
offset += off;
while (off < length) {
- tdb_len_t len;
+ tdb_len_t len1;
unsigned int samelen;
- len = different(tdb->tdb2.transaction->blocks[i] + off,
+ len1 = different(tdb->tdb2.transaction->blocks[i] + off,
buffer + off, length - off,
- sizeof(offset) + sizeof(len) + 1,
+ sizeof(offset) + sizeof(len1) + 1,
&samelen);
memcpy(p, &offset, sizeof(offset));
- memcpy(p + sizeof(offset), &len, sizeof(len));
- tdb_convert(tdb, p, sizeof(offset) + sizeof(len));
- p += sizeof(offset) + sizeof(len);
- memcpy(p, buffer + off, len);
- p += len;
- off += len + samelen;
- offset += len + samelen;
+ memcpy(p + sizeof(offset), &len1, sizeof(len1));
+ tdb_convert(tdb, p, sizeof(offset) + sizeof(len1));
+ p += sizeof(offset) + sizeof(len1);
+ memcpy(p, buffer + off, len1);
+ p += len1;
+ off += len1 + samelen;
+ offset += len1 + samelen;
}
tdb_access_release(tdb, buffer);
}
/* round up to a multiple of page size. Overallocate, since each
* such allocation forces us to expand the file. */
- rec->max_len
- = (((sizeof(*rec) + rec_length + rec_length / 2)
- + PAGESIZE-1) & ~(PAGESIZE-1))
+ rec->max_len = tdb_expand_adjust(tdb->file->map_size, rec_length);
+
+ /* Round up to a page. */
+ rec->max_len = ((sizeof(*rec) + rec->max_len + PAGESIZE-1)
+ & ~(PAGESIZE-1))
- sizeof(*rec);
+
off = tdb->file->map_size;
/* Restore ->map_size before calling underlying expand_file.
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
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,
recovery);
if (TDB_OFF_IS_ERR(recovery_off)) {
free(recovery);
- return recovery_off;
+ return TDB_OFF_TO_ERR(recovery_off);
}
}
/* 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");
}
/* 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);