]> git.proxmox.com Git - ceph.git/blob - ceph/src/mds/MDSContext.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / mds / MDSContext.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2012 Red Hat
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15
16 #include "MDSRank.h"
17
18 #include "MDSContext.h"
19
20 #include "common/dout.h"
21 #define dout_context g_ceph_context
22 #define dout_subsys ceph_subsys_mds
23
24 void MDSContext::complete(int r) {
25 MDSRank *mds = get_mds();
26 ceph_assert(mds != nullptr);
27 ceph_assert(ceph_mutex_is_locked_by_me(mds->mds_lock));
28 dout(10) << "MDSContext::complete: " << typeid(*this).name() << dendl;
29 mds->heartbeat_reset();
30 return Context::complete(r);
31 }
32
33 void MDSInternalContextWrapper::finish(int r)
34 {
35 fin->complete(r);
36 }
37
38 struct MDSIOContextList {
39 elist<MDSIOContextBase*> list;
40 ceph::spinlock lock;
41 MDSIOContextList() : list(member_offset(MDSIOContextBase, list_item)) {}
42 ~MDSIOContextList() {
43 list.clear(); // avoid assertion in elist's destructor
44 }
45 } ioctx_list;
46
47 MDSIOContextBase::MDSIOContextBase(bool track)
48 {
49 created_at = ceph::coarse_mono_clock::now();
50 if (track) {
51 ioctx_list.lock.lock();
52 ioctx_list.list.push_back(&list_item);
53 ioctx_list.lock.unlock();
54 }
55 }
56
57 MDSIOContextBase::~MDSIOContextBase()
58 {
59 ioctx_list.lock.lock();
60 list_item.remove_myself();
61 ioctx_list.lock.unlock();
62 }
63
64 bool MDSIOContextBase::check_ios_in_flight(ceph::coarse_mono_time cutoff,
65 std::string& slow_count,
66 ceph::coarse_mono_time& oldest)
67 {
68 static const unsigned MAX_COUNT = 100;
69 unsigned slow = 0;
70
71 ioctx_list.lock.lock();
72 for (elist<MDSIOContextBase*>::iterator p = ioctx_list.list.begin(); !p.end(); ++p) {
73 MDSIOContextBase *c = *p;
74 if (c->created_at >= cutoff)
75 break;
76 ++slow;
77 if (slow > MAX_COUNT)
78 break;
79 if (slow == 1)
80 oldest = c->created_at;
81 }
82 ioctx_list.lock.unlock();
83
84 if (slow > 0) {
85 if (slow > MAX_COUNT)
86 slow_count = std::to_string(MAX_COUNT) + "+";
87 else
88 slow_count = std::to_string(slow);
89 return true;
90 } else {
91 return false;
92 }
93 }
94
95 void MDSIOContextBase::complete(int r) {
96 MDSRank *mds = get_mds();
97
98 dout(10) << "MDSIOContextBase::complete: " << typeid(*this).name() << dendl;
99 ceph_assert(mds != NULL);
100 // Note, MDSIOContext is passed outside the MDS and, strangely, we grab the
101 // lock here when MDSContext::complete would otherwise assume the lock is
102 // already acquired.
103 std::lock_guard l(mds->mds_lock);
104
105 if (mds->is_daemon_stopping()) {
106 dout(4) << "MDSIOContextBase::complete: dropping for stopping "
107 << typeid(*this).name() << dendl;
108 return;
109 }
110
111 // It's possible that the osd op requests will be stuck and then times out
112 // after "rados_osd_op_timeout", the mds won't know what we should it, just
113 // respawn it.
114 if (r == -CEPHFS_EBLOCKLISTED || r == -CEPHFS_ETIMEDOUT) {
115 derr << "MDSIOContextBase: failed with " << r << ", restarting..." << dendl;
116 mds->respawn();
117 } else {
118 MDSContext::complete(r);
119 }
120 }
121
122 void MDSLogContextBase::complete(int r) {
123 MDLog *mdlog = get_mds()->mdlog;
124 uint64_t safe_pos = write_pos;
125 pre_finish(r);
126 // MDSIOContext::complete() free this
127 MDSIOContextBase::complete(r);
128 // safe_pos must be updated after MDSIOContext::complete() call
129 mdlog->set_safe_pos(safe_pos);
130 }
131
132 void MDSIOContextWrapper::finish(int r)
133 {
134 fin->complete(r);
135 }
136
137 void C_IO_Wrapper::complete(int r)
138 {
139 if (async) {
140 async = false;
141 get_mds()->finisher->queue(this, r);
142 } else {
143 MDSIOContext::complete(r);
144 }
145 }