From b29ec27e4ad1dcf6121404d6d3a4a288bf30fe6f Mon Sep 17 00:00:00 2001 From: Keith Bostic Date: Wed, 23 Aug 2017 23:00:49 -0400 Subject: WT-3538 Misaligned reads when using the lookaside table and timestamps (#3609) --- src/btree/bt_read.c | 20 ++++++++++++-------- src/cache/cache_las.c | 23 +++++++++++++---------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/btree/bt_read.c b/src/btree/bt_read.c index 0c3cb026421..26ddde8d6ad 100644 --- a/src/btree/bt_read.c +++ b/src/btree/bt_read.c @@ -136,8 +136,9 @@ __las_page_instantiate(WT_SESSION_IMPL *session, WT_CURSOR *cursor; WT_CURSOR_BTREE cbt; WT_DECL_ITEM(current_key); - WT_ITEM las_addr, las_key, las_timestamp, las_value; WT_DECL_RET; + WT_DECL_TIMESTAMP(timestamp) + WT_ITEM las_addr, las_key, las_timestamp, las_value; WT_PAGE *page; WT_UPDATE *first_upd, *last_upd, *upd; size_t incr, total_incr; @@ -154,7 +155,6 @@ __las_page_instantiate(WT_SESSION_IMPL *session, current_recno = recno = WT_RECNO_OOB; session_flags = 0; /* [-Werror=maybe-uninitialized] */ WT_CLEAR(las_key); - WT_CLEAR(las_timestamp); __wt_btcur_init(session, &cbt); __wt_btcur_open(&cbt); @@ -176,6 +176,7 @@ __las_page_instantiate(WT_SESSION_IMPL *session, */ las_addr.data = addr; las_addr.size = addr_size; + las_timestamp.size = 0; cursor->set_key(cursor, read_id, &las_addr, (uint64_t)0, (uint32_t)0, &las_timestamp, &las_key); if ((ret = cursor->search_near(cursor, &exact)) == 0 && exact < 0) @@ -195,13 +196,16 @@ __las_page_instantiate(WT_SESSION_IMPL *session, /* * If the on-page value has become globally visible, this record - * is no longer needed. We clear the las_timestamp structure - * above to avoid reading uninitialized memory here when - * timestamps are disabled (even though it is unused in that - * case). + * is no longer needed. + * + * Copy the timestamp from the cursor to avoid unaligned reads. */ +#ifdef HAVE_TIMESTAMPS + WT_ASSERT(session, las_timestamp.size == WT_TIMESTAMP_SIZE); + memcpy(×tamp, las_timestamp.data, las_timestamp.size); +#endif if (__wt_txn_visible_all( - session, las_txnid, las_timestamp.data)) + session, las_txnid, WT_TIMESTAMP_NULL(×tamp))) continue; /* Allocate the WT_UPDATE structure. */ @@ -213,7 +217,7 @@ __las_page_instantiate(WT_SESSION_IMPL *session, upd->txnid = upd_txnid; #ifdef HAVE_TIMESTAMPS WT_ASSERT(session, las_timestamp.size == WT_TIMESTAMP_SIZE); - __wt_timestamp_set(&upd->timestamp, las_timestamp.data); + memcpy(&upd->timestamp, las_timestamp.data, las_timestamp.size); #endif switch (page->type) { diff --git a/src/cache/cache_las.c b/src/cache/cache_las.c index a118e5d5e41..e1e47b9eecb 100644 --- a/src/cache/cache_las.c +++ b/src/cache/cache_las.c @@ -288,9 +288,10 @@ __wt_las_sweep(WT_SESSION_IMPL *session) { WT_CONNECTION_IMPL *conn; WT_CURSOR *cursor; - WT_ITEM las_addr, las_key, las_timestamp; WT_DECL_RET; + WT_DECL_TIMESTAMP(timestamp) WT_ITEM *key; + WT_ITEM las_addr, las_key, las_timestamp; uint64_t cnt, las_counter, las_txnid, remove_cnt; uint32_t las_id, session_flags; int notused; @@ -300,7 +301,6 @@ __wt_las_sweep(WT_SESSION_IMPL *session) key = &conn->las_sweep_key; remove_cnt = 0; session_flags = 0; /* [-Werror=maybe-uninitialized] */ - WT_CLEAR(las_timestamp); __wt_las_cursor(session, &cursor, &session_flags); @@ -359,6 +359,11 @@ __wt_las_sweep(WT_SESSION_IMPL *session) session, key, key->data, key->size)); } + /* + * Cursor opened overwrite=true: won't return WT_NOTFOUND should + * another thread remove the record before we do, and the cursor + * remains positioned in that case. + */ WT_ERR(cursor->get_key(cursor, &las_id, &las_addr, &las_counter, &las_txnid, &las_timestamp, &las_key)); @@ -366,16 +371,14 @@ __wt_las_sweep(WT_SESSION_IMPL *session) * If the on-page record transaction ID associated with the * record is globally visible, the record can be discarded. * - * Cursor opened overwrite=true: won't return WT_NOTFOUND should - * another thread remove the record before we do, and the cursor - * remains positioned in that case. - * - * We clear the las_timestamp structure above to avoid reading - * uninitialized memory here when timestamps are disabled (even - * though it is unused in that case). + * Copy the timestamp from the cursor to avoid unaligned reads. */ +#ifdef HAVE_TIMESTAMPS + WT_ASSERT(session, las_timestamp.size == WT_TIMESTAMP_SIZE); + memcpy(×tamp, las_timestamp.data, las_timestamp.size); +#endif if (__wt_txn_visible_all( - session, las_txnid, las_timestamp.data)) { + session, las_txnid, WT_TIMESTAMP_NULL(×tamp))) { WT_ERR(cursor->remove(cursor)); ++remove_cnt; } -- cgit v1.2.1