]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: move unstable SimpleLock state into separate struct
authorSage Weil <sage@newdream.net>
Thu, 11 Mar 2010 18:52:32 +0000 (10:52 -0800)
committerSage Weil <sage@newdream.net>
Fri, 12 Mar 2010 17:01:50 +0000 (09:01 -0800)
Allocated as needed, freed when lock returns to stable state.

Also make remaining int fields a bit smaller.

src/mds/CDentry.h
src/mds/CInode.h
src/mds/MDCache.cc
src/mds/Server.cc
src/mds/SimpleLock.h

index 0ae7d8cb1935daddfec43dbd26f66fdf118602a8..f8a398e19409e992b4abd231659d6edd4c531214 100644 (file)
@@ -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();
index 48a77f04417c6d394381e4f991c8125ad6a9c666..d5cb62704f79d8e6a0711f6795e245814a20de19 100644 (file)
@@ -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;
index 7e6d01f715ead00287bc5d957d153c154cbb0903..befbf1368b9dca9a529bde4f011edc41912b7567 100644 (file)
@@ -109,6 +109,8 @@ long g_num_dirs = 0;
 long g_num_dns = 0;
 long g_num_caps = 0;
 
+set<int> 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;
index e3a38fce8a59d31dbbde4eb4789bdb0b25f7a4f1..f64c4804428b56d66cf5ed2dce840c45986a115e 100644 (file)
@@ -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;
index 9f04d11908bf5df93fea466045a5daadc0120132..084cd1f33a339802c63ffb745c419bed7fe9154f 100644 (file)
@@ -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<int>& get_gather_set() { return gather_set; }
+  static set<int> empty_gather_set;
+  const set<int>& get_gather_set() { return have_more() ? more()->gather_set : empty_gather_set; }
   void init_gather() {
     for (map<int,int>::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<int> 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";