]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: record 'offset' for each entry of dir_result_t::buffer
authorYan, Zheng <zyan@redhat.com>
Mon, 25 Apr 2016 02:50:17 +0000 (10:50 +0800)
committerGreg Farnum <gfarnum@redhat.com>
Sun, 12 Jun 2016 21:10:14 +0000 (14:10 -0700)
This is preparation for using hash value as dentry 'offset'

Signed-off-by: Yan, Zheng <zyan@redhat.com>
(cherry picked from commit bd6546e5e8bfb4ef8927807492d63d5285534618)

Signed-off-by: Greg Farnum <gfarnum@redhat.com
src/client/Client.cc
src/client/Client.h
src/client/Dentry.h

index 6b1213085d29a8b37e2bd307afe3754252df4b8f..82eacbfa4fc3af431ee80d065bb61b7b2b3e385a 100644 (file)
@@ -174,8 +174,8 @@ bool Client::CommandHook::call(std::string command, cmdmap_t& cmdmap,
 // -------------
 
 dir_result_t::dir_result_t(Inode *in)
-  : inode(in), owner_uid(-1), owner_gid(-1), offset(0), this_offset(2),
-    next_offset(2), release_count(0), ordered_count(0), start_shared_gen(0)
+  : inode(in), owner_uid(-1), owner_gid(-1), offset(0), next_offset(2),
+    release_count(0), ordered_count(0), start_shared_gen(0)
   { }
 
 void Client::_reset_faked_inos()
@@ -1130,7 +1130,6 @@ void Client::insert_readdir_results(MetaRequest *request, MetaSession *session,
                   << ", readdir_start " << readdir_start << dendl;
 
     dirp->buffer_frag = fg;
-    dirp->this_offset = readdir_offset;
 
     _readdir_drop_dirp_buffer(dirp);
     dirp->buffer.reserve(numdn);
@@ -1167,7 +1166,7 @@ void Client::insert_readdir_results(MetaRequest *request, MetaSession *session,
       dn->offset = dir_result_t::make_fpos(fg, readdir_offset++);
 
       // add to cached result list
-      dirp->buffer.push_back(pair<string,InodeRef>(dname, in));
+      dirp->buffer.push_back(dir_result_t::dentry(dn->offset, dname, in));
 
       ldout(cct, 15) << __func__ << "  " << hex << dn->offset << dec << ": '" << dname << "' -> " << in->ino << dendl;
     }
@@ -6961,8 +6960,7 @@ int Client::_readdir_get_frag(dir_result_t *dirp)
 
   if (res == 0) {
     ldout(cct, 10) << "_readdir_get_frag " << dirp << " got frag " << dirp->buffer_frag
-            << " this_offset " << dirp->this_offset
-            << " size " << dirp->buffer.size() << dendl;
+                  << " size " << dirp->buffer.size() << dendl;
   } else {
     ldout(cct, 10) << "_readdir_get_frag got error " << res << ", setting end flag" << dendl;
     dirp->set_end();
@@ -7020,13 +7018,14 @@ int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p)
     struct stat st;
     struct dirent de;
     int stmask = fill_stat(dn->inode, &st);
-    fill_dirent(&de, dn->name.c_str(), st.st_mode, st.st_ino, dirp->offset + 1);
-      
+
     uint64_t next_off = dn->offset + 1;
     ++pd;
     if (pd.end())
       next_off = dir_result_t::END;
 
+    fill_dirent(&de, dn->name.c_str(), st.st_mode, st.st_ino, next_off);
+
     dn_name = dn->name; // fill in name while we have lock
 
     client_lock.Unlock();
@@ -7036,11 +7035,14 @@ int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p)
             << " = " << r
             << dendl;
     if (r < 0) {
-      dirp->next_offset = next_off - 1;
       return r;
     }
 
-    dirp->next_offset = dirp->offset = next_off;
+    dirp->offset = next_off;
+    if (dirp->at_end())
+      dirp->next_offset = 2;
+    else
+      dirp->next_offset = dirp->fragpos();
     dirp->at_cache_name = dn_name; // we successfully returned this one; update!
     if (r > 0)
       return r;
@@ -7068,7 +7070,6 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p)
   memset(&st, 0, sizeof(st));
 
   frag_t fg = dirp->frag();
-  uint32_t off = dirp->fragpos();
 
   InodeRef& diri = dirp->inode;
 
@@ -7090,31 +7091,30 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p)
       return r;
 
     dirp->offset = next_off;
-    off = next_off;
     if (r > 0)
       return r;
   }
   if (dirp->offset == 1) {
     ldout(cct, 15) << " including .." << dendl;
+    uint64_t next_off = 2;
     if (!diri->dn_set.empty()) {
       InodeRef& in = diri->get_first_parent()->inode;
       fill_stat(in, &st);
-      fill_dirent(&de, "..", S_IFDIR, st.st_ino, 2);
+      fill_dirent(&de, "..", S_IFDIR, st.st_ino, next_off);
     } else {
       /* must be at the root (no parent),
        * so we add the dotdot with a special inode (3) */
-      fill_dirent(&de, "..", S_IFDIR, CEPH_INO_DOTDOT, 2);
+      fill_dirent(&de, "..", S_IFDIR, CEPH_INO_DOTDOT, next_off);
     }
 
 
     client_lock.Unlock();
-    int r = cb(p, &de, &st, -1, 2);
+    int r = cb(p, &de, &st, -1, next_off);
     client_lock.Lock();
     if (r < 0)
       return r;
 
-    dirp->offset = 2;
-    off = 2;
+    dirp->offset = next_off;
     if (r > 0)
       return r;
   }
