]> git.proxmox.com Git - ceph.git/blame - ceph/src/osd/osd_internal_types.h
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / osd / osd_internal_types.h
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#ifndef CEPH_OSD_INTERNAL_TYPES_H
5#define CEPH_OSD_INTERNAL_TYPES_H
6
7#include "osd_types.h"
8#include "OpRequest.h"
9f95a23c 9#include "object_state.h"
7c673cae
FG
10
11/*
12 * keep tabs on object modifications that are in flight.
13 * we need to know the projected existence, size, snapset,
14 * etc., because we don't send writes down to disk until after
15 * replicas ack.
16 */
17
18struct SnapSetContext {
19 hobject_t oid;
20 SnapSet snapset;
21 int ref;
22 bool registered : 1;
23 bool exists : 1;
24
25 explicit SnapSetContext(const hobject_t& o) :
26 oid(o), ref(0), registered(false), exists(true) { }
27};
f67539c2 28struct ObjectContext;
11fdf7f2 29typedef std::shared_ptr<ObjectContext> ObjectContextRef;
7c673cae
FG
30
31struct ObjectContext {
32 ObjectState obs;
33
34 SnapSetContext *ssc; // may be null
35
36 Context *destructor_callback;
37
7c673cae 38public:
7c673cae
FG
39
40 // any entity in obs.oi.watchers MUST be in either watchers or unconnected_watchers.
f67539c2 41 std::map<std::pair<uint64_t, entity_name_t>, WatchRef> watchers;
7c673cae
FG
42
43 // attr cache
f67539c2 44 std::map<std::string, ceph::buffer::list> attr_cache;
7c673cae 45
9f95a23c
TL
46 RWState rwstate;
47 std::list<OpRequestRef> waiters; ///< ops waiting on state change
48 bool get_read(OpRequestRef& op) {
49 if (rwstate.get_read_lock()) {
50 return true;
51 } // else
11fdf7f2 52 // Now we really need to bump up the ref-counter.
9f95a23c
TL
53 waiters.emplace_back(op);
54 rwstate.inc_waiters();
55 return false;
56 }
57 bool get_write(OpRequestRef& op, bool greedy=false) {
58 if (rwstate.get_write_lock(greedy)) {
59 return true;
60 } // else
61 if (op) {
11fdf7f2 62 waiters.emplace_back(op);
9f95a23c 63 rwstate.inc_waiters();
7c673cae 64 }
9f95a23c
TL
65 return false;
66 }
67 bool get_excl(OpRequestRef& op) {
68 if (rwstate.get_excl_lock()) {
69 return true;
70 } // else
71 if (op) {
72 waiters.emplace_back(op);
73 rwstate.inc_waiters();
7c673cae 74 }
9f95a23c
TL
75 return false;
76 }
f67539c2 77 void wake(std::list<OpRequestRef> *requeue) {
9f95a23c
TL
78 rwstate.release_waiters();
79 requeue->splice(requeue->end(), waiters);
80 }
f67539c2 81 void put_read(std::list<OpRequestRef> *requeue) {
9f95a23c
TL
82 if (rwstate.put_read()) {
83 wake(requeue);
7c673cae 84 }
7c673cae 85 }
f67539c2 86 void put_write(std::list<OpRequestRef> *requeue) {
9f95a23c
TL
87 if (rwstate.put_write()) {
88 wake(requeue);
89 }
7c673cae 90 }
f67539c2 91 void put_excl(std::list<OpRequestRef> *requeue) {
9f95a23c
TL
92 if (rwstate.put_excl()) {
93 wake(requeue);
94 }
7c673cae 95 }
9f95a23c
TL
96 bool empty() const { return rwstate.empty(); }
97
11fdf7f2 98 bool get_lock_type(OpRequestRef& op, RWState::State type) {
7c673cae
FG
99 switch (type) {
100 case RWState::RWWRITE:
101 return get_write(op);
102 case RWState::RWREAD:
103 return get_read(op);
104 case RWState::RWEXCL:
105 return get_excl(op);
106 default:
11fdf7f2 107 ceph_abort_msg("invalid lock type");
7c673cae
FG
108 return true;
109 }
110 }
11fdf7f2 111 bool get_write_greedy(OpRequestRef& op) {
9f95a23c 112 return get_write(op, true);
7c673cae
FG
113 }
114 bool get_snaptrimmer_write(bool mark_if_unsuccessful) {
9f95a23c 115 return rwstate.get_snaptrimmer_write(mark_if_unsuccessful);
7c673cae
FG
116 }
117 bool get_recovery_read() {
9f95a23c 118 return rwstate.get_recovery_read();
7c673cae
FG
119 }
120 bool try_get_read_lock() {
121 return rwstate.get_read_lock();
122 }
f67539c2 123 void drop_recovery_read(std::list<OpRequestRef> *ls) {
11fdf7f2 124 ceph_assert(rwstate.recovery_read_marker);
9f95a23c 125 put_read(ls);
7c673cae
FG
126 rwstate.recovery_read_marker = false;
127 }
128 void put_lock_type(
9f95a23c 129 RWState::State type,
f67539c2 130 std::list<OpRequestRef> *to_wake,
7c673cae
FG
131 bool *requeue_recovery,
132 bool *requeue_snaptrimmer) {
133 switch (type) {
9f95a23c
TL
134 case RWState::RWWRITE:
135 put_write(to_wake);
7c673cae 136 break;
9f95a23c
TL
137 case RWState::RWREAD:
138 put_read(to_wake);
7c673cae 139 break;
9f95a23c
TL
140 case RWState::RWEXCL:
141 put_excl(to_wake);
7c673cae
FG
142 break;
143 default:
11fdf7f2 144 ceph_abort_msg("invalid lock type");
7c673cae
FG
145 }
146 if (rwstate.empty() && rwstate.recovery_read_marker) {
147 rwstate.recovery_read_marker = false;
148 *requeue_recovery = true;
149 }
150 if (rwstate.empty() && rwstate.snaptrimmer_write_marker) {
151 rwstate.snaptrimmer_write_marker = false;
152 *requeue_snaptrimmer = true;
153 }
154 }
155 bool is_request_pending() {
9f95a23c 156 return !rwstate.empty();
7c673cae
FG
157 }
158
159 ObjectContext()
160 : ssc(NULL),
161 destructor_callback(0),
7c673cae
FG
162 blocked(false), requeue_scrub_on_unblock(false) {}
163
164 ~ObjectContext() {
11fdf7f2 165 ceph_assert(rwstate.empty());
7c673cae
FG
166 if (destructor_callback)
167 destructor_callback->complete(0);
168 }
169
170 void start_block() {
11fdf7f2 171 ceph_assert(!blocked);
7c673cae
FG
172 blocked = true;
173 }
174 void stop_block() {
11fdf7f2 175 ceph_assert(blocked);
7c673cae
FG
176 blocked = false;
177 }
178 bool is_blocked() const {
179 return blocked;
180 }
181
7c673cae
FG
182 /// in-progress copyfrom ops for this object
183 bool blocked:1;
184 bool requeue_scrub_on_unblock:1; // true if we need to requeue scrub on unblock
185
186};
187
f67539c2 188inline std::ostream& operator<<(std::ostream& out, const ObjectState& obs)
7c673cae
FG
189{
190 out << obs.oi.soid;
191 if (!obs.exists)
192 out << "(dne)";
193 return out;
194}
195
f67539c2 196inline std::ostream& operator<<(std::ostream& out, const ObjectContext& obc)
7c673cae
FG
197{
198 return out << "obc(" << obc.obs << " " << obc.rwstate << ")";
199}
200
201class ObcLockManager {
202 struct ObjectLockState {
203 ObjectContextRef obc;
9f95a23c 204 RWState::State type;
7c673cae
FG
205 ObjectLockState(
206 ObjectContextRef obc,
9f95a23c 207 RWState::State type)
11fdf7f2 208 : obc(std::move(obc)), type(type) {}
7c673cae 209 };
f67539c2 210 std::map<hobject_t, ObjectLockState> locks;
7c673cae
FG
211public:
212 ObcLockManager() = default;
213 ObcLockManager(ObcLockManager &&) = default;
214 ObcLockManager(const ObcLockManager &) = delete;
215 ObcLockManager &operator=(ObcLockManager &&) = default;
216 bool empty() const {
217 return locks.empty();
218 }
219 bool get_lock_type(
9f95a23c 220 RWState::State type,
7c673cae 221 const hobject_t &hoid,
11fdf7f2
TL
222 ObjectContextRef& obc,
223 OpRequestRef& op) {
224 ceph_assert(locks.find(hoid) == locks.end());
7c673cae 225 if (obc->get_lock_type(op, type)) {
f67539c2 226 locks.insert(std::make_pair(hoid, ObjectLockState(obc, type)));
7c673cae
FG
227 return true;
228 } else {
229 return false;
230 }
231 }
232 /// Get write lock, ignore starvation
233 bool take_write_lock(
234 const hobject_t &hoid,
235 ObjectContextRef obc) {
11fdf7f2 236 ceph_assert(locks.find(hoid) == locks.end());
7c673cae
FG
237 if (obc->rwstate.take_write_lock()) {
238 locks.insert(
f67539c2 239 std::make_pair(
9f95a23c 240 hoid, ObjectLockState(obc, RWState::RWWRITE)));
7c673cae
FG
241 return true;
242 } else {
243 return false;
244 }
245 }
246 /// Get write lock for snap trim
247 bool get_snaptrimmer_write(
248 const hobject_t &hoid,
249 ObjectContextRef obc,
250 bool mark_if_unsuccessful) {
11fdf7f2 251 ceph_assert(locks.find(hoid) == locks.end());
7c673cae
FG
252 if (obc->get_snaptrimmer_write(mark_if_unsuccessful)) {
253 locks.insert(
f67539c2 254 std::make_pair(
9f95a23c 255 hoid, ObjectLockState(obc, RWState::RWWRITE)));
7c673cae
FG
256 return true;
257 } else {
258 return false;
259 }
260 }
261 /// Get write lock greedy
262 bool get_write_greedy(
263 const hobject_t &hoid,
264 ObjectContextRef obc,
265 OpRequestRef op) {
11fdf7f2 266 ceph_assert(locks.find(hoid) == locks.end());
7c673cae
FG
267 if (obc->get_write_greedy(op)) {
268 locks.insert(
f67539c2 269 std::make_pair(
9f95a23c 270 hoid, ObjectLockState(obc, RWState::RWWRITE)));
7c673cae
FG
271 return true;
272 } else {
273 return false;
274 }
275 }
276
277 /// try get read lock
278 bool try_get_read_lock(
279 const hobject_t &hoid,
280 ObjectContextRef obc) {
11fdf7f2 281 ceph_assert(locks.find(hoid) == locks.end());
7c673cae
FG
282 if (obc->try_get_read_lock()) {
283 locks.insert(
f67539c2 284 std::make_pair(
7c673cae 285 hoid,
9f95a23c 286 ObjectLockState(obc, RWState::RWREAD)));
7c673cae
FG
287 return true;
288 } else {
289 return false;
290 }
291 }
292
293 void put_locks(
f67539c2 294 std::list<std::pair<ObjectContextRef, std::list<OpRequestRef> > > *to_requeue,
7c673cae
FG
295 bool *requeue_recovery,
296 bool *requeue_snaptrimmer) {
11fdf7f2 297 for (auto& p: locks) {
f67539c2 298 std::list<OpRequestRef> _to_requeue;
7c673cae
FG
299 p.second.obc->put_lock_type(
300 p.second.type,
301 &_to_requeue,
302 requeue_recovery,
303 requeue_snaptrimmer);
304 if (to_requeue) {
11fdf7f2
TL
305 // We can safely std::move here as the whole `locks` is going
306 // to die just after the loop.
307 to_requeue->emplace_back(std::move(p.second.obc),
308 std::move(_to_requeue));
7c673cae
FG
309 }
310 }
311 locks.clear();
312 }
313 ~ObcLockManager() {
11fdf7f2 314 ceph_assert(locks.empty());
7c673cae
FG
315 }
316};
317
318
319
320#endif