]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: fixed up trace and readdir decoding
authorSage Weil <sage@newdream.net>
Wed, 26 Mar 2008 17:27:53 +0000 (10:27 -0700)
committerSage Weil <sage@newdream.net>
Wed, 26 Mar 2008 17:27:53 +0000 (10:27 -0700)
src/client/Client.cc
src/client/Client.h
src/mds/Locker.cc
src/mds/Server.cc
src/messages/MClientReply.h

index 8e71e96cb6ad6ec5adbf4f4165bd381b78923bde..3db038f7cf300c5ee45afca13899877366964ac1 100644 (file)
@@ -317,14 +317,18 @@ void Client::trim_cache()
 }
 
 
-void Client::update_inode(Inode *in, InodeStat *st, ceph_mds_reply_lease *l, utime_t ttl)
+void Client::update_inode(Inode *in, InodeStat *st, LeaseStat *lease, utime_t from)
 {
-  dout(12) << "update_inode stat mask is " << st->mask << dendl;
-  if (st->mask & CEPH_STAT_MASK_INODE) {
+  utime_t ttl = from;
+  ttl += (float)lease->duration_ms * 1000.0;
+
+  dout(12) << "update_inode mask " << lease->mask << " ttl " << ttl << dendl;
+  if (lease->mask & CEPH_STAT_MASK_INODE) {
     in->inode = st->inode;
     in->dirfragtree = st->dirfragtree;  // FIXME look at the mask!
   }
-  in->mask = st->mask;
+
+  in->mask = lease->mask;
   if (ttl > in->ttl) 
     in->ttl = ttl;
 
@@ -337,24 +341,31 @@ void Client::update_inode(Inode *in, InodeStat *st, ceph_mds_reply_lease *l, uti
 }
 
 
+
 /*
  * insert_dentry_inode - insert + link a single dentry + inode into the metadata cache.
  */
-Inode* Client::insert_dentry_inode(Dir *dir, const string& dname, int dmask, InodeStat *st, utime_t ttl)
+Inode* Client::insert_dentry_inode(Dir *dir, const string& dname, LeaseStat *dlease, 
+                                  InodeStat *ist, LeaseStat *ilease, 
+                                  utime_t from)
 {
+  int dmask = dlease->mask;
+  utime_t dttl = from;
+  dttl += (float)dlease->duration_ms * 1000.0;
+
   Dentry *dn = NULL;
   if (dir->dentries.count(dname))
     dn = dir->dentries[dname];
 
-  dout(12) << "insert_dentry_inode " << dname << " ino " << st->inode.ino 
-           << "  size " << st->inode.size
-           << "  mtime " << st->inode.mtime
-          << "  mask " << st->mask
+  dout(12) << "insert_dentry_inode " << dname << " ino " << ist->inode.ino 
+           << "  size " << ist->inode.size
+           << "  mtime " << ist->inode.mtime
+          << " dmask " << dmask
           << " in dir " << dir->parent_inode->inode.ino
            << dendl;
   
   if (dn) {
-    if (dn->inode->inode.ino == st->inode.ino) {
+    if (dn->inode->inode.ino == ist->inode.ino) {
       touch_dn(dn);
       dout(12) << " had dentry " << dname
                << " with correct ino " << dn->inode->inode.ino
@@ -370,8 +381,8 @@ Inode* Client::insert_dentry_inode(Dir *dir, const string& dname, int dmask, Ino
   
   if (!dn) {
     // have inode linked elsewhere?  -> unlink and relink!
-    if (inode_map.count(st->inode.ino)) {
-      Inode *in = inode_map[st->inode.ino];
+    if (inode_map.count(ist->inode.ino)) {
+      Inode *in = inode_map[ist->inode.ino];
       assert(in);
 
       if (in->dn) {
@@ -389,15 +400,15 @@ Inode* Client::insert_dentry_inode(Dir *dir, const string& dname, int dmask, Ino
   }
 
   if (!dn) {
-    Inode *in = new Inode(st->inode, objectcacher);
-    inode_map[st->inode.ino] = in;
+    Inode *in = new Inode(ist->inode, objectcacher);
+    inode_map[ist->inode.ino] = in;
     dn = link(dir, dname, in);
-    dout(12) << " new dentry+node with ino " << st->inode.ino << dendl;
+    dout(12) << " new dentry+node with ino " << ist->inode.ino << dendl;
   } 
 
   assert(dn && dn->inode);
 
-  update_inode(dn->inode, st, ttl);
+  update_inode(dn->inode, ist, ilease, from);
 
   return dn->inode;
 }
@@ -440,23 +451,57 @@ void Client::update_dir_dist(Inode *in, DirStat *dst)
  *
  * insert a trace from a MDS reply into the cache.
  */
-Inode* Client::insert_trace(MClientReply *reply, utime_t ttl)
+Inode* Client::insert_trace(MClientReply *reply, utime_t from)
 {
-  utime_t now = g_clock.real_now();
 
-  dout(10) << "insert_trace got " << reply->get_trace_in().size() << " inodes" << dendl;
-  if (reply->get_trace_in().empty())
+  bufferlist::iterator p = reply->get_trace_bl().begin();
+  if (p.end()) {
+    dout(10) << "insert_trace -- no trace" << dendl;
     return NULL;
+  }
+
+  __u32 numi, numd;
+  ::_decode_simple(numi, p);
+  ::_decode_simple(numd, p);
+  dout(10) << "insert_trace got " << numi << " inodes, " << numd << " dentries" << dendl;
 
-  list<string>::const_iterator pdn = reply->get_trace_dn().begin();
-  list<char>::const_iterator pdnmask = reply->get_trace_dn_mask().begin();
-  list<DirStat*>::const_iterator pdir = reply->get_trace_dir().begin();
-  list<InodeStat*>::const_iterator pin = reply->get_trace_in().begin();
+  // decode
+  LeaseStat ilease[numi];
+  InodeStat ist[numi];
+  DirStat dst[numd];
+  string dname[numd];
+  LeaseStat dlease[numd];
 
+  if (numi == 0)
+    return NULL;
+
+  int ileft = numi;
+  int dleft = numd;
+  if (numi == numd)
+    goto dentry;
+
+ inode:
+  if (!ileft) goto done;
+  ileft--;
+  ist[ileft]._decode(p);
+  ::_decode_simple(ilease[ileft], p);
+
+ dentry:
+  if (!dleft) goto done;
+  dleft--;
+  ::_decode_simple(dname[dleft], p);
+  ::_decode_simple(dlease[dleft], p);
+  dst[dleft]._decode(p);
+  goto inode;
+
+ done:
+  
+  // insert into cache --
+  // first inode
   Inode *curi = 0;
-  inodeno_t ino = (*pin)->inode.ino;
+  inodeno_t ino = ist[0].inode.ino;
   if (!root && ino == 1) {
-    curi = root = new Inode((*pin)->inode, objectcacher);
+    curi = root = new Inode(ist[0].inode, objectcacher);
     dout(10) << "insert_trace new root is " << root << dendl;
     inode_map[ino] = root;
     root->dir_auth = 0;
@@ -465,25 +510,23 @@ Inode* Client::insert_trace(MClientReply *reply, utime_t ttl)
     assert(inode_map.count(ino));
     curi = inode_map[ino];
   }
-  update_inode(curi, *pin, ttl);
-  pin++;
+  update_inode(curi, &ist[0], &ilease[0], from);
 
-  while (pdir != reply->get_trace_dir().end()) {
+  for (unsigned i=0; i<numd; i++) {
     Dir *dir = curi->open_dir();
-    assert(pdn != reply->get_trace_dn().end());
-    if (pin == reply->get_trace_in().end()) {
-      dout(10) << "insert_trace " << *pdn << " mask " << *pdnmask 
+
+    // in?
+    if (i+1 == numi) {
+      dout(10) << "insert_trace " << dname[i] << " mask " << dlease[i].mask
               << " -- NULL dentry caching not supported yet, IMPLEMENT ME" << dendl;
       //insert_null_dentry(dir, *pdn, *pdnmask, ttl);  // fixme
       break;
     }
-    curi = insert_dentry_inode(dir, *pdn, *pdnmask, *pin, ttl);
-    update_dir_dist(curi, *pdir);  // dir stat info is attached to inode...
-    pdn++;
-    pdnmask++;
-    pin++;
-    pdir++;
+    
+    curi = insert_dentry_inode(dir, dname[i], &dlease[i], &ist[i+1], &ilease[i+1], from);
+    update_dir_dist(curi, &dst[i]);  // dir stat info is attached to inode...
   }
+  assert(p.end());
 
   return curi;
 }
@@ -610,7 +653,7 @@ int Client::choose_target_mds(MClientRequest *req)
 
 
 
-MClientReply *Client::make_request(MClientRequest *req, Inode **ppin, int use_mds)
+MClientReply *Client::make_request(MClientRequest *req, Inode **ppin, utime_t *pfrom, int use_mds)
 {
   // time the call
   utime_t start = g_clock.real_now();
@@ -730,18 +773,12 @@ MClientReply *Client::make_request(MClientRequest *req, Inode **ppin, int use_md
 
 
   // insert trace
-  if (reply->get_result() >= 0) {
-    utime_t ttl = request.sent_stamp;
-    float dur = (float)reply->get_lease_duration_ms() / 1000.0;
-    ttl += dur;
-    dout(20) << "make_request got ttl of " << ttl
-            << " (sent_stamp " << request.sent_stamp
-            << " + " << dur << "s"
-            << ")" << dendl;
-    Inode *in = insert_trace(reply, ttl);
-    if (ppin)
-      *ppin = in;
-  }
+  utime_t from = request.sent_stamp;
+  if (pfrom) 
+    *pfrom = from;
+  Inode *in = insert_trace(reply, from);
+  if (ppin)
+    *ppin = in;
 
   // -- log times --
   if (client_logger) {
@@ -2426,23 +2463,20 @@ int Client::_readdir_get_frag(DirResult *dirp)
   req->set_caller_uid(getuid());
   req->set_caller_gid(getgid());
   
-  MClientReply *reply = make_request(req);
+  Inode *diri;
+  utime_t from;
+  MClientReply *reply = make_request(req, &diri, &from);
   int res = reply->get_result();
-  inodeno_t ino = reply->get_ino();
   
   // did i get directory inode?
-  Inode *diri = 0;
-  if ((res == -EAGAIN || res == 0) &&
-      inode_map.count(ino)) {
-    diri = inode_map[ino];
+  if ((res == -EAGAIN || res == 0) && diri) {
     dout(10) << "_readdir_get_frag got diri " << diri << " " << diri->inode.ino << dendl;
-    assert(diri);
     assert(diri->inode.is_dir());
   }
   
   if (!dirp->inode && diri) {
     dout(10) << "_readdir_get_frag attaching inode" << dendl;
-    dirp->inode = inode_map[ino];
+    dirp->inode = diri;
     diri->get();
   }
 
@@ -2471,28 +2505,35 @@ int Client::_readdir_get_frag(DirResult *dirp)
     }
     
     // the rest?
-    if (!reply->get_dir_dn().empty()) {
+    bufferlist::iterator p = reply->get_dir_bl().begin();
+    if (!p.end()) {
       // only open dir if we're actually adding stuff to it!
       Dir *dir = diri->open_dir();
       assert(dir);
-      utime_t ttl = g_clock.real_now();
-      ttl += 60.0;
-      
-      list<InodeStat*>::const_iterator pin = reply->get_dir_in().begin();
-      for (list<string>::const_iterator pdn = reply->get_dir_dn().begin();
-          pdn != reply->get_dir_dn().end(); 
-           ++pdn, ++pin) {
-       // count entries
-        res++;
-       
-       // put in cache
-       Inode *in = this->insert_dentry_inode(dir, *pdn, 0, *pin, ttl);
-       
-       // contents to caller too!
-       dout(15) << "_readdir_get_frag got " << *pdn << " to " << in->inode.ino << dendl;
-       _readdir_add_dirent(dirp, *pdn, in);
-      }
 
+      // dirstat
+      DirStat dst(p);
+      __u32 numdn;
+      ::_decode_simple(numdn, p);
+
+      string dname;
+      LeaseStat dlease, ilease;
+      while (numdn) {
+       ::_decode_simple(dname, p);
+       ::_decode_simple(dlease, p);
+       InodeStat ist(p);
+       ::_decode_simple(ilease, p);
+
+       // cache
+       Inode *in = this->insert_dentry_inode(dir, dname, &dlease, &ist, &ilease, from);
+
+       // caller
+       dout(15) << "_readdir_get_frag got " << dname << " to " << in->inode.ino << dendl;
+       _readdir_add_dirent(dirp, dname, in);
+
+       numdn--;
+      }
+      
       if (dir->is_empty())
        close_dir(dir);
     }
@@ -2654,7 +2695,8 @@ int Client::_open(const char *path, int flags, mode_t mode, Fh **fhp)
     in->add_open(cmode);  // make note of pending open, since it effects _wanted_ caps.
   }
   
-  MClientReply *reply = make_request(req);
+  in = 0;
+  MClientReply *reply = make_request(req, &in);
   assert(reply);
 
   int result = reply->get_result();
@@ -2667,8 +2709,8 @@ int Client::_open(const char *path, int flags, mode_t mode, Fh **fhp)
     f->mode = cmode;
 
     // inode
-    f->inode = inode_map[reply->get_ino()];
-    assert(f->inode);
+    assert(in);
+    f->inode = in;
     f->inode->get();
 
     if (!in) {
index d323fe1c3cc7319ed76fa6f3c4b36a3bdc8aba80..a40a03a3c9c0493840673dec5a9b8051ccd41877 100644 (file)
@@ -473,7 +473,7 @@ public:
   };
   map<tid_t,StatfsRequest*> statfs_requests;
   
-  MClientReply *make_request(MClientRequest *req, Inode **ppin=0, int use_mds=-1);
+  MClientReply *make_request(MClientRequest *req, Inode **ppin=0, utime_t *pfrom=0, int use_mds=-1);
   int choose_target_mds(MClientRequest *req);
   void send_request(MetaRequest *request, int mds);
   void kick_requests(int mds);
@@ -694,8 +694,10 @@ protected:
   void update_dir_dist(Inode *in, DirStat *st);
 
   Inode* insert_trace(MClientReply *reply, utime_t ttl);
-  void update_inode(Inode *in, InodeStat *st, utime_t ttl);
-  Inode* insert_dentry_inode(Dir *dir, const string& dname, int dmask, InodeStat *st, utime_t ttl);
+  void update_inode(Inode *in, InodeStat *st, LeaseStat *l, utime_t ttl);
+  Inode* insert_dentry_inode(Dir *dir, const string& dname, LeaseStat *dlease, 
+                            InodeStat *ist, LeaseStat *ilease, 
+                            utime_t from);
 
 
   // ----------------------
index 1bb2c0f4d386886548b8ac2214fde38f9b37878a..7479d112c2d06132c8bf11b46e274e401ddaf751 100644 (file)
@@ -44,6 +44,7 @@
 #include "messages/MDentryUnlink.h"
 
 #include "messages/MClientRequest.h"
+#include "messages/MClientReply.h"
 #include "messages/MClientFileCaps.h"
 
 #include "messages/MMDSSlaveRequest.h"
@@ -1030,16 +1031,16 @@ void Locker::_issue_client_lease(MDSCacheObject *p, int mask, int pool, int clie
     mdcache->touch_client_lease(l, pool, now);
   }
 
-  ceph_mds_reply_lease e;
-  e.mask = cpu_to_le16(mask);
-  e.duration_ms = cpu_to_le32(1000 * mdcache->client_lease_durations[pool]);
+  LeaseStat e;
+  e.mask = mask;
+  e.duration_ms = (int)(1000 * mdcache->client_lease_durations[pool]);
   ::_encode_simple(e, bl);
 }
   
 
 
 int Locker::issue_client_lease(CInode *in, int client, 
-                               bufferlist &bl, utime_t now, Session *session)
+                              bufferlist &bl, utime_t now, Session *session)
 {
   int mask = CEPH_LOCK_INO;
   int pool = 1;   // fixme.. do something smart!
@@ -1052,7 +1053,7 @@ int Locker::issue_client_lease(CInode *in, int client,
 }
 
 int Locker::issue_client_lease(CDentry *dn, int client,
-                               bufferlist &bl, utime_t now, Session *session)
+                              bufferlist &bl, utime_t now, Session *session)
 {
   int pool = 1;   // fixme.. do something smart!
   int mask = 0;
index d5c2869aec2428581c0653a42cddd9c5354f18a5..b4fe81a54df288b13b1ceb30aa631ddf4bbdc4fc 100644 (file)
@@ -579,7 +579,7 @@ void Server::set_trace_dist(Session *session, MClientReply *reply, CInode *in, C
   bufferlist bl;
   int whoami = mds->get_nodeid();
   int client = session->get_client();
-  int numi = 0, numdn = 0;
+  __u32 numi = 0, numdn = 0;
 
   // choose lease duration
   utime_t now = g_clock.now();
@@ -618,7 +618,12 @@ void Server::set_trace_dist(Session *session, MClientReply *reply, CInode *in, C
   goto inode;
 
 done:
-  reply->set_trace(numi, numdn, bl);
+  // put numi, numd in front
+  bufferlist fbl;
+  ::_encode(numi, fbl);
+  ::_encode(numdn, fbl);
+  fbl.claim_append(bl);
+  reply->set_trace(fbl);
 }
 
 
@@ -1792,7 +1797,7 @@ void Server::handle_client_readdir(MDRequest *mdr)
   
   // yay, reply
   MClientReply *reply = new MClientReply(req);
-  reply->take_dir_items(dirbl);
+  reply->set_dir_bl(dirbl);
   
   dout(10) << "reply to " << *req << " readdir " << numfiles << " files" << dendl;
   reply->set_result(0);
index 669ce96a4b20cfd099a8c683379cd6b9235da803..5c5fc5ea14f7906854aa075815d40d752185ce5b 100644 (file)
@@ -50,6 +50,13 @@ class CInode;
  *
  */
 
+
+struct LeaseStat {
+  // this matches ceph_mds_reply_lease
+  __u16 mask;
+  __u32 duration_ms;  
+};
+
 struct DirStat {
   // mds distribution hints
   frag_t frag;
@@ -163,18 +170,7 @@ struct InodeStat {
 class MClientReply : public Message {
   // reply data
   struct ceph_mds_reply_head st;
-  /*
-  list<InodeStat*> trace_in;
-  list<DirStat*>   trace_dir;
-  list<string>     trace_dn;
-  list<char>       trace_dn_mask;
-  */
   bufferlist trace_bl;
-
-  DirStat *dir_dir;
-  list<InodeStat*> dir_in;
-  list<string> dir_dn;
   bufferlist dir_bl;
 
  public:
@@ -186,9 +182,6 @@ class MClientReply : public Message {
 
   int get_result() { return st.result; }
 
-  inodeno_t get_ino() { return trace_in.back()->inode.ino; }
-  const inode_t& get_inode() { return trace_in.back()->inode; }
-
   unsigned char get_file_caps() { return st.file_caps; }
   long get_file_caps_seq() { return st.file_caps_seq; }
   //uint64_t get_file_data_version() { return st.file_data_version; }
@@ -198,22 +191,14 @@ class MClientReply : public Message {
   void set_file_caps_seq(long s) { st.file_caps_seq = s; }
   //void set_file_data_version(uint64_t v) { st.file_data_version = v; }
 
-  MClientReply() : dir_dir(0) {}
+  MClientReply() {}
   MClientReply(MClientRequest *req, int result = 0) : 
-    Message(CEPH_MSG_CLIENT_REPLY), dir_dir(0) {
+    Message(CEPH_MSG_CLIENT_REPLY) {
     memset(&st, 0, sizeof(st));
     this->st.tid = cpu_to_le64(req->get_tid());
     this->st.op = req->get_op();
     this->st.result = result;
   }
-  virtual ~MClientReply() {
-    list<InodeStat*>::iterator it;
-    
-    for (it = trace_in.begin(); it != trace_in.end(); ++it) 
-      delete *it;
-    for (it = dir_in.begin(); it != dir_in.end(); ++it) 
-      delete *it;
-  }
   const char *get_type_name() { return "creply"; }
   void print(ostream& o) {
     o << "creply(" << env.dst.name << "." << le64_to_cpu(st.tid);
@@ -239,98 +224,20 @@ class MClientReply : public Message {
 
 
   // dir contents
-  void take_dir_items(bufferlist& bl) {
+  void set_dir_bl(bufferlist& bl) {
     dir_bl.claim(bl);
   }
-  void _decode_dir() {
-    bufferlist::iterator p = dir_bl.begin();
-    dir_dir = new DirStat(p);
-    __u32 num;
-    ::_decode_simple(num, p);
-    while (num--) {
-      string dn;
-      ::_decode_simple(dn, p);
-      dir_dn.push_back(dn);
-      dir_in.push_back(new InodeStat(p));
-    }
-    assert(p.end());
-  }
-
-  const list<InodeStat*>& get_dir_in() { 
-    if (dir_in.empty() && dir_bl.length()) _decode_dir();
-    return dir_in;
+  bufferlist &get_dir_bl() {
+    return dir_bl;
   }
-  const list<string>& get_dir_dn() { 
-    if (dir_dn.empty() && dir_bl.length()) _decode_dir();    
-    return dir_dn; 
-  }
-  const DirStat* get_dir_dir() {
-    return dir_dir;
-  }
-
 
   // trace
-  void set_trace(__u16 numi, __u16 numdn, bufferlist& bl) {
-    ::_encode_simple(numi, trace_bl);
-    ::_encode_simple(numdn, trace_bl);
-    trace_bl.claim_append(bl);
+  void set_trace(bufferlist& bl) {
+    trace_bl.claim(bl);
   }
   bufferlist& get_trace_bl() {
     return trace_bl;
   }
-  /*
-  void _decode_trace() {
-    bufferlist::iterator p = trace_bl.begin();
-    __u16 numi, numdn;
-    string ref_dn;
-    char dn_mask;
-
-    ::_decode_simple(numi, p);
-    ::_decode_simple(numdn, p);
-    if (numi == numdn) 
-      goto dentry;
-
-  inode:
-    // inode
-    trace_in.push_front(new InodeStat(p));
-    if (--numi == 0) goto done;
-
-  dentry:
-    // dentry, dir
-    ::_decode_simple(ref_dn, p);
-    ::_decode_simple(dn_mask, p);
-    trace_dn.push_front(ref_dn);
-    trace_dn_mask.push_front(dn_mask);
-    trace_dir.push_front(new DirStat(p));
-    numdn--;
-    goto inode;
-
-  done:
-    assert(p.end());
-  }
-
-  bool have_trailing_inode() {
-    return trace_in.size() > trace_dn.size();
-  }
-
-  const list<InodeStat*>& get_trace_in() { 
-    if (trace_in.empty() && trace_bl.length()) _decode_trace();
-    return trace_in; 
-  }
-  const list<DirStat*>& get_trace_dir() { 
-    if (trace_in.empty() && trace_bl.length()) _decode_trace();
-    return trace_dir; 
-  }
-  const list<string>& get_trace_dn() { 
-    if (trace_in.empty() && trace_bl.length()) _decode_trace();
-    return trace_dn; 
-  }
-  const list<char>& get_trace_dn_mask() { 
-    if (trace_in.empty() && trace_bl.length()) _decode_trace();
-    return trace_dn_mask; 
-  }
-  */
-
 };
 
 #endif