Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / librbd / object_map / LockRequest.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/LockRequest.h"
5 #include "cls/lock/cls_lock_client.h"
6 #include "common/dout.h"
7 #include "common/errno.h"
8 #include "librbd/ImageCtx.h"
9 #include "librbd/ObjectMap.h"
10 #include "librbd/Utils.h"
11
12 #define dout_subsys ceph_subsys_rbd
13 #undef dout_prefix
14 #define dout_prefix *_dout << "librbd::object_map::LockRequest: "
15
16 namespace librbd {
17 namespace object_map {
18
19 using util::create_rados_callback;
20
21 template <typename I>
22 LockRequest<I>::LockRequest(I &image_ctx, Context *on_finish)
23   : m_image_ctx(image_ctx), m_on_finish(on_finish), m_broke_lock(false) {
24 }
25
26 template <typename I>
27 void LockRequest<I>::send() {
28   send_lock();
29 }
30
31 template <typename I>
32 void LockRequest<I>::send_lock() {
33   CephContext *cct = m_image_ctx.cct;
34   std::string oid(ObjectMap<>::object_map_name(m_image_ctx.id, CEPH_NOSNAP));
35   ldout(cct, 10) << this << " " << __func__ << ": oid=" << oid << dendl;
36
37   librados::ObjectWriteOperation op;
38   rados::cls::lock::lock(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", "", "",
39                            utime_t(), 0);
40
41   using klass = LockRequest<I>;
42   librados::AioCompletion *rados_completion =
43     create_rados_callback<klass, &klass::handle_lock>(this);
44   int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op);
45   assert(r == 0);
46   rados_completion->release();
47 }
48
49 template <typename I>
50 Context *LockRequest<I>::handle_lock(int *ret_val) {
51   CephContext *cct = m_image_ctx.cct;
52   ldout(cct, 10) << this << " " << __func__ << ": r=" << *ret_val << dendl;
53
54   if (*ret_val == 0) {
55     return m_on_finish;
56   } else if (*ret_val == -EEXIST) {
57     // already locked by myself
58     *ret_val = 0;
59     return m_on_finish;
60   } else if (m_broke_lock || *ret_val != -EBUSY) {
61     lderr(cct) << "failed to lock object map: " << cpp_strerror(*ret_val)
62                << dendl;
63     *ret_val = 0;
64     return m_on_finish;
65   }
66
67   send_get_lock_info();
68   return nullptr;
69 }
70
71 template <typename I>
72 void LockRequest<I>::send_get_lock_info() {
73   CephContext *cct = m_image_ctx.cct;
74   std::string oid(ObjectMap<>::object_map_name(m_image_ctx.id, CEPH_NOSNAP));
75   ldout(cct, 10) << this << " " << __func__ << ": oid=" << oid << dendl;
76
77   librados::ObjectReadOperation op;
78   rados::cls::lock::get_lock_info_start(&op, RBD_LOCK_NAME);
79
80   using klass = LockRequest<I>;
81   librados::AioCompletion *rados_completion =
82     create_rados_callback<klass, &klass::handle_get_lock_info>(this);
83   int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op, &m_out_bl);
84   assert(r == 0);
85   rados_completion->release();
86 }
87
88 template <typename I>
89 Context *LockRequest<I>::handle_get_lock_info(int *ret_val) {
90   CephContext *cct = m_image_ctx.cct;
91   ldout(cct, 10) << this << " " << __func__ << ": r=" << *ret_val << dendl;
92
93   if (*ret_val == -ENOENT) {
94     send_lock();
95     return nullptr;
96   }
97
98   ClsLockType lock_type;
99   std::string lock_tag;
100   if (*ret_val == 0) {
101     bufferlist::iterator it = m_out_bl.begin();
102     *ret_val = rados::cls::lock::get_lock_info_finish(&it, &m_lockers,
103                                                       &lock_type, &lock_tag);
104   }
105   if (*ret_val < 0) {
106     lderr(cct) << "failed to list object map locks: " << cpp_strerror(*ret_val)
107                << dendl;
108     *ret_val = 0;
109     return m_on_finish;
110   }
111
112   send_break_locks();
113   return nullptr;
114 }
115
116 template <typename I>
117 void LockRequest<I>::send_break_locks() {
118   CephContext *cct = m_image_ctx.cct;
119   std::string oid(ObjectMap<>::object_map_name(m_image_ctx.id, CEPH_NOSNAP));
120   ldout(cct, 10) << this << " " << __func__ << ": oid=" << oid << ", "
121                  << "num_lockers=" << m_lockers.size() << dendl;
122
123   librados::ObjectWriteOperation op;
124   for (auto &locker : m_lockers) {
125     rados::cls::lock::break_lock(&op, RBD_LOCK_NAME, locker.first.cookie,
126                                  locker.first.locker);
127   }
128
129   using klass = LockRequest<I>;
130   librados::AioCompletion *rados_completion =
131     create_rados_callback<klass, &klass::handle_break_locks>(this);
132   int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op);
133   assert(r == 0);
134   rados_completion->release();
135 }
136
137 template <typename I>
138 Context *LockRequest<I>::handle_break_locks(int *ret_val) {
139   CephContext *cct = m_image_ctx.cct;
140   ldout(cct, 10) << this << " " << __func__ << ": r=" << *ret_val << dendl;
141
142   m_broke_lock = true;
143   if (*ret_val == 0 || *ret_val == -ENOENT) {
144     send_lock();
145     return nullptr;
146   }
147
148   lderr(cct) << "failed to break object map lock: " << cpp_strerror(*ret_val)
149              << dendl;
150   *ret_val = 0;
151   return m_on_finish;
152 }
153
154 } // namespace object_map
155 } // namespace librbd
156
157 template class librbd::object_map::LockRequest<librbd::ImageCtx>;