From: Yan, Zheng Date: Thu, 17 Aug 2017 06:28:16 +0000 (+0800) Subject: mds: properly setup need_snapflush for flushsnap messages X-Git-Tag: v13.0.2~852^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=6085e035bca2cb4055ae2c6875b9b2a89d0d0155;p=ceph.git mds: properly setup need_snapflush for flushsnap messages When processing a cap flush message that is re-sent, it's possble that the sender has already released all WR caps. So can't rely on CEPH_CAP_ANY_WR check in MDCache:cow_inode(). Signed-off-by: "Yan, Zheng" --- diff --git a/src/mds/Capability.h b/src/mds/Capability.h index 0aaeda5c203e..e3ada8411c43 100644 --- a/src/mds/Capability.h +++ b/src/mds/Capability.h @@ -109,6 +109,7 @@ public: const static unsigned STATE_STALE = (1<<0); const static unsigned STATE_NEW = (1<<1); const static unsigned STATE_IMPORTING = (1<<2); + const static unsigned STATE_NEEDSNAPFLUSH = (1<<3); Capability(CInode *i = NULL, uint64_t id = 0, client_t c = 0) : @@ -242,6 +243,9 @@ public: bool is_importing() { return state & STATE_IMPORTING; } void mark_importing() { state |= STATE_IMPORTING; } void clear_importing() { state &= ~STATE_IMPORTING; } + bool need_snapflush() { return state & STATE_NEEDSNAPFLUSH; } + void mark_needsnapflush() { state |= STATE_NEEDSNAPFLUSH; } + void clear_needsnapflush() { state &= ~STATE_NEEDSNAPFLUSH; } CInode *get_inode() { return inode; } client_t get_client() const { return client; } diff --git a/src/mds/Locker.cc b/src/mds/Locker.cc index 388f6a58bcf4..7b214eadb6f9 100644 --- a/src/mds/Locker.cc +++ b/src/mds/Locker.cc @@ -2633,10 +2633,11 @@ void Locker::handle_client_caps(MClientCaps *m) m->put(); return; } - if (mds->is_reconnect() && + if ((mds->is_reconnect() || mds->get_want_state() == MDSMap::STATE_RECONNECT) && m->get_dirty() && m->get_client_tid() > 0 && !session->have_completed_flush(m->get_client_tid())) { - mdcache->set_reconnected_dirty_caps(client, m->get_ino(), m->get_dirty()); + mdcache->set_reconnected_dirty_caps(client, m->get_ino(), m->get_dirty(), + m->get_op() == CEPH_CAP_OP_FLUSHSNAP); } mds->wait_for_replay(new C_MDS_RetryMessage(mds, m)); return; @@ -2850,6 +2851,8 @@ void Locker::handle_client_caps(MClientCaps *m) dout(10) << " revocation in progress, not making any conclusions about null snapflushes" << dendl; } } + if (cap->need_snapflush() && (m->flags & MClientCaps::FLAG_NO_CAPSNAP)) + cap->clear_needsnapflush(); if (m->get_dirty() && in->is_auth()) { dout(7) << " flush client." << client << " dirty " << ccap_string(m->get_dirty()) diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index a82485e0078f..dbb0dbc7f2e3 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -1531,7 +1531,7 @@ CInode *MDCache::cow_inode(CInode *in, snapid_t last) for (auto p : in->client_caps) { client_t client = p.first; Capability *cap = p.second; - int issued = cap->issued(); + int issued = cap->need_snapflush() ? CEPH_CAP_ANY_WR : cap->issued(); if ((issued & CEPH_CAP_ANY_WR) && cap->client_follows < last) { // note in oldin @@ -5782,8 +5782,17 @@ void MDCache::open_snap_parents() auto q = reconnected_caps.find(child->ino()); assert(q != reconnected_caps.end()); for (auto r = q->second.begin(); r != q->second.end(); ++r) { - if (r->second.snap_follows > 0 && r->second.snap_follows < in->first - 1) { - rebuild_need_snapflush(child, in->snaprealm, r->first, r->second.snap_follows); + if (r->second.snap_follows > 0) { + if (r->second.snap_follows < child->first - 1) { + rebuild_need_snapflush(child, in->snaprealm, r->first, r->second.snap_follows); + } else if (r->second.snapflush) { + // When processing a cap flush message that is re-sent, it's possble + // that the sender has already released all WR caps. So we should + // force MDCache::cow_inode() to setup CInode::client_need_snapflush. + Capability *cap = child->get_client_cap(r->first); + if (cap) + cap->mark_needsnapflush(); + } } // make sure client's cap is in the correct snaprealm. if (r->second.realm_ino != in->ino()) { diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index 8fd8472e378e..8d5bda648344 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -616,8 +616,9 @@ public: inodeno_t realm_ino; snapid_t snap_follows; int dirty_caps; + bool snapflush; reconnected_cap_info_t() : - realm_ino(0), snap_follows(0), dirty_caps(0) {} + realm_ino(0), snap_follows(0), dirty_caps(0), snapflush(false) {} }; map > reconnected_caps; // inode -> client -> snap_follows,realmino map > reconnected_snaprealms; // realmino -> client -> realmseq @@ -627,9 +628,11 @@ public: info.realm_ino = inodeno_t(icr.capinfo.snaprealm); info.snap_follows = icr.snap_follows; } - void set_reconnected_dirty_caps(client_t client, inodeno_t ino, int dirty) { + void set_reconnected_dirty_caps(client_t client, inodeno_t ino, int dirty, bool snapflush) { reconnected_cap_info_t &info = reconnected_caps[ino][client]; info.dirty_caps |= dirty; + if (snapflush) + info.snapflush = snapflush; } void add_reconnected_snaprealm(client_t client, inodeno_t ino, snapid_t seq) { reconnected_snaprealms[ino][client] = seq;