summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2013-05-06 09:09:59 +0800
committerYan, Zheng <zheng.z.yan@intel.com>2013-05-28 13:57:21 +0800
commit3962a7510fd7f963c98ee34118cdd15cc9014c10 (patch)
treea6175f9edcb730142651e28c6a052a357326dd8d
parenta918e611e2d945a79de70730bd86da7636f6cf11 (diff)
downloadceph-3962a7510fd7f963c98ee34118cdd15cc9014c10.tar.gz
mds: defer releasing cap if necessary
When inode is freezing or frozen, we defer processing MClientCaps messages and cap release embedded in requests. The same deferral logical should also cover MClientCapRelease messages.
-rw-r--r--src/mds/Locker.cc88
-rw-r--r--src/mds/Locker.h2
2 files changed, 58 insertions, 32 deletions
diff --git a/src/mds/Locker.cc b/src/mds/Locker.cc
index 7e3e9fd8895..7823aedb536 100644
--- a/src/mds/Locker.cc
+++ b/src/mds/Locker.cc
@@ -2921,41 +2921,65 @@ void Locker::handle_client_cap_release(MClientCapRelease *m)
return;
}
- for (vector<ceph_mds_cap_item>::iterator p = m->caps.begin(); p != m->caps.end(); ++p) {
- inodeno_t ino((uint64_t)p->ino);
- CInode *in = mdcache->get_inode(ino);
- if (!in) {
- dout(10) << " missing ino " << ino << dendl;
- continue;
- }
- Capability *cap = in->get_client_cap(client);
- if (!cap) {
- dout(10) << " no cap on " << *in << dendl;
- continue;
- }
- if (cap->get_cap_id() != p->cap_id) {
- dout(7) << " ignoring client capid " << p->cap_id << " != my " << cap->get_cap_id() << " on " << *in << dendl;
- continue;
- }
- if (ceph_seq_cmp(p->migrate_seq, cap->get_mseq()) < 0) {
- dout(7) << " mseq " << p->migrate_seq << " < " << cap->get_mseq()
- << " on " << *in << dendl;
- continue;
- }
- if (p->seq != cap->get_last_issue()) {
- dout(10) << " issue_seq " << p->seq << " != " << cap->get_last_issue() << " on " << *in << dendl;
-
- // clean out any old revoke history
- cap->clean_revoke_from(p->seq);
- eval_cap_gather(in);
- continue;
- }
+ for (vector<ceph_mds_cap_item>::iterator p = m->caps.begin(); p != m->caps.end(); ++p)
+ _do_cap_release(client, inodeno_t((uint64_t)p->ino) , p->cap_id, p->migrate_seq, p->seq);
- dout(7) << "removing cap on " << *in << dendl;
- remove_client_cap(in, client);
+ m->put();
+}
+
+class C_Locker_RetryCapRelease : public Context {
+ Locker *locker;
+ client_t client;
+ inodeno_t ino;
+ uint64_t cap_id;
+ ceph_seq_t migrate_seq;
+ ceph_seq_t issue_seq;
+public:
+ C_Locker_RetryCapRelease(Locker *l, client_t c, inodeno_t i, uint64_t id,
+ ceph_seq_t mseq, ceph_seq_t seq) :
+ locker(l), client(c), ino(i), cap_id(id), migrate_seq(mseq), issue_seq(seq) {}
+ void finish(int r) {
+ locker->_do_cap_release(client, ino, cap_id, migrate_seq, issue_seq);
}
+};
- m->put();
+void Locker::_do_cap_release(client_t client, inodeno_t ino, uint64_t cap_id,
+ ceph_seq_t mseq, ceph_seq_t seq)
+{
+ CInode *in = mdcache->get_inode(ino);
+ if (!in) {
+ dout(7) << "_do_cap_release missing ino " << ino << dendl;
+ return;
+ }
+ Capability *cap = in->get_client_cap(client);
+ if (!cap) {
+ dout(7) << "_do_cap_release no cap for client" << client << " on "<< *in << dendl;
+ return;
+ }
+
+ dout(7) << "_do_cap_release for client." << client << " on "<< *in << dendl;
+ if (cap->get_cap_id() != cap_id) {
+ dout(7) << " capid " << cap_id << " != " << cap->get_cap_id() << ", ignore" << dendl;
+ return;
+ }
+ if (ceph_seq_cmp(mseq, cap->get_mseq()) < 0) {
+ dout(7) << " mseq " << mseq << " < " << cap->get_mseq() << ", ignore" << dendl;
+ return;
+ }
+ if (should_defer_client_cap_frozen(in)) {
+ dout(7) << " freezing|frozen, deferring" << dendl;
+ in->add_waiter(CInode::WAIT_UNFREEZE,
+ new C_Locker_RetryCapRelease(this, client, ino, cap_id, mseq, seq));
+ return;
+ }
+ if (seq != cap->get_last_issue()) {
+ dout(7) << " issue_seq " << seq << " != " << cap->get_last_issue() << dendl;
+ // clean out any old revoke history
+ cap->clean_revoke_from(seq);
+ eval_cap_gather(in);
+ return;
+ }
+ remove_client_cap(in, client);
}
/* This function DOES put the passed message before returning */
diff --git a/src/mds/Locker.h b/src/mds/Locker.h
index f4d9861a384..b97307d6cb2 100644
--- a/src/mds/Locker.h
+++ b/src/mds/Locker.h
@@ -225,6 +225,7 @@ public:
bool _do_cap_update(CInode *in, Capability *cap, int dirty, snapid_t follows, MClientCaps *m,
MClientCaps *ack=0);
void handle_client_cap_release(class MClientCapRelease *m);
+ void _do_cap_release(client_t client, inodeno_t ino, uint64_t cap_id, ceph_seq_t mseq, ceph_seq_t seq);
// local
@@ -284,6 +285,7 @@ private:
friend class C_MDL_CheckMaxSize;
friend class C_MDL_RequestInodeFileCaps;
friend class C_Locker_FileUpdate_finish;
+ friend class C_Locker_RetryCapRelease;
// -- client leases --