]>
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); |
c07f9fc5 FG |
41 | ssize_t compare_and_write(uint64_t off, uint64_t len, |
42 | bufferlist &&cmp_bl, bufferlist &&bl, | |
43 | uint64_t *mismatch_off, int op_flags); | |
11fdf7f2 | 44 | int flush(); |
7c673cae FG |
45 | |
46 | void aio_read(AioCompletion *c, uint64_t off, uint64_t len, | |
47 | ReadResult &&read_result, int op_flags, bool native_async=true); | |
48 | void aio_write(AioCompletion *c, uint64_t off, uint64_t len, | |
49 | bufferlist &&bl, int op_flags, bool native_async=true); | |
50 | void aio_discard(AioCompletion *c, uint64_t off, uint64_t len, | |
11fdf7f2 | 51 | uint32_t discard_granularity_bytes, bool native_async=true); |
7c673cae FG |
52 | void aio_flush(AioCompletion *c, bool native_async=true); |
53 | void aio_writesame(AioCompletion *c, uint64_t off, uint64_t len, | |
54 | bufferlist &&bl, int op_flags, bool native_async=true); | |
c07f9fc5 FG |
55 | void aio_compare_and_write(AioCompletion *c, uint64_t off, |
56 | uint64_t len, bufferlist &&cmp_bl, | |
57 | bufferlist &&bl, uint64_t *mismatch_off, | |
58 | int op_flags, bool native_async=true); | |
7c673cae | 59 | |
11fdf7f2 TL |
60 | using ThreadPool::PointerWQ<ImageDispatchSpec<ImageCtxT> >::drain; |
61 | using ThreadPool::PointerWQ<ImageDispatchSpec<ImageCtxT> >::empty; | |
7c673cae FG |
62 | |
63 | void shut_down(Context *on_shutdown); | |
64 | ||
7c673cae | 65 | inline bool writes_blocked() const { |
9f95a23c | 66 | std::shared_lock locker{m_lock}; |
7c673cae FG |
67 | return (m_write_blockers > 0); |
68 | } | |
69 | ||
70 | int block_writes(); | |
71 | void block_writes(Context *on_blocked); | |
72 | void unblock_writes(); | |
73 | ||
11fdf7f2 TL |
74 | void wait_on_writes_unblocked(Context *on_unblocked); |
75 | ||
224ce89b | 76 | void set_require_lock(Direction direction, bool enabled); |
7c673cae | 77 | |
11fdf7f2 TL |
78 | void apply_qos_schedule_tick_min(uint64_t tick); |
79 | ||
80 | void apply_qos_limit(const uint64_t flag, uint64_t limit, uint64_t burst); | |
9f95a23c | 81 | |
7c673cae FG |
82 | protected: |
83 | void *_void_dequeue() override; | |
11fdf7f2 TL |
84 | void process(ImageDispatchSpec<ImageCtxT> *req) override; |
85 | bool _empty() override { | |
86 | return (ThreadPool::PointerWQ<ImageDispatchSpec<ImageCtxT>>::_empty() && | |
87 | m_io_throttled.load() == 0); | |
88 | } | |
89 | ||
7c673cae FG |
90 | |
91 | private: | |
92 | typedef std::list<Context *> Contexts; | |
93 | ||
224ce89b WB |
94 | struct C_AcquireLock; |
95 | struct C_BlockedWrites; | |
96 | struct C_RefreshFinish; | |
97 | ||
98 | ImageCtxT &m_image_ctx; | |
9f95a23c | 99 | mutable ceph::shared_mutex m_lock; |
7c673cae | 100 | Contexts m_write_blocker_contexts; |
224ce89b | 101 | uint32_t m_write_blockers = 0; |
11fdf7f2 | 102 | Contexts m_unblocked_write_waiter_contexts; |
7c673cae | 103 | bool m_require_lock_on_read = false; |
224ce89b | 104 | bool m_require_lock_on_write = false; |
7c673cae FG |
105 | std::atomic<unsigned> m_queued_reads { 0 }; |
106 | std::atomic<unsigned> m_queued_writes { 0 }; | |
224ce89b WB |
107 | std::atomic<unsigned> m_in_flight_ios { 0 }; |
108 | std::atomic<unsigned> m_in_flight_writes { 0 }; | |
109 | std::atomic<unsigned> m_io_blockers { 0 }; | |
11fdf7f2 TL |
110 | std::atomic<unsigned> m_io_throttled { 0 }; |
111 | ||
9f95a23c TL |
112 | typedef interval_set<uint64_t> ImageExtentIntervals; |
113 | ImageExtentIntervals m_in_flight_extents; | |
114 | ||
115 | std::vector<ImageDispatchSpec<ImageCtxT>*> m_blocked_ios; | |
116 | std::atomic<unsigned> m_last_tid { 0 }; | |
117 | std::set<uint64_t> m_queued_or_blocked_io_tids; | |
118 | std::map<uint64_t, ImageDispatchSpec<ImageCtxT>*> m_queued_flushes; | |
119 | ||
11fdf7f2 TL |
120 | std::list<std::pair<uint64_t, TokenBucketThrottle*> > m_throttles; |
121 | uint64_t m_qos_enabled_flag = 0; | |
7c673cae | 122 | |
224ce89b WB |
123 | bool m_shutdown = false; |
124 | Context *m_on_shutdown = nullptr; | |
7c673cae | 125 | |
224ce89b | 126 | bool is_lock_required(bool write_op) const; |
7c673cae | 127 | |
224ce89b | 128 | inline bool require_lock_on_read() const { |
9f95a23c | 129 | std::shared_lock locker{m_lock}; |
224ce89b WB |
130 | return m_require_lock_on_read; |
131 | } | |
7c673cae | 132 | inline bool writes_empty() const { |
9f95a23c | 133 | std::shared_lock locker{m_lock}; |
7c673cae FG |
134 | return (m_queued_writes == 0); |
135 | } | |
136 | ||
11fdf7f2 TL |
137 | bool needs_throttle(ImageDispatchSpec<ImageCtxT> *item); |
138 | ||
9f95a23c TL |
139 | void finish_queued_io(bool write_op); |
140 | void remove_in_flight_write_ios(uint64_t offset, uint64_t length, | |
141 | bool write_op, uint64_t tid); | |
224ce89b | 142 | void finish_in_flight_write(); |
7c673cae | 143 | |
9f95a23c TL |
144 | void unblock_flushes(); |
145 | bool block_overlapping_io(ImageExtentIntervals* in_flight_image_extents, | |
146 | uint64_t object_off, uint64_t object_len); | |
147 | void unblock_overlapping_io(uint64_t offset, uint64_t length, uint64_t tid); | |
224ce89b WB |
148 | int start_in_flight_io(AioCompletion *c); |
149 | void finish_in_flight_io(); | |
11fdf7f2 | 150 | void fail_in_flight_io(int r, ImageDispatchSpec<ImageCtxT> *req); |
9f95a23c | 151 | void process_io(ImageDispatchSpec<ImageCtxT> *req, bool non_blocking_io); |
7c673cae | 152 | |
11fdf7f2 | 153 | void queue(ImageDispatchSpec<ImageCtxT> *req); |
9f95a23c TL |
154 | void queue_unblocked_io(AioCompletion *comp, |
155 | ImageDispatchSpec<ImageCtxT> *req); | |
7c673cae | 156 | |
11fdf7f2 TL |
157 | void handle_acquire_lock(int r, ImageDispatchSpec<ImageCtxT> *req); |
158 | void handle_refreshed(int r, ImageDispatchSpec<ImageCtxT> *req); | |
7c673cae | 159 | void handle_blocked_writes(int r); |
11fdf7f2 TL |
160 | |
161 | void handle_throttle_ready(int r, ImageDispatchSpec<ImageCtxT> *item, uint64_t flag); | |
7c673cae FG |
162 | }; |
163 | ||
164 | } // namespace io | |
165 | } // namespace librbd | |
166 | ||
224ce89b WB |
167 | extern template class librbd::io::ImageRequestWQ<librbd::ImageCtx>; |
168 | ||
7c673cae | 169 | #endif // CEPH_LIBRBD_IO_IMAGE_REQUEST_WQ_H |