1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2015 Red Hat
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.
16 #include "MDSUtility.h"
17 #include "include/rados/librados.hpp"
22 class RecoveryDriver
{
24 // If true, overwrite structures that generate decoding errors.
27 // If true, overwrite root objects during init_roots even if they
33 librados::Rados
&rados
,
34 std::string
&metadata_pool_name
,
36 fs_cluster_id_t fscid
) = 0;
38 void set_force_corrupt(const bool val
)
43 void set_force_init(const bool val
)
50 * Inject an inode + dentry parents into the metadata pool,
51 * based on a backtrace recovered from the data pool
53 virtual int inject_with_backtrace(
54 const inode_backtrace_t
&bt
,
55 const InodeStore
&dentry
) = 0;
58 * Inject an inode + dentry into the lost+found directory,
59 * when all we know about a file is its inode.
61 virtual int inject_lost_and_found(
63 const InodeStore
&dentry
) = 0;
66 * Create any missing roots (i.e. mydir, strays, root inode)
68 virtual int init_roots(
69 int64_t data_pool_id
) = 0;
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.
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
82 virtual int check_roots(bool *result
) = 0;
85 * Helper to compose dnames for links to lost+found
88 std::string
lost_found_dname(inodeno_t ino
)
91 snprintf(s
, sizeof(s
), "%llx", (unsigned long long)ino
);
92 return std::string(s
);
96 : force_corrupt(false),
100 virtual ~RecoveryDriver() {}
103 class LocalFileDriver
: public RecoveryDriver
106 const std::string path
;
107 librados::IoCtx
&data_io
;
110 const std::string
&file_path
,
116 LocalFileDriver(const std::string
&path_
, librados::IoCtx
&data_io_
)
117 : RecoveryDriver(), path(path_
), data_io(data_io_
)
120 // Implement RecoveryDriver interface
122 librados::Rados
&rados
,
123 std::string
&metadata_pool_name
,
125 fs_cluster_id_t fscid
) override
;
127 int inject_with_backtrace(
128 const inode_backtrace_t
&bt
,
129 const InodeStore
&dentry
) override
;
131 int inject_lost_and_found(
133 const InodeStore
&dentry
) override
;
135 int init_roots(int64_t data_pool_id
) override
;
137 int check_roots(bool *result
) override
;
141 * A class that knows how to work with objects in a CephFS
148 librados::IoCtx metadata_io
;
151 * Construct a synthetic InodeStore for a normal file
153 void build_file_dentry(
154 inodeno_t ino
, uint64_t file_size
, time_t file_mtime
,
155 const file_layout_t
&layout
,
159 * Construct a synthetic InodeStore for a directory
161 void build_dir_dentry(
163 const frag_info_t
&fragstat
,
164 const file_layout_t
&layout
,
168 * Try and read an fnode from a dirfrag
170 int read_fnode(inodeno_t ino
, frag_t frag
,
171 fnode_t
*fnode
, uint64_t *read_version
);
174 * Try and read a dentry from a dirfrag
176 int read_dentry(inodeno_t parent_ino
, frag_t frag
,
177 const std::string
&dname
, InodeStore
*inode
);
181 * A class that knows how to manipulate CephFS metadata pools
183 class MetadataDriver
: public RecoveryDriver
, public MetadataTool
187 * Create a .inode object, i.e. root or mydir
189 int inject_unlinked_inode(inodeno_t inono
, int mode
, int64_t data_pool_id
);
192 * Check for existence of .inode objects, before
193 * trying to go ahead and inject metadata.
195 int root_exists(inodeno_t ino
, bool *result
);
196 int find_or_create_dirfrag(
203 * Work out which fragment of a directory should contain a named
204 * dentry, recursing up the trace as necessary to retrieve
209 const std::string
&dname
,
214 // Implement RecoveryDriver interface
216 librados::Rados
&rados
,
217 std::string
&metadata_pool_name
,
219 fs_cluster_id_t fscid
) override
;
222 inodeno_t dir_ino
, const std::string
&dname
,
223 const frag_t fragment
, const InodeStore
&inode
);
225 int inject_with_backtrace(
226 const inode_backtrace_t
&bt
,
227 const InodeStore
&dentry
) override
;
229 int inject_lost_and_found(
231 const InodeStore
&dentry
) override
;
233 int init_roots(int64_t data_pool_id
) override
;
235 int check_roots(bool *result
) override
;
237 int load_table(MDSTable
*table
);
238 int save_table(MDSTable
*table
);
241 class DataScan
: public MDSUtility
, public MetadataTool
244 RecoveryDriver
*driver
;
245 fs_cluster_id_t fscid
;
247 string metadata_pool_name
;
248 std::vector
<int64_t> data_pools
;
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
;
259 * Scan data pool for backtraces, and inject inodes to metadata pool
264 * Scan data pool for file sizes and mtimes
269 * Scan metadata pool for 0th dirfrags to link orphaned
275 * Cleanup xattrs from data pool
280 * Check if an inode number is in the permitted ranges
282 bool valid_ino(inodeno_t ino
) const;
287 // Accept pools which are not in the FSMap
289 // Respond to decode errors by overwriting
291 // Overwrite root objects even if they exist
293 // Only scan inodes without this scrub tag
297 * @param r set to error on valid key with invalid value
298 * @return true if argument consumed, else false
301 const std::vector
<const char*> &args
,
302 std::vector
<const char *>::const_iterator
&i
,
306 * @return true if argument consumed, else false
309 const std::vector
<const char*> &arg
,
310 std::vector
<const char *>::const_iterator
&i
);
312 int probe_filter(librados::IoCtx
&ioctx
);
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.
320 librados::IoCtx
&ioctx
,
322 std::function
<int(std::string
, uint64_t, uint64_t)> handler
);
326 int main(const std::vector
<const char *> &args
);
329 : driver(NULL
), fscid(FS_CLUSTER_ID_NONE
),
330 data_pool_id(-1), n(0), m(1),
331 force_pool(false), force_corrupt(false),