Skip to content

Commit 9f89b94

Browse files
committed
MDEV-12358 Work around what looks like a bug in GCC 7.1.0
The parameter thr of the function btr_cur_optimistic_insert() is not declared as nonnull, but GCC 7.1.0 with -O3 is wrongly optimizing away the first part of the condition UNIV_UNLIKELY(thr && thr_get_trx(thr)->fake_changes) when the function is being called by row_merge_insert_index_tuples() with thr==NULL. The fake_changes is an XtraDB addition. This GCC bug only appears to have an impact on XtraDB, not InnoDB. We work around the problem by not attempting to dereference thr when both BTR_NO_LOCKING_FLAG and BTR_NO_UNDO_LOG_FLAG are set in the flags. Probably BTR_NO_LOCKING_FLAG alone should suffice. btr_cur_optimistic_insert(), btr_cur_pessimistic_insert(), btr_cur_pessimistic_update(): Correct comments that disagree with usage and with nonnull attributes. No other parameter than thr can actually be NULL. row_ins_duplicate_error_in_clust(): Remove an unused parameter. innobase_is_fake_change(): Unused function; remove. ibuf_insert_low(), row_log_table_apply(), row_log_apply(), row_undo_mod_clust_low(): Because we will be passing BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG in the flags, the trx->fake_changes flag will be treated as false, which is the right thing to do at these low-level operations (change buffer merge, ALTER TABLE…LOCK=NONE, or ROLLBACK). This might be fixing actual XtraDB bugs. Other callers that pass these two flags are also passing thr=NULL, implying fake_changes=false. (Some callers in ROLLBACK are passing BTR_NO_LOCKING_FLAG and a nonnull thr. In these callers, fake_changes better be false, to avoid corruption.)
1 parent e22d86a commit 9f89b94

File tree

9 files changed

+86
-87
lines changed

9 files changed

+86
-87
lines changed