@@ -7149,30 +7149,31 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p)
       // _readdir_get_frag () may updates dirp->offset if the replied dirfrag is
       // different than the requested one. (our dirfragtree was outdated)
       fg = dirp->buffer_frag;
-      off = dirp->fragpos();
     }
 
-    ldout(cct, 10) << "off " << off << " this_offset " << hex << dirp->this_offset << dec << " size " << dirp->buffer.size()
-            << " frag " << fg << dendl;
+    ldout(cct, 10) << "frag " << fg << " buffer size " << dirp->buffer.size()
+                  << " offset " << hex << dirp->offset << dendl;
 
-    while (off >= dirp->this_offset &&
-          off - dirp->this_offset < dirp->buffer.size()) {
-      pair<string,InodeRef>& ent = dirp->buffer[off - dirp->this_offset];
+    for (auto it = std::lower_bound(dirp->buffer.begin(), dirp->buffer.end(),
+                                   dirp->offset, dir_result_t::dentry_off_lt());
+        it != dirp->buffer.end();
+        ++it) {
+      dir_result_t::dentry &entry = *it;
+
+      uint64_t next_off = entry.offset + 1;
+      int stmask = fill_stat(entry.inode, &st);
+      fill_dirent(&de, entry.name.c_str(), st.st_mode, st.st_ino, next_off);
 
-      int stmask = fill_stat(ent.second, &st);
-      fill_dirent(&de, ent.first.c_str(), st.st_mode, st.st_ino, dirp->offset + 1);
-      
       client_lock.Unlock();
-      int r = cb(p, &de, &st, stmask, dirp->offset + 1);  // _next_ offset
+      int r = cb(p, &de, &st, stmask, next_off);  // _next_ offset
       client_lock.Lock();
-      ldout(cct, 15) << " de " << de.d_name << " off " << hex << dirp->offset << dec
-              << " = " << r
-              << dendl;
+
+      ldout(cct, 15) << " de " << de.d_name << " off " << hex << next_off - 1 << dec
+                    << " = " << r << dendl;
       if (r < 0)
        return r;
-      
-      off++;
-      dirp->offset++;
+
+      dirp->offset = next_off;
       if (r > 0)
        return r;
     }
@@ -7188,7 +7189,6 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p)
       _readdir_next_frag(dirp);
       ldout(cct, 10) << " advancing to next frag: " << fg << " -> " << dirp->frag() << dendl;
       fg = dirp->frag();
-      off = 0;
       continue;
     }
 
index b03e770cda2862fc471ae0af8d71e6b4c903b65b..df8ed79aa11b1bdc8c0578d05929a3a7d7e09476 100644 (file)
@@ -188,8 +188,7 @@ struct dir_result_t {
 
   int64_t offset;        // high bits: frag_t, low bits: an offset
 
-  uint64_t this_offset;  // offset of last chunk, adjusted for . and ..
-  uint64_t next_offset;  // offset of next chunk (last_name's + 1)
+  unsigned next_offset;  // offset of next chunk (last_name's + 1)
   string last_name;      // last entry in previous chunk
 
   uint64_t release_count;
@@ -197,7 +196,21 @@ struct dir_result_t {
   int start_shared_gen;  // dir shared_gen at start of readdir
 
   frag_t buffer_frag;
-  vector<pair<string,InodeRef> > buffer;
+
+  struct dentry {
+    int64_t offset;
+    string name;
+    InodeRef inode;
+    dentry(int64_t o) : offset(o) {}
+    dentry(int64_t o, const string& n, const InodeRef& in) :
+      offset(o), name(n), inode(in) {}
+  };
+  struct dentry_off_lt {
+    bool operator()(const dentry& d, int64_t off) const {
+      return dir_result_t::fpos_cmp(d.offset, off) < 0;
+    }
+  };
+  vector<dentry> buffer;
 
   string at_cache_name;  // last entry we successfully returned
 
@@ -224,7 +237,6 @@ struct dir_result_t {
     last_name.clear();
     at_cache_name.clear();
     next_offset = 2;
-    this_offset = 0;
     offset = 0;
     buffer.clear();
   }
index 198b375ce098804b187f2f15b37be77b54289e51..192ef01a80b4073fbd340d7709c5307f0c62bfe0 100644 (file)
@@ -17,7 +17,7 @@ class Dentry : public LRUObject {
   Dir     *dir;
   InodeRef inode;
   int     ref;                       // 1 if there's a dir beneath me.
-  uint64_t offset;
+  int64_t offset;
   mds_rank_t lease_mds;
   utime_t lease_ttl;
   uint64_t lease_gen;