]>
git.proxmox.com Git - ceph.git/blob - ceph/src/mds/ScatterLock.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
16 #ifndef CEPH_SCATTERLOCK_H
17 #define CEPH_SCATTERLOCK_H
19 #include "SimpleLock.h"
21 #include "MDSContext.h"
23 class ScatterLock
: public SimpleLock
{
26 xlist
<ScatterLock
*>::item item_updated
;
29 explicit more_bits_t(ScatterLock
*lock
) :
34 mutable std::unique_ptr
<more_bits_t
> _more
;
38 _more
.reset(new more_bits_t(this));
43 SCATTER_WANTED
= 1 << 8,
44 UNSCATTER_WANTED
= 1 << 9,
51 ScatterLock(MDSCacheObject
*o
, LockType
*lt
) :
53 ~ScatterLock() override
{
57 bool is_scatterlock() const override
{
61 bool is_sync_and_unlocked() const {
63 SimpleLock::is_sync_and_unlocked() &&
68 bool can_scatter_pin(client_t loner
) {
70 LOCK : NOT okay because it can MIX and force replicas to journal something
71 TSYN : also not okay for same reason
74 MIX : okay, replica can stall before sending AC_SYNCACK
75 SYNC : okay, replica can stall before sending AC_MIXACK or AC_LOCKACK
78 get_state() == LOCK_SYNC
||
79 get_state() == LOCK_MIX
;
82 void set_xlock_snap_sync(MDSContext
*c
)
84 ceph_assert(get_type() == CEPH_LOCK_IFILE
);
85 ceph_assert(state
== LOCK_XLOCK
|| state
== LOCK_XLOCKDONE
);
86 state
= LOCK_XLOCKSNAP
;
87 add_waiter(WAIT_STABLE
, c
);
90 xlist
<ScatterLock
*>::item
*get_updated_item() { return &more()->item_updated
; }
92 utime_t
get_update_stamp() {
93 return _more
? _more
->update_stamp
: utime_t();
96 void set_update_stamp(utime_t t
) { more()->update_stamp
= t
; }
98 void set_scatter_wanted() {
99 state_flags
|= SCATTER_WANTED
;
101 void set_unscatter_wanted() {
102 state_flags
|= UNSCATTER_WANTED
;
104 void clear_scatter_wanted() {
105 state_flags
&= ~SCATTER_WANTED
;
107 void clear_unscatter_wanted() {
108 state_flags
&= ~UNSCATTER_WANTED
;
110 bool get_scatter_wanted() const {
111 return state_flags
& SCATTER_WANTED
;
113 bool get_unscatter_wanted() const {
114 return state_flags
& UNSCATTER_WANTED
;
117 bool is_dirty() const override
{
118 return state_flags
& DIRTY
;
120 bool is_flushing() const override
{
121 return state_flags
& FLUSHING
;
123 bool is_flushed() const override
{
124 return state_flags
& FLUSHED
;
126 bool is_dirty_or_flushing() const {
127 return is_dirty() || is_flushing();
133 parent
->get(MDSCacheObject::PIN_DIRTYSCATTERED
);
143 void finish_flush() {
148 parent
->put(MDSCacheObject::PIN_DIRTYSCATTERED
);
149 parent
->clear_dirty_scattered(get_type());
153 void clear_flushed() override
{
154 state_flags
&= ~FLUSHED
;
156 void remove_dirty() {
162 void infer_state_from_strong_rejoin(int rstate
, bool locktoo
) {
163 if (rstate
== LOCK_MIX
||
164 rstate
== LOCK_MIX_LOCK
|| // replica still has wrlocks?
165 rstate
== LOCK_MIX_SYNC
)
167 else if (locktoo
&& rstate
== LOCK_LOCK
)
171 void encode_state_for_rejoin(bufferlist
& bl
, int rep
) {
172 __s16 s
= get_replica_state();
173 if (is_gathering(rep
)) {
174 // the recovering mds may hold rejoined wrlocks
175 if (state
== LOCK_MIX_SYNC
)
181 // If there is a recovering mds who replcated an object when it failed
182 // and scatterlock in the object was in MIX state, It's possible that
183 // the recovering mds needs to take wrlock on the scatterlock when it
184 // replays unsafe requests. So this mds should delay taking rdlock on
185 // the scatterlock until the recovering mds finishes replaying unsafe.
186 // Otherwise unsafe requests may get replayed after current request.
189 // The recovering mds is auth mds of a dirfrag, this mds is auth mds
190 // of corresponding inode. when 'rm -rf' the direcotry, this mds should
191 // delay the rmdir request until the recovering mds has replayed unlink
193 if (s
== LOCK_MIX
|| s
== LOCK_MIX_LOCK
|| s
== LOCK_MIX_SYNC
)
200 void decode_state_rejoin(bufferlist::const_iterator
& p
, MDSContext::vec
& waiters
, bool survivor
) {
201 SimpleLock::decode_state_rejoin(p
, waiters
, survivor
);
208 bool remove_replica(int from
, bool rejoin
) {
210 (state
== LOCK_MIX
||
211 state
== LOCK_MIX_SYNC
||
212 state
== LOCK_MIX_LOCK2
||
213 state
== LOCK_MIX_TSYN
||
214 state
== LOCK_MIX_EXCL
))
216 return SimpleLock::remove_replica(from
);
219 void print(ostream
& out
) const override
{
228 if (get_scatter_wanted())
229 out
<< " scatter_wanted";
234 void set_flushing() {
235 state_flags
|= FLUSHING
;
237 void clear_flushing() {
238 state_flags
&= ~FLUSHING
;
241 state_flags
|= FLUSHED
;
244 state_flags
|= DIRTY
;
247 state_flags
&= ~DIRTY
;
249 _more
->item_updated
.remove_myself();