1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2019 Red Hat Inc.
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
20 #include "common/ceph_context.h"
21 #include "osd/scheduler/OpSchedulerItem.h"
23 namespace ceph::osd::scheduler
{
25 using client
= uint64_t;
26 using WorkItem
= std::variant
<std::monostate
, OpSchedulerItem
, double>;
29 * Base interface for classes responsible for choosing
30 * op processing order in the OSD.
34 // Enqueue op for scheduling
35 virtual void enqueue(OpSchedulerItem
&&item
) = 0;
37 // Enqueue op for processing as though it were enqueued prior
38 // to other items already scheduled.
39 virtual void enqueue_front(OpSchedulerItem
&&item
) = 0;
41 // Returns true iff there are no ops scheduled
42 virtual bool empty() const = 0;
44 // Return next op to be processed
45 virtual WorkItem
dequeue() = 0;
47 // Dump formatted representation for the queue
48 virtual void dump(ceph::Formatter
&f
) const = 0;
50 // Print human readable brief description with relevant parameters
51 virtual void print(std::ostream
&out
) const = 0;
53 // Apply config changes to the scheduler (if any)
54 virtual void update_configuration() = 0;
57 virtual ~OpScheduler() {};
60 std::ostream
&operator<<(std::ostream
&lhs
, const OpScheduler
&);
61 using OpSchedulerRef
= std::unique_ptr
<OpScheduler
>;
63 OpSchedulerRef
make_scheduler(
64 CephContext
*cct
, uint32_t num_shards
, bool is_rotational
,
65 std::string_view osd_objectstore
);
68 * Implements OpScheduler in terms of OpQueue
70 * Templated on queue type to avoid dynamic dispatch, T should implement
71 * OpQueue<OpSchedulerItem, client>. This adapter is mainly responsible for
72 * the boilerplate priority cutoff/strict concept which is needed for
73 * OpQueue based implementations.
76 class ClassedOpQueueScheduler final
: public OpScheduler
{
80 static unsigned int get_io_prio_cut(CephContext
*cct
) {
81 if (cct
->_conf
->osd_op_queue_cut_off
== "debug_random") {
83 return (rand() % 2 < 1) ? CEPH_MSG_PRIO_HIGH
: CEPH_MSG_PRIO_LOW
;
84 } else if (cct
->_conf
->osd_op_queue_cut_off
== "high") {
85 return CEPH_MSG_PRIO_HIGH
;
87 // default / catch-all is 'low'
88 return CEPH_MSG_PRIO_LOW
;
92 template <typename
... Args
>
93 ClassedOpQueueScheduler(CephContext
*cct
, Args
&&... args
) :
94 cutoff(get_io_prio_cut(cct
)),
95 queue(std::forward
<Args
>(args
)...)
98 void enqueue(OpSchedulerItem
&&item
) final
{
99 unsigned priority
= item
.get_priority();
100 unsigned cost
= item
.get_cost();
102 if (priority
>= cutoff
)
103 queue
.enqueue_strict(
104 item
.get_owner(), priority
, std::move(item
));
107 item
.get_owner(), priority
, cost
, std::move(item
));
110 void enqueue_front(OpSchedulerItem
&&item
) final
{
111 unsigned priority
= item
.get_priority();
112 unsigned cost
= item
.get_cost();
113 if (priority
>= cutoff
)
114 queue
.enqueue_strict_front(
116 priority
, std::move(item
));
120 priority
, cost
, std::move(item
));
123 bool empty() const final
{
124 return queue
.empty();
127 WorkItem
dequeue() final
{
128 return queue
.dequeue();
131 void dump(ceph::Formatter
&f
) const final
{
132 return queue
.dump(&f
);
135 void print(std::ostream
&out
) const final
{
136 out
<< "ClassedOpQueueScheduler(queue=";
138 out
<< ", cutoff=" << cutoff
<< ")";
141 void update_configuration() final
{
145 ~ClassedOpQueueScheduler() final
{};