Skip to content

Commit

Permalink
mds: properly setup client_need_snapflush for snap inode
Browse files Browse the repository at this point in the history
MDCache::cow_inode() checks "cap->issued() & CEPH_CAP_ANY_WR" to decide
if it needs to setup client_need_snapflush for the new snap inode. If
cap message flushes dirty caps and releases the same caps, cap->issued()
may have no WR caps when MDCache::cow_inode() gets called. The solution
is temporarily setting NEEDSNAPFLUSH on Capability::state.

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
  • Loading branch information
ukernel committed May 15, 2018
1 parent 4b13d3f commit 9fb61cd
Showing 1 changed file with 15 additions and 6 deletions.
21 changes: 15 additions & 6 deletions src/mds/Locker.cc
Expand Up @@ -2892,16 +2892,20 @@ 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_PENDING_CAPSNAP))
cap->clear_needsnapflush();

bool need_snapflush = cap->need_snapflush();
if (m->get_dirty() && in->is_auth()) {
dout(7) << " flush client." << client << " dirty " << ccap_string(m->get_dirty())
<< " seq " << m->get_seq() << " on " << *in << dendl;
ack = new MClientCaps(CEPH_CAP_OP_FLUSH_ACK, in->ino(), 0, cap->get_cap_id(), m->get_seq(),
m->get_caps(), 0, m->get_dirty(), 0, mds->get_osd_epoch_barrier());
ack->set_client_tid(m->get_client_tid());
ack->set_oldest_flush_tid(m->get_oldest_flush_tid());

// client flushes and releases caps at the same time. make sure MDCache::cow_inode()
// properly setup CInode::client_need_snapflush
if ((m->get_dirty() & ~cap->issued()) && !need_snapflush)
cap->mark_needsnapflush();
}

// filter wanted based on what we could ever give out (given auth/replica status)
Expand All @@ -2915,10 +2919,15 @@ void Locker::handle_client_caps(MClientCaps *m)

adjust_cap_wanted(cap, new_wanted, m->get_issue_seq());
}

if (in->is_auth() &&
_do_cap_update(in, cap, m->get_dirty(), follows, m, ack, &need_flush)) {
// updated

bool updated = in->is_auth() &&
_do_cap_update(in, cap, m->get_dirty(), follows, m, ack, &need_flush);

if (cap->need_snapflush() &&
(!need_snapflush || !(m->flags & MClientCaps::FLAG_PENDING_CAPSNAP)))
cap->clear_needsnapflush();

if (updated) {
eval(in, CEPH_CAP_LOCKS);

if (!need_flush && (cap->wanted() & ~cap->pending()))
Expand Down

0 comments on commit 9fb61cd

Please sign in to comment.