]>
Commit | Line | Data |
---|---|---|
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 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net> | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | ||
16 | #ifndef CEPH_SIMPLELOCK_H | |
17 | #define CEPH_SIMPLELOCK_H | |
18 | ||
19 | #include <boost/intrusive_ptr.hpp> | |
20 | ||
21 | #include "MDSCacheObject.h" | |
22 | #include "MDSContext.h" | |
23 | ||
24 | // -- lock types -- | |
25 | // see CEPH_LOCK_* | |
26 | ||
7c673cae FG |
27 | extern "C" { |
28 | #include "locks.h" | |
29 | } | |
30 | ||
7c673cae FG |
31 | #define CAP_ANY 0 |
32 | #define CAP_LONER 1 | |
33 | #define CAP_XLOCKER 2 | |
34 | ||
9f95a23c TL |
35 | struct MDLockCache; |
36 | struct MDLockCacheItem; | |
37 | struct MutationImpl; | |
38 | typedef boost::intrusive_ptr<MutationImpl> MutationRef; | |
7c673cae | 39 | |
9f95a23c | 40 | struct LockType { |
7c673cae FG |
41 | explicit LockType(int t) : type(t) { |
42 | switch (type) { | |
43 | case CEPH_LOCK_DN: | |
44 | case CEPH_LOCK_IAUTH: | |
45 | case CEPH_LOCK_ILINK: | |
46 | case CEPH_LOCK_IXATTR: | |
47 | case CEPH_LOCK_ISNAP: | |
48 | case CEPH_LOCK_IFLOCK: | |
49 | case CEPH_LOCK_IPOLICY: | |
50 | sm = &sm_simplelock; | |
51 | break; | |
52 | case CEPH_LOCK_IDFT: | |
53 | case CEPH_LOCK_INEST: | |
54 | sm = &sm_scatterlock; | |
55 | break; | |
56 | case CEPH_LOCK_IFILE: | |
57 | sm = &sm_filelock; | |
58 | break; | |
59 | case CEPH_LOCK_DVERSION: | |
60 | case CEPH_LOCK_IVERSION: | |
61 | sm = &sm_locallock; | |
62 | break; | |
63 | default: | |
64 | sm = 0; | |
65 | } | |
66 | } | |
67 | ||
9f95a23c TL |
68 | int type; |
69 | const sm_t *sm; | |
7c673cae FG |
70 | }; |
71 | ||
72 | ||
73 | class SimpleLock { | |
74 | public: | |
9f95a23c TL |
75 | // waiting |
76 | static const uint64_t WAIT_RD = (1<<0); // to read | |
77 | static const uint64_t WAIT_WR = (1<<1); // to write | |
78 | static const uint64_t WAIT_XLOCK = (1<<2); // to xlock (** dup) | |
79 | static const uint64_t WAIT_STABLE = (1<<2); // for a stable state | |
80 | static const uint64_t WAIT_REMOTEXLOCK = (1<<3); // for a remote xlock | |
81 | static const int WAIT_BITS = 4; | |
82 | static const uint64_t WAIT_ALL = ((1<<WAIT_BITS)-1); | |
83 | ||
11fdf7f2 | 84 | static std::string_view get_state_name(int n) { |
7c673cae FG |
85 | switch (n) { |
86 | case LOCK_UNDEF: return "UNDEF"; | |
87 | case LOCK_SYNC: return "sync"; | |
88 | case LOCK_LOCK: return "lock"; | |
89 | ||
90 | case LOCK_PREXLOCK: return "prexlock"; | |
91 | case LOCK_XLOCK: return "xlock"; | |
92 | case LOCK_XLOCKDONE: return "xlockdone"; | |
93 | case LOCK_XLOCKSNAP: return "xlocksnap"; | |
94 | case LOCK_LOCK_XLOCK: return "lock->xlock"; | |
95 | ||
96 | case LOCK_SYNC_LOCK: return "sync->lock"; | |
97 | case LOCK_LOCK_SYNC: return "lock->sync"; | |
98 | case LOCK_REMOTEXLOCK: return "remote_xlock"; | |
99 | case LOCK_EXCL: return "excl"; | |
100 | case LOCK_EXCL_SYNC: return "excl->sync"; | |
101 | case LOCK_EXCL_LOCK: return "excl->lock"; | |
102 | case LOCK_SYNC_EXCL: return "sync->excl"; | |
103 | case LOCK_LOCK_EXCL: return "lock->excl"; | |
104 | ||
105 | case LOCK_XSYN: return "xsyn"; | |
106 | case LOCK_XSYN_EXCL: return "xsyn->excl"; | |
107 | case LOCK_EXCL_XSYN: return "excl->xsyn"; | |
108 | case LOCK_XSYN_SYNC: return "xsyn->sync"; | |
b32b8144 FG |
109 | case LOCK_XSYN_LOCK: return "xsyn->lock"; |
110 | case LOCK_XSYN_MIX: return "xsyn->mix"; | |
7c673cae FG |
111 | |
112 | case LOCK_SYNC_MIX: return "sync->mix"; | |
113 | case LOCK_SYNC_MIX2: return "sync->mix(2)"; | |
114 | case LOCK_LOCK_TSYN: return "lock->tsyn"; | |
115 | ||
116 | case LOCK_MIX_LOCK: return "mix->lock"; | |
117 | case LOCK_MIX_LOCK2: return "mix->lock(2)"; | |
118 | case LOCK_MIX: return "mix"; | |
119 | case LOCK_MIX_TSYN: return "mix->tsyn"; | |
120 | ||
121 | case LOCK_TSYN_MIX: return "tsyn->mix"; | |
122 | case LOCK_TSYN_LOCK: return "tsyn->lock"; | |
123 | case LOCK_TSYN: return "tsyn"; | |
124 | ||
125 | case LOCK_MIX_SYNC: return "mix->sync"; | |
126 | case LOCK_MIX_SYNC2: return "mix->sync(2)"; | |
127 | case LOCK_EXCL_MIX: return "excl->mix"; | |
128 | case LOCK_MIX_EXCL: return "mix->excl"; | |
129 | ||
130 | case LOCK_PRE_SCAN: return "*->scan"; | |
131 | case LOCK_SCAN: return "scan"; | |
132 | ||
133 | case LOCK_SNAP_SYNC: return "snap->sync"; | |
134 | ||
11fdf7f2 | 135 | default: ceph_abort(); return std::string_view(); |
7c673cae FG |
136 | } |
137 | } | |
138 | ||
11fdf7f2 TL |
139 | static std::string_view get_lock_type_name(int t) { |
140 | switch (t) { | |
141 | case CEPH_LOCK_DN: return "dn"; | |
142 | case CEPH_LOCK_DVERSION: return "dversion"; | |
143 | case CEPH_LOCK_IVERSION: return "iversion"; | |
144 | case CEPH_LOCK_IFILE: return "ifile"; | |
145 | case CEPH_LOCK_IAUTH: return "iauth"; | |
146 | case CEPH_LOCK_ILINK: return "ilink"; | |
147 | case CEPH_LOCK_IDFT: return "idft"; | |
148 | case CEPH_LOCK_INEST: return "inest"; | |
149 | case CEPH_LOCK_IXATTR: return "ixattr"; | |
150 | case CEPH_LOCK_ISNAP: return "isnap"; | |
11fdf7f2 TL |
151 | case CEPH_LOCK_IFLOCK: return "iflock"; |
152 | case CEPH_LOCK_IPOLICY: return "ipolicy"; | |
9f95a23c | 153 | default: return "unknown"; |
11fdf7f2 TL |
154 | } |
155 | } | |
156 | ||
157 | static std::string_view get_lock_action_name(int a) { | |
158 | switch (a) { | |
159 | case LOCK_AC_SYNC: return "sync"; | |
160 | case LOCK_AC_MIX: return "mix"; | |
161 | case LOCK_AC_LOCK: return "lock"; | |
162 | case LOCK_AC_LOCKFLUSHED: return "lockflushed"; | |
163 | ||
164 | case LOCK_AC_SYNCACK: return "syncack"; | |
165 | case LOCK_AC_MIXACK: return "mixack"; | |
166 | case LOCK_AC_LOCKACK: return "lockack"; | |
167 | ||
168 | case LOCK_AC_REQSCATTER: return "reqscatter"; | |
169 | case LOCK_AC_REQUNSCATTER: return "requnscatter"; | |
170 | case LOCK_AC_NUDGE: return "nudge"; | |
171 | case LOCK_AC_REQRDLOCK: return "reqrdlock"; | |
172 | default: return "???"; | |
173 | } | |
174 | } | |
7c673cae | 175 | |
9f95a23c TL |
176 | SimpleLock(MDSCacheObject *o, LockType *lt) : |
177 | type(lt), | |
178 | parent(o) | |
179 | {} | |
180 | virtual ~SimpleLock() {} | |
7c673cae FG |
181 | |
182 | client_t get_excl_client() const { | |
183 | return have_more() ? more()->excl_client : -1; | |
184 | } | |
185 | void set_excl_client(client_t c) { | |
186 | if (c < 0 && !have_more()) | |
187 | return; // default is -1 | |
188 | more()->excl_client = c; | |
189 | } | |
190 | ||
7c673cae FG |
191 | virtual bool is_scatterlock() const { |
192 | return false; | |
193 | } | |
194 | virtual bool is_locallock() const { | |
195 | return false; | |
196 | } | |
197 | ||
198 | // parent | |
199 | MDSCacheObject *get_parent() { return parent; } | |
200 | int get_type() const { return type->type; } | |
201 | const sm_t* get_sm() const { return type->sm; } | |
202 | ||
9f95a23c TL |
203 | int get_wait_shift() const; |
204 | int get_cap_shift() const; | |
205 | int get_cap_mask() const; | |
7c673cae | 206 | |
f67539c2 | 207 | void decode_locked_state(const ceph::buffer::list& bl) { |
7c673cae FG |
208 | parent->decode_lock_state(type->type, bl); |
209 | } | |
f67539c2 | 210 | void encode_locked_state(ceph::buffer::list& bl) { |
7c673cae FG |
211 | parent->encode_lock_state(type->type, bl); |
212 | } | |
213 | void finish_waiters(uint64_t mask, int r=0) { | |
214 | parent->finish_waiting(mask << get_wait_shift(), r); | |
215 | } | |
11fdf7f2 | 216 | void take_waiting(uint64_t mask, MDSContext::vec& ls) { |
7c673cae FG |
217 | parent->take_waiting(mask << get_wait_shift(), ls); |
218 | } | |
11fdf7f2 | 219 | void add_waiter(uint64_t mask, MDSContext *c) { |
7c673cae FG |
220 | parent->add_waiter((mask << get_wait_shift()) | MDSCacheObject::WAIT_ORDERED, c); |
221 | } | |
222 | bool is_waiter_for(uint64_t mask) const { | |
223 | return parent->is_waiter_for(mask << get_wait_shift()); | |
224 | } | |
9f95a23c TL |
225 | |
226 | bool is_cached() const { | |
227 | return state_flags & CACHED; | |
228 | } | |
229 | void add_cache(MDLockCacheItem& item); | |
230 | void remove_cache(MDLockCacheItem& item); | |
1911f103 | 231 | std::vector<MDLockCache*> get_active_caches(); |
7c673cae FG |
232 | |
233 | // state | |
234 | int get_state() const { return state; } | |
235 | int set_state(int s) { | |
236 | state = s; | |
237 | //assert(!is_stable() || gather_set.size() == 0); // gather should be empty in stable states. | |
238 | return s; | |
239 | } | |
11fdf7f2 TL |
240 | void set_state_rejoin(int s, MDSContext::vec& waiters, bool survivor) { |
241 | ceph_assert(!get_parent()->is_auth()); | |
b32b8144 FG |
242 | |
243 | // If lock in the replica object was not in SYNC state when auth mds of the object failed. | |
244 | // Auth mds of the object may take xlock on the lock and change the object when replaying | |
245 | // unsafe requests. | |
246 | if (!survivor || state != LOCK_SYNC) | |
247 | mark_need_recover(); | |
248 | ||
249 | state = s; | |
250 | ||
7c673cae FG |
251 | if (is_stable()) |
252 | take_waiting(SimpleLock::WAIT_ALL, waiters); | |
253 | } | |
254 | ||
255 | bool is_stable() const { | |
256 | return get_sm()->states[state].next == 0; | |
257 | } | |
258 | bool is_unstable_and_locked() const { | |
2a845540 TL |
259 | return (!is_stable() && is_locked()); |
260 | } | |
261 | bool is_locked() const { | |
7c673cae FG |
262 | return is_rdlocked() || is_wrlocked() || is_xlocked(); |
263 | } | |
264 | int get_next_state() { | |
265 | return get_sm()->states[state].next; | |
266 | } | |
267 | ||
7c673cae FG |
268 | bool is_sync_and_unlocked() const { |
269 | return | |
270 | get_state() == LOCK_SYNC && | |
271 | !is_rdlocked() && | |
272 | !is_leased() && | |
273 | !is_wrlocked() && | |
274 | !is_xlocked(); | |
275 | } | |
276 | ||
7c673cae FG |
277 | /* |
278 | bool fw_rdlock_to_auth() { | |
279 | return get_sm()->states[state].can_rdlock == FW; | |
280 | } | |
281 | */ | |
282 | bool req_rdlock_from_auth() { | |
283 | return get_sm()->states[state].can_rdlock == REQ; | |
284 | } | |
285 | ||
286 | // gather set | |
f67539c2 | 287 | static std::set<int32_t> empty_gather_set; |
7c673cae FG |
288 | |
289 | // int32_t: <0 is client, >=0 is MDS rank | |
f67539c2 | 290 | const std::set<int32_t>& get_gather_set() const { |
7c673cae FG |
291 | return have_more() ? more()->gather_set : empty_gather_set; |
292 | } | |
293 | ||
294 | void init_gather() { | |
f67539c2 | 295 | for (const auto& p : parent->get_replicas()) { |
181888fb FG |
296 | more()->gather_set.insert(p.first); |
297 | } | |
7c673cae FG |
298 | } |
299 | bool is_gathering() const { | |
300 | return have_more() && !more()->gather_set.empty(); | |
301 | } | |
302 | bool is_gathering(int32_t i) const { | |
303 | return have_more() && more()->gather_set.count(i); | |
304 | } | |
305 | void clear_gather() { | |
306 | if (have_more()) | |
307 | more()->gather_set.clear(); | |
308 | } | |
309 | void remove_gather(int32_t i) { | |
310 | if (have_more()) | |
311 | more()->gather_set.erase(i); | |
312 | } | |
313 | ||
7c673cae FG |
314 | virtual bool is_dirty() const { return false; } |
315 | virtual bool is_stale() const { return false; } | |
316 | virtual bool is_flushing() const { return false; } | |
317 | virtual bool is_flushed() const { return false; } | |
318 | virtual void clear_flushed() { } | |
319 | ||
320 | // can_* | |
321 | bool can_lease(client_t client) const { | |
322 | return get_sm()->states[state].can_lease == ANY || | |
323 | (get_sm()->states[state].can_lease == AUTH && parent->is_auth()) || | |
324 | (get_sm()->states[state].can_lease == XCL && client >= 0 && get_xlock_by_client() == client); | |
325 | } | |
326 | bool can_read(client_t client) const { | |
327 | return get_sm()->states[state].can_read == ANY || | |
328 | (get_sm()->states[state].can_read == AUTH && parent->is_auth()) || | |
329 | (get_sm()->states[state].can_read == XCL && client >= 0 && get_xlock_by_client() == client); | |
330 | } | |
331 | bool can_read_projected(client_t client) const { | |
332 | return get_sm()->states[state].can_read_projected == ANY || | |
333 | (get_sm()->states[state].can_read_projected == AUTH && parent->is_auth()) || | |
334 | (get_sm()->states[state].can_read_projected == XCL && client >= 0 && get_xlock_by_client() == client); | |
335 | } | |
336 | bool can_rdlock(client_t client) const { | |
337 | return get_sm()->states[state].can_rdlock == ANY || | |
338 | (get_sm()->states[state].can_rdlock == AUTH && parent->is_auth()) || | |
339 | (get_sm()->states[state].can_rdlock == XCL && client >= 0 && get_xlock_by_client() == client); | |
340 | } | |
341 | bool can_wrlock(client_t client) const { | |
342 | return get_sm()->states[state].can_wrlock == ANY || | |
343 | (get_sm()->states[state].can_wrlock == AUTH && parent->is_auth()) || | |
344 | (get_sm()->states[state].can_wrlock == XCL && client >= 0 && (get_xlock_by_client() == client || | |
345 | get_excl_client() == client)); | |
346 | } | |
347 | bool can_force_wrlock(client_t client) const { | |
348 | return get_sm()->states[state].can_force_wrlock == ANY || | |
349 | (get_sm()->states[state].can_force_wrlock == AUTH && parent->is_auth()) || | |
350 | (get_sm()->states[state].can_force_wrlock == XCL && client >= 0 && (get_xlock_by_client() == client || | |
351 | get_excl_client() == client)); | |
352 | } | |
353 | bool can_xlock(client_t client) const { | |
354 | return get_sm()->states[state].can_xlock == ANY || | |
355 | (get_sm()->states[state].can_xlock == AUTH && parent->is_auth()) || | |
356 | (get_sm()->states[state].can_xlock == XCL && client >= 0 && get_xlock_by_client() == client); | |
357 | } | |
358 | ||
359 | // rdlock | |
360 | bool is_rdlocked() const { return num_rdlock > 0; } | |
361 | int get_rdlock() { | |
362 | if (!num_rdlock) | |
363 | parent->get(MDSCacheObject::PIN_LOCK); | |
364 | return ++num_rdlock; | |
365 | } | |
366 | int put_rdlock() { | |
11fdf7f2 | 367 | ceph_assert(num_rdlock>0); |
7c673cae FG |
368 | --num_rdlock; |
369 | if (num_rdlock == 0) | |
370 | parent->put(MDSCacheObject::PIN_LOCK); | |
371 | return num_rdlock; | |
372 | } | |
373 | int get_num_rdlocks() const { | |
374 | return num_rdlock; | |
375 | } | |
376 | ||
377 | // wrlock | |
378 | void get_wrlock(bool force=false) { | |
379 | //assert(can_wrlock() || force); | |
380 | if (more()->num_wrlock == 0) | |
381 | parent->get(MDSCacheObject::PIN_LOCK); | |
382 | ++more()->num_wrlock; | |
383 | } | |
384 | void put_wrlock() { | |
385 | --more()->num_wrlock; | |
386 | if (more()->num_wrlock == 0) { | |
387 | parent->put(MDSCacheObject::PIN_LOCK); | |
388 | try_clear_more(); | |
389 | } | |
390 | } | |
391 | bool is_wrlocked() const { | |
392 | return have_more() && more()->num_wrlock > 0; | |
393 | } | |
394 | int get_num_wrlocks() const { | |
395 | return have_more() ? more()->num_wrlock : 0; | |
396 | } | |
397 | ||
398 | // xlock | |
399 | void get_xlock(MutationRef who, client_t client) { | |
11fdf7f2 TL |
400 | ceph_assert(get_xlock_by() == MutationRef()); |
401 | ceph_assert(state == LOCK_XLOCK || is_locallock() || | |
f67539c2 | 402 | state == LOCK_LOCK /* if we are a peer */); |
7c673cae FG |
403 | parent->get(MDSCacheObject::PIN_LOCK); |
404 | more()->num_xlock++; | |
405 | more()->xlock_by = who; | |
406 | more()->xlock_by_client = client; | |
407 | } | |
408 | void set_xlock_done() { | |
11fdf7f2 TL |
409 | ceph_assert(more()->xlock_by); |
410 | ceph_assert(state == LOCK_XLOCK || is_locallock() || | |
f67539c2 | 411 | state == LOCK_LOCK /* if we are a peer */); |
7c673cae FG |
412 | if (!is_locallock()) |
413 | state = LOCK_XLOCKDONE; | |
414 | more()->xlock_by.reset(); | |
415 | } | |
416 | void put_xlock() { | |
11fdf7f2 | 417 | ceph_assert(state == LOCK_XLOCK || state == LOCK_XLOCKDONE || |
a8e16298 | 418 | state == LOCK_XLOCKSNAP || state == LOCK_LOCK_XLOCK || |
f67539c2 | 419 | state == LOCK_LOCK || /* if we are a leader of a peer */ |
aee94f69 | 420 | state == LOCK_PREXLOCK || state == LOCK_SYNC || |
a8e16298 | 421 | is_locallock()); |
7c673cae FG |
422 | --more()->num_xlock; |
423 | parent->put(MDSCacheObject::PIN_LOCK); | |
424 | if (more()->num_xlock == 0) { | |
425 | more()->xlock_by.reset(); | |
426 | more()->xlock_by_client = -1; | |
427 | try_clear_more(); | |
428 | } | |
429 | } | |
430 | bool is_xlocked() const { | |
431 | return have_more() && more()->num_xlock > 0; | |
432 | } | |
433 | int get_num_xlocks() const { | |
434 | return have_more() ? more()->num_xlock : 0; | |
435 | } | |
436 | client_t get_xlock_by_client() const { | |
437 | return have_more() ? more()->xlock_by_client : -1; | |
438 | } | |
439 | bool is_xlocked_by_client(client_t c) const { | |
440 | return have_more() ? more()->xlock_by_client == c : false; | |
441 | } | |
442 | MutationRef get_xlock_by() const { | |
443 | return have_more() ? more()->xlock_by : MutationRef(); | |
444 | } | |
445 | ||
446 | // lease | |
b32b8144 FG |
447 | bool is_leased() const { |
448 | return state_flags & LEASED; | |
449 | } | |
7c673cae | 450 | void get_client_lease() { |
11fdf7f2 | 451 | ceph_assert(!is_leased()); |
b32b8144 | 452 | state_flags |= LEASED; |
7c673cae FG |
453 | } |
454 | void put_client_lease() { | |
11fdf7f2 | 455 | ceph_assert(is_leased()); |
b32b8144 | 456 | state_flags &= ~LEASED; |
7c673cae FG |
457 | } |
458 | ||
b32b8144 FG |
459 | bool needs_recover() const { |
460 | return state_flags & NEED_RECOVER; | |
461 | } | |
462 | void mark_need_recover() { | |
463 | state_flags |= NEED_RECOVER; | |
464 | } | |
465 | void clear_need_recover() { | |
466 | state_flags &= ~NEED_RECOVER; | |
7c673cae FG |
467 | } |
468 | ||
469 | // encode/decode | |
f67539c2 | 470 | void encode(ceph::buffer::list& bl) const { |
7c673cae | 471 | ENCODE_START(2, 2, bl); |
11fdf7f2 | 472 | encode(state, bl); |
7c673cae | 473 | if (have_more()) |
11fdf7f2 | 474 | encode(more()->gather_set, bl); |
7c673cae | 475 | else |
11fdf7f2 | 476 | encode(empty_gather_set, bl); |
7c673cae FG |
477 | ENCODE_FINISH(bl); |
478 | } | |
f67539c2 | 479 | void decode(ceph::buffer::list::const_iterator& p) { |
7c673cae | 480 | DECODE_START(2, p); |
11fdf7f2 | 481 | decode(state, p); |
f67539c2 | 482 | std::set<__s32> g; |
11fdf7f2 | 483 | decode(g, p); |
7c673cae FG |
484 | if (!g.empty()) |
485 | more()->gather_set.swap(g); | |
486 | DECODE_FINISH(p); | |
487 | } | |
f67539c2 | 488 | void encode_state_for_replica(ceph::buffer::list& bl) const { |
7c673cae | 489 | __s16 s = get_replica_state(); |
11fdf7f2 TL |
490 | using ceph::encode; |
491 | encode(s, bl); | |
7c673cae | 492 | } |
f67539c2 | 493 | void decode_state(ceph::buffer::list::const_iterator& p, bool is_new=true) { |
11fdf7f2 | 494 | using ceph::decode; |
7c673cae | 495 | __s16 s; |
11fdf7f2 | 496 | decode(s, p); |
7c673cae FG |
497 | if (is_new) |
498 | state = s; | |
499 | } | |
f67539c2 | 500 | void decode_state_rejoin(ceph::buffer::list::const_iterator& p, MDSContext::vec& waiters, bool survivor) { |
7c673cae | 501 | __s16 s; |
11fdf7f2 TL |
502 | using ceph::decode; |
503 | decode(s, p); | |
b32b8144 | 504 | set_state_rejoin(s, waiters, survivor); |
7c673cae FG |
505 | } |
506 | ||
7c673cae FG |
507 | // caps |
508 | bool is_loner_mode() const { | |
509 | return get_sm()->states[state].loner; | |
510 | } | |
511 | int gcaps_allowed_ever() const { | |
512 | return parent->is_auth() ? get_sm()->allowed_ever_auth : get_sm()->allowed_ever_replica; | |
513 | } | |
514 | int gcaps_allowed(int who, int s=-1) const { | |
515 | if (s < 0) s = state; | |
516 | if (parent->is_auth()) { | |
517 | if (get_xlock_by_client() >= 0 && who == CAP_XLOCKER) | |
518 | return get_sm()->states[s].xlocker_caps | get_sm()->states[s].caps; // xlocker always gets more | |
519 | else if (is_loner_mode() && who == CAP_ANY) | |
520 | return get_sm()->states[s].caps; | |
521 | else | |
522 | return get_sm()->states[s].loner_caps | get_sm()->states[s].caps; // loner always gets more | |
523 | } else | |
524 | return get_sm()->states[s].replica_caps; | |
525 | } | |
526 | int gcaps_careful() const { | |
527 | if (get_num_wrlocks()) | |
528 | return get_sm()->careful; | |
529 | return 0; | |
530 | } | |
531 | ||
7c673cae FG |
532 | int gcaps_xlocker_mask(client_t client) const { |
533 | if (client == get_xlock_by_client()) | |
534 | return type->type == CEPH_LOCK_IFILE ? 0xf : (CEPH_CAP_GSHARED|CEPH_CAP_GEXCL); | |
535 | return 0; | |
536 | } | |
537 | ||
538 | // simplelock specifics | |
539 | int get_replica_state() const { | |
540 | return get_sm()->states[state].replica_state; | |
541 | } | |
542 | void export_twiddle() { | |
543 | clear_gather(); | |
544 | state = get_replica_state(); | |
545 | } | |
546 | ||
7c673cae FG |
547 | bool remove_replica(int from) { |
548 | if (is_gathering(from)) { | |
549 | remove_gather(from); | |
550 | if (!is_gathering()) | |
551 | return true; | |
552 | } | |
553 | return false; | |
554 | } | |
555 | bool do_import(int from, int to) { | |
556 | if (!is_stable()) { | |
557 | remove_gather(from); | |
558 | remove_gather(to); | |
559 | if (!is_gathering()) | |
560 | return true; | |
561 | } | |
562 | if (!is_stable() && !is_gathering()) | |
563 | return true; | |
564 | return false; | |
565 | } | |
566 | ||
f67539c2 | 567 | void _print(std::ostream& out) const { |
7c673cae FG |
568 | out << get_lock_type_name(get_type()) << " "; |
569 | out << get_state_name(get_state()); | |
570 | if (!get_gather_set().empty()) | |
571 | out << " g=" << get_gather_set(); | |
b32b8144 FG |
572 | if (is_leased()) |
573 | out << " l"; | |
7c673cae FG |
574 | if (is_rdlocked()) |
575 | out << " r=" << get_num_rdlocks(); | |
576 | if (is_wrlocked()) | |
577 | out << " w=" << get_num_wrlocks(); | |
578 | if (is_xlocked()) { | |
579 | out << " x=" << get_num_xlocks(); | |
580 | if (get_xlock_by()) | |
581 | out << " by " << get_xlock_by(); | |
582 | } | |
583 | /*if (is_stable()) | |
584 | out << " stable"; | |
585 | else | |
586 | out << " unstable"; | |
587 | */ | |
588 | } | |
589 | ||
590 | /** | |
591 | * Write bare values (caller must be in an object section) | |
592 | * to formatter, or nothing if is_sync_and_unlocked. | |
593 | */ | |
f67539c2 | 594 | void dump(ceph::Formatter *f) const; |
7c673cae | 595 | |
f67539c2 | 596 | virtual void print(std::ostream& out) const { |
7c673cae FG |
597 | out << "("; |
598 | _print(out); | |
599 | out << ")"; | |
600 | } | |
9f95a23c TL |
601 | |
602 | LockType *type; | |
603 | ||
604 | protected: | |
605 | // parent (what i lock) | |
606 | MDSCacheObject *parent; | |
607 | ||
608 | // lock state | |
609 | __s16 state = LOCK_SYNC; | |
610 | __s16 state_flags = 0; | |
611 | ||
612 | enum { | |
613 | LEASED = 1 << 0, | |
614 | NEED_RECOVER = 1 << 1, | |
615 | CACHED = 1 << 2, | |
616 | }; | |
617 | ||
618 | private: | |
619 | // XXX not in mempool | |
620 | struct unstable_bits_t { | |
621 | unstable_bits_t(); | |
622 | ||
623 | bool empty() { | |
624 | return | |
625 | gather_set.empty() && | |
626 | num_wrlock == 0 && | |
627 | num_xlock == 0 && | |
628 | xlock_by.get() == NULL && | |
629 | xlock_by_client == -1 && | |
630 | excl_client == -1 && | |
631 | lock_caches.empty(); | |
632 | } | |
633 | ||
f67539c2 | 634 | std::set<__s32> gather_set; // auth+rep. >= 0 is mds, < 0 is client |
9f95a23c TL |
635 | |
636 | // local state | |
637 | int num_wrlock = 0, num_xlock = 0; | |
638 | MutationRef xlock_by; | |
639 | client_t xlock_by_client = -1; | |
640 | client_t excl_client = -1; | |
641 | ||
642 | elist<MDLockCacheItem*> lock_caches; | |
643 | }; | |
644 | ||
645 | bool have_more() const { return _unstable ? true : false; } | |
646 | unstable_bits_t *more() const { | |
647 | if (!_unstable) | |
648 | _unstable.reset(new unstable_bits_t); | |
649 | return _unstable.get(); | |
650 | } | |
651 | void try_clear_more() { | |
652 | if (_unstable && _unstable->empty()) { | |
653 | _unstable.reset(); | |
654 | } | |
655 | } | |
656 | ||
657 | int num_rdlock = 0; | |
658 | ||
659 | mutable std::unique_ptr<unstable_bits_t> _unstable; | |
7c673cae FG |
660 | }; |
661 | WRITE_CLASS_ENCODER(SimpleLock) | |
662 | ||
f67539c2 | 663 | inline std::ostream& operator<<(std::ostream& out, const SimpleLock& l) |
7c673cae FG |
664 | { |
665 | l.print(out); | |
666 | return out; | |
667 | } | |
7c673cae | 668 | #endif |