Skip to content

Commit 1cda462

Browse files
committed
Merge 10.3 into 10.4
2 parents c9cf6b1 + a7dd7c8 commit 1cda462

File tree

6 files changed

+95
-96
lines changed

6 files changed

+95
-96
lines changed

include/my_atomic_wrapper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ template <typename Type> class Atomic_relaxed
4848
{ return m.fetch_add(i, o); }
4949
Type fetch_sub(const Type i, std::memory_order o= std::memory_order_relaxed)
5050
{ return m.fetch_sub(i, o); }
51+
Type fetch_xor(const Type i, std::memory_order o= std::memory_order_relaxed)
52+
{ return m.fetch_xor(i, o); }
5153
bool compare_exchange_strong(Type& i1, const Type i2,
5254
std::memory_order o1= std::memory_order_relaxed,
5355
std::memory_order o2= std::memory_order_relaxed)

storage/innobase/fil/fil0crypt.cc

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,12 +1617,15 @@ inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space,
16171617
}
16181618
}
16191619

1620-
if (it == end)
1621-
return NULL;
1620+
while (it != end)
1621+
{
1622+
space= &*it;
1623+
if (space->acquire())
1624+
return space;
1625+
while (++it != end && (!UT_LIST_GET_LEN(it->chain) || it->is_stopping()));
1626+
}
16221627

1623-
space= &*it;
1624-
space->acquire();
1625-
return space;
1628+
return NULL;
16261629
}
16271630

16281631
/** Return the next tablespace.
@@ -1644,12 +1647,14 @@ static fil_space_t *fil_space_next(fil_space_t *space, bool recheck,
16441647
space= UT_LIST_GET_FIRST(fil_system.space_list);
16451648
/* We can trust that space is not NULL because at least the
16461649
system tablespace is always present and loaded first. */
1647-
space->acquire();
1650+
if (!space->acquire())
1651+
goto next;
16481652
}
16491653
else
16501654
{
16511655
/* Move on to the next fil_space_t */
16521656
space->release();
1657+
next:
16531658
space= UT_LIST_GET_NEXT(space_list, space);
16541659

16551660
/* Skip abnormal tablespaces or those that are being created by
@@ -1659,8 +1664,8 @@ static fil_space_t *fil_space_next(fil_space_t *space, bool recheck,
16591664
space->is_stopping() || space->purpose != FIL_TYPE_TABLESPACE))
16601665
space= UT_LIST_GET_NEXT(space_list, space);
16611666

1662-
if (space)
1663-
space->acquire();
1667+
if (space && !space->acquire())
1668+
goto next;
16641669
}
16651670

16661671
mutex_exit(&fil_system.mutex);
@@ -2529,51 +2534,49 @@ static void fil_crypt_rotation_list_fill()
25292534
space = UT_LIST_GET_NEXT(space_list, space)) {
25302535
if (space->purpose != FIL_TYPE_TABLESPACE
25312536
|| space->is_in_rotation_list
2532-
|| space->is_stopping()
2533-
|| UT_LIST_GET_LEN(space->chain) == 0) {
2537+
|| UT_LIST_GET_LEN(space->chain) == 0
2538+
|| !space->acquire()) {
25342539
continue;
25352540
}
25362541

25372542
/* Ensure that crypt_data has been initialized. */
25382543
if (!space->size) {
2539-
/* Protect the tablespace while we may
2540-
release fil_system.mutex. */
2541-
ut_d(space->acquire());
25422544
ut_d(const fil_space_t* s=)
25432545
fil_system.read_page0(space->id);
25442546
ut_ad(!s || s == space);
2545-
ut_d(space->release());
25462547
if (!space->size) {
25472548
/* Page 0 was not loaded.
25482549
Skip this tablespace. */
2549-
continue;
2550+
goto next;
25502551
}
25512552
}
25522553

25532554
/* Skip ENCRYPTION!=DEFAULT tablespaces. */
25542555
if (space->crypt_data
25552556
&& !space->crypt_data->is_default_encryption()) {
2556-
continue;
2557+
goto next;
25572558
}
25582559

25592560
if (srv_encrypt_tables) {
25602561
/* Skip encrypted tablespaces if
25612562
innodb_encrypt_tables!=OFF */
25622563
if (space->crypt_data
25632564
&& space->crypt_data->min_key_version) {
2564-
continue;
2565+
goto next;
25652566
}
25662567
} else {
25672568
/* Skip unencrypted tablespaces if
25682569
innodb_encrypt_tables=OFF */
25692570
if (!space->crypt_data
25702571
|| !space->crypt_data->min_key_version) {
2571-
continue;
2572+
goto next;
25722573
}
25732574
}
25742575

25752576
fil_system.rotation_list.push_back(*space);
25762577
space->is_in_rotation_list = true;
2578+
next:
2579+
space->release();
25772580
}
25782581
}
25792582

