]>
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 | #include "common/dout.h" | |
5 | #include "common/errno.h" | |
11fdf7f2 | 6 | #include "include/ceph_assert.h" |
7c673cae FG |
7 | #include "librbd/Utils.h" |
8 | #include "common/Timer.h" | |
7c673cae FG |
9 | #include "journal/Settings.h" |
10 | #include "librbd/journal/CreateRequest.h" | |
11 | #include "librbd/journal/RemoveRequest.h" | |
12 | ||
13 | #define dout_subsys ceph_subsys_rbd | |
14 | #undef dout_prefix | |
15 | #define dout_prefix *_dout << "librbd::Journal::CreateRequest: " | |
16 | ||
17 | namespace librbd { | |
18 | ||
19 | using util::create_context_callback; | |
20 | ||
21 | namespace journal { | |
22 | ||
23 | template<typename I> | |
24 | CreateRequest<I>::CreateRequest(IoCtx &ioctx, const std::string &imageid, | |
25 | uint8_t order, uint8_t splay_width, | |
26 | const std::string &object_pool, | |
27 | uint64_t tag_class, TagData &tag_data, | |
28 | const std::string &client_id, | |
29 | ContextWQ *op_work_queue, | |
30 | Context *on_finish) | |
31 | : m_ioctx(ioctx), m_image_id(imageid), m_order(order), | |
32 | m_splay_width(splay_width), m_object_pool(object_pool), | |
33 | m_tag_class(tag_class), m_tag_data(tag_data), m_image_client_id(client_id), | |
34 | m_op_work_queue(op_work_queue), m_on_finish(on_finish) { | |
35 | m_cct = reinterpret_cast<CephContext *>(m_ioctx.cct()); | |
36 | } | |
37 | ||
38 | template<typename I> | |
39 | void CreateRequest<I>::send() { | |
40 | ldout(m_cct, 20) << this << " " << __func__ << dendl; | |
41 | ||
42 | if (m_order > 64 || m_order < 12) { | |
43 | lderr(m_cct) << "order must be in the range [12, 64]" << dendl; | |
44 | complete(-EDOM); | |
45 | return; | |
46 | } | |
47 | if (m_splay_width == 0) { | |
48 | complete(-EINVAL); | |
49 | return; | |
50 | } | |
51 | ||
52 | get_pool_id(); | |
53 | } | |
54 | ||
55 | template<typename I> | |
56 | void CreateRequest<I>::get_pool_id() { | |
57 | ldout(m_cct, 20) << this << " " << __func__ << dendl; | |
58 | ||
59 | if (m_object_pool.empty()) { | |
60 | create_journal(); | |
61 | return; | |
62 | } | |
63 | ||
64 | librados::Rados rados(m_ioctx); | |
65 | IoCtx data_ioctx; | |
66 | int r = rados.ioctx_create(m_object_pool.c_str(), data_ioctx); | |
67 | if (r != 0) { | |
68 | lderr(m_cct) << "failed to create journal: " | |
69 | << "error opening journal object pool '" << m_object_pool | |
70 | << "': " << cpp_strerror(r) << dendl; | |
71 | complete(r); | |
72 | return; | |
73 | } | |
11fdf7f2 | 74 | data_ioctx.set_namespace(m_ioctx.get_namespace()); |
7c673cae FG |
75 | |
76 | m_pool_id = data_ioctx.get_id(); | |
77 | create_journal(); | |
78 | } | |
79 | ||
80 | template<typename I> | |
81 | void CreateRequest<I>::create_journal() { | |
82 | ldout(m_cct, 20) << this << " " << __func__ << dendl; | |
83 | ||
84 | ImageCtx::get_timer_instance(m_cct, &m_timer, &m_timer_lock); | |
9f95a23c TL |
85 | m_journaler = new Journaler(m_op_work_queue, m_timer, m_timer_lock, m_ioctx, |
86 | m_image_id, m_image_client_id, {}, nullptr); | |
7c673cae FG |
87 | |
88 | using klass = CreateRequest<I>; | |
89 | Context *ctx = create_context_callback<klass, &klass::handle_create_journal>(this); | |
90 | ||
91 | m_journaler->create(m_order, m_splay_width, m_pool_id, ctx); | |
92 | } | |
93 | ||
94 | template<typename I> | |
95 | Context *CreateRequest<I>::handle_create_journal(int *result) { | |
96 | ldout(m_cct, 20) << __func__ << ": r=" << *result << dendl; | |
97 | ||
98 | if (*result < 0) { | |
99 | lderr(m_cct) << "failed to create journal: " << cpp_strerror(*result) << dendl; | |
100 | shut_down_journaler(*result); | |
101 | return nullptr; | |
102 | } | |
103 | ||
104 | allocate_journal_tag(); | |
105 | return nullptr; | |
106 | } | |
107 | ||
108 | template<typename I> | |
109 | void CreateRequest<I>::allocate_journal_tag() { | |
110 | ldout(m_cct, 20) << this << " " << __func__ << dendl; | |
111 | ||
112 | using klass = CreateRequest<I>; | |
113 | Context *ctx = create_context_callback<klass, &klass::handle_journal_tag>(this); | |
114 | ||
11fdf7f2 | 115 | encode(m_tag_data, m_bl); |
7c673cae FG |
116 | m_journaler->allocate_tag(m_tag_class, m_bl, &m_tag, ctx); |
117 | } | |
118 | ||
119 | template<typename I> | |
120 | Context *CreateRequest<I>::handle_journal_tag(int *result) { | |
121 | ldout(m_cct, 20) << __func__ << ": r=" << *result << dendl; | |
122 | ||
123 | if (*result < 0) { | |
124 | lderr(m_cct) << "failed to allocate tag: " << cpp_strerror(*result) << dendl; | |
125 | shut_down_journaler(*result); | |
126 | return nullptr; | |
127 | } | |
128 | ||
129 | register_client(); | |
130 | return nullptr; | |
131 | } | |
132 | ||
133 | template<typename I> | |
134 | void CreateRequest<I>::register_client() { | |
135 | ldout(m_cct, 20) << this << " " << __func__ << dendl; | |
136 | ||
137 | m_bl.clear(); | |
11fdf7f2 | 138 | encode(ClientData{ImageClientMeta{m_tag.tag_class}}, m_bl); |
7c673cae FG |
139 | |
140 | using klass = CreateRequest<I>; | |
141 | Context *ctx = create_context_callback<klass, &klass::handle_register_client>(this); | |
142 | ||
143 | m_journaler->register_client(m_bl, ctx); | |
144 | } | |
145 | ||
146 | template<typename I> | |
147 | Context *CreateRequest<I>::handle_register_client(int *result) { | |
148 | ldout(m_cct, 20) << __func__ << ": r=" << *result << dendl; | |
149 | ||
150 | if (*result < 0) { | |
151 | lderr(m_cct) << "failed to register client: " << cpp_strerror(*result) << dendl; | |
152 | } | |
153 | ||
154 | shut_down_journaler(*result); | |
155 | return nullptr; | |
156 | } | |
157 | ||
158 | template<typename I> | |
159 | void CreateRequest<I>::shut_down_journaler(int r) { | |
160 | ldout(m_cct, 20) << this << " " << __func__ << dendl; | |
161 | ||
162 | m_r_saved = r; | |
163 | ||
164 | using klass = CreateRequest<I>; | |
165 | Context *ctx = create_context_callback<klass, &klass::handle_journaler_shutdown>(this); | |
166 | ||
167 | m_journaler->shut_down(ctx); | |
168 | } | |
169 | ||
170 | template<typename I> | |
171 | Context *CreateRequest<I>::handle_journaler_shutdown(int *result) { | |
172 | ldout(m_cct, 20) << __func__ << ": r=" << *result << dendl; | |
173 | ||
174 | if (*result < 0) { | |
175 | lderr(m_cct) << "failed to shut down journaler: " << cpp_strerror(*result) << dendl; | |
176 | } | |
177 | ||
178 | delete m_journaler; | |
179 | ||
180 | if (!m_r_saved) { | |
181 | complete(0); | |
182 | return nullptr; | |
183 | } | |
184 | ||
185 | // there was an error during journal creation, so we rollback | |
186 | // what ever was done. the easiest way to do this is to invoke | |
187 | // journal remove state machine, although it's not the most | |
188 | // cleanest approach when it comes to redundancy, but that's | |
189 | // ok during the failure path. | |
190 | remove_journal(); | |
191 | return nullptr; | |
192 | } | |
193 | ||
194 | template<typename I> | |
195 | void CreateRequest<I>::remove_journal() { | |
196 | ldout(m_cct, 20) << this << " " << __func__ << dendl; | |
197 | ||
198 | using klass = CreateRequest<I>; | |
199 | Context *ctx = create_context_callback<klass, &klass::handle_remove_journal>(this); | |
200 | ||
201 | RemoveRequest<I> *req = RemoveRequest<I>::create( | |
202 | m_ioctx, m_image_id, m_image_client_id, m_op_work_queue, ctx); | |
203 | req->send(); | |
204 | } | |
205 | ||
206 | template<typename I> | |
207 | Context *CreateRequest<I>::handle_remove_journal(int *result) { | |
208 | ldout(m_cct, 20) << __func__ << ": r=" << *result << dendl; | |
209 | ||
210 | if (*result < 0) { | |
211 | lderr(m_cct) << "error cleaning up journal after creation failed: " | |
212 | << cpp_strerror(*result) << dendl; | |
213 | } | |
214 | ||
215 | complete(m_r_saved); | |
216 | return nullptr; | |
217 | } | |
218 | ||
219 | template<typename I> | |
220 | void CreateRequest<I>::complete(int r) { | |
221 | ldout(m_cct, 20) << this << " " << __func__ << dendl; | |
222 | ||
223 | if (r == 0) { | |
224 | ldout(m_cct, 20) << "done." << dendl; | |
225 | } | |
226 | ||
227 | m_on_finish->complete(r); | |
228 | delete this; | |
229 | } | |
230 | ||
231 | } // namespace journal | |
232 | } // namespace librbd | |
233 | ||
234 | template class librbd::journal::CreateRequest<librbd::ImageCtx>; |