Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / mds / DamageTable.h
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
16 #ifndef DAMAGE_TABLE_H_
17 #define DAMAGE_TABLE_H_
18
19 #include "mdstypes.h"
20 #include "auth/Crypto.h"
21
22 class CDir;
23
24 typedef uint64_t damage_entry_id_t;
25
26 typedef enum
27 {
28   DAMAGE_ENTRY_DIRFRAG,
29   DAMAGE_ENTRY_DENTRY,
30   DAMAGE_ENTRY_BACKTRACE
31
32 } damage_entry_type_t;
33
34 class DamageEntry
35 {
36   public:
37   damage_entry_id_t id;
38   utime_t reported_at;
39
40   // path is optional, advisory.  Used to give the admin an idea of what
41   // part of his tree the damage affects.
42   std::string path;
43
44   DamageEntry()
45   {
46     id = get_random(0, 0xffffffff);
47     reported_at = ceph_clock_now();
48   }
49
50   virtual damage_entry_type_t get_type() const = 0;
51
52   virtual ~DamageEntry();
53
54   virtual void dump(Formatter *f) const = 0;
55 };
56
57
58 typedef ceph::shared_ptr<DamageEntry> DamageEntryRef;
59
60
61 class DirFragIdent
62 {
63   public:
64   inodeno_t ino;
65   frag_t frag;
66
67   bool operator<(const DirFragIdent &rhs) const
68   {
69     if (ino == rhs.ino) {
70       return frag < rhs.frag;
71     } else {
72       return ino < rhs.ino;
73     }
74   }
75
76   DirFragIdent(inodeno_t ino_, frag_t frag_)
77     : ino(ino_), frag(frag_)
78   {}
79 };
80
81 class DentryIdent
82 {
83   public:
84   std::string dname;
85   snapid_t snap_id;
86
87   bool operator<(const DentryIdent &rhs) const
88   {
89     if (dname == rhs.dname) {
90       return snap_id < rhs.snap_id;
91     } else {
92       return dname < rhs.dname;
93     }
94   }
95
96   DentryIdent(const std::string &dname_, snapid_t snap_id_)
97     : dname(dname_), snap_id(snap_id_)
98   {}
99 };
100
101 /**
102  * Registry of in-RADOS metadata damage identified
103  * during forward scrub or during normal fetches.
104  *
105  * Used to indicate damage to the administrator, and
106  * to cache known-bad paths so that we don't hit them
107  * repeatedly.
108  *
109  * Callers notifying damage must check return code; if
110  * an fatal condition is indicated then they should mark the MDS
111  * rank damaged.
112  *
113  * An artificial limit on the number of damage entries
114  * is imposed to avoid this structure growing indefinitely.  If
115  * a notification causes the limit to be exceeded, the fatal
116  * condition will be indicated in the return code and the MDS
117  * rank should be marked damaged.
118  *
119  * Protected by MDS::mds_lock
120  */
121 class DamageTable
122 {
123 protected:
124
125   // Map of all dirfrags reported damaged
126   std::map<DirFragIdent, DamageEntryRef> dirfrags;
127
128   // Store dentries in a map per dirfrag, so that we can
129   // readily look up all the bad dentries in a particular
130   // dirfrag
131   std::map<DirFragIdent, std::map<DentryIdent, DamageEntryRef> > dentries;
132
133   // Map of all inodes which could not be resolved remotely
134   // (i.e. have probably/possibly missing backtraces)
135   std::map<inodeno_t, DamageEntryRef> remotes;
136
137   // All damage, by ID.  This is a secondary index
138   // to the dirfrag, dentry, remote maps.  It exists
139   // to enable external tools to unambiguously operate
140   // on particular entries.
141   std::map<damage_entry_id_t, DamageEntryRef> by_id;
142
143   // I need to know my MDS rank so that I can check if
144   // metadata items are part of my mydir.
145   const mds_rank_t rank;
146
147   bool oversized() const;
148
149 public:
150
151   /**
152    * Return true if no damage entries exist
153    */
154   bool empty() const
155   {
156     return by_id.empty();
157   }
158
159   /**
160    * Indicate that a dirfrag cannot be loaded.
161    *
162    * @return true if fatal
163    */
164   bool notify_dirfrag(inodeno_t ino, frag_t frag, const std::string &path);
165
166   /**
167    * Indicate that a particular dentry cannot be loaded.
168    *
169    * @return true if fatal
170    */
171   bool notify_dentry(
172     inodeno_t ino, frag_t frag,
173     snapid_t snap_id, const std::string &dname, const std::string &path);
174
175   /**
176    * Indicate that a particular Inode could not be loaded by number
177    */
178   bool notify_remote_damaged(
179       inodeno_t ino, const std::string &path);
180
181   bool is_dentry_damaged(
182       const CDir *dir_frag,
183       const std::string &dname,
184       const snapid_t snap_id) const;
185
186   bool is_dirfrag_damaged(
187       const CDir *dir_frag) const;
188
189   bool is_remote_damaged(
190       const inodeno_t ino) const;
191
192
193   DamageTable(const mds_rank_t rank_)
194     : rank(rank_)
195   {
196     assert(rank_ != MDS_RANK_NONE);
197   }
198
199   void dump(Formatter *f) const;
200
201   void erase(damage_entry_id_t damage_id);
202 };
203
204 #endif // DAMAGE_TABLE_H_
205