]>
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 class ScatterLock
: public SimpleLock
{
24 xlist
<ScatterLock
*>::item item_updated
;
27 explicit more_bits_t(ScatterLock
*lock
) :
32 mutable std::unique_ptr
<more_bits_t
> _more
;
36 _more
.reset(new more_bits_t(this));
41 SCATTER_WANTED
= 1 << 8,
42 UNSCATTER_WANTED
= 1 << 9,
49 ScatterLock(MDSCacheObject
*o
, LockType
*lt
) :
51 ~ScatterLock() override
{
55 bool is_scatterlock() const override
{
59 bool is_sync_and_unlocked() const {
61 SimpleLock::is_sync_and_unlocked() &&
66 bool can_scatter_pin(client_t loner
) {
68 LOCK : NOT okay because it can MIX and force replicas to journal something
69 TSYN : also not okay for same reason
72 MIX : okay, replica can stall before sending AC_SYNCACK
73 SYNC : okay, replica can stall before sending AC_MIXACK or AC_LOCKACK
76 get_state() == LOCK_SYNC
||
77 get_state() == LOCK_MIX
;
80 void set_xlock_snap_sync(MDSInternalContextBase
*c
)
82 assert(get_type() == CEPH_LOCK_IFILE
);
83 assert(state
== LOCK_XLOCK
|| state
== LOCK_XLOCKDONE
);
84 state
= LOCK_XLOCKSNAP
;
85 add_waiter(WAIT_STABLE
, c
);
88 xlist
<ScatterLock
*>::item
*get_updated_item() { return &more()->item_updated
; }
90 utime_t
get_update_stamp() {
91 return _more
? _more
->update_stamp
: utime_t();
94 void set_update_stamp(utime_t t
) { more()->update_stamp
= t
; }
96 void set_scatter_wanted() {
97 state_flags
|= SCATTER_WANTED
;
99 void set_unscatter_wanted() {
100 state_flags
|= UNSCATTER_WANTED
;
102 void clear_scatter_wanted() {
103 state_flags
&= ~SCATTER_WANTED
;
105 void clear_unscatter_wanted() {
106 state_flags
&= ~UNSCATTER_WANTED
;
108 bool get_scatter_wanted() const {
109 return state_flags
& SCATTER_WANTED
;
111 bool get_unscatter_wanted() const {
112 return state_flags
& UNSCATTER_WANTED
;
115 bool is_dirty() const override
{
116 return state_flags
& DIRTY
;
118 bool is_flushing() const override
{
119 return state_flags
& FLUSHING
;
121 bool is_flushed() const override
{
122 return state_flags
& FLUSHED
;
124 bool is_dirty_or_flushing() const {
125 return is_dirty() || is_flushing();
131 parent
->get(MDSCacheObject::PIN_DIRTYSCATTERED
);
141 void finish_flush() {
146 parent
->put(MDSCacheObject::PIN_DIRTYSCATTERED
);
147 parent
->clear_dirty_scattered(get_type());
151 void remove_dirty() {
155 void clear_flushed() override
{
156 state_flags
&= ~FLUSHED
;
159 void infer_state_from_strong_rejoin(int rstate
, bool locktoo
) {
160 if (rstate
== LOCK_MIX
||
161 rstate
== LOCK_MIX_LOCK
|| // replica still has wrlocks?
162 rstate
== LOCK_MIX_SYNC
)
164 else if (locktoo
&& rstate
== LOCK_LOCK
)
168 void encode_state_for_rejoin(bufferlist
& bl
, int rep
) {
169 __s16 s
= get_replica_state();
170 if (is_gathering(rep
)) {
171 // the recovering mds may hold rejoined wrlocks
172 if (state
== LOCK_MIX_SYNC
)
178 // If there is a recovering mds who replcated an object when it failed
179 // and scatterlock in the object was in MIX state, It's possible that
180 // the recovering mds needs to take wrlock on the scatterlock when it
181 // replays unsafe requests. So this mds should delay taking rdlock on
182 // the scatterlock until the recovering mds finishes replaying unsafe.
183 // Otherwise unsafe requests may get replayed after current request.
186 // The recovering mds is auth mds of a dirfrag, this mds is auth mds
187 // of correspinding inode. when 'rm -rf' the direcotry, this mds should
188 // delay the rmdir request until the recovering mds has replayed unlink
190 if (s
== LOCK_MIX
|| s
== LOCK_MIX_LOCK
|| s
== LOCK_MIX_SYNC
)
196 void decode_state_rejoin(bufferlist::iterator
& p
, list
<MDSInternalContextBase
*>& waiters
, bool survivor
) {
197 SimpleLock::decode_state_rejoin(p
, waiters
, survivor
);
204 bool remove_replica(int from
, bool rejoin
) {
206 (state
== LOCK_MIX
||
207 state
== LOCK_MIX_SYNC
||
208 state
== LOCK_MIX_LOCK2
||
209 state
== LOCK_MIX_TSYN
||
210 state
== LOCK_MIX_EXCL
))
212 return SimpleLock::remove_replica(from
);
215 void print(ostream
& out
) const override
{
224 if (get_scatter_wanted())
225 out
<< " scatter_wanted";
230 void set_flushing() {
231 state_flags
|= FLUSHING
;
233 void clear_flushing() {
234 state_flags
&= ~FLUSHING
;
237 state_flags
|= FLUSHED
;
240 state_flags
|= DIRTY
;
243 state_flags
&= ~DIRTY
;
245 _more
->item_updated
.remove_myself();