]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/trash/RemoveRequest.cc
import ceph 14.2.5
[ceph.git] / ceph / src / librbd / trash / RemoveRequest.cc
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"
5 #include "common/WorkQueue.h"
6 #include "common/dout.h"
7 #include "common/errno.h"
8 #include "cls/rbd/cls_rbd_client.h"
9 #include "librbd/ExclusiveLock.h"
10 #include "librbd/ImageCtx.h"
11 #include "librbd/ImageState.h"
12 #include "librbd/Utils.h"
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
94 m_image_ctx->destroy();
95 m_image_ctx = nullptr;
96 finish(m_ret_val);
97 }
98
99 template <typename I>
100 void RemoveRequest<I>::remove_image() {
101 ldout(m_cct, 10) << dendl;
102
103 auto ctx = create_context_callback<
104 RemoveRequest<I>, &RemoveRequest<I>::handle_remove_image>(this);
105 if (m_image_ctx != nullptr) {
106 auto req = librbd::image::RemoveRequest<I>::create(
107 m_io_ctx, m_image_ctx, m_force, true, m_prog_ctx, m_op_work_queue, ctx);
108 req->send();
109 } else {
110 auto req = librbd::image::RemoveRequest<I>::create(
111 m_io_ctx, "", m_image_id, m_force, true, m_prog_ctx, m_op_work_queue,
112 ctx);
113 req->send();
114 }
115 }
116
117 template <typename I>
118 void RemoveRequest<I>::handle_remove_image(int r) {
119 ldout(m_cct, 10) << "r=" << r << dendl;
120
121 if (r < 0) {
122 ldout(m_cct, 5) << "failed to remove image:" << cpp_strerror(r) << dendl;
123
124 m_ret_val = r;
125 m_trash_set_state = cls::rbd::TRASH_IMAGE_STATE_NORMAL;
126 m_trash_expect_state = cls::rbd::TRASH_IMAGE_STATE_REMOVING;
127 set_state();
128 return;
129 }
130
131 m_image_ctx = nullptr;
132 remove_trash_entry();
133 }
134
135 template <typename I>
136 void RemoveRequest<I>::remove_trash_entry() {
137 ldout(m_cct, 10) << dendl;
138
139 librados::ObjectWriteOperation op;
140 cls_client::trash_remove(&op, m_image_id);
141
142 auto aio_comp = create_rados_callback<
143 RemoveRequest<I>, &RemoveRequest<I>::handle_remove_trash_entry>(this);
144 int r = m_io_ctx.aio_operate(RBD_TRASH, aio_comp, &op);
145 ceph_assert(r == 0);
146 aio_comp->release();
147 }
148
149 template <typename I>
150 void RemoveRequest<I>::handle_remove_trash_entry(int r) {
151 ldout(m_cct, 10) << "r=" << r << dendl;
152
153 if (r < 0 && r != -ENOENT) {
154 lderr(m_cct) << "error removing trash entry: " << cpp_strerror(r) << dendl;
155 }
156
157 finish(0);
158 }
159
160 template <typename I>
161 void RemoveRequest<I>::finish(int r) {
162 ldout(m_cct, 10) << "r=" << r << dendl;
163
164 m_on_finish->complete(r);
165 delete this;
166 }
167
168 } // namespace trash
169 } // namespace librbd
170
171 template class librbd::trash::RemoveRequest<librbd::ImageCtx>;