summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2013-09-19 13:48:38 +0800
committerYan, Zheng <zheng.z.yan@intel.com>2013-10-05 11:31:12 +0800
commit5074464017eea816ff534bdd8dec446278fddd09 (patch)
tree05a149b08df5e32eb89ceed294a11e26215f8a72
parentfe99882583d7373a71a3a1c22bddc8452d140a0a (diff)
downloadceph-5074464017eea816ff534bdd8dec446278fddd09.tar.gz
mds: handle dirfrag mismatch when processing readdir request
If client has outdated dirfrags information, readdir request from it may specify a non-existing dirfrag. Current method to handle this case is reply -EAGAIN and let client retry. When client receives the the -EAGAIN reply, it need to refresh its dirfrags information first, then re-send the readdir request. A better way to handle client request that specify a non-existing dirfrag is: MDS chooses a approximate dirfrag, then handle the request like normal. When client receives the readdir reply, it will also update its dirfrags information. Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
-rw-r--r--src/mds/Server.cc21
1 files changed, 9 insertions, 12 deletions
diff --git a/src/mds/Server.cc b/src/mds/Server.cc
index 869f3773441..733bdac5c7b 100644
--- a/src/mds/Server.cc
+++ b/src/mds/Server.cc
@@ -2735,13 +2735,15 @@ void Server::handle_client_readdir(MDRequest *mdr)
// which frag?
frag_t fg = (__u32)req->head.args.readdir.frag;
- dout(10) << " frag " << fg << dendl;
+ string offset_str = req->get_path2();
+ dout(10) << " frag " << fg << " offset '" << offset_str << "'" << dendl;
// does the frag exist?
if (diri->dirfragtree[fg.value()] != fg) {
- dout(10) << "frag " << fg << " doesn't appear in fragtree " << diri->dirfragtree << dendl;
- reply_request(mdr, -EAGAIN);
- return;
+ frag_t newfg = diri->dirfragtree[fg.value()];
+ dout(10) << " adjust frag " << fg << " -> " << newfg << " " << diri->dirfragtree << dendl;
+ fg = newfg;
+ offset_str.clear();
}
CDir *dir = try_open_auth_dirfrag(diri, fg, mdr);
@@ -2770,12 +2772,7 @@ void Server::handle_client_readdir(MDRequest *mdr)
mdr->now = ceph_clock_now(g_ceph_context);
snapid_t snapid = mdr->snapid;
-
- string offset_str = req->get_path2();
- const char *offset = offset_str.length() ? offset_str.c_str() : 0;
-
- dout(10) << "snapid " << snapid << " offset '" << offset_str << "'" << dendl;
-
+ dout(10) << "snapid " << snapid << dendl;
// purge stale snap data?
const set<snapid_t> *snaps = 0;
@@ -2831,7 +2828,7 @@ void Server::handle_client_readdir(MDRequest *mdr)
continue;
}
- if (offset && strcmp(dn->get_name().c_str(), offset) <= 0)
+ if (!offset_str.empty() && dn->get_name().compare(offset_str) <= 0)
continue;
CInode *in = dnl->get_inode();
@@ -2901,7 +2898,7 @@ void Server::handle_client_readdir(MDRequest *mdr)
}
__u8 end = (it == dir->end());
- __u8 complete = (end && !offset); // FIXME: what purpose does this serve
+ __u8 complete = (end && offset_str.empty()); // FIXME: what purpose does this serve
// finish final blob
::encode(numfiles, dirbl);