summaryrefslogtreecommitdiffstats
path: root/src/librbd/io/QosImageDispatch.h
blob: f5e08940a4b12e81694d52a28fa04df6f0f9611f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#ifndef CEPH_LIBRBD_IO_QOS_IMAGE_DISPATCH_H
#define CEPH_LIBRBD_IO_QOS_IMAGE_DISPATCH_H

#include <list>
#include <memory>

#include "librbd/io/ImageDispatchInterface.h"
#include "include/int_types.h"
#include "include/buffer.h"
#include "common/zipkin_trace.h"
#include "common/Throttle.h"
#include "librbd/io/ReadResult.h"
#include "librbd/io/Types.h"

struct Context;

namespace librbd {

struct ImageCtx;

namespace io {

struct AioCompletion;
template <typename> class FlushTracker;

template <typename ImageCtxT>
class QosImageDispatch : public ImageDispatchInterface {
public:
  struct Tag {
    std::atomic<uint32_t>* image_dispatch_flags;
    Context* on_dispatched;

    Tag(std::atomic<uint32_t>* image_dispatch_flags, Context* on_dispatched)
      : image_dispatch_flags(image_dispatch_flags),
        on_dispatched(on_dispatched) {
    }
  };

  QosImageDispatch(ImageCtxT* image_ctx);
  ~QosImageDispatch() override;

  ImageDispatchLayer get_dispatch_layer() const override {
    return IMAGE_DISPATCH_LAYER_QOS;
  }

  void shut_down(Context* on_finish) override;

  void apply_qos_schedule_tick_min(uint64_t tick);
  void apply_qos_limit(uint64_t flag, uint64_t limit, uint64_t burst,
                       uint64_t burst_seconds);
  void apply_qos_exclude_ops(uint64_t exclude_ops);

  bool read(
      AioCompletion* aio_comp, Extents &&image_extents,
      ReadResult &&read_result, IOContext io_context, int op_flags,
      int read_flags, const ZTracer::Trace &parent_trace, uint64_t tid,
      std::atomic<uint32_t>* image_dispatch_flags,
      DispatchResult* dispatch_result, Context** on_finish,
      Context* on_dispatched) override;
  bool write(
      AioCompletion* aio_comp, Extents &&image_extents, bufferlist &&bl,
      int op_flags, const ZTracer::Trace &parent_trace,
      uint64_t tid, std::atomic<uint32_t>* image_dispatch_flags,
      DispatchResult* dispatch_result, Context** on_finish,
      Context* on_dispatched) override;
  bool discard(
      AioCompletion* aio_comp, Extents &&image_extents,
      uint32_t discard_granularity_bytes, const ZTracer::Trace &parent_trace,
      uint64_t tid, std::atomic<uint32_t>* image_dispatch_flags,
      DispatchResult* dispatch_result, Context** on_finish,
      Context* on_dispatched) override;
  bool write_same(
      AioCompletion* aio_comp, Extents &&image_extents, bufferlist &&bl,
      int op_flags, const ZTracer::Trace &parent_trace,
      uint64_t tid, std::atomic<uint32_t>* image_dispatch_flags,
      DispatchResult* dispatch_result, Context** on_finish,
      Context* on_dispatched) override;
  bool compare_and_write(
      AioCompletion* aio_comp, Extents &&image_extents,
      bufferlist &&cmp_bl, bufferlist &&bl, uint64_t *mismatch_offset,
      int op_flags, const ZTracer::Trace &parent_trace,
      uint64_t tid, std::atomic<uint32_t>* image_dispatch_flags,
      DispatchResult* dispatch_result, Context** on_finish,
      Context* on_dispatched) override;
  bool flush(
      AioCompletion* aio_comp, FlushSource flush_source,
      const ZTracer::Trace &parent_trace, uint64_t tid,
      std::atomic<uint32_t>* image_dispatch_flags,
      DispatchResult* dispatch_result, Context** on_finish,
      Context* on_dispatched) override;

  bool list_snaps(
      AioCompletion* aio_comp, Extents&& image_extents, SnapIds&& snap_ids,
      int list_snaps_flags, SnapshotDelta* snapshot_delta,
      const ZTracer::Trace &parent_trace, uint64_t tid,
      std::atomic<uint32_t>* image_dispatch_flags,
      DispatchResult* dispatch_result, Context** on_finish,
      Context* on_dispatched) override {
    return false;
  }

  bool invalidate_cache(Context* on_finish) override {
    return false;
  }

private:
  ImageCtxT* m_image_ctx;

  std::list<std::pair<uint64_t, TokenBucketThrottle*> > m_throttles;
  uint64_t m_qos_enabled_flag = 0;
  uint64_t m_qos_exclude_ops = 0;

  std::unique_ptr<FlushTracker<ImageCtxT>> m_flush_tracker;

  void handle_finished(int r, uint64_t tid);

  bool set_throttle_flag(std::atomic<uint32_t>* image_dispatch_flags,
                         uint32_t flag);
  bool needs_throttle(bool read_op, const Extents& image_extents, uint64_t tid,
                      std::atomic<uint32_t>* image_dispatch_flags,
                      DispatchResult* dispatch_result, Context** on_finish,
                      Context* on_dispatched);
  void handle_throttle_ready(Tag&& tag, uint64_t flag);

};

} // namespace io
} // namespace librbd

extern template class librbd::io::QosImageDispatch<librbd::ImageCtx>;

#endif // CEPH_LIBRBD_IO_QOS_IMAGE_DISPATCH_H