X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fmds%2FScatterLock.h;fp=src%2Fceph%2Fsrc%2Fmds%2FScatterLock.h;h=618ced921bc3a34aaeb942b329855473d94b4547;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/mds/ScatterLock.h b/src/ceph/src/mds/ScatterLock.h new file mode 100644 index 0000000..618ced9 --- /dev/null +++ b/src/ceph/src/mds/ScatterLock.h @@ -0,0 +1,281 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + + +#ifndef CEPH_SCATTERLOCK_H +#define CEPH_SCATTERLOCK_H + +#include "SimpleLock.h" + +class ScatterLock : public SimpleLock { + + struct more_bits_t { + int state_flags; + utime_t last_scatter; + xlist::item item_updated; + utime_t update_stamp; + + explicit more_bits_t(ScatterLock *lock) : + state_flags(0), + item_updated(lock) + {} + + bool empty() const { + return + !state_flags && + !item_updated.is_on_list(); + } + }; + more_bits_t *_more; + + bool have_more() const { return _more ? true : false; } + void try_clear_more() { + if (_more && _more->empty()) { + delete _more; + _more = NULL; + } + } + more_bits_t *more() { + if (!_more) + _more = new more_bits_t(this); + return _more; + } + + enum flag_values { // flag values for more_bits_t state + SCATTER_WANTED = 1 << 0, + UNSCATTER_WANTED = 1 << 1, + DIRTY = 1 << 2, + FLUSHING = 1 << 3, + FLUSHED = 1 << 4, + REJOIN_MIX = 1 << 5, // no rdlock until the recovering mds become active + }; + +public: + ScatterLock(MDSCacheObject *o, LockType *lt) : + SimpleLock(o, lt), _more(NULL) + {} + ~ScatterLock() override { + if (_more) { + _more->item_updated.remove_myself(); // FIXME this should happen sooner, i think... + delete _more; + } + } + + bool is_scatterlock() const override { + return true; + } + + bool is_sync_and_unlocked() const { + return + SimpleLock::is_sync_and_unlocked() && + !is_dirty() && + !is_flushing(); + } + + bool can_scatter_pin(client_t loner) { + /* + LOCK : NOT okay because it can MIX and force replicas to journal something + TSYN : also not okay for same reason + EXCL : also not okay + + MIX : okay, replica can stall before sending AC_SYNCACK + SYNC : okay, replica can stall before sending AC_MIXACK or AC_LOCKACK + */ + return + get_state() == LOCK_SYNC || + get_state() == LOCK_MIX; + } + + void set_xlock_snap_sync(MDSInternalContextBase *c) + { + assert(get_type() == CEPH_LOCK_IFILE); + assert(state == LOCK_XLOCK || state == LOCK_XLOCKDONE); + state = LOCK_XLOCKSNAP; + add_waiter(WAIT_STABLE, c); + } + + xlist::item *get_updated_item() { return &more()->item_updated; } + + utime_t get_update_stamp() { + return more()->update_stamp; + } + + void set_update_stamp(utime_t t) { more()->update_stamp = t; } + + void set_scatter_wanted() { + more()->state_flags |= SCATTER_WANTED; + } + void set_unscatter_wanted() { + more()->state_flags |= UNSCATTER_WANTED; + } + void clear_scatter_wanted() { + if (have_more()) + _more->state_flags &= ~SCATTER_WANTED; + try_clear_more(); + } + void clear_unscatter_wanted() { + if (have_more()) + _more->state_flags &= ~UNSCATTER_WANTED; + try_clear_more(); + } + bool get_scatter_wanted() const { + return have_more() ? _more->state_flags & SCATTER_WANTED : false; + } + bool get_unscatter_wanted() const { + return have_more() ? _more->state_flags & UNSCATTER_WANTED : false; + } + + bool is_dirty() const override { + return have_more() ? _more->state_flags & DIRTY : false; + } + bool is_flushing() const override { + return have_more() ? _more->state_flags & FLUSHING: false; + } + bool is_flushed() const override { + return have_more() ? _more->state_flags & FLUSHED: false; + } + bool is_dirty_or_flushing() const { + return have_more() ? (is_dirty() || is_flushing()) : false; + } + bool is_rejoin_mix() const { + return have_more() ? _more->state_flags & REJOIN_MIX : false; + } + + void mark_dirty() { + if (!is_dirty()) { + if (!is_flushing()) + parent->get(MDSCacheObject::PIN_DIRTYSCATTERED); + set_dirty(); + } + } + void start_flush() { + if (is_dirty()) { + set_flushing(); + clear_dirty(); + } + } + void finish_flush() { + if (is_flushing()) { + clear_flushing(); + set_flushed(); + if (!is_dirty()) { + parent->put(MDSCacheObject::PIN_DIRTYSCATTERED); + parent->clear_dirty_scattered(get_type()); + } + } + } + void remove_dirty() { + start_flush(); + finish_flush(); + } + void clear_flushed() override { + if (have_more()) { + _more->state_flags &= ~FLUSHED; + try_clear_more(); + } + } + + void clear_rejoin_mix() { + if (have_more()) { + _more->state_flags &= ~REJOIN_MIX; + try_clear_more(); + } + } + + void set_last_scatter(utime_t t) { more()->last_scatter = t; } + utime_t get_last_scatter() { + return more()->last_scatter; + } + + void infer_state_from_strong_rejoin(int rstate, bool locktoo) { + if (rstate == LOCK_MIX || + rstate == LOCK_MIX_LOCK || // replica still has wrlocks? + rstate == LOCK_MIX_SYNC) + state = LOCK_MIX; + else if (locktoo && rstate == LOCK_LOCK) + state = LOCK_LOCK; + } + + void encode_state_for_rejoin(bufferlist& bl, int rep) { + __s16 s = get_replica_state(); + if (is_gathering(rep)) { + // the recovering mds may hold rejoined wrlocks + if (state == LOCK_MIX_SYNC) + s = LOCK_MIX_SYNC; + else + s = LOCK_MIX_LOCK; + } + + if (s == LOCK_MIX || s == LOCK_MIX_LOCK || s == LOCK_MIX_SYNC) + more()->state_flags |= REJOIN_MIX; + + ::encode(s, bl); + } + + void decode_state_rejoin(bufferlist::iterator& p, list& waiters) { + SimpleLock::decode_state_rejoin(p, waiters); + if (is_flushing()) { + set_dirty(); + clear_flushing(); + } + } + + bool remove_replica(int from, bool rejoin) { + if (rejoin && + (state == LOCK_MIX || + state == LOCK_MIX_SYNC || + state == LOCK_MIX_LOCK2 || + state == LOCK_MIX_TSYN || + state == LOCK_MIX_EXCL)) + return false; + return SimpleLock::remove_replica(from); + } + + void print(ostream& out) const override { + out << "("; + _print(out); + if (is_dirty()) + out << " dirty"; + if (is_flushing()) + out << " flushing"; + if (is_flushed()) + out << " flushed"; + if (get_scatter_wanted()) + out << " scatter_wanted"; + out << ")"; + } + +private: + void set_flushing() { + more()->state_flags |= FLUSHING; + } + void clear_flushing() { + if (have_more()) { + _more->state_flags &= ~FLUSHING; + } + } + void set_flushed() { + more()->state_flags |= FLUSHED; + } + void set_dirty() { + more()->state_flags |= DIRTY; + } + void clear_dirty() { + if (have_more()) { + _more->state_flags &= ~DIRTY; + } + } +}; + +#endif