]> git.proxmox.com Git - ceph.git/blame - ceph/src/mds/DamageTable.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / mds / DamageTable.cc
CommitLineData
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) 2004-2006 Sage Weil <sage@newdream.net>
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#include "common/debug.h"
16
17#include "mds/CDir.h"
18
19#include "DamageTable.h"
20
21#define dout_context g_ceph_context
22#define dout_subsys ceph_subsys_mds
23#undef dout_prefix
24#define dout_prefix *_dout << "mds." << rank << ".damage " << __func__ << " "
25
26namespace {
27/**
28 * Record damage to a particular dirfrag, implicitly affecting
29 * any dentries within it.
30 */
31class DirFragDamage : public DamageEntry
32{
33 public:
34 inodeno_t ino;
35 frag_t frag;
36
37 DirFragDamage(inodeno_t ino_, frag_t frag_)
38 : ino(ino_), frag(frag_)
39 {}
40
41 damage_entry_type_t get_type() const override
42 {
43 return DAMAGE_ENTRY_DIRFRAG;
44 }
45
46 void dump(Formatter *f) const override
47 {
48 f->open_object_section("dir_frag_damage");
49 f->dump_string("damage_type", "dir_frag");
50 f->dump_int("id", id);
51 f->dump_int("ino", ino);
52 f->dump_stream("frag") << frag;
53 f->dump_string("path", path);
54 f->close_section();
55 }
56};
57
58
59/**
60 * Record damage to a particular dname within a particular dirfrag
61 */
62class DentryDamage : public DamageEntry
63{
64 public:
65 inodeno_t ino;
66 frag_t frag;
67 std::string dname;
68 snapid_t snap_id;
69
70 DentryDamage(
71 inodeno_t ino_,
72 frag_t frag_,
11fdf7f2 73 std::string_view dname_,
7c673cae
FG
74 snapid_t snap_id_)
75 : ino(ino_), frag(frag_), dname(dname_), snap_id(snap_id_)
76 {}
77
78 damage_entry_type_t get_type() const override
79 {
80 return DAMAGE_ENTRY_DENTRY;
81 }
82
83 void dump(Formatter *f) const override
84 {
85 f->open_object_section("dentry_damage");
86 f->dump_string("damage_type", "dentry");
87 f->dump_int("id", id);
88 f->dump_int("ino", ino);
89 f->dump_stream("frag") << frag;
90 f->dump_string("dname", dname);
91 f->dump_stream("snap_id") << snap_id;
92 f->dump_string("path", path);
93 f->close_section();
94 }
95};
96
97
98/**
99 * Record damage to our ability to look up an ino by number
100 */
101class BacktraceDamage : public DamageEntry
102{
103 public:
104 inodeno_t ino;
105
106 BacktraceDamage(inodeno_t ino_)
107 : ino(ino_)
108 {}
109
110 damage_entry_type_t get_type() const override
111 {
112 return DAMAGE_ENTRY_BACKTRACE;
113 }
114
115 void dump(Formatter *f) const override
116 {
117 f->open_object_section("backtrace_damage");
118 f->dump_string("damage_type", "backtrace");
119 f->dump_int("id", id);
120 f->dump_int("ino", ino);
121 f->dump_string("path", path);
122 f->close_section();
123 }
124};
125}
126
127DamageEntry::~DamageEntry()
128{}
129
130bool DamageTable::notify_dentry(
131 inodeno_t ino, frag_t frag,
11fdf7f2 132 snapid_t snap_id, std::string_view dname, std::string_view path)
7c673cae
FG
133{
134 if (oversized()) {
135 return true;
136 }
137
138 // Special cases: damage to these dirfrags is considered fatal to
139 // the MDS rank that owns them.
140 if (
141 (MDS_INO_IS_MDSDIR(ino) && MDS_INO_MDSDIR_OWNER(ino) == rank)
142 ||
143 (MDS_INO_IS_STRAY(ino) && MDS_INO_STRAY_OWNER(ino) == rank)
144 ) {
145 derr << "Damage to dentries in fragment " << frag << " of ino " << ino
146 << "is fatal because it is a system directory for this rank" << dendl;
147 return true;
148 }
149
150 auto key = DirFragIdent(ino, frag);
151 if (dentries.count(key) == 0) {
152 DamageEntryRef entry = std::make_shared<DentryDamage>(
153 ino, frag, dname, snap_id);
11fdf7f2 154 entry->path = path;
7c673cae
FG
155 dentries[key][DentryIdent(dname, snap_id)] = entry;
156 by_id[entry->id] = std::move(entry);
157 }
158
159 return false;
160}
161
162bool DamageTable::notify_dirfrag(inodeno_t ino, frag_t frag,
11fdf7f2 163 std::string_view path)
7c673cae
FG
164{
165 // Special cases: damage to these dirfrags is considered fatal to
166 // the MDS rank that owns them.
167 if (
168 (MDS_INO_IS_STRAY(ino) && MDS_INO_STRAY_OWNER(ino) == rank)
169 ||
170 (ino == MDS_INO_ROOT)
171 ) {
172 derr << "Damage to fragment " << frag << " of ino " << ino
173 << " is fatal because it is a system directory for this rank" << dendl;
174 return true;
175 }
176
177 if (oversized()) {
178 return true;
179 }
180
181 auto key = DirFragIdent(ino, frag);
182 if (dirfrags.count(key) == 0) {
183 DamageEntryRef entry = std::make_shared<DirFragDamage>(ino, frag);
11fdf7f2 184 entry->path = path;
7c673cae
FG
185 dirfrags[key] = entry;
186 by_id[entry->id] = std::move(entry);
187 }
188
189 return false;
190}
191
11fdf7f2 192bool DamageTable::notify_remote_damaged(inodeno_t ino, std::string_view path)
7c673cae
FG
193{
194 if (oversized()) {
195 return true;
196 }
197
198 if (remotes.count(ino) == 0) {
199 auto entry = std::make_shared<BacktraceDamage>(ino);
11fdf7f2 200 entry->path = path;
7c673cae
FG
201 remotes[ino] = entry;
202 by_id[entry->id] = std::move(entry);
203 }
204
205 return false;
206}
207
208bool DamageTable::oversized() const
209{
11fdf7f2 210 return by_id.size() > (size_t)(g_conf()->mds_damage_table_max_entries);
7c673cae
FG
211}
212
213bool DamageTable::is_dentry_damaged(
214 const CDir *dir_frag,
11fdf7f2 215 std::string_view dname,
7c673cae
FG
216 const snapid_t snap_id) const
217{
218 if (dentries.count(
219 DirFragIdent(dir_frag->inode->ino(), dir_frag->frag)
220 ) == 0) {
221 return false;
222 }
223
224 const std::map<DentryIdent, DamageEntryRef> &frag_dentries =
225 dentries.at(DirFragIdent(dir_frag->inode->ino(), dir_frag->frag));
226
227 return frag_dentries.count(DentryIdent(dname, snap_id)) > 0;
228}
229
230bool DamageTable::is_dirfrag_damaged(
231 const CDir *dir_frag) const
232{
233 return dirfrags.count(
234 DirFragIdent(dir_frag->inode->ino(), dir_frag->frag)) > 0;
235}
236
237bool DamageTable::is_remote_damaged(
238 const inodeno_t ino) const
239{
240 return remotes.count(ino) > 0;
241}
242
243void DamageTable::dump(Formatter *f) const
244{
245 f->open_array_section("damage_table");
246 for (const auto &i : by_id)
247 {
248 i.second->dump(f);
249 }
250 f->close_section();
251}
252
253void DamageTable::erase(damage_entry_id_t damage_id)
254{
255 auto by_id_entry = by_id.find(damage_id);
256 if (by_id_entry == by_id.end()) {
257 return;
258 }
259
260 DamageEntryRef entry = by_id_entry->second;
11fdf7f2 261 ceph_assert(entry->id == damage_id); // Sanity
7c673cae
FG
262
263 const auto type = entry->get_type();
264 if (type == DAMAGE_ENTRY_DIRFRAG) {
265 auto dirfrag_entry = std::static_pointer_cast<DirFragDamage>(entry);
266 dirfrags.erase(DirFragIdent(dirfrag_entry->ino, dirfrag_entry->frag));
267 } else if (type == DAMAGE_ENTRY_DENTRY) {
268 auto dentry_entry = std::static_pointer_cast<DentryDamage>(entry);
269 dentries.erase(DirFragIdent(dentry_entry->ino, dentry_entry->frag));
270 } else if (type == DAMAGE_ENTRY_BACKTRACE) {
271 auto backtrace_entry = std::static_pointer_cast<BacktraceDamage>(entry);
272 remotes.erase(backtrace_entry->ino);
273 } else {
274 derr << "Invalid type " << type << dendl;
275 ceph_abort();
276 }
277
278 by_id.erase(by_id_entry);
279}
280