]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
merkle trees added, full cap stuff almost done
authoranwleung <anwleung@29311d96-e01e-0410-9327-a35deaab8ce9>
Tue, 6 Mar 2007 05:16:29 +0000 (05:16 +0000)
committeranwleung <anwleung@29311d96-e01e-0410-9327-a35deaab8ce9>
Tue, 6 Mar 2007 05:16:29 +0000 (05:16 +0000)
git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1173 29311d96-e01e-0410-9327-a35deaab8ce9

15 files changed:
branches/aleung/security1/ceph/client/Client.cc
branches/aleung/security1/ceph/client/Client.h
branches/aleung/security1/ceph/crypto/CapGroup.h
branches/aleung/security1/ceph/crypto/ExtCap.h
branches/aleung/security1/ceph/crypto/MerkleTree.h [new file with mode: 0644]
branches/aleung/security1/ceph/crypto/driver.cc
branches/aleung/security1/ceph/mds/Locker.cc
branches/aleung/security1/ceph/mds/MDS.h
branches/aleung/security1/ceph/messages/MClientUpdate.h [new file with mode: 0644]
branches/aleung/security1/ceph/messages/MOSDUpdate.h [new file with mode: 0644]
branches/aleung/security1/ceph/messages/MOSDUpdateReply.h [new file with mode: 0644]
branches/aleung/security1/ceph/msg/Message.cc
branches/aleung/security1/ceph/msg/Message.h
branches/aleung/security1/ceph/osd/OSD.cc
branches/aleung/security1/ceph/osd/OSD.h

index 2ed2149e5e360948b870626059bffa2304b52227..63f43af8257bc3624cea39466d3d9481b901338c 100644 (file)
@@ -713,13 +713,18 @@ void Client::put_user_ticket(Ticket *tk)
 }
 
 void Client::handle_osd_update(MOSDUpdate *m) {
-  cout << "Received a request to resolve group " << m->get_group() << endl;
   // check local cache
-  if (groups.count(m->get_group())) {
-    
-  }
-  // else, ask mds, pass it, cache it
-  assert(0);
+  MOSDUpdateReply *reply;
+  gid_t my_group = m->get_group();
+  cout << "Received a request to resolve group " << my_group << endl;
+  // if we dont have it cached, ask mds, cache it
+  //if (groups.count(my_group) == 0) {
+  //  MClientUpdate *update = new MClientUpdate(my_group);
+  //}
+  //reply = new MOSDUpdateReply(groups[my_group].get_list());
+  reply = new MOSDUpdateReply(my_group);
+
+  messenger->send_message(reply, m->get_source_inst());
 }
 
 // ------------------------
index 1ddb3bfe1409e5197f93e27edf90c3026c455647..0cadf3d7c79df125c61212c78754ca4d42f9aa34 100644 (file)
@@ -28,6 +28,8 @@
 #include "messages/MClientRequest.h"
 #include "messages/MClientReply.h"
 #include "messages/MOSDUpdate.h"
+#include "messages/MOSDUpdateReply.h"
+#include "messages/MClientUpdate.h"
 
 //#include "msgthread.h"
 
index a5703e168019f7d255a743c3b049b492d6573552..77f96a7b278ed290fa35e2b437a6296d16d2e2bf 100644 (file)
 #include<iostream>
 using namespace std;
 
-#include "include/types.h"
+//#include "include/types.h"
+#include "crypto/MerkleTree.h"
 
 class CapGroup {
  private:
-  gid_t group_id;
+  //gid_t group_id;
+  hash_t root_hash;
   list<uid_t> users;
 
  public:
   friend class OSD;
   friend class Locker;
   CapGroup () { }
-  CapGroup (gid_t id) { group_id = id; }
+  //CapGroup (gid_t id) { group_id = id; }
+  CapGroup (hash_t rhash, list<uid_t>& ulist) :
+    root_hash(rhash), users(ulist) { }
   
-  gid_t get_gid() { return group_id; }
-  void set_gid(gid_t id) { group_id = id; }
+  //gid_t get_gid() { return group_id; }
+  //void set_gid(gid_t id) { group_id = id; }
+
+  hash_t get_root_hash() { return root_hash; }
+  void set_root_hash(hash_t nhash) { root_hash = nhash; }
 
   void add_user(uid_t user) {
     users.push_back(user);
@@ -49,6 +56,9 @@ class CapGroup {
     }
     return false;
   }
+
+  void set_list(list<uid_t>& nlist) { users = nlist; }
+  list<uid_t>& get_list() { return users; }
 };
 
 #endif
