]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/operation/SnapshotProtectRequest.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / librbd / operation / SnapshotProtectRequest.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/operation/SnapshotProtectRequest.h"
5 #include "common/dout.h"
6 #include "common/errno.h"
7 #include "librbd/ImageCtx.h"
8
9 #define dout_subsys ceph_subsys_rbd
10 #undef dout_prefix
11 #define dout_prefix *_dout << "librbd::SnapshotProtectRequest: "
12
13 namespace librbd {
14 namespace operation {
15
16 namespace {
17
18 template <typename I>
19 std::ostream& operator<<(std::ostream& os,
20 const typename SnapshotProtectRequest<I>::State& state) {
21 switch(state) {
22 case SnapshotProtectRequest<I>::STATE_PROTECT_SNAP:
23 os << "PROTECT_SNAP";
24 break;
25 }
26 return os;
27 }
28
29 } // anonymous namespace
30
31 template <typename I>
32 SnapshotProtectRequest<I>::SnapshotProtectRequest(I &image_ctx,
33 Context *on_finish,
34 const cls::rbd::SnapshotNamespace &snap_namespace,
35 const std::string &snap_name)
36 : Request<I>(image_ctx, on_finish), m_snap_namespace(snap_namespace),
37 m_snap_name(snap_name), m_state(STATE_PROTECT_SNAP) {
38 }
39
40 template <typename I>
41 void SnapshotProtectRequest<I>::send_op() {
42 send_protect_snap();
43 }
44
45 template <typename I>
46 bool SnapshotProtectRequest<I>::should_complete(int r) {
47 I &image_ctx = this->m_image_ctx;
48 CephContext *cct = image_ctx.cct;
49 ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", "
50 << "r=" << r << dendl;
51 if (r < 0) {
52 if (r == -EBUSY) {
53 ldout(cct, 1) << "snapshot is already protected" << dendl;
54 } else {
55 lderr(cct) << "encountered error: " << cpp_strerror(r) << dendl;
56 }
57 }
58 return true;
59 }
60
61 template <typename I>
62 void SnapshotProtectRequest<I>::send_protect_snap() {
63 I &image_ctx = this->m_image_ctx;
64 ceph_assert(ceph_mutex_is_locked(image_ctx.owner_lock));
65
66 CephContext *cct = image_ctx.cct;
67 ldout(cct, 5) << this << " " << __func__ << dendl;
68
69 int r = verify_and_send_protect_snap();
70 if (r < 0) {
71 this->async_complete(r);
72 return;
73 }
74 }
75
76 template <typename I>
77 int SnapshotProtectRequest<I>::verify_and_send_protect_snap() {
78 I &image_ctx = this->m_image_ctx;
79 std::shared_lock image_locker{image_ctx.image_lock};
80
81 CephContext *cct = image_ctx.cct;
82 if ((image_ctx.features & RBD_FEATURE_LAYERING) == 0) {
83 lderr(cct) << "image must support layering" << dendl;
84 return -ENOSYS;
85 }
86
87 uint64_t snap_id = image_ctx.get_snap_id(m_snap_namespace, m_snap_name);
88 if (snap_id == CEPH_NOSNAP) {
89 return -ENOENT;
90 }
91
92 bool is_protected;
93 int r = image_ctx.is_snap_protected(snap_id, &is_protected);
94 if (r < 0) {
95 return r;
96 }
97
98 if (is_protected) {
99 return -EBUSY;
100 }
101
102 librados::ObjectWriteOperation op;
103 cls_client::set_protection_status(&op, snap_id,
104 RBD_PROTECTION_STATUS_PROTECTED);
105
106 librados::AioCompletion *rados_completion =
107 this->create_callback_completion();
108 r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, rados_completion,
109 &op);
110 ceph_assert(r == 0);
111 rados_completion->release();
112 return 0;
113 }
114
115 } // namespace operation
116 } // namespace librbd
117
118 template class librbd::operation::SnapshotProtectRequest<librbd::ImageCtx>;