Skip to content

Commit 0ab5214

Browse files
authored
Merge pull request ceph#58409 from baergj/upstream-fix-async-discard-on-start
blk/KernelDevice: React to bdev_enable_discard changes in handle_conf_change(); Fix several issues with stopping discard threads
2 parents d09655f + 617c936 commit 0ab5214

File tree

2 files changed

+46
-77
lines changed

2 files changed

+46
-77
lines changed

src/blk/kernel/KernelDevice.cc

Lines changed: 44 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ int KernelDevice::open(const string& p)
134134
{
135135
path = p;
136136
int r = 0, i = 0;
137-
uint64_t num_discard_threads = 0;
138137
dout(1) << __func__ << " path " << path << dendl;
139138

140139
struct stat statbuf;
@@ -286,10 +285,7 @@ int KernelDevice::open(const string& p)
286285
goto out_fail;
287286
}
288287

289-
num_discard_threads = cct->_conf.get_val<uint64_t>("bdev_async_discard_threads");
290-
if (support_discard && cct->_conf->bdev_enable_discard && num_discard_threads > 0) {
291-
_discard_start();
292-
}
288+
_discard_update_threads();
293289

294290
// round size down to an even block
295291
size &= ~(block_size - 1);
@@ -536,47 +532,49 @@ void KernelDevice::_aio_stop()
536532
}
537533
}
538534

539-
void KernelDevice::_discard_start()
535+
void KernelDevice::_discard_update_threads()
540536
{
541-
uint64_t num = cct->_conf.get_val<uint64_t>("bdev_async_discard_threads");
542-
dout(10) << __func__ << " starting " << num << " threads" << dendl;
543-
544537
std::unique_lock l(discard_lock);
545538

546-
target_discard_threads = num;
547-
discard_threads.reserve(num);
548-
for(uint64_t i = 0; i < num; i++)
549-
{
550-
// All threads created with the same name
551-
discard_threads.emplace_back(new DiscardThread(this, i));
552-
discard_threads.back()->create("bstore_discard");
553-
}
539+
uint64_t oldcount = discard_threads.size();
540+
uint64_t newcount = cct->_conf.get_val<uint64_t>("bdev_async_discard_threads");
541+
if (!cct->_conf.get_val<bool>("bdev_enable_discard") || !support_discard || discard_stop) {
542+
newcount = 0;
543+
}
544+
545+
// Increase? Spawn now, it's quick
546+
if (newcount > oldcount) {
547+
dout(10) << __func__ << " starting " << (newcount - oldcount) << " additional discard threads" << dendl;
548+
discard_threads.reserve(newcount);
549+
for(uint64_t i = oldcount; i < newcount; i++)
550+
{
551+
// All threads created with the same name
552+
discard_threads.emplace_back(new DiscardThread(this, i));
553+
discard_threads.back()->create("bstore_discard");
554+
}
555+
// Decrease? Signal threads after telling them to stop
556+
} else if (newcount < oldcount) {
557+
dout(10) << __func__ << " stopping " << (oldcount - newcount) << " existing discard threads" << dendl;
558+
559+
// Signal the last threads to quit, and stop tracking them
560+
for(uint64_t i = oldcount; i > newcount; i--)
561+
{
562+
discard_threads[i-1]->stop = true;
563+
discard_threads[i-1]->detach();
564+
}
565+
discard_threads.resize(newcount);
554566

555-
dout(10) << __func__ << " started " << num << " threads" << dendl;
567+
discard_cond.notify_all();
568+
}
556569
}
557570

