]>
Commit | Line | Data |
---|---|---|
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_H | |
5 | #define CEPH_LIBRBD_IO_IMAGE_REQUEST_H | |
6 | ||
7 | #include "include/int_types.h" | |
8 | #include "include/buffer_fwd.h" | |
9 | #include "common/snap_types.h" | |
10 | #include "osd/osd_types.h" | |
11 | #include "librbd/io/Types.h" | |
12 | #include <list> | |
13 | #include <utility> | |
14 | #include <vector> | |
15 | ||
16 | namespace librbd { | |
17 | class ImageCtx; | |
18 | ||
19 | namespace io { | |
20 | ||
21 | class AioCompletion; | |
22 | class ObjectRequestHandle; | |
23 | class ReadResult; | |
24 | ||
25 | template <typename ImageCtxT = ImageCtx> | |
26 | class ImageRequest { | |
27 | public: | |
28 | typedef std::vector<std::pair<uint64_t,uint64_t> > Extents; | |
29 | ||
30 | virtual ~ImageRequest() {} | |
31 | ||
32 | static void aio_read(ImageCtxT *ictx, AioCompletion *c, | |
33 | Extents &&image_extents, ReadResult &&read_result, | |
34 | int op_flags); | |
35 | static void aio_write(ImageCtxT *ictx, AioCompletion *c, | |
36 | Extents &&image_extents, bufferlist &&bl, int op_flags); | |
37 | static void aio_discard(ImageCtxT *ictx, AioCompletion *c, uint64_t off, | |
38 | uint64_t len, bool skip_partial_discard); | |
39 | static void aio_flush(ImageCtxT *ictx, AioCompletion *c); | |
40 | static void aio_writesame(ImageCtxT *ictx, AioCompletion *c, uint64_t off, | |
41 | uint64_t len, bufferlist &&bl, int op_flags); | |
42 | ||
43 | virtual bool is_write_op() const { | |
44 | return false; | |
45 | } | |
46 | ||
47 | void start_op(); | |
48 | ||
49 | void send(); | |
50 | void fail(int r); | |
51 | ||
52 | void set_bypass_image_cache() { | |
53 | m_bypass_image_cache = true; | |
54 | } | |
55 | ||
56 | protected: | |
57 | typedef std::list<ObjectRequestHandle *> ObjectRequests; | |
58 | ||
59 | ImageCtxT &m_image_ctx; | |
60 | AioCompletion *m_aio_comp; | |
61 | Extents m_image_extents; | |
62 | bool m_bypass_image_cache = false; | |
63 | ||
64 | ImageRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, | |
65 | Extents &&image_extents) | |
66 | : m_image_ctx(image_ctx), m_aio_comp(aio_comp), | |
67 | m_image_extents(image_extents) { | |
68 | } | |
69 | ||
70 | virtual int clip_request(); | |
71 | virtual void send_request() = 0; | |
72 | virtual void send_image_cache_request() = 0; | |
73 | ||
74 | virtual aio_type_t get_aio_type() const = 0; | |
75 | virtual const char *get_request_type() const = 0; | |
76 | }; | |
77 | ||
78 | template <typename ImageCtxT = ImageCtx> | |
79 | class ImageReadRequest : public ImageRequest<ImageCtxT> { | |
80 | public: | |
81 | using typename ImageRequest<ImageCtxT>::Extents; | |
82 | ||
83 | ImageReadRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, | |
84 | Extents &&image_extents, ReadResult &&read_result, | |
85 | int op_flags); | |
86 | ||
87 | protected: | |
88 | int clip_request() override; | |
89 | ||
90 | void send_request() override; | |
91 | void send_image_cache_request() override; | |
92 | ||
93 | aio_type_t get_aio_type() const override { | |
94 | return AIO_TYPE_READ; | |
95 | } | |
96 | const char *get_request_type() const override { | |
97 | return "aio_read"; | |
98 | } | |
99 | private: | |
100 | char *m_buf; | |
101 | bufferlist *m_pbl; | |
102 | int m_op_flags; | |
103 | }; | |
104 | ||
105 | template <typename ImageCtxT = ImageCtx> | |
106 | class AbstractImageWriteRequest : public ImageRequest<ImageCtxT> { | |
107 | public: | |
108 | bool is_write_op() const override { | |
109 | return true; | |
110 | } | |
111 | ||
112 | inline void flag_synchronous() { | |
113 | m_synchronous = true; | |
114 | } | |
115 | ||
116 | protected: | |
117 | using typename ImageRequest<ImageCtxT>::ObjectRequests; | |
118 | using typename ImageRequest<ImageCtxT>::Extents; | |
119 | ||
120 | typedef std::vector<ObjectExtent> ObjectExtents; | |
121 | ||
122 | AbstractImageWriteRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, | |
123 | Extents &&image_extents) | |
124 | : ImageRequest<ImageCtxT>(image_ctx, aio_comp, std::move(image_extents)), | |
125 | m_synchronous(false) { | |
126 | } | |
127 | ||
128 | void send_request() override; | |
129 | ||
130 | virtual void prune_object_extents(ObjectExtents &object_extents) { | |
131 | } | |
132 | virtual uint32_t get_object_cache_request_count(bool journaling) const { | |
133 | return 0; | |
134 | } | |
135 | virtual void send_object_cache_requests(const ObjectExtents &object_extents, | |
136 | uint64_t journal_tid) = 0; | |
137 | ||
138 | virtual void send_object_requests(const ObjectExtents &object_extents, | |
139 | const ::SnapContext &snapc, | |
140 | ObjectRequests *object_requests); | |
141 | virtual ObjectRequestHandle *create_object_request( | |
142 | const ObjectExtent &object_extent, const ::SnapContext &snapc, | |
143 | Context *on_finish) = 0; | |
144 | ||
145 | virtual uint64_t append_journal_event(const ObjectRequests &requests, | |
146 | bool synchronous) = 0; | |
147 | virtual void update_stats(size_t length) = 0; | |
148 | ||
149 | private: | |
150 | bool m_synchronous; | |
151 | }; | |
152 | ||
153 | template <typename ImageCtxT = ImageCtx> | |
154 | class ImageWriteRequest : public AbstractImageWriteRequest<ImageCtxT> { | |
155 | public: | |
156 | using typename ImageRequest<ImageCtxT>::Extents; | |
157 | ||
158 | ImageWriteRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, | |
159 | Extents &&image_extents, bufferlist &&bl, int op_flags) | |
160 | : AbstractImageWriteRequest<ImageCtxT>(image_ctx, aio_comp, | |
161 | std::move(image_extents)), | |
162 | m_bl(std::move(bl)), m_op_flags(op_flags) { | |
163 | } | |
164 | ||
165 | protected: | |
166 | using typename ImageRequest<ImageCtxT>::ObjectRequests; | |
167 | using typename AbstractImageWriteRequest<ImageCtxT>::ObjectExtents; | |
168 | ||
169 | aio_type_t get_aio_type() const override { | |
170 | return AIO_TYPE_WRITE; | |
171 | } | |
172 | const char *get_request_type() const override { | |
173 | return "aio_write"; | |
174 | } | |
175 | ||
176 | void assemble_extent(const ObjectExtent &object_extent, bufferlist *bl); | |
177 | ||
178 | void send_image_cache_request() override; | |
179 | ||
180 | void send_object_cache_requests(const ObjectExtents &object_extents, | |
181 | uint64_t journal_tid) override; | |
182 | ||
183 | void send_object_requests(const ObjectExtents &object_extents, | |
184 | const ::SnapContext &snapc, | |
185 | ObjectRequests *aio_object_requests) override; | |
186 | ||
187 | ObjectRequestHandle *create_object_request( | |
188 | const ObjectExtent &object_extent, const ::SnapContext &snapc, | |
189 | Context *on_finish) override; | |
190 | ||
191 | uint64_t append_journal_event(const ObjectRequests &requests, | |
192 | bool synchronous) override; | |
193 | void update_stats(size_t length) override; | |
194 | ||
195 | private: | |
196 | bufferlist m_bl; | |
197 | int m_op_flags; | |
198 | }; | |
199 | ||
200 | template <typename ImageCtxT = ImageCtx> | |
201 | class ImageDiscardRequest : public AbstractImageWriteRequest<ImageCtxT> { | |
202 | public: | |
203 | ImageDiscardRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, | |
204 | uint64_t off, uint64_t len, bool skip_partial_discard) | |
205 | : AbstractImageWriteRequest<ImageCtxT>(image_ctx, aio_comp, {{off, len}}), | |
206 | m_skip_partial_discard(skip_partial_discard) { | |
207 | } | |
208 | ||
209 | protected: | |
210 | using typename ImageRequest<ImageCtxT>::ObjectRequests; | |
211 | using typename AbstractImageWriteRequest<ImageCtxT>::ObjectExtents; | |
212 | ||
213 | aio_type_t get_aio_type() const override { | |
214 | return AIO_TYPE_DISCARD; | |
215 | } | |
216 | const char *get_request_type() const override { | |
217 | return "aio_discard"; | |
218 | } | |
219 | ||
220 | void prune_object_extents(ObjectExtents &object_extents) override; | |
221 | ||
222 | void send_image_cache_request() override; | |
223 | ||
224 | uint32_t get_object_cache_request_count(bool journaling) const override; | |
225 | void send_object_cache_requests(const ObjectExtents &object_extents, | |
226 | uint64_t journal_tid) override; | |
227 | ||
228 | ObjectRequestHandle *create_object_request( | |
229 | const ObjectExtent &object_extent, const ::SnapContext &snapc, | |
230 | Context *on_finish) override; | |
231 | ||
232 | uint64_t append_journal_event(const ObjectRequests &requests, | |
233 | bool synchronous) override; | |
234 | void update_stats(size_t length) override; | |
235 | private: | |
236 | bool m_skip_partial_discard; | |
237 | }; | |
238 | ||
239 | template <typename ImageCtxT = ImageCtx> | |
240 | class ImageFlushRequest : public ImageRequest<ImageCtxT> { | |
241 | public: | |
242 | ImageFlushRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp) | |
243 | : ImageRequest<ImageCtxT>(image_ctx, aio_comp, {}) { | |
244 | } | |
245 | ||
246 | bool is_write_op() const override { | |
247 | return true; | |
248 | } | |
249 | ||
250 | protected: | |
251 | using typename ImageRequest<ImageCtxT>::ObjectRequests; | |
252 | ||
253 | int clip_request() override { | |
254 | return 0; | |
255 | } | |
256 | void send_request() override; | |
257 | void send_image_cache_request() override; | |
258 | ||
259 | aio_type_t get_aio_type() const override { | |
260 | return AIO_TYPE_FLUSH; | |
261 | } | |
262 | const char *get_request_type() const override { | |
263 | return "aio_flush"; | |
264 | } | |
265 | }; | |
266 | ||
267 | template <typename ImageCtxT = ImageCtx> | |
268 | class ImageWriteSameRequest : public AbstractImageWriteRequest<ImageCtxT> { | |
269 | public: | |
270 | ImageWriteSameRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, | |
271 | uint64_t off, uint64_t len, bufferlist &&bl, | |
272 | int op_flags) | |
273 | : AbstractImageWriteRequest<ImageCtxT>(image_ctx, aio_comp, {{off, len}}), | |
274 | m_data_bl(std::move(bl)), m_op_flags(op_flags) { | |
275 | } | |
276 | ||
277 | protected: | |
278 | using typename ImageRequest<ImageCtxT>::ObjectRequests; | |
279 | using typename AbstractImageWriteRequest<ImageCtxT>::ObjectExtents; | |
280 | ||
281 | aio_type_t get_aio_type() const override { | |
282 | return AIO_TYPE_WRITESAME; | |
283 | } | |
284 | const char *get_request_type() const override { | |
285 | return "aio_writesame"; | |
286 | } | |
287 | ||
288 | bool assemble_writesame_extent(const ObjectExtent &object_extent, | |
289 | bufferlist *bl, bool force_write); | |
290 | ||
291 | void send_image_cache_request() override; | |
292 | ||
293 | void send_object_cache_requests(const ObjectExtents &object_extents, | |
294 | uint64_t journal_tid) override; | |
295 | ||
296 | void send_object_requests(const ObjectExtents &object_extents, | |
297 | const ::SnapContext &snapc, | |
298 | ObjectRequests *object_requests) override; | |
299 | ObjectRequestHandle *create_object_request( | |
300 | const ObjectExtent &object_extent, const ::SnapContext &snapc, | |
301 | Context *on_finish) override; | |
302 | ||
303 | uint64_t append_journal_event(const ObjectRequests &requests, | |
304 | bool synchronous) override; | |
305 | void update_stats(size_t length) override; | |
306 | private: | |
307 | bufferlist m_data_bl; | |
308 | int m_op_flags; | |
309 | }; | |
310 | ||
311 | } // namespace io | |
312 | } // namespace librbd | |
313 | ||
314 | extern template class librbd::io::ImageRequest<librbd::ImageCtx>; | |
315 | extern template class librbd::io::ImageReadRequest<librbd::ImageCtx>; | |
316 | extern template class librbd::io::AbstractImageWriteRequest<librbd::ImageCtx>; | |
317 | extern template class librbd::io::ImageWriteRequest<librbd::ImageCtx>; | |
318 | extern template class librbd::io::ImageDiscardRequest<librbd::ImageCtx>; | |
319 | extern template class librbd::io::ImageFlushRequest<librbd::ImageCtx>; | |
320 | extern template class librbd::io::ImageWriteSameRequest<librbd::ImageCtx>; | |
321 | ||
322 | #endif // CEPH_LIBRBD_IO_IMAGE_REQUEST_H |