index 64362ab25f0099b53f4f914718db9642f24a0726..b7f2229dd428c6b1cabe8bc0bbf3422322053707 100644 (file)
@@ -23,6 +23,7 @@ using namespace std;
 
 #include "crypto/CryptoLib.h"
 using namespace CryptoLib;
+#include "crypto/MerkleTree.h"
 
 #define NO_GROUP 0
 #define UNIX_GROUP 1
@@ -84,6 +85,10 @@ private:
     gid_t gid; // group id
     bool world;
 
+    // hash based users and files
+    hash_t user_group;
+    hash_t file_group;
+
     inodeno_t ino; // inode number
   };
   
@@ -166,6 +171,12 @@ public:
   }
   void set_type(__int8_t new_type) { data.type = new_type;}
 
+  void set_user_hash(hash_t nhash) { user_group = nhash; }
+  void set_file_hash(hash_t nhash) { file_group = nhash; }
+
+  hash_t get_user_hash() { return user_group; }
+  hash_t get_file_hash() { return file_group; }
+
   const cap_data_t* get_data() const {
     return (&data);
   }
diff --git a/branches/aleung/security1/ceph/crypto/MerkleTree.h b/branches/aleung/security1/ceph/crypto/MerkleTree.h
new file mode 100644 (file)
index 0000000..06d4c1e
--- /dev/null
@@ -0,0 +1,98 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * 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 __MERKLETREE_H
+#define __MERKLETREE_H
+
+#include<iostream>
+#include<list>
+using namespace std;
+
+#include "crypto/CryptoLib.h"
+using namespace CryptoLib;
+
+struct hash_t{
+  byte val[SHA1DIGESTSIZE];
+};
+
+// comparison operators
+inline bool operator==(const hash_t& a, const hash_t& b)
+{
+  return (memcmp((void*)&a, (void*)&b, sizeof(hash_t)) == 0);
+}
+inline bool operator>(const hash_t& a, const hash_t& b)
+{
+  return (memcmp((void*)&a, (void*)&b, sizeof(hash_t)) > 0);
+}
+inline bool operator<(const hash_t& a, const hash_t& b)
+{
+  return (memcmp((void*)&a, (void*)&b, sizeof(hash_t)) < 0);
+}
+// ostream
+inline std::ostream& operator<<(std::ostream& out, const hash_t& c)
+{
+  byte hexArray[SHA1DIGESTSIZE];
+  memset(hexArray, 0x00, sizeof(hexArray));
+  toHex(c.val, hexArray, SHA1DIGESTSIZE, SHA1DIGESTSIZE);
+  out << string((const char*)hexArray);
+  return out;
+}
+
+class MerkleTree {
+ private:
+  // the root hash of the tree
+  hash_t root_hash;
+
+ public:
+  // default constructor
+  MerkleTree () { memset(&root_hash, 0x00, sizeof(root_hash)); }
+
+  // constructor from an initial list of users
+  MerkleTree (list< uid_t >& input) {
+    memset(&root_hash, 0x00, sizeof(root_hash));
+    uid_t uidArray[input.size()];
+    int counter = 0;
+    
+    // FIXME just do a linear hash first for root hash
+    // copy list into buffer
+    for (list<uid_t>::iterator li = input.begin();
+        li != input.end();
+        li++) {
+      uidArray[counter] = *li;
+      counter++;
+    }
+    // zero the array
+    sha1((byte*)uidArray, (byte*)&root_hash, sizeof(uidArray));
+  }
+
+  void add_user(uid_t user) {
+    // hash the user
+    hash_t user_hash;
+    sha1((byte*)&user, (byte*)&user_hash, sizeof(user));
+    // join the user and root_hash
+    hash_t conjunction[2];
+    conjunction[0] = root_hash;
+    conjunction[1] = user_hash;
+    // hash em both
+    sha1((byte*)&conjunction, (byte*)&root_hash, sizeof(conjunction));
+  }
+  
+  hash_t& get_root_hash() { return root_hash; }
+};
+
+// ostream
+inline std::ostream& operator<<(std::ostream& out, MerkleTree& c)
+{
+  return out << c.get_root_hash();
+}
+
+#endif
index d940dd79a2a80753f17f22cbd8f83b5566cc83cc..a13222d7e83a30d8fa826f73ee2b89a79ab4b460 100644 (file)
@@ -13,6 +13,7 @@
  * Author: Andrew Leung Nov., 2006
  ******************************/
 #include"CryptoLib.h"
