Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / librbd / object_map / SnapshotRemoveRequest.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/object_map/SnapshotRemoveRequest.h"
5 #include "common/dout.h"
6 #include "common/errno.h"
7 #include "librbd/ImageCtx.h"
8 #include "librbd/ObjectMap.h"
9 #include "librbd/object_map/InvalidateRequest.h"
10 #include "cls/lock/cls_lock_client.h"
11
12 #define dout_subsys ceph_subsys_rbd
13 #undef dout_prefix
14 #define dout_prefix *_dout << "librbd::object_map::SnapshotRemoveRequest: "
15
16 namespace librbd {
17 namespace object_map {
18
19 namespace {
20
21 std::ostream& operator<<(std::ostream& os,
22                          const SnapshotRemoveRequest::State& state) {
23   switch(state) {
24   case SnapshotRemoveRequest::STATE_LOAD_MAP:
25     os << "LOAD_MAP";
26     break;
27   case SnapshotRemoveRequest::STATE_REMOVE_SNAPSHOT:
28     os << "REMOVE_SNAPSHOT";
29     break;
30   case SnapshotRemoveRequest::STATE_INVALIDATE_NEXT_MAP:
31     os << "INVALIDATE_NEXT_MAP";
32     break;
33   case SnapshotRemoveRequest::STATE_REMOVE_MAP:
34     os << "REMOVE_MAP";
35     break;
36   default:
37     os << "UNKNOWN (" << static_cast<uint32_t>(state) << ")";
38     break;
39   }
40   return os;
41 }
42
43 } // anonymous namespace
44
45 void SnapshotRemoveRequest::send() {
46   assert(m_image_ctx.owner_lock.is_locked());
47   assert(m_image_ctx.snap_lock.is_wlocked());
48
49   if ((m_image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0) {
50     compute_next_snap_id();
51
52     uint64_t flags;
53     int r = m_image_ctx.get_flags(m_snap_id, &flags);
54     assert(r == 0);
55
56     if ((flags & RBD_FLAG_OBJECT_MAP_INVALID) != 0) {
57       send_invalidate_next_map();
58     } else {
59       send_load_map();
60     }
61   } else {
62     send_remove_map();
63   }
64 }
65
66 bool SnapshotRemoveRequest::should_complete(int r) {
67   CephContext *cct = m_image_ctx.cct;
68   ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", "
69                 << "r=" << r << dendl;
70
71   RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
72   bool finished = false;
73   switch (m_state) {
74   case STATE_LOAD_MAP:
75     if (r == -ENOENT) {
76       finished = true;
77       break;
78     }
79
80     if (r == 0) {
81       bufferlist::iterator it = m_out_bl.begin();
82       r = cls_client::object_map_load_finish(&it, &m_snap_object_map);
83     }
84     if (r < 0) {
85       RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
86       send_invalidate_next_map();
87     } else {
88       send_remove_snapshot();
89     }
90     break;
91   case STATE_REMOVE_SNAPSHOT:
92     if (r < 0 && r != -ENOENT) {
93       RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
94       send_invalidate_next_map();
95     } else {
96       update_object_map();
97       send_remove_map();
98     }
99     break;
100   case STATE_INVALIDATE_NEXT_MAP:
101     send_remove_map();
102     break;
103   case STATE_REMOVE_MAP:
104     finished = true;
105     break;
106   default:
107     assert(false);
108     break;
109   }
110   return finished;
111 }
112
113 void SnapshotRemoveRequest::send_load_map() {
114   CephContext *cct = m_image_ctx.cct;
115   std::string snap_oid(ObjectMap<>::object_map_name(m_image_ctx.id, m_snap_id));
116   ldout(cct, 5) << this << " " << __func__ << ": snap_oid=" << snap_oid
117                 << dendl;
118   m_state = STATE_LOAD_MAP;
119
120   librados::ObjectReadOperation op;
121   cls_client::object_map_load_start(&op);
122
123   librados::AioCompletion *rados_completion = create_callback_completion();
124   int r = m_image_ctx.md_ctx.aio_operate(snap_oid, rados_completion, &op,
125                                          &m_out_bl);
126   assert(r == 0);
127   rados_completion->release();
128 }
129
130 void SnapshotRemoveRequest::send_remove_snapshot() {
131   CephContext *cct = m_image_ctx.cct;
132   std::string oid(ObjectMap<>::object_map_name(m_image_ctx.id, m_next_snap_id));
133   ldout(cct, 5) << this << " " << __func__ << ": oid=" << oid << dendl;
134   m_state = STATE_REMOVE_SNAPSHOT;
135
136   librados::ObjectWriteOperation op;
137   if (m_next_snap_id == CEPH_NOSNAP) {
138     rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", "");
139   }
140   cls_client::object_map_snap_remove(&op, m_snap_object_map);
141
142   librados::AioCompletion *rados_completion = create_callback_completion();
143   int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op);
144   assert(r == 0);
145   rados_completion->release();
146 }
147
148 void SnapshotRemoveRequest::send_invalidate_next_map() {
149   assert(m_image_ctx.owner_lock.is_locked());
150   assert(m_image_ctx.snap_lock.is_wlocked());
151
152   CephContext *cct = m_image_ctx.cct;
153   ldout(cct, 5) << this << " " << __func__ << dendl;
154   m_state = STATE_INVALIDATE_NEXT_MAP;
155
156   InvalidateRequest<> *req = new InvalidateRequest<>(m_image_ctx,
157                                                      m_next_snap_id, true,
158                                                      create_callback_context());
159   req->send();
160 }
161
162 void SnapshotRemoveRequest::send_remove_map() {
163   CephContext *cct = m_image_ctx.cct;
164   std::string oid(ObjectMap<>::object_map_name(m_image_ctx.id, m_snap_id));
165   ldout(cct, 5) << this << " " << __func__ << ": oid=" << oid << dendl;
166   m_state = STATE_REMOVE_MAP;
167
168   librados::ObjectWriteOperation op;
169   op.remove();
170
171   librados::AioCompletion *rados_completion = create_callback_completion();
172   int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op);
173   assert(r == 0);
174   rados_completion->release();
175 }
176
177 void SnapshotRemoveRequest::compute_next_snap_id() {
178   assert(m_image_ctx.snap_lock.is_locked());
179
180   m_next_snap_id = CEPH_NOSNAP;
181   std::map<librados::snap_t, SnapInfo>::const_iterator it =
182     m_image_ctx.snap_info.find(m_snap_id);
183   assert(it != m_image_ctx.snap_info.end());
184
185   ++it;
186   if (it != m_image_ctx.snap_info.end()) {
187     m_next_snap_id = it->first;
188   }
189 }
190
191 void SnapshotRemoveRequest::update_object_map() {
192   RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
193   RWLock::WLocker object_map_locker(m_image_ctx.object_map_lock);
194   if (m_next_snap_id == m_image_ctx.snap_id && m_next_snap_id == CEPH_NOSNAP) {
195     CephContext *cct = m_image_ctx.cct;
196     ldout(cct, 5) << this << " " << __func__ << dendl;
197
198     for (uint64_t i = 0; i < m_object_map.size(); ++i) {
199       if (m_object_map[i] == OBJECT_EXISTS_CLEAN &&
200           (i >= m_snap_object_map.size() ||
201            m_snap_object_map[i] == OBJECT_EXISTS)) {
202         m_object_map[i] = OBJECT_EXISTS;
203       }
204     }
205   }
206 }
207
208 } // namespace object_map
209 } // namespace librbd