storage/innobase/fil/fil0fil.cc

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -658,8 +658,7 @@ fil_try_to_close_file_in_LRU(
658658
static void fil_flush_low(fil_space_t* space, bool metadata = false)
659659
{
660660
ut_ad(mutex_own(&fil_system.mutex));
661-
ut_ad(space);
662-
ut_ad(!space->stop_new_ops);
661+
ut_ad(!space->is_stopping());
663662

664663
if (fil_buffering_disabled(space)) {
665664

@@ -1869,10 +1868,8 @@ fil_space_t* fil_space_acquire_low(ulint id, bool silent)
18691868
ib::warn() << "Trying to access missing"
18701869
" tablespace " << id;
18711870
}
1872-
} else if (space->is_stopping()) {
1871+
} else if (!space->acquire()) {
18731872
space = NULL;
1874-
} else {
1875-
space->acquire();
18761873
}
18771874

18781875
mutex_exit(&fil_system.mutex);
@@ -2156,14 +2153,14 @@ static ulint fil_check_pending_ops(const fil_space_t* space, ulint count)
21562153
{
21572154
ut_ad(mutex_own(&fil_system.mutex));
21582155

2159-
if (space == NULL) {
2156+
if (!space) {
21602157
return 0;
21612158
}
21622159

2163-
if (ulint n_pending_ops = space->n_pending_ops) {
2160+
if (auto n_pending_ops = space->referenced()) {
21642161

2165-
/* Give a warning every 10 second, starting after 1 second */
2166-
if ((count % 500) == 50) {
2162+
/* Give a warning every 10 second, starting after 1 second */
2163+
if ((count % 500) == 50) {
21672164
ib::warn() << "Trying to delete"
21682165
" tablespace '" << space->name
21692166
<< "' but there are " << n_pending_ops
@@ -2249,14 +2246,13 @@ fil_check_pending_operations(
22492246
fil_space_t* sp = fil_space_get_by_id(id);
22502247

22512248
if (sp) {
2252-
sp->stop_new_ops = true;
2253-
if (sp->crypt_data) {
2254-
sp->acquire();
2249+
if (sp->crypt_data && sp->acquire()) {
22552250
mutex_exit(&fil_system.mutex);
22562251
fil_space_crypt_close_tablespace(sp);
22572252
mutex_enter(&fil_system.mutex);
22582253
sp->release();
22592254
}
2255+
sp->set_stopping(true);
22602256
}
22612257

22622258
/* Check for pending operations. */
@@ -2777,7 +2773,7 @@ fil_rename_tablespace(
27772773
multiple datafiles per tablespace. */
27782774
ut_a(UT_LIST_GET_LEN(space->chain) == 1);
27792775
node = UT_LIST_GET_FIRST(space->chain);
2780-
space->n_pending_ops++;
2776+
ut_a(space->acquire());
27812777

27822778
mutex_exit(&fil_system.mutex);
27832779

@@ -2799,8 +2795,7 @@ fil_rename_tablespace(
27992795
/* log_sys.mutex is above fil_system.mutex in the latching order */
28002796
ut_ad(log_mutex_own());
28012797
mutex_enter(&fil_system.mutex);
2802-
ut_ad(space->n_pending_ops);
2803-
space->n_pending_ops--;
2798+
space->release();
28042799
ut_ad(space->name == old_space_name);
28052800
ut_ad(node->name == old_file_name);
28062801
bool success;
@@ -4133,7 +4128,7 @@ fil_io(
41334128
if (space == NULL
41344129
|| (req_type.is_read()
41354130
&& !sync
4136-
&& space->stop_new_ops
4131+
&& space->is_stopping()
41374132
&& !space->is_being_truncated)) {
41384133

41394134
mutex_exit(&fil_system.mutex);
@@ -4733,7 +4728,7 @@ fil_space_validate_for_mtr_commit(
47334728
fil_space_acquire() before mtr_start() and
47344729
fil_space_t::release() after mtr_commit(). This is why
47354730
n_pending_ops should not be zero if stop_new_ops is set. */
4736-
ut_ad(!space->stop_new_ops
4731+
ut_ad(!space->is_stopping()
47374732
|| space->is_being_truncated /* fil_truncate_prepare() */
47384733
|| space->referenced());
47394734
}
@@ -4949,23 +4944,3 @@ fil_space_get_block_size(const fil_space_t* space, unsigned offset)
49494944

49504945
return block_size;
49514946
}
4952-
4953-
/*******************************************************************//**
4954-
Returns the table space by a given id, NULL if not found. */
4955-
fil_space_t*
4956-
fil_space_found_by_id(
4957-
/*==================*/
4958-
ulint id)/*!< in: space id */
4959-
{
4960-
fil_space_t* space = NULL;
4961-
mutex_enter(&fil_system.mutex);
4962-
space = fil_space_get_by_id(id);
4963-
4964-
/* Not found if space is being deleted */
4965-
if (space && space->stop_new_ops) {
4966-
space = NULL;
4967-
}
4968-
4969-
mutex_exit(&fil_system.mutex);
4970-
return space;
4971-
}

storage/innobase/handler/i_s.cc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8576,8 +8576,7 @@ i_s_tablespaces_encryption_fill_table(
85768576
for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list);
85778577
space; space = UT_LIST_GET_NEXT(space_list, space)) {
85788578
if (space->purpose == FIL_TYPE_TABLESPACE
8579-
&& !space->is_stopping()) {
8580-
space->acquire();
8579+
&& space->acquire()) {
85818580
mutex_exit(&fil_system.mutex);
85828581
if (int err = i_s_dict_fill_tablespaces_encryption(
85838582
thd, space, tables->table)) {
@@ -8850,8 +8849,7 @@ i_s_tablespaces_scrubbing_fill_table(
88508849
for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list);
88518850
space; space = UT_LIST_GET_NEXT(space_list, space)) {
88528851
if (space->purpose == FIL_TYPE_TABLESPACE
8853-
&& !space->is_stopping()) {
8854-
space->acquire();
8852+
&& space->acquire()) {
88558853
mutex_exit(&fil_system.mutex);
88568854
if (int err = i_s_dict_fill_tablespaces_scrubbing(
88578855
thd, space, tables->table)) {

storage/innobase/include/fil0fil.h

Lines changed: 55 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,6 @@ struct fil_space_t
102102
/** Log sequence number of the latest MLOG_INDEX_LOAD record
103103
that was found while parsing the redo log */
104104
lsn_tenable_lsn;
105-
/** set when an .ibd file is about to be deleted,
106-
or an undo tablespace is about to be truncated.
107-
When this is set following new ops are not allowed:
108-
* read IO request
109-
* ibuf merge
110-
* file flush
111-
Note that we can still possibly have new write operations
112-
because we don't check this flag when doing flush batches. */
113-
boolstop_new_ops;
114105
/** whether undo tablespace truncation is in progress */
115106
boolis_being_truncated;
116107
#ifdef UNIV_DEBUG
@@ -142,14 +133,22 @@ struct fil_space_t
142133
ulint n_pending_flushes; /*!< this is positive when flushing
143134
the tablespace to disk; dropping of the
144135
tablespace is forbidden if this is positive */
145-
/** Number of pending buffer pool operations accessing the tablespace
146-
without holding a table lock or dict_sys.latch S-latch
147-
that would prevent the table (and tablespace) from being
148-
dropped. An example is change buffer merge.
149-
The tablespace cannot be dropped while this is nonzero,
150-
or while fil_node_t::n_pending is nonzero.
151-
Protected by fil_system.mutex and std::atomic. */
152-
std::atomic<ulint> n_pending_ops;
136+
private:
137+
/** Number of pending buffer pool operations accessing the
138+
tablespace without holding a table lock or dict_operation_lock
139+
S-latch that would prevent the table (and tablespace) from being
140+
dropped. An example is change buffer merge.
141+
142+
The tablespace cannot be dropped while this is nonzero, or while
143+
fil_node_t::n_pending is nonzero.
144+
145+
The most significant bit contains the STOP_NEW_OPS flag. */
146+
Atomic_relaxed<size_t> n_pending_ops;
147+
148+
/** Flag in n_pending_ops that indicates that the tablespace is being
149+
deleted, and no further operations should be performed */
150+
static const size_t STOP_NEW_OPS= ~(~size_t(0) >> 1);
151+
public:
153152
/** Number of pending block read or write operations
154153
(when a write is imminent or a read has recently completed).
155154
The tablespace object cannot be freed while this is nonzero,
@@ -183,9 +182,6 @@ struct fil_space_t
183182

184183
ulint magic_n;/*!< FIL_SPACE_MAGIC_N */
185184

186-
/** @return whether the tablespace is about to be dropped */
187-
bool is_stopping() const { return stop_new_ops; }
188-
189185
/** Clamp a page number for batched I/O, such as read-ahead.
190186
@param offset page number limit
191187
@return offset clamped to the tablespace size */
@@ -270,20 +266,45 @@ struct fil_space_t
270266
/** Close each file. Only invoked on fil_system.temp_space. */
271267
void close();
272268

273-
/** Acquire a tablespace reference. */
274-
void acquire() { n_pending_ops++; }
275-
/** Release a tablespace reference.
276-
@return whether this was the last reference */
277-
bool release() { auto n= n_pending_ops--; ut_ad(n); return n == 1; }
278-
/** @return whether references are being held */
279-
bool referenced() const { return n_pending_ops; }
280-
281-
/** Acquire a tablespace reference for I/O. */
282-
void acquire_for_io() { n_pending_ios++; }
283-
/** Release a tablespace reference for I/O. */
284-
void release_for_io() { ut_ad(pending_io()); n_pending_ios--; }
285-
/** @return whether I/O is pending */
286-
bool pending_io() const { return n_pending_ios; }
269+
/** @return whether the tablespace is about to be dropped */
270+
bool is_stopping() const { return n_pending_ops & STOP_NEW_OPS; }
271+
272+
/** @return number of references being held */
273+
size_t referenced() const { return n_pending_ops & ~STOP_NEW_OPS; }
274+
275+
/** Note that operations on the tablespace must stop or can resume */
276+
void set_stopping(bool stopping)
277+
{
278+
ut_d(auto n=) n_pending_ops.fetch_xor(STOP_NEW_OPS);
279+
ut_ad(!(n & STOP_NEW_OPS) == stopping);
280+
}
281+
282+
MY_ATTRIBUTE((warn_unused_result))
283+
/** @return whether a tablespace reference was successfully acquired */
284+
bool acquire()
285+
{
286+
size_t n= 0;
287+
while (!n_pending_ops.compare_exchange_strong(n, n + 1,
288+
std::memory_order_acquire,
289+
std::memory_order_relaxed))
290+
if (UNIV_UNLIKELY(n & STOP_NEW_OPS))
291+
return false;
292+
return true;
293+
}
294+
/** Release a tablespace reference.
295+
@return whether this was the last reference */
296+
bool release()
297+
{
298+
auto n= n_pending_ops.fetch_sub(1);
299+
ut_ad(n & ~STOP_NEW_OPS);
300+
return (n & ~STOP_NEW_OPS) == 1;
301+
}
302+
/** Acquire a tablespace reference for I/O. */
303+
void acquire_for_io() { n_pending_ios++; }
304+
/** Release a tablespace reference for I/O. */
305+
void release_for_io() { ut_d(auto n=) n_pending_ios--; ut_ad(n); }
306+
/** @return whether I/O is pending */
307+
bool pending_io() const { return n_pending_ios; }
287308
#endif /* !UNIV_INNOCHECKSUM */
288309
/** FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags;
289310
check fsp0types.h to more info about flags. */

storage/innobase/trx/trx0purge.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -776,12 +776,12 @@ static void trx_purge_truncate_history()
776776
/* This is only executed by srv_purge_coordinator_thread. */
777777
export_vars.innodb_undo_truncations++;
778778

779-
/* TODO: PUNCH_HOLE the garbage (with write-ahead logging) */
779+
/* In MDEV-8319 (10.5) we will PUNCH_HOLE the garbage
780+
(with write-ahead logging). */
780781
mutex_enter(&fil_system.mutex);
781782
ut_ad(&space == purge_sys.truncate.current);
782-
ut_ad(space.stop_new_ops);
783783
ut_ad(space.is_being_truncated);
784-
purge_sys.truncate.current->stop_new_ops = false;
784+
purge_sys.truncate.current->set_stopping(false);
785785
purge_sys.truncate.current->is_being_truncated = false;
786786
mutex_exit(&fil_system.mutex);
787787

0 commit comments

Comments
 (0)