+#include "MerkleTree.h"
 #include<iostream>
 
 using namespace std;
@@ -22,6 +23,20 @@ int main(int argc, char* argv[]) {
   // message to hash
   const byte* msg = (const byte*)"hash me";
 
+  // test merkle trees
+  MerkleTree mtree;
+  uid_t user1 = 1000;
+  mtree.add_user(user1);
+  cout << "My root hash: " << mtree << endl;
+  MerkleTree mtree2 = mtree;
+  uid_t user2 = 2000;
+  mtree2.add_user(user2);
+  cout << "My update root hash " << mtree2 << endl;
+  if (mtree2.get_root_hash() > mtree.get_root_hash())
+    cout << "mtree2 is bigger" << endl;
+  else
+    cout << "mtree is bigger" << endl;
+
   // sha-1
   byte digest[SHA1DIGESTSIZE];
   byte digestHex[2*SHA1DIGESTSIZE];
index dd51a2f1300d5264eee4e8dd9c42848579f745aa..dec9f918f7358dca50b678f776ba0056970644e4 100644 (file)
@@ -222,11 +222,12 @@ Capability* Locker::issue_new_caps(CInode *in,
  * This function does nothing for synchronization
  **********/
 ExtCap* Locker::issue_new_extcaps(CInode *in, int mode, MClientRequest *req) {
-  dout(3) << "issue_new_EXTcaps for mode " << mode << " on " << *in << endl;
+  dout(3) << "issue_new_extcaps for mode " << mode << " on " << *in << endl;
 
   // get the uid
   uid_t my_user = req->get_caller_uid();
   gid_t my_group = req->get_caller_gid();
+  gid_t file_group = req->get_gid();
   int my_want = 0;
   // issue most generic cap (RW)
   my_want |= FILE_MODE_RW;
@@ -238,16 +239,16 @@ ExtCap* Locker::issue_new_extcaps(CInode *in, int mode, MClientRequest *req) {
     // make new cap
     // unix grouping
     if (g_conf.mds_group == 1) {
-      ext_cap = new ExtCap(my_want, my_user, my_group, in->ino());
-
       // configure group
       if (mds->unix_groups.count(my_group) == 0)
        mds->unix_groups[my_group].set_gid(my_group);
-
+      
       // add user to group if not know already
       if (!(mds->unix_groups[my_group].contains(my_user)))
        mds->unix_groups[my_group].add_user(my_user);
 
+      ext_cap = new ExtCap(my_want, my_user, my_group, in->ino());
+
       ext_cap->set_type(1);
     }
     // default no grouping
index 85d53914aab95cb5330b65b3d7fb96c20fda6616..1dd7feb28567a376147c2c357beff2610a205e80 100644 (file)
@@ -47,6 +47,7 @@ using namespace CryptoLib;
 
 #include "crypto/ExtCap.h"
 #include "crypto/CapGroup.h"
+#include "crypto/MerkleTree.h"
 
 #define MDS_PORT_MAIN     0
 #define MDS_PORT_SERVER   1
@@ -156,6 +157,7 @@ public:
 
   // user groups
   map<gid_t, CapGroup> unix_groups;
+  map<hash_t, CapGroup> user_groups;
 
   void queue_waitfor_active(Context *c) { waitfor_active.push_back(c); }
 
diff --git a/branches/aleung/security1/ceph/messages/MClientUpdate.h b/branches/aleung/security1/ceph/messages/MClientUpdate.h
new file mode 100644 (file)
index 0000000..919f337
--- /dev/null
@@ -0,0 +1,50 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * 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 __MCLIENTUPDATE_H
+#define __MCLIENTUPDATE_H
+
+#include "msg/Message.h"
+#include "osd/osd_types.h"
+
+class MClientUpdate : public Message {
+private:
+  struct {
+    gid_t group;
+    entity_inst_t asking_client;
+  } mds_update_st;
+public:
+  MClientUpdate () : Message(MSG_CLIENT_UPDATE) { }
+  MClientUpdate (gid_t gid) : Message(MSG_CLIENT_UPDATE) {
+    memset(&mds_update_st, 0, sizeof(mds_update_st));
+    this->mds_update_st.group = gid;
+  }
+  
+  gid_t get_group () { return mds_update_st.group; }
+
+  virtual void encode_payload() {
+    payload.append((char*)&mds_update_st, sizeof(mds_update_st));
+  }
+  virtual void decode_payload() {
+    int off = 0;
+    payload.copy(off, sizeof(mds_update_st), (char*)&mds_update_st);
+    off += sizeof(mds_update_st);
+  }
+  virtual char *get_type_name() { return "mds_update"; }
+  void print(ostream& out) {
+    out << "mds_update(" << mds_update_st.group
+       << ")";
+  }
+};
+
+#endif
diff --git a/branches/aleung/security1/ceph/messages/MOSDUpdate.h b/branches/aleung/security1/ceph/messages/MOSDUpdate.h
new file mode 100644 (file)
index 0000000..6ba2c0a
--- /dev/null
@@ -0,0 +1,64 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * 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 __MOSDUPDATE_H
+#define __MOSDUPDATE_H
+
+#include "msg/Message.h"
+#include "osd/osd_types.h"
+
+class MOSDUpdate : public Message {
+private:
+  struct {
+    gid_t group;
+    entity_inst_t client;
+    entity_inst_t asker;
+  } update_st;
+public:
+  gid_t get_group() { return update_st.group; }
+  entity_inst_t get_client_inst() { return update_st.client; }
+  entity_inst_t get_asker() { return update_st.asker; }
+
+  MOSDUpdate () { }
+
+  MOSDUpdate(gid_t upGr) : Message(MSG_OSD_UPDATE) {
+    memset(&update_st,0, sizeof(update_st));
+    this->update_st.group = upGr;
+  }
+
+  MOSDUpdate(entity_inst_t asking_osd, entity_inst_t target_client,
+            gid_t upGr) : Message(MSG_OSD_UPDATE) {
+    memset(&update_st,0, sizeof(update_st));
+    this->update_st.group = upGr;
+    this->update_st.client  = target_client;
+    this->update_st.asker = asking_osd;
+  }
+
+  virtual void decode_payload() {
+    int off = 0;
+    payload.copy(off, sizeof(update_st), (char*)&update_st);
+    off += sizeof(update_st);
+  }
+  virtual void encode_payload() {
+    payload.append((char*)&update_st, sizeof(update_st));
+  }
+  
+  virtual char *get_type_name() { return "oop_update"; }
+  void print(ostream& out) {
+    out << "osd_update(" << update_st.group
+       << ")";
+  }
+};
+
+#endif
+
diff --git a/branches/aleung/security1/ceph/messages/MOSDUpdateReply.h b/branches/aleung/security1/ceph/messages/MOSDUpdateReply.h
new file mode 100644 (file)
index 0000000..29035a5
--- /dev/null
@@ -0,0 +1,51 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * 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 __MOSDUPDATEREPLY_H
+#define __MOSDUPDATEREPLY_H
+
+#include "msg/Message.h"
+#include "osd/osd_types.h"
+
+class MOSDUpdateReply : public Message {
+private:
+  gid_t group;
+  list<uid_t> updated_users;
+public:
+  MOSDUpdateReply () : Message(MSG_OSD_UPDATE_REPLY) { }
+  MOSDUpdateReply(gid_t gid) : Message(MSG_OSD_UPDATE_REPLY),
+                              group(gid) { }
+  MOSDUpdateReply (gid_t gid, list<uid_t> users) :
+    Message(MSG_OSD_UPDATE_REPLY), group(gid), updated_users(users) { }
+
+  gid_t get_group() { return group; }
+  list<uid_t>& get_list() { return updated_users; }
+
+  virtual void encode_payload() {
+    payload.append((char*)&group, sizeof(group));
+    _encode(updated_users, payload);
+  }
+  virtual void decode_payload() {
+    int off = 0;
+    payload.copy(off, sizeof(group), (char*)&group);
+    off += sizeof(group);
+    _decode(updated_users, payload, off);
+  }
+  virtual char *get_type_name() { return "oop_update_reply"; }
+  void print(ostream& out) {
+    out << "osd_update_reply(" << group
+       << ")";
+  }
+};
+
+#endif
index 2de00c770bb74e9601a563090e2eb81ca30ea907..31f65f863fdcbca64a8a70c335671cb81d3db4d3 100644 (file)
@@ -44,6 +44,7 @@ using namespace std;
 #include "messages/MOSDPGLog.h"
 #include "messages/MOSDPGRemove.h"
 #include "messages/MOSDUpdate.h"
+#include "messages/MOSDUpdateReply.h"
 
 #include "messages/MClientBoot.h"
 #include "messages/MClientMount.h"
@@ -53,6 +54,7 @@ using namespace std;
 #include "messages/MClientRequest.h"
 #include "messages/MClientReply.h"
 #include "messages/MClientFileCaps.h"
+#include "messages/MClientUpdate.h"
 
 #include "messages/MMDSGetMap.h"
 #include "messages/MMDSMap.h"
@@ -234,6 +236,9 @@ decode_message(msg_envelope_t& env, bufferlist& payload)
   case MSG_OSD_UPDATE:
     m = new MOSDUpdate();
     break;
+  case MSG_OSD_UPDATE_REPLY:
+    m = new MOSDUpdateReply();
+    break;
 
     // clients
   case MSG_CLIENT_BOOT:
index cf8d14003798dc474339b0ce9d94b389579be07e..74bba6d7d01efa447dedb1ffda5b8af151fa725c 100644 (file)
 
 // osd group update
 #define MSG_OSD_UPDATE         55
+#define MSG_OSD_UPDATE_REPLY   56
 
 #define MSG_CLIENT_REQUEST         60
 #define MSG_CLIENT_REPLY           61
 //#define MSG_CLIENT_DONE            62
 #define MSG_CLIENT_FILECAPS        63
 #define MSG_CLIENT_INODEAUTHUPDATE 64
+#define MSG_CLIENT_UPDATE          65
 
 #define MSG_CLIENT_BOOT            70
 #define MSG_CLIENT_MOUNT           71
index 9d56a52d2e7a8c753f393814a044193d32dd7ff9..016d5e81210d6e00fafbd0edd31790aeb89dc69d 100644 (file)
@@ -377,11 +377,18 @@ bool OSD::check_request(MOSDOp *op, ExtCap *op_capability) {
   if (op_capability->get_type() == UNIX_GROUP) {
     // check if user is in group
     gid_t my_group = op_capability->get_gid();
+
+    // do we have group cached? if not, update group
+    // this will block till we have the group!!
+    if (unix_groups.count(my_group) == 0) {
+      update_group(op->get_client_inst(), my_group);
+    }
+    
+    // now we should have the group, is the client in it?
     if (!(unix_groups[my_group].contains(op_capability->get_uid()))) {
       // do update to get new unix groups
       cout << "User " << op_capability->get_uid() << " not in group "
           << my_group << endl;
-      update_group(op->get_client_inst(), my_group);
       return false;
     }
   }
@@ -413,9 +420,51 @@ bool OSD::check_request(MOSDOp *op, ExtCap *op_capability) {
 void OSD::update_group(entity_inst_t client, gid_t group) {
     // set up reply
   MOSDUpdate *update = new MOSDUpdate(group);
+  Cond cond;
+  
+  // if no one has already requested the ticket
+  if (update_waiter_cond.count(group) == 0) {
+    dout(10) << "update_group requesting update for gid " << group << endl;
+      // send it
+    messenger->send_message(update, client);
+  } else {
+    // don't request, someone else already did.  just wait!
+    dout(10) << "update_group waiting for update for gid " << group << endl;
+  }
+  
+  // wait for reply
+  update_waiter_cond[group].push_back( &cond );
+  
+  // naively assume we'll get an update FIXME
+  while (unix_groups.count(group) == 0) { 
+    cond.Wait(osd_lock);
+    //cout << "Received a singal, going to check group " << group << endl;
+  }
+  cout << "Received updated group, returning" << endl;
+  
+}
 
-  // send it
-  messenger->send_message(update, client);
+// gets reply for group and wakes up waiters
+void OSD::handle_osd_update_reply(MOSDUpdateReply *m) {
+
+  // store the new list into group
+  gid_t my_group = m->get_group();
+
+  cout << "hande_osd_update_reply for " << my_group << endl;
+  dout(10) << "hande_osd_update_reply for " << my_group << endl;
+
+  // add the new list to our cache
+  unix_groups[my_group].set_list(m->get_list());
+
+  // wait up the waiter(s)
+  // this signals all update waiters
+  for (list<Cond*>::iterator p = update_waiter_cond[my_group].begin();
+       p != update_waiter_cond[my_group].end();
+       ++p) {
+    (*p)->Signal();
+  }
+
+  update_waiter_cond.erase(my_group);
 }
 
 // assumes the request and cap contents has already been checked
@@ -777,6 +826,10 @@ void OSD::dispatch(Message *m)
       case MSG_OSD_OPREPLY:
         handle_op_reply((MOSDOpReply*)m);
         break;
+       // for updating security groups
+      case MSG_OSD_UPDATE_REPLY:
+       handle_osd_update_reply((MOSDUpdateReply*)m);
+       break;
         
         
       default:
index b6199315108d192d6b5e92fdffd0b7a8dc078cdf..e2248abbcfa02dffeff87a909fd5a3cd0e1599b6 100644 (file)
@@ -33,11 +33,13 @@ using namespace __gnu_cxx;
 
 #include "messages/MOSDOp.h"
 #include "messages/MOSDUpdate.h"
+#include "messages/MOSDUpdateReply.h"
 
 #include "crypto/CryptoLib.h"
 using namespace CryptoLib;
 #include "crypto/CapCache.h"
 #include "crypto/CapGroup.h"
+#include "crypto/MerkleTree.h"
 
 class Messenger;
 class Message;
@@ -113,7 +115,11 @@ public:
   hash_map<int, float> peer_qlen;
 
   // unix group cache
-  map<gid_t, CapGroup> unix_groups;
+  //map<gid_t, CapGroup> unix_groups;
+  map<hash_t, CapGroup> user_groups;
+  //map<gid_t, list<Cond*> > update_waiter_cond;
+  map<hash_t, list<Cond*> > update_waiter_cond;
+  void handle_osd_update_reply(MOSDUpdateReply *m);
   
   // per-pg locking (serializing)
   hash_set<pg_t>               pg_lock;