}
}
-void ImageRequestWQ<I>::handle_iops_throttle_ready(int r, ImageRequest<I> *item) {
+ template <typename I>
+ void ImageRequestWQ<I>::apply_qos_iops_limit(uint64_t limit) {
+ iops_throttle->set_max(limit);
+ iops_throttle->set_average(limit);
+ }
+
+ template <typename I>
++void ImageRequestWQ<I>::handle_iops_throttle_ready(int r,
++ ImageRequest<I> *item) {
++ CephContext *cct = m_image_ctx.cct;
++ ldout(cct, 15) << "r=" << r << ", " << "req=" << item << dendl;
++
+ assert(m_io_blockers.load() > 0);
+ --m_io_blockers;
+ item->set_throttled();
+ this->requeue(item);
+ this->signal();
+ }
+
template <typename I>
void *ImageRequestWQ<I>::_void_dequeue() {
CephContext *cct = m_image_ctx.cct;
return nullptr;
}
++ if (!peek_item->was_throttled() &&
++ iops_throttle->get<
++ ImageRequestWQ<I>, ImageRequest<I>,
++ &ImageRequestWQ<I>::handle_iops_throttle_ready>(1, this, peek_item)) {
++ ldout(cct, 15) << "throttling IO " << peek_item << dendl;
++
++ // dequeue the throttled item and block future IO
++ ThreadPool::PointerWQ<ImageRequest<I> >::_void_dequeue();
++ ++m_io_blockers;
++ return nullptr;
++ }
++
bool lock_required;
bool refresh_required = m_image_ctx.state->is_refresh_required();
{