]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/image/ListWatchersRequest.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / librbd / image / ListWatchersRequest.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 "ListWatchersRequest.h"
5 #include "common/RWLock.h"
6 #include "common/dout.h"
7 #include "common/errno.h"
8 #include "cls/rbd/cls_rbd_client.h"
9 #include "librbd/ImageCtx.h"
10 #include "librbd/ImageWatcher.h"
11 #include "librbd/Utils.h"
12
13 #include <algorithm>
14
15 #define dout_subsys ceph_subsys_rbd
16 #undef dout_prefix
17 #define dout_prefix *_dout << "librbd::image::ListWatchersRequest: " << this \
18 << " " << __func__ << ": "
19
20 namespace librbd {
21 namespace image {
22
23 using librados::IoCtx;
24 using util::create_rados_callback;
25
26 template<typename I>
27 ListWatchersRequest<I>::ListWatchersRequest(I &image_ctx, int flags,
28 std::list<obj_watch_t> *watchers,
29 Context *on_finish)
30 : m_image_ctx(image_ctx), m_flags(flags), m_watchers(watchers),
31 m_on_finish(on_finish), m_cct(m_image_ctx.cct) {
32 ceph_assert((m_flags & LIST_WATCHERS_FILTER_OUT_MIRROR_INSTANCES) == 0 ||
33 (m_flags & LIST_WATCHERS_MIRROR_INSTANCES_ONLY) == 0);
34 }
35
36 template<typename I>
37 void ListWatchersRequest<I>::send() {
38 ldout(m_cct, 20) << dendl;
39
40 list_image_watchers();
41 }
42
43 template<typename I>
44 void ListWatchersRequest<I>::list_image_watchers() {
45 ldout(m_cct, 20) << dendl;
46
47 librados::ObjectReadOperation op;
48 op.list_watchers(&m_object_watchers, &m_ret_val);
49
50 using klass = ListWatchersRequest<I>;
51 librados::AioCompletion *rados_completion =
52 create_rados_callback<klass, &klass::handle_list_image_watchers>(this);
53
54 int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
55 rados_completion, &op, &m_out_bl);
56 ceph_assert(r == 0);
57 rados_completion->release();
58 }
59
60 template<typename I>
61 void ListWatchersRequest<I>::handle_list_image_watchers(int r) {
62 ldout(m_cct, 20) << "r=" << r << dendl;
63
64 if (r == 0 && m_ret_val < 0) {
65 r = m_ret_val;
66 }
67 if (r < 0) {
68 lderr(m_cct) << "error listing image watchers: " << cpp_strerror(r)
69 << dendl;
70 finish(r);
71 return;
72 }
73
74 list_mirror_watchers();
75 }
76
77 template<typename I>
78 void ListWatchersRequest<I>::list_mirror_watchers() {
79 if ((m_object_watchers.empty()) ||
80 (m_flags & (LIST_WATCHERS_FILTER_OUT_MIRROR_INSTANCES |
81 LIST_WATCHERS_MIRROR_INSTANCES_ONLY)) == 0) {
82 finish(0);
83 return;
84 }
85
86 ldout(m_cct, 20) << dendl;
87
88 librados::ObjectReadOperation op;
89 op.list_watchers(&m_mirror_watchers, &m_ret_val);
90
91 using klass = ListWatchersRequest<I>;
92 librados::AioCompletion *rados_completion =
93 create_rados_callback<klass, &klass::handle_list_mirror_watchers>(this);
94 m_out_bl.clear();
95 int r = m_image_ctx.md_ctx.aio_operate(RBD_MIRRORING, rados_completion,
96 &op, &m_out_bl);
97 ceph_assert(r == 0);
98 rados_completion->release();
99 }
100
101 template<typename I>
102 void ListWatchersRequest<I>::handle_list_mirror_watchers(int r) {
103 ldout(m_cct, 20) << "r=" << r << dendl;
104
105 if (r == 0 && m_ret_val < 0) {
106 r = m_ret_val;
107 }
108 if (r < 0 && r != -ENOENT) {
109 ldout(m_cct, 1) << "error listing mirror watchers: " << cpp_strerror(r)
110 << dendl;
111 }
112 finish(0);
113 }
114
115 template<typename I>
116 void ListWatchersRequest<I>::finish(int r) {
117 ldout(m_cct, 20) << "r=" << r << dendl;
118
119 if (r == 0) {
120 m_watchers->clear();
121
122 if (m_object_watchers.size() > 0) {
123 std::shared_lock owner_locker{m_image_ctx.owner_lock};
124 uint64_t watch_handle = m_image_ctx.image_watcher != nullptr ?
125 m_image_ctx.image_watcher->get_watch_handle() : 0;
126
127 for (auto &w : m_object_watchers) {
128 if ((m_flags & LIST_WATCHERS_FILTER_OUT_MY_INSTANCE) != 0) {
129 if (w.cookie == watch_handle) {
130 continue;
131 }
132 }
133 auto it = std::find_if(m_mirror_watchers.begin(),
134 m_mirror_watchers.end(),
135 [w] (obj_watch_t &watcher) {
136 return (strncmp(w.addr, watcher.addr,
137 sizeof(w.addr)) == 0);
138 });
139 if ((m_flags & LIST_WATCHERS_FILTER_OUT_MIRROR_INSTANCES) != 0) {
140 if (it != m_mirror_watchers.end()) {
141 continue;
142 }
143 } else if ((m_flags & LIST_WATCHERS_MIRROR_INSTANCES_ONLY) != 0) {
144 if (it == m_mirror_watchers.end()) {
145 continue;
146 }
147 }
148 m_watchers->push_back(w);
149 }
150 }
151 }
152
153 m_on_finish->complete(r);
154 delete this;
155 }
156
157 } // namespace image
158 } // namespace librbd
159
160 template class librbd::image::ListWatchersRequest<librbd::ImageCtx>;