]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/io/AioCompletion.h
import 14.2.4 nautilus point release
[ceph.git] / ceph / src / librbd / io / AioCompletion.h
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_AIO_COMPLETION_H
5 #define CEPH_LIBRBD_IO_AIO_COMPLETION_H
6
7 #include "common/Cond.h"
8 #include "common/Mutex.h"
9 #include "common/ceph_time.h"
10 #include "include/Context.h"
11 #include "include/utime.h"
12 #include "include/rbd/librbd.hpp"
13
14 #include "librbd/ImageCtx.h"
15 #include "librbd/io/AsyncOperation.h"
16 #include "librbd/io/ReadResult.h"
17 #include "librbd/io/Types.h"
18
19 class CephContext;
20
21 namespace librbd {
22 namespace io {
23
24
25 /**
26 * AioCompletion is the overall completion for a single
27 * rbd I/O request. It may be composed of many AioObjectRequests,
28 * which each go to a single object.
29 *
30 * The retrying of individual requests is handled at a lower level,
31 * so all AioCompletion cares about is the count of outstanding
32 * requests. The number of expected individual requests should be
33 * set initially using set_request_count() prior to issuing the
34 * requests. This ensures that the completion will not be completed
35 * within the caller's thread of execution (instead via a librados
36 * context or via a thread pool context for cache read hits).
37 */
38 struct AioCompletion {
39 typedef enum {
40 AIO_STATE_PENDING = 0,
41 AIO_STATE_CALLBACK,
42 AIO_STATE_COMPLETE,
43 } aio_state_t;
44
45 mutable Mutex lock;
46 Cond cond;
47 aio_state_t state;
48 ssize_t rval;
49 callback_t complete_cb;
50 void *complete_arg;
51 rbd_completion_t rbd_comp;
52 uint32_t pending_count; ///< number of requests
53 int ref;
54 bool released;
55 ImageCtx *ictx;
56 coarse_mono_time start_time;
57 aio_type_t aio_type;
58
59 ReadResult read_result;
60
61 AsyncOperation async_op;
62
63 xlist<AioCompletion*>::item m_xlist_item;
64 bool event_notify;
65
66 template <typename T, void (T::*MF)(int)>
67 static void callback_adapter(completion_t cb, void *arg) {
68 AioCompletion *comp = reinterpret_cast<AioCompletion *>(cb);
69 T *t = reinterpret_cast<T *>(arg);
70 (t->*MF)(comp->get_return_value());
71 comp->release();
72 }
73
74 static AioCompletion *create(void *cb_arg, callback_t cb_complete,
75 rbd_completion_t rbd_comp) {
76 AioCompletion *comp = new AioCompletion();
77 comp->set_complete_cb(cb_arg, cb_complete);
78 comp->rbd_comp = (rbd_comp != nullptr ? rbd_comp : comp);
79 return comp;
80 }
81
82 template <typename T, void (T::*MF)(int) = &T::complete>
83 static AioCompletion *create(T *obj) {
84 AioCompletion *comp = new AioCompletion();
85 comp->set_complete_cb(obj, &callback_adapter<T, MF>);
86 comp->rbd_comp = comp;
87 return comp;
88 }
89
90 template <typename T, void (T::*MF)(int) = &T::complete>
91 static AioCompletion *create_and_start(T *obj, ImageCtx *image_ctx,
92 aio_type_t type) {
93 AioCompletion *comp = create<T, MF>(obj);
94 comp->init_time(image_ctx, type);
95 comp->start_op();
96 return comp;
97 }
98
99 AioCompletion() : lock("AioCompletion::lock", true, false),
100 state(AIO_STATE_PENDING), rval(0), complete_cb(NULL),
101 complete_arg(NULL), rbd_comp(NULL),
102 pending_count(0), ref(1), released(false), ictx(NULL),
103 aio_type(AIO_TYPE_NONE), m_xlist_item(this),
104 event_notify(false) {
105 }
106
107 ~AioCompletion() {
108 }
109
110 int wait_for_complete();
111
112 void finalize(ssize_t rval);
113
114 inline bool is_initialized(aio_type_t type) const {
115 Mutex::Locker locker(lock);
116 return ((ictx != nullptr) && (aio_type == type));
117 }
118 inline bool is_started() const {
119 Mutex::Locker locker(lock);
120 return async_op.started();
121 }
122
123 void init_time(ImageCtx *i, aio_type_t t);
124 void start_op();
125 void fail(int r);
126
127 void complete();
128
129 void set_complete_cb(void *cb_arg, callback_t cb) {
130 complete_cb = cb;
131 complete_arg = cb_arg;
132 }
133
134 void set_request_count(uint32_t num);
135 void add_request() {
136 lock.Lock();
137 ceph_assert(pending_count > 0);
138 lock.Unlock();
139 get();
140 }
141 void complete_request(ssize_t r);
142
143 bool is_complete();
144
145 ssize_t get_return_value();
146
147 void get() {
148 lock.Lock();
149 ceph_assert(ref > 0);
150 ref++;
151 lock.Unlock();
152 }
153 void release() {
154 lock.Lock();
155 ceph_assert(!released);
156 released = true;
157 put_unlock();
158 }
159 void put() {
160 lock.Lock();
161 put_unlock();
162 }
163 void put_unlock() {
164 ceph_assert(ref > 0);
165 int n = --ref;
166 lock.Unlock();
167 if (!n) {
168 if (ictx != nullptr && event_notify) {
169 ictx->completed_reqs_lock.Lock();
170 m_xlist_item.remove_myself();
171 ictx->completed_reqs_lock.Unlock();
172 }
173 delete this;
174 }
175 }
176
177 void set_event_notify(bool s) {
178 Mutex::Locker l(lock);
179 event_notify = s;
180 }
181
182 void *get_arg() {
183 return complete_arg;
184 }
185 };
186
187 class C_AioRequest : public Context {
188 public:
189 C_AioRequest(AioCompletion *completion) : m_completion(completion) {
190 m_completion->add_request();
191 }
192 ~C_AioRequest() override {}
193 void finish(int r) override {
194 m_completion->complete_request(r);
195 }
196 protected:
197 AioCompletion *m_completion;
198 };
199
200 } // namespace io
201 } // namespace librbd
202
203 #endif // CEPH_LIBRBD_IO_AIO_COMPLETION_H