From 9e1efd6c45485030032b3e982c7d2eadc317a6d4 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 11 Jan 2018 17:50:22 +0800 Subject: [PATCH] client: fix cap revoke race If caps are been revoking by the auth MDS, don't consider them as issued even they are still issued by non-auth MDS. The non-auth MDS should also be revoking/exporting these caps, the client just hasn't received the cap revoke/export message. The race I encountered is: When caps are exporting to new MDS, the client receives cap import message and cap revoke message from the new MDS, then receives cap export message from the old MDS. When the client receives cap revoke message from the new MDS, the revoking caps are still issued by the old MDS, so the client does nothing. Later when the cap export message is received, the client removes the caps issued by the old MDS. (Another way to fix the race is calling ceph_check_caps() in handle_cap_export()) copid from kernel commit b1530f57 Signed-off-by: "Yan, Zheng" (cherry picked from commit 99d8c303ce689b7348a6ce923721cbd140775e1b) Conflicts: src/client/Inode.cc: Resolved for loop conflict in << operator and caps_issued func --- src/client/Inode.cc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/client/Inode.cc b/src/client/Inode.cc index 0dca7bdaae661..1fbae7084a588 100644 --- a/src/client/Inode.cc +++ b/src/client/Inode.cc @@ -23,10 +23,11 @@ ostream& operator<<(ostream &out, const Inode &in) << " caps=" << ccap_string(in.caps_issued()); if (!in.caps.empty()) { out << "("; - for (auto p = in.caps.begin(); p != in.caps.end(); ++p) { - if (p != in.caps.begin()) + bool first = true; + for (const auto &pair : in.caps) { + if (!first) out << ','; - out << p->first << '=' << ccap_string(p->second->issued); + out << pair.first << '=' << ccap_string(pair.second->issued); } out << ")"; } @@ -171,6 +172,12 @@ int Inode::caps_issued(int *implemented) const c |= it->second->issued; i |= it->second->implemented; } + // exclude caps issued by non-auth MDS, but are been revoking by + // the auth MDS. The non-auth MDS should be revoking/exporting + // these caps, but the message is delayed. + if (auth_cap) + c &= ~auth_cap->implemented | auth_cap->issued; + if (implemented) *implemented = i; return c; -- 2.39.5