Merge pull request #6432 from ukernel/wip-11482

mds: fix client capabilities during reconnect (client.XXXX isn't responding to mclientcaps(revoke))

Reviewed-by: John Spray <john.spray@redhat.com>
This commit is contained in:
John Spray 2015-11-30 17:53:51 +00:00
commit 304965f17e
6 changed files with 31 additions and 13 deletions

View File

@ -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);

View File

@ -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);
@ -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();

View File

@ -895,7 +895,7 @@ public:
// 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;

View File

@ -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;
}

View File

@ -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();
@ -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";
@ -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;
}
}

View File

@ -491,7 +491,7 @@ protected:
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;
@ -534,7 +534,6 @@ public:
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) &&
@ -549,6 +548,9 @@ public:
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