storage/innobase/btr/btr0cur.cc

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
44
Copyright (c) 2008, Google Inc.
55
Copyright (c) 2012, Facebook Inc.
6+
Copyright (c) 2017, MariaDB Corporation.
67
78
Portions of this file contain modifications contributed and copyrighted by
89
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -1223,15 +1224,17 @@ btr_cur_optimistic_insert(
12231224
btr_cur_t* cursor, /*!< in: cursor on page after which to insert;
12241225
cursor stays valid */
12251226
ulint** offsets,/*!< out: offsets on *rec */
1226-
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
1227+
mem_heap_t** heap, /*!< in/out: pointer to memory heap */
12271228
dtuple_t* entry, /*!< in/out: entry to insert */
12281229
rec_t** rec, /*!< out: pointer to inserted record if
12291230
succeed */
12301231
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
1231-
be stored externally by the caller, or
1232-
NULL */
1232+
be stored externally by the caller */
12331233
ulint n_ext, /*!< in: number of externally stored columns */
1234-
que_thr_t* thr, /*!< in: query thread or NULL */
1234+
que_thr_t* thr, /*!< in/out: query thread; can be NULL if
1235+
!(~flags
1236+
& (BTR_NO_LOCKING_FLAG
1237+
| BTR_NO_UNDO_LOG_FLAG)) */
12351238
mtr_t* mtr) /*!< in/out: mini-transaction;
12361239
if this function returns DB_SUCCESS on
12371240
a leaf page of a secondary index in a
@@ -1252,6 +1255,7 @@ btr_cur_optimistic_insert(
12521255
ulint rec_size;
12531256
dberr_t err;
12541257

1258+
ut_ad(thr || !(~flags & (BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG)));
12551259
*big_rec = NULL;
12561260

12571261
block = btr_cur_get_block(cursor);
@@ -1510,15 +1514,17 @@ btr_cur_pessimistic_insert(
15101514
cursor stays valid */
15111515
ulint** offsets,/*!< out: offsets on *rec */
15121516
mem_heap_t** heap, /*!< in/out: pointer to memory heap
1513-
that can be emptied, or NULL */
1517+
that can be emptied */
15141518
dtuple_t* entry, /*!< in/out: entry to insert */
15151519
rec_t** rec, /*!< out: pointer to inserted record if
15161520
succeed */
15171521
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
1518-
be stored externally by the caller, or
1519-
NULL */
1522+
be stored externally by the caller */
15201523
ulint n_ext, /*!< in: number of externally stored columns */
1521-
que_thr_t* thr, /*!< in: query thread or NULL */
1524+
que_thr_t* thr, /*!< in/out: query thread; can be NULL if
1525+
!(~flags
1526+
& (BTR_NO_LOCKING_FLAG
1527+
| BTR_NO_UNDO_LOG_FLAG)) */
15221528
mtr_t* mtr) /*!< in/out: mini-transaction */
15231529
{
15241530
dict_index_t* index = cursor->index;
@@ -1530,6 +1536,7 @@ btr_cur_pessimistic_insert(
15301536
ulint n_reserved = 0;
15311537

15321538
ut_ad(dtuple_check_typed(entry));
1539+
ut_ad(thr || !(~flags & (BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG)));
15331540

15341541
*big_rec = NULL;
15351542

@@ -2426,12 +2433,12 @@ btr_cur_pessimistic_update(
24262433
ulint** offsets,/*!< out: offsets on cursor->page_cur.rec */
24272434
mem_heap_t** offsets_heap,
24282435
/*!< in/out: pointer to memory heap
2429-
that can be emptied, or NULL */
2436+
that can be emptied */
24302437
mem_heap_t* entry_heap,
24312438
/*!< in/out: memory heap for allocating
24322439
big_rec and the index tuple */
24332440
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
2434-
be stored externally by the caller, or NULL */
2441+
be stored externally by the caller */
24352442
const upd_t* update, /*!< in: update vector; this is allowed also
24362443
contain trx id and roll ptr fields, but
24372444
the values in update vector have no effect */

storage/innobase/ibuf/ibuf0ibuf.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
4+
Copyright (c) 2017, MariaDB Corporation.
45
56
This program is free software; you can redistribute it and/or modify it under
67
the terms of the GNU General Public License as published by the Free Software
@@ -3662,7 +3663,7 @@ ibuf_insert_low(
36623663

36633664
if (mode == BTR_MODIFY_PREV) {
36643665
err = btr_cur_optimistic_insert(
3665-
BTR_NO_LOCKING_FLAG,
3666+
BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG,
36663667
cursor, &offsets, &offsets_heap,
36673668
ibuf_entry, &ins_rec,
36683669
&dummy_big_rec, 0, thr, &mtr);

storage/innobase/include/btr0cur.h

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
4+
Copyright (c) 2017, MariaDB Corporation.
45
56
This program is free software; you can redistribute it and/or modify it under
67
the terms of the GNU General Public License as published by the Free Software
@@ -220,15 +221,17 @@ btr_cur_optimistic_insert(
220221
btr_cur_t* cursor, /*!< in: cursor on page after which to insert;
221222
cursor stays valid */
222223
ulint** offsets,/*!< out: offsets on *rec */
223-
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
224+
mem_heap_t** heap, /*!< in/out: pointer to memory heap */
224225
dtuple_t* entry, /*!< in/out: entry to insert */
225226
rec_t** rec, /*!< out: pointer to inserted record if
226227
succeed */
227228
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
228-
be stored externally by the caller, or
229-
NULL */
229+
be stored externally by the caller */
230230
ulint n_ext, /*!< in: number of externally stored columns */
231-
que_thr_t* thr, /*!< in: query thread or NULL */
231+
que_thr_t* thr, /*!< in/out: query thread; can be NULL if
232+
!(~flags
233+
& (BTR_NO_LOCKING_FLAG
234+
| BTR_NO_UNDO_LOG_FLAG)) */
232235
mtr_t* mtr) /*!< in/out: mini-transaction;
233236
if this function returns DB_SUCCESS on
234237
a leaf page of a secondary index in a
@@ -256,15 +259,17 @@ btr_cur_pessimistic_insert(
256259
cursor stays valid */
257260
ulint** offsets,/*!< out: offsets on *rec */
258261
mem_heap_t** heap, /*!< in/out: pointer to memory heap
259-
that can be emptied, or NULL */
262+
that can be emptied */
260263
dtuple_t* entry, /*!< in/out: entry to insert */
261264
rec_t** rec, /*!< out: pointer to inserted record if
262265
succeed */
263266
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
264-
be stored externally by the caller, or
265-
NULL */
267+
be stored externally by the caller */
266268
ulint n_ext, /*!< in: number of externally stored columns */
267-
que_thr_t* thr, /*!< in: query thread or NULL */
269+
que_thr_t* thr, /*!< in/out: query thread; can be NULL if
270+
!(~flags
271+
& (BTR_NO_LOCKING_FLAG
272+
| BTR_NO_UNDO_LOG_FLAG)) */
268273
mtr_t* mtr) /*!< in/out: mini-transaction */
269274
MY_ATTRIBUTE((nonnull(2,3,4,5,6,7,10), warn_unused_result));
270275
/*************************************************************//**
@@ -390,12 +395,12 @@ btr_cur_pessimistic_update(
390395
ulint** offsets,/*!< out: offsets on cursor->page_cur.rec */
391396
mem_heap_t** offsets_heap,
392397
/*!< in/out: pointer to memory heap
393-
that can be emptied, or NULL */
398+
that can be emptied */
394399
mem_heap_t* entry_heap,
395400
/*!< in/out: memory heap for allocating
396401
big_rec and the index tuple */
397402
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
398-
be stored externally by the caller, or NULL */
403+
be stored externally by the caller */
399404
const upd_t* update, /*!< in: update vector; this is allowed also
400405
contain trx id and roll ptr fields, but
401406
the values in update vector have no effect */

storage/innobase/row/row0ins.cc

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4+
Copyright (c) 2017, MariaDB Corporation.
45
56
This program is free software; you can redistribute it and/or modify it under
67
the terms of the GNU General Public License as published by the Free Software
@@ -2121,14 +2122,10 @@ for a clustered index!
21212122
@retval DB_SUCCESS if no error
21222123
@retval DB_DUPLICATE_KEY if error,
21232124
@retval DB_LOCK_WAIT if we have to wait for a lock on a possible duplicate
2124-
record
2125-
@retval DB_SUCCESS_LOCKED_REC if an exact match of the record was found
2126-
in online table rebuild (flags & (BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG)) */
2125+
record */
21272126
static MY_ATTRIBUTE((nonnull, warn_unused_result))
21282127
dberr_t
21292128
row_ins_duplicate_error_in_clust(
2130-
/*=============================*/
2131-
ulint flags, /*!< in: undo logging and locking flags */
21322129
btr_cur_t* cursor, /*!< in: B-tree cursor */
21332130
const dtuple_t* entry, /*!< in: entry to insert */
21342131
que_thr_t* thr, /*!< in: query thread */
@@ -2386,7 +2383,7 @@ row_ins_clust_index_entry_low(
23862383
DB_LOCK_WAIT */
23872384

23882385
err = row_ins_duplicate_error_in_clust(
2389-
flags, &cursor, entry, thr, &mtr);
2386+
&cursor, entry, thr, &mtr);
23902387
}
23912388

23922389
if (err != DB_SUCCESS) {

storage/xtradb/btr/btr0cur.cc

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
44
Copyright (c) 2008, Google Inc.
55
Copyright (c) 2012, Facebook Inc.
6+
Copyright (c) 2017, MariaDB Corporation.
67
78
Portions of this file contain modifications contributed and copyrighted by
89
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -1328,15 +1329,17 @@ btr_cur_optimistic_insert(
13281329
btr_cur_t* cursor, /*!< in: cursor on page after which to insert;
13291330
cursor stays valid */
13301331
ulint** offsets,/*!< out: offsets on *rec */
1331-
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
1332+
mem_heap_t** heap, /*!< in/out: pointer to memory heap */
13321333
dtuple_t* entry, /*!< in/out: entry to insert */
13331334
rec_t** rec, /*!< out: pointer to inserted record if
13341335
succeed */
13351336
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
1336-
be stored externally by the caller, or
1337-
NULL */
1337+
be stored externally by the caller */
13381338
ulint n_ext, /*!< in: number of externally stored columns */
1339-
que_thr_t* thr, /*!< in: query thread or NULL */
1339+
que_thr_t* thr, /*!< in/out: query thread; can be NULL if
1340+
!(~flags
1341+
& (BTR_NO_LOCKING_FLAG
1342+
| BTR_NO_UNDO_LOG_FLAG)) */
13401343
mtr_t* mtr) /*!< in/out: mini-transaction;
13411344
if this function returns DB_SUCCESS on
13421345
a leaf page of a secondary index in a
@@ -1357,6 +1360,7 @@ btr_cur_optimistic_insert(
13571360
ulint rec_size;
13581361
dberr_t err;
13591362

1363+
ut_ad(thr || !(~flags & (BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG)));
13601364
*big_rec = NULL;
13611365

13621366
block = btr_cur_get_block(cursor);
@@ -1366,7 +1370,10 @@ btr_cur_optimistic_insert(
13661370
page = buf_block_get_frame(block);
13671371
index = cursor->index;
13681372

1369-
ut_ad((thr && thr_get_trx(thr)->fake_changes)
1373+
const bool fake_changes = (~flags & (BTR_NO_LOCKING_FLAG
1374+
| BTR_NO_UNDO_LOG_FLAG))
1375+
&& thr_get_trx(thr)->fake_changes;
1376+
ut_ad(fake_changes
13701377
|| mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
13711378
ut_ad(!dict_index_is_online_ddl(index)
13721379
|| dict_index_is_clust(index)
@@ -1507,7 +1514,7 @@ btr_cur_optimistic_insert(
15071514
goto fail_err;
15081515
}
15091516

1510-
if (UNIV_UNLIKELY(thr && thr_get_trx(thr)->fake_changes)) {
1517+
if (UNIV_UNLIKELY(fake_changes)) {
15111518
/* skip CHANGE, LOG */
15121519
*big_rec = big_rec_vec;
15131520
return(err); /* == DB_SUCCESS */
@@ -1625,15 +1632,17 @@ btr_cur_pessimistic_insert(
16251632
cursor stays valid */
16261633
ulint** offsets,/*!< out: offsets on *rec */
16271634
mem_heap_t** heap, /*!< in/out: pointer to memory heap
1628-
that can be emptied, or NULL */
1635+
that can be emptied */
16291636
dtuple_t* entry, /*!< in/out: entry to insert */
16301637
rec_t** rec, /*!< out: pointer to inserted record if
16311638
succeed */
16321639
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
1633-
be stored externally by the caller, or
1634-
NULL */
1640+
be stored externally by the caller */
16351641
ulint n_ext, /*!< in: number of externally stored columns */
1636-
que_thr_t* thr, /*!< in: query thread or NULL */
1642+
que_thr_t* thr, /*!< in/out: query thread; can be NULL if
1643+
!(~flags
1644+
& (BTR_NO_LOCKING_FLAG
1645+
| BTR_NO_UNDO_LOG_FLAG)) */
16371646
mtr_t* mtr) /*!< in/out: mini-transaction */
16381647
{
16391648
dict_index_t* index = cursor->index;
@@ -1645,13 +1654,17 @@ btr_cur_pessimistic_insert(
16451654
ulint n_reserved = 0;
16461655

16471656
ut_ad(dtuple_check_typed(entry));
1657+
ut_ad(thr || !(~flags & (BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG)));
16481658

16491659
*big_rec = NULL;
16501660

1651-
ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr,
1661+
const bool fake_changes = (~flags & (BTR_NO_LOCKING_FLAG
1662+
| BTR_NO_UNDO_LOG_FLAG))
1663+
&& thr_get_trx(thr)->fake_changes;
1664+
ut_ad(fake_changes || mtr_memo_contains(mtr,
16521665
dict_index_get_lock(btr_cur_get_index(cursor)),
16531666
MTR_MEMO_X_LOCK));
1654-
ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, btr_cur_get_block(cursor),
1667+
ut_ad(fake_changes || mtr_memo_contains(mtr, btr_cur_get_block(cursor),
16551668
MTR_MEMO_PAGE_X_FIX));
16561669
ut_ad(!dict_index_is_online_ddl(index)
16571670
|| dict_index_is_clust(index)
@@ -1712,7 +1725,7 @@ btr_cur_pessimistic_insert(
17121725
}
17131726
}
17141727

1715-
if (UNIV_UNLIKELY(thr && thr_get_trx(thr)->fake_changes)) {
1728+
if (UNIV_UNLIKELY(fake_changes)) {
17161729
/* skip CHANGE, LOG */
17171730
if (n_reserved > 0) {
17181731
fil_space_release_free_extents(index->space,
@@ -1803,7 +1816,7 @@ btr_cur_upd_lock_and_undo(
18031816

18041817
ut_ad((thr != NULL) || (flags & BTR_NO_LOCKING_FLAG));
18051818

1806-
if (UNIV_UNLIKELY(thr && thr_get_trx(thr)->fake_changes)) {
1819+
if (!(flags & BTR_NO_LOCKING_FLAG) && thr_get_trx(thr)->fake_changes) {
18071820
/* skip LOCK, UNDO */
18081821
return(DB_SUCCESS);
18091822
}
@@ -2582,12 +2595,12 @@ btr_cur_pessimistic_update(
25822595
ulint** offsets,/*!< out: offsets on cursor->page_cur.rec */
25832596
mem_heap_t** offsets_heap,
25842597
/*!< in/out: pointer to memory heap
2585-
that can be emptied, or NULL */
2598+
that can be emptied */
25862599
mem_heap_t* entry_heap,
25872600
/*!< in/out: memory heap for allocating
25882601
big_rec and the index tuple */
25892602
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
2590-
be stored externally by the caller, or NULL */
2603+
be stored externally by the caller */
25912604
const upd_t* update, /*!< in: update vector; this is allowed also
25922605
contain trx id and roll ptr fields, but
25932606
the values in update vector have no effect */

storage/xtradb/handler/ha_innodb.cc

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -769,17 +769,6 @@ innobase_purge_changed_page_bitmaps(
769769
ulonglong lsn) __attribute__((unused)); /*!< in: LSN to purge files up to */
770770

771771

772-
/*****************************************************************//**
773-
Check whether this is a fake change transaction.
774-
@return TRUE if a fake change transaction */
775-
static
776-
my_bool
777-
innobase_is_fake_change(
778-
/*====================*/
779-
handlerton *hton, /*!< in: InnoDB handlerton */
780-
THD* thd) __attribute__((unused)); /*!< in: MySQL thread handle of the user for
781-
whom the transaction is being committed */
782-
783772
/** Get the list of foreign keys referencing a specified table
784773
table.
785774
@param thd The thread handle
@@ -4242,22 +4231,6 @@ innobase_purge_changed_page_bitmaps(
42424231
return (my_bool)log_online_purge_changed_page_bitmaps(lsn);
42434232
}
42444233

4245-
/*****************************************************************//**
4246-
Check whether this is a fake change transaction.
4247-
@return TRUE if a fake change transaction */
4248-
static
4249-
my_bool
4250-
innobase_is_fake_change(
4251-
/*====================*/
4252-
handlerton *hton MY_ATTRIBUTE((unused)),
4253-
/*!< in: InnoDB handlerton */
4254-
THD* thd) /*!< in: MySQL thread handle of the user for
4255-
whom the transaction is being committed */
4256-
{
4257-
trx_t* trx = check_trx_exists(thd);
4258-
return UNIV_UNLIKELY(trx->fake_changes);
4259-
}
4260-
42614234
/*****************************************************************//**
42624235
Commits a transaction in an InnoDB database. */
42634236
static

storage/xtradb/ibuf/ibuf0ibuf.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
4+
Copyright (c) 2017, MariaDB Corporation.
45
56
This program is free software; you can redistribute it and/or modify it under
67
the terms of the GNU General Public License as published by the Free Software
@@ -3704,7 +3705,7 @@ ibuf_insert_low(
37043705

37053706
if (mode == BTR_MODIFY_PREV) {
37063707
err = btr_cur_optimistic_insert(
3707-
BTR_NO_LOCKING_FLAG,
3708+
BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG,
37083709
cursor, &offsets, &offsets_heap,
37093710
ibuf_entry, &ins_rec,
37103711
&dummy_big_rec, 0, thr, &mtr);

0 commit comments

Comments
 (0)