From: Sage Weil Date: Thu, 11 Mar 2010 18:52:32 +0000 (-0800) Subject: mds: move unstable SimpleLock state into separate struct X-Git-Tag: v0.20~275^2~22^2~7 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=580cf8379ffb3c7fc990b4f7096d7f42ed21a57e;p=ceph.git mds: move unstable SimpleLock state into separate struct Allocated as needed, freed when lock returns to stable state. Also make remaining int fields a bit smaller. --- diff --git a/src/mds/CDentry.h b/src/mds/CDentry.h index 0ae7d8cb1935..f8a398e19409 100644 --- a/src/mds/CDentry.h +++ b/src/mds/CDentry.h @@ -234,7 +234,7 @@ public: bool use_projected(client_t client, Mutation *mut) { return lock.can_read_projected(client) || - lock.get_xlocked_by() == mut; + lock.get_xlock_by() == mut; } linkage_t *get_linkage(client_t client, Mutation *mut) { return use_projected(client, mut) ? get_projected_linkage() : get_linkage(); diff --git a/src/mds/CInode.h b/src/mds/CInode.h index 48a77f04417c..d5cb62704f79 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -587,10 +587,10 @@ public: if (loner_cap >= 0 && loner_cap != want_loner_cap) return false; loner_cap = want_loner_cap; - authlock.excl_client = loner_cap; - filelock.excl_client = loner_cap; - linklock.excl_client = loner_cap; - xattrlock.excl_client = loner_cap; + authlock.set_excl_client(loner_cap); + filelock.set_excl_client(loner_cap); + linklock.set_excl_client(loner_cap); + xattrlock.set_excl_client(loner_cap); return true; } bool try_drop_loner() { @@ -602,10 +602,10 @@ public: if (!cap || (cap->issued() & ~other_allowed) == 0) { loner_cap = -1; - authlock.excl_client = -1; - filelock.excl_client = -1; - linklock.excl_client = -1; - xattrlock.excl_client = -1; + authlock.set_excl_client(-1); + filelock.set_excl_client(-1); + linklock.set_excl_client(-1); + xattrlock.set_excl_client(-1); return true; } return false; diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 7e6d01f715ea..befbf1368b9d 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -109,6 +109,8 @@ long g_num_dirs = 0; long g_num_dns = 0; long g_num_caps = 0; +set SimpleLock::empty_gather_set; + MDCache::MDCache(MDS *m) { @@ -5847,7 +5849,7 @@ int MDCache::path_traverse(MDRequest *mdr, Message *req, // who if (dnl && dn->lock.is_xlocked() && - dn->lock.get_xlocked_by() != mdr && + dn->lock.get_xlock_by() != mdr && !dn->lock.can_read(client) && (dnl->is_null() || forward)) { dout(10) << "traverse: xlocked dentry at " << *dn << dendl; diff --git a/src/mds/Server.cc b/src/mds/Server.cc index e3a38fce8a59..f64c4804428b 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -1791,7 +1791,7 @@ CDentry* Server::rdlock_path_xlock_dentry(MDRequest *mdr, int n, } // readable? - if (dn && !dn->lock.can_read(client) && dn->lock.get_xlocked_by() != mdr) { + if (dn && !dn->lock.can_read(client) && dn->lock.get_xlock_by() != mdr) { dout(10) << "waiting on xlocked dentry " << *dn << dendl; dn->lock.add_waiter(SimpleLock::WAIT_RD, new C_MDS_RetryRequest(mdcache, mdr)); return 0; diff --git a/src/mds/SimpleLock.h b/src/mds/SimpleLock.h index 9f04d11908bf..084cd1f33a33 100644 --- a/src/mds/SimpleLock.h +++ b/src/mds/SimpleLock.h @@ -141,27 +141,75 @@ protected: MDSCacheObject *parent; // lock state - __s32 state; - set<__s32> gather_set; // auth+rep. >= 0 is mds, < 0 is client - int num_client_lease; - - // local state - int num_rdlock, num_wrlock, num_xlock; - Mutation *xlock_by; - client_t xlock_by_client; -public: - client_t excl_client; + __s16 state; + +private: + __s16 num_rdlock; + __s32 num_client_lease; + + struct unstable_bits_t { + set<__s32> gather_set; // auth+rep. >= 0 is mds, < 0 is client + + // local state + int num_wrlock, num_xlock; + Mutation *xlock_by; + client_t xlock_by_client; + client_t excl_client; + + bool empty() { + return + num_wrlock == 0 && + num_xlock == 0 && + xlock_by == NULL && + xlock_by_client == -1 && + excl_client == -1; + } + + unstable_bits_t() : num_wrlock(0), + num_xlock(0), + xlock_by(NULL), + xlock_by_client(-1), + excl_client(-1) {} + }; + + mutable unstable_bits_t *_unstable; + bool have_more() const { return _unstable ? true : false; } + unstable_bits_t *more() const { + if (!_unstable) + _unstable = new unstable_bits_t; + return _unstable; + } + void clear_more() { + assert(_unstable->empty()); + delete _unstable; + _unstable = NULL; + } + void try_clear_more() { + if (_unstable->empty()) { + delete _unstable; + _unstable = NULL; + } + } public: + + void set_excl_client(client_t c) { more()->excl_client = c; } + client_t get_excl_client() { return have_more() ? more()->excl_client : -1; } + + + SimpleLock(MDSCacheObject *o, LockType *lt) : type(lt), parent(o), - state(LOCK_SYNC), num_client_lease(0), - num_rdlock(0), num_wrlock(0), num_xlock(0), - xlock_by(0), xlock_by_client(-1), excl_client(-1) { + state(LOCK_SYNC), + num_rdlock(0), + num_client_lease(0), + _unstable(NULL) + {} + virtual ~SimpleLock() { + delete _unstable; } - virtual ~SimpleLock() {} // parent MDSCacheObject *get_parent() { return parent; } @@ -266,22 +314,25 @@ public: } // gather set - const set& get_gather_set() { return gather_set; } + static set empty_gather_set; + const set& get_gather_set() { return have_more() ? more()->gather_set : empty_gather_set; } void init_gather() { for (map::const_iterator p = parent->replicas_begin(); p != parent->replicas_end(); ++p) - gather_set.insert(p->first); + more()->gather_set.insert(p->first); } - bool is_gathering() { return !gather_set.empty(); } + bool is_gathering() { return have_more() && !more()->gather_set.empty(); } bool is_gathering(int i) { - return gather_set.count(i); + return have_more() && more()->gather_set.count(i); } void clear_gather() { - gather_set.clear(); + if (have_more()) + more()->gather_set.clear(); } void remove_gather(int i) { - gather_set.erase(i); + if (have_more()) + more()->gather_set.erase(i); } @@ -293,45 +344,47 @@ public: bool can_lease(client_t client) { return get_sm()->states[state].can_lease == ANY || (get_sm()->states[state].can_lease == AUTH && parent->is_auth()) || - (get_sm()->states[state].can_lease == XCL && client >= 0 && xlock_by_client == client); + (get_sm()->states[state].can_lease == XCL && client >= 0 && get_xlock_by_client() == client); } bool can_read(client_t client) { return get_sm()->states[state].can_read == ANY || (get_sm()->states[state].can_read == AUTH && parent->is_auth()) || - (get_sm()->states[state].can_read == XCL && client >= 0 && xlock_by_client == client); + (get_sm()->states[state].can_read == XCL && client >= 0 && get_xlock_by_client() == client); } bool can_read_projected(client_t client) { return get_sm()->states[state].can_read_projected == ANY || (get_sm()->states[state].can_read_projected == AUTH && parent->is_auth()) || - (get_sm()->states[state].can_read_projected == XCL && client >= 0 && xlock_by_client == client); + (get_sm()->states[state].can_read_projected == XCL && client >= 0 && get_xlock_by_client() == client); } bool can_rdlock(client_t client) { return get_sm()->states[state].can_rdlock == ANY || (get_sm()->states[state].can_rdlock == AUTH && parent->is_auth()) || - (get_sm()->states[state].can_rdlock == XCL && client >= 0 && xlock_by_client == client); + (get_sm()->states[state].can_rdlock == XCL && client >= 0 && get_xlock_by_client() == client); } bool can_wrlock(client_t client) { return get_sm()->states[state].can_wrlock == ANY || (get_sm()->states[state].can_wrlock == AUTH && parent->is_auth()) || - (get_sm()->states[state].can_wrlock == XCL && client >= 0 && (xlock_by_client == client || - excl_client == client)); + (get_sm()->states[state].can_wrlock == XCL && client >= 0 && (get_xlock_by_client() == client || + get_excl_client() == client)); } bool can_xlock(client_t client) { return get_sm()->states[state].can_xlock == ANY || (get_sm()->states[state].can_xlock == AUTH && parent->is_auth()) || - (get_sm()->states[state].can_xlock == XCL && client >= 0 && xlock_by_client == client); + (get_sm()->states[state].can_xlock == XCL && client >= 0 && get_xlock_by_client() == client); } // rdlock bool is_rdlocked() { return num_rdlock > 0; } int get_rdlock() { - if (!num_rdlock) parent->get(MDSCacheObject::PIN_LOCK); + if (!num_rdlock) + parent->get(MDSCacheObject::PIN_LOCK); return ++num_rdlock; } int put_rdlock() { assert(num_rdlock>0); --num_rdlock; - if (num_rdlock == 0) parent->put(MDSCacheObject::PIN_LOCK); + if (num_rdlock == 0) + parent->put(MDSCacheObject::PIN_LOCK); return num_rdlock; } int get_num_rdlocks() { return num_rdlock; } @@ -339,46 +392,54 @@ public: // wrlock void get_wrlock(bool force=false) { //assert(can_wrlock() || force); - if (num_wrlock == 0) parent->get(MDSCacheObject::PIN_LOCK); - ++num_wrlock; + if (more()->num_wrlock == 0) + parent->get(MDSCacheObject::PIN_LOCK); + ++more()->num_wrlock; } void put_wrlock() { - --num_wrlock; - if (num_wrlock == 0) parent->put(MDSCacheObject::PIN_LOCK); + --more()->num_wrlock; + if (more()->num_wrlock == 0) { + parent->put(MDSCacheObject::PIN_LOCK); + try_clear_more(); + } } - bool is_wrlocked() { return num_wrlock > 0; } - int get_num_wrlocks() { return num_wrlock; } + bool is_wrlocked() { return have_more() && more()->num_wrlock > 0; } + int get_num_wrlocks() { return have_more() ? more()->num_wrlock : 0; } // xlock void get_xlock(Mutation *who, client_t client) { - assert(xlock_by == 0); + assert(get_xlock_by() == 0); assert(state == LOCK_XLOCK); parent->get(MDSCacheObject::PIN_LOCK); - num_xlock++; - xlock_by = who; - xlock_by_client = client; + more()->num_xlock++; + more()->xlock_by = who; + more()->xlock_by_client = client; } void set_xlock_done() { - assert(xlock_by); + assert(more()->xlock_by); assert(state == LOCK_XLOCK); state = LOCK_XLOCKDONE; - xlock_by = 0; + more()->xlock_by = 0; } void put_xlock() { assert(state == LOCK_XLOCK || state == LOCK_XLOCKDONE); - --num_xlock; + --more()->num_xlock; parent->put(MDSCacheObject::PIN_LOCK); - if (num_xlock == 0) { - xlock_by = 0; - xlock_by_client = -1; + if (more()->num_xlock == 0) { + more()->xlock_by = 0; + more()->xlock_by_client = -1; + try_clear_more(); } } - bool is_xlocked() { return num_xlock > 0; } - int get_num_xlocks() { return num_xlock; } + bool is_xlocked() { return have_more() && more()->num_xlock > 0; } + int get_num_xlocks() { return have_more() ? more()->num_xlock : 0; } + client_t get_xlock_by_client() { + return have_more() ? more()->xlock_by_client : -1; + } bool is_xlocked_by_client(client_t c) { - return xlock_by_client == c; + return have_more() ? more()->xlock_by_client == c : false; } - Mutation *get_xlocked_by() { return xlock_by; } + Mutation *get_xlock_by() { return have_more() ? more()->xlock_by : NULL; } // lease void get_client_lease() { @@ -387,6 +448,9 @@ public: void put_client_lease() { assert(num_client_lease > 0); num_client_lease--; + if (num_client_lease == 0) { + try_clear_more(); + } } bool is_leased() { return num_client_lease > 0; } int get_num_client_lease() { @@ -402,13 +466,19 @@ public: __u8 struct_v = 1; ::encode(struct_v, bl); ::encode(state, bl); - ::encode(gather_set, bl); + if (have_more()) + ::encode(more()->gather_set, bl); + else + ::encode(empty_gather_set, bl); } void decode(bufferlist::iterator& p) { __u8 struct_v; ::decode(struct_v, p); ::decode(state, p); - ::decode(gather_set, p); + set g; + ::decode(g, p); + if (!g.empty()) + more()->gather_set.swap(g); } void encode_state_for_replica(bufferlist& bl) const { __u32 s = get_replica_state(); @@ -439,7 +509,7 @@ public: int gcaps_allowed(int who, int s=-1) { if (s < 0) s = state; if (parent->is_auth()) { - if (xlock_by_client >= 0 && who == CAP_XLOCKER) + if (get_xlock_by_client() >= 0 && who == CAP_XLOCKER) return get_sm()->states[s].xlocker_caps; else if (is_loner_mode() && who == CAP_ANY) return get_sm()->states[s].caps; @@ -449,14 +519,14 @@ public: return get_sm()->states[s].replica_caps; } int gcaps_careful() { - if (num_wrlock) + if (get_num_wrlocks()) return get_sm()->careful; return 0; } int gcaps_xlocker_mask(client_t client) { - if (client == xlock_by_client) + if (client == get_xlock_by_client()) return type->type == CEPH_LOCK_IFILE ? 0xffff : (CEPH_CAP_GSHARED|CEPH_CAP_GEXCL); return 0; } @@ -512,8 +582,8 @@ public: out << " w=" << get_num_wrlocks(); if (is_xlocked()) { out << " x=" << get_num_xlocks(); - if (get_xlocked_by()) - out << " by " << get_xlocked_by(); + if (get_xlock_by()) + out << " by " << get_xlock_by(); } /*if (is_stable()) out << " stable";