Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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), m_snap_name(snap_name) {
37 }
38
39 template <typename I>
40 void SnapshotProtectRequest<I>::send_op() {
41   send_protect_snap();
42 }
43
44 template <typename I>
45 bool SnapshotProtectRequest<I>::should_complete(int r) {
46   I &image_ctx = this->m_image_ctx;
47   CephContext *cct = image_ctx.cct;
48   ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", "
49                 << "r=" << r << dendl;
50   if (r < 0) {
51     if (r == -EBUSY) {
52       ldout(cct, 1) << "snapshot is already protected" << dendl;
53     } else {
54       lderr(cct) << "encountered error: " << cpp_strerror(r) << dendl;
55     }
56   }
57   return true;
58 }
59
60 template <typename I>
61 void SnapshotProtectRequest<I>::send_protect_snap() {
62   I &image_ctx = this->m_image_ctx;
63   assert(image_ctx.owner_lock.is_locked());
64
65   CephContext *cct = image_ctx.cct;
66   ldout(cct, 5) << this << " " << __func__ << dendl;
67
68   m_state = STATE_PROTECT_SNAP;
69
70   int r = verify_and_send_protect_snap();
71   if (r < 0) {
72     this->async_complete(r);
73     return;
74   }
75 }
76
77 template <typename I>
78 int SnapshotProtectRequest<I>::verify_and_send_protect_snap() {
79   I &image_ctx = this->m_image_ctx;
80   RWLock::RLocker md_locker(image_ctx.md_lock);
81   RWLock::RLocker snap_locker(image_ctx.snap_lock);
82
83   CephContext *cct = image_ctx.cct;
84   if ((image_ctx.features & RBD_FEATURE_LAYERING) == 0) {
85     lderr(cct) << "image must support layering" << dendl;
86     return -ENOSYS;
87   }
88
89   uint64_t snap_id = image_ctx.get_snap_id(m_snap_namespace, m_snap_name);
90   if (snap_id == CEPH_NOSNAP) {
91     return -ENOENT;
92   }
93
94   bool is_protected;
95   int r = image_ctx.is_snap_protected(snap_id, &is_protected);
96   if (r < 0) {
97     return r;
98   }
99
100   if (is_protected) {
101     return -EBUSY;
102   }
103
104   librados::ObjectWriteOperation op;
105   cls_client::set_protection_status(&op, snap_id,
106                                     RBD_PROTECTION_STATUS_PROTECTED);
107
108   librados::AioCompletion *rados_completion =
109     this->create_callback_completion();
110   r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, rados_completion,
111                                      &op);
112   assert(r == 0);
113   rados_completion->release();
114   return 0;
115 }
116
117 } // namespace operation
118 } // namespace librbd
119
120 template class librbd::operation::SnapshotProtectRequest<librbd::ImageCtx>;