summaryrefslogtreecommitdiffstats
path: root/src/mds/MDSContext.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mds/MDSContext.cc')
-rw-r--r--src/mds/MDSContext.cc145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/mds/MDSContext.cc b/src/mds/MDSContext.cc
new file mode 100644
index 000000000..210c836b1
--- /dev/null
+++ b/src/mds/MDSContext.cc
@@ -0,0 +1,145 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2012 Red Hat
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+
+#include "MDSRank.h"
+
+#include "MDSContext.h"
+
+#include "common/dout.h"
+#define dout_context g_ceph_context
+#define dout_subsys ceph_subsys_mds
+
+void MDSContext::complete(int r) {
+ MDSRank *mds = get_mds();
+ ceph_assert(mds != nullptr);
+ ceph_assert(ceph_mutex_is_locked_by_me(mds->mds_lock));
+ dout(10) << "MDSContext::complete: " << typeid(*this).name() << dendl;
+ mds->heartbeat_reset();
+ return Context::complete(r);
+}
+
+void MDSInternalContextWrapper::finish(int r)
+{
+ fin->complete(r);
+}
+
+struct MDSIOContextList {
+ elist<MDSIOContextBase*> list;
+ ceph::spinlock lock;
+ MDSIOContextList() : list(member_offset(MDSIOContextBase, list_item)) {}
+ ~MDSIOContextList() {
+ list.clear(); // avoid assertion in elist's destructor
+ }
+} ioctx_list;
+
+MDSIOContextBase::MDSIOContextBase(bool track)
+{
+ created_at = ceph::coarse_mono_clock::now();
+ if (track) {
+ ioctx_list.lock.lock();
+ ioctx_list.list.push_back(&list_item);
+ ioctx_list.lock.unlock();
+ }
+}
+
+MDSIOContextBase::~MDSIOContextBase()
+{
+ ioctx_list.lock.lock();
+ list_item.remove_myself();
+ ioctx_list.lock.unlock();
+}
+
+bool MDSIOContextBase::check_ios_in_flight(ceph::coarse_mono_time cutoff,
+ std::string& slow_count,
+ ceph::coarse_mono_time& oldest)
+{
+ static const unsigned MAX_COUNT = 100;
+ unsigned slow = 0;
+
+ ioctx_list.lock.lock();
+ for (elist<MDSIOContextBase*>::iterator p = ioctx_list.list.begin(); !p.end(); ++p) {
+ MDSIOContextBase *c = *p;
+ if (c->created_at >= cutoff)
+ break;
+ ++slow;
+ if (slow > MAX_COUNT)
+ break;
+ if (slow == 1)
+ oldest = c->created_at;
+ }
+ ioctx_list.lock.unlock();
+
+ if (slow > 0) {
+ if (slow > MAX_COUNT)
+ slow_count = std::to_string(MAX_COUNT) + "+";
+ else
+ slow_count = std::to_string(slow);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void MDSIOContextBase::complete(int r) {
+ MDSRank *mds = get_mds();
+
+ dout(10) << "MDSIOContextBase::complete: " << typeid(*this).name() << dendl;
+ ceph_assert(mds != NULL);
+ // Note, MDSIOContext is passed outside the MDS and, strangely, we grab the
+ // lock here when MDSContext::complete would otherwise assume the lock is
+ // already acquired.
+ std::lock_guard l(mds->mds_lock);
+
+ if (mds->is_daemon_stopping()) {
+ dout(4) << "MDSIOContextBase::complete: dropping for stopping "
+ << typeid(*this).name() << dendl;
+ return;
+ }
+
+ // It's possible that the osd op requests will be stuck and then times out
+ // after "rados_osd_op_timeout", the mds won't know what we should it, just
+ // respawn it.
+ if (r == -CEPHFS_EBLOCKLISTED || r == -CEPHFS_ETIMEDOUT) {
+ derr << "MDSIOContextBase: failed with " << r << ", restarting..." << dendl;
+ mds->respawn();
+ } else {
+ MDSContext::complete(r);
+ }
+}
+
+void MDSLogContextBase::complete(int r) {
+ MDLog *mdlog = get_mds()->mdlog;
+ uint64_t safe_pos = write_pos;
+ pre_finish(r);
+ // MDSIOContext::complete() free this
+ MDSIOContextBase::complete(r);
+ // safe_pos must be updated after MDSIOContext::complete() call
+ mdlog->set_safe_pos(safe_pos);
+}
+
+void MDSIOContextWrapper::finish(int r)
+{
+ fin->complete(r);
+}
+
+void C_IO_Wrapper::complete(int r)
+{
+ if (async) {
+ async = false;
+ get_mds()->finisher->queue(this, r);
+ } else {
+ MDSIOContext::complete(r);
+ }
+}