Skip to content

Commit

Permalink
mds: sort dentries in CDir in hash order
Browse files Browse the repository at this point in the history
This gives us stable ordering of dentries. (Previously ordering of
dentries changes after directory gets fragmented)

Signed-off-by: Yan, Zheng <zyan@redhat.com>
  • Loading branch information
ukernel committed May 23, 2016
1 parent db5d60d commit f483224
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/mds/CDentry.h
Expand Up @@ -110,7 +110,7 @@ class CDentry : public MDSCacheObject, public LRUObject {
snapid_t first, last;

dentry_key_t key() {
return dentry_key_t(last, name.c_str());
return dentry_key_t(last, name.c_str(), hash);
}

public:
Expand Down
15 changes: 10 additions & 5 deletions src/mds/CDir.cc
Expand Up @@ -295,10 +295,11 @@ bool CDir::check_rstats(bool scrub)
return good;
}

CDentry *CDir::lookup(const char *name, snapid_t snap)
CDentry *CDir::lookup(const string& name, snapid_t snap)
{
dout(20) << "lookup (" << snap << ", '" << name << "')" << dendl;
map_t::iterator iter = items.lower_bound(dentry_key_t(snap, name));
map_t::iterator iter = items.lower_bound(dentry_key_t(snap, name.c_str(),
inode->hash_dentry_name(name)));
if (iter == items.end())
return 0;
if (iter->second->name == name &&
Expand All @@ -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
Expand Down
13 changes: 4 additions & 9 deletions src/mds/CDir.h
Expand Up @@ -448,16 +448,11 @@ class CDir : public MDSCacheObject {

// -- 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);
Expand Down
3 changes: 3 additions & 0 deletions src/mds/MDCache.cc
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
11 changes: 9 additions & 2 deletions src/mds/Server.cc
Expand Up @@ -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()];
Expand Down Expand Up @@ -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();

Expand Down
18 changes: 12 additions & 6 deletions src/mds/mdstypes.h
Expand Up @@ -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; }

Expand Down Expand Up @@ -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;
}


Expand Down

0 comments on commit f483224

Please sign in to comment.