* handle caps update from mds. including mds to mds caps transitions.
* do not block.
*/
+void Client::add_update_inode_cap(Inode *in, int mds, unsigned issued, unsigned seq, unsigned mseq)
+{
+ if (!in->caps.count(mds)) {
+ mds_sessions[mds].num_caps++;
+ if (in->caps.empty())
+ in->get();
+ if (in->exporting_mds == mds) {
+ dout(10) << " clearing exporting_caps on " << mds << dendl;
+ in->exporting_mds = -1;
+ in->exporting_issued = 0;
+ in->exporting_mseq = 0;
+ }
+ }
+ unsigned old_caps = in->caps[mds].issued;
+ InodeCap &cap = in->caps[mds];
+
+ cap.issued |= issued;
+ cap.implemented |= issued;
+ cap.seq = seq;
+ cap.mseq = mseq;
+
+ if (issued & ~old_caps)
+ signal_cond_list(in->waitfor_caps);
+}
+
+void Client::remove_cap(Inode *in, int mds)
+{
+ assert(in->caps.count(mds));
+ in->caps.erase(mds);
+ if (in->caps.empty())
+ put_inode(in);
+}
+
void Client::handle_file_caps(MClientFileCaps *m)
{
int mds = m->get_source().num();
}
if (m->get_op() == CEPH_CAP_OP_IMPORT) {
- // fresh from new mds?
- if (!in->caps.count(mds)) {
- mds_sessions[mds].num_caps++;
- if (in->caps.empty())
- in->get();
- if (in->exporting_mds == mds) {
- dout(10) << " clearing exporting_caps on " << mds << dendl;
- in->exporting_mds = -1;
- in->exporting_issued = 0;
- in->exporting_mseq = 0;
- }
- }
- in->caps[mds].seq = m->get_seq();
- in->caps[mds].issued = m->get_caps();
- in->caps[mds].mseq = m->get_mseq();
+ // add/update it
+ add_update_inode_cap(in, mds, m->get_caps(), m->get_seq(), m->get_mseq());
if (in->exporting_mseq < m->get_mseq()) {
dout(5) << "handle_file_caps ino " << m->get_ino() << " mseq " << m->get_mseq()
return;
}
- // don't have cap?
- // (it may be that we've reopened the file locally,
- // and thus want caps, but don't have a cap yet.
- // we should never reply to a cap out of turn.)
- if (in->caps.count(mds) == 0) {
- // silently drop.
- dout(5) << "handle_file_caps on ino " << m->get_ino()
- << " seq " << m->get_seq()
- << " " << cap_string(m->get_caps())
- << ", don't have this cap, silently dropping." << dendl;
- delete m;
- return;
- }
-
- // ok!
- InodeCap &cap = in->caps[mds];
-
-
- // stale?
if (m->get_op() == CEPH_CAP_OP_EXPORT) {
- // note
+ // note?
bool found_higher_mseq = false;
+ InodeCap *cap = 0;
for (map<int,InodeCap>::iterator p = in->caps.begin();
p != in->caps.end();
p++) {
- if (p->first == mds) continue;
+ if (p->first == mds) {
+ cap = &p->second;
+ continue;
+ }
if (p->second.mseq > m->get_mseq()) {
found_higher_mseq = true;
dout(5) << "handle_file_caps ino " << m->get_ino() << " mseq " << m->get_mseq()
break;
}
}
- if (!found_higher_mseq) {
+ if (cap && !found_higher_mseq) {
dout(5) << "handle_file_caps ino " << m->get_ino() << " mseq " << m->get_mseq()
<< " EXPORT from mds" << mds
- << ", setting exporting_issued " << cap_string(cap.issued) << dendl;
- in->exporting_issued = cap.issued;
+ << ", setting exporting_issued " << cap_string(cap->issued) << dendl;
+ in->exporting_issued = cap->issued;
in->exporting_mseq = m->get_mseq();
in->exporting_mds = mds;
- in->caps.erase(mds);
- if (in->caps.empty())
- put_inode(in);
+ remove_cap(in, mds);
}
delete m;
return;
}
+
+
+ // don't have cap?
+ // (it may be that we've reopened the file locally,
+ // and thus want caps, but don't have a cap yet.
+ // we should never reply to a cap out of turn.)
+ if (in->caps.count(mds) == 0) {
+ // silently drop.
+ dout(5) << "handle_file_caps on ino " << m->get_ino()
+ << " seq " << m->get_seq()
+ << " " << cap_string(m->get_caps())
+ << ", don't have this cap, silently dropping." << dendl;
+ delete m;
+ return;
+ }
+
+ // ok!
+ InodeCap &cap = in->caps[mds];
+
+
// truncate?
if (m->get_op() == CEPH_CAP_OP_TRUNC) {
dout(10) << "handle_file_caps TRUNC on ino " << in->ino()
// add the cap
int mds = reply->get_source().num();
- if (in->caps.empty()) { // first caps?
- dout(7) << " first caps on " << in->inode.ino << dendl;
- in->get();
- }
- if (in->caps.count(mds) == 0) {
- mds_sessions[mds].num_caps++;
- if (in->exporting_mds == mds) {
- dout(10) << " clearing exporting_caps on " << mds << dendl;
- in->exporting_mds = -1;
- in->exporting_issued = 0;
- in->exporting_mseq = 0;
- }
- }
- InodeCap &cap = in->caps[mds];
-
- int new_caps = reply->get_file_caps();
-
- assert(reply->get_file_caps_seq() >= cap.seq);
- if (reply->get_file_caps_seq() > cap.seq) {
- int old_caps = cap.issued;
-
- dout(7) << "open got caps " << cap_string(new_caps)
- << " (had " << cap_string(old_caps) << ")"
- << " for " << in->ino()
- << " seq " << reply->get_file_caps_seq()
- << " from mds" << mds
- << dendl;
-
- cap.issued |= new_caps;
- cap.implemented |= new_caps;
- cap.seq = reply->get_file_caps_seq();
- cap.mseq = reply->get_file_caps_mseq();
-
- // any caps?
- if (new_caps & ~old_caps)
- signal_cond_list(in->waitfor_caps);
-
- } else {
- dout(7) << "open got SAME caps " << cap_string(new_caps)
- << " for " << in->ino()
- << " seq " << reply->get_file_caps_seq()
- << " from mds" << mds
- << dendl;
- }
-
+ add_update_inode_cap(in, mds,
+ reply->get_file_caps(),
+ reply->get_file_caps_seq(),
+ reply->get_file_caps_mseq());
dout(5) << "open success, fh is " << f << " combined caps " << cap_string(in->caps_issued()) << dendl;
}