]>
Commit | Line | Data |
---|---|---|
eafe8130 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include "librbd/trash/RemoveRequest.h" | |
eafe8130 TL |
5 | #include "common/dout.h" |
6 | #include "common/errno.h" | |
7 | #include "cls/rbd/cls_rbd_client.h" | |
8 | #include "librbd/ExclusiveLock.h" | |
9 | #include "librbd/ImageCtx.h" | |
10 | #include "librbd/ImageState.h" | |
11 | #include "librbd/Utils.h" | |
f67539c2 | 12 | #include "librbd/asio/ContextWQ.h" |
eafe8130 TL |
13 | #include "librbd/image/RemoveRequest.h" |
14 | ||
15 | #define dout_subsys ceph_subsys_rbd | |
16 | #undef dout_prefix | |
17 | #define dout_prefix *_dout << "librbd::trash::RemoveRequest: " << this \ | |
18 | << " " << __func__ << ": " | |
19 | ||
20 | namespace librbd { | |
21 | namespace trash { | |
22 | ||
23 | using util::create_context_callback; | |
24 | using util::create_rados_callback; | |
25 | ||
26 | template <typename I> | |
27 | void RemoveRequest<I>::send() { | |
28 | set_state(); | |
29 | } | |
30 | ||
31 | template <typename I> | |
32 | void RemoveRequest<I>::set_state() { | |
33 | ldout(m_cct, 10) << dendl; | |
34 | ||
35 | librados::ObjectWriteOperation op; | |
36 | cls_client::trash_state_set(&op, m_image_id, m_trash_set_state, | |
37 | m_trash_expect_state); | |
38 | ||
39 | auto aio_comp = create_rados_callback< | |
40 | RemoveRequest<I>, &RemoveRequest<I>::handle_set_state>(this); | |
41 | int r = m_io_ctx.aio_operate(RBD_TRASH, aio_comp, &op); | |
42 | ceph_assert(r == 0); | |
43 | aio_comp->release(); | |
44 | } | |
45 | ||
46 | template <typename I> | |
47 | void RemoveRequest<I>::handle_set_state(int r) { | |
48 | ldout(m_cct, 10) << "r=" << r << dendl; | |
49 | ||
50 | if (r < 0 && r != -EOPNOTSUPP) { | |
51 | lderr(m_cct) << "error setting trash image state: " << cpp_strerror(r) | |
52 | << dendl; | |
53 | if (m_ret_val == 0) { | |
54 | m_ret_val = r; | |
55 | } | |
56 | if (m_trash_set_state == cls::rbd::TRASH_IMAGE_STATE_REMOVING) { | |
57 | close_image(); | |
58 | } else { | |
59 | finish(m_ret_val); | |
60 | } | |
61 | return; | |
62 | } | |
63 | ||
64 | if (m_trash_set_state == cls::rbd::TRASH_IMAGE_STATE_REMOVING) { | |
65 | remove_image(); | |
66 | } else { | |
67 | ceph_assert(m_trash_set_state == cls::rbd::TRASH_IMAGE_STATE_NORMAL); | |
68 | finish(m_ret_val < 0 ? m_ret_val : r); | |
69 | }; | |
70 | } | |
71 | ||
72 | template <typename I> | |
73 | void RemoveRequest<I>::close_image() { | |
74 | if (m_image_ctx == nullptr) { | |
75 | finish(m_ret_val); | |
76 | return; | |
77 | } | |
78 | ||
79 | ldout(m_cct, 10) << dendl; | |
80 | ||
81 | auto ctx = create_context_callback< | |
82 | RemoveRequest<I>, &RemoveRequest<I>::handle_close_image>(this); | |
83 | m_image_ctx->state->close(ctx); | |
84 | } | |
85 | ||
86 | template <typename I> | |
87 | void RemoveRequest<I>::handle_close_image(int r) { | |
88 | ldout(m_cct, 10) << "r=" << r << dendl; | |
89 | ||
90 | if (r < 0) { | |
91 | ldout(m_cct, 5) << "failed to close image:" << cpp_strerror(r) << dendl; | |
92 | } | |
93 | ||
eafe8130 TL |
94 | m_image_ctx = nullptr; |
95 | finish(m_ret_val); | |
96 | } | |
97 | ||
98 | template <typename I> | |
99 | void RemoveRequest<I>::remove_image() { | |
100 | ldout(m_cct, 10) << dendl; | |
101 | ||
102 | auto ctx = create_context_callback< | |
103 | RemoveRequest<I>, &RemoveRequest<I>::handle_remove_image>(this); | |
104 | if (m_image_ctx != nullptr) { | |
105 | auto req = librbd::image::RemoveRequest<I>::create( | |
106 | m_io_ctx, m_image_ctx, m_force, true, m_prog_ctx, m_op_work_queue, ctx); | |
107 | req->send(); | |
108 | } else { | |
109 | auto req = librbd::image::RemoveRequest<I>::create( | |
110 | m_io_ctx, "", m_image_id, m_force, true, m_prog_ctx, m_op_work_queue, | |
111 | ctx); | |
112 | req->send(); | |
113 | } | |
114 | } | |
115 | ||
116 | template <typename I> | |
117 | void RemoveRequest<I>::handle_remove_image(int r) { | |
118 | ldout(m_cct, 10) << "r=" << r << dendl; | |
119 | ||
120 | if (r < 0) { | |
121 | ldout(m_cct, 5) << "failed to remove image:" << cpp_strerror(r) << dendl; | |
122 | ||
123 | m_ret_val = r; | |
124 | m_trash_set_state = cls::rbd::TRASH_IMAGE_STATE_NORMAL; | |
125 | m_trash_expect_state = cls::rbd::TRASH_IMAGE_STATE_REMOVING; | |
126 | set_state(); | |
127 | return; | |
128 | } | |
129 | ||
130 | m_image_ctx = nullptr; | |
131 | remove_trash_entry(); | |
132 | } | |
133 | ||
134 | template <typename I> | |
135 | void RemoveRequest<I>::remove_trash_entry() { | |
136 | ldout(m_cct, 10) << dendl; | |
137 | ||
138 | librados::ObjectWriteOperation op; | |
139 | cls_client::trash_remove(&op, m_image_id); | |
140 | ||
141 | auto aio_comp = create_rados_callback< | |
142 | RemoveRequest<I>, &RemoveRequest<I>::handle_remove_trash_entry>(this); | |
143 | int r = m_io_ctx.aio_operate(RBD_TRASH, aio_comp, &op); | |
144 | ceph_assert(r == 0); | |
145 | aio_comp->release(); | |
146 | } | |
147 | ||
148 | template <typename I> | |
149 | void RemoveRequest<I>::handle_remove_trash_entry(int r) { | |
150 | ldout(m_cct, 10) << "r=" << r << dendl; | |
151 | ||
152 | if (r < 0 && r != -ENOENT) { | |
153 | lderr(m_cct) << "error removing trash entry: " << cpp_strerror(r) << dendl; | |
154 | } | |
155 | ||
156 | finish(0); | |
157 | } | |
158 | ||
159 | template <typename I> | |
160 | void RemoveRequest<I>::finish(int r) { | |
161 | ldout(m_cct, 10) << "r=" << r << dendl; | |
162 | ||
163 | m_on_finish->complete(r); | |
164 | delete this; | |
165 | } | |
166 | ||
167 | } // namespace trash | |
168 | } // namespace librbd | |
169 | ||
170 | template class librbd::trash::RemoveRequest<librbd::ImageCtx>; |