From: Yan, Zheng Date: Fri, 10 Feb 2017 09:31:37 +0000 (+0800) Subject: mds: issue new caps to client even when session is stale X-Git-Tag: v12.0.1~266^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=355328210a3ba013fb10e3608e3be73794113899;p=ceph.git mds: issue new caps to client even when session is stale If early reply is not allowed for open request, MDS does not send reply to client immediately after adding adds new caps. Later when MDS sends the reply, client session can be in stale stale. If MDS does not issue the new caps to client along with the reply, the new caps get lost. This issue can cause MDS to hang at revoking caps. Signed-off-by: "Yan, Zheng" --- diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 51aefb0f02a..b04b4712bf3 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -3240,12 +3240,26 @@ int CInode::encode_inodestat(bufferlist& bl, Session *session, } } + int issue = 0; if (!no_caps && cap) { int likes = get_caps_liked(); int allowed = get_caps_allowed_for_client(session, file_i); - int issue = (cap->wanted() | likes) & allowed; + issue = (cap->wanted() | likes) & allowed; cap->issue_norevoke(issue); issue = cap->pending(); + dout(10) << "encode_inodestat issuing " << ccap_string(issue) + << " seq " << cap->get_last_seq() << dendl; + } else if (cap && cap->is_new() && !dir_realm) { + // alway issue new caps to client, otherwise the caps get lost + assert(cap->is_stale()); + issue = cap->pending() | CEPH_CAP_PIN; + cap->issue_norevoke(issue); + dout(10) << "encode_inodestat issuing " << ccap_string(issue) + << " seq " << cap->get_last_seq() + << "(stale|new caps)" << dendl; + } + + if (issue) { cap->set_last_issue(); cap->set_last_issue_stamp(ceph_clock_now()); cap->clear_new(); @@ -3253,13 +3267,9 @@ int CInode::encode_inodestat(bufferlist& bl, Session *session, ecap.wanted = cap->wanted(); ecap.cap_id = cap->get_cap_id(); ecap.seq = cap->get_last_seq(); - dout(10) << "encode_inodestat issuing " << ccap_string(issue) - << " seq " << cap->get_last_seq() << dendl; ecap.mseq = cap->get_mseq(); ecap.realm = realm->inode->ino(); } else { - if (cap) - cap->clear_new(); ecap.cap_id = 0; ecap.caps = 0; ecap.seq = 0; diff --git a/src/mds/Capability.h b/src/mds/Capability.h index b8ea0a1e732..f2e5805075a 100644 --- a/src/mds/Capability.h +++ b/src/mds/Capability.h @@ -107,6 +107,7 @@ public: const static unsigned STATE_STALE = (1<<0); const static unsigned STATE_NEW = (1<<1); + const static unsigned STATE_IMPORTING = (1<<2); Capability(CInode *i = NULL, uint64_t id = 0, client_t c = 0) : @@ -253,6 +254,9 @@ public: bool is_new() { return state & STATE_NEW; } void mark_new() { state |= STATE_NEW; } void clear_new() { state &= ~STATE_NEW; } + bool is_importing() { return state & STATE_IMPORTING; } + void mark_importing() { state |= STATE_IMPORTING; } + void clear_importing() { state &= ~STATE_IMPORTING; } CInode *get_inode() { return inode; } client_t get_client() const { return client; } diff --git a/src/mds/Migrator.cc b/src/mds/Migrator.cc index 1fe1c862848..52df1588205 100644 --- a/src/mds/Migrator.cc +++ b/src/mds/Migrator.cc @@ -2511,7 +2511,7 @@ void Migrator::import_reverse(CDir *dir) ++q) { Capability *cap = in->get_client_cap(q->first); assert(cap); - if (cap->is_new()) + if (cap->is_importing()) in->remove_client_cap(q->first); } in->put(CInode::PIN_IMPORTINGCAPS); @@ -2705,6 +2705,7 @@ void Migrator::import_finish(CDir *dir, bool notify, bool last) Capability *cap = in->get_client_cap(q->first); assert(cap); cap->merge(q->second, true); + cap->clear_importing(); mds->mdcache->do_cap_import(session, in, cap, q->second.cap_id, q->second.seq, q->second.mseq - 1, it->second.peer, CEPH_CAP_FLAG_AUTH); } @@ -2879,7 +2880,7 @@ void Migrator::finish_import_inode_caps(CInode *in, mds_rank_t peer, bool auth_c if (!cap) { cap = in->add_client_cap(it->first, session); if (peer < 0) - cap->mark_new(); + cap->mark_importing(); } Capability::Import& im = import_map[it->first];