]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #ifndef CEPH_LIBRBD_IO_IMAGE_REQUEST_WQ_H | |
5 | #define CEPH_LIBRBD_IO_IMAGE_REQUEST_WQ_H | |
6 | ||
7 | #include "include/Context.h" | |
9f95a23c | 8 | #include "common/ceph_mutex.h" |
11fdf7f2 | 9 | #include "common/Throttle.h" |
7c673cae | 10 | #include "common/WorkQueue.h" |
224ce89b | 11 | #include "librbd/io/Types.h" |
9f95a23c | 12 | #include "include/interval_set.h" |
7c673cae FG |
13 | #include <list> |
14 | #include <atomic> | |
9f95a23c | 15 | #include <vector> |
7c673cae FG |
16 | |
17 | namespace librbd { | |
18 | ||
19 | class ImageCtx; | |
20 | ||
21 | namespace io { | |
22 | ||
23 | class AioCompletion; | |
11fdf7f2 | 24 | template <typename> class ImageDispatchSpec; |
7c673cae FG |
25 | class ReadResult; |
26 | ||
224ce89b WB |
27 | template <typename ImageCtxT = librbd::ImageCtx> |
28 | class ImageRequestWQ | |
11fdf7f2 | 29 | : public ThreadPool::PointerWQ<ImageDispatchSpec<ImageCtxT> > { |
7c673cae | 30 | public: |
224ce89b | 31 | ImageRequestWQ(ImageCtxT *image_ctx, const string &name, time_t ti, |
7c673cae | 32 | ThreadPool *tp); |
11fdf7f2 | 33 | ~ImageRequestWQ(); |
7c673cae FG |
34 | |
35 | ssize_t read(uint64_t off, uint64_t len, ReadResult &&read_result, | |
36 | int op_flags); | |
37 | ssize_t write(uint64_t off, uint64_t len, bufferlist &&bl, int op_flags); | |
11fdf7f2 TL |
38 | ssize_t discard(uint64_t off, uint64_t len, |
39 | uint32_t discard_granularity_bytes); | |
7c673cae | 40 | ssize_t writesame(uint64_t off, uint64_t len, bufferlist &&bl, int op_flags); |
f6b5b4d7 TL |
41 | ssize_t write_zeroes(uint64_t off, uint64_t len, int zero_flags, |
42 | int op_flags); | |
c07f9fc5 FG |
43 | ssize_t compare_and_write(uint64_t off, uint64_t len, |
44 | bufferlist &&cmp_bl, bufferlist &&bl, | |
45 | uint64_t *mismatch_off, int op_flags); | |
11fdf7f2 | 46 | int flush(); |
7c673cae FG |
47 | |
48 | void aio_read(AioCompletion *c, uint64_t off, uint64_t len, | |
49 | ReadResult &&read_result, int op_flags, bool native_async=true); | |
50 | void aio_write(AioCompletion *c, uint64_t off, uint64_t len, | |
51 | bufferlist &&bl, int op_flags, bool native_async=true); | |
52 | void aio_discard(AioCompletion *c, uint64_t off, uint64_t len, | |
11fdf7f2 | 53 | uint32_t discard_granularity_bytes, bool native_async=true); |
7c673cae FG |
54 | void aio_flush(AioCompletion *c, bool native_async=true); |
55 | void aio_writesame(AioCompletion *c, uint64_t off, uint64_t len, | |
56 | bufferlist &&bl, int op_flags, bool native_async=true); | |
f6b5b4d7 TL |
57 | void aio_write_zeroes(AioCompletion *c, uint64_t off, uint64_t len, |
58 | int zero_flags, int op_flags, bool native_async); | |
c07f9fc5 FG |
59 | void aio_compare_and_write(AioCompletion *c, uint64_t off, |
60 | uint64_t len, bufferlist &&cmp_bl, | |
61 | bufferlist &&bl, uint64_t *mismatch_off, | |
62 | int op_flags, bool native_async=true); | |
7c673cae | 63 | |
11fdf7f2 TL |
64 | using ThreadPool::PointerWQ<ImageDispatchSpec<ImageCtxT> >::drain; |
65 | using ThreadPool::PointerWQ<ImageDispatchSpec<ImageCtxT> >::empty; | |
7c673cae FG |
66 | |
67 | void shut_down(Context *on_shutdown); | |
68 | ||
7c673cae | 69 | inline bool writes_blocked() const { |
9f95a23c | 70 | std::shared_lock locker{m_lock}; |
7c673cae FG |
71 | return (m_write_blockers > 0); |
72 | } | |
73 | ||
74 | int block_writes(); | |
75 | void block_writes(Context *on_blocked); | |
76 | void unblock_writes(); | |
77 | ||
11fdf7f2 TL |
78 | void wait_on_writes_unblocked(Context *on_unblocked); |
79 | ||
224ce89b | 80 | void set_require_lock(Direction direction, bool enabled); |
7c673cae | 81 | |
11fdf7f2 TL |
82 | void apply_qos_schedule_tick_min(uint64_t tick); |
83 | ||
84 | void apply_qos_limit(const uint64_t flag, uint64_t limit, uint64_t burst); | |
9f95a23c | 85 | |
7c673cae FG |
86 | protected: |
87 | void *_void_dequeue() override; | |
11fdf7f2 TL |
88 | void process(ImageDispatchSpec<ImageCtxT> *req) override; |
89 | bool _empty() override { | |
90 | return (ThreadPool::PointerWQ<ImageDispatchSpec<ImageCtxT>>::_empty() && | |
91 | m_io_throttled.load() == 0); | |
92 | } | |
93 | ||
7c673cae FG |
94 | |
95 | private: | |
96 | typedef std::list<Context *> Contexts; | |
97 | ||
224ce89b WB |
98 | struct C_AcquireLock; |
99 | struct C_BlockedWrites; | |
100 | struct C_RefreshFinish; | |
101 | ||
102 | ImageCtxT &m_image_ctx; | |
9f95a23c | 103 | mutable ceph::shared_mutex m_lock; |
7c673cae | 104 | Contexts m_write_blocker_contexts; |
224ce89b | 105 | uint32_t m_write_blockers = 0; |
11fdf7f2 | 106 | Contexts m_unblocked_write_waiter_contexts; |
7c673cae | 107 | bool m_require_lock_on_read = false; |
224ce89b | 108 | bool m_require_lock_on_write = false; |
7c673cae FG |
109 | std::atomic<unsigned> m_queued_reads { 0 }; |
110 | std::atomic<unsigned> m_queued_writes { 0 }; | |
224ce89b WB |
111 | std::atomic<unsigned> m_in_flight_ios { 0 }; |
112 | std::atomic<unsigned> m_in_flight_writes { 0 }; | |
113 | std::atomic<unsigned> m_io_blockers { 0 }; | |
11fdf7f2 TL |
114 | std::atomic<unsigned> m_io_throttled { 0 }; |
115 | ||
9f95a23c TL |
116 | typedef interval_set<uint64_t> ImageExtentIntervals; |
117 | ImageExtentIntervals m_in_flight_extents; | |
118 | ||
119 | std::vector<ImageDispatchSpec<ImageCtxT>*> m_blocked_ios; | |
120 | std::atomic<unsigned> m_last_tid { 0 }; | |
121 | std::set<uint64_t> m_queued_or_blocked_io_tids; | |
122 | std::map<uint64_t, ImageDispatchSpec<ImageCtxT>*> m_queued_flushes; | |
123 | ||
11fdf7f2 TL |
124 | std::list<std::pair<uint64_t, TokenBucketThrottle*> > m_throttles; |
125 | uint64_t m_qos_enabled_flag = 0; | |
7c673cae | 126 | |
224ce89b WB |
127 | bool m_shutdown = false; |
128 | Context *m_on_shutdown = nullptr; | |
7c673cae | 129 | |
224ce89b | 130 | bool is_lock_required(bool write_op) const; |
7c673cae | 131 | |
224ce89b | 132 | inline bool require_lock_on_read() const { |
9f95a23c | 133 | std::shared_lock locker{m_lock}; |
224ce89b WB |
134 | return m_require_lock_on_read; |
135 | } | |
7c673cae | 136 | inline bool writes_empty() const { |
9f95a23c | 137 | std::shared_lock locker{m_lock}; |
7c673cae FG |
138 | return (m_queued_writes == 0); |
139 | } | |
140 | ||
11fdf7f2 TL |
141 | bool needs_throttle(ImageDispatchSpec<ImageCtxT> *item); |
142 | ||
9f95a23c TL |
143 | void finish_queued_io(bool write_op); |
144 | void remove_in_flight_write_ios(uint64_t offset, uint64_t length, | |
145 | bool write_op, uint64_t tid); | |
224ce89b | 146 | void finish_in_flight_write(); |
7c673cae | 147 | |
9f95a23c TL |
148 | void unblock_flushes(); |
149 | bool block_overlapping_io(ImageExtentIntervals* in_flight_image_extents, | |
150 | uint64_t object_off, uint64_t object_len); | |
151 | void unblock_overlapping_io(uint64_t offset, uint64_t length, uint64_t tid); | |
224ce89b WB |
152 | int start_in_flight_io(AioCompletion *c); |
153 | void finish_in_flight_io(); | |
11fdf7f2 | 154 | void fail_in_flight_io(int r, ImageDispatchSpec<ImageCtxT> *req); |
9f95a23c | 155 | void process_io(ImageDispatchSpec<ImageCtxT> *req, bool non_blocking_io); |
7c673cae | 156 | |
11fdf7f2 | 157 | void queue(ImageDispatchSpec<ImageCtxT> *req); |
9f95a23c TL |
158 | void queue_unblocked_io(AioCompletion *comp, |
159 | ImageDispatchSpec<ImageCtxT> *req); | |
7c673cae | 160 | |
11fdf7f2 TL |
161 | void handle_acquire_lock(int r, ImageDispatchSpec<ImageCtxT> *req); |
162 | void handle_refreshed(int r, ImageDispatchSpec<ImageCtxT> *req); | |
7c673cae | 163 | void handle_blocked_writes(int r); |
11fdf7f2 TL |
164 | |
165 | void handle_throttle_ready(int r, ImageDispatchSpec<ImageCtxT> *item, uint64_t flag); | |
7c673cae FG |
166 | }; |
167 | ||
168 | } // namespace io | |
169 | } // namespace librbd | |
170 | ||
224ce89b WB |
171 | extern template class librbd::io::ImageRequestWQ<librbd::ImageCtx>; |
172 | ||
7c673cae | 173 | #endif // CEPH_LIBRBD_IO_IMAGE_REQUEST_WQ_H |