alerts.emplace(device_name + "_DEVICE_STALLED_READ_ALERT", ss.str());
}
}
+ if (support_discard && cct->_conf->bdev_enable_discard) {
+ size_t current_discarded_bytes = discard_queue_bytes.load();
+ uint64_t current_discard_queue_items = discard_queue_length.load();
+
+ size_t discard_bytes_warn_threshold = static_cast<size_t>(0.8 * cct->_conf->bdev_discard_max_bytes);
+ uint64_t discard_items_warn_threshold =
+ static_cast<uint64_t>(0.8 * cct->_conf->bdev_async_discard_max_pending);
+
+ bool discard_queue_overload =
+ (current_discarded_bytes >= discard_bytes_warn_threshold) ||
+ (cct->_conf->bdev_async_discard_max_pending > 0 &&
+ current_discard_queue_items >= discard_items_warn_threshold);
+
+ if (discard_queue_overload) {
+ std::ostringstream ss;
+ ss << "Slow discard on " << device_name
+ << ", queue: " << current_discard_queue_items
+ << " items " << byte_u_t(current_discarded_bytes);
+ alerts.emplace(device_name + "_DEVICE_DISCARD_QUEUE", ss.str());
+ }
+ }
}
#include <fcntl.h>
#include <sys/file.h>
#include <sys/mman.h>
+#include <chrono>
#include <boost/container/flat_map.hpp>
#include <boost/lockfree/queue.hpp>
if (thr->stop && !discard_threads.empty())
break;
+ if (cct->_conf->bdev_debug_discard_sleep > 0)
+ std::this_thread::sleep_for(std::chrono::milliseconds(cct->_conf->bdev_debug_discard_sleep));
+
// Limit local processing to MAX_LOCAL_DISCARD items.
// This will allow threads to work in parallel
// instead of a single thread taking over the whole discard_queued.
// It will also allow threads to finish in a timely manner.
constexpr unsigned MAX_LOCAL_DISCARD = 32;
unsigned count = 0;
+ size_t bytes_discarded = 0;
for (auto it = discard_queued.begin();
it != discard_queued.end() && count < MAX_LOCAL_DISCARD;
++count) {
discard_processing.insert(it.get_start(), it.get_len());
+ bytes_discarded += it.get_len();
it = discard_queued.erase(it);
}
+ discard_queue_bytes -= bytes_discarded;
+ discard_queue_length = discard_queued.num_intervals();
// there are multiple active threads -> must use a counter instead of a flag
discard_running ++;
std::lock_guard l(discard_lock);
- if (max_pending > 0 && discard_queued.num_intervals() >= max_pending)
+ if (max_pending > 0 && discard_queued.num_intervals() >= max_pending) {
+ discard_cond.notify_one();
return false;
+ }
+
+ if(discard_queue_bytes >= cct->_conf->bdev_discard_max_bytes) {
+ discard_cond.notify_one();
+ return false;
+ }
discard_queued.insert(to_release);
+
+ size_t discarded_bytes = 0;
+ for(auto p = to_release.begin(); p != to_release.end(); ++p){
+ discarded_bytes += p.get_len();
+ }
+ discard_queue_bytes += discarded_bytes;
+
+ discard_queue_length = discard_queued.num_intervals();
+
discard_cond.notify_one();
return true;
}