Skip to content

Commit

Permalink
Merge pull request ceph#6432 from ukernel/wip-11482
Browse files Browse the repository at this point in the history
mds: fix client capabilities during reconnect (client.XXXX isn't responding to mclientcaps(revoke))

Reviewed-by: John Spray <[email protected]>
  • Loading branch information
jcsp committed Nov 30, 2015
2 parents 1ada4c3 + e242d84 commit 304965f
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 13 deletions.
12 changes: 7 additions & 5 deletions src/client/Client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2498,14 +2498,16 @@ void Client::send_reconnect(MetaSession *session)
bufferlist flockbl;
_encode_filelocks(in, flockbl);

in->caps[mds]->seq = 0; // reset seq.
in->caps[mds]->issue_seq = 0; // reset seq.
in->caps[mds]->mseq = 0; // reset seq.
Cap *cap = in->caps[mds];
cap->seq = 0; // reset seq.
cap->issue_seq = 0; // reset seq.
cap->mseq = 0; // reset seq.
cap->issued = cap->implemented;
m->add_cap(p->first.ino,
in->caps[mds]->cap_id,
cap->cap_id,
path.get_ino(), path.get_path(), // ino
in->caps_wanted(), // wanted
in->caps[mds]->issued, // issued
cap->issued, // issued
in->snaprealm->ino,
flockbl);

Expand Down
6 changes: 3 additions & 3 deletions src/mds/CInode.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2695,7 +2695,7 @@ void CInode::choose_lock_state(SimpleLock *lock, int allissued)
if (lock->is_xlocked()) {
// do nothing here
} else if (lock->get_state() != LOCK_MIX) {
if (issued & CEPH_CAP_GEXCL)
if (issued & (CEPH_CAP_GEXCL | CEPH_CAP_GBUFFER))
lock->set_state(LOCK_EXCL);
else if (issued & CEPH_CAP_GWR)
lock->set_state(LOCK_MIX);
Expand All @@ -2714,9 +2714,9 @@ void CInode::choose_lock_state(SimpleLock *lock, int allissued)
}
}

void CInode::choose_lock_states()
void CInode::choose_lock_states(int dirty_caps)
{
int issued = get_caps_issued();
int issued = get_caps_issued() | dirty_caps;
if (is_auth() && (issued & (CEPH_CAP_ANY_EXCL|CEPH_CAP_ANY_WR)) &&
choose_ideal_loner() >= 0)
try_set_loner();
Expand Down
2 changes: 1 addition & 1 deletion src/mds/CInode.h
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,7 @@ class CInode : public MDSCacheObject, public InodeStoreBase {

// choose new lock state during recovery, based on issued caps
void choose_lock_state(SimpleLock *lock, int allissued);
void choose_lock_states();
void choose_lock_states(int dirty_caps);

int count_nonstale_caps() {
int n = 0;
Expand Down
5 changes: 5 additions & 0 deletions src/mds/Locker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2463,6 +2463,11 @@ void Locker::handle_client_caps(MClientCaps *m)
<< " op " << ceph_cap_op_name(m->get_op()) << dendl;

if (!mds->is_clientreplay() && !mds->is_active() && !mds->is_stopping()) {
if (mds->is_reconnect() &&
m->get_dirty() && m->get_client_tid() > 0 &&
session->have_completed_flush(m->get_client_tid())) {
mdcache->set_reconnect_dirty_caps(m->get_ino(), m->get_dirty());
}
mds->wait_for_replay(new C_MDS_RetryMessage(mds, m));
return;
}
Expand Down
13 changes: 11 additions & 2 deletions src/mds/MDCache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5375,7 +5375,11 @@ void MDCache::choose_lock_states_and_reconnect_caps()
if (in->is_auth() && !in->is_base() && in->inode.is_dirty_rstat())
in->mark_dirty_rstat();

in->choose_lock_states();
int dirty_caps = 0;
map<inodeno_t, int>::iterator it = cap_imports_dirty.find(in->ino());
if (it != cap_imports_dirty.end())
dirty_caps = it->second;
in->choose_lock_states(dirty_caps);
dout(15) << " chose lock states on " << *in << dendl;

SnapRealm *realm = in->find_snaprealm();
Expand Down Expand Up @@ -5521,6 +5525,7 @@ void MDCache::export_remaining_imported_caps()
}

cap_imports.clear();
cap_imports_dirty.clear();

if (warn_str.peek() != EOF) {
mds->clog->warn() << "failed to reconnect caps for missing inodes:" << "\n";
Expand All @@ -5543,7 +5548,11 @@ void MDCache::try_reconnect_cap(CInode *in, Session *session)
if (in->is_replicated()) {
mds->locker->try_eval(in, CEPH_CAP_LOCKS);
} else {
in->choose_lock_states();
int dirty_caps = 0;
map<inodeno_t, int>::iterator it = cap_imports_dirty.find(in->ino());
if (it != cap_imports_dirty.end())
dirty_caps = it->second;
in->choose_lock_states(dirty_caps);
dout(15) << " chose lock states on " << *in << dendl;
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/mds/MDCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ class MDCache {
map<inodeno_t,mds_rank_t> cap_export_targets; // ino -> auth mds

map<inodeno_t,map<client_t,map<mds_rank_t,ceph_mds_cap_reconnect> > > cap_imports; // ino -> client -> frommds -> capex
map<inodeno_t,filepath> cap_import_paths;
map<inodeno_t,int> cap_imports_dirty;
set<inodeno_t> cap_imports_missing;
int cap_imports_num_opening;

Expand Down Expand Up @@ -534,7 +534,6 @@ class MDCache {
void rejoin_recovered_caps(inodeno_t ino, client_t client, cap_reconnect_t& icr,
mds_rank_t frommds=MDS_RANK_NONE) {
cap_imports[ino][client][frommds] = icr.capinfo;
cap_import_paths[ino] = filepath(icr.path, (uint64_t)icr.capinfo.pathbase);
}
ceph_mds_cap_reconnect *get_replay_cap_reconnect(inodeno_t ino, client_t client) {
if (cap_imports.count(ino) &&
Expand All @@ -549,6 +548,9 @@ class MDCache {
assert(cap_imports[ino][client].size() == 1);
cap_imports.erase(ino);
}
void set_reconnect_dirty_caps(inodeno_t ino, int dirty) {
cap_imports_dirty[ino] |= dirty;
}

// [reconnect/rejoin caps]
map<CInode*,map<client_t, inodeno_t> > reconnected_caps; // inode -> client -> realmino
Expand Down

0 comments on commit 304965f

Please sign in to comment.