]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/ImageWatcher.h
2d97467617e8dfb3f8ad219bee324e7780517bfb
[ceph.git] / ceph / src / librbd / ImageWatcher.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_IMAGE_WATCHER_H
5 #define CEPH_LIBRBD_IMAGE_WATCHER_H
6
7 #include "cls/rbd/cls_rbd_types.h"
8 #include "common/AsyncOpTracker.h"
9 #include "common/ceph_mutex.h"
10 #include "include/Context.h"
11 #include "include/rbd/librbd.hpp"
12 #include "librbd/Watcher.h"
13 #include "librbd/WatchNotifyTypes.h"
14 #include <set>
15 #include <string>
16 #include <utility>
17
18 class entity_name_t;
19
20 namespace librbd {
21
22 namespace watcher {
23 namespace util {
24 template <typename> struct HandlePayloadVisitor;
25 }
26 }
27
28 class ImageCtx;
29 template <typename> class TaskFinisher;
30
31 template <typename ImageCtxT = ImageCtx>
32 class ImageWatcher : public Watcher {
33 friend struct watcher::util::HandlePayloadVisitor<ImageWatcher<ImageCtxT>>;
34
35 public:
36 ImageWatcher(ImageCtxT& image_ctx);
37 ~ImageWatcher() override;
38
39 void unregister_watch(Context *on_finish) override;
40 void block_notifies(Context *on_finish) override;
41
42 void notify_flatten(uint64_t request_id, ProgressContext &prog_ctx,
43 Context *on_finish);
44 void notify_resize(uint64_t request_id, uint64_t size, bool allow_shrink,
45 ProgressContext &prog_ctx, Context *on_finish);
46 void notify_snap_create(const cls::rbd::SnapshotNamespace &snap_namespace,
47 const std::string &snap_name,
48 Context *on_finish);
49 void notify_snap_rename(const snapid_t &src_snap_id,
50 const std::string &dst_snap_name,
51 Context *on_finish);
52 void notify_snap_remove(const cls::rbd::SnapshotNamespace &snap_namespace,
53 const std::string &snap_name,
54 Context *on_finish);
55 void notify_snap_protect(const cls::rbd::SnapshotNamespace &snap_namespace,
56 const std::string &snap_name,
57 Context *on_finish);
58 void notify_snap_unprotect(const cls::rbd::SnapshotNamespace &snap_namespace,
59 const std::string &snap_name,
60 Context *on_finish);
61 void notify_rebuild_object_map(uint64_t request_id,
62 ProgressContext &prog_ctx, Context *on_finish);
63 void notify_rename(const std::string &image_name, Context *on_finish);
64
65 void notify_update_features(uint64_t features, bool enabled,
66 Context *on_finish);
67
68 void notify_migrate(uint64_t request_id, ProgressContext &prog_ctx,
69 Context *on_finish);
70
71 void notify_sparsify(uint64_t request_id, size_t sparse_size,
72 ProgressContext &prog_ctx, Context *on_finish);
73
74 void notify_acquired_lock();
75 void notify_released_lock();
76 void notify_request_lock();
77
78 void notify_header_update(Context *on_finish);
79 static void notify_header_update(librados::IoCtx &io_ctx,
80 const std::string &oid);
81
82 private:
83 enum TaskCode {
84 TASK_CODE_REQUEST_LOCK,
85 TASK_CODE_CANCEL_ASYNC_REQUESTS,
86 TASK_CODE_REREGISTER_WATCH,
87 TASK_CODE_ASYNC_REQUEST,
88 TASK_CODE_ASYNC_PROGRESS
89 };
90
91 typedef std::pair<Context *, ProgressContext *> AsyncRequest;
92
93 class Task {
94 public:
95 Task(TaskCode task_code) : m_task_code(task_code) {}
96 Task(TaskCode task_code, const watch_notify::AsyncRequestId &id)
97 : m_task_code(task_code), m_async_request_id(id) {}
98
99 inline bool operator<(const Task& rhs) const {
100 if (m_task_code != rhs.m_task_code) {
101 return m_task_code < rhs.m_task_code;
102 } else if ((m_task_code == TASK_CODE_ASYNC_REQUEST ||
103 m_task_code == TASK_CODE_ASYNC_PROGRESS) &&
104 m_async_request_id != rhs.m_async_request_id) {
105 return m_async_request_id < rhs.m_async_request_id;
106 }
107 return false;
108 }
109 private:
110 TaskCode m_task_code;
111 watch_notify::AsyncRequestId m_async_request_id;
112 };
113
114 class RemoteProgressContext : public ProgressContext {
115 public:
116 RemoteProgressContext(ImageWatcher &image_watcher,
117 const watch_notify::AsyncRequestId &id)
118 : m_image_watcher(image_watcher), m_async_request_id(id)
119 {
120 }
121
122 int update_progress(uint64_t offset, uint64_t total) override {
123 m_image_watcher.schedule_async_progress(m_async_request_id, offset,
124 total);
125 return 0;
126 }
127
128 private:
129 ImageWatcher &m_image_watcher;
130 watch_notify::AsyncRequestId m_async_request_id;
131 };
132
133 class RemoteContext : public Context {
134 public:
135 RemoteContext(ImageWatcher &image_watcher,
136 const watch_notify::AsyncRequestId &id,
137 ProgressContext *prog_ctx)
138 : m_image_watcher(image_watcher), m_async_request_id(id),
139 m_prog_ctx(prog_ctx)
140 {
141 }
142
143 ~RemoteContext() override {
144 delete m_prog_ctx;
145 }
146
147 void finish(int r) override;
148
149 private:
150 ImageWatcher &m_image_watcher;
151 watch_notify::AsyncRequestId m_async_request_id;
152 ProgressContext *m_prog_ctx;
153 };
154
155 struct C_ProcessPayload;
156 struct C_ResponseMessage : public Context {
157 C_NotifyAck *notify_ack;
158
159 C_ResponseMessage(C_NotifyAck *notify_ack) : notify_ack(notify_ack) {
160 }
161 void finish(int r) override;
162 };
163
164 ImageCtxT &m_image_ctx;
165
166 TaskFinisher<Task> *m_task_finisher;
167
168 ceph::shared_mutex m_async_request_lock;
169 std::map<watch_notify::AsyncRequestId, AsyncRequest> m_async_requests;
170 std::set<watch_notify::AsyncRequestId> m_async_pending;
171
172 ceph::mutex m_owner_client_id_lock;
173 watch_notify::ClientId m_owner_client_id;
174
175 AsyncOpTracker m_async_op_tracker;
176
177 void handle_register_watch(int r);
178
179 void schedule_cancel_async_requests();
180 void cancel_async_requests();
181
182 void set_owner_client_id(const watch_notify::ClientId &client_id);
183 watch_notify::ClientId get_client_id();
184
185 void handle_request_lock(int r);
186 void schedule_request_lock(bool use_timer, int timer_delay = -1);
187
188 void notify_lock_owner(const watch_notify::Payload& payload,
189 Context *on_finish);
190
191 Context *remove_async_request(const watch_notify::AsyncRequestId &id);
192 void schedule_async_request_timed_out(const watch_notify::AsyncRequestId &id);
193 void async_request_timed_out(const watch_notify::AsyncRequestId &id);
194 void notify_async_request(const watch_notify::AsyncRequestId &id,
195 const watch_notify::Payload &payload,
196 ProgressContext& prog_ctx,
197 Context *on_finish);
198
199 void schedule_async_progress(const watch_notify::AsyncRequestId &id,
200 uint64_t offset, uint64_t total);
201 int notify_async_progress(const watch_notify::AsyncRequestId &id,
202 uint64_t offset, uint64_t total);
203 void schedule_async_complete(const watch_notify::AsyncRequestId &id, int r);
204 void notify_async_complete(const watch_notify::AsyncRequestId &id, int r);
205 void handle_async_complete(const watch_notify::AsyncRequestId &request, int r,
206 int ret_val);
207
208 int prepare_async_request(const watch_notify::AsyncRequestId& id,
209 bool* new_request, Context** ctx,
210 ProgressContext** prog_ctx);
211
212 bool handle_payload(const watch_notify::HeaderUpdatePayload& payload,
213 C_NotifyAck *ctx);
214 bool handle_payload(const watch_notify::AcquiredLockPayload& payload,
215 C_NotifyAck *ctx);
216 bool handle_payload(const watch_notify::ReleasedLockPayload& payload,
217 C_NotifyAck *ctx);
218 bool handle_payload(const watch_notify::RequestLockPayload& payload,
219 C_NotifyAck *ctx);
220 bool handle_payload(const watch_notify::AsyncProgressPayload& payload,
221 C_NotifyAck *ctx);
222 bool handle_payload(const watch_notify::AsyncCompletePayload& payload,
223 C_NotifyAck *ctx);
224 bool handle_payload(const watch_notify::FlattenPayload& payload,
225 C_NotifyAck *ctx);
226 bool handle_payload(const watch_notify::ResizePayload& payload,
227 C_NotifyAck *ctx);
228 bool handle_payload(const watch_notify::SnapCreatePayload& payload,
229 C_NotifyAck *ctx);
230 bool handle_payload(const watch_notify::SnapRenamePayload& payload,
231 C_NotifyAck *ctx);
232 bool handle_payload(const watch_notify::SnapRemovePayload& payload,
233 C_NotifyAck *ctx);
234 bool handle_payload(const watch_notify::SnapProtectPayload& payload,
235 C_NotifyAck *ctx);
236 bool handle_payload(const watch_notify::SnapUnprotectPayload& payload,
237 C_NotifyAck *ctx);
238 bool handle_payload(const watch_notify::RebuildObjectMapPayload& payload,
239 C_NotifyAck *ctx);
240 bool handle_payload(const watch_notify::RenamePayload& payload,
241 C_NotifyAck *ctx);
242 bool handle_payload(const watch_notify::UpdateFeaturesPayload& payload,
243 C_NotifyAck *ctx);
244 bool handle_payload(const watch_notify::MigratePayload& payload,
245 C_NotifyAck *ctx);
246 bool handle_payload(const watch_notify::SparsifyPayload& payload,
247 C_NotifyAck *ctx);
248 bool handle_payload(const watch_notify::UnknownPayload& payload,
249 C_NotifyAck *ctx);
250 void process_payload(uint64_t notify_id, uint64_t handle,
251 const watch_notify::Payload &payload);
252
253 void handle_notify(uint64_t notify_id, uint64_t handle,
254 uint64_t notifier_id, bufferlist &bl) override;
255 void handle_error(uint64_t cookie, int err) override;
256 void handle_rewatch_complete(int r) override;
257
258 void send_notify(const watch_notify::Payload& payload,
259 Context *ctx = nullptr);
260
261 };
262
263 } // namespace librbd
264
265 extern template class librbd::ImageWatcher<librbd::ImageCtx>;
266
267 #endif // CEPH_LIBRBD_IMAGE_WATCHER_H