558571
void KernelDevice::_discard_stop()
559572
{
560573
dout(10) << __func__ << dendl;
561574

562-
// Signal threads to stop, then wait for them to join
563-
{
564-
std::unique_lock l(discard_lock);
565-
while (discard_threads.empty()) {
566-
discard_cond.wait(l);
567-
}
568-
569-
for(auto &t : discard_threads) {
570-
t->stop = true;
571-
}
572-
573-
discard_cond.notify_all();
574-
}
575-
576-
// Threads are shared pointers and are cleaned up for us
577-
for(auto &t : discard_threads)
578-
t->join();
579-
discard_threads.clear();
575+
discard_stop = true;
576+
_discard_update_threads();
577+
discard_drain();
580578

581579
dout(10) << __func__ << " stopped" << dendl;
582580
}
@@ -761,6 +759,13 @@ void KernelDevice::_discard_thread(uint64_t tid)
761759
discard_cond.wait(l);
762760
dout(20) << __func__ << " wake" << dendl;
763761
} else {
762+
// If there are non-stopped discard threads and we have been requested
763+
// to stop, do so now. Otherwise, we need to proceed because
764+
// discard_queued is non-empty and at least one thread is needed to
765+
// drain it.
766+
if (thr->stop && !discard_threads.empty())
767+
break;
768+
764769
// Limit local processing to MAX_LOCAL_DISCARD items.
765770
// This will allow threads to work in parallel
766771
// instead of a single thread taking over the whole discard_queued.
@@ -1513,6 +1518,7 @@ const char** KernelDevice::get_tracked_conf_keys() const
15131518
{
15141519
static const char* KEYS[] = {
15151520
"bdev_async_discard_threads",
1521+
"bdev_enable_discard",
15161522
NULL
15171523
};
15181524
return KEYS;
@@ -1521,44 +1527,7 @@ const char** KernelDevice::get_tracked_conf_keys() const
15211527
void KernelDevice::handle_conf_change(const ConfigProxy& conf,
15221528
const std::set <std::string> &changed)
15231529
{
1524-
if (changed.count("bdev_async_discard_threads")) {
1525-
std::unique_lock l(discard_lock);
1526-
1527-
uint64_t oldval = target_discard_threads;
1528-
uint64_t newval = cct->_conf.get_val<uint64_t>("bdev_async_discard_threads");
1529-
1530-
target_discard_threads = newval;
1531-
1532-
// Increase? Spawn now, it's quick
1533-
if (newval > oldval) {
1534-
dout(10) << __func__ << " starting " << (newval - oldval) << " additional discard threads" << dendl;
1535-
discard_threads.reserve(target_discard_threads);
1536-
for(uint64_t i = oldval; i < newval; i++)
1537-
{
1538-
// All threads created with the same name
1539-
discard_threads.emplace_back(new DiscardThread(this, i));
1540-
discard_threads.back()->create("bstore_discard");
1541-
}
1542-
} else {
1543-
// Decrease? Signal threads after telling them to stop
1544-
dout(10) << __func__ << " stopping " << (oldval - newval) << " existing discard threads" << dendl;
1545-
1546-
// Decreasing to zero is exactly the same as disabling async discard.
1547-
// Signal all threads to stop
1548-
if(newval == 0) {
1549-
_discard_stop();
1550-
} else {
1551-
// Signal the last threads to quit, and stop tracking them
1552-
for(uint64_t i = oldval - 1; i >= newval; i--)
1553-
{
1554-
// Also detach the thread so we no longer need to join
1555-
discard_threads[i]->stop = true;
1556-
discard_threads[i]->detach();
1557-
discard_threads.erase(discard_threads.begin() + i);
1558-
}
1559-
}
1560-
1561-
discard_cond.notify_all();
1562-
}
1530+
if (changed.count("bdev_async_discard_threads") || changed.count("bdev_enable_discard")) {
1531+
_discard_update_threads();
15631532
}
15641533
}

src/blk/kernel/KernelDevice.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class KernelDevice : public BlockDevice,
5252
aio_callback_t discard_callback;
5353
void *discard_callback_priv;
5454
bool aio_stop;
55+
bool discard_stop;
5556

5657
ceph::mutex discard_lock = ceph::make_mutex("KernelDevice::discard_lock");
5758
ceph::condition_variable discard_cond;
@@ -78,7 +79,6 @@ class KernelDevice : public BlockDevice,
7879
}
7980
};
8081
std::vector<std::shared_ptr<DiscardThread>> discard_threads;
81-
uint64_t target_discard_threads = 0;
8282

8383
std::atomic_int injecting_crash;
8484

@@ -93,7 +93,7 @@ class KernelDevice : public BlockDevice,
9393
int _aio_start();
9494
void _aio_stop();
9595

96-
void _discard_start();
96+
void _discard_update_threads();
9797
void _discard_stop();
9898
bool _discard_started();
9999

0 commit comments

Comments
 (0)