From: Rusty Russell Date: Thu, 21 Apr 2011 01:46:35 +0000 (+0930) Subject: tdb2: handle non-transaction-page-aligned sizes in recovery. X-Git-Url: https://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=ba7740e689b5791d79b95d2c5345870f9c29fb71 tdb2: handle non-transaction-page-aligned sizes in recovery. tdb1 always makes the tdb a multiple of the transaction page size, tdb2 doesn't. This means that if a transaction hits the exact end of the file, we might need to save off a partial page. So that we don't have to rewrite tdb_recovery_size() too, we simply do a short read and memset the unused section to 0 (to keep valgrind happy). --- diff --git a/ccan/tdb2/transaction.c b/ccan/tdb2/transaction.c index 7a2ebbe9..73ceb962 100644 --- a/ccan/tdb2/transaction.c +++ b/ccan/tdb2/transaction.c @@ -815,6 +815,7 @@ static enum TDB_ERROR transaction_setup_recovery(struct tdb_context *tdb, if (offset >= old_map_size) { continue; } + if (offset + length > tdb->file->map_size) { free(data); return tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR, @@ -829,9 +830,19 @@ static enum TDB_ERROR transaction_setup_recovery(struct tdb_context *tdb, /* the recovery area contains the old data, not the new data, so we have to call the original tdb_read method to get it */ - ecode = methods->tread(tdb, offset, - p + sizeof(offset) + sizeof(length), - length); + if (offset + length > old_map_size) { + /* Short read at EOF, and zero fill. */ + unsigned int len = old_map_size - offset; + ecode = methods->tread(tdb, offset, + p + sizeof(offset) + sizeof(length), + len); + memset(p + sizeof(offset) + sizeof(length) + len, 0, + length - len); + } else { + ecode = methods->tread(tdb, offset, + p + sizeof(offset) + sizeof(length), + length); + } if (ecode != TDB_SUCCESS) { free(data); return ecode;