]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
11fdf7f2 | 24 | void MDSContext::complete(int r) { |
7c673cae | 25 | MDSRank *mds = get_mds(); |
11fdf7f2 | 26 | ceph_assert(mds != nullptr); |
9f95a23c | 27 | ceph_assert(ceph_mutex_is_locked_by_me(mds->mds_lock)); |
11fdf7f2 | 28 | dout(10) << "MDSContext::complete: " << typeid(*this).name() << dendl; |
20effc67 | 29 | mds->heartbeat_reset(); |
11fdf7f2 | 30 | return Context::complete(r); |
7c673cae FG |
31 | } |
32 | ||
33 | void MDSInternalContextWrapper::finish(int r) | |
34 | { | |
35 | fin->complete(r); | |
36 | } | |
37 | ||
e306af50 TL |
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; | |
91327a77 AA |
46 | |
47 | MDSIOContextBase::MDSIOContextBase(bool track) | |
48 | { | |
49 | created_at = ceph::coarse_mono_clock::now(); | |
50 | if (track) { | |
e306af50 TL |
51 | ioctx_list.lock.lock(); |
52 | ioctx_list.list.push_back(&list_item); | |
53 | ioctx_list.lock.unlock(); | |
91327a77 AA |
54 | } |
55 | } | |
56 | ||
57 | MDSIOContextBase::~MDSIOContextBase() | |
58 | { | |
e306af50 | 59 | ioctx_list.lock.lock(); |
91327a77 | 60 | list_item.remove_myself(); |
e306af50 | 61 | ioctx_list.lock.unlock(); |
91327a77 AA |
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 | ||
e306af50 TL |
71 | ioctx_list.lock.lock(); |
72 | for (elist<MDSIOContextBase*>::iterator p = ioctx_list.list.begin(); !p.end(); ++p) { | |
91327a77 AA |
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 | } | |
e306af50 | 82 | ioctx_list.lock.unlock(); |
91327a77 AA |
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 | ||
7c673cae FG |
95 | void MDSIOContextBase::complete(int r) { |
96 | MDSRank *mds = get_mds(); | |
97 | ||
98 | dout(10) << "MDSIOContextBase::complete: " << typeid(*this).name() << dendl; | |
11fdf7f2 | 99 | ceph_assert(mds != NULL); |
9f95a23c TL |
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. | |
11fdf7f2 | 103 | std::lock_guard l(mds->mds_lock); |
91327a77 | 104 | |
7c673cae FG |
105 | if (mds->is_daemon_stopping()) { |
106 | dout(4) << "MDSIOContextBase::complete: dropping for stopping " | |
107 | << typeid(*this).name() << dendl; | |
e306af50 TL |
108 | return; |
109 | } | |
110 | ||
b3b6e05e TL |
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; | |
7c673cae FG |
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); | |
f67539c2 | 126 | // MDSIOContext::complete() free this |
7c673cae | 127 | MDSIOContextBase::complete(r); |
f67539c2 | 128 | // safe_pos must be updated after MDSIOContext::complete() call |
7c673cae FG |
129 | mdlog->set_safe_pos(safe_pos); |
130 | } | |
131 | ||
7c673cae FG |
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 | } |