]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/cephfs/DataScan.h
dd064492d01e7eb627c0eecfe8af76e1ddb2fdee
[ceph.git] / ceph / src / tools / cephfs / DataScan.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) 2015 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 "MDSUtility.h"
17 #include "include/rados/librados.hpp"
18
19 class InodeStore;
20 class MDSTable;
21
22 class RecoveryDriver {
23 protected:
24 // If true, overwrite structures that generate decoding errors.
25 bool force_corrupt;
26
27 // If true, overwrite root objects during init_roots even if they
28 // exist
29 bool force_init;
30
31 public:
32 virtual int init(
33 librados::Rados &rados,
34 std::string &metadata_pool_name,
35 const FSMap *fsmap,
36 fs_cluster_id_t fscid) = 0;
37
38 void set_force_corrupt(const bool val)
39 {
40 force_corrupt = val;
41 }
42
43 void set_force_init(const bool val)
44 {
45 force_init = val;
46 }
47
48
49 /**
50 * Inject an inode + dentry parents into the metadata pool,
51 * based on a backtrace recovered from the data pool
52 */
53 virtual int inject_with_backtrace(
54 const inode_backtrace_t &bt,
55 const InodeStore &dentry) = 0;
56
57 /**
58 * Inject an inode + dentry into the lost+found directory,
59 * when all we know about a file is its inode.
60 */
61 virtual int inject_lost_and_found(
62 inodeno_t ino,
63 const InodeStore &dentry) = 0;
64
65 /**
66 * Create any missing roots (i.e. mydir, strays, root inode)
67 */
68 virtual int init_roots(
69 int64_t data_pool_id) = 0;
70
71 /**
72 * Pre-injection check that all the roots are present in
73 * the metadata pool. Used to avoid parallel workers interfering
74 * with one another, by cueing the user to go run 'init' on a
75 * single node before running a parallel scan.
76 *
77 * @param result: set to true if roots are present, else set to false
78 * @returns 0 on no unexpected errors, else error code. Missing objects
79 * are not considered an unexpected error: check *result for
80 * this case.
81 */
82 virtual int check_roots(bool *result) = 0;
83
84 /**
85 * Helper to compose dnames for links to lost+found
86 * inodes.
87 */
88 std::string lost_found_dname(inodeno_t ino)
89 {
90 char s[20];
91 snprintf(s, sizeof(s), "%llx", (unsigned long long)ino);
92 return std::string(s);
93 }
94
95 RecoveryDriver()
96 : force_corrupt(false),
97 force_init(false)
98 {}
99
100 virtual ~RecoveryDriver() {}
101 };
102
103 class LocalFileDriver : public RecoveryDriver
104 {
105 protected:
106 const std::string path;
107 librados::IoCtx &data_io;
108
109 int inject_data(
110 const std::string &file_path,
111 uint64_t size,
112 uint32_t chunk_size,
113 inodeno_t ino);
114 public:
115
116 LocalFileDriver(const std::string &path_, librados::IoCtx &data_io_)
117 : RecoveryDriver(), path(path_), data_io(data_io_)
118 {}
119
120 // Implement RecoveryDriver interface
121 int init(
122 librados::Rados &rados,
123 std::string &metadata_pool_name,
124 const FSMap *fsmap,
125 fs_cluster_id_t fscid) override;
126
127 int inject_with_backtrace(
128 const inode_backtrace_t &bt,
129 const InodeStore &dentry) override;
130
131 int inject_lost_and_found(
132 inodeno_t ino,
133 const InodeStore &dentry) override;
134
135 int init_roots(int64_t data_pool_id) override;
136
137 int check_roots(bool *result) override;
138 };
139
140 /**
141 * A class that knows how to work with objects in a CephFS
142 * metadata pool.
143 */
144 class MetadataTool
145 {
146 protected:
147
148 librados::IoCtx metadata_io;
149
150 /**
151 * Construct a synthetic InodeStore for a normal file
152 */
153 void build_file_dentry(
154 inodeno_t ino, uint64_t file_size, time_t file_mtime,
155 const file_layout_t &layout,
156 InodeStore *out);
157
158 /**
159 * Construct a synthetic InodeStore for a directory
160 */
161 void build_dir_dentry(
162 inodeno_t ino,
163 const frag_info_t &fragstat,
164 const file_layout_t &layout,
165 InodeStore *out);
166
167 /**
168 * Try and read an fnode from a dirfrag
169 */
170 int read_fnode(inodeno_t ino, frag_t frag,
171 fnode_t *fnode, uint64_t *read_version);
172
173 /**
174 * Try and read a dentry from a dirfrag
175 */
176 int read_dentry(inodeno_t parent_ino, frag_t frag,
177 const std::string &dname, InodeStore *inode);
178 };
179
180 /**
181 * A class that knows how to manipulate CephFS metadata pools
182 */
183 class MetadataDriver : public RecoveryDriver, public MetadataTool
184 {
185 protected:
186 /**
187 * Create a .inode object, i.e. root or mydir
188 */
189 int inject_unlinked_inode(inodeno_t inono, int mode, int64_t data_pool_id);
190
191 /**
192 * Check for existence of .inode objects, before
193 * trying to go ahead and inject metadata.
194 */
195 int root_exists(inodeno_t ino, bool *result);
196 int find_or_create_dirfrag(
197 inodeno_t ino,
198 frag_t fragment,
199 bool *created);
200
201
202 /**
203 * Work out which fragment of a directory should contain a named
204 * dentry, recursing up the trace as necessary to retrieve
205 * fragtrees.
206 */
207 int get_frag_of(
208 inodeno_t dirino,
209 const std::string &dname,
210 frag_t *result_ft);
211
212 public:
213
214 // Implement RecoveryDriver interface
215 int init(
216 librados::Rados &rados,
217 std::string &metadata_pool_name,
218 const FSMap *fsmap,
219 fs_cluster_id_t fscid) override;
220
221 int inject_linkage(
222 inodeno_t dir_ino, const std::string &dname,
223 const frag_t fragment, const InodeStore &inode);
224
225 int inject_with_backtrace(
226 const inode_backtrace_t &bt,
227 const InodeStore &dentry) override;
228
229 int inject_lost_and_found(
230 inodeno_t ino,
231 const InodeStore &dentry) override;
232
233 int init_roots(int64_t data_pool_id) override;
234
235 int check_roots(bool *result) override;
236
237 int load_table(MDSTable *table);
238 int save_table(MDSTable *table);
239 };
240
241 class DataScan : public MDSUtility, public MetadataTool
242 {
243 protected:
244 RecoveryDriver *driver;
245 fs_cluster_id_t fscid;
246
247 string metadata_pool_name;
248 std::vector<int64_t> data_pools;
249
250 // IoCtx for data pool (where we scrape file backtraces from)
251 librados::IoCtx data_io;
252 // Remember the data pool ID for use in layouts
253 int64_t data_pool_id;
254
255 uint32_t n;
256 uint32_t m;
257
258 /**
259 * Scan data pool for backtraces, and inject inodes to metadata pool
260 */
261 int scan_inodes();
262
263 /**
264 * Scan data pool for file sizes and mtimes
265 */
266 int scan_extents();
267
268 /**
269 * Scan metadata pool for 0th dirfrags to link orphaned
270 * directory inodes.
271 */
272 int scan_frags();
273
274 /**
275 * Cleanup xattrs from data pool
276 */
277 int cleanup();
278
279 /**
280 * Check if an inode number is in the permitted ranges
281 */
282 bool valid_ino(inodeno_t ino) const;
283
284
285 int scan_links();
286
287 // Accept pools which are not in the FSMap
288 bool force_pool;
289 // Respond to decode errors by overwriting
290 bool force_corrupt;
291 // Overwrite root objects even if they exist
292 bool force_init;
293 // Only scan inodes without this scrub tag
294 string filter_tag;
295
296 /**
297 * @param r set to error on valid key with invalid value
298 * @return true if argument consumed, else false
299 */
300 bool parse_kwarg(
301 const std::vector<const char*> &args,
302 std::vector<const char *>::const_iterator &i,
303 int *r);
304
305 /**
306 * @return true if argument consumed, else false
307 */
308 bool parse_arg(
309 const std::vector<const char*> &arg,
310 std::vector<const char *>::const_iterator &i);
311
312 int probe_filter(librados::IoCtx &ioctx);
313
314 /**
315 * Apply a function to all objects in an ioctx's pool, optionally
316 * restricted to only those objects with a 00000000 offset and
317 * no tag matching DataScan::scrub_tag.
318 */
319 int forall_objects(
320 librados::IoCtx &ioctx,
321 bool untagged_only,
322 std::function<int(std::string, uint64_t, uint64_t)> handler);
323
324 public:
325 static void usage();
326 int main(const std::vector<const char *> &args);
327
328 DataScan()
329 : driver(NULL), fscid(FS_CLUSTER_ID_NONE),
330 data_pool_id(-1), n(0), m(1),
331 force_pool(false), force_corrupt(false),
332 force_init(false)
333 {
334 }
335
336 ~DataScan() override
337 {
338 delete driver;
339 }
340 };
341