]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/trash/RemoveRequest.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / librbd / trash / RemoveRequest.cc
CommitLineData
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
20namespace librbd {
21namespace trash {
22
23using util::create_context_callback;
24using util::create_rados_callback;
25
26template <typename I>
27void RemoveRequest<I>::send() {
28 set_state();
29}
30
31template <typename I>
32void 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
46template <typename I>
47void 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
72template <typename I>
73void 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
86template <typename I>
87void 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
98template <typename I>
99void 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
116template <typename I>
117void 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
134template <typename I>
135void 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
148template <typename I>
149void 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
159template <typename I>
160void 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
170template class librbd::trash::RemoveRequest<librbd::ImageCtx>;