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