From: Yan, Zheng Date: Sat, 23 Apr 2016 08:03:48 +0000 (+0800) Subject: mds: sort dentries in CDir in hash order X-Git-Tag: v10.2.2~8^2~8 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=9ce73cdeb6056060b299cf92e4c858d1ab2aef2c;p=ceph.git mds: sort dentries in CDir in hash order This gives us stable ordering of dentries. (Previously ordering of dentries changes after directory gets fragmented) Signed-off-by: Yan, Zheng (cherry picked from commit f483224a0bc70b9eb5f62cd6cbb8b97df5b65953) Signed-off-by: Greg Farnum hash_dentry_name(name))); if (iter == items.end()) return 0; if (iter->second->name == name && @@ -310,9 +311,13 @@ CDentry *CDir::lookup(const char *name, snapid_t snap) return 0; } - - - +CDentry *CDir::lookup_exact_snap(const string& name, snapid_t last) { + map_t::iterator p = items.find(dentry_key_t(last, name.c_str(), + inode->hash_dentry_name(name))); + if (p == items.end()) + return NULL; + return p->second; +} /*** * linking fun diff --git a/src/mds/CDir.h b/src/mds/CDir.h index 2748526125f7..7b6d4888f867 100644 --- a/src/mds/CDir.h +++ b/src/mds/CDir.h @@ -448,16 +448,11 @@ protected: // -- dentries and inodes -- public: - CDentry* lookup_exact_snap(const std::string& dname, snapid_t last) { - map_t::iterator p = items.find(dentry_key_t(last, dname.c_str())); - if (p == items.end()) - return NULL; - return p->second; + CDentry* lookup_exact_snap(const std::string& dname, snapid_t last); + CDentry* lookup(const std::string& n, snapid_t snap=CEPH_NOSNAP); + CDentry* lookup(const char *n, snapid_t snap=CEPH_NOSNAP) { + return lookup(std::string(n), snap); } - CDentry* lookup(const std::string& n, snapid_t snap=CEPH_NOSNAP) { - return lookup(n.c_str(), snap); - } - CDentry* lookup(const char *n, snapid_t snap=CEPH_NOSNAP); CDentry* add_null_dentry(const std::string& dname, snapid_t first=2, snapid_t last=CEPH_NOSNAP); diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 152b47b85ae4..ddf46842276f 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -4558,6 +4558,7 @@ CDir *MDCache::rejoin_invent_dirfrag(dirfrag_t df) if (!in->is_dir()) { assert(in->state_test(CInode::STATE_REJOINUNDEF)); in->inode.mode = S_IFDIR; + in->inode.dir_layout.dl_dir_hash = g_conf->mds_default_dir_hash; } CDir *dir = in->get_or_open_dirfrag(this, df.frag); dir->state_set(CDir::STATE_REJOINUNDEF); @@ -5753,6 +5754,8 @@ void MDCache::opened_undef_inode(CInode *in) { dout(10) << "opened_undef_inode " << *in << dendl; rejoin_undef_inodes.erase(in); if (in->is_dir()) { + // FIXME: re-hash dentries if necessary + assert(in->inode.dir_layout.dl_dir_hash == g_conf->mds_default_dir_hash); if (in->has_dirfrags() && !in->dirfragtree.is_leaf(frag_t())) { CDir *dir = in->get_dirfrag(frag_t()); assert(dir); diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 750fb418cef4..d303b531f280 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -3277,6 +3277,10 @@ void Server::handle_client_readdir(MDRequestRef& mdr) string offset_str = req->get_path2(); dout(10) << " frag " << fg << " offset '" << offset_str << "'" << dendl; + __u32 offset_hash = 0; + if (!offset_str.empty()) + offset_hash = ceph_frag_value(diri->hash_dentry_name(offset_str)); + // does the frag exist? if (diri->dirfragtree[fg.value()] != fg) { frag_t newfg = diri->dirfragtree[fg.value()]; @@ -3359,8 +3363,11 @@ void Server::handle_client_readdir(MDRequestRef& mdr) continue; } - if (!offset_str.empty() && dn->get_name().compare(offset_str) <= 0) - continue; + if (!offset_str.empty()) { + dentry_key_t offset_key(dn->last, offset_str.c_str(), offset_hash); + if (!(offset_key < dn->key())) + continue; + } CInode *in = dnl->get_inode(); diff --git a/src/mds/mdstypes.h b/src/mds/mdstypes.h index e789856b36d7..991712d4de77 100644 --- a/src/mds/mdstypes.h +++ b/src/mds/mdstypes.h @@ -721,8 +721,10 @@ WRITE_CLASS_ENCODER(session_info_t) struct dentry_key_t { snapid_t snapid; const char *name; - dentry_key_t() : snapid(0), name(0) {} - dentry_key_t(snapid_t s, const char *n) : snapid(s), name(n) {} + __u32 hash; + dentry_key_t() : snapid(0), name(0), hash(0) {} + dentry_key_t(snapid_t s, const char *n, __u32 h=0) : + snapid(s), name(n), hash(h) {} bool is_valid() { return name || snapid; } @@ -774,11 +776,15 @@ inline std::ostream& operator<<(std::ostream& out, const dentry_key_t &k) inline bool operator<(const dentry_key_t& k1, const dentry_key_t& k2) { /* - * order by name, then snap + * order by hash, name, snap */ - int c = strcmp(k1.name, k2.name); - return - c < 0 || (c == 0 && k1.snapid < k2.snapid); + int c = ceph_frag_value(k1.hash) - ceph_frag_value(k2.hash); + if (c) + return c < 0; + c = strcmp(k1.name, k2.name); + if (c) + return c < 0; + return k1.snapid < k2.snapid; }